solargraph 0.58.2 → 0.59.0.dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -7
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/complex_type/conformance.rb +176 -0
  19. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  20. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  21. data/lib/solargraph/complex_type.rb +119 -14
  22. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  23. data/lib/solargraph/convention/data_definition.rb +4 -1
  24. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  25. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  26. data/lib/solargraph/convention/struct_definition.rb +5 -1
  27. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  28. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  29. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  30. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  31. data/lib/solargraph/doc_map.rb +134 -373
  32. data/lib/solargraph/equality.rb +1 -1
  33. data/lib/solargraph/gem_pins.rb +14 -15
  34. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  35. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  36. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  37. data/lib/solargraph/language_server/host/sources.rb +1 -0
  38. data/lib/solargraph/language_server/host.rb +6 -1
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  40. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  49. data/lib/solargraph/library.rb +59 -13
  50. data/lib/solargraph/location.rb +9 -4
  51. data/lib/solargraph/logging.rb +21 -1
  52. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  54. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  55. data/lib/solargraph/parser/node_processor.rb +7 -6
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  77. data/lib/solargraph/parser/region.rb +9 -3
  78. data/lib/solargraph/parser/snippet.rb +1 -1
  79. data/lib/solargraph/pin/base.rb +53 -21
  80. data/lib/solargraph/pin/base_variable.rb +312 -20
  81. data/lib/solargraph/pin/block.rb +26 -4
  82. data/lib/solargraph/pin/breakable.rb +5 -1
  83. data/lib/solargraph/pin/callable.rb +50 -3
  84. data/lib/solargraph/pin/closure.rb +2 -6
  85. data/lib/solargraph/pin/common.rb +20 -5
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +2 -1
  88. data/lib/solargraph/pin/delegated_method.rb +15 -4
  89. data/lib/solargraph/pin/documenting.rb +1 -0
  90. data/lib/solargraph/pin/instance_variable.rb +5 -1
  91. data/lib/solargraph/pin/keyword.rb +0 -4
  92. data/lib/solargraph/pin/local_variable.rb +13 -57
  93. data/lib/solargraph/pin/method.rb +90 -42
  94. data/lib/solargraph/pin/method_alias.rb +8 -0
  95. data/lib/solargraph/pin/namespace.rb +7 -1
  96. data/lib/solargraph/pin/parameter.rb +76 -13
  97. data/lib/solargraph/pin/proxy_type.rb +2 -1
  98. data/lib/solargraph/pin/reference/override.rb +1 -1
  99. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  100. data/lib/solargraph/pin/reference.rb +2 -0
  101. data/lib/solargraph/pin/search.rb +1 -0
  102. data/lib/solargraph/pin/signature.rb +8 -0
  103. data/lib/solargraph/pin/symbol.rb +1 -1
  104. data/lib/solargraph/pin/until.rb +1 -1
  105. data/lib/solargraph/pin/while.rb +1 -1
  106. data/lib/solargraph/pin.rb +2 -0
  107. data/lib/solargraph/pin_cache.rb +477 -57
  108. data/lib/solargraph/position.rb +12 -26
  109. data/lib/solargraph/range.rb +6 -6
  110. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  111. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  113. data/lib/solargraph/rbs_map.rb +74 -20
  114. data/lib/solargraph/shell.rb +73 -28
  115. data/lib/solargraph/source/chain/call.rb +52 -17
  116. data/lib/solargraph/source/chain/constant.rb +2 -0
  117. data/lib/solargraph/source/chain/hash.rb +1 -0
  118. data/lib/solargraph/source/chain/if.rb +1 -0
  119. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  120. data/lib/solargraph/source/chain/literal.rb +5 -0
  121. data/lib/solargraph/source/chain/or.rb +9 -1
  122. data/lib/solargraph/source/chain.rb +25 -22
  123. data/lib/solargraph/source/change.rb +9 -2
  124. data/lib/solargraph/source/cursor.rb +7 -1
  125. data/lib/solargraph/source/source_chainer.rb +13 -3
  126. data/lib/solargraph/source/updater.rb +4 -0
  127. data/lib/solargraph/source.rb +33 -7
  128. data/lib/solargraph/source_map/clip.rb +13 -2
  129. data/lib/solargraph/source_map/data.rb +4 -1
  130. data/lib/solargraph/source_map/mapper.rb +24 -1
  131. data/lib/solargraph/source_map.rb +14 -6
  132. data/lib/solargraph/type_checker/problem.rb +3 -1
  133. data/lib/solargraph/type_checker/rules.rb +75 -2
  134. data/lib/solargraph/type_checker.rb +111 -30
  135. data/lib/solargraph/version.rb +1 -1
  136. data/lib/solargraph/workspace/config.rb +3 -1
  137. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  138. data/lib/solargraph/workspace/require_paths.rb +1 -0
  139. data/lib/solargraph/workspace.rb +158 -16
  140. data/lib/solargraph/yard_map/helpers.rb +2 -1
  141. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  142. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  143. data/lib/solargraph/yard_map/mapper.rb +5 -0
  144. data/lib/solargraph/yardoc.rb +33 -23
  145. data/lib/solargraph.rb +24 -3
  146. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  147. data/rbs/fills/tuple/tuple.rbs +28 -0
  148. data/rbs/shims/ast/0/node.rbs +1 -1
  149. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  150. data/solargraph.gemspec +2 -1
  151. metadata +12 -7
  152. data/lib/solargraph/type_checker/checks.rb +0 -124
  153. data/lib/solargraph/type_checker/param_def.rb +0 -37
  154. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -24,6 +24,7 @@ module Solargraph
