rucoa 0.11.0 → 0.13.0

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -3
  3. data/Gemfile.lock +3 -3
  4. data/README.md +6 -1
  5. data/images/document-highlight.gif +0 -0
  6. data/lib/rucoa/configuration.rb +22 -12
  7. data/lib/rucoa/definition_store.rb +131 -131
  8. data/lib/rucoa/definitions/method_definition.rb +11 -11
  9. data/lib/rucoa/handler_concerns/configuration_requestable.rb +7 -7
  10. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +11 -11
  11. data/lib/rucoa/handler_concerns/text_document_position_parameters.rb +29 -0
  12. data/lib/rucoa/handler_concerns/text_document_uri_parameters.rb +21 -0
  13. data/lib/rucoa/handler_concerns.rb +2 -0
  14. data/lib/rucoa/handlers/base.rb +9 -9
  15. data/lib/rucoa/handlers/initialize_handler.rb +1 -0
  16. data/lib/rucoa/handlers/initialized_handler.rb +16 -16
  17. data/lib/rucoa/handlers/text_document_code_action_handler.rb +12 -12
  18. data/lib/rucoa/handlers/text_document_completion_handler.rb +85 -99
  19. data/lib/rucoa/handlers/text_document_definition_handler.rb +11 -30
  20. data/lib/rucoa/handlers/text_document_did_close_handler.rb +2 -8
  21. data/lib/rucoa/handlers/text_document_did_open_handler.rb +3 -7
  22. data/lib/rucoa/handlers/text_document_document_highlight_handler.rb +531 -0
  23. data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +47 -76
  24. data/lib/rucoa/handlers/text_document_formatting_handler.rb +16 -24
  25. data/lib/rucoa/handlers/text_document_hover_handler.rb +24 -43
  26. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +17 -25
  27. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +11 -19
  28. data/lib/rucoa/handlers/text_document_signature_help_handler.rb +17 -36
  29. data/lib/rucoa/handlers.rb +1 -0
  30. data/lib/rucoa/node_concerns/body.rb +1 -1
  31. data/lib/rucoa/node_concerns/modifier.rb +35 -0
  32. data/lib/rucoa/node_concerns/qualified_name.rb +5 -5
  33. data/lib/rucoa/node_concerns/rescue.rb +21 -0
  34. data/lib/rucoa/node_concerns/variable.rb +26 -0
  35. data/lib/rucoa/node_concerns.rb +3 -0
  36. data/lib/rucoa/node_inspector.rb +5 -5
  37. data/lib/rucoa/nodes/arg_node.rb +26 -0
  38. data/lib/rucoa/nodes/args_node.rb +14 -0
  39. data/lib/rucoa/nodes/base.rb +111 -47
  40. data/lib/rucoa/nodes/begin_node.rb +2 -0
  41. data/lib/rucoa/nodes/block_node.rb +38 -0
  42. data/lib/rucoa/nodes/case_node.rb +24 -0
  43. data/lib/rucoa/nodes/const_node.rb +26 -26
  44. data/lib/rucoa/nodes/cvar_node.rb +9 -0
  45. data/lib/rucoa/nodes/cvasgn_node.rb +9 -0
  46. data/lib/rucoa/nodes/def_node.rb +28 -13
  47. data/lib/rucoa/nodes/ensure_node.rb +19 -0
  48. data/lib/rucoa/nodes/for_node.rb +8 -0
  49. data/lib/rucoa/nodes/gvar_node.rb +9 -0
  50. data/lib/rucoa/nodes/gvasgn_node.rb +9 -0
  51. data/lib/rucoa/nodes/if_node.rb +34 -0
  52. data/lib/rucoa/nodes/ivar_node.rb +9 -0
  53. data/lib/rucoa/nodes/ivasgn_node.rb +9 -0
  54. data/lib/rucoa/nodes/lvar_node.rb +1 -18
  55. data/lib/rucoa/nodes/lvasgn_node.rb +9 -0
  56. data/lib/rucoa/nodes/resbody_node.rb +8 -0
  57. data/lib/rucoa/nodes/rescue_node.rb +17 -0
  58. data/lib/rucoa/nodes/send_node.rb +40 -0
  59. data/lib/rucoa/nodes/until_node.rb +9 -0
  60. data/lib/rucoa/nodes/when_node.rb +8 -0
  61. data/lib/rucoa/nodes/while_node.rb +9 -0
  62. data/lib/rucoa/nodes.rb +19 -1
  63. data/lib/rucoa/parser_builder.rb +26 -2
  64. data/lib/rucoa/range.rb +9 -3
  65. data/lib/rucoa/rbs/constant_definition_mapper.rb +5 -5
  66. data/lib/rucoa/rbs/method_definition_mapper.rb +18 -18
  67. data/lib/rucoa/rbs/module_definition_mapper.rb +13 -13
  68. data/lib/rucoa/rbs/ruby_definitions_loader.rb +5 -5
  69. data/lib/rucoa/rubocop/configuration_checker.rb +7 -7
  70. data/lib/rucoa/server.rb +24 -23
  71. data/lib/rucoa/source.rb +6 -6
  72. data/lib/rucoa/source_store.rb +8 -8
  73. data/lib/rucoa/version.rb +1 -1
  74. data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +1 -1
  75. data/lib/rucoa/yard/definitions_loader.rb +1 -1
  76. data/rucoa.gemspec +0 -1
  77. metadata +28 -4
  78. data/lib/rucoa/nodes/defs_node.rb +0 -33
