ruby_language_server 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 403609bb04e3734281518bc6a175b6e839e6b731d684dd5716f31e91bb7e1d98
4
- data.tar.gz: b7c597616a85977982dc2ddbcb8b8c7d896a1829904fa19dfbb52951da6895b6
3
+ metadata.gz: ccce6fdef542a593c6ccc3add4e33f24bce0f612ed5969ee24dddc8e5a806a41
4
+ data.tar.gz: 630857182e42bca93affb6c591de7c1826812242608c541fd3b42a99458fab0c
5
5
  SHA512:
6
- metadata.gz: cfbd3c60687d08b1f9e19bc632e9d8f4ceb0f5e579e8d6b9edd7e7cf81403dac9b0c7a795fac403b550950b7c1ef615095ad94bbbefe80662390edbdd16f13b7
7
- data.tar.gz: 784a22cdadad7ebdf6f25ce35a78e2cff90aa148dbf62c88e650ba42e7ce522df59e9758e9de166f99308e5226b9100505c73a7f9ee7c470575435072926afae
6
+ metadata.gz: 9c81f9f115dc34b0506b2094039943c9bea9e8238817eac3ed4e79dd44ee9a0eeda5c010c1fa52accf516b3243feff86e943f51c80cb3d159362540328971187
7
+ data.tar.gz: fe0d1a52613afb2a890d3621ec500e8b56d0dedc7b793d2f0f1aba3a5d73a6d2c01b075471d65e337d23b6b9c4d7361f50a090a2e0d9c204c6698deced569224
data/CHANGELOG.txt CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ #### 0.2.1 Wed Jan 30 11:46:09 PST 2019
4
+
5
+ * Convert to Gem
6
+ * Bunch of refactoring
7
+ * More test (fixed stuff)
8
+ * Better block (and other) line start/end setting
9
+ * Better block variable handling
10
+ * Fixed subclass assignment (not that it matters, yet)
11
+ * Added support for object&.method
12
+
3
13
  #### 0.2.0 Mon Dec 24 18:19:55 PST 2018
4
14
 
5
15
  * Support for rake files
data/FAQ_ROADMAP.md CHANGED
@@ -1,25 +1,7 @@
1
- # Why docker?
2
-
3
- Docker guarantees me a target environment. I don't have to wonder which version of ruby you have installed or if you can build all the gems. I may also scale this thing to multiple processes and a database and a cache server.
4
-
5
- One requirement: docker.
6
-
7
- # Why not [language_server-ruby](https://github.com/mtsmfm/language_server-ruby)
8
-
9
- My goals are not as high. I just want this stuff working now. I hope some day there will be merging.
10
-
11
- # A little light on tests?
12
-
13
- Oh yeah. Tests are mostly for when you know where you're going. I'm doing a whole lot of this by the seat of my pants. OMG, please write tests.
14
-
15
1
  # Next?
16
2
 
17
3
  * Getting a definition just looks at the tags - but tags do not include parameters passed in a method - which seems like it should. We are functional, right?
18
- * Guess a symbol's class.
19
- * `def some_method(parent)` should guess that parent is a Parent.
20
4
  * Be smarter about context and completions
21
- * `class << self` is busted. Fix it.
22
- * Fix the outline. Seriously - why isn't it working as expected?
23
5
  * Symbol pairs. If I have typed 'foo.bar' a thousand times in my project, the next time I type 'foo.' the IDE had damn well ought to show me 'bar' as a completion option.
24
6
  * It makes me very sad that I could not get this working using sockets. Tried and tried and failed.
25
7
 
@@ -27,4 +9,5 @@ Oh yeah. Tests are mostly for when you know where you're going. I'm doing a wh
27
9
 
28
10
  * Pay special attention to the project's Gemfile. Install all the gems (we can). Integrate with gem server?
29
11
  * Full scan of installed gems?
12
+ * Maybe use a database (sqlite?) to store data and do lookups?
30
13
  * Integrate class based scope logic. If I'm in Foo < Bar then I should see Bar's methods at just slightly lower priority than Foo's.
data/Makefile CHANGED
@@ -19,6 +19,9 @@ continuous_development: build
19
19
  console: build
20
20
  docker run -it $(LOCAL_LINK) $(PROJECT_NAME) bin/console
21
21
 
22
+ test: build
23
+ docker run -it $(LOCAL_LINK) $(PROJECT_NAME) rake test && rubocop -c .rubocop_ruby_language_parser.yml
24
+
22
25
  shell: build
23
26
  docker run -it $(LOCAL_LINK) $(PROJECT_NAME) sh
24
27
 
data/README.md CHANGED
@@ -19,9 +19,9 @@ Help wanted.
19
19
 
