rucoa 0.3.0 → 0.4.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +2 -2
  4. data/lib/rucoa/configuration.rb +8 -0
  5. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +140 -0
  6. data/lib/rucoa/handlers/initialize_handler.rb +1 -0
  7. data/lib/rucoa/handlers/text_document_code_action_handler.rb +78 -3
  8. data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +241 -0
  9. data/lib/rucoa/handlers/text_document_formatting_handler.rb +36 -5
  10. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +65 -13
  11. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +124 -8
  12. data/lib/rucoa/handlers.rb +1 -0
  13. data/lib/rucoa/node_concerns/name_full_qualifiable.rb +20 -0
  14. data/lib/rucoa/node_concerns.rb +7 -0
  15. data/lib/rucoa/nodes/base.rb +13 -0
  16. data/lib/rucoa/nodes/casgn_node.rb +14 -0
  17. data/lib/rucoa/nodes/class_node.rb +8 -0
  18. data/lib/rucoa/nodes/const_node.rb +12 -0
  19. data/lib/rucoa/nodes/def_node.rb +12 -0
  20. data/lib/rucoa/nodes/defs_node.rb +12 -0
  21. data/lib/rucoa/nodes/module_node.rb +21 -0
  22. data/lib/rucoa/nodes/sclass_node.rb +8 -0
  23. data/lib/rucoa/nodes/send_node.rb +17 -0
  24. data/lib/rucoa/nodes/str_node.rb +4 -0
  25. data/lib/rucoa/nodes/sym_node.rb +12 -0
  26. data/lib/rucoa/nodes.rb +9 -0
  27. data/lib/rucoa/parser_builder.rb +19 -10
  28. data/lib/rucoa/server.rb +1 -0
  29. data/lib/rucoa/source.rb +2 -2
  30. data/lib/rucoa/version.rb +1 -1
  31. data/lib/rucoa.rb +1 -5
  32. metadata +14 -7
  33. data/lib/rucoa/code_action_provider.rb +0 -102
  34. data/lib/rucoa/diagnostic_provider.rb +0 -143
  35. data/lib/rucoa/formatting_provider.rb +0 -54
  36. data/lib/rucoa/range_formatting_provider.rb +0 -67
  37. data/lib/rucoa/selection_range_provider.rb +0 -99
@@ -4,22 +4,138 @@ module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentSelectionRangeHandler < Base
6
6
  def call
7
- return unless configuration.enables_selection_range?
8
-
9
- source = source_store.get(
10
- request.dig('params', 'textDocument', 'uri')
11
- )
12
- return unless source
7
+ return unless respondable?
13
8
 
14
9
  respond(
15
- request.dig('params', 'positions').filter_map do |position|
10
+ positions.filter_map do |position|
16
11
  SelectionRangeProvider.call(
17
- position: Position.from_vscode_position(position),
12
+ position: position,
18
13
  source: source
19
14
  )
20
15
  end
21
16
  )
22
17
  end