24
24
  end
25
25
  # Some yardocs contain documentation for dependencies that can be
26
26
  # ignored here. The YardMap will load dependencies separately.
27
+ # @sg-ignore Need to add nil check here
27
28
  @pins.keep_if { |pin| pin.location.nil? || File.file?(pin.location.filename) } if @spec
28
29
  @pins
29
30
  end
@@ -38,13 +39,17 @@ module Solargraph
38
39
  nspin = ToNamespace.make(code_object, @spec, @namespace_pins[code_object.namespace.to_s])
39
40
  @namespace_pins[code_object.path] = nspin
40
41
  result.push nspin
42
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
41
43
  if code_object.is_a?(YARD::CodeObjects::ClassObject) and !code_object.superclass.nil?
42
44
  # This method of superclass detection is a bit of a hack. If
43
45
  # the superclass is a Proxy, it is assumed to be undefined in its
44
46
  # yardoc and converted to a fully qualified namespace.
47
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
45
48
  superclass = if code_object.superclass.is_a?(YARD::CodeObjects::Proxy)
49
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
46
50
  "::#{code_object.superclass}"
47
51
  else
52
+ # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
48
53
  code_object.superclass.to_s
49
54
  end
50
55
  result.push Solargraph::Pin::Reference::Superclass.new(name: superclass, closure: nspin, source: :yard_map)
@@ -8,15 +8,15 @@ module Solargraph
8
8
  module Yardoc
9
9
  module_function
10
10
 
11
- # Build and cache a gem's yardoc and return the path. If the cache already
12
- # exists, do nothing and return the path.
11
+ # Build and save a gem's yardoc into a given path.
13
12
  #
14
- # @param yard_plugins [Array<String>] The names of YARD plugins to use.
13
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
14
+ # @param yard_plugins [Array<String>]
15
15
  # @param gemspec [Gem::Specification]
16
- # @return [String] The path to the cached yardoc.
17
- def cache(yard_plugins, gemspec)
18
- path = PinCache.yardoc_path gemspec
19
- return path if cached?(gemspec)
16
+ #
17
+ # @return [void]
18
+ def build_docs gem_yardoc_path, yard_plugins, gemspec
19
+ return if docs_built?(gem_yardoc_path)
20
20
 
21
21
  unless Dir.exist? gemspec.gem_dir
22
22
  # Can happen in at least some (old?) RubyGems versions when we
@@ -24,35 +24,44 @@ module Solargraph
24
24
  #
25
25
  # https://github.com/apiology/solargraph/actions/runs/17650140201/job/50158676842?pr=10
26
26
  Solargraph.logger.info { "Bad info from gemspec - #{gemspec.gem_dir} does not exist" }
27
- return path
27
+ return
28
28
  end
29
29
 
