solargraph 0.58.3 → 0.60.3
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 +18 -28
- data/.github/workflows/typecheck.yml +6 -3
- data/.rubocop.yml +39 -6
- data/.rubocop_todo.yml +53 -966
- data/CHANGELOG.md +57 -0
- data/Gemfile +6 -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 +13 -4
- data/lib/solargraph/api_map/index.rb +42 -20
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +61 -36
- data/lib/solargraph/api_map.rb +191 -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 +225 -63
- data/lib/solargraph/complex_type.rb +177 -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 +39 -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 +63 -40
- 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 +222 -72
- 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 +64 -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 +157 -85
- 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 +67 -23
- data/lib/solargraph/pin/closure.rb +7 -10
- data/lib/solargraph/pin/common.rb +36 -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 +203 -111
- 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 +227 -238
- 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/rbs_translator.rb +206 -0
- data/lib/solargraph/server_methods.rb +1 -1
- data/lib/solargraph/shell.rb +330 -71
- 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 +92 -120
- 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 +19 -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 +71 -43
- 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 +30 -133
- data/lib/solargraph/source_map.rb +35 -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 +208 -125
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace/gemspecs.rb +373 -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/directives/attribute_directive.rb +65 -0
- data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
- data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
- data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
- data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
- data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
- data/lib/solargraph/yard_map/directives.rb +35 -0
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- data/lib/solargraph/yard_map/macro.rb +113 -0
- 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 +31 -8
- data/lib/solargraph/yard_map.rb +19 -18
- data/lib/solargraph/yard_tags.rb +2 -2
- data/lib/solargraph/yardoc.rb +7 -4
- data/lib/solargraph.rb +34 -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 +39 -35
- metadata +77 -41
- 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,28 +144,43 @@ 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?
|
|
120
162
|
result.push Problem.new(pin.location, "Untyped method #{pin.path} could not be inferred")
|
|
121
163
|
end
|
|
122
164
|
elsif rules.validate_tags?
|
|
123
|
-
|
|
165
|
+
# Attribute pins never have a node (attr_reader/attr_writer/attr_accessor are
|
|
166
|
+
# synthesized, not parsed method bodies), but their inferred type is still
|
|
167
|
+
# meaningful: #probe walks the backing ivar's assignments via infer_from_iv.
|
|
168
|
+
# Without this carve-out, a manually-written @return tag on an attribute is
|
|
169
|
+
# never cross-checked against how the ivar is actually assigned (e.g. a nilable
|
|
170
|
+
# default in the constructor), so a bad tag silently passes at every level.
|
|
171
|
+
unless (pin.node.nil? && !pin.attribute?) || declared.void? || virtual_pin?(pin) || abstract?(pin)
|
|
124
172
|
inferred = pin.probe(api_map).self_to_type(pin.full_context)
|
|
125
173
|
if inferred.undefined?
|
|
126
|
-
|
|
174
|
+
# An attribute with no locally-discoverable ivar assignment (set via a
|
|
175
|
+
# mixin, metaprogramming, etc.) isn't a tag/inference mismatch - just
|
|
176
|
+
# unproven. Only methods with an actual body get flagged for this.
|
|
177
|
+
unless rules.ignore_all_undefined? || external?(pin) || pin.attribute?
|
|
127
178
|
result.push Problem.new(pin.location, "#{pin.path} return type could not be inferred", pin: pin)
|
|
128
179
|
end
|
|
129
180
|
else
|
|
130
|
-
unless
|
|
131
|
-
result.push Problem.new(pin.location,
|
|
181
|
+
unless return_type_conforms_to?(inferred, declared)
|
|
182
|
+
result.push Problem.new(pin.location,
|
|
183
|
+
"Declared return type #{declared.rooted_tags} does not match inferred type #{inferred.rooted_tags} for #{pin.path}", pin: pin)
|
|
132
184
|
end
|
|
133
185
|
end
|
|
134
186
|
end
|
|
@@ -144,7 +196,7 @@ module Solargraph
|
|
|
144
196
|
def resolved_constant? pin
|
|
145
197
|
return true if pin.typify(api_map).defined?
|
|
146
198
|
constant_pins = api_map.get_constants('', *pin.closure.gates)
|
|
147
|
-
|
|
199
|
+
.select { |p| p.name == pin.return_type.namespace }
|
|
148
200
|
return true if constant_pins.find { |p| p.typify(api_map).defined? }
|
|
149
201
|
# will need to probe when a constant name is assigned to a
|
|
150
202
|
# class/module (alias)
|
|
@@ -154,6 +206,7 @@ module Solargraph
|
|
|
154
206
|
|
|
155
207
|
# @param pin [Pin::Base]
|
|
156
208
|
def virtual_pin? pin
|
|
209
|
+
# @sg-ignore Need to add nil check here
|
|
157
210
|
pin.location && source.comment_at?(pin.location.range.ending)
|
|
158
211
|
end
|
|
159
212
|
|
|
@@ -165,19 +218,19 @@ module Solargraph
|
|
|
165
218
|
pin.signatures.each do |sig|
|
|
166
219
|
params = param_details_from_stack(sig, stack)
|
|
167
220
|
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
|
|
221
|
+
sig.parameters.each do |par|
|
|
222
|
+
break if %i[restarg kwrestarg blockarg].include?(par.decl)
|
|
223
|
+
unless params[par.name]
|
|
224
|
+
if pin.attribute?
|
|
225
|
+
inferred = pin.probe(api_map).self_to_type(pin.full_context)
|
|
226
|
+
if inferred.undefined?
|
|
177
227
|
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
|
178
228
|
end
|
|
229
|
+
else
|
|
230
|
+
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
|
179
231
|
end
|
|
180
232
|
end
|
|
233
|
+
end
|
|
181
234
|
end
|
|
182
235
|
# @param name [String]
|
|
183
236
|
# @param data [Hash{Symbol => BasicObject}]
|
|
@@ -185,7 +238,8 @@ module Solargraph
|
|
|
185
238
|
# @type [ComplexType]
|
|
186
239
|
type = data[:qualified]
|
|
187
240
|
if type.undefined?
|
|
188
|
-
result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}",
|
|
241
|
+
result.push Problem.new(pin.location, "Unresolved type #{data[:tagged]} for #{name} param on #{pin.path}",
|
|
242
|
+
pin: pin)
|
|
189
243
|
end
|
|
190
244
|
end
|
|
191
245
|
end
|
|
@@ -201,6 +255,7 @@ module Solargraph
|
|
|
201
255
|
def variable_type_tag_problems
|
|
202
256
|
result = []
|
|
203
257
|
all_variables.each do |pin|
|
|
258
|
+
# @sg-ignore Need to add nil check here
|
|
204
259
|
if pin.return_type.defined?
|
|
205
260
|
declared = pin.typify(api_map)
|
|
206
261
|
next if declared.duck_type?
|
|
@@ -215,21 +270,21 @@ module Solargraph
|
|
|
215
270
|
result.push Problem.new(pin.location, "Variable type could not be inferred for #{pin.name}", pin: pin)
|
|
216
271
|
end
|
|
217
272
|
else
|
|
218
|
-
unless
|
|
219
|
-
result.push Problem.new(pin.location,
|
|
273
|
+
unless assignment_conforms_to?(inferred, declared)
|
|
274
|
+
result.push Problem.new(pin.location,
|
|
275
|
+
"Declared type #{declared} does not match inferred type #{inferred} for variable #{pin.name}", pin: pin)
|
|
220
276
|
end
|
|
221
277
|
end
|
|
222
278
|
elsif declared_externally?(pin)
|
|
223
279
|
ignored_pins.push pin
|
|
224
280
|
end
|
|
225
281
|
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}",
|
|
282
|
+
result.push Problem.new(pin.location, "Unresolved type #{pin.return_type} for variable #{pin.name}",
|
|
283
|
+
pin: pin)
|
|
227
284
|
end
|
|
228
285
|
elsif pin.assignment
|
|
229
286
|
inferred = pin.probe(api_map)
|
|
230
|
-
if inferred.undefined? && declared_externally?(pin)
|
|
231
|
-
ignored_pins.push pin
|
|
232
|
-
end
|
|
287
|
+
ignored_pins.push pin if inferred.undefined? && declared_externally?(pin)
|
|
233
288
|
end
|
|
234
289
|
end
|
|
235
290
|
result
|
|
@@ -237,7 +292,7 @@ module Solargraph
|
|
|
237
292
|
|
|
238
293
|
# @return [Array<Pin::BaseVariable>]
|
|
239
294
|
def all_variables
|
|
240
|
-
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.
|
|
295
|
+
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.grep(Pin::LocalVariable)
|
|
241
296
|
end
|
|
242
297
|
|
|
243
298
|
# @return [Array<Problem>]
|
|
@@ -247,8 +302,10 @@ module Solargraph
|
|
|
247
302
|
Solargraph::Parser::NodeMethods.const_nodes_from(source.node).each do |const|
|
|
248
303
|
rng = Solargraph::Range.from_node(const)
|
|
249
304
|
chain = Solargraph::Parser.chain(const, filename)
|
|
305
|
+
# @sg-ignore Need to add nil check here
|
|
250
306
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
251
307
|
closure_pin.rebind(api_map)
|
|
308
|
+
# @sg-ignore Need to add nil check here
|
|
252
309
|
location = Location.new(filename, rng)
|
|
253
310
|
locals = source_map.locals_at(location)
|
|
254
311
|
pins = chain.define(api_map, closure_pin, locals)
|
|
@@ -265,44 +322,54 @@ module Solargraph
|
|
|
265
322
|
result = []
|
|
266
323
|
Solargraph::Parser::NodeMethods.call_nodes_from(source.node).each do |call|
|
|
267
324
|
rng = Solargraph::Range.from_node(call)
|
|
325
|
+
# @sg-ignore Need to add nil check here
|
|
268
326
|
next if @marked_ranges.any? { |d| d.contain?(rng.start) }
|
|
269
327
|
chain = Solargraph::Parser.chain(call, filename)
|
|
328
|
+
# @sg-ignore Need to add nil check here
|
|
270
329
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
271
|
-
namespace_pin = closure_pin
|
|
272
330
|
if call.type == :block
|
|
273
331
|
# blocks in the AST include the method call as well, so the
|
|
274
332
|
# node returned by #call_nodes_from needs to be backed out
|
|
275
333
|
# one closure
|
|
334
|
+
# @todo Need to add nil check here
|
|
335
|
+
# @todo Should warn on nil deference here
|
|
276
336
|
closure_pin = closure_pin.closure
|
|
277
337
|
end
|
|
338
|
+
# @sg-ignore Need to add nil check here
|
|
278
339
|
closure_pin.rebind(api_map)
|
|
340
|
+
# @sg-ignore Need to add nil check here
|
|
279
341
|
location = Location.new(filename, rng)
|
|
280
342
|
locals = source_map.locals_at(location)
|
|
343
|
+
# @sg-ignore Need to add nil check here
|
|
281
344
|
type = chain.infer(api_map, closure_pin, locals)
|
|
282
345
|
if type.undefined? && !rules.ignore_all_undefined?
|
|
283
346
|
base = chain
|
|
284
347
|
missing = chain
|
|
348
|
+
# @type [Solargraph::Pin::Base, nil]
|
|
285
349
|
found = nil
|
|
286
|
-
|
|
350
|
+
# @type [Array<Solargraph::Pin::Base>]
|
|
351
|
+
all_found = []
|
|
287
352
|
until base.links.first.undefined?
|
|
288
|
-
|
|
353
|
+
# @sg-ignore Need to add nil check here
|
|
354
|
+
all_found = base.define(api_map, closure_pin, locals)
|
|
355
|
+
found = all_found.first
|
|
289
356
|
break if found
|
|
290
357
|
missing = base
|
|
291
358
|
base = base.base
|
|
292
359
|
end
|
|
293
|
-
|
|
360
|
+
all_closest = all_found.map { |pin| pin.typify(api_map) }
|
|
361
|
+
closest = ComplexType.new(all_closest.flat_map(&:items).uniq)
|
|
294
362
|
# @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
|
|
363
|
+
if (!found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))) && !(closest.generic? || ignored_pins.include?(found))
|
|
364
|
+
if closest.defined?
|
|
365
|
+
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word} on #{closest}")
|
|
366
|
+
else
|
|
367
|
+
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
|
303
368
|
end
|
|
369
|
+
@marked_ranges.push rng
|
|
304
370
|
end
|
|
305
371
|
end
|
|
372
|
+
# @sg-ignore Need to add nil check here
|
|
306
373
|
result.concat argument_problems_for(chain, api_map, closure_pin, locals, location)
|
|
307
374
|
end
|
|
308
375
|
result
|
|
@@ -311,13 +378,12 @@ module Solargraph
|
|
|
311
378
|
# @param chain [Solargraph::Source::Chain]
|
|
312
379
|
# @param api_map [Solargraph::ApiMap]
|
|
313
380
|
# @param closure_pin [Solargraph::Pin::Closure]
|
|
314
|
-
# @param locals [Array<Solargraph::Pin::
|
|
381
|
+
# @param locals [Array<Solargraph::Pin::LocalVariable>]
|
|
315
382
|
# @param location [Solargraph::Location]
|
|
316
383
|
# @return [Array<Problem>]
|
|
317
384
|
def argument_problems_for chain, api_map, closure_pin, locals, location
|
|
318
385
|
result = []
|
|
319
386
|
base = chain
|
|
320
|
-
# @type last_base_link [Solargraph::Source::Chain::Call]
|
|
321
387
|
last_base_link = base.links.last
|
|
322
388
|
return [] unless last_base_link.is_a?(Solargraph::Source::Chain::Call)
|
|
323
389
|
|
|
@@ -340,6 +406,8 @@ module Solargraph
|
|
|
340
406
|
base.base.infer(api_map, closure_pin, locals).namespace
|
|
341
407
|
end
|
|
342
408
|
init = api_map.get_method_stack(fqns, 'initialize').first
|
|
409
|
+
|
|
410
|
+
# @type [::Array<Solargraph::TypeChecker::Problem>]
|
|
343
411
|
init ? arity_problems_for(init, arguments, location) : []
|
|
344
412
|
else
|
|
345
413
|
arity_problems_for(pin, arguments, location)
|
|
@@ -348,7 +416,7 @@ module Solargraph
|
|
|
348
416
|
return [] if !rules.validate_calls? || base.links.first.is_a?(Solargraph::Source::Chain::ZSuper)
|
|
349
417
|
|
|
350
418
|
all_errors = []
|
|
351
|
-
pin.signatures.
|
|
419
|
+
pin.signatures.sort_by { |sig| sig.parameters.length }.each do |sig|
|
|
352
420
|
params = param_details_from_stack(sig, pins)
|
|
353
421
|
|
|
354
422
|
signature_errors = signature_argument_problems_for location, locals, closure_pin, params, arguments, sig, pin
|
|
@@ -368,11 +436,10 @@ module Solargraph
|
|
|
368
436
|
# @param location [Location]
|
|
369
437
|
# @param locals [Array<Pin::LocalVariable>]
|
|
370
438
|
# @param closure_pin [Pin::Closure]
|
|
371
|
-
# @param params [Hash{String =>
|
|
439
|
+
# @param params [Hash{String => undefined}]
|
|
372
440
|
# @param arguments [Array<Source::Chain>]
|
|
373
441
|
# @param sig [Pin::Signature]
|
|
374
442
|
# @param pin [Pin::Method]
|
|
375
|
-
# @param pins [Array<Pin::Method>]
|
|
376
443
|
#
|
|
377
444
|
# @return [Array<Problem>]
|
|
378
445
|
def signature_argument_problems_for location, locals, closure_pin, params, arguments, sig, pin
|
|
@@ -382,31 +449,25 @@ module Solargraph
|
|
|
382
449
|
# when possible, and when not, ensure provably
|
|
383
450
|
# incorrect situations are detected.
|
|
384
451
|
sig.parameters.each_with_index do |par, idx|
|
|
385
|
-
return errors if par.decl == :restarg
|
|
452
|
+
return errors if par.decl == :restarg # bail out and assume the rest is valid pending better arg processing
|
|
386
453
|
argchain = arguments[idx]
|
|
387
454
|
if argchain.nil?
|
|
455
|
+
final_arg = arguments.last
|
|
388
456
|
if par.decl == :arg
|
|
389
|
-
final_arg = arguments.last
|
|
390
457
|
if final_arg && final_arg.node.type == :splat
|
|
391
458
|
argchain = final_arg
|
|
392
459
|
return errors
|
|
393
460
|
else
|
|
394
461
|
errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
|
|
395
462
|
end
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
argchain = final_arg if final_arg && [:kwsplat, :hash].include?(final_arg.node.type)
|
|
463
|
+
elsif final_arg && %i[kwsplat hash].include?(final_arg.node.type)
|
|
464
|
+
argchain = final_arg
|
|
399
465
|
end
|
|
400
466
|
end
|
|
401
467
|
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)
|
|
468
|
+
if par.decl == :arg
|
|
469
|
+
final_arg = argchain if argchain.node.type == :splat && argchain == arguments.last
|
|
470
|
+
if final_arg && final_arg.node.type == :splat
|
|
410
471
|
# The final argument given has been seen and was a
|
|
411
472
|
# splat, which doesn't give us useful types or
|
|
412
473
|
# arities against positional parameters, so let's
|
|
@@ -426,15 +487,19 @@ module Solargraph
|
|
|
426
487
|
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
|
427
488
|
ptype = ptype.self_to_type(par.context)
|
|
428
489
|
if ptype.nil?
|
|
429
|
-
|
|
490
|
+
# @todo Some level (strong, I guess) should require the param here
|
|
430
491
|
else
|
|
431
492
|
argtype = argchain.infer(api_map, closure_pin, locals)
|
|
432
493
|
argtype = argtype.self_to_type(closure_pin.context)
|
|
433
|
-
if argtype.defined? && ptype.defined? && !
|
|
434
|
-
errors.push Problem.new(location,
|
|
494
|
+
if argtype.defined? && ptype.defined? && !arg_conforms_to?(argtype, ptype)
|
|
495
|
+
errors.push Problem.new(location,
|
|
496
|
+
"Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
|
435
497
|
return errors
|
|
436
498
|
end
|
|
437
499
|
end
|
|
500
|
+
else
|
|
501
|
+
errors.concat kwarg_problems_for sig, argchain, api_map, closure_pin, locals, location, pin, params, idx
|
|
502
|
+
next
|
|
438
503
|
end
|
|
439
504
|
elsif par.decl == :kwarg
|
|
440
505
|
errors.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
|
@@ -445,13 +510,13 @@ module Solargraph
|
|
|
445
510
|
end
|
|
446
511
|
|
|
447
512
|
# @param sig [Pin::Signature]
|
|
448
|
-
# @param argchain [Source::Chain]
|
|
513
|
+
# @param argchain [Solargraph::Source::Chain]
|
|
449
514
|
# @param api_map [ApiMap]
|
|
450
515
|
# @param closure_pin [Pin::Closure]
|
|
451
516
|
# @param locals [Array<Pin::LocalVariable>]
|
|
452
517
|
# @param location [Location]
|
|
453
518
|
# @param pin [Pin::Method]
|
|
454
|
-
# @param params [Hash{String => Hash{Symbol =>
|
|
519
|
+
# @param params [Hash{String => Hash{Symbol => undefined}}]
|
|
455
520
|
# @param idx [Integer]
|
|
456
521
|
#
|
|
457
522
|
# @return [Array<Problem>]
|
|
@@ -459,29 +524,30 @@ module Solargraph
|
|
|
459
524
|
result = []
|
|
460
525
|
kwargs = convert_hash(argchain.node)
|
|
461
526
|
par = sig.parameters[idx]
|
|
527
|
+
# @type [Solargraph::Source::Chain]
|
|
462
528
|
argchain = kwargs[par.name.to_sym]
|
|
463
529
|
if par.decl == :kwrestarg || (par.decl == :optarg && idx == pin.parameters.length - 1 && par.asgn_code == '{}')
|
|
464
530
|
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
|
-
|
|
531
|
+
elsif argchain
|
|
532
|
+
data = params[par.name]
|
|
533
|
+
if data.nil?
|
|
534
|
+
# @todo Some level (strong, I guess) should require the param here
|
|
535
|
+
else
|
|
536
|
+
# @type [ComplexType, ComplexType::UniqueType]
|
|
537
|
+
ptype = data[:qualified]
|
|
538
|
+
ptype = ptype.self_to_type(pin.context)
|
|
539
|
+
unless ptype.undefined?
|
|
540
|
+
# @type [ComplexType]
|
|
541
|
+
argtype = argchain.infer(api_map, closure_pin, locals).self_to_type(closure_pin.context)
|
|
542
|
+
# @todo Unresolved call to defined?
|
|
543
|
+
if argtype.defined? && ptype && !arg_conforms_to?(argtype, ptype)
|
|
544
|
+
result.push Problem.new(location,
|
|
545
|
+
"Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
|
480
546
|
end
|
|
481
547
|
end
|
|
482
|
-
elsif par.decl == :kwarg
|
|
483
|
-
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
|
484
548
|
end
|
|
549
|
+
elsif par.decl == :kwarg
|
|
550
|
+
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
|
485
551
|
end
|
|
486
552
|
result
|
|
487
553
|
end
|
|
@@ -491,19 +557,22 @@ module Solargraph
|
|
|
491
557
|
# @param locals [Array<Pin::LocalVariable>]
|
|
492
558
|
# @param location [Location]
|
|
493
559
|
# @param pin [Pin::Method]
|
|
494
|
-
# @param params [Hash{String =>
|
|
560
|
+
# @param params [Hash{String => nil, Hash}]
|
|
495
561
|
# @param kwargs [Hash{Symbol => Source::Chain}]
|
|
496
562
|
# @return [Array<Problem>]
|
|
497
|
-
def kwrestarg_problems_for
|
|
563
|
+
def kwrestarg_problems_for api_map, closure_pin, locals, location, pin, params, kwargs
|
|
498
564
|
result = []
|
|
499
565
|
kwargs.each_pair do |pname, argchain|
|
|
500
566
|
next unless params.key?(pname.to_s)
|
|
501
|
-
|
|
502
|
-
|
|
567
|
+
# @sg-ignore
|
|
568
|
+
# @type [ComplexType]
|
|
569
|
+
raw_ptype = params[pname.to_s][:qualified]
|
|
570
|
+
ptype = raw_ptype.self_to_type(pin.context)
|
|
503
571
|
argtype = argchain.infer(api_map, closure_pin, locals)
|
|
504
572
|
argtype = argtype.self_to_type(closure_pin.context)
|
|
505
|
-
if argtype.defined? && ptype && !
|
|
506
|
-
result.push Problem.new(location,
|
|
573
|
+
if argtype.defined? && ptype && !arg_conforms_to?(argtype, ptype)
|
|
574
|
+
result.push Problem.new(location,
|
|
575
|
+
"Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
|
|
507
576
|
end
|
|
508
577
|
end
|
|
509
578
|
result
|
|
@@ -513,7 +582,7 @@ module Solargraph
|
|
|
513
582
|
# @param pin [Pin::Method, Pin::Signature]
|
|
514
583
|
# @param relevant_pin [Pin::Method, Pin::Signature] the pin which is under inspection
|
|
515
584
|
# @return [void]
|
|
516
|
-
def add_restkwarg_param_tag_details
|
|
585
|
+
def add_restkwarg_param_tag_details param_details, pin, relevant_pin
|
|
517
586
|
# see if we have additional tags to pay attention to from YARD -
|
|
518
587
|
# e.g., kwargs in a **restkwargs splat
|
|
519
588
|
tags = pin.docstring.tags(:param)
|
|
@@ -534,7 +603,7 @@ module Solargraph
|
|
|
534
603
|
|
|
535
604
|
# @param pin [Pin::Signature]
|
|
536
605
|
# @return [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
537
|
-
def signature_param_details
|
|
606
|
+
def signature_param_details pin
|
|
538
607
|
# @type [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
539
608
|
result = {}
|
|
540
609
|
pin.parameters.each do |param|
|
|
@@ -553,6 +622,7 @@ module Solargraph
|
|
|
553
622
|
next if tag.types.nil?
|
|
554
623
|
result[tag.name.to_s] = {
|
|
555
624
|
tagged: tag.types.join(', '),
|
|
625
|
+
# @sg-ignore need to add a nil check here
|
|
556
626
|
qualified: Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, *pin.closure.gates)
|
|
557
627
|
}
|
|
558
628
|
end
|
|
@@ -567,7 +637,7 @@ module Solargraph
|
|
|
567
637
|
# @param new_param_details [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
568
638
|
#
|
|
569
639
|
# @return [void]
|
|
570
|
-
def add_to_param_details
|
|
640
|
+
def add_to_param_details param_details, param_names, new_param_details
|
|
571
641
|
new_param_details.each do |param_name, details|
|
|
572
642
|
next unless param_names.include?(param_name)
|
|
573
643
|
|
|
@@ -580,7 +650,7 @@ module Solargraph
|
|
|
580
650
|
# @param signature [Pin::Signature]
|
|
581
651
|
# @param method_pin_stack [Array<Pin::Method>]
|
|
582
652
|
# @return [Hash{String => Hash{Symbol => String, ComplexType}}]
|
|
583
|
-
def param_details_from_stack
|
|
653
|
+
def param_details_from_stack signature, method_pin_stack
|
|
584
654
|
signature_type = signature.typify(api_map)
|
|
585
655
|
signature = signature.proxy signature_type
|
|
586
656
|
param_details = signature_param_details(signature)
|
|
@@ -602,6 +672,7 @@ module Solargraph
|
|
|
602
672
|
# @param pin [Pin::Base]
|
|
603
673
|
def internal? pin
|
|
604
674
|
return false if pin.nil?
|
|
675
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
605
676
|
pin.location && api_map.bundled?(pin.location.filename)
|
|
606
677
|
end
|
|
607
678
|
|
|
@@ -619,29 +690,32 @@ module Solargraph
|
|
|
619
690
|
|
|
620
691
|
# @param pin [Pin::BaseVariable]
|
|
621
692
|
def declared_externally? pin
|
|
622
|
-
raise
|
|
693
|
+
raise 'No assignment found' if pin.assignment.nil?
|
|
623
694
|
|
|
624
695
|
chain = Solargraph::Parser.chain(pin.assignment, filename)
|
|
696
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
625
697
|
rng = Solargraph::Range.from_node(pin.assignment)
|
|
698
|
+
# @sg-ignore Need to add nil check here
|
|
626
699
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
700
|
+
# @sg-ignore flow sensitive typing needs to handle "if foo.nil?"
|
|
627
701
|
location = Location.new(filename, Range.from_node(pin.assignment))
|
|
628
702
|
locals = source_map.locals_at(location)
|
|
629
703
|
type = chain.infer(api_map, closure_pin, locals)
|
|
630
704
|
if type.undefined? && !rules.ignore_all_undefined?
|
|
631
705
|
base = chain
|
|
632
|
-
|
|
706
|
+
# @type [Solargraph::Pin::Base, nil]
|
|
633
707
|
found = nil
|
|
634
|
-
|
|
708
|
+
# @type [Array<Solargraph::Pin::Base>]
|
|
709
|
+
all_found = []
|
|
635
710
|
until base.links.first.undefined?
|
|
636
|
-
|
|
711
|
+
all_found = base.define(api_map, closure_pin, locals)
|
|
712
|
+
found = all_found.first
|
|
637
713
|
break if found
|
|
638
|
-
missing = base
|
|
639
714
|
base = base.base
|
|
640
715
|
end
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
end
|
|
716
|
+
all_closest = all_found.map { |pin| pin.typify(api_map) }
|
|
717
|
+
closest = ComplexType.new(all_closest.flat_map(&:items).uniq)
|
|
718
|
+
return false if !found || closest.defined? || internal?(found)
|
|
645
719
|
end
|
|
646
720
|
true
|
|
647
721
|
end
|
|
@@ -664,7 +738,7 @@ module Solargraph
|
|
|
664
738
|
# @param arguments [Array<Source::Chain>]
|
|
665
739
|
# @param location [Location]
|
|
666
740
|
# @return [Array<Problem>]
|
|
667
|
-
def parameterized_arity_problems_for
|
|
741
|
+
def parameterized_arity_problems_for pin, parameters, arguments, location
|
|
668
742
|
return [] unless pin.explicit?
|
|
669
743
|
return [] if parameters.empty? && arguments.empty?
|
|
670
744
|
return [] if pin.anon_splat?
|
|
@@ -679,7 +753,7 @@ module Solargraph
|
|
|
679
753
|
settled_kwargs = parameters.count(&:keyword?)
|
|
680
754
|
else
|
|
681
755
|
kwargs = convert_hash(unchecked.last.node)
|
|
682
|
-
if parameters.any? { |param| [
|
|
756
|
+
if parameters.any? { |param| %i[kwarg kwoptarg].include?(param.decl) || param.kwrestarg? }
|
|
683
757
|
if kwargs.empty?
|
|
684
758
|
add_params += 1
|
|
685
759
|
else
|
|
@@ -708,10 +782,12 @@ module Solargraph
|
|
|
708
782
|
return [] if parameters.any?(&:rest?)
|
|
709
783
|
opt = optional_param_count(parameters)
|
|
710
784
|
return [] if unchecked.length <= req + opt
|
|
711
|
-
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) &&
|
|
785
|
+
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && parameters.map(&:decl).intersect?(%i[
|
|
786
|
+
kwarg kwoptarg kwrestarg
|
|
787
|
+
])
|
|
712
788
|
return []
|
|
713
789
|
end
|
|
714
|
-
return [] if arguments.length - req == parameters.select { |p| [
|
|
790
|
+
return [] if arguments.length - req == parameters.select { |p| %i[optarg kwoptarg].include?(p.decl) }.length
|
|
715
791
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
|
716
792
|
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || (!arguments.last.splat? && !arguments.last.links.last.is_a?(Solargraph::Source::Chain::Hash)))
|
|
717
793
|
# HACK: Kernel#raise signature is incorrect in Ruby 2.7 core docs.
|
|
@@ -727,42 +803,48 @@ module Solargraph
|
|
|
727
803
|
# @todo need to use generic types in method to choose correct
|
|
728
804
|
# signature and generate Integer as return type
|
|
729
805
|
# @return [Integer]
|
|
730
|
-
def required_param_count
|
|
806
|
+
def required_param_count parameters
|
|
731
807
|
parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
|
732
808
|
end
|
|
733
809
|
|
|
734
810
|
# @param parameters [Enumerable<Pin::Parameter>]
|
|
735
|
-
#
|
|
811
|
+
#
|
|
736
812
|
# @return [Integer]
|
|
737
|
-
def optional_param_count
|
|
813
|
+
def optional_param_count parameters
|
|
738
814
|
parameters.select { |p| p.decl == :optarg }.length
|
|
739
815
|
end
|
|
740
816
|
|
|
741
817
|
# @param pin [Pin::Method]
|
|
742
818
|
def abstract? pin
|
|
743
819
|
pin.docstring.has_tag?('abstract') ||
|
|
744
|
-
|
|
820
|
+
pin.closure&.docstring&.has_tag?('abstract')
|
|
745
821
|
end
|
|
746
822
|
|
|
747
823
|
# @param pin [Pin::Method]
|
|
748
824
|
# @return [Array<Source::Chain>]
|
|
749
|
-
def fake_args_for
|
|
825
|
+
def fake_args_for pin
|
|
750
826
|
args = []
|
|
751
827
|
with_opts = false
|
|
752
828
|
with_block = false
|
|
829
|
+
# @param pin [Pin::Parameter]
|
|
753
830
|
pin.parameters.each do |pin|
|
|
754
|
-
|
|
831
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
832
|
+
if %i[kwarg kwoptarg kwrestarg].include?(pin.decl)
|
|
755
833
|
with_opts = true
|
|
834
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
756
835
|
elsif pin.decl == :block
|
|
757
836
|
with_block = true
|
|
837
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
758
838
|
elsif pin.decl == :restarg
|
|
759
839
|
args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)], nil, true)
|
|
760
840
|
else
|
|
761
841
|
args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)])
|
|
762
842
|
end
|
|
763
843
|
end
|
|
764
|
-
|
|
765
|
-
|
|
844
|
+
pin_location = pin.location
|
|
845
|
+
starting_line = pin_location ? pin_location.range.start.line : 0
|
|
846
|
+
args.push Solargraph::Parser.chain_string('{}', filename, starting_line) if with_opts
|
|
847
|
+
args.push Solargraph::Parser.chain_string('&', filename, starting_line) if with_block
|
|
766
848
|
args
|
|
767
849
|
end
|
|
768
850
|
|
|
@@ -774,7 +856,8 @@ module Solargraph
|
|
|
774
856
|
# @return [Set<Integer>]
|
|
775
857
|
def all_sg_ignore_lines
|
|
776
858
|
source.associated_comments.select do |_line, text|
|
|
777
|
-
|
|
859
|
+
# @sg-ignore Need to add nil check here
|
|
860
|
+
text.any? { |t| t.include?('@sg-ignore') }
|
|
778
861
|
end.keys.to_set
|
|
779
862
|
end
|
|
780
863
|
|