solargraph 0.58.2 → 0.59.0.dev.1
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 +4 -5
- data/.github/workflows/plugins.yml +40 -36
- data/.github/workflows/rspec.yml +45 -13
- data/.github/workflows/typecheck.yml +2 -2
- data/.gitignore +0 -1
- data/.rubocop_todo.yml +27 -49
- data/CHANGELOG.md +1 -7
- data/README.md +3 -3
- data/Rakefile +1 -0
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +13 -3
- data/lib/solargraph/api_map/index.rb +22 -11
- data/lib/solargraph/api_map/source_to_yard.rb +13 -1
- data/lib/solargraph/api_map/store.rb +11 -8
- data/lib/solargraph/api_map.rb +105 -50
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +16 -2
- data/lib/solargraph/complex_type/unique_type.rb +170 -20
- data/lib/solargraph/complex_type.rb +119 -14
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
- data/lib/solargraph/convention/data_definition.rb +4 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition.rb +5 -1
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/doc_map.rb +134 -373
- data/lib/solargraph/equality.rb +1 -1
- data/lib/solargraph/gem_pins.rb +14 -15
- data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
- data/lib/solargraph/language_server/host/dispatch.rb +1 -0
- data/lib/solargraph/language_server/host/message_worker.rb +2 -1
- data/lib/solargraph/language_server/host/sources.rb +1 -0
- data/lib/solargraph/language_server/host.rb +6 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
- data/lib/solargraph/library.rb +59 -13
- data/lib/solargraph/location.rb +9 -4
- data/lib/solargraph/logging.rb +21 -1
- data/lib/solargraph/parser/comment_ripper.rb +7 -0
- data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
- data/lib/solargraph/parser/node_processor/base.rb +32 -2
- data/lib/solargraph/parser/node_processor.rb +7 -6
- data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
- data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
- 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 -11
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
- 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/opasgn_node.rb +2 -2
- 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 +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +1 -1
- data/lib/solargraph/pin/base.rb +53 -21
- data/lib/solargraph/pin/base_variable.rb +312 -20
- data/lib/solargraph/pin/block.rb +26 -4
- data/lib/solargraph/pin/breakable.rb +5 -1
- data/lib/solargraph/pin/callable.rb +50 -3
- data/lib/solargraph/pin/closure.rb +2 -6
- data/lib/solargraph/pin/common.rb +20 -5
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/conversions.rb +2 -1
- data/lib/solargraph/pin/delegated_method.rb +15 -4
- data/lib/solargraph/pin/documenting.rb +1 -0
- data/lib/solargraph/pin/instance_variable.rb +5 -1
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/local_variable.rb +13 -57
- data/lib/solargraph/pin/method.rb +90 -42
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +7 -1
- data/lib/solargraph/pin/parameter.rb +76 -13
- data/lib/solargraph/pin/proxy_type.rb +2 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference.rb +2 -0
- data/lib/solargraph/pin/search.rb +1 -0
- data/lib/solargraph/pin/signature.rb +8 -0
- data/lib/solargraph/pin/symbol.rb +1 -1
- data/lib/solargraph/pin/until.rb +1 -1
- data/lib/solargraph/pin/while.rb +1 -1
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +477 -57
- data/lib/solargraph/position.rb +12 -26
- data/lib/solargraph/range.rb +6 -6
- data/lib/solargraph/rbs_map/conversions.rb +33 -10
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
- data/lib/solargraph/rbs_map.rb +74 -20
- data/lib/solargraph/shell.rb +73 -28
- data/lib/solargraph/source/chain/call.rb +52 -17
- data/lib/solargraph/source/chain/constant.rb +2 -0
- data/lib/solargraph/source/chain/hash.rb +1 -0
- data/lib/solargraph/source/chain/if.rb +1 -0
- data/lib/solargraph/source/chain/instance_variable.rb +22 -1
- data/lib/solargraph/source/chain/literal.rb +5 -0
- data/lib/solargraph/source/chain/or.rb +9 -1
- data/lib/solargraph/source/chain.rb +25 -22
- data/lib/solargraph/source/change.rb +9 -2
- data/lib/solargraph/source/cursor.rb +7 -1
- data/lib/solargraph/source/source_chainer.rb +13 -3
- data/lib/solargraph/source/updater.rb +4 -0
- data/lib/solargraph/source.rb +33 -7
- data/lib/solargraph/source_map/clip.rb +13 -2
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +24 -1
- data/lib/solargraph/source_map.rb +14 -6
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +75 -2
- data/lib/solargraph/type_checker.rb +111 -30
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +3 -1
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +158 -16
- data/lib/solargraph/yard_map/helpers.rb +2 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/mapper.rb +5 -0
- data/lib/solargraph/yardoc.rb +33 -23
- data/lib/solargraph.rb +24 -3
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -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 +2 -1
- metadata +12 -7
- 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
|
@@ -60,8 +60,81 @@ module Solargraph
|
|
|
60
60
|
report?(:validate_tags, :typed)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def
|
|
64
|
-
report?(:
|
|
63
|
+
def require_inferred_type_params?
|
|
64
|
+
report?(:require_inferred_type_params, :alpha)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
#
|
|
68
|
+
# False negatives:
|
|
69
|
+
#
|
|
70
|
+
# @todo 4: Missed nil violation
|
|
71
|
+
#
|
|
72
|
+
# pending code fixes (277):
|
|
73
|
+
#
|
|
74
|
+
# @todo 281: Need to add nil check here
|
|
75
|
+
# @todo 22: Translate to something flow sensitive typing understands
|
|
76
|
+
# @todo 3: Need a downcast here
|
|
77
|
+
#
|
|
78
|
+
# flow sensitive typing could handle (96):
|
|
79
|
+
#
|
|
80
|
+
# @todo 36: flow sensitive typing needs to handle attrs
|
|
81
|
+
# @todo 29: flow sensitive typing should be able to handle redefinition
|
|
82
|
+
# @todo 19: flow sensitive typing needs to narrow down type with an if is_a? check
|
|
83
|
+
# @todo 13: Need to validate config
|
|
84
|
+
# @todo 8: flow sensitive typing should support .class == .class
|
|
85
|
+
# @todo 6: need boolish support for ? methods
|
|
86
|
+
# @todo 5: literal arrays in this module turn into ::Solargraph::Source::Chain::Array
|
|
87
|
+
# @todo 5: flow sensitive typing needs to handle 'raise if'
|
|
88
|
+
# @todo 5: flow sensitive typing needs better handling of ||= on lvars
|
|
89
|
+
# @todo 4: flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
90
|
+
# @todo 4: nil? support in flow sensitive typing
|
|
91
|
+
# @todo 2: downcast output of Enumerable#select
|
|
92
|
+
# @todo 2: flow sensitive typing should handle return nil if location&.name.nil?
|
|
93
|
+
# @todo 2: flow sensitive typing should handle is_a? and next
|
|
94
|
+
# @todo 2: Need to look at Tuple#include? handling
|
|
95
|
+
# @todo 2: Should better support meaning of '&' in RBS
|
|
96
|
+
# @todo 2: (*) flow sensitive typing needs to handle "if foo = bar"
|
|
97
|
+
# @todo 2: flow sensitive typing needs to handle "if foo = bar"
|
|
98
|
+
# @todo 2: Need to handle duck-typed method calls on union types
|
|
99
|
+
# @todo 2: Need better handling of #compact
|
|
100
|
+
# @todo 2: flow sensitive typing should allow shadowing of Kernel#caller
|
|
101
|
+
# @todo 2: flow sensitive typing ought to be able to handle 'when ClassName'
|
|
102
|
+
# @todo 1: flow sensitive typing not smart enough to handle this case
|
|
103
|
+
# @todo 1: flow sensitive typing needs to handle if foo = bar
|
|
104
|
+
# @todo 1: flow sensitive typing needs to handle "if foo.nil?"
|
|
105
|
+
# @todo 1: flow sensitive typing should support case/when
|
|
106
|
+
# @todo 1: flow sensitive typing should support ivars
|
|
107
|
+
# @todo 1: Need to support this in flow sensitive typing
|
|
108
|
+
# @todo 1: flow sensitive typing needs to handle self.class == other.class
|
|
109
|
+
# @todo 1: flow sensitive typing needs to remove literal with
|
|
110
|
+
# @todo 1: flow sensitive typing needs to understand reassignment
|
|
111
|
+
# @todo 1: flow sensitive typing should be able to identify more blocks that always return
|
|
112
|
+
# @todo 1: should warn on nil dereference below
|
|
113
|
+
# @todo 1: flow sensitive typing needs to create separate ranges for postfix if
|
|
114
|
+
# @todo 1: flow sensitive typing needs to handle constants
|
|
115
|
+
# @todo 1: flow sensitive typing needs to eliminate literal from union with return if foo == :bar
|
|
116
|
+
def require_all_unique_types_match_expected?
|
|
117
|
+
report?(:require_all_unique_types_match_expected, :strong)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def require_all_unique_types_support_call?
|
|
121
|
+
report?(:require_all_unique_types_support_call, :strong)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def require_no_undefined_args?
|
|
125
|
+
report?(:require_no_undefined_args, :alpha)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def require_generics_resolved?
|
|
129
|
+
report?(:require_generics_resolved, :alpha)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def require_interfaces_resolved?
|
|
133
|
+
report?(:require_interfaces_resolved, :alpha)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def require_downcasts?
|
|
137
|
+
report?(:require_downcasts, :alpha)
|
|
65
138
|
end
|
|
66
139
|
|
|
67
140
|
# We keep this at strong because if you added an @ sg-ignore to
|
|
@@ -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,7 +47,40 @@ 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>]
|
|
@@ -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,6 +144,7 @@ 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)
|
|
@@ -114,6 +152,7 @@ module Solargraph
|
|
|
114
152
|
else
|
|
115
153
|
result.push Problem.new(pin.location, "Missing @return tag for #{pin.path}", pin: pin)
|
|
116
154
|
end
|
|
155
|
+
# @sg-ignore Need to add nil check here
|
|
117
156
|
elsif pin.return_type.defined? && !resolved_constant?(pin)
|
|
118
157
|
result.push Problem.new(pin.location, "Unresolved return type #{pin.return_type} for #{pin.path}", pin: pin)
|
|
119
158
|
elsif rules.must_tag_or_infer? && pin.probe(api_map).undefined?
|
|
@@ -127,7 +166,7 @@ module Solargraph
|
|
|
127
166
|
result.push Problem.new(pin.location, "#{pin.path} return type could not be inferred", pin: pin)
|
|
128
167
|
end
|
|
129
168
|
else
|
|
130
|
-
unless
|
|
169
|
+
unless return_type_conforms_to?(inferred, declared)
|
|
131
170
|
result.push Problem.new(pin.location, "Declared return type #{declared.rooted_tags} does not match inferred type #{inferred.rooted_tags} for #{pin.path}", pin: pin)
|
|
132
171
|
end
|
|
133
172
|
end
|
|
@@ -154,6 +193,7 @@ module Solargraph
|
|
|
154
193
|
|
|
155
194
|
# @param pin [Pin::Base]
|
|
156
195
|
def virtual_pin? pin
|
|
196
|
+
# @sg-ignore Need to add nil check here
|
|
157
197
|
pin.location && source.comment_at?(pin.location.range.ending)
|
|
158
198
|
end
|
|
159
199
|
|
|
@@ -201,6 +241,7 @@ module Solargraph
|
|
|
201
241
|
def variable_type_tag_problems
|
|
202
242
|
result = []
|
|
203
243
|
all_variables.each do |pin|
|
|
244
|
+
# @sg-ignore Need to add nil check here
|
|
204
245
|
if pin.return_type.defined?
|
|
205
246
|
declared = pin.typify(api_map)
|
|
206
247
|
next if declared.duck_type?
|
|
@@ -215,7 +256,7 @@ module Solargraph
|
|
|
215
256
|
result.push Problem.new(pin.location, "Variable type could not be inferred for #{pin.name}", pin: pin)
|
|
216
257
|
end
|
|
217
258
|
else
|
|
218
|
-
unless
|
|
259
|
+
unless assignment_conforms_to?(inferred, declared)
|
|
219
260
|
result.push Problem.new(pin.location, "Declared type #{declared} does not match inferred type #{inferred} for variable #{pin.name}", pin: pin)
|
|
220
261
|
end
|
|
221
262
|
end
|
|
@@ -247,8 +288,10 @@ module Solargraph
|
|
|
247
288
|
Solargraph::Parser::NodeMethods.const_nodes_from(source.node).each do |const|
|
|
248
289
|
rng = Solargraph::Range.from_node(const)
|
|
249
290
|
chain = Solargraph::Parser.chain(const, filename)
|
|
291
|
+
# @sg-ignore Need to add nil check here
|
|
250
292
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
251
293
|
closure_pin.rebind(api_map)
|
|
294
|
+
# @sg-ignore Need to add nil check here
|
|
252
295
|
location = Location.new(filename, rng)
|
|
253
296
|
locals = source_map.locals_at(location)
|
|
254
297
|
pins = chain.define(api_map, closure_pin, locals)
|
|
@@ -265,34 +308,48 @@ module Solargraph
|
|
|
265
308
|
result = []
|
|
266
309
|
Solargraph::Parser::NodeMethods.call_nodes_from(source.node).each do |call|
|
|
267
310
|
rng = Solargraph::Range.from_node(call)
|
|
311
|
+
# @sg-ignore Need to add nil check here
|
|
268
312
|
next if @marked_ranges.any? { |d| d.contain?(rng.start) }
|
|
269
313
|
chain = Solargraph::Parser.chain(call, filename)
|
|
314
|
+
# @sg-ignore Need to add nil check here
|
|
270
315
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
271
316
|
namespace_pin = closure_pin
|
|
272
317
|
if call.type == :block
|
|
273
318
|
# blocks in the AST include the method call as well, so the
|
|
274
319
|
# node returned by #call_nodes_from needs to be backed out
|
|
275
320
|
# one closure
|
|
321
|
+
# @todo Need to add nil check here
|
|
322
|
+
# @todo Should warn on nil deference here
|
|
276
323
|
closure_pin = closure_pin.closure
|
|
277
324
|
end
|
|
325
|
+
# @sg-ignore Need to add nil check here
|
|
278
326
|
closure_pin.rebind(api_map)
|
|
327
|
+
# @sg-ignore Need to add nil check here
|
|
279
328
|
location = Location.new(filename, rng)
|
|
280
329
|
locals = source_map.locals_at(location)
|
|
330
|
+
# @sg-ignore Need to add nil check here
|
|
281
331
|
type = chain.infer(api_map, closure_pin, locals)
|
|
282
332
|
if type.undefined? && !rules.ignore_all_undefined?
|
|
283
333
|
base = chain
|
|
284
334
|
missing = chain
|
|
335
|
+
# @type [Solargraph::Pin::Base, nil]
|
|
285
336
|
found = nil
|
|
337
|
+
# @type [Array<Solargraph::Pin::Base>]
|
|
338
|
+
all_found = []
|
|
286
339
|
closest = ComplexType::UNDEFINED
|
|
287
340
|
until base.links.first.undefined?
|
|
288
|
-
|
|
341
|
+
# @sg-ignore Need to add nil check here
|
|
342
|
+
all_found = base.define(api_map, closure_pin, locals)
|
|
343
|
+
found = all_found.first
|
|
289
344
|
break if found
|
|
290
345
|
missing = base
|
|
291
346
|
base = base.base
|
|
292
347
|
end
|
|
293
|
-
|
|
348
|
+
all_closest = all_found.map { |pin| pin.typify(api_map) }
|
|
349
|
+
closest = ComplexType.new(all_closest.flat_map(&:items).uniq)
|
|
294
350
|
# @todo remove the internal_or_core? check at a higher-than-strict level
|
|
295
351
|
if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
|
|
352
|
+
# @sg-ignore Need to add nil check here
|
|
296
353
|
unless closest.generic? || ignored_pins.include?(found)
|
|
297
354
|
if closest.defined?
|
|
298
355
|
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word} on #{closest}")
|
|
@@ -303,6 +360,7 @@ module Solargraph
|
|
|
303
360
|
end
|
|
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)
|
|
@@ -368,7 +427,7 @@ 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]
|
|
@@ -430,7 +489,7 @@ module Solargraph
|
|
|
430
489
|
else
|
|
431
490
|
argtype = argchain.infer(api_map, closure_pin, locals)
|
|
432
491
|
argtype = argtype.self_to_type(closure_pin.context)
|
|
433
|
-
if argtype.defined? && ptype.defined? && !
|
|
492
|
+
if argtype.defined? && ptype.defined? && !arg_conforms_to?(argtype, ptype)
|
|
434
493
|
errors.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
|
435
494
|
return errors
|
|
436
495
|
end
|
|
@@ -445,13 +504,13 @@ module Solargraph
|
|
|
445
504
|
end
|
|
446
505
|
|
|
447
506
|
# @param sig [Pin::Signature]
|
|
448
|
-
# @param argchain [Source::Chain]
|
|
507
|
+
# @param argchain [Solargraph::Source::Chain]
|
|
449
508
|
# @param api_map [ApiMap]
|
|
450
509
|
# @param closure_pin [Pin::Closure]
|
|
451
510
|
# @param locals [Array<Pin::LocalVariable>]
|
|
452
511
|
# @param location [Location]
|
|
453
512
|
# @param pin [Pin::Method]
|
|
454
|
-
# @param params [Hash{String => Hash{Symbol =>
|
|
513
|
+
# @param params [Hash{String => Hash{Symbol => undefined}}]
|
|
455
514
|
# @param idx [Integer]
|
|
456
515
|
#
|
|
457
516
|
# @return [Array<Problem>]
|
|
@@ -459,6 +518,7 @@ module Solargraph
|
|
|
459
518
|
result = []
|
|
460
519
|
kwargs = convert_hash(argchain.node)
|
|
461
520
|
par = sig.parameters[idx]
|
|
521
|
+
# @type [Solargraph::Source::Chain]
|
|
462
522
|
argchain = kwargs[par.name.to_sym]
|
|
463
523
|
if par.decl == :kwrestarg || (par.decl == :optarg && idx == pin.parameters.length - 1 && par.asgn_code == '{}')
|
|
464
524
|
result.concat kwrestarg_problems_for(api_map, closure_pin, locals, location, pin, params, kwargs)
|
|
@@ -468,13 +528,14 @@ module Solargraph
|
|
|
468
528
|
if data.nil?
|
|
469
529
|
# @todo Some level (strong, I guess) should require the param here
|
|
470
530
|
else
|
|
531
|
+
# @type [ComplexType, ComplexType::UniqueType]
|
|
471
532
|
ptype = data[:qualified]
|
|
472
533
|
ptype = ptype.self_to_type(pin.context)
|
|
473
534
|
unless ptype.undefined?
|
|
474
|
-
# @
|
|
535
|
+
# @type [ComplexType]
|
|
475
536
|
argtype = argchain.infer(api_map, closure_pin, locals).self_to_type(closure_pin.context)
|
|
476
|
-
# @
|
|
477
|
-
if argtype.defined? && ptype && !
|
|
537
|
+
# @todo Unresolved call to defined?
|
|
538
|
+
if argtype.defined? && ptype && !arg_conforms_to?(argtype, ptype)
|
|
478
539
|
result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
|
479
540
|
end
|
|
480
541
|
end
|
|
@@ -498,11 +559,12 @@ module Solargraph
|
|
|
498
559
|
result = []
|
|
499
560
|
kwargs.each_pair do |pname, argchain|
|
|
500
561
|
next unless params.key?(pname.to_s)
|
|
562
|
+
# @type [ComplexType]
|
|
501
563
|
ptype = params[pname.to_s][:qualified]
|
|
502
564
|
ptype = ptype.self_to_type(pin.context)
|
|
503
565
|
argtype = argchain.infer(api_map, closure_pin, locals)
|
|
504
566
|
argtype = argtype.self_to_type(closure_pin.context)
|
|
505
|
-
if argtype.defined? && ptype && !
|
|
567
|
+
if argtype.defined? && ptype && !arg_conforms_to?(argtype, ptype)
|
|
506
568
|
result.push Problem.new(location, "Wrong argument type for #{pin.path}: #{pname} expected #{ptype}, received #{argtype}")
|
|
507
569
|
end
|
|
508
570
|
end
|
|
@@ -553,6 +615,7 @@ module Solargraph
|
|
|
553
615
|
next if tag.types.nil?
|
|
554
616
|
result[tag.name.to_s] = {
|
|
555
617
|
tagged: tag.types.join(', '),
|
|
618
|
+
# @sg-ignore need to add a nil check here
|
|
556
619
|
qualified: Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, *pin.closure.gates)
|
|
557
620
|
}
|
|
558
621
|
end
|
|
@@ -602,6 +665,7 @@ module Solargraph
|
|
|
602
665
|
# @param pin [Pin::Base]
|
|
603
666
|
def internal? pin
|
|
604
667
|
return false if pin.nil?
|
|
668
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
605
669
|
pin.location && api_map.bundled?(pin.location.filename)
|
|
606
670
|
end
|
|
607
671
|
|
|
@@ -622,23 +686,31 @@ module Solargraph
|
|
|
622
686
|
raise "No assignment found" if pin.assignment.nil?
|
|
623
687
|
|
|
624
688
|
chain = Solargraph::Parser.chain(pin.assignment, filename)
|
|
689
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
625
690
|
rng = Solargraph::Range.from_node(pin.assignment)
|
|
691
|
+
# @sg-ignore Need to add nil check here
|
|
626
692
|
closure_pin = source_map.locate_closure_pin(rng.start.line, rng.start.column)
|
|
693
|
+
# @sg-ignore flow sensitive typing needs to handle "if foo.nil?"
|
|
627
694
|
location = Location.new(filename, Range.from_node(pin.assignment))
|
|
628
695
|
locals = source_map.locals_at(location)
|
|
629
696
|
type = chain.infer(api_map, closure_pin, locals)
|
|
630
697
|
if type.undefined? && !rules.ignore_all_undefined?
|
|
631
698
|
base = chain
|
|
632
699
|
missing = chain
|
|
700
|
+
# @type [Solargraph::Pin::Base, nil]
|
|
633
701
|
found = nil
|
|
702
|
+
# @type [Array<Solargraph::Pin::Base>]
|
|
703
|
+
all_found = []
|
|
634
704
|
closest = ComplexType::UNDEFINED
|
|
635
705
|
until base.links.first.undefined?
|
|
636
|
-
|
|
706
|
+
all_found = base.define(api_map, closure_pin, locals)
|
|
707
|
+
found = all_found.first
|
|
637
708
|
break if found
|
|
638
709
|
missing = base
|
|
639
710
|
base = base.base
|
|
640
711
|
end
|
|
641
|
-
|
|
712
|
+
all_closest = all_found.map { |pin| pin.typify(api_map) }
|
|
713
|
+
closest = ComplexType.new(all_closest.flat_map(&:items).uniq)
|
|
642
714
|
if !found || closest.defined? || internal?(found)
|
|
643
715
|
return false
|
|
644
716
|
end
|
|
@@ -739,8 +811,10 @@ module Solargraph
|
|
|
739
811
|
end
|
|
740
812
|
|
|
741
813
|
# @param pin [Pin::Method]
|
|
814
|
+
# @sg-ignore need boolish support for ? methods
|
|
742
815
|
def abstract? pin
|
|
743
816
|
pin.docstring.has_tag?('abstract') ||
|
|
817
|
+
# @sg-ignore of low sensitive typing needs to handle ivars
|
|
744
818
|
(pin.closure && pin.closure.docstring.has_tag?('abstract'))
|
|
745
819
|
end
|
|
746
820
|
|
|
@@ -750,19 +824,25 @@ module Solargraph
|
|
|
750
824
|
args = []
|
|
751
825
|
with_opts = false
|
|
752
826
|
with_block = false
|
|
827
|
+
# @param pin [Pin::Parameter]
|
|
753
828
|
pin.parameters.each do |pin|
|
|
829
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
754
830
|
if [:kwarg, :kwoptarg, :kwrestarg].include?(pin.decl)
|
|
755
831
|
with_opts = true
|
|
832
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
756
833
|
elsif pin.decl == :block
|
|
757
834
|
with_block = true
|
|
835
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
758
836
|
elsif pin.decl == :restarg
|
|
759
837
|
args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)], nil, true)
|
|
760
838
|
else
|
|
761
839
|
args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)])
|
|
762
840
|
end
|
|
763
841
|
end
|
|
764
|
-
|
|
765
|
-
|
|
842
|
+
pin_location = pin.location
|
|
843
|
+
starting_line = pin_location ? pin_location.range.start.line : 0
|
|
844
|
+
args.push Solargraph::Parser.chain_string('{}', filename, starting_line) if with_opts
|
|
845
|
+
args.push Solargraph::Parser.chain_string('&', filename, starting_line) if with_block
|
|
766
846
|
args
|
|
767
847
|
end
|
|
768
848
|
|
|
@@ -774,6 +854,7 @@ module Solargraph
|
|
|
774
854
|
# @return [Set<Integer>]
|
|
775
855
|
def all_sg_ignore_lines
|
|
776
856
|
source.associated_comments.select do |_line, text|
|
|
857
|
+
# @sg-ignore Need to add nil check here
|
|
777
858
|
text.include?('@sg-ignore')
|
|
778
859
|
end.keys.to_set
|
|
779
860
|
end
|
data/lib/solargraph/version.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Solargraph
|
|
|
14
14
|
# @return [String]
|
|
15
15
|
attr_reader :directory
|
|
16
16
|
|
|
17
|
-
# @todo
|
|
17
|
+
# @todo Need to validate config
|
|
18
18
|
# @return [Hash{String => undefined, nil}]
|
|
19
19
|
attr_reader :raw_data
|
|
20
20
|
|
|
@@ -78,7 +78,9 @@ module Solargraph
|
|
|
78
78
|
|
|
79
79
|
# An array of load paths for required paths.
|
|
80
80
|
#
|
|
81
|
+
# @sg-ignore Need to validate config
|
|
81
82
|
# @return [Array<String>]
|
|
83
|
+
# @sg-ignore Need to validate config
|
|
82
84
|
def require_paths
|
|
83
85
|
raw_data['require_paths'] || []
|
|
84
86
|
end
|