18
+
19
+ private
20
+
21
+ # @return [Boolean]
22
+ def respondable?
23
+ configuration.enables_selection_range? &&
24
+ source
25
+ end
26
+
27
+ # @return [Rucoa::Source]
28
+ def source
29
+ @source ||= source_store.get(uri)
30
+ end
31
+
32
+ # @return [Array<Rucoa::Position>]
33
+ def positions
34
+ request.dig('params', 'positions').map do |position|
35
+ Position.from_vscode_position(position)
36
+ end
37
+ end
38
+
39
+ # @return [String]
40
+ def uri
41
+ request.dig('params', 'textDocument', 'uri')
42
+ end
43
+
44
+ class SelectionRangeProvider
45
+ class << self
46
+ # @param source [Rucoa::Source]
47
+ # @param position [Rucoa::Position]
48
+ # @return [Hash, nil]
49
+ def call(position:, source:)
50
+ new(
51
+ position: position,
52
+ source: source
53
+ ).call
54
+ end
55
+ end
56
+
57
+ # @param position [Rucoa::Position]
58
+ # @param source [Rucoa::Source]
59
+ def initialize(position:, source:)
60
+ @position = position
61
+ @source = source
62
+ end
63
+
64
+ # @return [Hash, nil]
65
+ def call
66
+ ranges.reverse.reduce(nil) do |result, range|
67
+ {
68
+ parent: result,
69
+ range: range.to_vscode_range
70
+ }
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ # @return [Rucoa::Nodes::Base, nil]
77
+ def node_at_position
78
+ if instance_variable_defined?(:@node_at_position)
79
+ @node_at_position
80
+ else
81
+ @node_at_position = @source.node_at(@position)
82
+ end
83
+ end
84
+
85
+ # @return [Array<Rucoa::Range>]
86
+ def ranges
87
+ return [] unless node_at_position
88
+
89
+ [node_at_position, *node_at_position.ancestors].flat_map do |node|
90
+ NodeToRangesMapper.call(node)
91
+ end
92
+ end
93
+
94
+ class NodeToRangesMapper
95
+ class << self
96
+ # @param node [Rucoa::Nodes::Base]
97
+ # @return [Array<Rucoa::Range>]
98
+ def call(node)
99
+ new(node).call
100
+ end
101
+ end
102
+
103
+ # @param node [Rucoa::Nodes::Base]
104
+ def initialize(node)
105
+ @node = node
106
+ end
107
+
108
+ # @return [Array<Rucoa::Range>]
109
+ def call
110
+ case @node
111
+ when Nodes::StrNode
112
+ [
113
+ inner_range,
114
+ expression_range
115
+ ]
116
+ else
117
+ [
118
+ expression_range
119
+ ]
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ # @return [Rucoa::Range]
126
+ def inner_range
127
+ Range.new(
128
+ Position.from_parser_range_ending(@node.location.begin),
129
+ Position.from_parser_range_beginning(@node.location.end)
130
+ )
131
+ end
132
+
133
+ # @return [Rucoa::Range]
134
+ def expression_range
135
+ Range.from_parser_range(@node.location.expression)
136
+ end
137
+ end
138
+ end
23
139
  end
24
140
  end
25
141
  end
@@ -8,6 +8,7 @@ module Rucoa
8
8
  autoload :TextDocumentCodeActionHandler, 'rucoa/handlers/text_document_code_action_handler'
9
9
  autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
10
10
  autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
11
+ autoload :TextDocumentDocumentSymbolHandler, 'rucoa/handlers/text_document_document_symbol_handler'
11
12
  autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
12
13
  autoload :TextDocumentRangeFormattingHandler, 'rucoa/handlers/text_document_range_formatting_handler'
13
14
  autoload :TextDocumentSelectionRangeHandler, 'rucoa/handlers/text_document_selection_range_handler'
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module NodeConcerns
5
+ module NameFullQualifiable
6
+ # @return [String]
7
+ def full_qualified_name
8
+ [
9
+ name,
10
+ *each_ancestor(:class, :constant, :module).map(&:name)
11
+ ].reverse.join('::')
12
+ end
13
+
14
+ # @return [String]
15
+ def name
16
+ raise NotImplementedError
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module NodeConcerns
5
+ autoload :NameFullQualifiable, 'rucoa/node_concerns/name_full_qualifiable'
6
+ end
7
+ end
@@ -64,6 +64,19 @@ module Rucoa
64
64
  self
65
65
  end
66
66
 
67
+ # @note Override.
68
+ # Some nodes change their type depending on the context.
69
+ # For example, `const` node can be `casgn` node.
70
+ # @return [Rucoa::Nodes::Base]
71
+ def updated(type = nil, children = nil, properties = {})
72
+ properties[:location] ||= @location
73
+ ParserBuilder.node_class_for(type || @type).new(
74
+ type || @type,
75
+ children || @children,
76
+ properties
77
+ )
78
+ end
79
+
67
80
  # @param position [Rucoa::Position]
68
81
  # @return [Boolean]
69
82
  def include_position?(position)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class CasgnNode < Base
