solargraph 0.56.2 → 0.58.0

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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +183 -7
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +6 -3
  6. data/.gitignore +5 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +69 -0
  13. data/README.md +8 -4
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +3 -2
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +49 -31
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +144 -26
  21. data/lib/solargraph/api_map.rb +217 -245
  22. data/lib/solargraph/bench.rb +1 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +6 -0
  24. data/lib/solargraph/complex_type/unique_type.rb +19 -12
  25. data/lib/solargraph/complex_type.rb +24 -3
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +17 -0
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
  30. data/lib/solargraph/convention/data_definition.rb +2 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
  34. data/lib/solargraph/convention/struct_definition.rb +36 -13
  35. data/lib/solargraph/convention.rb +31 -2
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +44 -13
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +1 -0
  41. data/lib/solargraph/gem_pins.rb +21 -11
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  44. data/lib/solargraph/language_server/host.rb +12 -5
  45. data/lib/solargraph/language_server/message/base.rb +2 -1
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  47. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -2
  49. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  50. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  51. data/lib/solargraph/language_server/progress.rb +8 -0
  52. data/lib/solargraph/language_server/request.rb +4 -1
  53. data/lib/solargraph/library.rb +11 -18
  54. data/lib/solargraph/location.rb +3 -0
  55. data/lib/solargraph/logging.rb +11 -2
  56. data/lib/solargraph/page.rb +3 -0
  57. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  58. data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
  59. data/lib/solargraph/parser/node_processor/base.rb +1 -1
  60. data/lib/solargraph/parser/node_processor.rb +6 -2
  61. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
  62. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  63. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  64. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
  65. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  66. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  67. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  68. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
  69. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
  70. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  71. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
  72. data/lib/solargraph/parser/region.rb +3 -0
  73. data/lib/solargraph/parser/snippet.rb +2 -0
  74. data/lib/solargraph/pin/base.rb +77 -14
  75. data/lib/solargraph/pin/base_variable.rb +6 -5
  76. data/lib/solargraph/pin/block.rb +3 -2
  77. data/lib/solargraph/pin/callable.rb +14 -1
  78. data/lib/solargraph/pin/closure.rb +5 -7
  79. data/lib/solargraph/pin/common.rb +6 -2
  80. data/lib/solargraph/pin/constant.rb +2 -0
  81. data/lib/solargraph/pin/local_variable.rb +1 -2
  82. data/lib/solargraph/pin/method.rb +28 -9
  83. data/lib/solargraph/pin/method_alias.rb +3 -0
  84. data/lib/solargraph/pin/parameter.rb +24 -10
  85. data/lib/solargraph/pin/proxy_type.rb +5 -1
  86. data/lib/solargraph/pin/reference/override.rb +15 -1
  87. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  88. data/lib/solargraph/pin/reference.rb +17 -0
  89. data/lib/solargraph/pin/search.rb +6 -1
  90. data/lib/solargraph/pin/signature.rb +2 -0
  91. data/lib/solargraph/pin/symbol.rb +5 -0
  92. data/lib/solargraph/pin_cache.rb +64 -4
  93. data/lib/solargraph/position.rb +3 -0
  94. data/lib/solargraph/range.rb +5 -0
  95. data/lib/solargraph/rbs_map/conversions.rb +29 -6
  96. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  97. data/lib/solargraph/rbs_map/core_map.rb +14 -7
  98. data/lib/solargraph/rbs_map.rb +14 -1
  99. data/lib/solargraph/shell.rb +85 -1
  100. data/lib/solargraph/source/chain/call.rb +7 -3
  101. data/lib/solargraph/source/chain/constant.rb +3 -66
  102. data/lib/solargraph/source/chain/if.rb +1 -1
  103. data/lib/solargraph/source/chain/link.rb +11 -2
  104. data/lib/solargraph/source/chain/or.rb +1 -1
  105. data/lib/solargraph/source/chain.rb +11 -2
  106. data/lib/solargraph/source/change.rb +2 -2
  107. data/lib/solargraph/source/cursor.rb +2 -3
  108. data/lib/solargraph/source/source_chainer.rb +1 -1
  109. data/lib/solargraph/source.rb +6 -3
  110. data/lib/solargraph/source_map/clip.rb +18 -26
  111. data/lib/solargraph/source_map/data.rb +4 -0
  112. data/lib/solargraph/source_map/mapper.rb +2 -2
  113. data/lib/solargraph/source_map.rb +28 -16
  114. data/lib/solargraph/type_checker/param_def.rb +2 -0
  115. data/lib/solargraph/type_checker/rules.rb +30 -8
  116. data/lib/solargraph/type_checker.rb +301 -186
  117. data/lib/solargraph/version.rb +1 -1
  118. data/lib/solargraph/workspace/config.rb +21 -5
  119. data/lib/solargraph/workspace/require_paths.rb +97 -0
  120. data/lib/solargraph/workspace.rb +30 -67
  121. data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
  122. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  123. data/lib/solargraph/yard_map/to_method.rb +2 -1
  124. data/lib/solargraph/yardoc.rb +39 -3
  125. data/lib/solargraph.rb +2 -0
  126. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  127. data/rbs/fills/open3/0/open3.rbs +172 -0
  128. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  129. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  130. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  131. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  132. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  133. data/rbs_collection.yaml +4 -4
  134. data/sig/shims/ast/0/node.rbs +5 -0
  135. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  136. data/sig/shims/ast/2.4/ast.rbs +73 -0
  137. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  138. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  139. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  140. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  141. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  142. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  143. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  144. data/solargraph.gemspec +26 -5
  145. metadata +181 -13
  146. data/lib/.rubocop.yml +0 -22
  147. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -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