20
20
  # Editor Integrations
21
21
 
22
- * You probably want to use one of the developed integrations:
23
- * Atom - https://github.com/kwerle/ide-ruby
24
- * Theia - https://github.com/kwerle/theia_ruby_language_server
22
+ You probably want to use one of the developed integrations:
23
+ * Atom - https://github.com/kwerle/ide-ruby
24
+ * Theia - https://github.com/kwerle/theia_ruby_language_server
25
25
 
26
26
  # Running
27
27
 
@@ -32,7 +32,7 @@ Help wanted.
32
32
  Clone. I love git [HubFlow](https://datasift.github.io/gitflow/).
33
33
 
34
34
  Check out the [Makefile](Makefile). You are going to want to do
35
- `make guard` and `make continuous_development`.
35
+ `make guard` in one window and `make continuous_development` in another.
36
36
 
37
37
  * In Atom: install the ide-ruby.
38
38
  * Settings > Packages > ide-ruby > Image Name > local_ruby_language_server
@@ -125,5 +125,14 @@ module RubyLanguageServer
125
125
  end
126
126
  @root_scope
127
127
  end
128
+
129
+ # Returns the context of what is being typed in the given line
130
+ def context_at_location(position)
131
+ lines = text.split("\n")
132
+ line = lines[position.line]
133
+ return [] if line.nil? || line.strip.length.zero?
134
+
135
+ LineContext.for(line, position.character)
136
+ end
128
137
  end
129
138
  end
@@ -65,10 +65,10 @@ module RubyLanguageServer
65
65
  def scope_completions(word, scopes)
66
66
  words = {}
67
67
  scopes.each_with_object(words) do |scope, words_hash|
68
- scope.children.each do |function|
69
- words_hash[function.name] ||= {
68
+ scope.children.select(&:'method?').each do |method_scope|
69
+ words_hash[method_scope.name] ||= {
70
70
  depth: scope.depth,
71
- type: function.type
71
+ type: method_scope.type
72
72
  }
73
73
  end
74
74
  scope.variables.each do |variable|
@@ -78,7 +78,7 @@ module RubyLanguageServer
78
78
  }
79
79
  end
80
80
  end
81
- # words = words.sort_by{|word, hash| hash[:depth] }.to_h
81
+ words = words.sort_by { |_word, hash| hash[:depth] }.to_h
82
82
  good_words = FuzzyMatch.new(words.keys, threshold: 0.01).find_all(word).slice(0..10) || []
83
83
  words = good_words.map { |w| [w, words[w]] }.to_h
84
84
  end
@@ -6,9 +6,9 @@ module RubyLanguageServer
6
6
  class GoodCop < RuboCop::Runner
7
7
  CONFIG_PATH = '/project/.rubocop.yml'
8
8
  FALLBACK_PATH = '/app/.rubocop.yml'
9
- @initialization_error = nil
10
9
 
11
10
  def initialize
11
+ @initialization_error = nil
12
12
  config_store = RuboCop::ConfigStore.new
13
13
  config_store.options_config =
14
14
  if File.exist?(CONFIG_PATH)
@@ -29,8 +29,9 @@ module RubyLanguageServer
29
29
  line_start = line[0..(position + match.length - 1)]
30
30
  RubyLanguageServer.logger.debug("line_start: #{line_start}")
31
31
  # Match as much as we can to the end of the line - which is now the end of the word
32
- end_match = line_start.partition(/(@{0,2}[:\.\w]+)$/)[1]
33
- matches = end_match.split('.', -1)
32
+ end_match = line_start.partition(/(@{0,2}[:&\.\w]+)$/)[1]
33
+ matches = end_match.split('&.', -1)
34
+ matches = matches.map { |m| m.length.positive? ? m.split('.', -1) : m }.flatten
34
35
  matches = matches.map { |m| m.length.positive? ? m.split('::', -1) : m }.flatten
35
36
  RubyLanguageServer.logger.debug("matches: #{matches}")
36
37
  matches
@@ -3,7 +3,7 @@
3
3
  require 'logger'
4
4
 
5
5
  module RubyLanguageServer
6
- level_name = ENV.fetch('LOG_LEVEL') { 'info' }.upcase
6
+ level_name = ENV.fetch('LOG_LEVEL') { 'error' }.upcase
7
7
  # level_name = 'DEBUG'
8
8
  level = Logger::Severity.const_get(level_name)
9
9
  @logger = ::Logger.new(STDERR, level: level)
@@ -175,14 +175,10 @@ module RubyLanguageServer
175
175
  end
176
176
  end
177
177
 
178
+ # Returns the context of what is being typed in the given line
178
179
  def context_at_location(uri, position)
179
- lines = text_for_uri(uri).split("\n")
180
- line = lines[position.line]
181
- return [] if line.nil? || line.strip.length.zero?
182
-
183
- contexts = LineContext.for(line, position.character)
184
- RubyLanguageServer.logger.debug("LineContext.for(line, position.character): #{contexts}")
185
- contexts
180
+ code_file = code_file_for_uri(uri)
181
+ code_file&.context_at_location(position)
186
182
  end
187
183
 
188
184
  def word_at_location(uri, position)
@@ -18,6 +18,12 @@ module RubyLanguageServer
18
18
  TYPE_ROOT => '',
19
19
  TYPE_VARIABLE => '^'
20
20
  }.freeze
