solargraph 0.57.0 → 0.58.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +4 -2
  4. data/.github/workflows/plugins.yml +61 -27
  5. data/.github/workflows/rspec.yml +19 -4
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop.yml +1 -1
  8. data/.rubocop_todo.yml +90 -1438
  9. data/CHANGELOG.md +30 -0
  10. data/Rakefile +1 -1
  11. data/bin/solargraph +3 -0
  12. data/lib/solargraph/api_map/constants.rb +107 -46
  13. data/lib/solargraph/api_map/index.rb +32 -8
  14. data/lib/solargraph/api_map/source_to_yard.rb +5 -2
  15. data/lib/solargraph/api_map/store.rb +22 -12
  16. data/lib/solargraph/api_map.rb +27 -33
  17. data/lib/solargraph/complex_type/type_methods.rb +5 -0
  18. data/lib/solargraph/complex_type/unique_type.rb +12 -5
  19. data/lib/solargraph/complex_type.rb +19 -2
  20. data/lib/solargraph/convention/active_support_concern.rb +1 -1
  21. data/lib/solargraph/convention/data_definition/data_definition_node.rb +1 -1
  22. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -2
  23. data/lib/solargraph/doc_map.rb +9 -6
  24. data/lib/solargraph/environ.rb +1 -1
  25. data/lib/solargraph/equality.rb +1 -0
  26. data/lib/solargraph/gem_pins.rb +4 -0
  27. data/lib/solargraph/language_server/host.rb +10 -4
  28. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -2
  29. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -1
  30. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -1
  31. data/lib/solargraph/language_server/progress.rb +1 -1
  32. data/lib/solargraph/language_server/request.rb +3 -1
  33. data/lib/solargraph/library.rb +3 -3
  34. data/lib/solargraph/location.rb +1 -0
  35. data/lib/solargraph/page.rb +0 -1
  36. data/lib/solargraph/parser/flow_sensitive_typing.rb +1 -1
  37. data/lib/solargraph/parser/parser_gem/class_methods.rb +2 -12
  38. data/lib/solargraph/parser/parser_gem/node_methods.rb +1 -14
  39. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  40. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
  41. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  42. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +4 -5
  43. data/lib/solargraph/pin/base.rb +29 -8
  44. data/lib/solargraph/pin/base_variable.rb +5 -3
  45. data/lib/solargraph/pin/block.rb +3 -2
  46. data/lib/solargraph/pin/callable.rb +6 -2
  47. data/lib/solargraph/pin/closure.rb +3 -7
  48. data/lib/solargraph/pin/delegated_method.rb +0 -1
  49. data/lib/solargraph/pin/local_variable.rb +0 -4
  50. data/lib/solargraph/pin/method.rb +20 -4
  51. data/lib/solargraph/pin/parameter.rb +6 -2
  52. data/lib/solargraph/pin/proxy_type.rb +4 -1
  53. data/lib/solargraph/pin/reference.rb +2 -11
  54. data/lib/solargraph/pin/search.rb +3 -0
  55. data/lib/solargraph/pin_cache.rb +5 -5
  56. data/lib/solargraph/position.rb +1 -0
  57. data/lib/solargraph/range.rb +4 -0
  58. data/lib/solargraph/rbs_map/conversions.rb +22 -1
  59. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  60. data/lib/solargraph/rbs_map/core_map.rb +11 -7
  61. data/lib/solargraph/rbs_map.rb +2 -2
  62. data/lib/solargraph/shell.rb +82 -1
  63. data/lib/solargraph/source/chain/call.rb +7 -3
  64. data/lib/solargraph/source/chain/constant.rb +3 -66
  65. data/lib/solargraph/source/chain/if.rb +1 -1
  66. data/lib/solargraph/source/chain/link.rb +1 -1
  67. data/lib/solargraph/source/chain/or.rb +1 -1
  68. data/lib/solargraph/source/chain.rb +2 -0
  69. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  70. data/lib/solargraph/source.rb +1 -1
  71. data/lib/solargraph/source_map/clip.rb +17 -25
  72. data/lib/solargraph/source_map/mapper.rb +0 -2
  73. data/lib/solargraph/source_map.rb +8 -3
  74. data/lib/solargraph/type_checker/rules.rb +23 -9
  75. data/lib/solargraph/type_checker.rb +133 -71
  76. data/lib/solargraph/version.rb +5 -5
  77. data/lib/solargraph/workspace/config.rb +21 -3
  78. data/lib/solargraph/workspace/require_paths.rb +0 -1
  79. data/lib/solargraph/workspace.rb +14 -19
  80. data/lib/solargraph/yard_map/mapper/to_method.rb +2 -1
  81. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  82. data/lib/solargraph/yard_map/to_method.rb +2 -1
  83. data/lib/solargraph/yardoc.rb +27 -4
  84. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  85. data/rbs/fills/open3/0/open3.rbs +172 -0
  86. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  87. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  88. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  89. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  90. data/rbs_collection.yaml +4 -4
  91. data/sig/shims/ast/0/node.rbs +5 -0
  92. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  93. data/sig/shims/ast/2.4/ast.rbs +73 -0
  94. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  95. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  96. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  97. data/solargraph.gemspec +15 -4
  98. metadata +67 -12
  99. data/lib/solargraph/parser/node_methods.rb +0 -97
  100. /data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +0 -0