6
+ include NodeConcerns::NameFullQualifiable
7
+
8
+ # @return [String]
9
+ def name
10
+ children[1].to_s
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ClassNode < ModuleNode
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ConstNode < Base
6
+ # @return [String]
7
+ def name
8
+ children[1].to_s
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class DefNode < Base
6
+ # @return [String]
7
+ def name
8
+ children[0].to_s
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class DefsNode < Base
6
+ # @return [String]
7
+ def name
8
+ children[1].to_s
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class ModuleNode < Base
6
+ include NodeConcerns::NameFullQualifiable
7
+
8
+ # @return [String]
9
+ def name
10
+ const_node.name
11
+ end
12
+
13
+ private
14
+
15
+ # @return [Rucoa::Nodes::ConstNode]
16
+ def const_node
17
+ children[0]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class SclassNode < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class SendNode < Base
6
+ # @return [Array<Rucoa::Nodes::Base>]
7
+ def arguments
8
+ children[2..]
9
+ end
10
+
11
+ # @return [String]
12
+ def name
13
+ children[1].to_s
14
+ end
15
+ end
16
+ end
17
+ end
@@ -3,6 +3,10 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  class StrNode < Base
6
+ # @return [String]
7
+ def value
8
+ children[0]
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class SymNode < Base
6
+ # @return [String]
7
+ def value
8
+ children[0]
9
+ end
10
+ end
11
+ end
12
+ end
data/lib/rucoa/nodes.rb CHANGED
@@ -3,6 +3,15 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  autoload :Base, 'rucoa/nodes/base'
6
+ autoload :ClassNode, 'rucoa/nodes/class_node'
7
+ autoload :CasgnNode, 'rucoa/nodes/casgn_node'
8
+ autoload :ConstNode, 'rucoa/nodes/const_node'
9
+ autoload :DefNode, 'rucoa/nodes/def_node'
10
+ autoload :DefsNode, 'rucoa/nodes/defs_node'
11
+ autoload :ModuleNode, 'rucoa/nodes/module_node'
12
+ autoload :SclassNode, 'rucoa/nodes/sclass_node'
13
+ autoload :SendNode, 'rucoa/nodes/send_node'
6
14
  autoload :StrNode, 'rucoa/nodes/str_node'
15
+ autoload :SymNode, 'rucoa/nodes/sym_node'
7
16
  end
8
17
  end
@@ -5,24 +5,33 @@ require 'parser/current'
5
5
  module Rucoa
6
6
  class ParserBuilder < ::Parser::Builders::Default
7
7
  NODE_CLASS_BY_TYPE = {
8
- str: Nodes::StrNode
8
+ casgn: Nodes::CasgnNode,
9
+ class: Nodes::ClassNode,
10
+ const: Nodes::ConstNode,
11
+ def: Nodes::DefNode,
12
+ defs: Nodes::DefsNode,
13
+ module: Nodes::ModuleNode,
14
+ sclass: Nodes::SclassNode,
15
+ send: Nodes::SendNode,
16
+ str: Nodes::StrNode,
17
+ sym: Nodes::SymNode
9
18
  }.freeze
10
19
 
20
+ class << self
21
+ # @param type [Symbol]
22
+ # @return [Class]
23
+ def node_class_for(type)
24
+ NODE_CLASS_BY_TYPE.fetch(type, Nodes::Base)
25
+ end
26
+ end
27
+
11
28
  # @note Override.
12
29
  def n(type, children, source_map)
