Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
6acfa0c
RuboCop todo file stability
apiology Aug 30, 2025
14be6bf
Merge remote-tracking branch 'origin/master' into rubocop_stability
apiology Aug 30, 2025
61260f3
Fix merge issue
apiology Aug 30, 2025
f632481
Centralize all pin-caching logic in PinCache
apiology Sep 3, 2025
c7b66cf
Exclude more scenarios that RBS does not support
apiology Sep 4, 2025
eb676b7
Fix indentation
apiology Sep 4, 2025
8ea2104
Adjust comment location
apiology Sep 4, 2025
2b3152e
Ensure using latest RBS version in undercover
apiology Sep 4, 2025
1b644b4
Add regression specs
apiology Sep 4, 2025
102f711
Merge branch 'rubocop_stability' into add_regression_specs
apiology Sep 4, 2025
71c2db0
Merge branch 'add_regression_specs' into pin_cache_refactor
apiology Sep 4, 2025
aafaa5d
Ensure overrides are handled properly regardless of state of pin
apiology Sep 4, 2025
e2ba569
Lint fixes
apiology Sep 4, 2025
adde97d
Merge remote-tracking branch 'origin/master' into pin_cache_refactor
apiology Sep 6, 2025
8edc773
Merge remote-tracking branch 'origin/master' into rubocop_stability
apiology Sep 6, 2025
bb0f607
Rerun rubocop todo
apiology Sep 6, 2025
7cb3edd
Merge branch 'master' into pin_cache_refactor
apiology Sep 7, 2025
837d7f6
Force build
apiology Sep 7, 2025
a4208e7
Restore
apiology Sep 7, 2025
f08b76a
Merge remote-tracking branch 'origin/master' into fix_solargraph_rspe…
apiology Sep 7, 2025
b66f2ac
install -> update with rbs collection
apiology Sep 7, 2025
a09a9af
Try Ruby 3.2
apiology Sep 7, 2025
6fc8feb
Update solargraph
apiology Sep 7, 2025
388c170
Re-add bundle install
apiology Sep 7, 2025
f80b73a
Drop MATRIX_SOLARGRAPH_VERSION
apiology Sep 7, 2025
ce2bee6
Drop debugging changes
apiology Sep 7, 2025
c261704
Merge remote-tracking branch 'origin/master' into rubocop_stability
apiology Sep 7, 2025
dbe9a3e
Update expectations from master branch
apiology Sep 7, 2025
620fa00
Merge branch 'fix_solargraph_rspec_check' into rubocop_stability
apiology Sep 7, 2025
217fecd
Update expectations from master branch
apiology Sep 7, 2025
2d2f0a7
install -> update with rbs collection
apiology Sep 7, 2025
3db4b1f
Try Ruby 3.2
apiology Sep 7, 2025
faa6428
Update solargraph
apiology Sep 7, 2025
3f68a02
Re-add bundle install
apiology Sep 7, 2025
b8c1605
Drop MATRIX_SOLARGRAPH_VERSION
apiology Sep 7, 2025
d3a0c36
Drop debugging changes
apiology Sep 7, 2025
9b713b2
Fix combined gem cache implementation
apiology Sep 9, 2025
1b12d27
Merge branch 'master' into rubocop_stability
apiology Sep 13, 2025
db725f7
Update rubocop todo
apiology Sep 13, 2025
84c605a
Merge branch 'master' into pin_cache_refactor
apiology Sep 13, 2025
743b71c
Merge branch 'rubocop_stability' into pin_cache_refactor
apiology Sep 13, 2025
64de402
Merge branch 'master' into pin_cache_refactor
apiology Sep 16, 2025
004b7a4
Merge remote-tracking branch 'origin/master' into pin_cache_refactor
apiology Sep 30, 2025
eabe151
Update rubocop todo
apiology Sep 30, 2025
ce3ce8c
Fix merge issue
apiology Sep 30, 2025
a6bdfd6
Drop no-longer-needed @sg-ignores
apiology Sep 30, 2025
096ff16
Merge remote-tracking branch 'origin/master' into pin_cache_refactor
apiology Oct 6, 2025
88e1f73
Fix merge
apiology Oct 6, 2025
d9fa32f
Fix a Gem::Specification class limitation found on another branch
apiology Oct 8, 2025
f4f1620
Fix RuboCop issues
apiology Oct 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,20 @@ jobs:
matrix:
ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4', 'head']
rbs-version: ['3.6.1', '3.9.4', '4.0.0.dev.4']
# Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4
exclude:
# Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4
- ruby-version: '3.0'
rbs-version: '3.9.4'
- ruby-version: '3.0'
rbs-version: '4.0.0.dev.4'
# Missing require in 'rbs collection update' - hopefully
# fixed in next RBS dev release
- ruby-version: 'head'
rbs-version: '4.0.0.dev.4'
- ruby-version: 'head'
rbs-version: '3.9.4'
- ruby-version: 'head'
rbs-version: '3.6.1'
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
Expand All @@ -48,6 +56,8 @@ jobs:
run: |
bundle install
bundle update rbs # use latest available for this Ruby version
- name: Install types
run: bundle exec rbs collection update
- name: Run tests
run: bundle exec rake spec
undercover:
Expand All @@ -64,7 +74,11 @@ jobs:
ruby-version: '3.4'
bundler-cache: false
- name: Install gems
run: bundle install
run: |
bundle install
bundle update rbs # use latest available for this Ruby version
- name: Install types
run: bundle exec rbs collection update
- name: Run tests
run: bundle exec rake spec
- name: Check PR coverage
Expand Down
23 changes: 0 additions & 23 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ Gemspec/OrderedDependencies:
# Configuration parameters: Severity.
Gemspec/RequireMFA:
Exclude:
- 'solargraph.gemspec'
- 'spec/fixtures/rdoc-lib/rdoc-lib.gemspec'
- 'spec/fixtures/rubocop-custom-version/specifications/rubocop-0.0.0.gemspec'