@@ -48,7 +48,7 @@ module Solargraph
48
48
  end
49
49
 
50
50
  # @param require [String]
51
- # @return [Array<Pin::Base>]
51
+ # @return [Array<Pin::Base>, nil]
52
52
  def deserialize_stdlib_require require
53
53
  load(stdlib_require_path(require))
54
54
  end
@@ -65,7 +65,7 @@ module Solargraph
65
65
  File.join(work_dir, 'core.ser')
66
66
  end
67
67
 
68
- # @return [Array<Pin::Base>]
68
+ # @return [Array<Pin::Base>, nil]
69
69
  def deserialize_core
70
70
  load(core_path)
71
71
  end
@@ -83,7 +83,7 @@ module Solargraph
83
83
  end
84
84
 
85
85
  # @param gemspec [Gem::Specification]
86
- # @return [Array<Pin::Base>]
86
+ # @return [Array<Pin::Base>, nil]
87
87
  def deserialize_yard_gem(gemspec)
88
88
  load(yard_gem_path(gemspec))
89
89
  end
@@ -116,7 +116,7 @@ module Solargraph
116
116
 
117
117
  # @param gemspec [Gem::Specification]
118
118
  # @param hash [String, nil]
119
- # @return [Array<Pin::Base>]
119
+ # @return [Array<Pin::Base>, nil]
120
120
  def deserialize_rbs_collection_gem(gemspec, hash)
121
121
  load(rbs_collection_path(gemspec, hash))
122
122
  end
@@ -152,7 +152,7 @@ module Solargraph
152
152
 
153
153
  # @param gemspec [Gem::Specification]
154
154
  # @param hash [String, nil]
155
- # @return [Array<Pin::Base>]
155
+ # @return [Array<Pin::Base>, nil]
156
156
  def deserialize_combined_gem gemspec, hash
157
157
  load(combined_path(gemspec, hash))
158
158
  end
@@ -112,6 +112,7 @@ module Solargraph
112
112
 
113
113
  def == other
114
114
  return false unless other.is_a?(Position)
115
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
115
116
  line == other.line and character == other.character
116
117
  end
117
118
  end
@@ -27,9 +27,12 @@ module Solargraph
27
27
  # @param other [BasicObject]
28
28
  def <=>(other)
29
29
  return nil unless other.is_a?(Range)
30
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
30
31
  if start == other.start
32
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
31
33
  ending <=> other.ending
32
34
  else
35
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
33
36
  start <=> other.start
34
37
  end
35
38
  end
@@ -98,6 +101,7 @@ module Solargraph
98
101
 
99
102
  def == other