13
- node_class_for(type).new(
30
+ self.class.node_class_for(type).new(
14
31
  type,
15
32
  children,
16
33
  location: source_map
17
34
  )
18
35
  end
19
-
20
- private
21
-
22
- # @param type [Symbol]
23
- # @return [Class]
24
- def node_class_for(type)
25
- NODE_CLASS_BY_TYPE.fetch(type, Nodes::Base)
26
- end
27
36
  end
28
37
  end
data/lib/rucoa/server.rb CHANGED
@@ -9,6 +9,7 @@ module Rucoa
9
9
  'textDocument/codeAction' => Handlers::TextDocumentCodeActionHandler,
10
10
  'textDocument/didChange' => Handlers::TextDocumentDidChangeHandler,
11
11
  'textDocument/didOpen' => Handlers::TextDocumentDidOpenHandler,
12
+ 'textDocument/documentSymbol' => Handlers::TextDocumentDocumentSymbolHandler,
12
13
  'textDocument/formatting' => Handlers::TextDocumentFormattingHandler,
13
14
  'textDocument/rangeFormatting' => Handlers::TextDocumentRangeFormattingHandler,
14
15
  'textDocument/selectionRange' => Handlers::TextDocumentSelectionRangeHandler,
data/lib/rucoa/source.rb CHANGED
@@ -23,13 +23,13 @@ module Rucoa
23
23
  end
24
24
  end
25
25
 
26
- private
27
-
28
26
  # @return [Rucoa::Nodes::Base, nil]
29
27
  def root_node
30
28
  @root_node ||= Parser.call(@content)
31
29
  end
32
30
 
31
+ private
32
+
33
33
  # @return [Array<Rucoa::Nodes::Base>]
34
34
  def root_and_descendant_nodes
35
35
  return [] unless root_node
data/lib/rucoa/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rucoa
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/rucoa.rb CHANGED
@@ -4,25 +4,21 @@ require_relative 'rucoa/version'
4
4
 
5
5
  module Rucoa
6
6
  autoload :Cli, 'rucoa/cli'
7
- autoload :CodeActionProvider, 'rucoa/code_action_provider'
8
7
  autoload :Configuration, 'rucoa/configuration'
9
- autoload :DiagnosticProvider, 'rucoa/diagnostic_provider'
10
8
  autoload :Errors, 'rucoa/errors'
11
- autoload :FormattingProvider, 'rucoa/formatting_provider'
12
9
  autoload :HandlerConcerns, 'rucoa/handler_concerns'
13
10
  autoload :Handlers, 'rucoa/handlers'
14
11
  autoload :MessageReader, 'rucoa/message_reader'
15
12
  autoload :MessageWriter, 'rucoa/message_writer'
13
+ autoload :NodeConcerns, 'rucoa/node_concerns'
16
14
  autoload :Nodes, 'rucoa/nodes'
17
15
  autoload :Parser, 'rucoa/parser'
18
16
  autoload :ParserBuilder, 'rucoa/parser_builder'
19
17
  autoload :Position, 'rucoa/position'
20
18
  autoload :Range, 'rucoa/range'
21
- autoload :RangeFormattingProvider, 'rucoa/range_formatting_provider'
22
19
  autoload :RubocopAutocorrector, 'rucoa/rubocop_autocorrector'
23
20
  autoload :RubocopConfigurationChecker, 'rucoa/rubocop_configuration_checker'
24
21
  autoload :RubocopInvestigator, 'rucoa/rubocop_investigator'
25
- autoload :SelectionRangeProvider, 'rucoa/selection_range_provider'
26
22
  autoload :Server, 'rucoa/server'
27
23
  autoload :Source, 'rucoa/source'
28
24
  autoload :SourceStore, 'rucoa/source_store'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rucoa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-07 00:00:00.000000000 Z
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -57,11 +57,8 @@ files:
57
57
  - exe/rucoa
58
58
  - lib/rucoa.rb
59
59
  - lib/rucoa/cli.rb
60
- - lib/rucoa/code_action_provider.rb
61
60
  - lib/rucoa/configuration.rb
62
- - lib/rucoa/diagnostic_provider.rb
63
61
  - lib/rucoa/errors.rb
64
- - lib/rucoa/formatting_provider.rb
65
62
  - lib/rucoa/handler_concerns.rb
66
63
  - lib/rucoa/handler_concerns/configuration_requestable.rb
67
64
  - lib/rucoa/handler_concerns/diagnostics_publishable.rb
@@ -72,24 +69,34 @@ files:
72
69
  - lib/rucoa/handlers/text_document_code_action_handler.rb
73
70
  - lib/rucoa/handlers/text_document_did_change_handler.rb
74
71
  - lib/rucoa/handlers/text_document_did_open_handler.rb
72
+ - lib/rucoa/handlers/text_document_document_symbol_handler.rb
75
73
  - lib/rucoa/handlers/text_document_formatting_handler.rb
76
74
  - lib/rucoa/handlers/text_document_range_formatting_handler.rb
77
75
  - lib/rucoa/handlers/text_document_selection_range_handler.rb
78
76
  - lib/rucoa/handlers/workspace_did_change_configuration_handler.rb
79
77
  - lib/rucoa/message_reader.rb
80
78
  - lib/rucoa/message_writer.rb
79
+ - lib/rucoa/node_concerns.rb
80
+ - lib/rucoa/node_concerns/name_full_qualifiable.rb
81
81
  - lib/rucoa/nodes.rb
82
82
  - lib/rucoa/nodes/base.rb
83
+ - lib/rucoa/nodes/casgn_node.rb
84
+ - lib/rucoa/nodes/class_node.rb
85
+ - lib/rucoa/nodes/const_node.rb
86
+ - lib/rucoa/nodes/def_node.rb
87
+ - lib/rucoa/nodes/defs_node.rb
88
+ - lib/rucoa/nodes/module_node.rb
89
+ - lib/rucoa/nodes/sclass_node.rb
90
+ - lib/rucoa/nodes/send_node.rb
83
91
  - lib/rucoa/nodes/str_node.rb
92
+ - lib/rucoa/nodes/sym_node.rb
84
93
  - lib/rucoa/parser.rb
85
94
  - lib/rucoa/parser_builder.rb
86
95
  - lib/rucoa/position.rb
87
96
  - lib/rucoa/range.rb
88
- - lib/rucoa/range_formatting_provider.rb
89
97
  - lib/rucoa/rubocop_autocorrector.rb
90
98
  - lib/rucoa/rubocop_configuration_checker.rb
91
99
  - lib/rucoa/rubocop_investigator.rb
92
- - lib/rucoa/selection_range_provider.rb
93
100
  - lib/rucoa/server.rb
94
101
  - lib/rucoa/source.rb
95
102
  - lib/rucoa/source_store.rb
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rucoa
4
- class CodeActionProvider
5
- class << self
6
- # @param diagnostics [Array<Hash>]
7
- # @return [Array<Hash>]
8
- def call(diagnostics:)
9
- new(diagnostics: diagnostics).call
10
- end
11
- end
12
-
13
- # @param diagnostics [Array<Hash>]
14
- def initialize(diagnostics:)
15
- @diagnostics = diagnostics
16
- end
17
-
18
- # @return [Array<Hash>]
19
- def call
20
- correctable_diagnostics.map do |diagnostic|
21
- DiagnosticToCodeActionMapper.call(diagnostic)
22
- end
23
- end
24
-
25
- private
26
-
27
- # @return [Array<Hash>]
28
- def correctable_diagnostics
29
- @diagnostics.select do |diagnostic|
30
- diagnostic.dig('data', 'edits')
31
- end
32
- end
33
-
34
- class DiagnosticToCodeActionMapper
35
- class << self
36
- # @param diagnostic [Hash]
37
- # @return [Hash]
38
- def call(diagnostic)
39
- new(diagnostic).call
40
- end
41
- end
42
-
43
- # @param diagnostic [Hash]
44
- def initialize(diagnostic)
45
- @diagnostic = diagnostic
46
- end
47
-
48
- # @return [Hash]
49
- def call
50
- {
51
- diagnostics: diagnostics,
52
- edit: edit,
53
- isPreferred: preferred?,
54
- kind: kind,
55
- title: title
56
- }
57
- end
58
-
59
- private
60
-
61
- # @return [Hash]
62
- def edit
63
- {
64
- documentChanges: [
65
- {
66
- edits: @diagnostic.dig('data', 'edits'),
67
- textDocument: {
68
- uri: @diagnostic.dig('data', 'uri'),
69
- version: nil
70
- }
71
- }
72
- ]
73
- }
74
- end
75
-
76
- # @return [String]
77
- def cop_name
78
- @diagnostic.dig('data', 'cop_name')
79
- end
80
-
81
- # @return [Array]
82
- def diagnostics
83
- [@diagnostic]
84
- end
85
-
86
- # @return [Boolean]
87
- def preferred?
88
- true
89
- end
90
-
91
- # @return [String]
92
- def kind
93
- 'quickfix'
94
- end
95
-
96
- # @return [String]
97
- def title
98
- "Autocorrect #{cop_name}"
99
- end
100
- end
101
- end
102
- end