solargraph 0.58.3 → 0.59.2
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/.envrc +3 -0
- data/.github/workflows/linting.yml +12 -5
- data/.github/workflows/plugins.yml +54 -34
- data/.github/workflows/rspec.yml +15 -28
- data/.github/workflows/typecheck.yml +6 -3
- data/.rubocop.yml +38 -6
- data/.rubocop_todo.yml +53 -966
- data/CHANGELOG.md +24 -0
- data/Gemfile +3 -1
- data/README.md +3 -3
- data/Rakefile +26 -23
- data/bin/solargraph +2 -1
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +12 -3
- data/lib/solargraph/api_map/index.rb +29 -18
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +40 -30
- data/lib/solargraph/api_map.rb +160 -78
- data/lib/solargraph/bench.rb +2 -3
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +31 -18
- data/lib/solargraph/complex_type/unique_type.rb +221 -63
- data/lib/solargraph/complex_type.rb +173 -59
- data/lib/solargraph/convention/active_support_concern.rb +111 -111
- data/lib/solargraph/convention/base.rb +50 -50
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
- data/lib/solargraph/convention/data_definition.rb +5 -2
- data/lib/solargraph/convention/gemfile.rb +1 -1
- data/lib/solargraph/convention/gemspec.rb +1 -1
- data/lib/solargraph/convention/rakefile.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
- data/lib/solargraph/convention/struct_definition.rb +8 -4
- data/lib/solargraph/convention.rb +2 -2
- data/lib/solargraph/converters/dd.rb +2 -0
- data/lib/solargraph/converters/dl.rb +2 -0
- data/lib/solargraph/converters/dt.rb +2 -0
- data/lib/solargraph/converters/misc.rb +2 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +11 -10
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/diagnostics/type_check.rb +11 -10
- data/lib/solargraph/diagnostics/update_errors.rb +4 -8
- data/lib/solargraph/diagnostics.rb +55 -55
- data/lib/solargraph/doc_map.rb +38 -39
- data/lib/solargraph/environ.rb +52 -52
- data/lib/solargraph/equality.rb +4 -4
- data/lib/solargraph/gem_pins.rb +4 -15
- data/lib/solargraph/language_server/error_codes.rb +10 -10
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +3 -3
- data/lib/solargraph/language_server/host/message_worker.rb +4 -3
- data/lib/solargraph/language_server/host/sources.rb +2 -1
- data/lib/solargraph/language_server/host.rb +35 -28
- data/lib/solargraph/language_server/message/base.rb +1 -1
- data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
- data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
- data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
- data/lib/solargraph/language_server/message/extended/search.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +20 -14
- data/lib/solargraph/language_server/message/initialized.rb +28 -28
- data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
- data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
- data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
- data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
- data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
- data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
- data/lib/solargraph/language_server/message/text_document.rb +28 -28
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
- data/lib/solargraph/language_server/message.rb +1 -1
- data/lib/solargraph/language_server/progress.rb +143 -143
- data/lib/solargraph/language_server/request.rb +4 -2
- data/lib/solargraph/language_server/transport/adapter.rb +68 -68
- data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
- data/lib/solargraph/language_server/uri_helpers.rb +2 -2
- data/lib/solargraph/language_server.rb +20 -20
- data/lib/solargraph/library.rb +57 -38
- data/lib/solargraph/location.rb +17 -14
- data/lib/solargraph/logging.rb +22 -4
- data/lib/solargraph/page.rb +1 -1
- data/lib/solargraph/parser/comment_ripper.rb +19 -4
- data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
- data/lib/solargraph/parser/node_processor/base.rb +34 -4
- data/lib/solargraph/parser/node_processor.rb +8 -7
- data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
- data/lib/solargraph/parser/parser_gem/node_methods.rb +181 -73
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/parser_gem.rb +2 -0
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +3 -1
- data/lib/solargraph/parser.rb +2 -0
- data/lib/solargraph/pin/base.rb +126 -82
- data/lib/solargraph/pin/base_variable.rb +273 -24
- data/lib/solargraph/pin/block.rb +29 -6
- data/lib/solargraph/pin/breakable.rb +7 -1
- data/lib/solargraph/pin/callable.rb +65 -21
- data/lib/solargraph/pin/closure.rb +7 -10
- data/lib/solargraph/pin/common.rb +24 -6
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/constant.rb +3 -5
- data/lib/solargraph/pin/conversions.rb +10 -4
- data/lib/solargraph/pin/delegated_method.rb +19 -8
- data/lib/solargraph/pin/documenting.rb +4 -2
- data/lib/solargraph/pin/instance_variable.rb +5 -1
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/local_variable.rb +15 -59
- data/lib/solargraph/pin/method.rb +158 -104
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +19 -12
- data/lib/solargraph/pin/parameter.rb +102 -36
- data/lib/solargraph/pin/proxy_type.rb +4 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/require.rb +14 -14
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference/type_alias.rb +16 -0
- data/lib/solargraph/pin/reference.rb +20 -0
- data/lib/solargraph/pin/search.rb +8 -7
- data/lib/solargraph/pin/signature.rb +15 -12
- data/lib/solargraph/pin/singleton.rb +11 -11
- data/lib/solargraph/pin/symbol.rb +2 -1
- data/lib/solargraph/pin/until.rb +2 -4
- data/lib/solargraph/pin/while.rb +2 -4
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +22 -19
- data/lib/solargraph/position.rb +17 -10
- data/lib/solargraph/range.rb +16 -15
- data/lib/solargraph/rbs_map/conversions.rb +367 -231
- data/lib/solargraph/rbs_map/core_fills.rb +18 -11
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
- data/lib/solargraph/rbs_map.rb +76 -32
- data/lib/solargraph/server_methods.rb +1 -1
- data/lib/solargraph/shell.rb +258 -66
- data/lib/solargraph/source/chain/array.rb +3 -12
- data/lib/solargraph/source/chain/block_symbol.rb +13 -13
- data/lib/solargraph/source/chain/block_variable.rb +13 -13
- data/lib/solargraph/source/chain/call.rb +96 -56
- data/lib/solargraph/source/chain/class_variable.rb +1 -1
- data/lib/solargraph/source/chain/constant.rb +5 -1
- data/lib/solargraph/source/chain/global_variable.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +8 -5
- data/lib/solargraph/source/chain/head.rb +19 -19
- data/lib/solargraph/source/chain/if.rb +12 -10
- data/lib/solargraph/source/chain/instance_variable.rb +24 -1
- data/lib/solargraph/source/chain/link.rb +12 -22
- data/lib/solargraph/source/chain/literal.rb +22 -15
- data/lib/solargraph/source/chain/or.rb +10 -4
- data/lib/solargraph/source/chain/q_call.rb +2 -0
- data/lib/solargraph/source/chain/variable.rb +3 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -3
- data/lib/solargraph/source/chain.rb +51 -38
- data/lib/solargraph/source/change.rb +12 -5
- data/lib/solargraph/source/cursor.rb +33 -18
- data/lib/solargraph/source/encoding_fixes.rb +6 -7
- data/lib/solargraph/source/source_chainer.rb +56 -32
- data/lib/solargraph/source/updater.rb +5 -1
- data/lib/solargraph/source.rb +59 -35
- data/lib/solargraph/source_map/clip.rb +54 -30
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +69 -42
- data/lib/solargraph/source_map.rb +21 -9
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +81 -8
- data/lib/solargraph/type_checker.rb +196 -122
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +50 -28
- data/lib/solargraph/yard_map/cache.rb +25 -25
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
- data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
- data/lib/solargraph/yard_map/mapper.rb +13 -8
- data/lib/solargraph/yard_map.rb +17 -18
- data/lib/solargraph/yard_tags.rb +2 -2
- data/lib/solargraph/yardoc.rb +7 -4
- data/lib/solargraph.rb +33 -10
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/shims/ast/0/node.rbs +1 -1
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/solargraph.gemspec +37 -35
- metadata +41 -42
- data/lib/solargraph/type_checker/checks.rb +0 -124
- data/lib/solargraph/type_checker/param_def.rb +0 -37
- data/lib/solargraph/yard_map/to_method.rb +0 -89
- data/rbs/fills/tuple/tuple.rbs +0 -149
|
@@ -4,6 +4,7 @@ require 'parser'
|
|
|
4
4
|
require 'ast'
|
|
5
5
|
|
|
6
6
|
# https://github.com/whitequark/parser
|
|
7
|
+
# rubocop:disable Metrics/ModuleLength
|
|
7
8
|
module Solargraph
|
|
8
9
|
module Parser
|
|
9
10
|
module ParserGem
|
|
@@ -12,17 +13,17 @@ module Solargraph
|
|
|
12
13
|
|
|
13
14
|
# @param node [Parser::AST::Node]
|
|
14
15
|
# @return [String]
|
|
15
|
-
def unpack_name
|
|
16
|
-
pack_name(node).join(
|
|
16
|
+
def unpack_name node
|
|
17
|
+
pack_name(node).join('::')
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
# @param node [Parser::AST::Node]
|
|
20
21
|
# @return [Array<String>]
|
|
21
|
-
def pack_name
|
|
22
|
+
def pack_name node
|
|
22
23
|
# @type [Array<String>]
|
|
23
24
|
parts = []
|
|
24
25
|
if node.is_a?(AST::Node)
|
|
25
|
-
node.children.each
|
|
26
|
+
node.children.each do |n|
|
|
26
27
|
if n.is_a?(AST::Node)
|
|
27
28
|
if n.type == :cbase
|
|
28
29
|
parts = [''] + pack_name(n)
|
|
@@ -32,16 +33,16 @@ module Solargraph
|
|
|
32
33
|
else
|
|
33
34
|
parts.push n unless n.nil?
|
|
34
35
|
end
|
|
35
|
-
|
|
36
|
+
end
|
|
36
37
|
end
|
|
37
38
|
parts
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
# @param node [Parser::AST::Node]
|
|
41
|
+
# @param node [Parser::AST::Node, nil]
|
|
41
42
|
# @return [String, nil]
|
|
42
43
|
def infer_literal_node_type node
|
|
43
44
|
return nil unless node.is_a?(AST::Node)
|
|
44
|
-
if
|
|
45
|
+
if %i[str dstr].include?(node.type)
|
|
45
46
|
return '::String'
|
|
46
47
|
elsif node.type == :array
|
|
47
48
|
return '::Array'
|
|
@@ -53,30 +54,30 @@ module Solargraph
|
|
|
53
54
|
return '::Integer'
|
|
54
55
|
elsif node.type == :float
|
|
55
56
|
return '::Float'
|
|
56
|
-
elsif
|
|
57
|
+
elsif %i[sym dsym].include?(node.type)
|
|
57
58
|
return '::Symbol'
|
|
58
59
|
elsif node.type == :regexp
|
|
59
60
|
return '::Regexp'
|
|
60
61
|
elsif node.type == :irange
|
|
61
62
|
return '::Range'
|
|
62
|
-
elsif
|
|
63
|
+
elsif %i[true false].include?(node.type)
|
|
63
64
|
return '::Boolean'
|
|
64
65
|
# @todo Support `nil` keyword in types
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
# elsif node.type == :nil
|
|
67
|
+
# return 'NilClass'
|
|
67
68
|
end
|
|
68
69
|
nil
|
|
69
70
|
end
|
|
70
71
|
|
|
71
72
|
# @param node [Parser::AST::Node]
|
|
72
73
|
# @return [Position]
|
|
73
|
-
def get_node_start_position
|
|
74
|
+
def get_node_start_position node
|
|
74
75
|
Position.new(node.loc.line, node.loc.column)
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
# @param node [Parser::AST::Node]
|
|
78
79
|
# @return [Position]
|
|
79
|
-
def get_node_end_position
|
|
80
|
+
def get_node_end_position node
|
|
80
81
|
Position.new(node.loc.last_line, node.loc.last_column)
|
|
81
82
|
end
|
|
82
83
|
|
|
@@ -86,40 +87,42 @@ module Solargraph
|
|
|
86
87
|
# @return [String]
|
|
87
88
|
def drill_signature node, signature
|
|
88
89
|
return signature unless node.is_a?(AST::Node)
|
|
89
|
-
if
|
|
90
|
-
unless node.children[0].nil?
|
|
91
|
-
signature += drill_signature(node.children[0], signature)
|
|
92
|
-
end
|
|
90
|
+
if %i[const cbase].include?(node.type)
|
|
91
|
+
signature += drill_signature(node.children[0], signature) unless node.children[0].nil?
|
|
93
92
|
signature += '::' unless signature.empty?
|
|
94
93
|
signature += node.children[1].to_s
|
|
95
|
-
elsif
|
|
94
|
+
elsif %i[lvar ivar cvar].include?(node.type)
|
|
96
95
|
signature += '.' unless signature.empty?
|
|
97
96
|
signature += node.children[0].to_s
|
|
98
97
|
elsif node.type == :send
|
|
99
|
-
unless node.children[0].nil?
|
|
100
|
-
signature += drill_signature(node.children[0], signature)
|
|
101
|
-
end
|
|
98
|
+
signature += drill_signature(node.children[0], signature) unless node.children[0].nil?
|
|
102
99
|
signature += '.' unless signature.empty?
|
|
103
100
|
signature += node.children[1].to_s
|
|
104
101
|
end
|
|
105
102
|
signature
|
|
106
103
|
end
|
|
107
104
|
|
|
108
|
-
# @param node [Parser::AST::Node]
|
|
105
|
+
# @param node [Parser::AST::Node, nil]
|
|
109
106
|
# @return [Hash{Symbol => Chain}]
|
|
110
107
|
def convert_hash node
|
|
111
108
|
return {} unless Parser.is_ast_node?(node)
|
|
109
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
112
110
|
return convert_hash(node.children[0]) if node.type == :kwsplat
|
|
113
|
-
|
|
111
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
112
|
+
if Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
|
|
113
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
114
|
+
return convert_hash(node.children[0])
|
|
115
|
+
end
|
|
116
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
114
117
|
return {} unless node.type == :hash
|
|
115
118
|
result = {}
|
|
119
|
+
# @sg-ignore Translate to something flow sensitive typing understands
|
|
116
120
|
node.children.each do |pair|
|
|
117
121
|
result[pair.children[0].children[0]] = Solargraph::Parser.chain(pair.children[1])
|
|
118
122
|
end
|
|
119
123
|
result
|
|
120
124
|
end
|
|
121
125
|
|
|
122
|
-
# @sg-ignore Wrong argument type for AST::Node.new: type expected AST::_ToSym, received :nil
|
|
123
126
|
NIL_NODE = ::Parser::AST::Node.new(:nil)
|
|
124
127
|
|
|
125
128
|
# @param node [Parser::AST::Node]
|
|
@@ -148,7 +151,7 @@ module Solargraph
|
|
|
148
151
|
end
|
|
149
152
|
|
|
150
153
|
# @param nodes [Enumerable<Parser::AST::Node>]
|
|
151
|
-
def any_splatted_call?
|
|
154
|
+
def any_splatted_call? nodes
|
|
152
155
|
nodes.any? { |n| splatted_call?(n) }
|
|
153
156
|
end
|
|
154
157
|
|
|
@@ -161,14 +164,17 @@ module Solargraph
|
|
|
161
164
|
if node.type == :block
|
|
162
165
|
result.push node
|
|
163
166
|
if Parser.is_ast_node?(node.children[0]) && node.children[0].children.length > 2
|
|
164
|
-
|
|
167
|
+
# @sg-ignore Need to add nil check here
|
|
168
|
+
node.children[0].children[2..].each { |child| result.concat call_nodes_from(child) }
|
|
165
169
|
end
|
|
166
|
-
|
|
170
|
+
# @sg-ignore Need to add nil check here
|
|
171
|
+
node.children[1..].each { |child| result.concat call_nodes_from(child) }
|
|
167
172
|
elsif node.type == :send
|
|
168
173
|
result.push node
|
|
169
174
|
result.concat call_nodes_from(node.children.first)
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
# @sg-ignore Need to add nil check here
|
|
176
|
+
node.children[2..].each { |child| result.concat call_nodes_from(child) }
|
|
177
|
+
elsif %i[super zsuper].include?(node.type)
|
|
172
178
|
result.push node
|
|
173
179
|
node.children.each { |child| result.concat call_nodes_from(child) }
|
|
174
180
|
else
|
|
@@ -199,53 +205,142 @@ module Solargraph
|
|
|
199
205
|
# @return [Array<AST::Node>] low-level value nodes in
|
|
200
206
|
# value position. Does not include explicit return
|
|
201
207
|
# statements
|
|
202
|
-
def value_position_nodes_only
|
|
208
|
+
def value_position_nodes_only node
|
|
203
209
|
DeepInference.value_position_nodes_only(node).map { |n| n || NIL_NODE }
|
|
204
210
|
end
|
|
205
211
|
|
|
206
212
|
# @param cursor [Solargraph::Source::Cursor]
|
|
207
213
|
# @return [Parser::AST::Node, nil]
|
|
208
214
|
def find_recipient_node cursor
|
|
209
|
-
|
|
215
|
+
if cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '('
|
|
216
|
+
return repaired_find_recipient_node(cursor)
|
|
217
|
+
end
|
|
210
218
|
source = cursor.source
|
|
211
219
|
position = cursor.position
|
|
212
220
|
offset = cursor.offset
|
|
213
221
|
tree = if source.synchronized?
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
# @sg-ignore Need to add nil check here
|
|
223
|
+
match = source.code[0..(offset - 1)].match(/,\s*\z/)
|
|
224
|
+
if match
|
|
225
|
+
# @sg-ignore Need to add nil check here
|
|
226
|
+
source.tree_at(position.line, position.column - match[0].length)
|
|
227
|
+
else
|
|
228
|
+
source.tree_at(position.line, position.column)
|
|
229
|
+
end
|
|
230
|
+
else
|
|
231
|
+
source.tree_at(position.line, position.column - 1)
|
|
232
|
+
end
|
|
223
233
|
# @type [AST::Node, nil]
|
|
224
234
|
prev = nil
|
|
225
235
|
tree.each do |node|
|
|
226
236
|
if node.type == :send
|
|
227
|
-
args = node.children[2
|
|
237
|
+
args = node.children[2..]
|
|
238
|
+
# @sg-ignore Need to add nil check here
|
|
228
239
|
if !args.empty?
|
|
240
|
+
# @sg-ignore Need to add nil check here
|
|
229
241
|
return node if prev && args.include?(prev)
|
|
230
|
-
|
|
231
|
-
if source.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
return node if source.code[0..offset-1] =~ /\([^(]*\z/
|
|
235
|
-
end
|
|
242
|
+
elsif source.synchronized?
|
|
243
|
+
return node if source.code[0..(offset - 1)] =~ /\(\s*\z/ && source.code[offset..] =~ /^\s*\)/
|
|
244
|
+
elsif source.code[0..(offset - 1)] =~ /\([^(]*\z/
|
|
245
|
+
return node
|
|
236
246
|
end
|
|
237
247
|
end
|
|
238
248
|
prev = node
|
|
239
249
|
end
|
|
240
|
-
|
|
250
|
+
find_recipient_node_by_text(source, offset)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Text-based fallback for finding a method call recipient when the AST
|
|
254
|
+
# is unavailable (e.g., unparseable source with syntax errors).
|
|
255
|
+
#
|
|
256
|
+
# Scans backward from cursor offset to find '(' and the method name
|
|
257
|
+
# before it, then creates a minimal :send node.
|
|
258
|
+
#
|
|
259
|
+
# @param source [Solargraph::Source]
|
|
260
|
+
# @param offset [Integer]
|
|
261
|
+
# @return [Parser::AST::Node, nil]
|
|
262
|
+
def find_recipient_node_by_text source, offset
|
|
263
|
+
code = source.code
|
|
264
|
+
return nil if offset.nil? || offset <= 0 || offset > code.length
|
|
265
|
+
|
|
266
|
+
# The '(' could be at offset-1 (cursor after '(') or at offset (cursor on '(')
|
|
267
|
+
start_pos = offset - 1
|
|
268
|
+
if start_pos.positive? && code[start_pos] != '(' && code[offset] == '('
|
|
269
|
+
start_pos = offset
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Scan backward to find the matching '(' (handle nested parens)
|
|
273
|
+
depth = 0
|
|
274
|
+
paren_pos = nil
|
|
275
|
+
pos = start_pos
|
|
276
|
+
while pos >= 0
|
|
277
|
+
case code[pos]
|
|
278
|
+
when ')'
|
|
279
|
+
depth += 1
|
|
280
|
+
when '('
|
|
281
|
+
if depth.zero?
|
|
282
|
+
paren_pos = pos
|
|
283
|
+
break
|
|
284
|
+
end
|
|
285
|
+
depth -= 1
|
|
286
|
+
end
|
|
287
|
+
pos -= 1
|
|
288
|
+
end
|
|
289
|
+
return nil if paren_pos.nil?
|
|
290
|
+
|
|
291
|
+
# Skip whitespace before '(' to find method name
|
|
292
|
+
idx = paren_pos - 1
|
|
293
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /\s/
|
|
294
|
+
return nil if idx.negative?
|
|
295
|
+
|
|
296
|
+
# Read method name (including ? and !)
|
|
297
|
+
name_end = idx + 1
|
|
298
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_?!]/
|
|
299
|
+
name_start = idx + 1
|
|
300
|
+
return nil if name_start >= name_end
|
|
301
|
+
method_name = code[name_start...name_end]
|
|
302
|
+
return nil if method_name.empty?
|
|
303
|
+
|
|
304
|
+
# Check for receiver pattern: receiver.method( or receiver::method(
|
|
305
|
+
idx = name_start - 1
|
|
306
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /\s/
|
|
307
|
+
if idx >= 0 && code[idx] == '.'
|
|
308
|
+
idx -= 1
|
|
309
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /\s/
|
|
310
|
+
recv_end = idx + 1
|
|
311
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_@$]/
|
|
312
|
+
recv_start = idx + 1
|
|
313
|
+
if recv_start < recv_end
|
|
314
|
+
recv_name = code[recv_start...recv_end]
|
|
315
|
+
unless recv_name.empty?
|
|
316
|
+
receiver_node = ::Parser::AST::Node.new(:send, [nil, recv_name.to_sym])
|
|
317
|
+
return ::Parser::AST::Node.new(:send, [receiver_node, method_name.to_sym])
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
elsif idx >= 0 && idx.positive? && code[idx - 1] == ':' && code[idx] == ':'
|
|
321
|
+
const_end = idx - 1
|
|
322
|
+
const_start = const_end
|
|
323
|
+
const_start -= 1 while const_start.positive? && code[const_start - 1] =~ /[a-zA-Z0-9_]/
|
|
324
|
+
const_name = code[const_start...const_end]
|
|
325
|
+
unless const_name.empty? || method_name.empty?
|
|
326
|
+
const_node = ::Parser::AST::Node.new(:const, [nil, const_name.to_sym])
|
|
327
|
+
return ::Parser::AST::Node.new(:send, [const_node, method_name.to_sym])
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Simple method call without receiver
|
|
332
|
+
::Parser::AST::Node.new(:send, [nil, method_name.to_sym])
|
|
241
333
|
end
|
|
242
334
|
|
|
243
335
|
# @param cursor [Solargraph::Source::Cursor]
|
|
244
336
|
# @return [Parser::AST::Node, nil]
|
|
245
337
|
def repaired_find_recipient_node cursor
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
338
|
+
c = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
|
|
339
|
+
tree = c.source.tree_at(c.position.line, c.position.column)
|
|
340
|
+
tree.each do |node|
|
|
341
|
+
return node if node.type == :send
|
|
342
|
+
end
|
|
343
|
+
find_recipient_node_by_text(cursor.source, cursor.offset)
|
|
249
344
|
end
|
|
250
345
|
|
|
251
346
|
#
|
|
@@ -302,19 +397,15 @@ module Solargraph
|
|
|
302
397
|
# statements in value positions.
|
|
303
398
|
module DeepInference
|
|
304
399
|
class << self
|
|
305
|
-
CONDITIONAL_ALL_BUT_FIRST = [
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
CASE_STATEMENT = [:case]
|
|
400
|
+
CONDITIONAL_ALL_BUT_FIRST = %i[if unless].freeze
|
|
401
|
+
ONLY_ONE_CHILD = [:return].freeze
|
|
402
|
+
FIRST_TWO_CHILDREN = [:rescue].freeze
|
|
403
|
+
COMPOUND_STATEMENTS = %i[begin kwbegin].freeze
|
|
404
|
+
SKIPPABLE = %i[def defs class sclass module].freeze
|
|
405
|
+
FUNCTION_VALUE = [:block].freeze
|
|
406
|
+
CASE_STATEMENT = [:case].freeze
|
|
313
407
|
|
|
314
408
|
# @param node [AST::Node] a method body compound statement
|
|
315
|
-
# @param include_explicit_returns [Boolean] If true,
|
|
316
|
-
# include the value nodes of the parameter of the
|
|
317
|
-
# 'return' statements in the type returned.
|
|
318
409
|
# @return [Array<AST::Node>] low-level value nodes from
|
|
319
410
|
# both nodes in value position as well as explicit
|
|
320
411
|
# return statements in the method's closure.
|
|
@@ -327,14 +418,14 @@ module Solargraph
|
|
|
327
418
|
# @return [Array<AST::Node>] low-level value nodes in
|
|
328
419
|
# value position. Does not include explicit return
|
|
329
420
|
# statements
|
|
330
|
-
def value_position_nodes_only
|
|
421
|
+
def value_position_nodes_only node
|
|
331
422
|
from_value_position_statement(node, include_explicit_returns: false)
|
|
332
423
|
end
|
|
333
424
|
|
|
334
425
|
# Look at known control statements and use them to find
|
|
335
426
|
# more specific return nodes.
|
|
336
427
|
#
|
|
337
|
-
# @param node [
|
|
428
|
+
# @param node [AST::Node] Statement which is in
|
|
338
429
|
# value position for a method body
|
|
339
430
|
# @param include_explicit_returns [Boolean] If true,
|
|
340
431
|
# include the value nodes of the parameter of the
|
|
@@ -348,10 +439,9 @@ module Solargraph
|
|
|
348
439
|
if COMPOUND_STATEMENTS.include?(node.type)
|
|
349
440
|
result.concat from_value_position_compound_statement node
|
|
350
441
|
elsif CONDITIONAL_ALL_BUT_FIRST.include?(node.type)
|
|
351
|
-
|
|
442
|
+
# @sg-ignore Need to add nil check here
|
|
443
|
+
result.concat reduce_to_value_nodes(node.children[1..])
|
|
352
444
|
# result.push NIL_NODE unless node.children[2]
|
|
353
|
-
elsif CONDITIONAL_ALL.include?(node.type)
|
|
354
|
-
result.concat reduce_to_value_nodes(node.children)
|
|
355
445
|
elsif ONLY_ONE_CHILD.include?(node.type)
|
|
356
446
|
result.concat reduce_to_value_nodes([node.children[0]])
|
|
357
447
|
elsif FIRST_TWO_CHILDREN.include?(node.type)
|
|
@@ -362,9 +452,12 @@ module Solargraph
|
|
|
362
452
|
# @todo any explicit returns actually return from
|
|
363
453
|
# scope in which the proc is run. This asssumes
|
|
364
454
|
# that the function is executed here.
|
|
365
|
-
|
|
455
|
+
if include_explicit_returns
|
|
456
|
+
result.concat explicit_return_values_from_compound_statement(node.children[2])
|
|
457
|
+
end
|
|
366
458
|
elsif CASE_STATEMENT.include?(node.type)
|
|
367
|
-
|
|
459
|
+
# @sg-ignore Need to add nil check here
|
|
460
|
+
node.children[1..].each do |cc|
|
|
368
461
|
if cc.nil?
|
|
369
462
|
result.push NIL_NODE
|
|
370
463
|
elsif cc.type == :when
|
|
@@ -397,7 +490,7 @@ module Solargraph
|
|
|
397
490
|
# @return [Array<Parser::AST::Node>]
|
|
398
491
|
def from_value_position_compound_statement parent
|
|
399
492
|
result = []
|
|
400
|
-
nodes = parent.children.select{|n| n.is_a?(AST::Node)}
|
|
493
|
+
nodes = parent.children.select { |n| n.is_a?(AST::Node) }
|
|
401
494
|
nodes.each_with_index do |node, idx|
|
|
402
495
|
if node.type == :block
|
|
403
496
|
result.concat explicit_return_values_from_compound_statement(node.children[2])
|
|
@@ -422,7 +515,10 @@ module Solargraph
|
|
|
422
515
|
# value position. we already have the explicit values
|
|
423
516
|
# from above; now we need to also gather the value
|
|
424
517
|
# position nodes
|
|
425
|
-
|
|
518
|
+
if idx == nodes.length - 1
|
|
519
|
+
result.concat from_value_position_statement(nodes.last,
|
|
520
|
+
include_explicit_returns: false)
|
|
521
|
+
end
|
|
426
522
|
end
|
|
427
523
|
result
|
|
428
524
|
end
|
|
@@ -438,7 +534,7 @@ module Solargraph
|
|
|
438
534
|
def explicit_return_values_from_compound_statement parent
|
|
439
535
|
return [] unless parent.is_a?(::Parser::AST::Node)
|
|
440
536
|
result = []
|
|
441
|
-
nodes = parent.children.select{|n| n.is_a?(::Parser::AST::Node)}
|
|
537
|
+
nodes = parent.children.select { |n| n.is_a?(::Parser::AST::Node) }
|
|
442
538
|
nodes.each do |node|
|
|
443
539
|
next if SKIPPABLE.include?(node.type)
|
|
444
540
|
if node.type == :return
|
|
@@ -460,17 +556,28 @@ module Solargraph
|
|
|
460
556
|
nodes.each do |node|
|
|
461
557
|
if !node.is_a?(::Parser::AST::Node)
|
|
462
558
|
result.push nil
|
|
559
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
463
560
|
elsif COMPOUND_STATEMENTS.include?(node.type)
|
|
464
561
|
result.concat from_value_position_compound_statement(node)
|
|
562
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
465
563
|
elsif CONDITIONAL_ALL_BUT_FIRST.include?(node.type)
|
|
466
|
-
|
|
564
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
565
|
+
result.concat reduce_to_value_nodes(node.children[1..])
|
|
566
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
467
567
|
elsif node.type == :return
|
|
568
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
468
569
|
result.concat reduce_to_value_nodes([node.children[0]])
|
|
570
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
469
571
|
elsif node.type == :or
|
|
572
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
470
573
|
result.concat reduce_to_value_nodes(node.children)
|
|
574
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
471
575
|
elsif node.type == :block
|
|
576
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
472
577
|
result.concat explicit_return_values_from_compound_statement(node.children[2])
|
|
578
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
473
579
|
elsif node.type == :resbody
|
|
580
|
+
# @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
474
581
|
result.concat reduce_to_value_nodes([node.children[2]])
|
|
475
582
|
else
|
|
476
583
|
result.push node
|
|
@@ -484,3 +591,4 @@ module Solargraph
|
|
|
484
591
|
end
|
|
485
592
|
end
|
|
486
593
|
end
|
|
594
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
module Parser
|
|
5
|
-
module ParserGem
|
|
6
|
-
module NodeProcessors
|
|
7
|
-
class AliasNode < Parser::NodeProcessor::Base
|
|
8
|
-
def process
|
|
9
|
-
loc = get_node_location(node)
|
|
10
|
-
pins.push Solargraph::Pin::MethodAlias.new(
|
|
11
|
-
location: loc,
|
|
12
|
-
closure: region.closure,
|
|
13
|
-
name: node.children[0].children[0].to_s,
|
|
14
|
-
original: node.children[1].children[0].to_s,
|
|
15
|
-
scope: region.scope || :instance,
|
|
16
|
-
source: :parser
|
|
17
|
-
)
|
|
18
|
-
process_children
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Parser
|
|
5
|
+
module ParserGem
|
|
6
|
+
module NodeProcessors
|
|
7
|
+
class AliasNode < Parser::NodeProcessor::Base
|
|
8
|
+
def process
|
|
9
|
+
loc = get_node_location(node)
|
|
10
|
+
pins.push Solargraph::Pin::MethodAlias.new(
|
|
11
|
+
location: loc,
|
|
12
|
+
closure: region.closure,
|
|
13
|
+
name: node.children[0].children[0].to_s,
|
|
14
|
+
original: node.children[1].children[0].to_s,
|
|
15
|
+
scope: region.scope || :instance,
|
|
16
|
+
source: :parser
|
|
17
|
+
)
|
|
18
|
+
process_children
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -10,10 +10,10 @@ module Solargraph
|
|
|
10
10
|
def process
|
|
11
11
|
process_children
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
FlowSensitiveTyping.new(locals,
|
|
14
|
+
ivars,
|
|
15
|
+
enclosing_breakable_pin,
|
|
16
|
+
enclosing_compound_statement_pin).process_and(node)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -14,16 +14,17 @@ module Solargraph
|
|
|
14
14
|
node.children.each do |u|
|
|
15
15
|
loc = get_node_location(u)
|
|
16
16
|
locals.push Solargraph::Pin::Parameter.new(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
location: loc,
|
|
18
|
+
closure: callable,
|
|
19
|
+
comments: comments_for(node),
|
|
20
|
+
name: u.children[0].to_s,
|
|
21
|
+
assignment: u.children[1],
|
|
22
|
+
asgn_code: u.children[1] ? region.code_for(u.children[1]) : nil,
|
|
23
|
+
# @sg-ignore Need to add nil check here
|
|
24
|
+
presence: callable.location.range,
|
|
25
|
+
decl: get_decl(u),
|
|
26
|
+
source: :parser
|
|
27
|
+
)
|
|
27
28
|
callable.parameters.push locals.last
|
|
28
29
|
end
|
|
29
30
|
end
|
|
@@ -35,11 +36,12 @@ module Solargraph
|
|
|
35
36
|
|
|
36
37
|
# @param callable [Pin::Callable]
|
|
37
38
|
# @return [void]
|
|
38
|
-
def forward
|
|
39
|
+
def forward callable
|
|
39
40
|
loc = get_node_location(node)
|
|
40
41
|
locals.push Solargraph::Pin::Parameter.new(
|
|
41
42
|
location: loc,
|
|
42
43
|
closure: callable,
|
|
44
|
+
# @sg-ignore Need to add nil check here
|
|
43
45
|
presence: region.closure.location.range,
|
|
44
46
|
decl: get_decl(node),
|
|
45
47
|
source: :parser
|
|
@@ -6,6 +6,15 @@ module Solargraph
|
|
|
6
6
|
module NodeProcessors
|
|
7
7
|
class BeginNode < Parser::NodeProcessor::Base
|
|
8
8
|
def process
|
|
9
|
+
# We intentionally don't create a CompoundStatement pin
|
|
10
|
+
# here, as this is not necessarily a control flow block -
|
|
11
|
+
# e.g., a begin...end without rescue or ensure should be
|
|
12
|
+
# treated by flow sensitive typing as if the begin and end
|
|
13
|
+
# didn't exist at all. As such, we create the
|
|
14
|
+
# CompoundStatement pins around the things which actually
|
|
15
|
+
# result in control flow changes - like
|
|
16
|
+
# if/while/rescue/etc
|
|
17
|
+
|
|
9
18
|
process_children
|
|
10
19
|
end
|
|
11
20
|
end
|
|
@@ -9,23 +9,22 @@ module Solargraph
|
|
|
9
9
|
|
|
10
10
|
def process
|
|
11
11
|
location = get_node_location(node)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
else
|
|
20
|
-
region.closure
|
|
12
|
+
scope = region.scope || region.closure.context.scope
|
|
13
|
+
if other_class_eval?
|
|
14
|
+
clazz_name = unpack_name(node.children[0].children[0])
|
|
15
|
+
# instance variables should come from the Class<T> type
|
|
16
|
+
# - i.e., treated as class instance variables
|
|
17
|
+
context = ComplexType.try_parse("Class<#{clazz_name}>")
|
|
18
|
+
scope = :class
|
|
21
19
|
end
|
|
22
20
|
block_pin = Solargraph::Pin::Block.new(
|
|
23
21
|
location: location,
|
|
24
|
-
closure:
|
|
22
|
+
closure: region.closure,
|
|
25
23
|
node: node,
|
|
24
|
+
context: context,
|
|
26
25
|
receiver: node.children[0],
|
|
27
26
|
comments: comments_for(node),
|
|
28
|
-
scope:
|
|
27
|
+
scope: scope,
|
|
29
28
|
source: :parser
|
|
30
29
|
)
|
|
31
30
|
pins.push block_pin
|
|
@@ -37,7 +36,7 @@ module Solargraph
|
|
|
37
36
|
def other_class_eval?
|
|
38
37
|
node.children[0].type == :send &&
|
|
39
38
|
node.children[0].children[1] == :class_eval &&
|
|
40
|
-
[
|
|
39
|
+
%i[cbase const].include?(node.children[0].children[0]&.type)
|
|
41
40
|
end
|
|
42
41
|
end
|
|
43
42
|
end
|