@@ -3,19 +3,14 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentFormattingHandler < Base
6
+ include HandlerConcerns::TextDocumentUriParameters
7
+
6
8
  def call
7
9
  respond(edits)
8
10
  end
9
11
 
10
12
  private
11
13
 
12
- # @return [Boolean]
13
- def formattable?
14
- configuration.enables_formatting? &&
15
- source &&
16
- Rubocop::ConfigurationChecker.call
17
- end
18
-
19
14
  # @return [Array<Hash>]
20
15
  def edits
21
16
  return [] unless formattable?
@@ -23,22 +18,11 @@ module Rucoa
23
18
  [text_edit]
24
19
  end
25
20
 
26
- # @return [Rucoa::Source, nil]
27
- def source
28
- @source ||= source_store.get(uri)
29
- end
30
-
31
- # @return [String]
32
- def uri
33
- request.dig('params', 'textDocument', 'uri')
34
- end
35
-
36
- # @return [Hash]
37
- def text_edit
38
- {
39
- newText: new_text,
40
- range: range
41
- }
21
+ # @return [Boolean]
22
+ def formattable?
23
+ configuration.enables_formatting? &&
24
+ source &&
25
+ Rubocop::ConfigurationChecker.call
42
26
  end
43
27
 
44
28
  # @return [String]
@@ -54,11 +38,19 @@ module Rucoa
54
38
  line: 1
55
39
  ),
56
40
  Position.new(
57
- column: @source.content.lines.last.length,
41
+ column: @source.content.lines.last&.length || 0,
58
42
  line: @source.content.lines.count + 1
59
43
  )
60
44
  ).to_vscode_range
61
45
  end
46
+
47
+ # @return [Hash]
48
+ def text_edit
49
+ {
50
+ newText: new_text,
51
+ range: range
52
+ }
53
+ end
62
54
  end
63
55
  end
64
56
  end
@@ -3,28 +3,15 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentHoverHandler < Base
6
+ include HandlerConcerns::TextDocumentPositionParameters
7
+ include HandlerConcerns::TextDocumentUriParameters
8
+
6
9
  def call
7
10
  respond(hover)
8
11
  end
9
12
 
10
13
  private
11
14
 
12
- # @return [Hash, nil]
13
- def hover
14
- return unless responsible?
15
-
16
- {
17
- contents: contents,
18
- range: range.to_vscode_range
19
- }
20
- end
21
-
22
- # @return [Boolean]
23
- def responsible?
24
- configuration.enables_hover? &&
25
- !contents.nil?
26
- end
27
-
28
15
  # @return [String, nil]
29
16
  def contents
30
17
  @contents ||=
@@ -42,33 +29,6 @@ module Rucoa
42
29
  end
43
30
  end
44
31
 
45
- # @return [Rucoa::Range]
46
- def range
47
- Range.from_parser_range(node.location.expression)
48
- end
49
-
50
- # @return [Rucoa::Nodes::Base, nil]
51
- def node
52
- @node ||= source&.node_at(position)
53
- end
54
-
55
- # @return [Rucoa::Source, nil]
56
- def source
57
- @source ||= source_store.get(uri)
58
- end
59
-
60
- # @return [String]
61
- def uri
62
- request.dig('params', 'textDocument', 'uri')
63
- end
64
-
65
- # @return [Rucoa::Position]
66
- def position
67
- Position.from_vscode_position(
68
- request.dig('params', 'position')
69
- )
70
- end
71
-
72
32
  # @return [Rucoa::Definitions::Base, nil]
