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.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -7
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/complex_type/conformance.rb +176 -0
  19. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  20. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  21. data/lib/solargraph/complex_type.rb +119 -14
  22. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  23. data/lib/solargraph/convention/data_definition.rb +4 -1
  24. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  25. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  26. data/lib/solargraph/convention/struct_definition.rb +5 -1
  27. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  28. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  29. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  30. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  31. data/lib/solargraph/doc_map.rb +134 -373
  32. data/lib/solargraph/equality.rb +1 -1
  33. data/lib/solargraph/gem_pins.rb +14 -15
  34. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  35. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  36. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  37. data/lib/solargraph/language_server/host/sources.rb +1 -0
  38. data/lib/solargraph/language_server/host.rb +6 -1
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  40. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  49. data/lib/solargraph/library.rb +59 -13
  50. data/lib/solargraph/location.rb +9 -4
  51. data/lib/solargraph/logging.rb +21 -1
  52. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  54. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  55. data/lib/solargraph/parser/node_processor.rb +7 -6
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  77. data/lib/solargraph/parser/region.rb +9 -3
  78. data/lib/solargraph/parser/snippet.rb +1 -1
  79. data/lib/solargraph/pin/base.rb +53 -21
  80. data/lib/solargraph/pin/base_variable.rb +312 -20
  81. data/lib/solargraph/pin/block.rb +26 -4
  82. data/lib/solargraph/pin/breakable.rb +5 -1
  83. data/lib/solargraph/pin/callable.rb +50 -3
  84. data/lib/solargraph/pin/closure.rb +2 -6
  85. data/lib/solargraph/pin/common.rb +20 -5
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +2 -1
  88. data/lib/solargraph/pin/delegated_method.rb +15 -4
  89. data/lib/solargraph/pin/documenting.rb +1 -0
  90. data/lib/solargraph/pin/instance_variable.rb +5 -1
  91. data/lib/solargraph/pin/keyword.rb +0 -4
  92. data/lib/solargraph/pin/local_variable.rb +13 -57
  93. data/lib/solargraph/pin/method.rb +90 -42
  94. data/lib/solargraph/pin/method_alias.rb +8 -0
  95. data/lib/solargraph/pin/namespace.rb +7 -1
  96. data/lib/solargraph/pin/parameter.rb +76 -13
  97. data/lib/solargraph/pin/proxy_type.rb +2 -1
  98. data/lib/solargraph/pin/reference/override.rb +1 -1
  99. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  100. data/lib/solargraph/pin/reference.rb +2 -0
  101. data/lib/solargraph/pin/search.rb +1 -0
  102. data/lib/solargraph/pin/signature.rb +8 -0
  103. data/lib/solargraph/pin/symbol.rb +1 -1
  104. data/lib/solargraph/pin/until.rb +1 -1
  105. data/lib/solargraph/pin/while.rb +1 -1
  106. data/lib/solargraph/pin.rb +2 -0
  107. data/lib/solargraph/pin_cache.rb +477 -57
  108. data/lib/solargraph/position.rb +12 -26
  109. data/lib/solargraph/range.rb +6 -6
  110. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  111. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  113. data/lib/solargraph/rbs_map.rb +74 -20
  114. data/lib/solargraph/shell.rb +73 -28
  115. data/lib/solargraph/source/chain/call.rb +52 -17
  116. data/lib/solargraph/source/chain/constant.rb +2 -0
  117. data/lib/solargraph/source/chain/hash.rb +1 -0
  118. data/lib/solargraph/source/chain/if.rb +1 -0
  119. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  120. data/lib/solargraph/source/chain/literal.rb +5 -0
  121. data/lib/solargraph/source/chain/or.rb +9 -1
  122. data/lib/solargraph/source/chain.rb +25 -22
  123. data/lib/solargraph/source/change.rb +9 -2
  124. data/lib/solargraph/source/cursor.rb +7 -1
  125. data/lib/solargraph/source/source_chainer.rb +13 -3
  126. data/lib/solargraph/source/updater.rb +4 -0
  127. data/lib/solargraph/source.rb +33 -7
  128. data/lib/solargraph/source_map/clip.rb +13 -2
  129. data/lib/solargraph/source_map/data.rb +4 -1
  130. data/lib/solargraph/source_map/mapper.rb +24 -1
  131. data/lib/solargraph/source_map.rb +14 -6
  132. data/lib/solargraph/type_checker/problem.rb +3 -1
  133. data/lib/solargraph/type_checker/rules.rb +75 -2
  134. data/lib/solargraph/type_checker.rb +111 -30
  135. data/lib/solargraph/version.rb +1 -1
  136. data/lib/solargraph/workspace/config.rb +3 -1
  137. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  138. data/lib/solargraph/workspace/require_paths.rb +1 -0
  139. data/lib/solargraph/workspace.rb +158 -16
  140. data/lib/solargraph/yard_map/helpers.rb +2 -1
  141. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  142. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  143. data/lib/solargraph/yard_map/mapper.rb +5 -0
  144. data/lib/solargraph/yardoc.rb +33 -23
  145. data/lib/solargraph.rb +24 -3
  146. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  147. data/rbs/fills/tuple/tuple.rbs +28 -0
  148. data/rbs/shims/ast/0/node.rbs +1 -1
  149. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  150. data/solargraph.gemspec +2 -1
  151. metadata +12 -7
  152. data/lib/solargraph/type_checker/checks.rb +0 -124
  153. data/lib/solargraph/type_checker/param_def.rb +0 -37
  154. 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 require_all_return_types_match_inferred?
64
- report?(:require_all_return_types_match_inferred, :alpha)
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
- include Checks
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
- @source_map.source
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
- api_map = Solargraph::ApiMap.new
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
- api_map = Solargraph::ApiMap.new
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 (rules.require_all_return_types_match_inferred? ? all_types_match?(api_map, inferred, declared) : any_types_match?(api_map, declared, inferred))
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 any_types_match?(api_map, declared, inferred)
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
- found = base.define(api_map, closure_pin, locals).first
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
- closest = found.typify(api_map) if found
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::Base>]
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 => Hash{Symbol => String, Solargraph::ComplexType}}]
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? && !any_types_match?(api_map, ptype, argtype)
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 => String, Solargraph::ComplexType}}]
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
- # @sg-ignore https://github.com/castwide/solargraph/pull/1127
535
+ # @type [ComplexType]
475
536
  argtype = argchain.infer(api_map, closure_pin, locals).self_to_type(closure_pin.context)
476
- # @sg-ignore Unresolved call to defined?
477
- if argtype.defined? && ptype && !any_types_match?(api_map, ptype, argtype)
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 && !any_types_match?(api_map, ptype, argtype)
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
- found = base.define(api_map, closure_pin, locals).first
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
- closest = found.typify(api_map) if found
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
- args.push Solargraph::Parser.chain_string('{}') if with_opts
765
- args.push Solargraph::Parser.chain_string('&') if with_block
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.58.2'
4
+ VERSION = ENV.fetch('SOLARGRAPH_FORCE_VERSION', '0.59.0.dev.1')
5
5
  end
@@ -14,7 +14,7 @@ module Solargraph
14
14
  # @return [String]
15
15
  attr_reader :directory
16
16
 
17
- # @todo To make JSON strongly typed we'll need a record syntax
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