rucoa 0.7.0 → 0.9.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +4 -1
  4. data/data/definitions_ruby_3_1 +0 -0
  5. data/lib/rucoa/configuration.rb +10 -0
  6. data/lib/rucoa/definition_store.rb +194 -27
  7. data/lib/rucoa/definitions/class_definition.rb +82 -0
  8. data/lib/rucoa/definitions/constant_definition.rb +7 -7
  9. data/lib/rucoa/definitions/method_definition.rb +18 -6
  10. data/lib/rucoa/definitions/module_definition.rb +8 -0
  11. data/lib/rucoa/definitions.rb +2 -0
  12. data/lib/rucoa/handlers/initialize_handler.rb +1 -0
  13. data/lib/rucoa/handlers/initialized_handler.rb +33 -5
  14. data/lib/rucoa/handlers/text_document_completion_handler.rb +2 -2
  15. data/lib/rucoa/handlers/text_document_definition_handler.rb +155 -0
  16. data/lib/rucoa/handlers/text_document_did_open_handler.rb +1 -4
  17. data/lib/rucoa/handlers/text_document_hover_handler.rb +3 -4
  18. data/lib/rucoa/handlers.rb +1 -0
  19. data/lib/rucoa/node_concerns/{name_full_qualifiable.rb → name_fully_qualifiable.rb} +2 -2
  20. data/lib/rucoa/node_concerns.rb +1 -1
  21. data/lib/rucoa/node_inspector.rb +56 -34
  22. data/lib/rucoa/nodes/base.rb +32 -7
  23. data/lib/rucoa/nodes/casgn_node.rb +1 -1
  24. data/lib/rucoa/nodes/cbase_node.rb +8 -0
  25. data/lib/rucoa/nodes/class_node.rb +62 -1
  26. data/lib/rucoa/nodes/const_node.rb +72 -0
  27. data/lib/rucoa/nodes/def_node.rb +11 -9
  28. data/lib/rucoa/nodes/defs_node.rb +21 -0
  29. data/lib/rucoa/nodes/lvar_node.rb +2 -1
  30. data/lib/rucoa/nodes/module_node.rb +1 -1
  31. data/lib/rucoa/nodes/send_node.rb +14 -10
  32. data/lib/rucoa/nodes.rb +1 -0
  33. data/lib/rucoa/parse_result.rb +29 -0
  34. data/lib/rucoa/parser.rb +40 -8
  35. data/lib/rucoa/parser_builder.rb +1 -0
  36. data/lib/rucoa/position.rb +1 -1
  37. data/lib/rucoa/rbs/class_definition_mapper.rb +46 -0
  38. data/lib/rucoa/rbs/constant_definition_mapper.rb +2 -2
  39. data/lib/rucoa/rbs/module_definition_mapper.rb +40 -0
  40. data/lib/rucoa/rbs/ruby_definitions_loader.rb +11 -7
  41. data/lib/rucoa/rbs.rb +2 -0
  42. data/lib/rucoa/rubocop/autocorrector.rb +12 -1
  43. data/lib/rucoa/rubocop/investigator.rb +10 -1
  44. data/lib/rucoa/server.rb +2 -1
  45. data/lib/rucoa/source.rb +47 -24
  46. data/lib/rucoa/source_store.rb +0 -13
  47. data/lib/rucoa/version.rb +1 -1
  48. data/lib/rucoa/yard/definitions_loader.rb +320 -48
  49. data/lib/rucoa/yard/type.rb +46 -0
  50. data/lib/rucoa/yard.rb +1 -1
  51. data/lib/rucoa.rb +1 -0
  52. metadata +11 -4
  53. data/lib/rucoa/yard/definition_mapper.rb +0 -217
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Handlers
5
+ class TextDocumentDefinitionHandler < Base
6
+ def call
7
+ respond(location)
8
+ end
9
+
10
+ private
11
+
12
+ # @return [Hash, nil]
13
+ def location
14
+ return unless reponsible?
15
+
16
+ {
17
+ range: location_range.to_vscode_range,
18
+ uri: location_uri
19
+ }
20
+ end
21
+
22
+ # @return [Boolean]
23
+ def reponsible?
24
+ configuration.enables_definition? &&
25
+ !location_uri.nil? &&
26
+ !location_source.nil?
27
+ end
28
+
29
+ # @return [Rucoa::Range]
30
+ def location_range
31
+ return Range.from_parser_range(location_node.location.expression) if location_node
32
+
33
+ Position.new.to_range
34
+ end
35
+
36
+ # @return [String, nil]
37
+ def location_uri
38
+ return unless definition
39
+
40
+ if definition.source_path.start_with?('Untitled-')
41
+ "untitled:#{definition.source_path}"
42
+ else
43
+ "file://#{definition.source_path}"
44
+ end
45
+ end
46
+
47
+ # @return [Rucoa::Nodes::Base, nil]
48
+ def location_node
49
+ @location_node ||=
50
+ case definition
51
+ when Definitions::ClassDefinition
52
+ find_class_node
53
+ when Definitions::ModuleDefinition
54
+ find_module_node
55
+ when Definitions::MethodDefinition
56
+ find_method_node
57
+ end
58
+ end
59
+
60
+ # @return [Rucoa::Source, nil]
61
+ def location_source
62
+ source_store.get(location_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
+ # @return [String]
73
+ def uri
74
+ request.dig('params', 'textDocument', 'uri')
75
+ end
76
+
77
+ # @return [Rucoa::Source, nil]
78
+ def source
79
+ source_store.get(uri)
80
+ end
81
+
82
+ # @return [Rucoa::Nodes::Base]
83
+ def node
84
+ source&.node_at(position)
85
+ end
86
+
87
+ # @return [Rucoa::Definitions::Base, nil]
88
+ def definition
89
+ @definition ||= NodeInspector.new(
90
+ definition_store: definition_store,
91
+ node: node
92
+ ).definitions.first
93
+ end
94
+
95
+ # @return [Rucoa::Nodes::ClassNode, nil]
96
+ def find_class_node
97
+ find_by_fully_qualified_name(
98
+ fully_qualified_name: definition.fully_qualified_name,
99
+ klass: Nodes::ClassNode
100
+ ) || find_by_name(
101
+ klass: Nodes::ClassNode,
102
+ name: definition.name
103
+ )
104
+ end
105
+
106
+ # @return [Rucoa::Nodes::ModuleNode, nil]
107
+ def find_module_node
108
+ find_by_fully_qualified_name(
109
+ fully_qualified_name: definition.fully_qualified_name,
110
+ klass: Nodes::ModuleNode
111
+ ) || find_by_name(
112
+ klass: Nodes::ModuleNode,
113
+ name: definition.name
114
+ )
115
+ end
116
+
117
+ # @return [Rucoa::Nodes::MethodNode, nil]
118
+ def find_method_node
119
+ location_root_or_descendant_nodes.reverse.find do |node|
120
+ node.is_a?(Nodes::DefNode) &&
121
+ node.name == definition.method_name &&
122
+ node.namespace == definition.namespace
123
+ end
124
+ end
125
+
126
+ # @param fully_qualified_name [String]
127
+ # @param klass [Class]
128
+ # @return [Rucoa::Nodes::Base, nil]
129
+ def find_by_fully_qualified_name(fully_qualified_name:, klass:)
130
+ location_root_or_descendant_nodes.reverse.find do |node|
131
+ node.is_a?(klass) &&
132
+ node.fully_qualified_name == fully_qualified_name
133
+ end
134
+ end
135
+
136
+ # @param name [String]
137
+ # @param klass [Class]
138
+ # @return [Rucoa::Nodes::Base, nil]
139
+ def find_by_name(klass:, name:)
140
+ location_root_or_descendant_nodes.reverse.find do |node|
141
+ node.is_a?(klass) &&
142
+ node.name == name
143
+ end
144
+ end
145
+
146
+ # @return [Array<Rucoa::Nodes::Base>]
147
+ def location_root_or_descendant_nodes
148
+ @location_root_or_descendant_nodes ||= [
149
+ location_source.root_node,
150
+ *location_source.root_node.descendants
151
+ ]
152
+ end
153
+ end
154
+ end
155
+ end
@@ -7,10 +7,7 @@ module Rucoa
7
7
 
8
8
  def call
9
9
  source_store.update(source)
10
- definition_store.update_definitions_defined_in(
11
- source.path,
12
- definitions: source.definitions
13
- )
10
+ definition_store.update_from(source)
14
11
  publish_diagnostics_on(uri)
15
12
  end
16
13
 
@@ -23,14 +23,13 @@ module Rucoa
23
23
  def responsible?
24
24
  configuration.enables_hover? &&
25
25
  !source.nil? &&
26
- !node.nil?
26
+ !node.nil? &&
27
+ !method_definitions.empty?
27
28
  end
28
29
 
29
30
  # @return [String, nil]
30
31
  def contents
31
32
  method_definition = method_definitions.first
32
- return unless method_definition
33
-
34
33
  [
35
34
  method_definition.signatures.join("\n"),
36
35
  method_definition.description
@@ -66,7 +65,7 @@ module Rucoa
66
65
 
67
66
  # @return [Array<Rucoa::Definitions::MethodDefinition>]
68
67
  def method_definitions
69
- NodeInspector.new(
68
+ @method_definitions ||= NodeInspector.new(
70
69
  definition_store: definition_store,
71
70
  node: node
72
71
  ).method_definitions
@@ -9,6 +9,7 @@ module Rucoa
9
9
  autoload :ShutdownHandler, 'rucoa/handlers/shutdown_handler'
10
10
  autoload :TextDocumentCodeActionHandler, 'rucoa/handlers/text_document_code_action_handler'
11
11
  autoload :TextDocumentCompletionHandler, 'rucoa/handlers/text_document_completion_handler'
12
+ autoload :TextDocumentDefinitionHandler, 'rucoa/handlers/text_document_definition_handler'
12
13
  autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
13
14
  autoload :TextDocumentDidCloseHandler, 'rucoa/handlers/text_document_did_close_handler'
14
15
  autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Rucoa
4
4
  module NodeConcerns
5
- module NameFullQualifiable
5
+ module NameFullyQualifiable
6
6
  # @return [String]
7
- def full_qualified_name
7
+ def fully_qualified_name
8
8
  [
9
9
  name,
10
10
  *each_ancestor(:class, :constant, :module).map(&:name)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rucoa
4
4
  module NodeConcerns
5
- autoload :NameFullQualifiable, 'rucoa/node_concerns/name_full_qualifiable'
5
+ autoload :NameFullyQualifiable, 'rucoa/node_concerns/name_fully_qualifiable'
6
6
  end
7
7
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
-
5
3
  module Rucoa
6
4
  class NodeInspector
7
5
  # @param definition_store [Rucoa::DefinitionStore]
@@ -11,10 +9,24 @@ module Rucoa
11
9
  @node = node
12
10
  end
13
11
 
14
- # @return [Array<String>]
12
+ # @return [Array<Rucoa::Definitions::Base>]
13
+ def definitions
14
+ case @node
15
+ when Nodes::ConstNode
16
+ [constant_definition]
17
+ when Nodes::SendNode
18
+ method_definitions
19
+ else
20
+ []
21
+ end
22
+ end
23
+
24
+ # @return [Array<Rucoa::Definitions::MethodDefinition>]
15
25
  def method_definitions
16
- method_full_qualified_names.flat_map do |full_qualified_name|
17
- @definition_store.select_by_full_qualified_name(full_qualified_name)
26
+ method_receiver_types.flat_map do |type|
27
+ @definition_store.instance_method_definitions_of(type)
28
+ end.select do |method_definition|
29
+ method_definition.method_name == @node.name
18
30
  end
19
31
  end
20
32
 
@@ -36,7 +48,7 @@ module Rucoa
36
48
  def return_types
37
49
  case @node.type
38
50
  when :const
39
- [@node.name]
51
+ ["singleton<#{@node.name}>"]
40
52
  when :lvar
41
53
  return_types_for_lvar
42
54
  when :send
@@ -74,50 +86,60 @@ module Rucoa
74
86
 
75
87
  private
76
88
 
77
- # @return [Array<String>]
78
- def method_full_qualified_names
79
- method_receiver_types.map do |type|
89
+ # @return [Rucoa::Definitions::ConstantDefinition, nil]
90
+ def constant_definition
91
+ return unless @node.is_a?(Nodes::ConstNode)
92
+
93
+ module_nesting = @node.module_nesting
94
+ candidate_fully_qualified_names = module_nesting.flat_map do |module_nesting_fully_qualified_name|
80
95
  [
81
- type,
82
- @node.name
83
- ].join(method_kind_symbol)
96
+ module_nesting_fully_qualified_name
97
+ # TODO: *ancestors_of(module_nesting_fully_qualified_name)
98
+ ].map do |fully_qualified_name|
99
+ [
100
+ fully_qualified_name,
101
+ @node.chained_name
102
+ ].join('::')
103
+ end
104
+ end + [@node.chained_name]
105
+ candidate_fully_qualified_names.find do |candidate_fully_qualified_name|
106
+ definition = @definition_store.find_definition_by_fully_qualified_name(candidate_fully_qualified_name)
107
+ break definition if definition
84
108
  end
85
109
  end
86
110
 
87
- # @return [String, nil]
88
- def method_kind_symbol
89
- return unless @node.is_a?(Nodes::SendNode)
90
-
91
- case @node.receiver
92
- when Nodes::ConstNode
93
- '.'
94
- else
95
- '#'
96
- end
111
+ # @return [Boolean]
112
+ def singleton_method_call?
113
+ @node.is_a?(Nodes::ConstNode)
97
114
  end
98
115
 
99
116
  # @return [String, nil]
100
- def nearest_def_full_qualified_name
101
- @node.each_ancestor(:def).first&.full_qualified_name
117
+ def nearest_def_fully_qualified_name
118
+ @node.each_ancestor(:def).first&.fully_qualified_name
102
119
  end
103
120
 
104
121
  # @return [Array<String>]
105
122
  def return_types_for_lvar
106
- full_qualified_name = nearest_def_full_qualified_name
107
- return [] unless full_qualified_name
123
+ fully_qualified_name = nearest_def_fully_qualified_name
124
+ return [] unless fully_qualified_name
108
125
 
109
- @definition_store.select_by_full_qualified_name(full_qualified_name).flat_map do |definition|
110
- definition.parameters.select do |parameter|
111
- parameter.name == @node.name
112
- end.flat_map(&:types)
113
- end
126
+ definition = @definition_store.find_definition_by_fully_qualified_name(fully_qualified_name)
127
+ return [] unless definition
128
+
129
+ definition.parameters.select do |parameter|
130
+ parameter.name == @node.name
131
+ end.flat_map(&:types)
114
132
  end
115
133
 
116
134
  # @return [Array<String>]
117
135
  def return_types_for_send
118
- method_full_qualified_names.flat_map do |full_qualified_name|
119
- @definition_store.select_by_full_qualified_name(full_qualified_name).flat_map(&:return_types)
120
- end.uniq
136
+ method_receiver_types.flat_map do |type|
137
+ @definition_store.find_method_definition_by(
138
+ method_name: @node.name,
139
+ namespace: type,
140
+ singleton: singleton_method_call?
141
+ )&.return_types
142
+ end.compact
121
143
  end
122
144
  end
123
145
  end
@@ -89,7 +89,7 @@ module Rucoa
89
89
  # @return [String]
90
90
  # @example returns namespace
91
91
  # node = Rucoa::Source.new(
92
- # content: <<~RUBY
92
+ # content: <<~RUBY,
93
93
  # module Foo
94
94
  # class Bar
95
95
  # def baz
@@ -97,6 +97,7 @@ module Rucoa
97
97
  # end
98
98
  # end
99
99
  # RUBY
100
+ # uri: 'file:///path/to/foo/bar.rb'
100
101
  # ).node_at(
101
102
  # Rucoa::Position.new(
102
103
  # column: 4,
@@ -105,14 +106,38 @@ module Rucoa
105
106
  # )
106
107
  # expect(node.namespace).to eq('Foo::Bar')
107
108
  # @example returns "Object" when the node is not in a namespace
108
- # node = Rucoa::Parser.call(
109
- # <<~RUBY
109
+ # node = Rucoa::Source.new(
110
+ # content: <<~RUBY,
110
111
  # foo
111
112
  # RUBY
112
- # )
113
+ # uri: 'file:///path/to/example.rb'
114
+ # ).root_node
113
115
  # expect(node.namespace).to eq('Object')
114
116
  def namespace
115
- each_ancestor(:module, :class).first&.full_qualified_name || 'Object'
117
+ module_nesting.first || 'Object'
118
+ end
119
+
120
+ # @return [Array<String>]
121
+ # @example return ["Bar::Foo", "Foo"] for class Foo::Bar::Baz
122
+ # node = Rucoa::Source.new(
123
+ # content: <<~RUBY,
124
+ # module Foo
125
+ # module Bar
126
+ # module Baz
127
+ # end
128
+ # end
129
+ # end
130
+ # RUBY
131
+ # uri: 'file:///path/to/foo/bar/baz.rb'
132
+ # ).node_at(
133
+ # Rucoa::Position.new(
134
+ # column: 4,
135
+ # line: 3
136
+ # )
137
+ # )
138
+ # expect(node.module_nesting).to eq(['Foo::Bar', 'Foo'])
139
+ def module_nesting
140
+ each_ancestor(:class, :module).map(&:fully_qualified_name)
116
141
  end
117
142
 
118
143
  protected
@@ -121,8 +146,8 @@ module Rucoa
121
146
  # @param types [Array<Symbol>]
122
147
  # @return [void]
123
148
  def visit_descendants(types, &block)
124
- each_child_node(*types) do |child|
125
- yield(child)
149
+ each_child_node do |child|
150
+ yield(child) if types.empty? || types.include?(child.type)
126
151
  child.visit_descendants(types, &block)
127
152
  end
128
153
  end
@@ -3,7 +3,7 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  class CasgnNode < Base
6
- include NodeConcerns::NameFullQualifiable
6
+ include NodeConcerns::NameFullyQualifiable
7
7
 
8
8
  # @return [String]
9
9
  def name
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Nodes
5
+ class CbaseNode < Base
6
+ end
7
+ end
8
+ end
@@ -2,7 +2,68 @@
2
2
 
3
3
  module Rucoa
4
4
  module Nodes
5
- class ClassNode < ModuleNode
5
+ class ClassNode < Base
6
+ include NodeConcerns::NameFullyQualifiable
7
+
8
+ # @return [String]
9
+ def name
10
+ const_node.name
11
+ end
12
+
13
+ # @return [String, nil]
14
+ # @example returns nil for class for `class Foo`
15
+ # node = Rucoa::Source.new(
16
+ # content: <<~RUBY,
17
+ # class Foo
18
+ # end
19
+ # RUBY
20
+ # uri: 'file:///path/to/foo.rb'
21
+ # ).root_node
22
+ # expect(node.super_class_chained_name).to be_nil
23
+ # @example returns "Bar" for class for `class Foo < Bar`
24
+ # node = Rucoa::Source.new(
25
+ # content: <<~RUBY,
26
+ # class Foo < Bar
27
+ # end
28
+ # RUBY
29
+ # uri: 'file:///path/to/foo.rb'
30
+ # ).root_node
31
+ # expect(node.super_class_chained_name).to eq('Bar')
32
+ # @example returns "Bar::Baz" for class for `class Foo < Bar::Baz`
33
+ # node = Rucoa::Source.new(
34
+ # content: <<~RUBY,
35
+ # class Foo < Bar::Baz
36
+ # end
37
+ # RUBY
38
+ # uri: 'file:///path/to/foo.rb'
39
+ # ).root_node
40
+ # expect(node.super_class_chained_name).to eq('Bar::Baz')
41
+ # @example returns "::Bar" for class for `class Foo < ::Bar`
42
+ # node = Rucoa::Source.new(
43
+ # content: <<~RUBY,
44
+ # class Foo < ::Bar
45
+ # end
46
+ # RUBY
47
+ # uri: 'file:///path/to/foo.rb'
48
+ # ).root_node
49
+ # expect(node.super_class_chained_name).to eq('::Bar')
50
+ def super_class_chained_name
51
+ return unless super_class_node.is_a?(Nodes::ConstNode)
52
+
53
+ super_class_node.chained_name
54
+ end
55
+
56
+ private
57
+
58
+ # @return [Rucoa::Nodes::ConstNode]
59
+ def const_node
60
+ children[0]
61
+ end
62
+
63
+ # @return [Rucoa::Nodes::Base, nil]
64
+ def super_class_node
65
+ children[1]
66
+ end
6
67
  end
7
68
  end
8
69
  end
@@ -4,9 +4,81 @@ module Rucoa
4
4
  module Nodes
5
5
  class ConstNode < Base
6
6
  # @return [String]
7
+ # @example returns "A" for "A"
8
+ # node = Rucoa::Parser.call(
9
+ # path: '/path/to/example.rb',
10
+ # text: 'A'
11
+ # ).root_node
12
+ # expect(node.name).to eq('A')
13
+ # @example returns "B" for "A::B"
14
+ # node = Rucoa::Parser.call(
15
+ # path: '/path/to/example.rb',
16
+ # text: 'A::B'
17
+ # ).root_node
18
+ # expect(node.name).to eq('B')
7
19
  def name
8
20
  children[1].to_s
9
21
  end
22
+
23
+ # @return [String]
24
+ # @example returns "A" for "A"
25
+ # node = Rucoa::Parser.call(
26
+ # path: '/path/to/example.rb',
27
+ # text: 'A'
28
+ # ).root_node
29
+ # expect(node.chained_name).to eq('A')
30
+ # @example returns "A::B" for "A::B"
31
+ # node = Rucoa::Parser.call(
32
+ # path: '/path/to/example.rb',
33
+ # text: 'A::B'
34
+ # ).root_node
35
+ # expect(node.chained_name).to eq('A::B')
36
+ def chained_name
37
+ case receiver
38
+ when Nodes::CbaseNode
39
+ [
40
+ '',
41
+ name
42
+ ].join('::')
43
+ when Nodes::ConstNode
44
+ [
45
+ receiver.chained_name,
46
+ name
47
+ ].join('::')
48
+ else
49
+ name
50
+ end
51
+ end
52
+
53
+ # @return [Array<String>]
54
+ # @example return ["Bar::Foo", "Foo"] for class Foo::Bar::Baz
55
+ # node = Rucoa::Source.new(
56
+ # content: <<~RUBY,
57
+ # module Foo
58
+ # module Bar
59
+ # module Baz
60
+ # end
61
+ # end
62
+ # end
63
+ # RUBY
64
+ # uri: 'file:///path/to/foo/bar/baz.rb'
65
+ # ).node_at(
66
+ # Rucoa::Position.new(
67
+ # column: 4,
68
+ # line: 3
69
+ # )
70
+ # )
71
+ # expect(node.module_nesting).to eq(['Foo::Bar', 'Foo'])
72
+ def module_nesting
73
+ each_ancestor(:class, :module).map(&:fully_qualified_name)
74
+ end
75
+
76
+ private
77
+
78
+ # @return [Rucoa::Nodes::Base, nil]
79
+ def receiver
80
+ children[0]
81
+ end
10
82
  end
11
83
  end
12
84
  end
@@ -6,7 +6,7 @@ module Rucoa
6
6
  # @return [String]
7
7
  # @example returns method name
8
8
  # node = Rucoa::Source.new(
9
- # content: <<~RUBY
9
+ # content: <<~RUBY,
10
10
  # module Foo
11
11
  # class Bar
12
12
  # def baz
@@ -14,6 +14,7 @@ module Rucoa
14
14
  # end
15
15
  # end
16
16
  # RUBY
17
+ # uri: 'file:///path/to/foo/bar.rb'
17
18
  # ).node_at(
18
19
  # Rucoa::Position.new(
19
20
  # column: 4,
@@ -28,7 +29,7 @@ module Rucoa
28
29
  # @return [String]
29
30
  # @example returns full qualified name
30
31
  # node = Rucoa::Source.new(
31
- # content: <<~RUBY
32
+ # content: <<~RUBY,
32
33
  # module Foo
33
34
  # class Bar
34
35
  # def baz
@@ -36,14 +37,15 @@ module Rucoa
36
37
  # end
37
38
  # end
38
39
  # RUBY
40
+ # uri: 'file:///path/to/foo/bar.rb'
39
41
  # ).node_at(
40
42
  # Rucoa::Position.new(
41
43
  # column: 4,
42
44
  # line: 3
43
45
  # )
44
46
  # )
45
- # expect(node.full_qualified_name).to eq('Foo::Bar#baz')
46
- def full_qualified_name
47
+ # expect(node.fully_qualified_name).to eq('Foo::Bar#baz')
48
+ def fully_qualified_name
47
49
  [
48
50
  namespace,
49
51
  method_marker,
@@ -51,6 +53,11 @@ module Rucoa
51
53
  ].join
52
54
  end
53
55
 
56
+ # @return [Boolean]
57
+ def singleton?
58
+ each_ancestor(:sclass).any?
59
+ end
60
+
54
61
  private
55
62
 
56
63
  # @return [String]
@@ -61,11 +68,6 @@ module Rucoa
61
68
  '#'
62
69
  end
63
70
  end
64
-
65
- # @return [Boolean]
66
- def singleton?
67
- each_ancestor(:sclass).any?
68
- end
69
71
  end
70
72
  end
71
73
  end
@@ -3,10 +3,31 @@
3
3
  module Rucoa
4
4
  module Nodes
5
5
  class DefsNode < Base
6
+ # @return [String]
7
+ def fully_qualified_name
8
+ [
9
+ namespace,
10
+ method_marker,
11
+ name
12
+ ].join
13
+ end
14
+
6
15
  # @return [String]
7
16
  def name
8
17
  children[1].to_s
9
18
  end
19
+
20
+ # @return [Boolean]
21
+ def singleton?
22
+ true
23
+ end
24
+
25
+ private
26
+
27
+ # @return [String]
28
+ def method_marker
29
+ '.'
30
+ end
10
31
  end
11
32
  end
12
33
  end