Expand Down Expand Up @@ -201,7 +200,6 @@ Layout/MultilineMethodCallIndentation:
# SupportedStyles: aligned, indented
Layout/MultilineOperationIndentation:
Exclude:
- 'lib/solargraph/api_map.rb'
- 'lib/solargraph/language_server/host/dispatch.rb'
- 'lib/solargraph/source.rb'

Expand Down Expand Up @@ -432,12 +430,6 @@ Lint/UnusedBlockArgument:
Lint/UnusedMethodArgument:
Enabled: false

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
- 'lib/solargraph/api_map.rb'

# This cop supports safe autocorrection (--autocorrect).
Lint/UselessAssignment:
Enabled: false
Expand Down Expand Up @@ -554,7 +546,6 @@ Naming/VariableName:
RSpec/Be:
Exclude:
- 'spec/rbs_map/stdlib_map_spec.rb'
- 'spec/rbs_map_spec.rb'
- 'spec/source/source_chainer_spec.rb'

# This cop supports unsafe autocorrection (--autocorrect-all).
Expand All @@ -577,7 +568,6 @@ RSpec/BeforeAfterAll:
- '**/spec/rails_helper.rb'
- '**/spec/support/**/*.rb'
- 'spec/api_map_spec.rb'
- 'spec/doc_map_spec.rb'
- 'spec/language_server/host/dispatch_spec.rb'
- 'spec/language_server/protocol_spec.rb'

Expand Down Expand Up @@ -664,14 +654,6 @@ RSpec/LetBeforeExamples:
Exclude:
- 'spec/complex_type_spec.rb'

# Configuration parameters: EnforcedStyle.
# SupportedStyles: have_received, receive
RSpec/MessageSpies:
Exclude:
- 'spec/doc_map_spec.rb'
- 'spec/language_server/host/diagnoser_spec.rb'
- 'spec/language_server/host/message_worker_spec.rb'

RSpec/MissingExampleGroupArgument:
Exclude:
- 'spec/diagnostics/rubocop_helpers_spec.rb'
Expand Down Expand Up @@ -732,10 +714,6 @@ RSpec/ScatteredLet:
Exclude:
- 'spec/complex_type_spec.rb'

RSpec/StubbedMock:
Exclude:
- 'spec/language_server/host/message_worker_spec.rb'

# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
RSpec/VerifiedDoubles:
Enabled: false
Expand Down Expand Up @@ -1125,7 +1103,6 @@ Style/RedundantRegexpEscape:
Style/RedundantReturn:
Exclude:
- 'lib/solargraph/complex_type/type_methods.rb'
- 'lib/solargraph/doc_map.rb'
- 'lib/solargraph/parser/parser_gem/node_methods.rb'
- 'lib/solargraph/source/chain/z_super.rb'

Expand Down
81 changes: 39 additions & 42 deletions lib/solargraph/api_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ def initialize pins: []
index pins
end

# @param out [IO, nil] output stream for logging
# @return [void]
def self.reset_core out: nil
@@core_map = RbsMap::CoreMap.new
end

#
# This is a mutable object, which is cached in the Chain class -
# if you add any fields which change the results of calls (not
Expand All @@ -47,6 +53,7 @@ def ==(other)
self.eql?(other)
end