30
30
  Solargraph.logger.info "Caching yardoc for #{gemspec.name} #{gemspec.version}"
31
- cmd = "yardoc --db #{path} --no-output --plugin solargraph"
31
+ cmd = "yardoc --db #{gem_yardoc_path} --no-output --plugin solargraph"
32
32
  yard_plugins.each { |plugin| cmd << " --plugin #{plugin}" }
33
33
  Solargraph.logger.debug { "Running: #{cmd}" }
34
34
  # @todo set these up to run in parallel
35
+ # @sg-ignore Our fill won't work properly due to an issue in
36
+ # Callable#arity_matches? - see comment there
35
37
  stdout_and_stderr_str, status = Open3.capture2e(current_bundle_env_tweaks, cmd, chdir: gemspec.gem_dir)
36
- unless status.success?
37
- Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
38
- Solargraph.logger.info stdout_and_stderr_str
39
- end
40
- path
38
+ return if status.success?
39
+ Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
40
+ Solargraph.logger.info stdout_and_stderr_str
41
+ end
42
+
43
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
44
+ # @param gemspec [Gem::Specification, Bundler::LazySpecification]
45
+ # @param out [StringIO, IO, nil] where to log messages
46
+ # @return [Array<Pin::Base>]
47
+ def build_pins gem_yardoc_path, gemspec, out: $stderr
48
+ yardoc = load!(gem_yardoc_path)
49
+ YardMap::Mapper.new(yardoc, gemspec).map
41
50
  end
42
51
 
43
52
  # True if the gem yardoc is cached.
44
53
  #
45
- # @param gemspec [Gem::Specification]
46
- def cached?(gemspec)
47
- yardoc = File.join(PinCache.yardoc_path(gemspec), 'complete')
54
+ # @param gem_yardoc_path [String]
55
+ def docs_built? gem_yardoc_path
56
+ yardoc = File.join(gem_yardoc_path, 'complete')
48
57
  File.exist?(yardoc)
49
58
  end
50
59
 
51
60
  # True if another process is currently building the yardoc cache.
52
61
  #
53
- # @param gemspec [Gem::Specification]
54
- def processing?(gemspec)
55
- yardoc = File.join(PinCache.yardoc_path(gemspec), 'processing')
62
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
63
+ def processing? gem_yardoc_path
64
+ yardoc = File.join(gem_yardoc_path, 'processing')
56
65
  File.exist?(yardoc)
57
66
  end
58
67
 
@@ -60,10 +69,10 @@ module Solargraph
60
69
  #
61
70
  # @note This method modifies the global YARD registry.
62
71
  #
63
- # @param gemspec [Gem::Specification]
72
+ # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
64
73
  # @return [Array<YARD::CodeObjects::Base>]
65
- def load!(gemspec)
66
- YARD::Registry.load! PinCache.yardoc_path gemspec
74
+ def load! gem_yardoc_path
75
+ YARD::Registry.load! gem_yardoc_path
67
76
  YARD::Registry.all
68
77
  end
69
78
 
@@ -78,6 +87,7 @@ module Solargraph
78
87
  # @return [Hash{String => String}] a hash of environment variables to override
79
88
  def current_bundle_env_tweaks
80
89
  tweaks = {}
90
+ # @sg-ignore Translate to something flow sensitive typing understands
81
91
  if ENV['BUNDLE_GEMFILE'] && !ENV['BUNDLE_GEMFILE'].empty?
82
92
  tweaks['BUNDLE_GEMFILE'] = File.expand_path(ENV['BUNDLE_GEMFILE'])
83
93
  end
data/lib/solargraph.rb CHANGED
@@ -55,8 +55,8 @@ module Solargraph
55
55
 
56
56
  CHDIR_MUTEX = Mutex.new
57
57
 
58
- # @param type [Symbol] Type of assert.
59
- def self.asserts_on?(type)
58
+ def self.asserts_on?
59
+ # @sg-ignore Translate to something flow sensitive typing understands
60
60
  if ENV['SOLARGRAPH_ASSERTS'].nil? || ENV['SOLARGRAPH_ASSERTS'].empty?
61
61
  false
62
62
  elsif ENV['SOLARGRAPH_ASSERTS'] == 'on'
