yoda-language-server 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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/client/atom/main.js +27 -0
- data/client/vscode/.gitignore +4 -0
- data/client/vscode/.vscode/launch.json +28 -0
- data/client/vscode/.vscode/settings.json +9 -0
- data/client/vscode/.vscode/tasks.json +20 -0
- data/client/vscode/.vscodeignore +8 -0
- data/client/vscode/CHANGELOG.md +7 -0
- data/client/vscode/README.md +65 -0
- data/client/vscode/package-lock.json +2688 -0
- data/client/vscode/package.json +39 -0
- data/client/vscode/src/extension.ts +42 -0
- data/client/vscode/src/test/extension.test.ts +22 -0
- data/client/vscode/src/test/index.ts +22 -0
- data/client/vscode/tsconfig.json +16 -0
- data/client/vscode/vsc-extension-quickstart.md +33 -0
- data/exe/yoda +27 -0
- data/lib/yoda.rb +11 -0
- data/lib/yoda/evaluation.rb +9 -0
- data/lib/yoda/evaluation/code_completion.rb +65 -0
- data/lib/yoda/evaluation/code_completion/base_provider.rb +57 -0
- data/lib/yoda/evaluation/code_completion/const_provider.rb +90 -0
- data/lib/yoda/evaluation/code_completion/method_provider.rb +82 -0
- data/lib/yoda/evaluation/code_completion/variable_provider.rb +18 -0
- data/lib/yoda/evaluation/comment_completion.rb +70 -0
- data/lib/yoda/evaluation/comment_completion/base_provider.rb +64 -0
- data/lib/yoda/evaluation/comment_completion/param_provider.rb +18 -0
- data/lib/yoda/evaluation/comment_completion/tag_provider.rb +41 -0
- data/lib/yoda/evaluation/comment_completion/type_provider.rb +58 -0
- data/lib/yoda/evaluation/current_node_explain.rb +70 -0
- data/lib/yoda/evaluation/evaluator.rb +103 -0
- data/lib/yoda/evaluation/signature_discovery.rb +83 -0
- data/lib/yoda/model.rb +12 -0
- data/lib/yoda/model/completion_item.rb +56 -0
- data/lib/yoda/model/descriptions.rb +10 -0
- data/lib/yoda/model/descriptions/base.rb +26 -0
- data/lib/yoda/model/descriptions/function_description.rb +40 -0
- data/lib/yoda/model/descriptions/value_description.rb +33 -0
- data/lib/yoda/model/descriptions/word_description.rb +32 -0
- data/lib/yoda/model/function_signatures.rb +13 -0
- data/lib/yoda/model/function_signatures/base.rb +68 -0
- data/lib/yoda/model/function_signatures/constructor.rb +70 -0
- data/lib/yoda/model/function_signatures/formatter.rb +82 -0
- data/lib/yoda/model/function_signatures/method.rb +67 -0
- data/lib/yoda/model/function_signatures/overload.rb +79 -0
- data/lib/yoda/model/function_signatures/parameter_list.rb +108 -0
- data/lib/yoda/model/function_signatures/type_builder.rb +101 -0
- data/lib/yoda/model/node_signature.rb +28 -0
- data/lib/yoda/model/path.rb +96 -0
- data/lib/yoda/model/scoped_path.rb +44 -0
- data/lib/yoda/model/types.rb +84 -0
- data/lib/yoda/model/types/any_type.rb +32 -0
- data/lib/yoda/model/types/base.rb +37 -0
- data/lib/yoda/model/types/duck_type.rb +41 -0
- data/lib/yoda/model/types/function_type.rb +174 -0
- data/lib/yoda/model/types/generic_type.rb +66 -0
- data/lib/yoda/model/types/instance_type.rb +42 -0
- data/lib/yoda/model/types/module_type.rb +42 -0
- data/lib/yoda/model/types/sequence_type.rb +53 -0
- data/lib/yoda/model/types/union_type.rb +56 -0
- data/lib/yoda/model/types/unknown_type.rb +40 -0
- data/lib/yoda/model/types/value_type.rb +58 -0
- data/lib/yoda/model/values.rb +9 -0
- data/lib/yoda/model/values/base.rb +32 -0
- data/lib/yoda/model/values/instance_value.rb +65 -0
- data/lib/yoda/model/values/module_value.rb +72 -0
- data/lib/yoda/parsing.rb +15 -0
- data/lib/yoda/parsing/ast_traversable.rb +18 -0
- data/lib/yoda/parsing/comment_tokenizer.rb +59 -0
- data/lib/yoda/parsing/location.rb +101 -0
- data/lib/yoda/parsing/node_objects.rb +10 -0
- data/lib/yoda/parsing/node_objects/const_node.rb +52 -0
- data/lib/yoda/parsing/node_objects/method_definition.rb +46 -0
- data/lib/yoda/parsing/node_objects/namespace.rb +104 -0
- data/lib/yoda/parsing/node_objects/send_node.rb +72 -0
- data/lib/yoda/parsing/parser.rb +27 -0
- data/lib/yoda/parsing/query.rb +11 -0
- data/lib/yoda/parsing/query/current_comment_query.rb +80 -0
- data/lib/yoda/parsing/query/current_comment_token_query.rb +153 -0
- data/lib/yoda/parsing/query/current_commenting_node_query.rb +68 -0
- data/lib/yoda/parsing/query/current_location_node_query.rb +51 -0
- data/lib/yoda/parsing/query/current_node_comment_query.rb +40 -0
- data/lib/yoda/parsing/range.rb +41 -0
- data/lib/yoda/parsing/scopes.rb +15 -0
- data/lib/yoda/parsing/scopes/base.rb +78 -0
- data/lib/yoda/parsing/scopes/builder.rb +60 -0
- data/lib/yoda/parsing/scopes/class_definition.rb +47 -0
- data/lib/yoda/parsing/scopes/meta_class_definition.rb +44 -0
- data/lib/yoda/parsing/scopes/meta_method_definition.rb +70 -0
- data/lib/yoda/parsing/scopes/method_definition.rb +69 -0
- data/lib/yoda/parsing/scopes/module_definition.rb +36 -0
- data/lib/yoda/parsing/scopes/root.rb +25 -0
- data/lib/yoda/parsing/source_analyzer.rb +59 -0
- data/lib/yoda/parsing/source_cutter.rb +231 -0
- data/lib/yoda/parsing/type_parser.rb +141 -0
- data/lib/yoda/runner.rb +6 -0
- data/lib/yoda/runner/infer.rb +50 -0
- data/lib/yoda/runner/setup.rb +26 -0
- data/lib/yoda/server.rb +191 -0
- data/lib/yoda/server/client_info.rb +98 -0
- data/lib/yoda/server/completion_provider.rb +78 -0
- data/lib/yoda/server/definition_provider.rb +36 -0
- data/lib/yoda/server/deserializer.rb +27 -0
- data/lib/yoda/server/hover_provider.rb +38 -0
- data/lib/yoda/server/signature_provider.rb +46 -0
- data/lib/yoda/store.rb +13 -0
- data/lib/yoda/store/actions.rb +10 -0
- data/lib/yoda/store/actions/import_core_library.rb +30 -0
- data/lib/yoda/store/actions/import_gems.rb +91 -0
- data/lib/yoda/store/actions/read_file.rb +36 -0
- data/lib/yoda/store/actions/read_project_files.rb +29 -0
- data/lib/yoda/store/adapters.rb +14 -0
- data/lib/yoda/store/adapters/base.rb +58 -0
- data/lib/yoda/store/adapters/leveldb_adapter.rb +80 -0
- data/lib/yoda/store/adapters/lmdb_adapter.rb +113 -0
- data/lib/yoda/store/objects.rb +46 -0
- data/lib/yoda/store/objects/addressable.rb +25 -0
- data/lib/yoda/store/objects/base.rb +116 -0
- data/lib/yoda/store/objects/class_object.rb +51 -0
- data/lib/yoda/store/objects/merger.rb +94 -0
- data/lib/yoda/store/objects/meta_class_object.rb +41 -0
- data/lib/yoda/store/objects/method_object.rb +94 -0
- data/lib/yoda/store/objects/module_object.rb +11 -0
- data/lib/yoda/store/objects/namespace_object.rb +67 -0
- data/lib/yoda/store/objects/overload.rb +51 -0
- data/lib/yoda/store/objects/patch.rb +46 -0
- data/lib/yoda/store/objects/patch_set.rb +80 -0
- data/lib/yoda/store/objects/tag.rb +62 -0
- data/lib/yoda/store/objects/value_object.rb +45 -0
- data/lib/yoda/store/project.rb +159 -0
- data/lib/yoda/store/query.rb +12 -0
- data/lib/yoda/store/query/associators.rb +10 -0
- data/lib/yoda/store/query/associators/associate_ancestors.rb +103 -0
- data/lib/yoda/store/query/associators/associate_methods.rb +38 -0
- data/lib/yoda/store/query/base.rb +16 -0
- data/lib/yoda/store/query/find_constant.rb +150 -0
- data/lib/yoda/store/query/find_meta_class.rb +18 -0
- data/lib/yoda/store/query/find_method.rb +74 -0
- data/lib/yoda/store/query/find_signature.rb +43 -0
- data/lib/yoda/store/registry.rb +67 -0
- data/lib/yoda/store/yard_importer.rb +260 -0
- data/lib/yoda/typing.rb +10 -0
- data/lib/yoda/typing/context.rb +96 -0
- data/lib/yoda/typing/environment.rb +35 -0
- data/lib/yoda/typing/evaluator.rb +256 -0
- data/lib/yoda/typing/lexical_scope.rb +26 -0
- data/lib/yoda/typing/relation.rb +15 -0
- data/lib/yoda/typing/traces.rb +9 -0
- data/lib/yoda/typing/traces/base.rb +26 -0
- data/lib/yoda/typing/traces/normal.rb +22 -0
- data/lib/yoda/typing/traces/send.rb +26 -0
- data/lib/yoda/version.rb +3 -0
- data/lib/yoda/yard_extensions.rb +11 -0
- data/lib/yoda/yard_extensions/sig_directive.rb +40 -0
- data/lib/yoda/yard_extensions/type_tag.rb +10 -0
- data/package.json +76 -0
- data/scripts/benchmark.rb +6 -0
- data/scripts/build_core_index.sh +16 -0
- data/yarn.lock +13 -0
- data/yoda-language-server.gemspec +40 -0
- metadata +424 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Parsing
|
|
3
|
+
module NodeObjects
|
|
4
|
+
class SendNode
|
|
5
|
+
attr_reader :node
|
|
6
|
+
|
|
7
|
+
# @param node [::Parser::AST::Node]
|
|
8
|
+
def initialize(node)
|
|
9
|
+
fail ArgumentError, node unless node.is_a?(::Parser::AST::Node)
|
|
10
|
+
@node = node
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [true, false]
|
|
14
|
+
def on_selector?(location)
|
|
15
|
+
node.location.selector ? selector_range.include?(location) : false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param location [Location]
|
|
19
|
+
# @return [true, false]
|
|
20
|
+
def on_dot?(location)
|
|
21
|
+
node.location.dot ? dot_range.include?(location) : false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param location [Location]
|
|
25
|
+
# @return [true, false]
|
|
26
|
+
def on_parameter?(location)
|
|
27
|
+
parameter_range.include?(location)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Range]
|
|
31
|
+
def parameter_range
|
|
32
|
+
@parameter_range ||=
|
|
33
|
+
Range.new(
|
|
34
|
+
Location.of_ast_location(node.location.selector.end),
|
|
35
|
+
Location.of_ast_location(node.location.expression.end).move(row: 0, column: -1),
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [Range]
|
|
40
|
+
def selector_range
|
|
41
|
+
@selector_range ||= Range.of_ast_location(node.location.selector)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Range, nil]
|
|
45
|
+
def dot_range
|
|
46
|
+
@dot_range ||= node.location.dot && Range.of_ast_location(node.location.dot)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [Location, nil]
|
|
50
|
+
def next_location_to_dot
|
|
51
|
+
node.location.dot && Range.of_ast_location(node.location.dot).end_location
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [Parser::AST::Node, nil]
|
|
55
|
+
def receiver_node
|
|
56
|
+
node && node.children[0]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @return [String]
|
|
60
|
+
def selector_name
|
|
61
|
+
node.children[1].to_s
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @param location [Location]
|
|
65
|
+
# @return Integer
|
|
66
|
+
def offset_in_selector(location)
|
|
67
|
+
location.offset_from_begin(node.location.selector)[:column]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'parser/current'
|
|
2
|
+
|
|
3
|
+
module Yoda
|
|
4
|
+
module Parsing
|
|
5
|
+
class Parser
|
|
6
|
+
# @param string [String]
|
|
7
|
+
# @return [::Parser::AST::Node]
|
|
8
|
+
def parse(string)
|
|
9
|
+
::Parser::CurrentRuby.parse(string)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @param string [String]
|
|
13
|
+
# @return [(::Parser::AST::Node, Array<::Parser::Source::Comment>)]
|
|
14
|
+
def parse_with_comments(string)
|
|
15
|
+
::Parser::CurrentRuby.parse_with_comments(string)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param string [String]
|
|
19
|
+
# @return [(::Parser::AST::Node, Array<::Parser::Source::Comment>), nil]
|
|
20
|
+
def parse_with_comments_if_valid(string)
|
|
21
|
+
parse_with_comments(source)
|
|
22
|
+
rescue ::Parser::SyntaxError
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Parsing
|
|
3
|
+
module Query
|
|
4
|
+
require 'yoda/parsing/query/current_comment_query'
|
|
5
|
+
require 'yoda/parsing/query/current_comment_token_query'
|
|
6
|
+
require 'yoda/parsing/query/current_commenting_node_query'
|
|
7
|
+
require 'yoda/parsing/query/current_location_node_query'
|
|
8
|
+
require 'yoda/parsing/query/current_node_comment_query'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Parsing
|
|
3
|
+
module Query
|
|
4
|
+
# Provides helper methods to find the current comment which means the comment on the current position.
|
|
5
|
+
class CurrentCommentQuery
|
|
6
|
+
attr_reader :comments, :location
|
|
7
|
+
|
|
8
|
+
# @param comments [Array<::Parser::Source::Comment>]
|
|
9
|
+
# @param location [Location] represents the current position.
|
|
10
|
+
def initialize(comments, location)
|
|
11
|
+
fail ArgumentError, comments unless comments.all? { |comment| comment.is_a?(::Parser::Source::Comment) }
|
|
12
|
+
fail ArgumentError, location unless location.is_a?(Location)
|
|
13
|
+
@comments = comments
|
|
14
|
+
@location = location
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# The single line comment which the current position is on.
|
|
18
|
+
# @return [::Parser::Source::Comment, nil]
|
|
19
|
+
def current_comment
|
|
20
|
+
@current_comment ||= comments.find { |comment| location.included?(comment.location) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# The multiple line comments which the current position is on.
|
|
24
|
+
# @return [Array<::Parser::Source::Comment>]
|
|
25
|
+
def current_comment_block
|
|
26
|
+
@current_comment_block ||= current_comment ? comment_blocks.find { |block| block.include?(current_comment) } : []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The relative coordinates of the current position from the beginning position of the current comment.
|
|
30
|
+
# @return [Location]
|
|
31
|
+
def location_in_current_comment_block
|
|
32
|
+
relative_position(location)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Location]
|
|
36
|
+
def begin_point_of_current_comment_block
|
|
37
|
+
Location.new(row: current_comment_block.first.location.line, column: current_comment_block.first.location.column)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @group Coordinate conversion
|
|
41
|
+
|
|
42
|
+
# Calculate relative position (the coordinates from the beginning point) from the relative position.
|
|
43
|
+
# @param position [Location]
|
|
44
|
+
def relative_position(position)
|
|
45
|
+
position.move(row: 1 - current_comment_block.first.location.line, column: - current_comment_block.first.location.column)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Calculate absolute position from the relative position.
|
|
49
|
+
# @param position [Location]
|
|
50
|
+
def absolute_position(position)
|
|
51
|
+
position.move(row: current_comment_block.first.location.line - 1, column: current_comment_block.first.location.column)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Calculate relative range from the relative range.
|
|
55
|
+
# @param range [Range]
|
|
56
|
+
def relative_range(range)
|
|
57
|
+
range.move(row: 1 - current_comment_block.first.location.line, column: - current_comment_block.first.location.column)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Calculate absolute range from the relative range.
|
|
61
|
+
# @param range [Range]
|
|
62
|
+
def absolute_range(range)
|
|
63
|
+
range.move(row: current_comment_block.first.location.line - 1, column: current_comment_block.first.location.column)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [String]
|
|
67
|
+
def current_comment_block_text
|
|
68
|
+
current_comment_block.map(&:text).join("\n")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# @return [Array<Array<::Parser::Source::Comment>>]
|
|
74
|
+
def comment_blocks
|
|
75
|
+
@comment_blocks ||= comments.chunk_while { |i, j| i.location.line + 1 == j.location.line }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Parsing
|
|
3
|
+
module Query
|
|
4
|
+
# Provides helper methods to find the current comment token (token on current position) and its kind.
|
|
5
|
+
class CurrentCommentTokenQuery
|
|
6
|
+
attr_reader :comment, :location_in_comment
|
|
7
|
+
|
|
8
|
+
# @param comment [String]
|
|
9
|
+
# @param location_in_comment [Location] represents relative coordinates of the current position from the beginning position of the current comment.
|
|
10
|
+
def initialize(comment, location_in_comment)
|
|
11
|
+
fail ArgumentError, comment unless comment.is_a?(String)
|
|
12
|
+
fail ArgumentError, location_in_comment unless location_in_comment.is_a?(Location)
|
|
13
|
+
@comment = comment
|
|
14
|
+
@location_in_comment = location_in_comment
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @return [String]
|
|
18
|
+
def current_line_comment
|
|
19
|
+
comment.split("\n")[location_in_comment.row - 1] || ''
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @return [Symbol]
|
|
23
|
+
def current_state
|
|
24
|
+
return :none unless inputting_line
|
|
25
|
+
inputting_line.current_state
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @return [String, nil]
|
|
29
|
+
def current_word
|
|
30
|
+
return nil unless inputting_line
|
|
31
|
+
inputting_line.current_token.to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @return [Range, nil]
|
|
35
|
+
def current_range
|
|
36
|
+
return nil if !inputting_line || !inputting_line.current_range
|
|
37
|
+
start, last = inputting_line.current_range
|
|
38
|
+
Range.new(Location.new(row: location_in_comment.row, column: start), Location.new(row: location_in_comment.row, column: last))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [true, false]
|
|
42
|
+
def at_sign?
|
|
43
|
+
inputting_line.at_sign?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# @return [CommentTokenizer::Sequence, nil]
|
|
49
|
+
def tokenize
|
|
50
|
+
return @tokenize if instance_variable_defined?(:@tokenized)
|
|
51
|
+
@tokenize = CommentTokenizer.new.parse(line_to_current_position)
|
|
52
|
+
rescue Parslet::ParseFailed
|
|
53
|
+
@tokenize = nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [String]
|
|
57
|
+
def line_to_current_position
|
|
58
|
+
current_line_comment.slice(0...location_in_comment.column)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [InputtingLine, nil]
|
|
62
|
+
def inputting_line
|
|
63
|
+
return nil unless tokenize
|
|
64
|
+
@inputting_line ||= InputtingLine.new(tokenize, location_in_comment.column)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class InputtingLine
|
|
68
|
+
# @type CommentTokenizer::Sequence
|
|
69
|
+
attr_reader :token_sequence
|
|
70
|
+
|
|
71
|
+
# @type Integer
|
|
72
|
+
attr_reader :column
|
|
73
|
+
|
|
74
|
+
# @param token_sequence [CommentTokenizer::Sequence]
|
|
75
|
+
# @param column [Integer]
|
|
76
|
+
def initialize(token_sequence, column)
|
|
77
|
+
@token_sequence = token_sequence
|
|
78
|
+
@column = column
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @return [Parslet::Slice, nil]
|
|
82
|
+
def tag
|
|
83
|
+
token_sequence.tag
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @return [(Integer, Integer), nil]
|
|
87
|
+
def current_range
|
|
88
|
+
return nil unless current_token
|
|
89
|
+
[current_token.offset, current_token.offset + current_token.size]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @return [Parslet::Slice, nil]
|
|
93
|
+
def current_token
|
|
94
|
+
@current_token ||= token_sequence.all_tokens.find { |token| token.offset <= column && column <= token.offset + token.size }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @return [Symbol]
|
|
98
|
+
def current_state
|
|
99
|
+
@current_state ||= begin
|
|
100
|
+
if tag && %w(@type @!sig).include?(tag.to_s) && !on_tag?
|
|
101
|
+
:type_tag_type
|
|
102
|
+
elsif tag && token_sequence.parameter_tokens.empty?
|
|
103
|
+
:tag
|
|
104
|
+
elsif in_bracket?
|
|
105
|
+
:type
|
|
106
|
+
elsif at_parameter_name?
|
|
107
|
+
:param
|
|
108
|
+
else
|
|
109
|
+
:none
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @return [true, false]
|
|
115
|
+
def at_sign?
|
|
116
|
+
current_token &&
|
|
117
|
+
current_token.to_s.match?(/\A[{}.&\]\[\(\)<>]/) &&
|
|
118
|
+
column == current_token.offset + current_token.size
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
# @return [Boolean]
|
|
124
|
+
def on_tag?
|
|
125
|
+
tag && tag.offset <= column && column <= tag.offset + tag.size
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @return [Boolean]
|
|
129
|
+
def at_parameter_name?
|
|
130
|
+
case token_sequence.parameter_tokens.length
|
|
131
|
+
when 0
|
|
132
|
+
# TODO
|
|
133
|
+
false
|
|
134
|
+
when 1
|
|
135
|
+
tag && %w(@param).include?(tag.to_s)
|
|
136
|
+
else
|
|
137
|
+
false
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# @return [Boolean]
|
|
142
|
+
def in_bracket?
|
|
143
|
+
token_sequence.parameter_tokens.reverse_each do |token|
|
|
144
|
+
return false if token.to_s == ']'
|
|
145
|
+
return true if token.to_s == '['
|
|
146
|
+
end
|
|
147
|
+
false
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Parsing
|
|
3
|
+
module Query
|
|
4
|
+
# Provides helper methods to find the node whose comment include the current position (is the current comment).
|
|
5
|
+
class CurrentCommentingNodeQuery
|
|
6
|
+
attr_reader :ast, :comments, :location
|
|
7
|
+
|
|
8
|
+
# @param ast [::Parser::AST::Node]
|
|
9
|
+
# @param comments [Array<::Parser::Source::Comment>]
|
|
10
|
+
# @param location [Location] represents the current position.
|
|
11
|
+
def initialize(ast, comments, location)
|
|
12
|
+
fail ArgumentError, ast unless ast.is_a?(::Parser::AST::Node)
|
|
13
|
+
fail ArgumentError, comments unless comments.all? { |comment| comment.is_a?(::Parser::Source::Comment) }
|
|
14
|
+
fail ArgumentError, location unless location.is_a?(Location)
|
|
15
|
+
@ast = ast
|
|
16
|
+
@comments = comments
|
|
17
|
+
@location = location
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [Array<::Parser::Source::Comment>]
|
|
21
|
+
def current_commenting_node
|
|
22
|
+
@current_commenting_node ||= inverse_association[current_comment_query.current_comment_block]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [NodeObjects::Namespace, nil]
|
|
26
|
+
def current_namespace
|
|
27
|
+
@current_namespace ||= namespace.calc_current_location_namespace(current_commenting_node_location)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [NodeObjects::MethodDefition, nil]
|
|
31
|
+
def current_method_definition
|
|
32
|
+
@current_method_definition ||= namespace.calc_current_location_method(current_commenting_node_location)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def current_commenting_node_location
|
|
38
|
+
@current_commenting_node_location ||= Location.of_ast_location(current_commenting_node.location)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Namespace]
|
|
42
|
+
def namespace
|
|
43
|
+
@namespace ||= NodeObjects::Namespace.new(ast)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @return [{::Parser::AST::Node => Array<::Parser::Source::Comment>}]
|
|
47
|
+
def association
|
|
48
|
+
@association ||= ::Parser::Source::Comment.associate(ast, comments)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [{Array<::Parser::Source::Comment> => ::Parser::AST::Node}]
|
|
52
|
+
def inverse_association
|
|
53
|
+
@inverse_association ||= association.invert
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [{::Parser::Source::Map => Array<::Parser::Source::Comment>]
|
|
57
|
+
def location_association
|
|
58
|
+
@location_association ||= ::Parser::Source::Comment.associate_with_location(ast, comments)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [CurrentCommentQuery]
|
|
62
|
+
def current_comment_query
|
|
63
|
+
@current_comment_query ||= CurrentCommentQuery.new(comments, location)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Parsing
|
|
3
|
+
module Query
|
|
4
|
+
class CurrentLocationQuery
|
|
5
|
+
attr_reader :ast, :location
|
|
6
|
+
|
|
7
|
+
# @param ast [::Parser::AST::Node]
|
|
8
|
+
# @param location [Location]
|
|
9
|
+
def initialize(ast, location)
|
|
10
|
+
@ast = ast
|
|
11
|
+
@location = location
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [NodeObjects::Namespace, nil]
|
|
15
|
+
def current_namespace
|
|
16
|
+
@current_namespace ||= namespace.calc_current_location_namespace(location)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [NodeObjects::MethodDefition, nil]
|
|
20
|
+
def current_method_definition
|
|
21
|
+
@current_method_definition ||= namespace.calc_current_location_method(location)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# @return [Namespace]
|
|
27
|
+
def namespace
|
|
28
|
+
@namespace ||= NodeObjects::Namespace.new(self.ast)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Array<::Parser::AST::Node>]
|
|
32
|
+
def nodes_to_current_location_from_root
|
|
33
|
+
@nodes_to_current_location ||= calc_nodes_to_current_location(ast, location)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param root_node [Array<::Parser::AST::Node>]
|
|
37
|
+
# @param current_location [Parser::Source::Map]
|
|
38
|
+
# @return [Array<::Parser::AST::Node>]
|
|
39
|
+
def calc_nodes_to_current_location(root_node, current_location)
|
|
40
|
+
nodes = []
|
|
41
|
+
node = root_node
|
|
42
|
+
while node && !node.children.empty?
|
|
43
|
+
nodes << node
|
|
44
|
+
node = node.children.find { |n| n.respond_to?(:location) && current_location.included?(n.location) }
|
|
45
|
+
end
|
|
46
|
+
nodes
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|