# @return [Integer]
def hash
equality_fields.hash
end
Expand Down Expand Up @@ -97,11 +104,11 @@ def catalog bench
end
unresolved_requires = (bench.external_requires + conventions_environ.requires + bench.workspace.config.required).to_a.compact.uniq
recreate_docmap = @unresolved_requires != unresolved_requires ||
@doc_map&.uncached_yard_gemspecs&.any? ||
@doc_map&.uncached_rbs_collection_gemspecs&.any? ||
@doc_map&.rbs_collection_path != bench.workspace.rbs_collection_path
workspace.rbs_collection_path != bench.workspace.rbs_collection_path ||
@doc_map.any_uncached?

if recreate_docmap
@doc_map = DocMap.new(unresolved_requires, [], bench.workspace) # @todo Implement gem preferences
@doc_map = DocMap.new(unresolved_requires, [], bench.workspace, out: nil) # @todo Implement gem preferences
@unresolved_requires = @doc_map.unresolved_requires
end
@cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins)
Expand All @@ -116,26 +123,14 @@ def catalog bench
[self.class, @source_map_hash, conventions_environ, @doc_map, @unresolved_requires]
end

# @return [DocMap]
def doc_map
@doc_map ||= DocMap.new([], [])
end
# @return [DocMap, nil]
attr_reader :doc_map

# @return [::Array<Gem::Specification>]
def uncached_gemspecs
@doc_map&.uncached_gemspecs || []
end

# @return [::Array<Gem::Specification>]
def uncached_rbs_collection_gemspecs
@doc_map.uncached_rbs_collection_gemspecs
end

# @return [::Array<Gem::Specification>]
def uncached_yard_gemspecs
@doc_map.uncached_yard_gemspecs
end

# @return [Enumerable<Pin::Base>]
def core_pins
@@core_map.pins
Expand Down Expand Up @@ -193,8 +188,8 @@ def self.load directory

# @param out [IO, nil]
# @return [void]
def cache_all!(out)
@doc_map.cache_all!(out)
def cache_all_for_doc_map! out
@doc_map.cache_doc_map_gems!(out)
end

# @param gemspec [Gem::Specification]
Expand All @@ -217,14 +212,14 @@ class << self
# @param out [IO] The output stream for messages
#
# @return [ApiMap]
def self.load_with_cache directory, out
def self.load_with_cache directory, out = $stderr
api_map = load(directory)
if api_map.uncached_gemspecs.empty?
logger.info { "All gems cached for #{directory}" }
return api_map
end

api_map.cache_all!(out)
api_map.cache_all_for_doc_map!(out)
load(directory)
end

Expand All @@ -240,13 +235,6 @@ def keyword_pins
store.pins_by_class(Pin::Keyword)
end

# An array of namespace names defined in the ApiMap.
#
# @return [Set<String>]
def namespaces
store.namespaces
end

# True if the namespace exists.
#
# @param name [String] The namespace to match
Expand Down Expand Up @@ -334,7 +322,7 @@ def get_includes(fqns)
# @param namespace [String] A fully qualified namespace
# @param scope [Symbol] :instance or :class
# @return [Array<Solargraph::Pin::InstanceVariable>]
def get_instance_variable_pins(namespace, scope = :instance)
def get_instance_variable_pins namespace, scope = :instance
result = []
used = [namespace]
result.concat store.get_instance_variables(namespace, scope)
Expand All @@ -346,8 +334,10 @@ def get_instance_variable_pins(namespace, scope = :instance)
result
end

# @sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins
# @see Solargraph::Parser::FlowSensitiveTyping#visible_pins
# @param (see Solargraph::Parser::FlowSensitiveTyping#visible_pins)
# @sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins
# @return (see Solargraph::Parser::FlowSensitiveTyping#visible_pins)
def visible_pins(*args, **kwargs, &blk)
Solargraph::Parser::FlowSensitiveTyping.visible_pins(*args, **kwargs, &blk)
end
Expand All @@ -356,7 +346,7 @@ def visible_pins(*args, **kwargs, &blk)
#
# @param namespace [String] A fully qualified namespace
# @return [Enumerable<Solargraph::Pin::ClassVariable>]
def get_class_variable_pins(namespace)
def get_class_variable_pins namespace
prefer_non_nil_variables(store.get_class_variables(namespace))
end