100
103
  return false unless other.is_a?(Range)
104
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
101
105
  start == other.start && ending == other.ending
102
106
  end
103
107
 
@@ -65,6 +65,7 @@ module Solargraph
65
65
  # STDERR.puts "Skipping interface #{decl.name.relative!}"
66
66
  interface_decl_to_pin decl, closure
67
67
  when RBS::AST::Declarations::TypeAlias
68
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
68
69
  type_aliases[decl.name.to_s] = decl
69
70
  when RBS::AST::Declarations::Module
70
71
  module_decl_to_pin decl
@@ -426,6 +427,7 @@ module Solargraph
426
427
  # @param pin [Pin::Method]
427
428
  # @return [void]
428
429
  def method_def_to_sigs decl, pin
430
+ # @param overload [RBS::AST::Members::MethodDefinition::Overload]
429
431
  decl.overloads.map do |overload|
430
432
  type_location = location_decl_to_pin_location(overload.method_type.location)
431
433
  generics = overload.method_type.type_params.map(&:name).map(&:to_s)
@@ -466,33 +468,50 @@ module Solargraph
466
468
  parameters = []
467
469
  arg_num = -1
468
470
  type.type.required_positionals.each do |param|
471
+ # @sg-ignore RBS generic type understanding issue
469
472
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
473
+ # @sg-ignore RBS generic type understanding issue
470
474
  parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted, source: :rbs, type_location: type_location)
471
475
  end
472
476
  type.type.optional_positionals.each do |param|
477
+ # @sg-ignore RBS generic type understanding issue
473
478
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
474
479
  parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin,
480
+ # @sg-ignore RBS generic type understanding issue
475
481
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
476
482
  type_location: type_location,
477
483
  source: :rbs)
478
484
  end
479
485
  if type.type.rest_positionals
480
486
  name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg_#{arg_num += 1}"
481
- parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin, source: :rbs, type_location: type_location)
487
+ inner_rest_positional_type =
488
+ ComplexType.try_parse(other_type_to_tag(type.type.rest_positionals.type))
489
+ rest_positional_type = ComplexType::UniqueType.new('Array',
490
+ [],
491
+ [inner_rest_positional_type],
492
+ rooted: true, parameters_type: :list)
493
+ parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin,
494
+ source: :rbs, type_location: type_location,
495
+ return_type: rest_positional_type,)
482
496
  end
483
497
  type.type.trailing_positionals.each do |param|
498
+ # @sg-ignore RBS generic type understanding issue
484
499
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
485
500
  parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, source: :rbs, type_location: type_location)
486
501
  end
487
502
  type.type.required_keywords.each do |orig, param|
503
+ # @sg-ignore RBS generic type understanding issue
488
504
  name = orig ? orig.to_s : "arg_#{arg_num += 1}"
489
505
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin,
506
+ # @sg-ignore RBS generic type understanding issue
490
507
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
491
508
  source: :rbs, type_location: type_location)
492
509
  end
493
510
  type.type.optional_keywords.each do |orig, param|
511
+ # @sg-ignore RBS generic type understanding issue
494
512
  name = orig ? orig.to_s : "arg_#{arg_num += 1}"
495
513
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin,
514
+ # @sg-ignore RBS generic type understanding issue
496
515
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
497
516
  type_location: type_location,
498
517
  source: :rbs)
@@ -784,7 +803,9 @@ module Solargraph
784
803
  # @param namespace [Pin::Namespace]
785
804
  # @return [void]
786
805
  def add_mixins decl, namespace
806
+ # @param mixin [RBS::AST::Members::Include, RBS::AST::Members::Members::Extend, RBS::AST::Members::Members::Prepend]
787
807
  decl.each_mixin do |mixin|
808
+ # @todo are we handling prepend correctly?
788
809
  klass = mixin.is_a?(RBS::AST::Members::Include) ? Pin::Reference::Include : Pin::Reference::Extend
789
810
  type = build_type(mixin.name, mixin.args)
790
811
  generic_values = type.all_params.map(&:to_s)