73
33
  def definition
74
34
  return unless node
@@ -78,6 +38,27 @@ module Rucoa
78
38
  node: node
79
39
  ).definitions.first
80
40
  end
41
+
42
+ # @return [Hash, nil]
43
+ def hover
44
+ return unless responsible?
45
+
46
+ {
47
+ contents: contents,
48
+ range: range.to_vscode_range
49
+ }
50
+ end
51
+
52
+ # @return [Rucoa::Range]
53
+ def range
54
+ Range.from_parser_range(node.location.expression)
55
+ end
56
+
57
+ # @return [Boolean]
58
+ def responsible?
59
+ configuration.enables_hover? &&
60
+ !contents.nil?
61
+ end
81
62
  end
82
63
  end
83
64
  end
@@ -3,12 +3,26 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentRangeFormattingHandler < Base
6
+ include HandlerConcerns::TextDocumentUriParameters
7
+
6
8
  def call
7
9
  respond(edits)
8
10
  end
9
11
 
10
12
  private
11
13
 
14
+ # @return [Array<RuboCop::Cop::Corrector>]
15
+ def correctable_offenses
16
+ offenses.select(&:corrector)
17
+ end
18
+
19
+ # @return [Array(Rucoa::Range, String)]
20
+ def correctable_replacements
21
+ replacements.select do |replacement_range, _|
22
+ range.contain?(replacement_range)
23
+ end
24
+ end
25
+
12
26
  # @return [Array<Hash>]
13
27
  def edits
14
28
  return [] unless formattable?
@@ -28,14 +42,9 @@ module Rucoa
28
42
  Rubocop::ConfigurationChecker.call
29
43
  end
30
44
 
31
- # @return [Rucoa::Source]
32
- def source
33
- @source ||= source_store.get(uri)
34
- end
35
-
36
- # @return [String]
37
- def uri
38
- request.dig('params', 'textDocument', 'uri')
45
+ # @return [Array<RuboCop::Cop::Offense>]
46
+ def offenses
47
+ Rubocop::Investigator.call(source: source)
39
48
  end
40
49
 
41
50
  # @return [Rucoa::Range]
@@ -45,23 +54,6 @@ module Rucoa
45
54
  )
46
55
  end
47
56
 
48
- # @return [Array<RuboCop::Cop::Corrector>]
49
- def correctable_offenses
50
- offenses.select(&:corrector)
51
- end
52
-
53
- # @return [Array(Rucoa::Range, String)]
54
- def correctable_replacements
55
- replacements.select do |replacement_range, _|
56
- range.contain?(replacement_range)
57
- end
58
- end
59
-
60
- # @return [Array<RuboCop::Cop::Offense>]
61
- def offenses
62
- Rubocop::Investigator.call(source: source)
63
- end
64
-
65
57
  # @return [Array(Rucoa::Range, String)]
66
58
  def replacements
67
59
  correctable_offenses.map(&:corrector).flat_map(&:as_replacements).map do |replacement_range, replacement|
@@ -3,6 +3,8 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentSelectionRangeHandler < Base
6
+ include HandlerConcerns::TextDocumentUriParameters
7
+
6
8
  def call
7
9
  return unless responsible?
8
10
 
@@ -18,17 +20,6 @@ module Rucoa
18
20
 
19
21
  private
20
22
 
21
- # @return [Boolean]
22
- def responsible?
23
- configuration.enables_selection_range? &&
24
- !source.nil?
25
- end
26
-
27
- # @return [Rucoa::Source]
28
- def source
29
- @source ||= source_store.get(uri)
30
- end
31
-
32
23
  # @return [Array<Rucoa::Position>]
33
24
  def positions
34
25
  request.dig('params', 'positions').map do |position|
@@ -36,9 +27,10 @@ module Rucoa
36
27
  end
37
28
  end
38
29
 
39
- # @return [String]
40
- def uri
41
- request.dig('params', 'textDocument', 'uri')
30
+ # @return [Boolean]
31
+ def responsible?
32
+ configuration.enables_selection_range? &&
33
+ !source.nil?
42
34
  end