21
+
22
+ attr_accessor :type # Type of this scope (module, class, block)
23
+
24
+ def method?
25
+ type == TYPE_METHOD
26
+ end
21
27
  end
22
28
  end
23
29
  end
@@ -3,8 +3,7 @@
3
3
  module RubyLanguageServer
4
4
  module ScopeData
5
5
  # The Scope class is basically a container with context.
6
- # It is used to track top & bottom line, variables in this scope, contanst, and children - which could be functions, classes, blocks, etc. Anything that adds scope.
7
- # Remember, this is scope for a file. It seems reasonabble that this will get used less in the future when we know more about classes.
6
+ # It is used to track top & bottom line, variables in this scope, constants, and children - which could be functions, classes, blocks, etc. Anything that adds scope.
8
7
  class Scope < Base
9
8
  include Enumerable
10
9
 
@@ -15,7 +14,6 @@ module RubyLanguageServer
15
14
  attr_accessor :variables # variables declared in this scope
16
15
  attr_accessor :constants # constants declared in this scope
17
16
  attr_accessor :children # child scopes
18
- attr_accessor :type # Type of this scope (module, class, block)
19
17
  attr_accessor :name # method
20
18
  attr_accessor :superclass_name # superclass name
21
19
 
@@ -26,14 +24,18 @@ module RubyLanguageServer
26
24
  @name = name
27
25
  @top_line = top_line
28
26
  @depth = parent.nil? ? 0 : parent.depth + 1
29
- @full_name = [parent ? parent.full_name : nil, @name].compact.join(JoinHash[type]) unless type == TYPE_ROOT
27
+ if type == TYPE_ROOT
28
+ @full_name = nil
29
+ else
30
+ @full_name = [parent ? parent.full_name : nil, @name].compact.join(JoinHash[type])
31
+ end
30
32
  @children = []
31
33
  @variables = []
32
34
  @constants = []
33
35
  end
34
36
 
35
37
  def inspect
36
- "Scope: #{@name} (#{@full_name}) #{@top_line}-#{@bottom_line} children: #{@children} vars: #{@variables}"
38
+ "Scope: #{@name} (#{@full_name} - #{@type}) #{@top_line}-#{@bottom_line} children: #{@children} vars: #{@variables}"
37
39
  end
38
40
 
39
41
  def pretty_print(pp) # rubocop:disable Naming/UncommunicativeMethodParamName
@@ -87,9 +89,7 @@ module RubyLanguageServer
87
89
 
88
90
  # [self, parent, parent.parent...]
89
91
  def self_and_ancestors
90
- return [self, parent.self_and_ancestors].flatten unless parent.nil?
91
-
92
- [self]
92
+ [self, parent&.self_and_ancestors].flatten.compact
93
93
  end
94
94
 
95
95
  def set_superclass_name(partial)
@@ -7,7 +7,6 @@ module RubyLanguageServer
7
7
  attr_accessor :column # column
8
8
  attr_accessor :name # name
9
9
  attr_accessor :full_name # Module::Class name
10
- attr_accessor :type # type
11
10
 
12
11
  def initialize(scope, name, line = 1, column = 1, type = TYPE_VARIABLE)
13
12
  @name = name
@@ -22,6 +22,7 @@ module RubyLanguageServer
22
22
  def initialize(sexp, lines = 1)
23
23
  @sexp = sexp
24
24
  @lines = lines
25
+ @root_scope = nil
25
26
  end
26
27
 
27
28
  def root_scope
@@ -55,6 +56,8 @@ module RubyLanguageServer
55
56
  RubyLanguageServer.logger.debug("We don't do Strings like #{root} with #{args}")
56
57
  when NilClass
57
58
  process(args)
59
+ when FalseClass
60
+ process(args)
58
61
  else
59
62
  RubyLanguageServer.logger.warn("We don't respond to the likes of #{root} of class #{root.class}")
60
63
  end
@@ -91,11 +94,20 @@ module RubyLanguageServer
91
94
  end
92
95
 
93
96
  def on_module(args, rest)