@@ -163,9 +164,10 @@ module Solargraph
163
164
  generic_defaults[param.name.to_s] = ComplexType.parse(tag).force_rooted
164
165
  end
165
166
  end
167
+ class_name = decl.name.relative!.to_s
166
168
  class_pin = Solargraph::Pin::Namespace.new(
167
169
  type: :class,
168
- name: decl.name.relative!.to_s,
170
+ name: class_name,
169
171
  closure: Solargraph::Pin::ROOT_PIN,
170
172
  comments: decl.comment&.string,
171
173
  type_location: location_decl_to_pin_location(decl.location),
@@ -180,11 +182,12 @@ module Solargraph
180
182
  if decl.super_class
181
183
  type = build_type(decl.super_class.name, decl.super_class.args)
182
184
  generic_values = type.all_params.map(&:to_s)
185
+ superclass_name = decl.super_class.name.to_s
183
186
  pins.push Solargraph::Pin::Reference::Superclass.new(
184
187
  type_location: location_decl_to_pin_location(decl.super_class.location),
185
188
  closure: class_pin,
186
189
  generic_values: generic_values,
187
- name: decl.super_class.name.relative!.to_s,
190
+ name: superclass_name,
188
191
  source: :rbs
189
192
  )
190
193
  end
@@ -345,7 +348,7 @@ module Solargraph
345
348
  }
346
349
 
347
350
  # @param decl [RBS::AST::Members::MethodDefinition, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrAccessor]
348
- # @param closure [Pin::Namespace]
351
+ # @param closure [Pin::Closure]
349
352
  # @param context [Context]
350
353
  # @param scope [Symbol] :instance or :class
351
354
  # @param name [String] The name of the method
@@ -424,6 +427,7 @@ module Solargraph
424
427
  # @param pin [Pin::Method]
425
428
  # @return [void]
426
429
  def method_def_to_sigs decl, pin
430
+ # @param overload [RBS::AST::Members::MethodDefinition::Overload]
427
431
  decl.overloads.map do |overload|
428
432
  type_location = location_decl_to_pin_location(overload.method_type.location)
429
433
  generics = overload.method_type.type_params.map(&:name).map(&:to_s)
@@ -464,33 +468,50 @@ module Solargraph
464
468
  parameters = []
465
469
  arg_num = -1
466
470
  type.type.required_positionals.each do |param|
471
+ # @sg-ignore RBS generic type understanding issue
467
472
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
473
+ # @sg-ignore RBS generic type understanding issue
468
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)
469
475
  end
470
476
  type.type.optional_positionals.each do |param|
477
+ # @sg-ignore RBS generic type understanding issue
471
478
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
472
479
  parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin,
480
+ # @sg-ignore RBS generic type understanding issue
473
481
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
474
482
  type_location: type_location,
475
483
  source: :rbs)
476
484
  end
477
485
  if type.type.rest_positionals
478
486
  name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg_#{arg_num += 1}"
479
- 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,)
480
496
  end
481
497
  type.type.trailing_positionals.each do |param|
498
+ # @sg-ignore RBS generic type understanding issue
482
499
  name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
483
500
  parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, source: :rbs, type_location: type_location)
484
501
  end
485
502
  type.type.required_keywords.each do |orig, param|
503
+ # @sg-ignore RBS generic type understanding issue
486
504
  name = orig ? orig.to_s : "arg_#{arg_num += 1}"
487
505
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin,
506
+ # @sg-ignore RBS generic type understanding issue
488
507
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
489
508
  source: :rbs, type_location: type_location)
490
509
  end
491
510
  type.type.optional_keywords.each do |orig, param|
511
+ # @sg-ignore RBS generic type understanding issue
492
512
  name = orig ? orig.to_s : "arg_#{arg_num += 1}"
493
513
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin,
514
+ # @sg-ignore RBS generic type understanding issue
494
515
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
495
516
  type_location: type_location,
496
517
  source: :rbs)
@@ -699,13 +720,13 @@ module Solargraph
699
720
  # @return [ComplexType::UniqueType]
700
721
  def build_type(type_name, type_args = [])
701
722
  base = RBS_TO_YARD_TYPE[type_name.relative!.to_s] || type_name.relative!.to_s
702
- 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|
703
724
  ComplexType.try_parse(t).force_rooted
704
725
  end
705
726
  if base == 'Hash' && params.length == 2
706
727
  ComplexType::UniqueType.new(base, [params.first], [params.last], rooted: true, parameters_type: :hash)
707
728
  else