@@ -72,7 +72,28 @@ module Solargraph
72
72
  # @param block [Proc] A block that returns a message to log
73
73
  # @return [void]
74
74
  def self.assert_or_log(type, msg = nil, &block)
75
- raise (msg || block.call) if asserts_on?(type) && ![:combine_with_visibility].include?(type)
75
+ if asserts_on?
76
+ # @type [String, nil]
77
+ msg ||= block.call
78
+
79
+ raise "No message given for #{type.inspect}" if msg.nil?
80
+
81
+ # conditional aliases to handle compatibility corner cases
82
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
83
+ return if type == :alias_target_missing && msg.include?('highline/compatibility.rb')
84
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
85
+ return if type == :alias_target_missing && msg.include?('lib/json/add/date.rb')
86
+ # @todo :combine_with_visibility is not ready for prime time -
87
+ # lots of disagreements found in practice that heuristics need
88
+ # to be created for and/or debugging needs to resolve in pin
89
+ # generation.
90
+ # @todo :api_map_namespace_pin_stack triggers in a badly handled
91
+ # self type case - 'keeps track of self type in method
92
+ # parameters in subclass' in call_spec.rb
93
+ return if %i[api_map_namespace_pin_stack combine_with_visibility].include?(type)
94
+
95
+ raise msg
96
+ end
76
97
  logger.info msg, &block
77
98
  end
78
99
 