Expand Down Expand Up @@ -537,7 +527,7 @@ def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private,
# @deprecated Use #get_path_pins instead.
#
# @param path [String] The path to find
# @return [Enumerable<Solargraph::Pin::Base>]
# @return [Array<Solargraph::Pin::Base>]
def get_path_suggestions path
return [] if path.nil?
resolve_method_aliases store.get_path_pins(path)
Expand All @@ -546,7 +536,7 @@ def get_path_suggestions path
# Get an array of pins that match the specified path.
#
# @param path [String]
# @return [Enumerable<Pin::Base>]
# @return [Array<Pin::Base>]
def get_path_pins path
get_path_suggestions(path)
end
Expand Down Expand Up @@ -678,10 +668,17 @@ def resolve_method_aliases pins, visibility = [:public, :private, :protected]
next nil if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
resolved
end.compact
logger.debug { "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" }
logger.debug do
"ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}"
end
GemPins.combine_method_pins_by_path(with_resolved_aliases)
end

# @return [Workspace, nil]
def workspace
@doc_map&.workspace
end

# @param fq_reference_tag [String] A fully qualified whose method should be pulled in
# @param namespace_pin [Pin::Base] Namespace pin for the rooted_type
# parameter - used to pull generics information
Expand Down Expand Up @@ -788,7 +785,8 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false
end
rooted_sc_tag = qualify_superclass(rooted_tag)
unless rooted_sc_tag.nil?
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, no_core)
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope,
visibility, true, skip, no_core)
end
else
logger.info { "ApiMap#inner_get_methods(#{fqns}, #{scope}, #{visibility}, #{deep}, #{skip}) - looking for get_extends() from #{fqns}" }
Expand All @@ -798,7 +796,8 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false
end
rooted_sc_tag = qualify_superclass(rooted_tag)
unless rooted_sc_tag.nil?
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, true)
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope,
visibility, true, skip, true)
end
unless no_core || fqns.empty?
type = get_namespace_type(fqns)
Expand Down Expand Up @@ -856,8 +855,6 @@ def prefer_non_nil_variables pins

include Logging

private

# @param alias_pin [Pin::MethodAlias]
# @return [Pin::Method, nil]
def resolve_method_alias(alias_pin)
Expand Down Expand Up @@ -931,7 +928,7 @@ def create_resolved_alias_pin(alias_pin, original)
# @param rooted_type [ComplexType]
# @param pins [Enumerable<Pin::Base>]
# @return [Array<Pin::Base>]
def erase_generics(namespace_pin, rooted_type, pins)
def erase_generics namespace_pin, rooted_type, pins
return pins unless should_erase_generics_when_done?(namespace_pin, rooted_type)

logger.debug("Erasing generics on namespace_pin=#{namespace_pin} / rooted_type=#{rooted_type}")
Expand All @@ -942,7 +939,7 @@ def erase_generics(namespace_pin, rooted_type, pins)

# @param namespace_pin [Pin::Namespace]
# @param rooted_type [ComplexType]
def should_erase_generics_when_done?(namespace_pin, rooted_type)
def should_erase_generics_when_done? namespace_pin, rooted_type
has_generics?(namespace_pin) && !can_resolve_generics?(namespace_pin, rooted_type)
end

Expand All @@ -953,7 +950,7 @@ def has_generics?(namespace_pin)

# @param namespace_pin [Pin::Namespace]
# @param rooted_type [ComplexType]
def can_resolve_generics?(namespace_pin, rooted_type)
def can_resolve_generics? namespace_pin, rooted_type
has_generics?(namespace_pin) && !rooted_type.all_params.empty?
end
end
Expand Down
12 changes: 7 additions & 5 deletions lib/solargraph/api_map/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,13 @@ def map_overrides
ovr.tags.each do |tag|
pin.docstring.add_tag(tag)
redefine_return_type pin, tag
if new_pin
new_pin.docstring.add_tag(tag)
redefine_return_type new_pin, tag
end
pin.reset_generated!

next unless new_pin

new_pin.docstring.add_tag(tag)
redefine_return_type new_pin, tag
new_pin.reset_generated!
Copy link
Contributor Author

@apiology apiology Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes an existing bug, where not only are we not always calling reset_generated! on pins (only when return_type is overridden), and we don't reset the parameters.

As a result, params overloading would only work if #inspect had not been called on the pin before it was overridden, which is bad news for debugging.

See #1066 for the spec behind it; on this branch it fails because some debug logging was added and we're exercising debug logging in specs.

end
end
end
Expand All @@ -160,7 +163,6 @@ def redefine_return_type pin, tag
pin.signatures.each do |sig|
sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
end
pin.reset_generated!
end
end
end
Expand Down
Loading
Loading