rucoa 0.3.0 → 0.4.0

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