@@ -48,6 +48,24 @@ module Solargraph
48
48
  Solargraph::Pin::Reference::Include.new(name: '_ToAry',
49
49
  closure: Solargraph::Pin::Namespace.new(name: 'Array', source: :core_fill),
50
50
  generic_values: ['generic<Elem>'],
51
+ source: :core_fill),
52
+ Solargraph::Pin::Reference::Include.new(name: '_ToAry',
53
+ closure: Solargraph::Pin::Namespace.new(name: 'Set', source: :core_fill),
54
+ generic_values: ['generic<Elem>'],
55
+ source: :core_fill),
56
+ Solargraph::Pin::Reference::Include.new(name: '_Each',
57
+ closure: Solargraph::Pin::Namespace.new(name: 'Array', source: :core_fill),
58
+ generic_values: ['generic<Elem>'],
59
+ source: :core_fill),
60
+ Solargraph::Pin::Reference::Include.new(name: '_Each',
61
+ closure: Solargraph::Pin::Namespace.new(name: 'Set', source: :core_fill),
62
+ generic_values: ['generic<Elem>'],
63
+ source: :core_fill),
64
+ Solargraph::Pin::Reference::Include.new(name: '_ToS',
65
+ closure: Solargraph::Pin::Namespace.new(name: 'Object', source: :core_fill),
66
+ source: :core_fill),
67
+ Solargraph::Pin::Reference::Include.new(name: '_ToS',
68
+ closure: Solargraph::Pin::Namespace.new(name: 'String', source: :core_fill),
51
69
  source: :core_fill)
52
70
  ]
53
71
 
@@ -5,12 +5,13 @@ module Solargraph
5
5
  # Ruby core pins
6
6
  #
7
7
  class CoreMap
8
+ include Logging
8
9
 
9
10
  def resolved?
10
11
  true
11
12
  end
12
13
 
13
- FILLS_DIRECTORY = File.join(File.dirname(__FILE__), '..', '..', '..', 'rbs', 'fills')
14
+ FILLS_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'rbs', 'fills'))
14
15
 
15
16
  def initialize; end
16
17
 
@@ -23,9 +24,16 @@ module Solargraph
23
24
  if cache
24
25
  @pins.replace cache
25
26
  else
26
- loader.add(path: Pathname(FILLS_DIRECTORY))
27
- @pins = conversions.pins
27
+ @pins.concat conversions.pins
28
+
29
+ # Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
30
+ fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
31
+ fill_loader.add(path: Pathname(FILLS_DIRECTORY))
32
+ fill_conversions = Conversions.new(loader: fill_loader)
33
+ @pins.concat fill_conversions.pins
34
+
28
35
  @pins.concat RbsMap::CoreFills::ALL
36
+
29
37
  processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
30
38
  @pins.replace processed
31
39
 
@@ -34,10 +42,6 @@ module Solargraph
34
42
  @pins
35
43
  end
36
44
 
37
- def loader
38
- @loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
39
- end
40
-
41
45
  private
42
46
 
43
47
  # @return [RBS::EnvironmentLoader]
@@ -23,7 +23,7 @@ module Solargraph
23
23
  attr_reader :rbs_collection_config_path
24
24
 
25
25
  # @param library [String]
26
- # @param version [String, nil
26
+ # @param version [String, nil]
27
27
  # @param rbs_collection_config_path [String, Pathname, nil]
28
28
  # @param rbs_collection_paths [Array<Pathname, String>]
29
29
  def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: []
@@ -72,7 +72,7 @@ module Solargraph
72
72
  end
73
73
  end
74
74
 
75
- # @param gemspec [Gem::Specification]
75
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
76
76
  # @param rbs_collection_path [String, Pathname, nil]
77
77
  # @param rbs_collection_config_path [String, Pathname, nil]
78
78
  # @return [RbsMap]
@@ -79,6 +79,7 @@ module Solargraph
79
79
  conf['extensions'].push m
80
80
  end
81
81
  end
82
+ # @param file [File]
82
83
  File.open(File.join(directory, '.solargraph.yml'), 'w') do |file|
83
84
  file.puts conf.to_yaml
84
85
  end
@@ -172,6 +173,9 @@ module Solargraph
172
173
  # @return [void]
173
174
  def typecheck *files
174
175
  directory = File.realpath(options[:directory])
176
+ workspace = Solargraph::Workspace.new(directory)
177
+ level = options[:level].to_sym
178
+ rules = workspace.rules(level)
175
179
  api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
176
180
  probcount = 0
177
181
  if files.empty?
@@ -183,7 +187,7 @@ module Solargraph
183
187
 
184
188
  time = Benchmark.measure {
185
189
  files.each do |file|
186
- checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym)
190
+ checker = TypeChecker.new(file, api_map: api_map, level: options[:level].to_sym, workspace: workspace)
187
191
  problems = checker.problems
188
192
  next if problems.empty?
189
193
  problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
@@ -241,6 +245,63 @@ module Solargraph
241
245
  puts "#{workspace.filenames.length} files total."
242
246
  end
243
247
 
248
+ desc 'pin [PATH]', 'Describe a pin', hide: true
249
+ option :rbs, type: :boolean, desc: 'Output the pin as RBS', default: false
250
+ option :typify, type: :boolean, desc: 'Output the calculated return type of the pin from annotations', default: false
251
+ option :references, type: :boolean, desc: 'Show references', default: false
252
+ option :probe, type: :boolean, desc: 'Output the calculated return type of the pin from annotations and inference', default: false
253
+ option :stack, type: :boolean, desc: 'Show entire stack of a method pin by including definitions in superclasses', default: false
254
+ # @param path [String] The path to the method pin, e.g. 'Class#method' or 'Class.method'
255
+ # @return [void]
256
+ def pin path
257
+ api_map = Solargraph::ApiMap.load_with_cache('.', $stderr)
258
+ is_method = path.include?('#') || path.include?('.')
259
+ if is_method && options[:stack]
260
+ scope, ns, meth = if path.include? '#'
261
+ [:instance, *path.split('#', 2)]
262
+ else
263
+ [:class, *path.split('.', 2)]
264
+ end
265
+
266
+ # @sg-ignore Wrong argument type for
267
+ # Solargraph::ApiMap#get_method_stack: rooted_tag
268
+ # expected String, received Array<String>
269
+ pins = api_map.get_method_stack(ns, meth, scope: scope)
270
+ else
271
+ pins = api_map.get_path_pins path
272
+ end
273
+ # @type [Hash{Symbol => Pin::Base}]
274
+ references = {}
275
+ pin = pins.first
276
+ case pin
277
+ when nil
278
+ $stderr.puts "Pin not found for path '#{path}'"
279
+ exit 1
280
+ when Pin::Namespace
281
+ if options[:references]
282
+ superclass_tag = api_map.qualify_superclass(pin.return_type.tag)
283
+ superclass_pin = api_map.get_path_pins(superclass_tag).first if superclass_tag
284
+ references[:superclass] = superclass_pin if superclass_pin
285
+ end
286
+ end
287
+
288
+ pins.each do |pin|
289
+ if options[:typify] || options[:probe]
290
+ type = ComplexType::UNDEFINED
291
+ type = pin.typify(api_map) if options[:typify]
292
+ type = pin.probe(api_map) if options[:probe] && type.undefined?
293
+ print_type(type)
294
+ next
295
+ end
296
+
297
+ print_pin(pin)
298
+ end
299
+ references.each do |key, refpin|
300
+ puts "\n# #{key.to_s.capitalize}:\n\n"
301
+ print_pin(refpin)
302
+ end
303
+ end
304
+
244
305
  private
245
306
 
246
307
  # @param pin [Solargraph::Pin::Base]
@@ -267,5 +328,25 @@ module Solargraph
267
328
  # typecheck doesn't complain on the below line
268
329
  api_map.cache_gem(gemspec, rebuild: options.rebuild, out: $stdout)
269
330
  end
331
+
332
+ # @param type [ComplexType]
333
+ # @return [void]
334
+ def print_type(type)
335
+ if options[:rbs]
336
+ puts type.to_rbs
337
+ else
338
+ puts type.rooted_tag
339
+ end
340
+ end
341
+
342
+ # @param pin [Solargraph::Pin::Base]
343
+ # @return [void]
344
+ def print_pin(pin)
345
+ if options[:rbs]
346
+ puts pin.to_rbs
347
+ else
348
+ puts pin.inspect
349
+ end
350
+ end
270
351
  end
271
352
  end
@@ -98,7 +98,10 @@ module Solargraph
98
98
  match = ol.parameters.any?(&:restarg?)
99
99
  break
100
100
  end
101
- atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context, source: :chain), locals)
101
+ arg_name_pin = Pin::ProxyType.anonymous(name_pin.context,
102
+ gates: name_pin.gates,
103
+ source: :chain)
104
+ atype = atypes[idx] ||= arg.infer(api_map, arg_name_pin, locals)
102
105
  unless param.compatible_arg?(atype, api_map) || param.restarg?
103
106
  match = false
104
107
  break
@@ -137,7 +140,7 @@ module Solargraph
137
140
  #
138
141
  # qualify(), however, happens in the namespace where
139
142
  # the docs were written - from the method pin.
140
- type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, p.namespace) if new_return_type.defined?
143
+ type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, *p.gates) if new_return_type.defined?
141
144
  type ||= ComplexType::UNDEFINED
142
145
  end
143
146
  break if type.defined?
@@ -266,8 +269,9 @@ module Solargraph
266
269
  method_pin = find_method_pin(name_pin)
267
270
  return [] unless method_pin
268
271
 
272
+ # @param signature_pin [Pin::Signature]
269
273
  method_pin.signatures.map(&:block).compact.map do |signature_pin|
270
- return_type = signature_pin.return_type.qualify(api_map, name_pin.namespace)
274
+ return_type = signature_pin.return_type.qualify(api_map, *name_pin.gates)
271
275
  signature_pin.proxy(return_type)
272
276
  end
273
277
  end
@@ -15,73 +15,10 @@ module Solargraph
15
15
  gates = ['']
16
16
  else
17
17
  base = word
18
- gates = crawl_gates(name_pin)
18
+ gates = name_pin.gates
19
19
  end
20
- parts = base.split('::')
21
- gates.each do |gate|
22
- # @todo 'Wrong argument type for
23
- # Solargraph::Source::Chain::Constant#deep_constant_type:
24
- # gate expected String, received generic<Elem>' is because
25
- # we lose 'rooted' information in the 'Chain::Array' class
26
- # internally, leaving ::Array#each shadowed when it
27
- # shouldn't be.
28
- type = deep_constant_type(gate, api_map)
29
- # Use deep inference to resolve root
30
- parts[0..-2].each do |sym|
31
- pins = api_map.get_constants('', type.namespace).select{ |pin| pin.name == sym }
32
- type = first_pin_type(pins, api_map)
33
- break if type.undefined?
34
- end
35
- next if type.undefined?
36
- result = api_map.get_constants('', type.namespace).select { |pin| pin.name == parts.last }
37
- return result unless result.empty?
38
- end
39
- []
40
- end
41
-
42
- private
43
-
44
- # @param pin [Pin::Closure]
45
- # @return [::Array<String>]
46
- def crawl_gates pin
47
- clos = pin
48
- until clos.nil?
49
- if clos.is_a?(Pin::Namespace)
50
- gates = clos.gates
51
- gates.push('') if gates.empty?
52
- return gates
53
- end
54
- clos = clos.closure
55
- end
56
- ['']
57
- end
58
-
59
- # @param pins [::Array<Pin::Base>]
60
- # @param api_map [ApiMap]
61
- # @return [ComplexType]
62
- def first_pin_type(pins, api_map)
63
- type = ComplexType::UNDEFINED
64
- pins.each do |pin|
65
- type = pin.typify(api_map)
66
- break if type.defined?
67
- type = pin.probe(api_map)
68
- break if type.defined?
69
- end
70
- type
71
- end
72
-
73
- # @param gate [String]
74
- # @param api_map [ApiMap]
75
- # @return [ComplexType]
76
- def deep_constant_type(gate, api_map)
77
- type = ComplexType::ROOT
78
- return type if gate == ''
79
- gate.split('::').each do |word|
80
- pins = api_map.get_constants('', type.namespace).select { |pin| pin.name == word }
81
- type = first_pin_type(pins, api_map)
82
- break if type.undefined?
83
- end
84
- type
20
+ fqns = api_map.resolve(base, gates)
21
+ api_map.get_path_pins(fqns)
85
22
  end
86
23
  end
87
24
  end
@@ -8,7 +8,7 @@ module Solargraph
8
8
  '<if>'
9
9
  end
10
10
 
11
- # @param links [::Array<Link>]
11
+ # @param links [::Array<Chain>]
12
12
  def initialize links
13
13
  @links = links
14
14
  end
@@ -38,7 +38,7 @@ module Solargraph
38
38
 
39
39
  # @param api_map [ApiMap]
40
40
  # @param name_pin [Pin::Base]
41
- # @param locals [::Enumerable<Pin::Base>]
41
+ # @param locals [::Array<Pin::Base>]
42
42
  # @return [::Array<Pin::Base>]
43
43
  def resolve api_map, name_pin, locals
44
44
  []
@@ -8,7 +8,7 @@ module Solargraph
8
8
  '<or>'
9
9
  end
10
10
 
11
- # @param links [::Array<Link>]
11
+ # @param links [::Array<Chain>]
12
12
  def initialize links
13
13
  @links = links
14
14
  end
@@ -264,6 +264,8 @@ module Solargraph
264
264
  ComplexType::UNDEFINED
265
265
  elsif types.length > 1
266
266
  # Move nil to the end by convention
267
+
268
+ # @param a [ComplexType::UniqueType]
267
269
  sorted = types.flat_map(&:items).sort { |a, _| a.tag == 'nil' ? 1 : 0 }
268
270
  ComplexType.new(sorted.uniq)
269
271
  else
@@ -1,23 +1,23 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class Source
5
- module EncodingFixes
6
- module_function
7
-
8
- # Convert strings to normalized UTF-8.
9
- #
10
- # @param string [String]
11
- # @return [String]
12
- def normalize string
13
- begin
14
- string.dup.force_encoding('UTF-8')
15
- rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError, ::Encoding::InvalidByteSequenceError => e
16
- # @todo Improve error handling
17
- Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
18
- string
19
- end
20
- end
21
- end
22
- end
23
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ module EncodingFixes
6
+ module_function
7
+
8
+ # Convert strings to normalized UTF-8.
9
+ #
10
+ # @param string [String]
11
+ # @return [String]
12
+ def normalize string
13
+ begin
14
+ string.dup.force_encoding('UTF-8')
15
+ rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError, ::Encoding::InvalidByteSequenceError => e
16
+ # @todo Improve error handling
17
+ Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
18
+ string
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -15,7 +15,7 @@ module Solargraph
15
15
 
16
16
  include EncodingFixes
17
17
 
18
- # @return [String]
18
+ # @return [String, nil]
19
19
  attr_reader :filename
20
20
 
21
21
  # @return [String]
@@ -11,15 +11,14 @@ module Solargraph
11
11
  def initialize api_map, cursor
12
12
  @api_map = api_map
13
13
  @cursor = cursor
14
- block_pin = block
15
- block_pin.rebind(api_map) if block_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(block_pin.receiver).contain?(cursor.range.start)
16
- @in_block = nil
14
+ closure_pin = closure
15
+ closure_pin.rebind(api_map) if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver).contain?(cursor.range.start)
17
16
  end
18
17
 
19
18
  # @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
