rucoa 0.11.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
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