@@ -0,0 +1,193 @@
1
+ # <!-- rdoc-file=lib/rubygems/dependency.rb -->
2
+ # The Dependency class holds a Gem name and a Gem::Requirement.
3
+ #
4
+ class Gem::Dependency
5
+ @name: untyped
6
+
7
+ @requirement: untyped
8
+
9
+ @type: untyped
10
+
11
+ @prerelease: untyped
12
+
13
+ @version_requirements: untyped
14
+
15
+ @version_requirement: untyped
16
+
17
+ # <!-- rdoc-file=lib/rubygems/dependency.rb -->
18
+ # Valid dependency types.
19
+ #
20
+ TYPES: ::Array[:development | :runtime]
21
+
22
+ # <!-- rdoc-file=lib/rubygems/dependency.rb -->
23
+ # Dependency name or regular expression.
24
+ #
25
+ attr_accessor name: untyped
26
+
27
+ # <!-- rdoc-file=lib/rubygems/dependency.rb -->
28
+ # Allows you to force this dependency to be a prerelease.
29
+ #
30
+ attr_writer prerelease: untyped
31
+
32
+ # <!--
33
+ # rdoc-file=lib/rubygems/dependency.rb
34
+ # - new(name, *requirements)
35
+ # -->
36
+ # Constructs a dependency with `name` and `requirements`. The last argument can
37
+ # optionally be the dependency type, which defaults to `:runtime`.
38
+ #
39
+ def initialize: (untyped name, *untyped requirements) -> void
40
+
41
+ def hash: () -> untyped
42
+
43
+ def inspect: () -> untyped
44
+
45
+ # <!--
46
+ # rdoc-file=lib/rubygems/dependency.rb
47
+ # - prerelease?()
48
+ # -->
49
+ # Does this dependency require a prerelease?
50
+ #
51
+ def prerelease?: () -> untyped
52
+
53
+ # <!--
54
+ # rdoc-file=lib/rubygems/dependency.rb
55
+ # - latest_version?()
56
+ # -->
57
+ # Is this dependency simply asking for the latest version of a gem?
58
+ #
59
+ def latest_version?: () -> untyped
60
+
61
+ def pretty_print: (untyped q) -> untyped
62
+
63
+ # <!--
64
+ # rdoc-file=lib/rubygems/dependency.rb
65
+ # - requirement()
66
+ # -->
67
+ # What does this dependency require?
68
+ #
69
+ def requirement: () -> untyped
70
+
71
+ # <!--
72
+ # rdoc-file=lib/rubygems/dependency.rb
73
+ # - requirements_list()
74
+ # -->
75
+ #
76
+ def requirements_list: () -> untyped
77
+
78
+ def to_s: () -> ::String
79
+
80
+ # <!--
81
+ # rdoc-file=lib/rubygems/dependency.rb
82
+ # - type()
83
+ # -->
84
+ # Dependency type.
85
+ #
86
+ def type: () -> untyped
87
+
88
+ # <!--
89
+ # rdoc-file=lib/rubygems/dependency.rb
90
+ # - runtime?()
91
+ # -->
92
+ #
93
+ def runtime?: () -> untyped
94
+
95
+ def ==: (untyped other) -> untyped
96
+
97
+ # <!--
98
+ # rdoc-file=lib/rubygems/dependency.rb
99
+ # - <=>(other)
100
+ # -->
101
+ # Dependencies are ordered by name.
102
+ #
103
+ def <=>: (untyped other) -> untyped
104
+
105
+ # <!--
106
+ # rdoc-file=lib/rubygems/dependency.rb
107
+ # - =~(other)
108
+ # -->
109
+ # Uses this dependency as a pattern to compare to `other`. This dependency will
110
+ # match if the name matches the other's name, and other has only an equal
111
+ # version requirement that satisfies this dependency.
112
+ #
113
+ def =~: (untyped other) -> (nil | false | untyped)
114
+
115
+ # <!--
116
+ # rdoc-file=lib/rubygems/dependency.rb
117
+ # - ===(other)
118
+ # -->
119
+ #
120
+ alias === =~
121
+
122
+ # <!--
123
+ # rdoc-file=lib/rubygems/dependency.rb
124
+ # - dep.match? name => true or false
125
+ # - dep.match? name, version => true or false
126
+ # - dep.match? spec => true or false
127
+ # -->
128
+ # Does this dependency match the specification described by `name` and `version`
129
+ # or match `spec`?
130
+ #
131
+ # NOTE: Unlike #matches_spec? this method does not return true when the version
132
+ # is a prerelease version unless this is a prerelease dependency.
133
+ #
134
+ def match?: (untyped obj, ?untyped? version, ?bool allow_prerelease) -> (false | true | untyped)
135
+
136
+ # <!--
137
+ # rdoc-file=lib/rubygems/dependency.rb
138
+ # - matches_spec?(spec)
139
+ # -->
140
+ # Does this dependency match `spec`?
141
+ #
142
+ # NOTE: This is not a convenience method. Unlike #match? this method returns
143
+ # true when `spec` is a prerelease version even if this dependency is not a
144
+ # prerelease dependency.
145
+ #
146
+ def matches_spec?: (untyped spec) -> (false | true | untyped)
147
+
148
+ # <!--
149
+ # rdoc-file=lib/rubygems/dependency.rb
150
+ # - merge(other)
151
+ # -->
152
+ # Merges the requirements of `other` into this dependency
153
+ #
154
+ def merge: (untyped other) -> untyped
155
+
156
+ # <!--
157
+ # rdoc-file=lib/rubygems/dependency.rb
158
+ # - matching_specs(platform_only = false)
159
+ # -->
160
+ #
161
+ def matching_specs: (?bool platform_only) -> untyped
162
+
163
+ # <!--
164
+ # rdoc-file=lib/rubygems/dependency.rb
165
+ # - specific?()
166
+ # -->
167
+ # True if the dependency will not always match the latest version.
168
+ #
169
+ def specific?: () -> untyped
170
+
171
+ # <!--
172
+ # rdoc-file=lib/rubygems/dependency.rb
173
+ # - to_specs()
174
+ # -->
175
+ #
176
+ def to_specs: () -> untyped
177
+
178
+ # <!--
179
+ # rdoc-file=lib/rubygems/dependency.rb
180
+ # - to_spec()
181
+ # -->
182
+ #
183
+ def to_spec: () -> untyped
184
+
185
+ # <!--
186
+ # rdoc-file=lib/rubygems/dependency.rb
187
+ # - identity()
188
+ # -->
189
+ #
190
+ def identity: () -> (:complete | :abs_latest | :latest | :released)
191
+
192
+ def encode_with: (untyped coder) -> untyped
193
+ end
@@ -144,6 +144,34 @@ module Solargraph
144
144
  | [T] (8 index) { (int index) -> T } -> (I | T)
145
145
  | [T] (9 index) { (int index) -> T } -> (J | T)
146
146
  | [T] (int index) { (int index) -> T } -> (A | B | C | D | E | F | G | H | I | J | T)
