rucoa 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +11 -2
- data/README.md +36 -5
- data/data/definitions_ruby_3_1 +0 -0
- data/images/diagnostics.gif +0 -0
- data/images/document-formatting.gif +0 -0
- data/images/document-symbol.gif +0 -0
- data/images/selection-ranges.gif +0 -0
- data/lib/rucoa/configuration.rb +58 -32
- data/lib/rucoa/definition_archiver.rb +29 -0
- data/lib/rucoa/definition_builders/rbs_constant_definition_builder.rb +44 -0
- data/lib/rucoa/definition_builders/rbs_method_definition_builder.rb +106 -0
- data/lib/rucoa/definition_builders/yard_method_definition_builder.rb +191 -0
- data/lib/rucoa/definition_builders.rb +9 -0
- data/lib/rucoa/definition_store.rb +63 -0
- data/lib/rucoa/definitions/base.rb +12 -0
- data/lib/rucoa/definitions/constant_definition.rb +51 -0
- data/lib/rucoa/definitions/method_definition.rb +126 -0
- data/lib/rucoa/definitions/method_parameter_definition.rb +30 -0
- data/lib/rucoa/definitions.rb +9 -0
- data/lib/rucoa/handlers/base.rb +8 -0
- data/lib/rucoa/handlers/exit_handler.rb +11 -0
- data/lib/rucoa/handlers/initialize_handler.rb +6 -0
- data/lib/rucoa/handlers/initialized_handler.rb +10 -0
- data/lib/rucoa/handlers/shutdown_handler.rb +12 -0
- data/lib/rucoa/handlers/text_document_did_change_handler.rb +1 -20
- data/lib/rucoa/handlers/text_document_did_open_handler.rb +11 -4
- data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +1 -1
- data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +1 -1
- data/lib/rucoa/handlers/text_document_signature_help_handler.rb +68 -0
- data/lib/rucoa/handlers.rb +3 -0
- data/lib/rucoa/node_inspector.rb +109 -0
- data/lib/rucoa/nodes/base.rb +30 -0
- data/lib/rucoa/nodes/def_node.rb +59 -0
- data/lib/rucoa/nodes/lvar_node.rb +25 -0
- data/lib/rucoa/nodes/send_node.rb +43 -0
- data/lib/rucoa/nodes.rb +1 -0
- data/lib/rucoa/parser_builder.rb +1 -0
- data/lib/rucoa/range.rb +64 -14
- data/lib/rucoa/rbs_document_loader.rb +43 -0
- data/lib/rucoa/rubocop_autocorrector.rb +1 -1
- data/lib/rucoa/rubocop_investigator.rb +1 -1
- data/lib/rucoa/server.rb +19 -1
- data/lib/rucoa/source.rb +54 -4
- data/lib/rucoa/source_store.rb +6 -10
- data/lib/rucoa/types/method_type.rb +23 -0
- data/lib/rucoa/types.rb +7 -0
- data/lib/rucoa/version.rb +1 -1
- data/lib/rucoa/yard_glob_document_loader.rb +47 -0
- data/lib/rucoa/yard_string_document_loader.rb +70 -0
- data/lib/rucoa.rb +9 -0
- data/rucoa.gemspec +1 -0
- metadata +42 -2
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
class DefinitionStore
|
5
|
+
# @return [Array<Rucoa::Definition::Base>]
|
6
|
+
attr_accessor :definitions
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@definitions = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param source_path [String]
|
13
|
+
# @return [Array<Rucoa::Definition::Base>]
|
14
|
+
def update_definitions_defined_in(source_path, definitions:)
|
15
|
+
delete_definitions_defined_in(source_path)
|
16
|
+
@definitions += definitions
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param full_qualified_name [String]
|
20
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
21
|
+
def select_by_full_qualified_name(full_qualified_name)
|
22
|
+
@definitions.select do |definition|
|
23
|
+
definition.full_qualified_name == full_qualified_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param namespace [String]
|
28
|
+
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
29
|
+
def method_definitions_of(namespace)
|
30
|
+
method_definitions.select do |method_definition|
|
31
|
+
method_definition.namespace == namespace
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param namespace [String]
|
36
|
+
# @return [Array<Rucoa::Definitions::ConstantDefinition>] e.g. File::Separator, File::SEPARATOR, etc.
|
37
|
+
def constant_definitions_under(namespace)
|
38
|
+
constant_definitions.select do |constant_definition|
|
39
|
+
constant_definition.namespace == namespace
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# @return [Array<Rucoa::Definition::ConstantDefinition>]
|
46
|
+
def constant_definitions
|
47
|
+
@definitions.grep(Definitions::ConstantDefinition)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
51
|
+
def method_definitions
|
52
|
+
@definitions.grep(Definitions::MethodDefinition)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param source_path [String]
|
56
|
+
# @return [Array<Rucoa::Definition::Base>]
|
57
|
+
def delete_definitions_defined_in(source_path)
|
58
|
+
@definitions.delete_if do |definition|
|
59
|
+
definition.source_path == source_path
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Definitions
|
5
|
+
# Represents class definition, module definition, or constant assignment.
|
6
|
+
class ConstantDefinition < Base
|
7
|
+
# @return [String]
|
8
|
+
attr_reader :full_qualified_name
|
9
|
+
|
10
|
+
# @return [String]
|
11
|
+
attr_reader :source_path
|
12
|
+
|
13
|
+
# @param full_qualified_name [String]
|
14
|
+
# @param source_path [String]
|
15
|
+
def initialize(full_qualified_name:, source_path:)
|
16
|
+
super()
|
17
|
+
@full_qualified_name = full_qualified_name
|
18
|
+
@source_path = source_path
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String]
|
22
|
+
# @example returns non-full-qualified name
|
23
|
+
# definition = Rucoa::Definitions::ConstantDefinition.new(
|
24
|
+
# full_qualified_name: 'Foo::Bar::Baz',
|
25
|
+
# source_path: '/path/to/foo/bar/baz.rb'
|
26
|
+
# )
|
27
|
+
# expect(definition.name).to eq('Baz')
|
28
|
+
def name
|
29
|
+
names.last
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String]
|
33
|
+
# @example returns namespace
|
34
|
+
# definition = Rucoa::Definitions::ConstantDefinition.new(
|
35
|
+
# full_qualified_name: 'Foo::Bar::Baz',
|
36
|
+
# source_path: '/path/to/foo/bar/baz.rb'
|
37
|
+
# )
|
38
|
+
# expect(definition.namespace).to eq('Foo::Bar')
|
39
|
+
def namespace
|
40
|
+
names[..-2].join('::')
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# @return [Array<String>]
|
46
|
+
def names
|
47
|
+
@names ||= full_qualified_name.split('::')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Definitions
|
5
|
+
class MethodDefinition < Base
|
6
|
+
# @return [String, nil]
|
7
|
+
attr_reader :description
|
8
|
+
|
9
|
+
# @return [String]
|
10
|
+
attr_reader :method_name
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :namespace
|
14
|
+
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :source_path
|
17
|
+
|
18
|
+
# @param description [String, nil]
|
19
|
+
# @param kind [Symbol]
|
20
|
+
# @param method_name [String]
|
21
|
+
# @param namespace [String]
|
22
|
+
# @param source_path [String]
|
23
|
+
# @param types [Array<Rucoa::Types::MethodType>]
|
24
|
+
def initialize(
|
25
|
+
description:,
|
26
|
+
kind:,
|
27
|
+
method_name:,
|
28
|
+
namespace:,
|
29
|
+
source_path:,
|
30
|
+
types:
|
31
|
+
)
|
32
|
+
super()
|
33
|
+
@description = description
|
34
|
+
@kind = kind
|
35
|
+
@method_name = method_name
|
36
|
+
@namespace = namespace
|
37
|
+
@source_path = source_path
|
38
|
+
@types = types
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String]
|
42
|
+
# @example returns qualified name of method
|
43
|
+
# method_definition = Rucoa::Definitions::MethodDefinition.new(
|
44
|
+
# description: nil,
|
45
|
+
# kind: :instance,
|
46
|
+
# method_name: 'foo',
|
47
|
+
# namespace: 'Foo::Bar',
|
48
|
+
# source_path: '/path/to/foo/bar.rb',
|
49
|
+
# types: []
|
50
|
+
# )
|
51
|
+
# expect(method_definition.full_qualified_name).to eq('Foo::Bar#foo')
|
52
|
+
def full_qualified_name
|
53
|
+
[
|
54
|
+
@namespace,
|
55
|
+
method_kind_symbol,
|
56
|
+
@method_name
|
57
|
+
].join
|
58
|
+
end
|
59
|
+
|
60
|
+
# @todo
|
61
|
+
# @return [Array<Rucoa::Definitions::MethodParameter>]
|
62
|
+
def parameters
|
63
|
+
[]
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Array<String>]
|
67
|
+
# @example returns return types
|
68
|
+
# method_definition = Rucoa::Definitions::MethodDefinition.new(
|
69
|
+
# description: nil,
|
70
|
+
# kind: :instance,
|
71
|
+
# method_name: 'foo',
|
72
|
+
# namespace: 'Foo::Bar',
|
73
|
+
# source_path: '/path/to/foo/bar.rb',
|
74
|
+
# types: [
|
75
|
+
# Rucoa::Types::MethodType.new(
|
76
|
+
# parameters_string: '',
|
77
|
+
# return_type: 'String'
|
78
|
+
# )
|
79
|
+
# ]
|
80
|
+
# )
|
81
|
+
# expect(method_definition.return_types).to eq(%w[String])
|
82
|
+
def return_types
|
83
|
+
@types.map(&:return_type)
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [Array<String>]
|
87
|
+
# @example returns signature
|
88
|
+
# method_definition = Rucoa::Definitions::MethodDefinition.new(
|
89
|
+
# description: nil,
|
90
|
+
# kind: :instance,
|
91
|
+
# method_name: 'foo',
|
92
|
+
# namespace: 'Foo::Bar',
|
93
|
+
# source_path: '/path/to/foo/bar.rb',
|
94
|
+
# types: [
|
95
|
+
# Rucoa::Types::MethodType.new(
|
96
|
+
# parameters_string: '?::int base',
|
97
|
+
# return_type: 'String'
|
98
|
+
# )
|
99
|
+
# ]
|
100
|
+
# )
|
101
|
+
# expect(method_definition.signatures).to eq(['Foo::Bar#foo(?::int base) -> String'])
|
102
|
+
def signatures
|
103
|
+
@types.map do |type|
|
104
|
+
format(
|
105
|
+
'%<full_qualified_name>s(%<parameters>s) -> %<return_types>s',
|
106
|
+
full_qualified_name: full_qualified_name,
|
107
|
+
parameters: type.parameters_string,
|
108
|
+
return_types: type.return_type
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
# @return [String]
|
116
|
+
def method_kind_symbol
|
117
|
+
case @kind
|
118
|
+
when :instance
|
119
|
+
'#'
|
120
|
+
else
|
121
|
+
'.'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Definitions
|
5
|
+
# Represents method parameter definition.
|
6
|
+
class MethodParameterDefinition < Base
|
7
|
+
# @return [String]
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
# @return [Array<String>]
|
11
|
+
attr_reader :types
|
12
|
+
|
13
|
+
# @param name [String]
|
14
|
+
# @param types [Array<String>]
|
15
|
+
def initialize(name:, types:)
|
16
|
+
super()
|
17
|
+
@name = name
|
18
|
+
@types = types
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Hash{Symbol => Object}]
|
22
|
+
def to_hash
|
23
|
+
{
|
24
|
+
name: name,
|
25
|
+
types: types
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/rucoa/handlers/base.rb
CHANGED
@@ -32,6 +32,9 @@ module Rucoa
|
|
32
32
|
# @return [Hash]
|
33
33
|
attr_reader :request
|
34
34
|
|
35
|
+
# @return [Rucoa::Server]
|
36
|
+
attr_reader :server
|
37
|
+
|
35
38
|
# @param message [Hash]
|
36
39
|
# @return [void]
|
37
40
|
def respond(message)
|
@@ -46,6 +49,11 @@ module Rucoa
|
|
46
49
|
@server.configuration
|
47
50
|
end
|
48
51
|
|
52
|
+
# @return [Rucoa::DefinitionStore]
|
53
|
+
def definition_store
|
54
|
+
@server.definition_store
|
55
|
+
end
|
56
|
+
|
49
57
|
# @return [Rucoa::SourceStore]
|
50
58
|
def source_store
|
51
59
|
@server.source_store
|
@@ -11,6 +11,12 @@ module Rucoa
|
|
11
11
|
documentRangeFormattingProvider: true,
|
12
12
|
documentSymbolProvider: true,
|
13
13
|
selectionRangeProvider: true,
|
14
|
+
signatureHelpProvider: {
|
15
|
+
triggerCharacters: %w[
|
16
|
+
(
|
17
|
+
,
|
18
|
+
]
|
19
|
+
},
|
14
20
|
textDocumentSync: {
|
15
21
|
change: 1, # Full
|
16
22
|
openClose: true
|
@@ -7,6 +7,16 @@ module Rucoa
|
|
7
7
|
|
8
8
|
def call
|
9
9
|
request_workspace_configuration
|
10
|
+
load_definitions
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# @return [void]
|
16
|
+
def load_definitions
|
17
|
+
YardGlobDocumentLoader.call(
|
18
|
+
globs: ::YARD::Parser::SourceParser::DEFAULT_PATH_GLOB
|
19
|
+
)
|
10
20
|
end
|
11
21
|
end
|
12
22
|
end
|
@@ -2,30 +2,11 @@
|
|
2
2
|
|
3
3
|
module Rucoa
|
4
4
|
module Handlers
|
5
|
-
class TextDocumentDidChangeHandler <
|
6
|
-
include HandlerConcerns::DiagnosticsPublishable
|
7
|
-
|
8
|
-
def call
|
9
|
-
update_source
|
10
|
-
publish_diagnostics_on(uri)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
# @return [void]
|
16
|
-
def update_source
|
17
|
-
source_store.set(uri, text)
|
18
|
-
end
|
19
|
-
|
5
|
+
class TextDocumentDidChangeHandler < TextDocumentDidOpenHandler
|
20
6
|
# @return [String]
|
21
7
|
def text
|
22
8
|
request.dig('params', 'contentChanges')[0]['text']
|
23
9
|
end
|
24
|
-
|
25
|
-
# @return [String]
|
26
|
-
def uri
|
27
|
-
@uri ||= request.dig('params', 'textDocument', 'uri')
|
28
|
-
end
|
29
10
|
end
|
30
11
|
end
|
31
12
|
end
|
@@ -6,15 +6,22 @@ module Rucoa
|
|
6
6
|
include HandlerConcerns::DiagnosticsPublishable
|
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
14
|
publish_diagnostics_on(uri)
|
11
15
|
end
|
12
16
|
|
13
17
|
private
|
14
18
|
|
15
|
-
# @return [
|
16
|
-
def
|
17
|
-
|
19
|
+
# @return [Rucoa::Source]
|
20
|
+
def source
|
21
|
+
@source ||= Source.new(
|
22
|
+
content: text,
|
23
|
+
uri: uri
|
24
|
+
)
|
18
25
|
end
|
19
26
|
|
20
27
|
# @return [String]
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Handlers
|
5
|
+
class TextDocumentSignatureHelpHandler < Base
|
6
|
+
def call
|
7
|
+
respond(signature_help)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# @return [Hash]
|
13
|
+
def signature_help
|
14
|
+
return unless respondable?
|
15
|
+
|
16
|
+
{
|
17
|
+
signatures: signature_informations
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Boolean]
|
22
|
+
def respondable?
|
23
|
+
configuration.enables_signature_help? &&
|
24
|
+
node.is_a?(Nodes::SendNode)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Hash>]
|
28
|
+
def signature_informations
|
29
|
+
method_definitions.map do |method_definition|
|
30
|
+
{
|
31
|
+
documentation: method_definition.description,
|
32
|
+
label: method_definition.signatures.join("\n")
|
33
|
+
}
|
34
|
+
end
|
35
|
+
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
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/rucoa/handlers.rb
CHANGED
@@ -3,8 +3,10 @@
|
|
3
3
|
module Rucoa
|
4
4
|
module Handlers
|
5
5
|
autoload :Base, 'rucoa/handlers/base'
|
6
|
+
autoload :ExitHandler, 'rucoa/handlers/exit_handler'
|
6
7
|
autoload :InitializeHandler, 'rucoa/handlers/initialize_handler'
|
7
8
|
autoload :InitializedHandler, 'rucoa/handlers/initialized_handler'
|
9
|
+
autoload :ShutdownHandler, 'rucoa/handlers/shutdown_handler'
|
8
10
|
autoload :TextDocumentCodeActionHandler, 'rucoa/handlers/text_document_code_action_handler'
|
9
11
|
autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
|
10
12
|
autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
|
@@ -12,6 +14,7 @@ module Rucoa
|
|
12
14
|
autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
|
13
15
|
autoload :TextDocumentRangeFormattingHandler, 'rucoa/handlers/text_document_range_formatting_handler'
|
14
16
|
autoload :TextDocumentSelectionRangeHandler, 'rucoa/handlers/text_document_selection_range_handler'
|
17
|
+
autoload :TextDocumentSignatureHelpHandler, 'rucoa/handlers/text_document_signature_help_handler'
|
15
18
|
autoload :WorkspaceDidChangeConfigurationHandler, 'rucoa/handlers/workspace_did_change_configuration_handler'
|
16
19
|
end
|
17
20
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Rucoa
|
6
|
+
class NodeInspector
|
7
|
+
# @param definition_store [Rucoa::DefinitionStore]
|
8
|
+
# @param node [Rucoa::Node]
|
9
|
+
def initialize(definition_store:, node:)
|
10
|
+
@definition_store = definition_store
|
11
|
+
@node = node
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<String>, nil]
|
15
|
+
def method_definitions
|
16
|
+
method_full_qualified_name&.flat_map do |full_qualified_name|
|
17
|
+
@definition_store.select_by_full_qualified_name(full_qualified_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Array<String>, nil]
|
22
|
+
def method_receiver_types
|
23
|
+
return unless @node.is_a?(Nodes::SendNode)
|
24
|
+
|
25
|
+
if @node.receiver
|
26
|
+
self.class.new(
|
27
|
+
definition_store: @definition_store,
|
28
|
+
node: @node.receiver
|
29
|
+
).return_types
|
30
|
+
else
|
31
|
+
[@node.namespace]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Array<String>, nil]
|
36
|
+
def return_types
|
37
|
+
case @node.type
|
38
|
+
when :const
|
39
|
+
[@node.name]
|
40
|
+
when :lvar
|
41
|
+
return_types_for_lvar
|
42
|
+
when :send
|
43
|
+
return_types_for_send
|
44
|
+
when :array
|
45
|
+
%w[Array]
|
46
|
+
when :class, :module, :nil
|
47
|
+
%w[NilClass]
|
48
|
+
when :complex
|
49
|
+
%w[Complex]
|
50
|
+
when :def, :sym
|
51
|
+
%w[Symbol]
|
52
|
+
when :dstr, :str, :xstr
|
53
|
+
%w[String]
|
54
|
+
when :erange, :irange
|
55
|
+
%w[Range]
|
56
|
+
when false
|
57
|
+
%w[FalseClass]
|
58
|
+
when :float
|
59
|
+
%w[Float]
|
60
|
+
when :hash, :pair
|
61
|
+
%w[Hash]
|
62
|
+
when :int
|
63
|
+
%w[Integer]
|
64
|
+
when :rational
|
65
|
+
%w[Rational]
|
66
|
+
when :regexp, :regopt
|
67
|
+
%w[Regexp]
|
68
|
+
when true
|
69
|
+
%w[TrueClass]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# @return [Array<String>, nil]
|
76
|
+
def method_full_qualified_name
|
77
|
+
method_receiver_types&.map do |type|
|
78
|
+
[
|
79
|
+
type,
|
80
|
+
@node.name
|
81
|
+
].join('#')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [String, nil]
|
86
|
+
def nearest_def_full_qualified_name
|
87
|
+
@node.each_ancestor(:def).first&.full_qualified_name
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Array<String>]
|
91
|
+
def return_types_for_lvar
|
92
|
+
full_qualified_name = nearest_def_full_qualified_name
|
93
|
+
return [] unless full_qualified_name
|
94
|
+
|
95
|
+
@definition_store.select_by_full_qualified_name(full_qualified_name).flat_map do |definition|
|
96
|
+
definition.parameters.select do |parameter|
|
97
|
+
parameter.name == @node.name
|
98
|
+
end.flat_map(&:types)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Array<String>]
|
103
|
+
def return_types_for_send
|
104
|
+
method_full_qualified_name.flat_map do |full_qualified_name|
|
105
|
+
@definition_store.select_by_full_qualified_name(full_qualified_name).flat_map(&:return_types)
|
106
|
+
end.uniq
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/rucoa/nodes/base.rb
CHANGED
@@ -85,6 +85,36 @@ module Rucoa
|
|
85
85
|
Range.from_parser_range(location.expression).include?(position)
|
86
86
|
end
|
87
87
|
|
88
|
+
# @note namespace is a String representation of `Module.nesting`.
|
89
|
+
# @return [String]
|
90
|
+
# @example returns namespace
|
91
|
+
# node = Rucoa::Source.new(
|
92
|
+
# content: <<~RUBY
|
93
|
+
# module Foo
|
94
|
+
# class Bar
|
95
|
+
# def baz
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
# RUBY
|
100
|
+
# ).node_at(
|
101
|
+
# Rucoa::Position.new(
|
102
|
+
# column: 4,
|
103
|
+
# line: 3
|
104
|
+
# )
|
105
|
+
# )
|
106
|
+
# expect(node.namespace).to eq('Foo::Bar')
|
107
|
+
# @example returns "Object" when the node is not in a namespace
|
108
|
+
# node = Rucoa::Parser.call(
|
109
|
+
# <<~RUBY
|
110
|
+
# foo
|
111
|
+
# RUBY
|
112
|
+
# )
|
113
|
+
# expect(node.namespace).to eq('Object')
|
114
|
+
def namespace
|
115
|
+
each_ancestor(:module, :class).first&.full_qualified_name || 'Object'
|
116
|
+
end
|
117
|
+
|
88
118
|
protected
|
89
119
|
|
90
120
|
# Visit all descendants.
|