94
- add_scope(args.last, rest, ScopeData::Scope::TYPE_MODULE)
97
+ scope = add_scope(args.last, rest, ScopeData::Scope::TYPE_MODULE)
98
+ assign_subclass(scope, rest)
95
99
  end
96
100
 
97
101
  def on_class(args, rest)
98
- add_scope(args.last, rest, ScopeData::Scope::TYPE_CLASS)
102
+ scope = add_scope(args.last, rest, ScopeData::Scope::TYPE_CLASS)
103
+ assign_subclass(scope, rest)
104
+ end
105
+
106
+ def assign_subclass(scope, sexp)
107
+ return unless !sexp[0].nil? && sexp[0][0] == :var_ref
108
+
109
+ (_, (_, name)) = sexp[0]
110
+ scope.set_superclass_name(name)
99
111
  end
100
112
 
101
113
  def on_method_add_block(args, rest)
@@ -117,11 +129,20 @@ module RubyLanguageServer
117
129
  pop_scope
118
130
  end
119
131
 
120
- # Used only to describe subclasses?
121
- def on_var_ref(args, _)
132
+ def on_block_var(args, rest)
133
+ (_, ((_, name, (line, column)))) = args
134
+ add_variable(name, line, column)
135
+ # blocks don't declare their first line in the parser
136
+ current_scope.top_line ||= line
137
+ process(args)
138
+ process(rest)
139
+ end
140
+
141
+ # Used only to describe subclasses? -- nope
142
+ def on_var_ref(_args, _rest)
122
143
  # [:@const, "Bar", [13, 20]]
123
- (_, name) = args
124
- @current_scope.set_superclass_name(name)
144
+ # (_, name) = args
145
+ # @current_scope.set_superclass_name(name)
125
146
  end
126
147
 
127
148
  def on_assign(args, rest)
@@ -261,9 +282,10 @@ module RubyLanguageServer
261
282
 
262
283
  def add_scope(args, rest, type)
263
284
  (_, name, (line, column)) = args
264
- push_scope(type, name, line, column)
285
+ scope = push_scope(type, name, line, column)
265
286
  process(rest)
266
287
  pop_scope
288
+ scope
267
289
  end
268
290
 
269
291
  def type_is_class_or_module(type)
@@ -292,14 +314,8 @@ module RubyLanguageServer
292
314
  # This is a very poor man's "end" handler because there is no end handler.
293
315
  # The notion is that when you start the next scope, all the previous peers and unclosed descendents of the previous peer should be closed.
294
316
  def close_sibling_scopes(line)
295
- parent_scope = @current_scope.parent
296
- unless parent_scope.nil?
297
- last_sibling = parent_scope.children.last
298
- until last_sibling.nil?
299
- last_sibling.bottom_line = line - 1
300
- last_sibling = last_sibling.children.last
301
- end
302
- end
317
+ parent_scope = @current_scope
318
+ parent_scope&.descendants&.each { |scope| scope.bottom_line = [scope.bottom_line, line - 1].compact.min }
303
319
  end
304
320
 
305
321
  def pop_scope
@@ -327,7 +343,7 @@ module RubyLanguageServer
327
343
  rescue TypeError => exception
328
344
  RubyLanguageServer.logger.error("Exception in sexp: #{exception} for text: #{text}")
329
345
  end
330
- processor = SEXPProcessor.new(sexp, text.length)
346
+ processor = SEXPProcessor.new(sexp, text.split("\n").length)
331
347
  @root_scope = processor.root_scope
332
348
  end
333
349
  end
@@ -42,6 +42,10 @@ module RubyLanguageServer
42
42
  }
43
43
  end
44
44
 
45
+ def on_initialized(_hash)
46
+ RubyLanguageServer.logger.error("RubyLanguageServer::VERSION #{RubyLanguageServer::VERSION}")
47
+ end
48
+
45
49
  def on_workspace_didChangeWatchedFiles(params)
46
50
  RubyLanguageServer.logger.debug('on_workspace_didChangeWatchedFiles')
47
51
  RubyLanguageServer.logger.debug(params)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyLanguageServer
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
@@ -35,8 +35,8 @@ Gem::Specification.new do |spec|
35
35
 
36
36
  # Normally the system will have these - but not if it's a stripped down docker image
37
37
  spec.add_dependency 'bundler'
38
- spec.add_dependency 'json'
39
38
  spec.add_dependency 'etc'
39
+ spec.add_dependency 'json'
40
40
 
41
41
  # No - do not put these in dev - they are needed for the app
42
42
  spec.add_dependency 'rubocop'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_language_server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kurt Werle
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-29 00:00:00.000000000 Z
11
+ date: 2019-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: json
28
+ name: etc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: etc
42
+ name: json
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="