Skip to content

Cache gems where the LSP server will look for them - #103

Draft
apiology wants to merge 3 commits into
pincache-instance-prereqsfrom
pincache-instance-engine
Draft

Cache gems where the LSP server will look for them#103
apiology wants to merge 3 commits into
pincache-instance-prereqsfrom
pincache-instance-engine

Conversation

@apiology

@apiology apiology commented Sep 9, 2026

Copy link
Copy Markdown
Owner

This PR was written by Claude Code on behalf of @apiology.

Problem: The LSP server caches a gem by shelling out to solargraph cache, which reads the project's RBS collection from its own working directory rather than the workspace's. When those differ the pins land under a key the server never reads: the run exits 0, the gem is marked failed, and its types never appear.

Solution: Each workspace now owns a PinCache built from its RBS collection paths and YARD plugins, and the CLI, Library and server all go through it; the server also runs the subprocess in the workspace directory. Keys still come from configuration content, so worktrees sharing a lockfile share every entry.

Stacks on pincache-instance-prereqs, which merges castwide/solargraph#1342, cache only bundle gems, castwide/solargraph#1339, skip parser YARD, apiology/solargraph#98, serve RBS stdlib pins early, apiology/solargraph#93, stop types leaking between workspaces and apiology/solargraph#102, callers choose the yardoc path.

pincache-instance made PinCache a class holding one RBS configuration,
but only combined-pin entries went through it. Everything else -- YARD
pins, RBS collection pins, the stdlib, and the in-memory indexes for
all of them -- stayed on DocMap class methods keyed by gem name and
version alone. Two workspaces open at once shared those, and the CLI,
which built its own configuration from Dir.pwd, wrote under a key the
language server did not read back.

DocMap loses about 500 lines to PinCache: cache_yard_pins,
cache_rbs_collection_pins, the deserialize_* readers, the path
helpers, calculate_build_needs, build_combine_and_cache and
log_cache_info, plus the in-memory indexes. What is left is the
require-to-gemspec work. Workspace owns the instance and hands it to
Library, DocMap and Shell, so all three build and read the same
entries. cache_all! is now cache_doc_map_gems!, and any_uncached?
replaces reaching for the per-kind lists ApiMap used to expose.

Ported from pin-caching-3-pincache-core, reconciled against the five
PRs already merged into pincache-instance-prereqs rather than applied
as a diff. Kept from those: the YARD_SUPPRESSED_GEMS constant over an
inline gem name, Workspace#gemspecs_to_cache as the gem list that
cache_all_for_workspace! drives, the rbs_collection_gem_path name, the
cache_key_for name over lookup_rbs_version_cache_key, and the
cache_errors retry guard in Library. Yardoc is untouched: that split
landed separately and its build_pins takes no out: keyword here, so
cache_yard_pins drops the argument.

Left out of the port, still on the source branch: the GemPins.combine
rewrite and combine_method_pins_by_path, the Pin::Callable, Pin::Method
and Pin::Parameter changes, RbsMap::Conversions, the RbsMap.from_gemspec
stdlib fallback, the Gemspecs#resolve_require find_by_path fix, and the
chdir on the Library cache subprocess.

Full suite green. Typecheck moves from 532 problems to 529 against
pincache-instance-prereqs in the same cache namespace: seven resolve as
DocMap sheds the code holding them, and four appear, listed in the PR.
The LSP server caches a gem by shelling out to solargraph cache. That
subprocess derives its cache key from the RBS collection it finds in
its own working directory, so a server started anywhere other than the
project root wrote the entry under a key it never looks up: the run
exits 0, the gem stays uncached, and the retry guard marks it failed.
Reorganising where the key is derived does not close that on its own,
which is why this line comes across from the source branch.

Also version each YARD plugin in the yardoc path rather than naming it
alone. Replacing the hardcoded yard-activesupport-concern segment with
the workspace plugin list started keying on which plugins are active
and stopped keying on their versions, so an upgraded plugin would have
been served the pins its predecessor built.

Suite 1700 examples, 0 failures. Typecheck unchanged at 529 problems.
Array#first is nilable, and stdlib_dependencies declares a String
parameter, so a require path that splits to nothing was passed straight
through. Skipping such a path is what the loop already did further down
via compact; doing it up front lets the compact and the splat marker go
too, which brings doc_map.rb to zero typecheck problems.

Suite 1700 examples, 0 failures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant