solargraph 0.56.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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +183 -7
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.gitignore +5 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +86 -1
  14. data/README.md +8 -4
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +3 -2
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +49 -31
  20. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  21. data/lib/solargraph/api_map/store.rb +144 -26
  22. data/lib/solargraph/api_map.rb +217 -245
  23. data/lib/solargraph/bench.rb +1 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +6 -0
  25. data/lib/solargraph/complex_type/unique_type.rb +19 -12
  26. data/lib/solargraph/complex_type.rb +24 -3
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +17 -0
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemspec.rb +3 -2
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -2
  35. data/lib/solargraph/convention/struct_definition.rb +87 -24
  36. data/lib/solargraph/convention.rb +32 -2
  37. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  38. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  39. data/lib/solargraph/doc_map.rb +52 -18
  40. data/lib/solargraph/environ.rb +9 -2
  41. data/lib/solargraph/equality.rb +1 -0
  42. data/lib/solargraph/gem_pins.rb +21 -11
  43. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  44. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  45. data/lib/solargraph/language_server/host.rb +12 -5
  46. data/lib/solargraph/language_server/message/base.rb +2 -1
  47. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  48. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  49. data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -2
  50. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  51. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  52. data/lib/solargraph/language_server/progress.rb +8 -0
  53. data/lib/solargraph/language_server/request.rb +4 -1
  54. data/lib/solargraph/library.rb +50 -33
  55. data/lib/solargraph/location.rb +3 -0
  56. data/lib/solargraph/logging.rb +11 -2
  57. data/lib/solargraph/page.rb +3 -0
  58. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  59. data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
  60. data/lib/solargraph/parser/node_processor/base.rb +10 -5
  61. data/lib/solargraph/parser/node_processor.rb +24 -8
  62. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
  63. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  64. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  65. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
  66. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  68. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
  69. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
  72. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +65 -8
  73. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  74. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +1 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  76. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
  77. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
  78. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  79. data/lib/solargraph/parser/region.rb +3 -0
  80. data/lib/solargraph/parser/snippet.rb +2 -0
  81. data/lib/solargraph/pin/base.rb +92 -14
  82. data/lib/solargraph/pin/base_variable.rb +6 -5
  83. data/lib/solargraph/pin/block.rb +3 -2
  84. data/lib/solargraph/pin/callable.rb +14 -1
  85. data/lib/solargraph/pin/closure.rb +5 -7
  86. data/lib/solargraph/pin/common.rb +6 -2
  87. data/lib/solargraph/pin/constant.rb +2 -0
  88. data/lib/solargraph/pin/local_variable.rb +1 -2
  89. data/lib/solargraph/pin/method.rb +32 -11
  90. data/lib/solargraph/pin/method_alias.rb +3 -0
  91. data/lib/solargraph/pin/parameter.rb +24 -10
  92. data/lib/solargraph/pin/proxy_type.rb +5 -1
  93. data/lib/solargraph/pin/reference/override.rb +15 -1
  94. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  95. data/lib/solargraph/pin/reference.rb +17 -0
  96. data/lib/solargraph/pin/search.rb +6 -1
  97. data/lib/solargraph/pin/signature.rb +2 -0
  98. data/lib/solargraph/pin/symbol.rb +5 -0
  99. data/lib/solargraph/pin_cache.rb +64 -4
  100. data/lib/solargraph/position.rb +3 -0
  101. data/lib/solargraph/range.rb +5 -0
  102. data/lib/solargraph/rbs_map/conversions.rb +68 -18
  103. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  104. data/lib/solargraph/rbs_map/core_map.rb +14 -7
  105. data/lib/solargraph/rbs_map.rb +14 -1
  106. data/lib/solargraph/shell.rb +85 -1
  107. data/lib/solargraph/source/chain/call.rb +7 -3
  108. data/lib/solargraph/source/chain/constant.rb +3 -66
  109. data/lib/solargraph/source/chain/if.rb +1 -1
  110. data/lib/solargraph/source/chain/link.rb +11 -2
  111. data/lib/solargraph/source/chain/or.rb +1 -1
  112. data/lib/solargraph/source/chain.rb +11 -2
  113. data/lib/solargraph/source/change.rb +2 -2
  114. data/lib/solargraph/source/cursor.rb +2 -3
  115. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  116. data/lib/solargraph/source/source_chainer.rb +1 -1
  117. data/lib/solargraph/source.rb +6 -3
  118. data/lib/solargraph/source_map/clip.rb +18 -26
  119. data/lib/solargraph/source_map/data.rb +4 -0
  120. data/lib/solargraph/source_map/mapper.rb +2 -2
  121. data/lib/solargraph/source_map.rb +28 -16
  122. data/lib/solargraph/type_checker/param_def.rb +2 -0
  123. data/lib/solargraph/type_checker/rules.rb +30 -8
  124. data/lib/solargraph/type_checker.rb +301 -186
  125. data/lib/solargraph/version.rb +5 -5
  126. data/lib/solargraph/workspace/config.rb +22 -6
  127. data/lib/solargraph/workspace/require_paths.rb +97 -0
  128. data/lib/solargraph/workspace.rb +38 -67
  129. data/lib/solargraph/yard_map/helpers.rb +29 -1
  130. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
  131. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -9
  132. data/lib/solargraph/yard_map/mapper/to_namespace.rb +8 -7
  133. data/lib/solargraph/yard_map/to_method.rb +2 -1
  134. data/lib/solargraph/yardoc.rb +41 -3
  135. data/lib/solargraph.rb +15 -0
  136. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  137. data/rbs/fills/open3/0/open3.rbs +172 -0
  138. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  139. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  140. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  141. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  142. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  143. data/rbs_collection.yaml +4 -4
  144. data/sig/shims/ast/0/node.rbs +5 -0
  145. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  146. data/sig/shims/ast/2.4/ast.rbs +73 -0
  147. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  148. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  149. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  150. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  151. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  152. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  153. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  154. data/solargraph.gemspec +26 -5
  155. metadata +187 -15
  156. data/lib/.rubocop.yml +0 -22
  157. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -22,12 +22,14 @@ module Solargraph
22
22
  end
23
23
  end
24
24
 
25
+ # @param loader [RBS::EnvironmentLoader]
25
26
  def initialize(loader:)
26
27
  @loader = loader
27
28
  @pins = []
28
29
  load_environment_to_pins(loader)
29
30
  end
30
31
 
32
+ # @return [RBS::EnvironmentLoader]
31
33
  attr_reader :loader
32
34
 
33
35
  # @return [Array<Pin::Base>]
@@ -63,6 +65,7 @@ module Solargraph
63
65
  # STDERR.puts "Skipping interface #{decl.name.relative!}"
64
66
  interface_decl_to_pin decl, closure
65
67
  when RBS::AST::Declarations::TypeAlias
68
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
66
69
  type_aliases[decl.name.to_s] = decl
67
70
  when RBS::AST::Declarations::Module
68
71
  module_decl_to_pin decl
@@ -106,14 +109,14 @@ module Solargraph
106
109
  # @param closure [Pin::Namespace]
107
110
  # @return [void]
108
111
  def convert_members_to_pins decl, closure
109
- context = Context.new
112
+ context = Conversions::Context.new
110
113
  decl.members.each { |m| context = convert_member_to_pin(m, closure, context) }
111
114
  end
112
115
 
113
116
  # @param member [RBS::AST::Members::Base,RBS::AST::Declarations::Base]
114
117
  # @param closure [Pin::Namespace]
115
118
  # @param context [Context]
116
- # @return [void]
119
+ # @return [Context]
117
120
  def convert_member_to_pin member, closure, context
118
121
  case member
119
122
  when RBS::AST::Members::MethodDefinition
@@ -161,9 +164,10 @@ module Solargraph
161
164
  generic_defaults[param.name.to_s] = ComplexType.parse(tag).force_rooted
162
165
  end
163
166
  end
167
+ class_name = decl.name.relative!.to_s
164
168
  class_pin = Solargraph::Pin::Namespace.new(
165
169
  type: :class,
166
- name: decl.name.relative!.to_s,
170
+ name: class_name,
167
171
  closure: Solargraph::Pin::ROOT_PIN,
168
172
  comments: decl.comment&.string,
169
173
  type_location: location_decl_to_pin_location(decl.location),
@@ -178,11 +182,12 @@ module Solargraph
178
182
  if decl.super_class
179
183
  type = build_type(decl.super_class.name, decl.super_class.args)
180
184
  generic_values = type.all_params.map(&:to_s)
185
+ superclass_name = decl.super_class.name.to_s
181
186
  pins.push Solargraph::Pin::Reference::Superclass.new(
182
187
  type_location: location_decl_to_pin_location(decl.super_class.location),
183
188
  closure: class_pin,
184
189
  generic_values: generic_values,
185
- name: decl.super_class.name.relative!.to_s,
190
+ name: superclass_name,
186
191
  source: :rbs
187
192
  )
188
193
  end
@@ -295,6 +300,7 @@ module Solargraph
295
300
  name: name,
296
301
  closure: closure,
297
302
  comments: decl.comment&.string,
303
+ type_location: location_decl_to_pin_location(decl.location),
298
304
  source: :rbs
299
305
  )
300
306
  rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
@@ -316,6 +322,7 @@ module Solargraph
316
322
  # related overrides
317
323
  # @todo externalize remaining overrides into yaml file, then
318
324
  # allow that to be extended via .solargraph.yml
325
+ # @type [Hash{Array(String, Symbol, String) => Symbol}
319
326
  VISIBILITY_OVERRIDE = {
320
327
  ["Rails::Engine", :instance, "run_tasks_blocks"] => :protected,
321
328
  # Should have been marked as both instance and class method in module -e.g., 'module_function'
@@ -340,6 +347,13 @@ module Solargraph
340
347
  ["Rainbow::Presenter", :instance, "wrap_with_sgr"] => :private,
341
348
  }
342
349
 
350
+ # @param decl [RBS::AST::Members::MethodDefinition, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrAccessor]
351
+ # @param closure [Pin::Closure]
352
+ # @param context [Context]
353
+ # @param scope [Symbol] :instance or :class
354
+ # @param name [String] The name of the method
355
+ # @sg-ignore
356
+ # @return [Symbol]
343
357
  def calculate_method_visibility(decl, context, closure, scope, name)
344
358
  override_key = [closure.path, scope, name]
345
359
  visibility = VISIBILITY_OVERRIDE[override_key]
@@ -413,16 +427,18 @@ module Solargraph
413
427
  # @param pin [Pin::Method]
414
428
  # @return [void]
415
429
  def method_def_to_sigs decl, pin
430
+ # @param overload [RBS::AST::Members::MethodDefinition::Overload]
416
431
  decl.overloads.map do |overload|
432
+ type_location = location_decl_to_pin_location(overload.method_type.location)
417
433
  generics = overload.method_type.type_params.map(&:name).map(&:to_s)
418
434
  signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin)
419
435
  block = if overload.method_type.block
420
436
  block_parameters, block_return_type = parts_of_function(overload.method_type.block, pin)
421
- Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type,
422
- closure: pin, source: :rbs)
437
+ Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs,
438
+ type_location: type_location, closure: pin)
423
439
  end
424
- Pin::Signature.new(generics: generics, parameters: signature_parameters, return_type: signature_return_type, block: block,
425
- closure: pin, source: :rbs)
440
+ Pin::Signature.new(generics: generics, parameters: signature_parameters, return_type: signature_return_type, block: block, source: :rbs,
441
+ type_location: type_location, closure: pin)
426
442
  end
427
443
  end
428
444
 
@@ -441,44 +457,69 @@ module Solargraph
441
457
  # @param pin [Pin::Method]
442
458
  # @return [Array(Array<Pin::Parameter>, ComplexType)]
443
459
  def parts_of_function type, pin
444
- return [[Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin, source: :rbs)], ComplexType.try_parse(method_type_to_tag(type)).force_rooted] if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
460
+ type_location = pin.type_location
461
+ if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
462
+ return [
463
+ [Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin, source: :rbs, type_location: type_location)],
464
+ ComplexType.try_parse(method_type_to_tag(type)).force_rooted
465
+ ]
466
+ end
445
467
 
446
468
  parameters = []
447
469
  arg_num = -1
448
470
  type.type.required_positionals.each do |param|
471
+ # @sg-ignore RBS generic type understanding issue
449
472
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
450
- 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)
473
+ # @sg-ignore RBS generic type understanding issue
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)
451
475
  end
452
476
  type.type.optional_positionals.each do |param|
477
+ # @sg-ignore RBS generic type understanding issue
453
478
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
454
479
  parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin,
480
+ # @sg-ignore RBS generic type understanding issue
455
481
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
482
+ type_location: type_location,
456
483
  source: :rbs)
457
484
  end
458
485
  if type.type.rest_positionals
459
486
  name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg_#{arg_num += 1}"
460
- parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin, source: :rbs)
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,)
461
496
  end
462
497
  type.type.trailing_positionals.each do |param|
498
+ # @sg-ignore RBS generic type understanding issue
463
499
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
464
- parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, source: :rbs)
500
+ parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, source: :rbs, type_location: type_location)
465
501
  end
466
502
  type.type.required_keywords.each do |orig, param|
503
+ # @sg-ignore RBS generic type understanding issue
467
504
  name = orig ? orig.to_s : "arg_#{arg_num += 1}"
468
505
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin,
506
+ # @sg-ignore RBS generic type understanding issue
469
507
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
470
- source: :rbs)
508
+ source: :rbs, type_location: type_location)
471
509
  end
472
510
  type.type.optional_keywords.each do |orig, param|
511
+ # @sg-ignore RBS generic type understanding issue
473
512
  name = orig ? orig.to_s : "arg_#{arg_num += 1}"
474
513
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin,
514
+ # @sg-ignore RBS generic type understanding issue
475
515
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
516
+ type_location: type_location,
476
517
  source: :rbs)
477
518
  end
478
519
  if type.type.rest_keywords
479
520
  name = type.type.rest_keywords.name ? type.type.rest_keywords.name.to_s : "arg_#{arg_num += 1}"
480
521
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwrestarg, name: type.type.rest_keywords.name.to_s, closure: pin,
481
- source: :rbs)
522
+ source: :rbs, type_location: type_location)
482
523
  end
483
524
 
484
525
  rooted_tag = method_type_to_tag(type)
@@ -488,6 +529,7 @@ module Solargraph
488
529
 
489
530
  # @param decl [RBS::AST::Members::AttrReader,RBS::AST::Members::AttrAccessor]
490
531
  # @param closure [Pin::Namespace]
532
+ # @param context [Context]
491
533
  # @return [void]
492
534
  def attr_reader_to_pin(decl, closure, context)
493
535
  name = decl.name.to_s
@@ -511,14 +553,16 @@ module Solargraph
511
553
 
512
554
  # @param decl [RBS::AST::Members::AttrWriter, RBS::AST::Members::AttrAccessor]
513
555
  # @param closure [Pin::Namespace]
556
+ # @param context [Context]
514
557
  # @return [void]
515
558
  def attr_writer_to_pin(decl, closure, context)
516
559
  final_scope = decl.kind == :instance ? :instance : :class
517
560
  name = "#{decl.name.to_s}="
518
561
  visibility = calculate_method_visibility(decl, context, closure, final_scope, name)
562
+ type_location = location_decl_to_pin_location(decl.location)
519
563
  pin = Solargraph::Pin::Method.new(
520
564
  name: name,
521
- type_location: location_decl_to_pin_location(decl.location),
565
+ type_location: type_location,
522
566
  closure: closure,
523
567
  parameters: [],
524
568
  comments: decl.comment&.string,
@@ -532,7 +576,8 @@ module Solargraph
532
576
  name: 'value',
533
577
  return_type: ComplexType.try_parse(other_type_to_tag(decl.type)).force_rooted,
534
578
  source: :rbs,
535
- closure: pin
579
+ closure: pin,
580
+ type_location: type_location
536
581
  )
537
582
  rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
538
583
  pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', rooted_tag))
@@ -541,6 +586,7 @@ module Solargraph
541
586
 
542
587
  # @param decl [RBS::AST::Members::AttrAccessor]
543
588
  # @param closure [Pin::Namespace]
589
+ # @param context [Context]
544
590
  # @return [void]
545
591
  def attr_accessor_to_pin(decl, closure, context)
546
592
  attr_reader_to_pin(decl, closure, context)
@@ -572,6 +618,7 @@ module Solargraph
572
618
  name: name,
573
619
  closure: closure,
574
620
  comments: decl.comment&.string,
621
+ type_location: location_decl_to_pin_location(decl.location),
575
622
  source: :rbs
576
623
  )
577
624
  rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
@@ -588,6 +635,7 @@ module Solargraph
588
635
  name: name,
589
636
  closure: closure,
590
637
  comments: decl.comment&.string,
638
+ type_location: location_decl_to_pin_location(decl.location),
591
639
  source: :rbs
592
640
  )
593
641
  rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags
@@ -672,13 +720,13 @@ module Solargraph
672
720
  # @return [ComplexType::UniqueType]
673
721
  def build_type(type_name, type_args = [])
674
722
  base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
675
- params = type_args.map { |a| other_type_to_tag(a) }.reject { |t| t == 'undefined' }.map do |t|
723
+ params = type_args.map { |a| other_type_to_tag(a) }.map do |t|
676
724
  ComplexType.try_parse(t).force_rooted
677
725
  end
678
726
  if base == 'Hash' && params.length == 2
679
727
  ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
680
728
  else
681
- ComplexType::UniqueType.new(base, [], params, rooted: true, parameters_type: :list)
729
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
682
730
  end
683
731
  end
684
732
 
@@ -755,7 +803,9 @@ module Solargraph
755
803
  # @param namespace [Pin::Namespace]
756
804
  # @return [void]
757
805
  def add_mixins decl, namespace
806
+ # @param mixin [RBS::AST::Members::Include, RBS::AST::Members::Members::Extend, RBS::AST::Members::Members::Prepend]
758
807
  decl.each_mixin do |mixin|
808
+ # @todo are we handling prepend correctly?
759
809
  klass = mixin.is_a?(RBS::AST::Members::Include) ? Pin::Reference::Include : Pin::Reference::Extend
760
810
  type = build_type(mixin.name, mixin.args)
761
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,15 +5,17 @@ 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
 
18
+ # @return [Enumerable<Pin::Base>]
17
19
  def pins
18
20
  return @pins if @pins
19
21
 
@@ -22,9 +24,16 @@ module Solargraph
22
24
  if cache
23
25
  @pins.replace cache
24
26
  else
25
- loader.add(path: Pathname(FILLS_DIRECTORY))
26
- @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
+
27
35
  @pins.concat RbsMap::CoreFills::ALL
36
+
28
37
  processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
29
38
  @pins.replace processed
30
39
 
@@ -33,16 +42,14 @@ module Solargraph
33
42
  @pins
34
43
  end
35
44
 
36
- def loader
37
- @loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
38
- end
39
-
40
45
  private
41
46
 
47
+ # @return [RBS::EnvironmentLoader]
42
48
  def loader
43
49
  @loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
44
50
  end
45
51
 
52
+ # @return [Conversions]
46
53
  def conversions
47
54
  @conversions ||= Conversions.new(loader: loader)
48
55
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'digest'
3
4
  require 'pathname'
4
5
  require 'rbs'
5
6
 
@@ -23,6 +24,7 @@ module Solargraph
23
24
 
24
25
  # @param library [String]
25
26
  # @param version [String, nil]
27
+ # @param rbs_collection_config_path [String, Pathname, nil]
26
28
  # @param rbs_collection_paths [Array<Pathname, String>]
27
29
  def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: []
28
30
  if rbs_collection_config_path.nil? && !rbs_collection_paths.empty?
@@ -35,16 +37,18 @@ module Solargraph
35
37
  add_library loader, library, version
36
38
  end
37
39
 
40
+ # @return [RBS::EnvironmentLoader]
38
41
  def loader
39
42
  @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
40
43
  end
41
44
 
42
- # @return string representing the version of the RBS info fetched
45
+ # @return [String] representing the version of the RBS info fetched
43
46
  # for the given library. Must change when the RBS info is
44
47
  # updated upstream for the same library and version. May change
45
48
  # if the config for where information comes form changes.
46
49
  def cache_key
47
50
  @hextdigest ||= begin
51
+ # @type [String, nil]
48
52
  data = nil
49
53
  if rbs_collection_config_path
50
54
  lockfile_path = RBS::Collection::Config.to_lockfile_path(Pathname.new(rbs_collection_config_path))
@@ -68,6 +72,10 @@ module Solargraph
68
72
  end
69
73
  end
70
74
 
75
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
76
+ # @param rbs_collection_path [String, Pathname, nil]
77
+ # @param rbs_collection_config_path [String, Pathname, nil]
78
+ # @return [RbsMap]
71
79
  def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path
72
80
  rbs_map = RbsMap.new(gemspec.name, gemspec.version,
73
81
  rbs_collection_paths: [rbs_collection_path].compact,
@@ -80,6 +88,7 @@ module Solargraph
80
88
  rbs_collection_config_path: rbs_collection_config_path)
81
89
  end
82
90
 
91
+ # @return [Array<Pin::Base>]
83
92
  def pins
84
93
  @pins ||= resolved? ? conversions.pins : []
85
94
  end
@@ -103,6 +112,7 @@ module Solargraph
103
112
  @resolved
104
113
  end
105
114
 
115
+ # @return [RBS::Repository]
106
116
  def repository
107
117
  @repository ||= RBS::Repository.new(no_stdlib: false).tap do |repo|
108
118
  @rbs_collection_paths.each do |dir|
@@ -120,16 +130,19 @@ module Solargraph
120
130
 
121
131
  private
122
132
 
133
+ # @return [RBS::EnvironmentLoader]
123
134
  def loader
124
135
  @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
125
136
  end
126
137
 
138
+ # @return [Conversions]
127
139
  def conversions
128
140
  @conversions ||= Conversions.new(loader: loader)
129
141
  end
130
142
 
131
143
  # @param loader [RBS::EnvironmentLoader]
132
144
  # @param library [String]
145
+ # @param version [String, nil]
133
146
  # @return [Boolean] true if adding the library succeeded
134
147
  def add_library loader, library, version
135
148
  @resolved = if loader.has_library?(library: library, version: version)
@@ -36,6 +36,7 @@ module Solargraph
36
36
  Signal.trap("TERM") do
37
37
  Backport.stop
38
38
  end
39
+ # @sg-ignore Wrong argument type for Backport.prepare_tcp_server: adapter expected Backport::Adapter, received Module<Solargraph::LanguageServer::Transport::Adapter>
39
40
  Backport.prepare_tcp_server host: options[:host], port: port, adapter: Solargraph::LanguageServer::Transport::Adapter
40
41
  STDERR.puts "Solargraph is listening PORT=#{port} PID=#{Process.pid}"
41
42
  end
@@ -52,6 +53,7 @@ module Solargraph
52
53
  Signal.trap("TERM") do
53
54
  Backport.stop
54
55
  end
56
+ # @sg-ignore Wrong argument type for Backport.prepare_stdio_server: adapter expected Backport::Adapter, received Module<Solargraph::LanguageServer::Transport::Adapter>
55
57
  Backport.prepare_stdio_server adapter: Solargraph::LanguageServer::Transport::Adapter
56
58
  STDERR.puts "Solargraph is listening on stdio PID=#{Process.pid}"
57
59
  end
@@ -77,6 +79,7 @@ module Solargraph
77
79
  conf['extensions'].push m
78
80
  end
79
81
  end
82
+ # @param file [File]
80
83
  File.open(File.join(directory, '.solargraph.yml'), 'w') do |file|
81
84
  file.puts conf.to_yaml
82
85
  end
@@ -170,6 +173,9 @@ module Solargraph
170
173
  # @return [void]
171
174
  def typecheck *files
172
175
  directory = File.realpath(options[:directory])
176
+ workspace = Solargraph::Workspace.new(directory)
177
+ level = options[:level].to_sym
178
+ rules = workspace.rules(level)
173
179
  api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
174
180
  probcount = 0
175
181
  if files.empty?
@@ -181,7 +187,7 @@ module Solargraph
181
187
 
182
188
  time = Benchmark.measure {
183
189
  files.each do |file|
184
- 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)
185
191
  problems = checker.problems
186
192
  next if problems.empty?
187
193
  problems.sort! { |a, b| a.location.range.start.line <=> b.location.range.start.line }
@@ -239,6 +245,63 @@ module Solargraph
239
245
  puts "#{workspace.filenames.length} files total."
240
246
  end
241
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
+
242
305
  private
243
306
 
244
307
  # @param pin [Solargraph::Pin::Base]
@@ -258,11 +321,32 @@ module Solargraph
258
321
  end
259
322
 
260
323
  # @param gemspec [Gem::Specification]
324
+ # @param api_map [ApiMap]
261
325
  # @return [void]
262
326
  def do_cache gemspec, api_map
263
327
  # @todo if the rebuild: option is passed as a positional arg,
264
328
  # typecheck doesn't complain on the below line
265
329
  api_map.cache_gem(gemspec, rebuild: options.rebuild, out: $stdout)
266
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
267
351
  end
268
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