147
+
148
+ # <!--
149
+ # rdoc-file=array.rb
150
+ # - first -> object or nil
151
+ # - first(count) -> new_array
152
+ # -->
153
+ # Returns elements from `self`, or `nil`; does not modify `self`.
154
+ #
155
+ # With no argument given, returns the first element (if available):
156
+ #
157
+ # a = [:foo, 'bar', 2]
158
+ # a.first # => :foo
159
+ # a # => [:foo, "bar", 2]
160
+ #
161
+ # If `self` is empty, returns `nil`.
162
+ #
163
+ # [].first # => nil
164
+ #
165
+ # With a non-negative integer argument `count` given, returns the first `count`
166
+ # elements (as available) in a new array:
167
+ #
168
+ # a.first(0) # => []
169
+ # a.first(2) # => [:foo, "bar"]
170
+ # a.first(50) # => [:foo, "bar", 2]
171
+ #
172
+ # Related: see [Methods for Querying](rdoc-ref:Array@Methods+for+Querying).
173
+ #
174
+ def first: %a{implicitly-returns-nil} () -> A
147
175
  end
148
176
  end
149
177
  end
@@ -1,5 +1,5 @@
1
1
  module ::AST
2
2
  class Node
3
- def children: () -> [self, Integer, String, Symbol, nil]
3
+ def children: () -> Array[self | Integer | String | Symbol | nil]
4
4
  end
5
5
  end
@@ -0,0 +1,11 @@
1
+ module Diff
2
+ end
3
+
4
+ module Diff::LCS
5
+ def self.LCS: (Array[String], Array[String]) -> Array[String]
6
+ | (String, String) -> Array[String]
7
+ def self.diff: (Array[String], Array[String]) -> Array[Array[String]]
8
+ | (String, String) -> Array[Array[Diff::LCS::Change]]
9
+
10
+ def self.patch!: (Array[String], Array[String]) -> String
11
+ end
data/solargraph.gemspec CHANGED
@@ -1,3 +1,4 @@
1
+ # @sg-ignore Should better support meaning of '&' in RBS
1
2
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
2
3
  require 'solargraph/version'
3
4
  require 'date'
@@ -42,7 +43,7 @@ Gem::Specification.new do |s|
42
43
  s.add_runtime_dependency 'open3', '~> 0.2.1'
43
44
  s.add_runtime_dependency 'parser', '~> 3.0'
44
45
  s.add_runtime_dependency 'prism', '~> 1.4'
45
- s.add_runtime_dependency 'rbs', ['>= 3.6.1', '<= 4.0.0.dev.4']
46
+ s.add_runtime_dependency 'rbs', ['>= 3.6.1', '<= 4.0.0.dev.5']
46
47
  s.add_runtime_dependency 'reverse_markdown', '~> 3.0'
47
48
  s.add_runtime_dependency 'rubocop', '~> 1.76'
48
49
  s.add_runtime_dependency 'thor', '~> 1.0'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.58.2
4
+ version: 0.59.0.dev.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-01-19 00:00:00.000000000 Z
10
+ date: 2026-01-13 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ast
@@ -220,7 +220,7 @@ dependencies:
220
220
  version: 3.6.1
221
221
  - - "<="
222
222
  - !ruby/object:Gem::Version
223
- version: 4.0.0.dev.4
223
+ version: 4.0.0.dev.5
224
224
  type: :runtime
225
225
  prerelease: false
226
226
  version_requirements: !ruby/object:Gem::Requirement
@@ -230,7 +230,7 @@ dependencies:
230
230
  version: 3.6.1
231
231
  - - "<="
232
232
  - !ruby/object:Gem::Version
233
- version: 4.0.0.dev.4
233
+ version: 4.0.0.dev.5
234
234
  - !ruby/object:Gem::Dependency
235
235
  name: reverse_markdown
236
236
  requirement: !ruby/object:Gem::Requirement
@@ -538,6 +538,7 @@ executables:
538
538
  extensions: []
539
539
  extra_rdoc_files: []
540
540
  files:
541
+ - ".envrc"
541
542
  - ".gitattributes"
542
543
  - ".github/FUNDING.yml"
543
544
  - ".github/workflows/linting.yml"
@@ -566,6 +567,7 @@ files:
566
567
  - lib/solargraph/api_map/store.rb
567
568
  - lib/solargraph/bench.rb
568
569
  - lib/solargraph/complex_type.rb
570
+ - lib/solargraph/complex_type/conformance.rb
569
571
  - lib/solargraph/complex_type/type_methods.rb
570
572
  - lib/solargraph/complex_type/unique_type.rb
571
573
  - lib/solargraph/convention.rb
@@ -688,12 +690,14 @@ files:
688
690
  - lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb
689
691
  - lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb
690
692
  - lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb
693
+ - lib/solargraph/parser/parser_gem/node_processors/or_node.rb
691
694
  - lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb
692
695
  - lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb
693
696
  - lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb
694
697
  - lib/solargraph/parser/parser_gem/node_processors/send_node.rb
695
698
  - lib/solargraph/parser/parser_gem/node_processors/sym_node.rb
696
699
  - lib/solargraph/parser/parser_gem/node_processors/until_node.rb
700
+ - lib/solargraph/parser/parser_gem/node_processors/when_node.rb
697
701
  - lib/solargraph/parser/parser_gem/node_processors/while_node.rb
698
702
  - lib/solargraph/parser/region.rb
699
703
  - lib/solargraph/parser/snippet.rb
@@ -706,6 +710,7 @@ files:
706
710
  - lib/solargraph/pin/class_variable.rb
707
711
  - lib/solargraph/pin/closure.rb
708
712
  - lib/solargraph/pin/common.rb
713
+ - lib/solargraph/pin/compound_statement.rb
709
714
  - lib/solargraph/pin/constant.rb
710
715
  - lib/solargraph/pin/conversions.rb
711
716
  - lib/solargraph/pin/delegated_method.rb
@@ -774,8 +779,6 @@ files:
774
779
  - lib/solargraph/source_map/data.rb
775
780
  - lib/solargraph/source_map/mapper.rb
776
781
  - lib/solargraph/type_checker.rb
777
- - lib/solargraph/type_checker/checks.rb
778
- - lib/solargraph/type_checker/param_def.rb
779
782
  - lib/solargraph/type_checker/problem.rb
780
783
  - lib/solargraph/type_checker/rules.rb
781
784
  - lib/solargraph/version.rb
@@ -788,6 +791,7 @@ files:
788
791
  - lib/solargraph/views/search.erb
789
792
  - lib/solargraph/workspace.rb
790
793
  - lib/solargraph/workspace/config.rb
794
+ - lib/solargraph/workspace/gemspecs.rb
791
795
  - lib/solargraph/workspace/require_paths.rb
792
796
  - lib/solargraph/yard_map.rb
793
797
  - lib/solargraph/yard_map/cache.rb
@@ -796,12 +800,12 @@ files:
796
800
  - lib/solargraph/yard_map/mapper/to_constant.rb
797
801
  - lib/solargraph/yard_map/mapper/to_method.rb
798
802
  - lib/solargraph/yard_map/mapper/to_namespace.rb
799
- - lib/solargraph/yard_map/to_method.rb
800
803
  - lib/solargraph/yard_tags.rb
801
804
  - lib/solargraph/yardoc.rb
802
805
  - rbs/fills/bundler/0/bundler.rbs
803
806
  - rbs/fills/open3/0/open3.rbs
804
807
  - rbs/fills/rubygems/0/basic_specification.rbs
808
+ - rbs/fills/rubygems/0/dependency.rbs
805
809
  - rbs/fills/rubygems/0/errors.rbs
806
810
  - rbs/fills/rubygems/0/spec_fetcher.rbs
807
811
  - rbs/fills/rubygems/0/specification.rbs
@@ -809,6 +813,7 @@ files:
809
813
  - rbs/shims/ast/0/node.rbs
810
814
  - rbs/shims/ast/2.4/.rbs_meta.yaml
811
815
  - rbs/shims/ast/2.4/ast.rbs
816
+ - rbs/shims/diff-lcs/1.5/diff-lcs.rbs
812
817
  - rbs/shims/parser/3.2.0.1/builders/default.rbs
813
818
  - rbs/shims/parser/3.2.0.1/manifest.yaml
814
819
  - rbs/shims/parser/3.2.0.1/parser.rbs
@@ -1,124 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class TypeChecker
5
- # Helper methods for performing type checks
6
- #
7
- module Checks
8
- module_function
9
-
10
- # Compare an expected type with an inferred type. Common usage is to
11
- # check if the type declared in a method's @return tag matches the type
12
- # inferred from static analysis of the code.
13
- #
14
- # @param api_map [ApiMap]
15
- # @param expected [ComplexType]
16
- # @param inferred [ComplexType]
17
- # @return [Boolean]
18
- def types_match? api_map, expected, inferred
19
- return true if expected.to_s == inferred.to_s
20
- matches = []
21
- expected.each do |exp|
22
- found = false
23
- inferred.each do |inf|
24
- # if api_map.super_and_sub?(fuzz(inf), fuzz(exp))
25
- if either_way?(api_map, inf, exp)
26
- found = true
27
- matches.push inf
28
- break
29
- end
30
- end
31
- return false unless found
32
- end
33
- inferred.each do |inf|
34
- next if matches.include?(inf)
35
- found = false
36
- expected.each do |exp|
37
- # if api_map.super_and_sub?(fuzz(inf), fuzz(exp))
38
- if either_way?(api_map, inf, exp)
39
- found = true
40
- break
41
- end
42
- end
43
- return false unless found
44
- end
45
- true
46
- end
47
-
48
- # @param api_map [ApiMap]
49
- # @param expected [ComplexType]
50
- # @param inferred [ComplexType]
51
- # @return [Boolean]
52
- def any_types_match? api_map, expected, inferred
53
- expected = expected.downcast_to_literal_if_possible
54
- inferred = inferred.downcast_to_literal_if_possible
55
- return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
56
- # walk through the union expected type and see if any members
57
- # of the union match the inferred type
58
- expected.each do |exp|
59
- next if exp.duck_type?
60
- # @todo: there should be a level of typechecking where all
61
- # unique types in the inferred must match one of the
62
- # expected unique types
63
- inferred.each do |inf|
64
- # return true if exp == inf || api_map.super_and_sub?(fuzz(inf), fuzz(exp))
65
- return true if exp == inf || either_way?(api_map, inf, exp)
66
- end
67
- end
68
- false
69
- end
70
-
71
- # @param api_map [ApiMap]
72
- # @param inferred [ComplexType]
73
- # @param expected [ComplexType]
74
- # @return [Boolean]
75
- def all_types_match? api_map, inferred, expected
76
- expected = expected.downcast_to_literal_if_possible
77
- inferred = inferred.downcast_to_literal_if_possible
78
- return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
79
- inferred.each do |inf|
80
- next if inf.duck_type?
81
- return false unless expected.any? { |exp| exp == inf || either_way?(api_map, inf, exp) }
82
- end
83
- true
84
- end
85
-
86
- # @param api_map [ApiMap]
87
- # @param expected [ComplexType]
88
- # @param inferred [ComplexType]
89
- # @return [Boolean]
90
- def duck_types_match? api_map, expected, inferred
91
- raise ArgumentError, 'Expected type must be duck type' unless expected.duck_type?
92
- expected.each do |exp|
93
- next unless exp.duck_type?
94
- quack = exp.to_s[1..-1]
95
- return false if api_map.get_method_stack(inferred.namespace, quack, scope: inferred.scope).empty?
96
- end
97
- true
98
- end
99
-
100
- # @param type [ComplexType::UniqueType]
101
- # @return [String]
102
- def fuzz type
103
- if type.parameters?
104
- type.name
105
- else
106
- type.tag
107
- end
108
- end
109
-
110
- # @param api_map [ApiMap]
111
- # @param cls1 [ComplexType::UniqueType]
112
- # @param cls2 [ComplexType::UniqueType]
113
- # @return [Boolean]
114
- def either_way?(api_map, cls1, cls2)
115
- # @todo there should be a level of typechecking which uses the
116
- # full tag with parameters to determine compatibility
117
- f1 = cls1.name
118
- f2 = cls2.name
119
- api_map.type_include?(f1, f2) || api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1)
120
- # api_map.type_include?(f1, f2) || api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1)
121
- end
122
- end
123
- end
124
- end