20
19
  def define
21
20
  return [] if cursor.comment? || cursor.chain.literal?
22
- result = cursor.chain.define(api_map, block, locals)
21
+ result = cursor.chain.define(api_map, closure, locals)
23
22
  result.concat file_global_methods
24
23
  result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
25
24
  result
@@ -51,14 +50,15 @@ module Solargraph
51
50
 
52
51
  # @return [ComplexType]
53
52
  def infer
54
- result = cursor.chain.infer(api_map, block, locals)
53
+ result = cursor.chain.infer(api_map, closure, locals)
55
54
  if result.tag == 'Class'
56
55
  # HACK: Exception to return BasicObject from Class#new
57
- dfn = cursor.chain.define(api_map, block, locals).first
56
+ dfn = cursor.chain.define(api_map, closure, locals).first
58
57
  return ComplexType.try_parse('::BasicObject') if dfn && dfn.path == 'Class#new'
59
58
  end
60
- return result unless result.tag == 'self'
61
- cursor.chain.base.infer(api_map, block, locals)
59
+ # should receive result with selfs resolved from infer()
60
+ Solargraph.assert_or_log(:clip_infer_self, 'Received selfy inference') if result.selfy?
61
+ result
62
62
  end
63
63
 
64
64
  # Get an array of all the locals that are visible from the cursors's
@@ -72,22 +72,14 @@ module Solargraph
72
72
 
73
73
  # @return [::Array<String>]
74
74
  def gates
75
- block.gates
76
- end
77
-
78
- def in_block?
79
- return @in_block unless @in_block.nil?
80
- @in_block = begin
81
- tree = cursor.source.tree_at(cursor.position.line, cursor.position.column)
82
- Parser.is_ast_node?(tree[1]) && [:block, :ITER].include?(tree[1].type)
83
- end
75
+ closure.gates
84
76
  end
85
77
 
86
78
  # @param phrase [String]
87
79
  # @return [Array<Solargraph::Pin::Base>]
88
80
  def translate phrase
89
81
  chain = Parser.chain(Parser.parse(phrase))
90
- chain.define(api_map, block, locals)
82
+ chain.define(api_map, closure, locals)
91
83
  end
92
84
 
93
85
  private
@@ -109,8 +101,8 @@ module Solargraph
109
101
  end
110
102
 
111
103
  # @return [Solargraph::Pin::Closure]
112
- def block
113
- @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
104
+ def closure
105
+ @closure ||= source_map.locate_closure_pin(cursor.node_position.line, cursor.node_position.character)
114
106
  end
115
107
 
116
108
  # The context at the current position.
@@ -201,20 +193,20 @@ module Solargraph
201
193
  result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
202
194
  end
203
195
  else
204
- type = cursor.chain.base.infer(api_map, block, locals)
205
- result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
196
+ type = cursor.chain.base.infer(api_map, closure, locals)
197
+ result.concat api_map.get_complex_type_methods(type, closure.binder.namespace, cursor.chain.links.length == 1)
206
198
  if cursor.chain.links.length == 1
207
199
  if cursor.word.start_with?('@@')
208
200
  return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
209
201
  elsif cursor.word.start_with?('@')
210
- return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
202
+ return package_completions(api_map.get_instance_variable_pins(closure.binder.namespace, closure.binder.scope))
211
203
  elsif cursor.word.start_with?('$')
212
204
  return package_completions(api_map.get_global_variable_pins)
213
205
  end
214
206
  result.concat locals
215
- result.concat file_global_methods unless block.binder.namespace.empty?
207
+ result.concat file_global_methods unless closure.binder.namespace.empty?
216
208
  result.concat api_map.get_constants(context_pin.context.namespace, *gates)
217
- result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
209
+ result.concat api_map.get_methods(closure.binder.namespace, scope: closure.binder.scope, visibility: [:public, :private, :protected])
218
210
  result.concat api_map.get_methods('Kernel')
219
211
  result.concat api_map.keyword_pins.to_a
220
212
  end