708
- ComplexType::UniqueType.new(base, [], params, rooted: true, parameters_type: :list)
729
+ ComplexType::UniqueType.new(base, [], params.reject(&:undefined?), rooted: true, parameters_type: :list)
709
730
  end
710
731
  end
711
732
 
@@ -782,7 +803,9 @@ module Solargraph
782
803
  # @param namespace [Pin::Namespace]
783
804
  # @return [void]
784
805
  def add_mixins decl, namespace
806
+ # @param mixin [RBS::AST::Members::Include, RBS::AST::Members::Members::Extend, RBS::AST::Members::Members::Prepend]
785
807
  decl.each_mixin do |mixin|
808
+ # @todo are we handling prepend correctly?
786
809
  klass = mixin.is_a?(RBS::AST::Members::Include) ? Pin::Reference::Include : Pin::Reference::Extend
787
810
  type = build_type(mixin.name, mixin.args)
788
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
@@ -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
@@ -17,7 +17,13 @@ module Solargraph
17
17
  @word = word
18
18
  end
19
19
 
20
- # @sg-ignore Fix "Not enough arguments to Module#protected"
20
+ # @sg-ignore two problems - Declared return type
21
+ # ::Solargraph::Source::Chain::Array does not match inferred
22
+ # type ::Array(::Class<::Solargraph::Source::Chain::Link>,
23
+ # ::String) for
24
+ # Solargraph::Source::Chain::Link#equality_fields
25
+ # and
26
+ # Not enough arguments to Module#protected
21
27
  protected def equality_fields
22
28
  [self.class, word]
23
29
  end
@@ -32,13 +38,14 @@ module Solargraph
32
38
 
33
39
  # @param api_map [ApiMap]
34
40
  # @param name_pin [Pin::Base]
35
- # @param locals [::Enumerable<Pin::Base>]
41
+ # @param locals [::Array<Pin::Base>]
36
42
  # @return [::Array<Pin::Base>]
37
43
  def resolve api_map, name_pin, locals
38
44
  []
39
45
  end
40
46
 
41
47
  # debugging description of contents; not for machine use
48
+ # @return [String]
42
49
  def desc
43
50
  word
44
51
  end
@@ -74,6 +81,8 @@ module Solargraph
74
81
  end
75
82
 
76
83
  # debugging description of contents; not for machine use
84
+ #
85
+ # @return [String]
77
86
  def desc
78
87
  word
79
88
  end
@@ -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
@@ -15,6 +15,7 @@ module Solargraph
15
15
  #
16
16
  class Chain
17
17
  include Equality
18
+ include Logging
18
19
 
19
20
  autoload :Link, 'solargraph/source/chain/link'
20
21
  autoload :Call, 'solargraph/source/chain/call'
@@ -75,7 +76,9 @@ module Solargraph
75
76
 
76
77
  # Determine potential Pins returned by this chain of words
77
78
  #
78
- # @param api_map [ApiMap] @param name_pin [Pin::Base] A pin
79
+ # @param api_map [ApiMap]
80
+ #
81
+ # @param name_pin [Pin::Base] A pin
79
82
  # representing the place in which expression is evaluated (e.g.,
80
83
  # a Method pin, or a Module or Class pin if not run within a
81
84
  # method - both in terms of the closure around the chain, as well
@@ -192,6 +195,7 @@ module Solargraph
192
195
 
193
196
  include Logging
194
197
 
198
+ # @return [String]
195
199
  def desc
196
200
  links.map(&:desc).to_s
197
201
  end
@@ -260,12 +264,17 @@ module Solargraph
260
264
  ComplexType::UNDEFINED
261
265
  elsif types.length > 1
262
266
  # Move nil to the end by convention
267
+
268
+ # @param a [ComplexType::UniqueType]
263
269
  sorted = types.flat_map(&:items).sort { |a, _| a.tag == 'nil' ? 1 : 0 }
264
270
  ComplexType.new(sorted.uniq)
265
271
  else
266
272
  ComplexType.new(types)
267
273
  end
268
- return type if context.nil? || context.return_type.undefined?
274
+ if context.nil? || context.return_type.undefined?
275
+ # up to downstream to resolve self type
276
+ return type
277
+ end
269
278
 
270
279
  type.self_to_type(context.return_type)
271
280
  end
@@ -28,7 +28,7 @@ module Solargraph
28
28
  # syntax errors will be repaired.
29
29
  # @return [String] The updated text.
30
30
  def write text, nullable = false
31
- if nullable and !range.nil? and new_text.match(/[\.\[\{\(@\$:]$/)
31
+ if nullable and !range.nil? and new_text.match(/[.\[{(@$:]$/)
32
32
  [':', '@'].each do |dupable|
33
33
  next unless new_text == dupable
34
34
  offset = Position.to_offset(text, range.start)
@@ -59,7 +59,7 @@ module Solargraph
59
59
  else
60
60
  result = commit text, fixed
61
61
  off = Position.to_offset(text, range.start)
62
- match = result[0, off].match(/[\.:]+\z/)
62
+ match = result[0, off].match(/[.:]+\z/)
63
63
  if match
64
64
  result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1]
65
65
  end