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
|
@@ -5,11 +5,10 @@ module Solargraph
|
|
|
5
5
|
#
|
|
6
6
|
class TypeChecker
|
|
7
7
|
autoload :Problem, 'solargraph/type_checker/problem'
|
|
8
|
-
autoload :ParamDef, 'solargraph/type_checker/param_def'
|
|
9
8
|
autoload :Rules, 'solargraph/type_checker/rules'
|
|
10
|
-
autoload :Checks, 'solargraph/type_checker/checks'
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
# @!parse
|
|
11
|
+
# include Solargraph::Parser::ParserGem::NodeMethods
|
|
13
12
|
include Parser::NodeMethods
|
|
14
13
|
|
|
15
14
|
# @return [String]
|
|
@@ -26,8 +25,6 @@ module Solargraph
|
|
|
26
25
|
# @param level [Symbol] Don't complain about anything above this level
|
|
27
26
|
# @param workspace [Workspace, nil] Workspace to use for loading
|
|
28
27
|
# type checker rules modified by user config
|
|
29
|
-
# @param type_checker_rules [Hash{Symbol => Symbol}] Overrides for
|
|
30
|
-
# type checker rules - e.g., :report_undefined => :strong
|
|
31
28
|
# @param rules [Rules] Type checker rules object
|
|
32
29
|
def initialize filename,
|
|
33
30
|
api_map: nil,
|
|
@@ -36,7 +33,8 @@ module Solargraph
|
|
|
36
33
|
rules: workspace ? workspace.rules(level) : Rules.new(level, {})
|
|
37
34
|
@filename = filename
|
|
38
35
|
# @todo Smarter directory resolution
|
|
39
|
-
@api_map = api_map || Solargraph::ApiMap.load(File.dirname(filename)
|
|
36
|
+
@api_map = api_map || Solargraph::ApiMap.load(File.dirname(filename),
|
|
37
|
+
loose_unions: !rules.require_all_unique_types_support_call?)
|
|
40
38
|
@rules = rules
|
|
41
39
|
# @type [Array<Range>]
|
|
42
40
|
@marked_ranges = []
|
|
@@ -49,18 +47,51 @@ module Solargraph
|
|
|
49
47
|
|
|
50
48
|
# @return [Source]
|
|
51
49
|
def source
|
|
52
|
-
|
|
50
|
+
source_map.source
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @param inferred [ComplexType, ComplexType::UniqueType]
|
|
54
|
+
# @param expected [ComplexType, ComplexType::UniqueType]
|
|
55
|
+
def return_type_conforms_to? inferred, expected
|
|
56
|
+
conforms_to?(inferred, expected, :return_type)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param inferred [ComplexType, ComplexType::UniqueType]
|
|
60
|
+
# @param expected [ComplexType, ComplexType::UniqueType]
|
|
61
|
+
def arg_conforms_to? inferred, expected
|
|
62
|
+
conforms_to?(inferred, expected, :method_call)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @param inferred [ComplexType, ComplexType::UniqueType]
|
|
66
|
+
# @param expected [ComplexType, ComplexType::UniqueType]
|
|
67
|
+
def assignment_conforms_to? inferred, expected
|
|
68
|
+
conforms_to?(inferred, expected, :assignment)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @param inferred [ComplexType, ComplexType::UniqueType]
|
|
72
|
+
# @param expected [ComplexType, ComplexType::UniqueType]
|
|
73
|
+
# @param scenario [Symbol]
|
|
74
|
+
def conforms_to? inferred, expected, scenario
|
|
75
|
+
rules_arr = []
|
|
76
|
+
rules_arr << :allow_empty_params unless rules.require_inferred_type_params?
|
|
77
|
+
rules_arr << :allow_any_match unless rules.require_all_unique_types_match_expected?
|
|
78
|
+
rules_arr << :allow_undefined unless rules.require_no_undefined_args?
|
|
79
|
+
rules_arr << :allow_unresolved_generic unless rules.require_generics_resolved?
|
|
80
|
+
rules_arr << :allow_unmatched_interface unless rules.require_interfaces_resolved?
|
|
81
|
+
rules_arr << :allow_reverse_match unless rules.require_downcasts?
|
|
82
|
+
inferred.conforms_to?(api_map, expected, scenario,
|
|
83
|
+
rules_arr)
|
|
53
84
|
end
|
|
54
85
|
|
|
55
86
|
# @return [Array<Problem>]
|
|
56
87
|
def problems
|
|
57
88
|
@problems ||= begin
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
89
|
+
all = method_tag_problems
|
|
90
|
+
.concat(variable_type_tag_problems)
|
|
91
|
+
.concat(const_problems)
|
|
92
|
+
.concat(call_problems)
|
|
93
|
+
unignored = without_ignored(all)
|
|
94
|
+
unignored.concat(unneeded_sgignore_problems)
|
|
64
95
|
end
|
|
65
96
|
end
|
|
66
97
|
|
|
@@ -70,20 +101,26 @@ module Solargraph
|
|
|
70
101
|
# @return [self]
|
|
71
102
|
def load filename, level = :normal
|
|
72
103
|
source = Solargraph::Source.load(filename)
|
|
73
|
-
|
|
104
|
+
rules = Rules.new(level, {})
|
|
105
|
+
api_map = Solargraph::ApiMap.new(loose_unions:
|
|
106
|
+
!rules.require_all_unique_types_support_call?)
|
|
74
107
|
api_map.map(source)
|
|
75
|
-
new(filename, api_map: api_map, level: level)
|
|
108
|
+
new(filename, api_map: api_map, level: level, rules: rules)
|
|
76
109
|
end
|
|
77
110
|
|
|
78
111
|
# @param code [String]
|
|
79
112
|
# @param filename [String, nil]
|
|
80
113
|
# @param level [Symbol]
|
|
114
|
+
# @param api_map [Solargraph::ApiMap, nil]
|
|
81
115
|
# @return [self]
|
|
82
|
-
def load_string code, filename = nil, level = :normal
|
|
116
|
+
def load_string code, filename = nil, level = :normal, api_map: nil
|
|
83
117
|
source = Solargraph::Source.load_string(code, filename)
|
|
84
|
-
|
|
118
|
+
rules = Rules.new(level, {})
|
|
119
|
+
api_map ||= Solargraph::ApiMap.new(loose_unions:
|
|
120
|
+
!rules.require_all_unique_types_support_call?)
|
|
121
|
+
# @sg-ignore flow sensitive typing needs better handling of ||= on lvars
|
|
85
122
|
api_map.map(source)
|
|
86
|
-
new(filename, api_map: api_map, level: level)
|
|
123
|
+
new(filename, api_map: api_map, level: level, rules: rules)
|
|
87
124
|
end
|
|
88
125
|
end
|
|
89
126
|
|
|
@@ -107,13 +144,18 @@ module Solargraph
|
|
|
107
144
|
result = []
|
|
108
145
|
declared = pin.typify(api_map).self_to_type(pin.full_context).qualify(api_map, *pin.gates)
|
|
109
146
|
if declared.undefined?
|
|
147
|
+
# @sg-ignore Need to add nil check here
|
|
110
148
|
if pin.return_type.undefined? && rules.require_type_tags?
|
|
111
149
|
if pin.attribute?
|
|
112
150
|
inferred = pin.probe(api_map).self_to_type(pin.full_context)
|
|
113
|
-
|
|
151
|
+
unless inferred.defined?
|
|
152
|
+
result.push Problem.new(pin.location, "Missing @return tag for #{pin.path}",
|
|
153
|
+
pin: pin)
|
|
154
|
+
end
|
|
114
155
|
else
|
|
115
156
|
result.push Problem.new(pin.location, "Missing @return tag for #{pin.path}", pin: pin)
|
|
116
157
|
end
|
|
158
|
+
# @sg-ignore Need to add nil check here
|
|
117
159
|
elsif pin.return_type.defined? && !resolved_constant?(pin)
|
|
118
160
|
result.push Problem.new(pin.location, "Unresolved return type #{pin.return_type} for #{pin.path}", pin: pin)
|
|
119
161
|
elsif rules.must_tag_or_infer? && pin.probe(api_map).undefined?
|
|
@@ -127,8 +169,9 @@ module Solargraph
|
|
|
127
169
|
result.push Problem.new(pin.location, "#{pin.path} return type could not be inferred", pin: pin)
|
|
128
170
|
end
|
|
129
171
|
else
|
|
130
|
-
unless
|
|
131
|
-
result.push Problem.new(pin.location,
|
|
172
|
+
unless return_type_conforms_to?(inferred, declared)
|
|
173
|
+
result.push Problem.new(pin.location,
|
|
174
|
+
"Declared return type #{declared.rooted_tags} does not match inferred type #{inferred.rooted_tags} for #{pin.path}", pin: pin)
|
|
132
175
|
end
|
|
133
176
|
end
|
|
134
177
|
end
|
|
@@ -144,7 +187,7 @@ module Solargraph
|
|
|
144
187
|
def resolved_constant? pin
|
|
145
188
|
return true if pin.typify(api_map).defined?
|
|
146
189
|
constant_pins = api_map.get_constants('', *pin.closure.gates)
|
|
147
|
-
|
|
190
|
+
.select { |p| p.name == pin.return_type.namespace }
|
|
148
191
|
return true if constant_pins.find { |p| p.typify(api_map).defined? }
|
|
149
192
|
# will need to probe when a constant name is assigned to a
|
|
150
193
|
# class/module (alias)
|
|
@@ -154,6 +197,7 @@ module Solargraph
|
|
|
154
197
|
|
|
155
198
|
# @param pin [Pin::Base]
|
|
156
199
|
def virtual_pin? pin
|
|
200
|
+
# @sg-ignore Need to add nil check here
|
|
157
201
|
pin.location && source.comment_at?(pin.location.range.ending)
|
|
158
202
|
end
|
|
159
203
|
|
|
@@ -165,19 +209,19 @@ module Solargraph
|
|
|
165
209
|
pin.signatures.each do |sig|
|
|
166
210
|
params = param_details_from_stack(sig, stack)
|
|
167
211
|
if rules.require_type_tags?
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
|
175
|
-
end
|
|
176
|
-
else
|
|
212
|
+
sig.parameters.each do |par|
|
|
213
|
+
break if %i[restarg kwrestarg blockarg].include?(par.decl)
|
|
214
|
+
unless params[par.name]
|
|
215
|
+
if pin.attribute?
|
|
216
|
+
inferred = pin.probe(api_map).self_to_type(pin.full_context)
|
|
217
|
+
if inferred.undefined?
|
|
177
218
|
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
|
178
219
|
end
|
|
220
|
+
else
|
|
221
|
+
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
|
179
222
|
end
|
|
180
223
|
end
|
|
224
|
+
end
|
|
181
225
|
end
|
|
182
226
|
# @param name [String]
|
|
183
227
|
# @param data [Hash{Symbol => BasicObject}]
|
|
@@ -185,7 +229,8 @@ module Solargraph
|
|
|
185
229
|
# @type [ComplexType]
|
|
186
230
|
type = data[:qualified]
|
|
187
231
|
if type.undefined?
|
|
188
|
-
result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}",
|
|
232
|
+
result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}",
|
|
233
|
+
pin: pin)
|
|
189
234
|
end
|
|
190
235
|
end
|
|
191
236
|
end
|
|
@@ -201,6 +246,7 @@ module Solargraph
|
|
|
201
246
|
def variable_type_tag_problems
|
|
202
247
|
result = []
|
|
203
248
|
all_variables.each do |pin|
|
|
249
|
+
# @sg-ignore Need to add nil check here
|
|
204
250
|
if pin.return_type.defined?
|
|
205
251
|
declared = pin.typify(api_map)
|
|
206
252
|
next if declared.duck_type?
|
|
@@ -215,21 +261,21 @@ module Solargraph
|
|
|
215
261
|
result.push Problem.new(pin.location, "Variable type could not be inferred for #{pin.name}", pin: pin)
|
|
216
262
|
end
|
|
217
263
|
else
|
|
218
|
-
unless
|
|
219
|
-
result.push Problem.new(pin.location,
|
|
264
|
+
unless assignment_conforms_to?(inferred, declared)
|
|
265
|
+
result.push Problem.new(pin.location,
|
|
266
|
+
"Declared type #{declared} does not match inferred type #{inferred} for variable #{pin.name}", pin: pin)
|
|
220
267
|
end
|
|
221
268
|
end
|
|
222
269
|
elsif declared_externally?(pin)
|
|
223
270
|
ignored_pins.push pin
|
|
224
271
|
end
|
|
225
272
|
elsif !pin.is_a?(Pin::Parameter) && !resolved_constant?(pin)
|
|
226
|
-
result.push Problem.new(pin.location, "Unresolved type #{pin.return_type} for variable #{pin.name}",
|
|
273
|
+
result.push Problem.new(pin.location, "Unresolved type #{pin.return_type} for variable #{pin.name}",
|
|
274
|
+
pin: pin)
|
|
227
275
|
end
|
|
228
276
|
elsif pin.assignment
|
|
229
277
|
inferred = pin.probe(api_map)
|
|
230
|
-
if inferred.undefined? && declared_externally?(pin)
|
|
231
|
-
ignored_pins.push pin
|
|
232
|
-
end
|
|
278
|
+
ignored_pins.push pin if inferred.undefined? && declared_externally?(pin)
|
|
233
279
|
end
|
|
234
280
|
end
|
|
235
281
|
result
|
|
@@ -237,7 +283,7 @@ module Solargraph
|
|
|
237
283
|
|
|
238
284
|
# @return [Array<Pin::BaseVariable>]
|
|
239
285
|
def all_variables
|
|
240
|
-
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.
|
|
286
|
+
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.grep(Pin::LocalVariable)
|
|
241
287
|
end
|
|
242
288
|
|
|
243
289
|
# @return [Array<Problem>]
|
|
@@ -247,8 +293,10 @@ module Solargraph
|
|
|
247
293
|
Solargraph::Parser::NodeMethods.const_nodes_from(source.node).each do |const|
|
|
248
294
|
rng = Solargraph::Range.from_node(const)
|
|
249
295
|
chain = Solargraph::Parser.chain(const, filename)
|
|
296
|
+
# @sg-ignore Need to add nil check here
|
|
250
297
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
251
298
|
closure_pin.rebind(api_map)
|
|
299
|
+
# @sg-ignore Need to add nil check here
|
|
252
300
|
location = Location.new(filename, rng)
|
|
253
301
|
locals = source_map.locals_at(location)
|
|
254
302
|
pins = chain.define(api_map, closure_pin, locals)
|
|
@@ -265,44 +313,54 @@ module Solargraph
|
|
|
265
313
|
result = []
|
|
266
314
|
Solargraph::Parser::NodeMethods.call_nodes_from(source.node).each do |call|
|
|
267
315
|
rng = Solargraph::Range.from_node(call)
|
|
316
|
+
# @sg-ignore Need to add nil check here
|
|
268
317
|
next if @marked_ranges.any? { |d| d.contain?(rng.start) }
|
|
269
318
|
chain = Solargraph::Parser.chain(call, filename)
|
|
319
|
+
# @sg-ignore Need to add nil check here
|
|
270
320
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
271
|
-
namespace_pin = closure_pin
|
|
272
321
|
if call.type == :block
|
|
273
322
|
# blocks in the AST include the method call as well, so the
|
|
274
323
|
# node returned by #call_nodes_from needs to be backed out
|
|
275
324
|
# one closure
|
|
325
|
+
# @todo Need to add nil check here
|
|
326
|
+
# @todo Should warn on nil deference here
|
|
276
327
|
closure_pin = closure_pin.closure
|
|
277
328
|
end
|
|
329
|
+
# @sg-ignore Need to add nil check here
|
|
278
330
|
closure_pin.rebind(api_map)
|
|
331
|
+
# @sg-ignore Need to add nil check here
|
|
279
332
|
location = Location.new(filename, rng)
|
|
280
333
|
locals = source_map.locals_at(location)
|
|
334
|
+
# @sg-ignore Need to add nil check here
|
|
281
335
|
type = chain.infer(api_map, closure_pin, locals)
|
|
282
336
|
if type.undefined? && !rules.ignore_all_undefined?
|
|
283
337
|
base = chain
|
|
284
338
|
missing = chain
|
|
339
|
+
# @type [Solargraph::Pin::Base, nil]
|
|
285
340
|
found = nil
|
|
286
|
-
|
|
341
|
+
# @type [Array<Solargraph::Pin::Base>]
|
|
342
|
+
all_found = []
|
|
287
343
|
until base.links.first.undefined?
|
|
288
|
-
|
|
344
|
+
# @sg-ignore Need to add nil check here
|
|
345
|
+
all_found = base.define(api_map, closure_pin, locals)
|
|
346
|
+
found = all_found.first
|
|
289
347
|
break if found
|
|
290
348
|
missing = base
|
|
291
349
|
base = base.base
|
|
292
350
|
end
|
|
293
|
-
|
|
351
|
+
all_closest = all_found.map { |pin| pin.typify(api_map) }
|
|
352
|
+
closest = ComplexType.new(all_closest.flat_map(&:items).uniq)
|
|
294
353
|
# @todo remove the internal_or_core? check at a higher-than-strict level
|
|
295
|
-
if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
|
301
|
-
end
|
|
302
|
-
@marked_ranges.push rng
|
|
354
|
+
if (!found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))) && !(closest.generic? || ignored_pins.include?(found))
|
|
355
|
+
if closest.defined?
|
|
356
|
+
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word} on #{closest}")
|
|
357
|
+
else
|
|
358
|
+
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
|
303
359
|
end
|
|
360
|
+
@marked_ranges.push rng
|
|
304
361
|
end
|
|
305
362
|
end
|
|
363
|
+
# @sg-ignore Need to add nil check here
|
|
306
364
|
result.concat argument_problems_for(chain, api_map, closure_pin, locals, location)
|
|
307
365
|
end
|
|
308
366
|
result
|
|
@@ -311,13 +369,12 @@ module Solargraph
|
|
|
311
369
|
# @param chain [Solargraph::Source::Chain]
|
|
312
370
|
# @param api_map [Solargraph::ApiMap]
|
|
313
371
|
# @param closure_pin [Solargraph::Pin::Closure]
|
|
314
|
-
# @param locals [Array<Solargraph::Pin::
|
|
372
|
+
# @param locals [Array<Solargraph::Pin::LocalVariable>]
|
|
315
373
|
# @param location [Solargraph::Location]
|
|
316
374
|
# @return [Array<Problem>]
|
|
317
375
|
def argument_problems_for chain, api_map, closure_pin, locals, location
|
|
318
376
|
result = []
|
|
319
377
|
base = chain
|
|
320
|
-
# @type last_base_link [Solargraph::Source::Chain::Call]
|
|
321
378
|
last_base_link = base.links.last
|
|
322
379
|
return [] unless last_base_link.is_a?(Solargraph::Source::Chain::Call)
|
|
323
380
|
|
|
@@ -340,6 +397,8 @@ module Solargraph
|
|
|
340
397
|
base.base.infer(api_map, closure_pin, locals).namespace
|
|
341
398
|
end
|
|
342
399
|
init = api_map.get_method_stack(fqns, 'initialize').first
|
|
400
|
+
|
|
401
|
+
# @type [::Array<Solargraph::TypeChecker::Problem>]
|
|
343
402
|
init ? arity_problems_for(init, arguments, location) : []
|
|
344
403
|
else
|
|
345
404
|
arity_problems_for(pin, arguments, location)
|
|
@@ -348,7 +407,7 @@ module Solargraph
|
|
|
348
407
|
return [] if !rules.validate_calls? || base.links.first.is_a?(Solargraph::Source::Chain::ZSuper)
|
|
349
408
|
|
|
350
409
|
all_errors = []
|
|
351
|
-
pin.signatures.
|
|
410
|
+
pin.signatures.sort_by { |sig| sig.parameters.length }.each do |sig|
|
|
352
411
|
params = param_details_from_stack(sig, pins)
|
|
353
412
|
|
|
354
413
|
signature_errors = signature_argument_problems_for location, locals, closure_pin, params, arguments, sig, pin
|
|
@@ -368,11 +427,10 @@ module Solargraph
|
|
|
368
427
|
# @param location [Location]
|
|
369
428
|
# @param locals [Array<Pin::LocalVariable>]
|
|
370
429
|
# @param closure_pin [Pin::Closure]
|
|
371
|
-
# @param params [Hash{String =>
|
|
430
|
+
# @param params [Hash{String => undefined}]
|
|
372
431
|
# @param arguments [Array<Source::Chain>]
|
|
373
432
|
# @param sig [Pin::Signature]
|
|
374
433
|
# @param pin [Pin::Method]
|
|
375
|
-
# @param pins [Array<Pin::Method>]
|
|
376
434
|
#
|
|
377
435
|
# @return [Array<Problem>]
|
|
378
436
|
def signature_argument_problems_for location, locals, closure_pin, params, arguments, sig, pin
|
|
@@ -382,31 +440,25 @@ module Solargraph
|
|
|
382
440
|
# when possible, and when not, ensure provably
|
|
383
441
|
# incorrect situations are detected.
|
|
384
442
|
sig.parameters.each_with_index do |par, idx|
|
|
385
|
-
return errors if par.decl == :restarg
|
|
443
|
+
return errors if par.decl == :restarg # bail out and assume the rest is valid pending better arg processing
|
|
386
444
|
argchain = arguments[idx]
|
|
387
445
|
if argchain.nil?
|
|
446
|
+
final_arg = arguments.last
|
|
388
447
|
if par.decl == :arg
|
|
389
|
-
final_arg = arguments.last
|
|
390
448
|
if final_arg && final_arg.node.type == :splat
|
|
391
449
|
argchain = final_arg
|
|
392
450
|
return errors
|
|
393
451
|
else
|
|
394
452
|
errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
|
|
395
453
|
end
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
argchain = final_arg if final_arg && [:kwsplat, :hash].include?(final_arg.node.type)
|
|
454
|
+
elsif final_arg && %i[kwsplat hash].include?(final_arg.node.type)
|
|
455
|
+
argchain = final_arg
|
|
399
456
|
end
|
|
400
457
|
end
|
|
401
458
|
if argchain
|
|
402
|
-
if par.decl
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
else
|
|
406
|
-
if argchain.node.type == :splat && argchain == arguments.last
|
|
407
|
-
final_arg = argchain
|
|
408
|
-
end
|
|
409
|
-
if (final_arg && final_arg.node.type == :splat)
|
|
459
|
+
if par.decl == :arg
|
|
460
|
+
final_arg = argchain if argchain.node.type == :splat && argchain == arguments.last
|
|
461
|
+
if final_arg && final_arg.node.type == :splat
|
|
410
462
|
# The final argument given has been seen and was a
|
|
411
463
|
# splat, which doesn't give us useful types or
|
|
412
464
|
# arities against positional parameters, so let's
|
|
@@ -426,15 +478,19 @@ module Solargraph
|
|
|
426
478
|
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
|
427
479
|
ptype = ptype.self_to_type(par.context)
|
|
428
480
|
if ptype.nil?
|
|
429
|
-
|
|
481
|
+
# @todo Some level (strong, I guess) should require the param here
|
|
430
482
|
else
|
|
431
483
|
argtype = argchain.infer(api_map, closure_pin, locals)
|
|
432
484
|
argtype = argtype.self_to_type(closure_pin.context)
|
|
433
|
-
if argtype.defined? && ptype.defined? && !
|
|
434
|
-
errors.push Problem.new(location,
|
|
485
|
+
if argtype.defined? && ptype.defined? && !arg_conforms_to?(argtype, ptype)
|
|
486
|
+
errors.push Problem.new(location,
|
|
487
|
+
"Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
|
435
488
|
return errors
|
|
436
489
|
end
|
|
437
490
|
end
|
|
491
|
+
else
|
|
492
|
+
errors.concat kwarg_problems_for sig, argchain, api_map, closure_pin, locals, location, pin, params, idx
|
|
493
|
+
next
|
|
438
494
|
end
|
|
439
495
|
elsif par.decl == :kwarg
|
|
440
496
|
errors.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
|
@@ -445,13 +501,13 @@ module Solargraph
|
|
|
445
501
|
end
|
|
446
502
|
|
|
447
503
|
# @param sig [Pin::Signature]
|
|
448
|
-
# @param argchain [Source::Chain]
|
|
504
|
+
# @param argchain [Solargraph::Source::Chain]
|
|
449
505
|
# @param api_map [ApiMap]
|
|
450
506
|
# @param closure_pin [Pin::Closure]
|
|
451
507
|
# @param locals [Array<Pin::LocalVariable>]
|
|
452
508
|
# @param location [Location]
|
|
453
509
|
# @param pin [Pin::Method]
|
|
454
|
-
# @param params [Hash{String => Hash{Symbol =>
|
|
510
|
+
# @param params [Hash{String => Hash{Symbol => undefined}}]
|
|
455
511
|
# @param idx [Integer]
|
|
456
512
|
#
|
|
457
513
|
# @return [Array<Problem>]
|
|
@@ -459,29 +515,30 @@ module Solargraph
|
|
|
459
515
|
result = []
|
|
460
516
|
kwargs = convert_hash(argchain.node)
|
|
461
517
|
par = sig.parameters[idx]
|
|
518
|
+
# @type [Solargraph::Source::Chain]
|
|
462
519
|
argchain = kwargs[par.name.to_sym]
|
|
463
520
|
if par.decl == :kwrestarg || (par.decl == :optarg && idx == pin.parameters.length - 1 && par.asgn_code == '{}')
|
|
464
521
|
result.concat kwrestarg_problems_for(api_map, closure_pin, locals, location, pin, params, kwargs)
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
522
|
+
elsif argchain
|
|
523
|
+
data = params[par.name]
|
|
524
|
+
if data.nil?
|
|
525
|
+
# @todo Some level (strong, I guess) should require the param here
|
|
526
|
+
else
|
|
527
|
+
# @type [ComplexType, ComplexType::UniqueType]
|
|
528
|
+
ptype = data[:qualified]
|
|
529
|
+
ptype = ptype.self_to_type(pin.context)
|
|
530
|
+
unless ptype.undefined?
|
|
531
|
+
# @type [ComplexType]
|
|
532
|
+
argtype = argchain.infer(api_map, closure_pin, locals).self_to_type(closure_pin.context)
|
|
533
|
+
# @todo Unresolved call to defined?
|
|
534
|
+
if argtype.defined? && ptype && !arg_conforms_to?(argtype, ptype)
|
|
535
|
+
result.push Problem.new(location,
|
|
536
|
+
"Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
|
480
537
|
end
|
|
481
538
|
end
|
|
482
|
-
elsif par.decl == :kwarg
|
|
483
|
-
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
|
484
539
|
end
|
|
540
|
+
elsif par.decl == :kwarg
|
|
541
|
+
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
|
485
542
|
end
|
|
486
543
|
result
|
|
487
544
|
end
|
|
@@ -491,19 +548,22 @@ module Solargraph
|
|
|
491
548
|
# @param locals [Array<Pin::LocalVariable>]
|
|
492
549
|
# @param location [Location]
|
|
493
550
|
# @param pin [Pin::Method]
|
|
494
|
-
# @param params [Hash{String =>
|
|
551
|
+
# @param params [Hash{String => nil, Hash}]
|
|
495
552
|
# @param kwargs [Hash{Symbol => Source::Chain}]
|
|
496
553
|
# @return [Array<Problem>]
|
|
497
|
-
def kwrestarg_problems_for
|
|
554
|
+
def kwrestarg_problems_for api_map, closure_pin, locals, location, pin, params, kwargs
|
|
498
555
|
result = []
|
|
499
556
|
kwargs.each_pair do |pname, argchain|
|
|
500
557
|
next unless params.key?(pname.to_s)
|
|
501
|
-
|
|
502
|
-
|
|
558
|
+
# @sg-ignore
|
|
559
|
+
# @type [ComplexType]
|
|
560
|
+
raw_ptype = params[pname.to_s][:qualified]
|
|
561
|
+
ptype = raw_ptype.self_to_type(pin.context)
|
|
503
562
|
argtype = argchain.infer(api_map, closure_pin, locals)
|
|
504
563
|
argtype = argtype.self_to_type(closure_pin.context)
|
|
505
|
-
if argtype.defined? && ptype && !
|
|
506
|
-
result.push Problem.new(location,
|
|
564
|
+
if argtype.defined? && ptype && !arg_conforms_to?(argtype, ptype)
|
|
565
|
+
result.push Problem.new(location,
|
|
566
|
+
"Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
|
|
507
567
|
end
|
|
508
568
|
end
|
|
509
569
|
result
|
|
@@ -513,7 +573,7 @@ module Solargraph
|
|
|
513
573
|
# @param pin [Pin::Method, Pin::Signature]
|
|
514
574
|
# @param relevant_pin [Pin::Method, Pin::Signature] the pin which is under inspection
|
|
515
575
|
# @return [void]
|
|
516
|
-
def add_restkwarg_param_tag_details
|
|
576
|
+
def add_restkwarg_param_tag_details param_details, pin, relevant_pin
|
|
517
577
|
# see if we have additional tags to pay attention to from YARD -
|
|
518
578
|
# e.g., kwargs in a **restkwargs splat
|
|
519
579
|
tags = pin.docstring.tags(:param)
|
|
@@ -534,7 +594,7 @@ module Solargraph
|
|
|
534
594
|
|
|
535
595
|
# @param pin [Pin::Signature]
|
|
536
596
|
# @return [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
537
|
-
def signature_param_details
|
|
597
|
+
def signature_param_details pin
|
|
538
598
|
# @type [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
539
599
|
result = {}
|
|
540
600
|
pin.parameters.each do |param|
|
|
@@ -553,6 +613,7 @@ module Solargraph
|
|
|
553
613
|
next if tag.types.nil?
|
|
554
614
|
result[tag.name.to_s] = {
|
|
555
615
|
tagged: tag.types.join(', '),
|
|
616
|
+
# @sg-ignore need to add a nil check here
|
|
556
617
|
qualified: Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, *pin.closure.gates)
|
|
557
618
|
}
|
|
558
619
|
end
|
|
@@ -567,7 +628,7 @@ module Solargraph
|
|
|
567
628
|
# @param new_param_details [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
568
629
|
#
|
|
569
630
|
# @return [void]
|
|
570
|
-
def add_to_param_details
|
|
631
|
+
def add_to_param_details param_details, param_names, new_param_details
|
|
571
632
|
new_param_details.each do |param_name, details|
|
|
572
633
|
next unless param_names.include?(param_name)
|
|
573
634
|
|
|
@@ -580,7 +641,7 @@ module Solargraph
|
|
|
580
641
|
# @param signature [Pin::Signature]
|
|
581
642
|
# @param method_pin_stack [Array<Pin::Method>]
|
|
582
643
|
# @return [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
583
|
-
def param_details_from_stack
|
|
644
|
+
def param_details_from_stack signature, method_pin_stack
|
|
584
645
|
signature_type = signature.typify(api_map)
|
|
585
646
|
signature = signature.proxy signature_type
|
|
586
647
|
param_details = signature_param_details(signature)
|
|
@@ -602,6 +663,7 @@ module Solargraph
|
|
|
602
663
|
# @param pin [Pin::Base]
|
|
603
664
|
def internal? pin
|
|
604
665
|
return false if pin.nil?
|
|
666
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
605
667
|
pin.location && api_map.bundled?(pin.location.filename)
|
|
606
668
|
end
|
|
607
669
|
|
|
@@ -619,29 +681,32 @@ module Solargraph
|
|
|
619
681
|
|
|
620
682
|
# @param pin [Pin::BaseVariable]
|
|
621
683
|
def declared_externally? pin
|
|
622
|
-
raise
|
|
684
|
+
raise 'No assignment found' if pin.assignment.nil?
|
|
623
685
|
|
|
624
686
|
chain = Solargraph::Parser.chain(pin.assignment, filename)
|
|
687
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
625
688
|
rng = Solargraph::Range.from_node(pin.assignment)
|
|
689
|
+
# @sg-ignore Need to add nil check here
|
|
626
690
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
691
|
+
# @sg-ignore flow sensitive typing needs to handle "if foo.nil?"
|
|
627
692
|
location = Location.new(filename, Range.from_node(pin.assignment))
|
|
628
693
|
locals = source_map.locals_at(location)
|
|
629
694
|
type = chain.infer(api_map, closure_pin, locals)
|
|
630
695
|
if type.undefined? && !rules.ignore_all_undefined?
|
|
631
696
|
base = chain
|
|
632
|
-
|
|
697
|
+
# @type [Solargraph::Pin::Base, nil]
|
|
633
698
|
found = nil
|
|
634
|
-
|
|
699
|
+
# @type [Array<Solargraph::Pin::Base>]
|
|
700
|
+
all_found = []
|
|
635
701
|
until base.links.first.undefined?
|
|
636
|
-
|
|
702
|
+
all_found = base.define(api_map, closure_pin, locals)
|
|
703
|
+
found = all_found.first
|
|
637
704
|
break if found
|
|
638
|
-
missing = base
|
|
639
705
|
base = base.base
|
|
640
706
|
end
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
end
|
|
707
|
+
all_closest = all_found.map { |pin| pin.typify(api_map) }
|
|
708
|
+
closest = ComplexType.new(all_closest.flat_map(&:items).uniq)
|
|
709
|
+
return false if !found || closest.defined? || internal?(found)
|
|
645
710
|
end
|
|
646
711
|
true
|
|
647
712
|
end
|
|
@@ -664,7 +729,7 @@ module Solargraph
|
|
|
664
729
|
# @param arguments [Array<Source::Chain>]
|
|
665
730
|
# @param location [Location]
|
|
666
731
|
# @return [Array<Problem>]
|
|
667
|
-
def parameterized_arity_problems_for
|
|
732
|
+
def parameterized_arity_problems_for pin, parameters, arguments, location
|
|
668
733
|
return [] unless pin.explicit?
|
|
669
734
|
return [] if parameters.empty? && arguments.empty?
|
|
670
735
|
return [] if pin.anon_splat?
|
|
@@ -679,7 +744,7 @@ module Solargraph
|
|
|
679
744
|
settled_kwargs = parameters.count(&:keyword?)
|
|
680
745
|
else
|
|
681
746
|
kwargs = convert_hash(unchecked.last.node)
|
|
682
|
-
if parameters.any? { |param| [
|
|
747
|
+
if parameters.any? { |param| %i[kwarg kwoptarg].include?(param.decl) || param.kwrestarg? }
|
|
683
748
|
if kwargs.empty?
|
|
684
749
|
add_params += 1
|
|
685
750
|
else
|
|
@@ -708,10 +773,12 @@ module Solargraph
|
|
|
708
773
|
return [] if parameters.any?(&:rest?)
|
|
709
774
|
opt = optional_param_count(parameters)
|
|
710
775
|
return [] if unchecked.length <= req + opt
|
|
711
|
-
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) &&
|
|
776
|
+
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && parameters.map(&:decl).intersect?(%i[
|
|
777
|
+
kwarg kwoptarg kwrestarg
|
|
778
|
+
])
|
|
712
779
|
return []
|
|
713
780
|
end
|
|
714
|
-
return [] if arguments.length - req == parameters.select { |p| [
|
|
781
|
+
return [] if arguments.length - req == parameters.select { |p| %i[optarg kwoptarg].include?(p.decl) }.length
|
|
715
782
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
|
716
783
|
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || (!arguments.last.splat? && !arguments.last.links.last.is_a?(Solargraph::Source::Chain::Hash)))
|
|
717
784
|
# HACK: Kernel#raise signature is incorrect in Ruby 2.7 core docs.
|
|
@@ -727,42 +794,48 @@ module Solargraph
|
|
|
727
794
|
# @todo need to use generic types in method to choose correct
|
|
728
795
|
# signature and generate Integer as return type
|
|
729
796
|
# @return [Integer]
|
|
730
|
-
def required_param_count
|
|
797
|
+
def required_param_count parameters
|
|
731
798
|
parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
|
732
799
|
end
|
|
733
800
|
|
|
734
801
|
# @param parameters [Enumerable<Pin::Parameter>]
|
|
735
|
-
#
|
|
802
|
+
#
|
|
736
803
|
# @return [Integer]
|
|
737
|
-
def optional_param_count
|
|
804
|
+
def optional_param_count parameters
|
|
738
805
|
parameters.select { |p| p.decl == :optarg }.length
|
|
739
806
|
end
|
|
740
807
|
|
|
741
808
|
# @param pin [Pin::Method]
|
|
742
809
|
def abstract? pin
|
|
743
810
|
pin.docstring.has_tag?('abstract') ||
|
|
744
|
-
|
|
811
|
+
pin.closure&.docstring&.has_tag?('abstract')
|
|
745
812
|
end
|
|
746
813
|
|
|
747
814
|
# @param pin [Pin::Method]
|
|
748
815
|
# @return [Array<Source::Chain>]
|
|
749
|
-
def fake_args_for
|
|
816
|
+
def fake_args_for pin
|
|
750
817
|
args = []
|
|
751
818
|
with_opts = false
|
|
752
819
|
with_block = false
|
|
820
|
+
# @param pin [Pin::Parameter]
|
|
753
821
|
pin.parameters.each do |pin|
|
|
754
|
-
|
|
822
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
823
|
+
if %i[kwarg kwoptarg kwrestarg].include?(pin.decl)
|
|
755
824
|
with_opts = true
|
|
825
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
756
826
|
elsif pin.decl == :block
|
|
757
827
|
with_block = true
|
|
828
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
758
829
|
elsif pin.decl == :restarg
|
|
759
830
|
args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)], nil, true)
|
|
760
831
|
else
|
|
761
832
|
args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)])
|
|
762
833
|
end
|
|
763
834
|
end
|
|
764
|
-
|
|
765
|
-
|
|
835
|
+
pin_location = pin.location
|
|
836
|
+
starting_line = pin_location ? pin_location.range.start.line : 0
|
|
837
|
+
args.push Solargraph::Parser.chain_string('{}', filename, starting_line) if with_opts
|
|
838
|
+
args.push Solargraph::Parser.chain_string('&', filename, starting_line) if with_block
|
|
766
839
|
args
|
|
767
840
|
end
|
|
768
841
|
|
|
@@ -774,6 +847,7 @@ module Solargraph
|
|
|
774
847
|
# @return [Set<Integer>]
|
|
775
848
|
def all_sg_ignore_lines
|
|
776
849
|
source.associated_comments.select do |_line, text|
|
|
850
|
+
# @sg-ignore Need to add nil check here
|
|
777
851
|
text.include?('@sg-ignore')
|
|
778
852
|
end.keys.to_set
|
|
779
853
|
end
|