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
data/lib/rucoa/nodes/def_node.rb
CHANGED
@@ -4,9 +4,68 @@ module Rucoa
|
|
4
4
|
module Nodes
|
5
5
|
class DefNode < Base
|
6
6
|
# @return [String]
|
7
|
+
# @example returns method name
|
8
|
+
# node = Rucoa::Source.new(
|
9
|
+
# content: <<~RUBY
|
10
|
+
# module Foo
|
11
|
+
# class Bar
|
12
|
+
# def baz
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
# RUBY
|
17
|
+
# ).node_at(
|
18
|
+
# Rucoa::Position.new(
|
19
|
+
# column: 4,
|
20
|
+
# line: 3
|
21
|
+
# )
|
22
|
+
# )
|
23
|
+
# expect(node.name).to eq('baz')
|
7
24
|
def name
|
8
25
|
children[0].to_s
|
9
26
|
end
|
27
|
+
|
28
|
+
# @return [String]
|
29
|
+
# @example returns full qualified name
|
30
|
+
# node = Rucoa::Source.new(
|
31
|
+
# content: <<~RUBY
|
32
|
+
# module Foo
|
33
|
+
# class Bar
|
34
|
+
# def baz
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# RUBY
|
39
|
+
# ).node_at(
|
40
|
+
# Rucoa::Position.new(
|
41
|
+
# column: 4,
|
42
|
+
# line: 3
|
43
|
+
# )
|
44
|
+
# )
|
45
|
+
# expect(node.full_qualified_name).to eq('Foo::Bar#baz')
|
46
|
+
def full_qualified_name
|
47
|
+
[
|
48
|
+
namespace,
|
49
|
+
method_marker,
|
50
|
+
name
|
51
|
+
].join
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def method_marker
|
58
|
+
if singleton?
|
59
|
+
'.'
|
60
|
+
else
|
61
|
+
'#'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Boolean]
|
66
|
+
def singleton?
|
67
|
+
each_ancestor(:sclass).any?
|
68
|
+
end
|
10
69
|
end
|
11
70
|
end
|
12
71
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Nodes
|
5
|
+
class LvarNode < Base
|
6
|
+
# @return [String]
|
7
|
+
# @example returns local variable name
|
8
|
+
# node = Rucoa::Source.new(
|
9
|
+
# content: <<~RUBY
|
10
|
+
# foo = 1
|
11
|
+
# foo
|
12
|
+
# RUBY
|
13
|
+
# ).node_at(
|
14
|
+
# Rucoa::Position.new(
|
15
|
+
# column: 2,
|
16
|
+
# line: 2
|
17
|
+
# )
|
18
|
+
# )
|
19
|
+
# expect(node.name).to eq('foo')
|
20
|
+
def name
|
21
|
+
children[0].to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -4,14 +4,57 @@ module Rucoa
|
|
4
4
|
module Nodes
|
5
5
|
class SendNode < Base
|
6
6
|
# @return [Array<Rucoa::Nodes::Base>]
|
7
|
+
# @example returns arguments
|
8
|
+
# node = Rucoa::Parser.call(
|
9
|
+
# <<~RUBY
|
10
|
+
# foo(bar, baz)
|
11
|
+
# RUBY
|
12
|
+
# )
|
13
|
+
# expect(node.arguments.map(&:name)).to eq(
|
14
|
+
# %w[
|
15
|
+
# bar
|
16
|
+
# baz
|
17
|
+
# ]
|
18
|
+
# )
|
7
19
|
def arguments
|
8
20
|
children[2..]
|
9
21
|
end
|
10
22
|
|
11
23
|
# @return [String]
|
24
|
+
# @example returns method name
|
25
|
+
# node = Rucoa::Parser.call(
|
26
|
+
# <<~RUBY
|
27
|
+
# foo(bar, baz)
|
28
|
+
# RUBY
|
29
|
+
# )
|
30
|
+
# expect(node.name).to eq('foo')
|
12
31
|
def name
|
13
32
|
children[1].to_s
|
14
33
|
end
|
34
|
+
|
35
|
+
# @return [Rucoa::Nodes::Base, nil]
|
36
|
+
# @example returns nil for receiver-less method call
|
37
|
+
# node = Rucoa::Parser.call(
|
38
|
+
# <<~RUBY
|
39
|
+
# foo(bar, baz)
|
40
|
+
# RUBY
|
41
|
+
# )
|
42
|
+
# expect(node.receiver).to be_nil
|
43
|
+
# @example returns receiver
|
44
|
+
# node = Rucoa::Source.new(
|
45
|
+
# content: <<~RUBY
|
46
|
+
# foo.bar
|
47
|
+
# RUBY
|
48
|
+
# ).node_at(
|
49
|
+
# Rucoa::Position.new(
|
50
|
+
# column: 4,
|
51
|
+
# line: 1
|
52
|
+
# )
|
53
|
+
# )
|
54
|
+
# expect(node.receiver).to be_a(Rucoa::Nodes::SendNode)
|
55
|
+
def receiver
|
56
|
+
children[0]
|
57
|
+
end
|
15
58
|
end
|
16
59
|
end
|
17
60
|
end
|
data/lib/rucoa/nodes.rb
CHANGED
@@ -8,6 +8,7 @@ module Rucoa
|
|
8
8
|
autoload :ConstNode, 'rucoa/nodes/const_node'
|
9
9
|
autoload :DefNode, 'rucoa/nodes/def_node'
|
10
10
|
autoload :DefsNode, 'rucoa/nodes/defs_node'
|
11
|
+
autoload :LvarNode, 'rucoa/nodes/lvar_node'
|
11
12
|
autoload :ModuleNode, 'rucoa/nodes/module_node'
|
12
13
|
autoload :SclassNode, 'rucoa/nodes/sclass_node'
|
13
14
|
autoload :SendNode, 'rucoa/nodes/send_node'
|
data/lib/rucoa/parser_builder.rb
CHANGED
data/lib/rucoa/range.rb
CHANGED
@@ -30,28 +30,85 @@ module Rucoa
|
|
30
30
|
|
31
31
|
# @param beginning [Rucoa::Position]
|
32
32
|
# @param ending [Ruoca::Position]
|
33
|
-
# @param
|
34
|
-
def initialize(beginning, ending,
|
33
|
+
# @param including_ending [Boolean]
|
34
|
+
def initialize(beginning, ending, including_ending: true)
|
35
35
|
@beginning = beginning
|
36
36
|
@ending = ending
|
37
|
-
@
|
37
|
+
@including_ending = including_ending
|
38
38
|
end
|
39
39
|
|
40
40
|
# @param range [Rucoa::Range]
|
41
41
|
# @return [Boolean]
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
# @example returns true when the range is contained in self
|
43
|
+
# range = Rucoa::Range.new(
|
44
|
+
# Rucoa::Position.new(
|
45
|
+
# column: 0,
|
46
|
+
# line: 0
|
47
|
+
# ),
|
48
|
+
# Rucoa::Position.new(
|
49
|
+
# column: 0,
|
50
|
+
# line: 2
|
51
|
+
# )
|
52
|
+
# )
|
53
|
+
# expect(range).to contain(
|
54
|
+
# Rucoa::Range.new(
|
55
|
+
# Rucoa::Position.new(
|
56
|
+
# column: 0,
|
57
|
+
# line: 0
|
58
|
+
# ),
|
59
|
+
# Rucoa::Position.new(
|
60
|
+
# column: 0,
|
61
|
+
# line: 0
|
62
|
+
# )
|
63
|
+
# )
|
64
|
+
# )
|
65
|
+
def contain?(range)
|
66
|
+
include?(range.beginning) && include?(range.ending)
|
45
67
|
end
|
46
68
|
|
47
69
|
# @param position [Rucoa::Position]
|
48
70
|
# @return [Boolean]
|
71
|
+
# @example returns true when the position is included in self
|
72
|
+
# range = Rucoa::Range.new(
|
73
|
+
# Rucoa::Position.new(
|
74
|
+
# column: 0,
|
75
|
+
# line: 0
|
76
|
+
# ),
|
77
|
+
# Rucoa::Position.new(
|
78
|
+
# column: 0,
|
79
|
+
# line: 2
|
80
|
+
# )
|
81
|
+
# )
|
82
|
+
# expect(range).to include(
|
83
|
+
# Rucoa::Position.new(
|
84
|
+
# column: 0,
|
85
|
+
# line: 0
|
86
|
+
# )
|
87
|
+
# )
|
88
|
+
# expect(range).to include(
|
89
|
+
# Rucoa::Position.new(
|
90
|
+
# column: 0,
|
91
|
+
# line: 1
|
92
|
+
# )
|
93
|
+
# )
|
94
|
+
# expect(range).to include(
|
95
|
+
# Rucoa::Position.new(
|
96
|
+
# column: 0,
|
97
|
+
# line: 2
|
98
|
+
# )
|
99
|
+
# )
|
100
|
+
# expect(range).not_to include(
|
101
|
+
# Rucoa::Position.new(
|
102
|
+
# column: 0,
|
103
|
+
# line: 3
|
104
|
+
# )
|
105
|
+
# )
|
49
106
|
def include?(position)
|
50
107
|
return false if position.line > @ending.line
|
51
108
|
return false if position.line < @beginning.line
|
52
109
|
return false if position.column < @beginning.column
|
53
110
|
return false if position.column > @ending.column
|
54
|
-
return false if position.column == @ending.column &&
|
111
|
+
return false if position.column == @ending.column && !@including_ending
|
55
112
|
|
56
113
|
true
|
57
114
|
end
|
@@ -63,12 +120,5 @@ module Rucoa
|
|
63
120
|
start: @beginning.to_vscode_position
|
64
121
|
}
|
65
122
|
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# @return [Rucoa::Range]
|
70
|
-
def with_including_end
|
71
|
-
self.class.new(@beginning, @ending, exclude_end: false)
|
72
|
-
end
|
73
123
|
end
|
74
124
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
|
5
|
+
module Rucoa
|
6
|
+
class RbsDocumentLoader
|
7
|
+
class << self
|
8
|
+
def call
|
9
|
+
new.call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
14
|
+
def call
|
15
|
+
declarations.flat_map do |declaration|
|
16
|
+
case declaration
|
17
|
+
when ::RBS::AST::Declarations::Constant
|
18
|
+
[
|
19
|
+
DefinitionBuilders::RbsConstantDefinitionBuilder.call(declaration: declaration)
|
20
|
+
]
|
21
|
+
when ::RBS::AST::Declarations::Class, ::RBS::AST::Declarations::Module
|
22
|
+
declaration.members.grep(::RBS::AST::Members::MethodDefinition).map do |method_definition|
|
23
|
+
DefinitionBuilders::RbsMethodDefinitionBuilder.call(
|
24
|
+
declaration: declaration,
|
25
|
+
method_definition: method_definition
|
26
|
+
)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @return [Array<RBS::AST::Declarations::Base>]
|
37
|
+
def declarations
|
38
|
+
::RBS::Environment.from_loader(
|
39
|
+
::RBS::EnvironmentLoader.new
|
40
|
+
).resolve_type_names.declarations
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/rucoa/server.rb
CHANGED
@@ -4,8 +4,10 @@ module Rucoa
|
|
4
4
|
class Server
|
5
5
|
# @return [Hash{String => Class}]
|
6
6
|
METHOD_TO_HANDLER_MAP = {
|
7
|
+
'exit' => Handlers::ExitHandler,
|
7
8
|
'initialize' => Handlers::InitializeHandler,
|
8
9
|
'initialized' => Handlers::InitializedHandler,
|
10
|
+
'shutdown' => Handlers::ShutdownHandler,
|
9
11
|
'textDocument/codeAction' => Handlers::TextDocumentCodeActionHandler,
|
10
12
|
'textDocument/didChange' => Handlers::TextDocumentDidChangeHandler,
|
11
13
|
'textDocument/didOpen' => Handlers::TextDocumentDidOpenHandler,
|
@@ -13,13 +15,20 @@ module Rucoa
|
|
13
15
|
'textDocument/formatting' => Handlers::TextDocumentFormattingHandler,
|
14
16
|
'textDocument/rangeFormatting' => Handlers::TextDocumentRangeFormattingHandler,
|
15
17
|
'textDocument/selectionRange' => Handlers::TextDocumentSelectionRangeHandler,
|
18
|
+
'textDocument/signatureHelp' => Handlers::TextDocumentSignatureHelpHandler,
|
16
19
|
'workspace/didChangeConfiguration' => Handlers::WorkspaceDidChangeConfigurationHandler
|
17
20
|
}.freeze
|
18
21
|
private_constant :METHOD_TO_HANDLER_MAP
|
19
22
|
|
23
|
+
# @return [Boolean]
|
24
|
+
attr_accessor :shutting_down
|
25
|
+
|
20
26
|
# @return [Rucoa::Configuration]
|
21
27
|
attr_reader :configuration
|
22
28
|
|
29
|
+
# @return [Rucoa::DefinitionStore]
|
30
|
+
attr_reader :definition_store
|
31
|
+
|
23
32
|
# @return [Rucoa::SourceStore]
|
24
33
|
attr_reader :source_store
|
25
34
|
|
@@ -29,10 +38,14 @@ module Rucoa
|
|
29
38
|
@reader = MessageReader.new(input)
|
30
39
|
@writer = MessageWriter.new(output)
|
31
40
|
|
41
|
+
@client_response_handlers = {}
|
32
42
|
@configuration = Configuration.new
|
33
43
|
@server_request_id = 0
|
34
|
-
@
|
44
|
+
@shutting_down = false
|
35
45
|
@source_store = SourceStore.new
|
46
|
+
|
47
|
+
@definition_store = DefinitionStore.new
|
48
|
+
@definition_store.definitions += DefinitionArchiver.load
|
36
49
|
end
|
37
50
|
|
38
51
|
# @return [void]
|
@@ -42,6 +55,11 @@ module Rucoa
|
|
42
55
|
end
|
43
56
|
end
|
44
57
|
|
58
|
+
# @return [void]
|
59
|
+
def finish
|
60
|
+
exit(0)
|
61
|
+
end
|
62
|
+
|
45
63
|
# @yieldparam response [Hash]
|
46
64
|
# @param message [Hash]
|
47
65
|
# @return [void]
|
data/lib/rucoa/source.rb
CHANGED
@@ -6,13 +6,59 @@ module Rucoa
|
|
6
6
|
attr_reader :content
|
7
7
|
|
8
8
|
# @return [String]
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :uri
|
10
10
|
|
11
11
|
# @param content [String]
|
12
|
-
# @param
|
13
|
-
def initialize(content:,
|
12
|
+
# @param uri [String, nil]
|
13
|
+
def initialize(content:, uri: nil)
|
14
14
|
@content = content
|
15
|
-
@
|
15
|
+
@uri = uri
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Array<Rucoa::Definition::Base>]
|
19
|
+
# @example returns definitions from given source
|
20
|
+
# content = <<~RUBY
|
21
|
+
# class Foo
|
22
|
+
# def bar
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# RUBY
|
26
|
+
# source = Rucoa::Source.new(
|
27
|
+
# content: content,
|
28
|
+
# uri: 'file:///path/to/foo.rb'
|
29
|
+
# )
|
30
|
+
# expect(source.definitions).to match(
|
31
|
+
# [
|
32
|
+
# a_kind_of(Rucoa::Definitions::MethodDefinition)
|
33
|
+
# ]
|
34
|
+
# )
|
35
|
+
def definitions
|
36
|
+
@definitions ||= YardStringDocumentLoader.call(
|
37
|
+
content: @content,
|
38
|
+
path: path
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String, nil]
|
43
|
+
# @example returns path from given VSCode URI
|
44
|
+
# source = Rucoa::Source.new(
|
45
|
+
# content: '',
|
46
|
+
# uri: 'file:///path/to/foo.rb'
|
47
|
+
# )
|
48
|
+
# expect(source.path).to eq('/path/to/foo.rb')
|
49
|
+
# @example returns nil for untitled URI
|
50
|
+
# source = Rucoa::Source.new(
|
51
|
+
# content: '',
|
52
|
+
# uri: 'untitled:Untitled-1'
|
53
|
+
# )
|
54
|
+
# expect(source.path).to be_nil
|
55
|
+
def path
|
56
|
+
return unless @uri
|
57
|
+
|
58
|
+
path = ::URI.parse(@uri).path
|
59
|
+
return unless path
|
60
|
+
|
61
|
+
::CGI.unescape(path)
|
16
62
|
end
|
17
63
|
|
18
64
|
# @param position [Rucoa::Position]
|
@@ -21,11 +67,15 @@ module Rucoa
|
|
21
67
|
root_and_descendant_nodes.reverse.find do |node|
|
22
68
|
node.include_position?(position)
|
23
69
|
end
|
70
|
+
rescue ::Parser::SyntaxError
|
71
|
+
nil
|
24
72
|
end
|
25
73
|
|
26
74
|
# @return [Rucoa::Nodes::Base, nil]
|
27
75
|
def root_node
|
28
76
|
@root_node ||= Parser.call(@content)
|
77
|
+
rescue ::Parser::SyntaxError
|
78
|
+
nil
|
29
79
|
end
|
30
80
|
|
31
81
|
private
|
data/lib/rucoa/source_store.rb
CHANGED
@@ -9,22 +9,18 @@ module Rucoa
|
|
9
9
|
@data = {}
|
10
10
|
end
|
11
11
|
|
12
|
+
# @param source [Rucoa::Source]
|
13
|
+
# @return [void]
|
14
|
+
def update(source)
|
15
|
+
@data[source.uri] = source
|
16
|
+
end
|
17
|
+
|
12
18
|
# @param uri [String]
|
13
19
|
# @return [String, nil]
|
14
20
|
def get(uri)
|
15
21
|
@data[uri]
|
16
22
|
end
|
17
23
|
|
18
|
-
# @param uri [String]
|
19
|
-
# @param content [String]
|
20
|
-
# @return [void]
|
21
|
-
def set(uri, content)
|
22
|
-
@data[uri] = Source.new(
|
23
|
-
content: content,
|
24
|
-
path: path_from_uri(uri)
|
25
|
-
)
|
26
|
-
end
|
27
|
-
|
28
24
|
# @yieldparam uri [String]
|
29
25
|
# @return [Enumerable<String>]
|
30
26
|
def each_uri(&block)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Types
|
5
|
+
class MethodType
|
6
|
+
# @return [String]
|
7
|
+
attr_reader :parameters_string
|
8
|
+
|
9
|
+
# @return [String]
|
10
|
+
attr_reader :return_type
|
11
|
+
|
12
|
+
# @param parameters_string [String]
|
13
|
+
# @param return_type [String]
|
14
|
+
def initialize(
|
15
|
+
parameters_string:,
|
16
|
+
return_type:
|
17
|
+
)
|
18
|
+
@parameters_string = parameters_string
|
19
|
+
@return_type = return_type
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/rucoa/types.rb
ADDED
data/lib/rucoa/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'yard'
|
5
|
+
|
6
|
+
module Rucoa
|
7
|
+
class YardGlobDocumentLoader
|
8
|
+
class << self
|
9
|
+
# @param globs [Array<String>]
|
10
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
11
|
+
def call(globs:)
|
12
|
+
new(
|
13
|
+
globs: globs
|
14
|
+
).call
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param globs [String]
|
19
|
+
def initialize(globs:)
|
20
|
+
@globs = globs
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
24
|
+
def call
|
25
|
+
code_objects.filter_map do |code_object|
|
26
|
+
case code_object
|
27
|
+
when ::YARD::CodeObjects::MethodObject
|
28
|
+
DefinitionBuilders::YardMethodDefinitionBuilder.call(
|
29
|
+
code_object: code_object,
|
30
|
+
path: code_object.file
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @return [Array<YARD::CodeObjects::Base>]
|
39
|
+
def code_objects
|
40
|
+
::YARD::Logger.instance.enter_level(::Logger::FATAL) do
|
41
|
+
::YARD::Registry.clear
|
42
|
+
::YARD.parse(@globs)
|
43
|
+
::YARD::Registry.all
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'yard'
|
5
|
+
|
6
|
+
module Rucoa
|
7
|
+
class YardStringDocumentLoader
|
8
|
+
class << self
|
9
|
+
# @param content [String]
|
10
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
11
|
+
# @example returns method definitions from Ruby source code
|
12
|
+
# content = <<~RUBY
|
13
|
+
# class Foo
|
14
|
+
# # Return given argument as an Integer.
|
15
|
+
# # @param bar [String]
|
16
|
+
# # @return [Integer]
|
17
|
+
# def foo(bar)
|
18
|
+
# bar.to_i
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# RUBY
|
22
|
+
# definitions = Rucoa::YardStringDocumentLoader.call(
|
23
|
+
# content: content,
|
24
|
+
# path: '/path/to/foo.rb'
|
25
|
+
# )
|
26
|
+
# expect(definitions.size).to eq(1)
|
27
|
+
# expect(definitions.first.full_qualified_name).to eq('Foo#foo')
|
28
|
+
# expect(definitions.first.source_path).to eq('/path/to/foo.rb')
|
29
|
+
# expect(definitions.first.description).to eq('Return given argument as an Integer.')
|
30
|
+
# expect(definitions.first.return_types).to eq(%w[Integer])
|
31
|
+
def call(content:, path:)
|
32
|
+
new(
|
33
|
+
content: content,
|
34
|
+
path: path
|
35
|
+
).call
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param content [String]
|
40
|
+
# @param path [String]
|
41
|
+
def initialize(content:, path:)
|
42
|
+
@content = content
|
43
|
+
@path = path
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
47
|
+
def call
|
48
|
+
code_objects.filter_map do |code_object|
|
49
|
+
case code_object
|
50
|
+
when ::YARD::CodeObjects::MethodObject
|
51
|
+
DefinitionBuilders::YardMethodDefinitionBuilder.call(
|
52
|
+
code_object: code_object,
|
53
|
+
path: @path
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# @return [Array<YARD::CodeObjects::Base>]
|
62
|
+
def code_objects
|
63
|
+
::YARD::Logger.instance.enter_level(::Logger::FATAL) do
|
64
|
+
::YARD::Registry.clear
|
65
|
+
::YARD.parse_string(@content)
|
66
|
+
::YARD::Registry.all
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|