43
35
 
44
36
  class SelectionRangeProvider
@@ -128,6 +120,11 @@ module Rucoa
128
120
 
129
121
  private
130
122
 
123
+ # @return [Rucoa::Range]
124
+ def expression_range
125
+ Range.from_parser_range(@node.location.expression)
126
+ end
127
+
131
128
  # @return [Rucoa::Range]
132
129
  def inner_range
133
130
  Range.new(
@@ -135,11 +132,6 @@ module Rucoa
135
132
  Position.from_parser_range_beginning(@node.location.end)
136
133
  )
137
134
  end
138
-
139
- # @return [Rucoa::Range]
140
- def expression_range
141
- Range.from_parser_range(@node.location.expression)
142
- end
143
135
  end
144
136
  end
145
137
  end
@@ -3,12 +3,29 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentSignatureHelpHandler < Base
6
+ include HandlerConcerns::TextDocumentPositionParameters
7
+ include HandlerConcerns::TextDocumentUriParameters
8
+
6
9
  def call
7
10
  respond(signature_help)
8
11
  end
9
12
 
10
13
  private
11
14
 
15
+ # @return [Array<Rucoa::Definitions::MethodDefinition>]
16
+ def method_definitions
17
+ NodeInspector.new(
18
+ definition_store: definition_store,
19
+ node: node
20
+ ).method_definitions
21
+ end
22
+
23
+ # @return [Boolean]
24
+ def responsible?
25
+ configuration.enables_signature_help? &&
26
+ node.is_a?(Nodes::SendNode)
27
+ end
28
+
12
29
  # @return [Hash]
13
30
  def signature_help
14
31
  return unless responsible?
@@ -18,12 +35,6 @@ module Rucoa
18
35
  }
19
36
  end
20
37
 
21
- # @return [Boolean]
22
- def responsible?
23
- configuration.enables_signature_help? &&
24
- node.is_a?(Nodes::SendNode)
25
- end
26
-
27
38
  # @return [Array<Hash>]
28
39
  def signature_informations
29
40
  method_definitions.map do |method_definition|
@@ -33,36 +44,6 @@ module Rucoa
33
44
  }
34
45
  end
35
46
  end
36
-
37
- # @return [Array<Rucoa::Definitions::MethodDefinition>]
38
- def method_definitions
39
- NodeInspector.new(
40
- definition_store: definition_store,
41
- node: node
42
- ).method_definitions
43
- end
44
-
45
- # @return [Rucoa::Nodes::Base, nil]
46
- def node
47
- @node ||= source.node_at(position)
48
- end
49
-
50
- # @return [Rucoa::Position]
51
- def position
52
- Position.from_vscode_position(
53
- request.dig('params', 'position')
54
- )
55
- end
56
-
57
- # @return [Rucoa::Source]
58
- def source
59
- source_store.get(uri)
60
- end
61
-
62
- # @return [String]
63
- def uri
64
- request.dig('params', 'textDocument', 'uri')
65
- end
66
47
  end
67
48
  end
68
49
  end
@@ -13,6 +13,7 @@ module Rucoa
13
13
  autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
14
14
  autoload :TextDocumentDidCloseHandler, 'rucoa/handlers/text_document_did_close_handler'
15
15
  autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
16
+ autoload :TextDocumentDocumentHighlightHandler, 'rucoa/handlers/text_document_document_highlight_handler'
16
17
  autoload :TextDocumentDocumentSymbolHandler, 'rucoa/handlers/text_document_document_symbol_handler'
17
18
  autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
18
19
  autoload :TextDocumentHoverHandler, 'rucoa/handlers/text_document_hover_handler'
@@ -5,7 +5,7 @@ module Rucoa
5
5
  module Body
6
6
  # @return [Rucoa::Nodes::BeginNode, nil]
7
7
  def body
8
- children[2]
8
+ children.last
9
9
  end
10
10
 
11
11
  # @return [Array<Rucoa::Nodes::Base>]
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module NodeConcerns
5
+ module Modifier
6
+ # @return [Boolean]
7
+ # @example returns true on modifier if node
8
+ # node = Rucoa::Source.new(
9
+ # content: <<~RUBY,
10
+ # 1 if true
11
+ # RUBY
12
+ # uri: 'file:///path/to/example.rb'
13
+ # ).node_at(
14
+ # Rucoa::Position.new(
15
+ # column: 2,
16
+ # line: 1
17
+ # )
18
+ # )
19
+ # expect(node).to be_modifier
20
+ # @example returns false on non-modifier if node
21
+ # node = Rucoa::Source.new(
22
+ # content: <<~RUBY,
23
+ # if true
24
+ # 1
25
+ # end
26
+ # RUBY
27
+ # uri: 'file:///path/to/example.rb'
28
+ # ).root_node
29
+ # expect(node).not_to be_modifier
30
+ def modifier?
31
+ location.end.nil?
32
+ end
33
+ end
34
+ end
35
+ end
@@ -3,6 +3,11 @@
3
3
  module Rucoa
4
4
  module NodeConcerns
5
5
  module QualifiedName
6
+ # @return [String]
7
+ def name
8
+ raise NotImplementedError
9
+ end
10
+
6
11
  # @return [String]
7
12
  def qualified_name
8
13
  [
@@ -10,11 +15,6 @@ module Rucoa
10
15
  *each_ancestor(:class, :constant, :module).map(&:name)
11
16
  ].reverse.join('::')
12
17
  end
13
-
14
- # @return [String]
15
- def name
16
- raise NotImplementedError
17
- end
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module NodeConcerns
5
+ module Rescue
6
+ # @return [Rucoa::Nodes::EnsureNode, nil]
7
+ def ensure
8
+ return unless body.is_a?(Nodes::EnsureNode)
9
+
10
+ body
11
+ end
12
+
13
+ # @return [Rucoa::Nodes::RescueNode, nil]
14
+ def rescue
15
+ return unless body.is_a?(Nodes::RescueNode)
16
+
17
+ body
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module NodeConcerns
5
+ module Variable
6
+ # @return [String]
7
+ # @example returns variable name
8
+ # node = Rucoa::Source.new(
9
+ # content: <<~RUBY,
10
+ # foo = 1
11
+ # foo
12
+ # RUBY
13
+ # uri: 'file:///path/to/example.rb'
14
+ # ).node_at(
15
+ # Rucoa::Position.new(
16
+ # column: 0,
17
+ # line: 2
18
+ # )
19
+ # )
20
+ # expect(node.name).to eq('foo')
21
+ def name
22
+ children[0].to_s
23
+ end
24
+ end
25
+ end
26
+ end
@@ -3,6 +3,9 @@
3
3
  module Rucoa
4
4
  module NodeConcerns
5
5
  autoload :Body, 'rucoa/node_concerns/body'
6
+ autoload :Modifier, 'rucoa/node_concerns/modifier'
6
7
  autoload :QualifiedName, 'rucoa/node_concerns/qualified_name'
8
+ autoload :Rescue, 'rucoa/node_concerns/rescue'
9
+ autoload :Variable, 'rucoa/node_concerns/variable'
7
10
  end
8
11
  end
@@ -103,11 +103,6 @@ module Rucoa
103
103
  )
104
104
  end
105
105
 
106
- # @return [Boolean]
107
- def singleton_method_call?
108
- @node.is_a?(Nodes::ConstNode)
109
- end
110
-
111
106
  # @return [String, nil]
112
107
  def nearest_def_qualified_name
113
108
  @node.each_ancestor(:def).first&.qualified_name
@@ -147,5 +142,10 @@ module Rucoa
147
142
  )&.return_types
148
143
  end.compact
149
144
  end
145
+
146
+ # @return [Boolean]
147
+ def singleton_method_call?
148
+ @node.is_a?(Nodes::ConstNode)
149
+ end
150
150
  end
151
151
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ArgNode < Base
6
+ # @return [String]
7
+ # @example returns variable name
8
+ # node = Rucoa::Source.new(
9
+ # content: <<~RUBY,
10
+ # def foo(bar)
11
+ # end
12
+ # RUBY
13
+ # uri: 'file:///path/to/example.rb'
14
+ # ).node_at(
15
+ # Rucoa::Position.new(
16
+ # column: 8,
17
+ # line: 1
18
+ # )
19
+ # )
20
+ # expect(node.name).to eq('bar')
21
+ def name
22
+ children[0].to_s
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ArgsNode < Base
6
+ include ::Enumerable
7
+
8
+ # @note For `Enumerable`.
9
+ def each(&block)
10
+ children.each(&block)
11
+ end
12
+ end
13
+ end
14
+ end