When the client opts in to `workspace/tests/refresh` or
`workspace/playgrounds/refresh` via experimental client capabilities,
SourceKit-LSP now maintains a proactive cache of the current test and
playground lists and sends the corresponding `workspace/.../refresh`
notification whenever the cache changes. `workspaceTests()` /
`workspacePlaygrounds()` then serve subsequent fetch requests directly
from the cache.
Add `EntryPointManager`: runs background scans, stores the results,
fires callbacks on changes:
- Start scanning when build targets are updated including initial
updates, any watched files are changed, and index is updated.
- Send '/refresh' server initiated requests when the cache has changed.
- Coalesces rapid invalidations by cancelling any in-flight refresh task.
Also:
- Simplify `SourceKitIndexDelegate` from an `actor` with `AtomicInt32`
to a plain `class`, since it is only called from IndexStoreDB's
internal serial dispatch queue.
When semantic test discovery encounters XCTest methods in an extension it adds the extension definition to the root items list for each child test method. With N test methods, the same extension root appears N times, each copy receiving all N children. After merging, this produces N*N test items instead of N.
The bug is normally masked by the syntactic index, which provides correct results that take priority via combineTests(). This bug was exposed while I was debugging why tests generated by build plugins would appear multiple times. Turns out because they don't exist on disk at the time of the syntatic scan only the semantic results are used, which surfaced the issue.
The fix is to track already-added extension USRs to ensure each extension added once as a root item.
If we have a source item `include/Test.h` that gets copied to `build/Test.h`, we currently don’t provide any semantic functionality for `build/Test.h`. Improve the build settings fallback logic to construct fallback build settings for `build/Test.h` based on `include/Test.h`.
When semantic test discovery encounters XCTest methods in an extension
it adds the extension definition to the root items list for each child
test method. With N test methods, the same extension root appears N
times, each copy receiving all N children. After merging, this produces
N*N test items instead of N.
The bug is normally masked by the syntactic index, which provides
correct results that take priority via `combineTests()`. This bug was
exposed while I was debugging why tests generated by build plugins would
appear multiple times. Turns out because they don't exist on disk at the
time of the syntatic scan only the semantic results are used, which
surfaced the issue.
The fix is to track already-added extension USRs to ensure each extension
added once as a root item.
Related issue: https://github.com/swiftlang/vscode-swift/issues/2162
Remove hand-written `init?(fromLSPDictionary:)` / `encodeToLSPAny()`
from LSPAnyCodable types, relying instead on the default implementations
backed by `LSPAnyEncoder`/`LSPAnyDecoder`
Fixing up the ranges require 'textDocument/symbols' request, which needs
the document opened. But we don't want to open/close the documents just
for fixing up the ranges.
Instead of querying the index twice (once for up-to-date files, once for
outdated ones), collect file modification timestamps during the syntactic
scan phase and use them to filter a single semantic index query.
For files that don't support syntactic scans, use the semantic index
results even if outdated.
Also extracts symlink-aware mtime resolution into URL.fileModificationDate
and exposes snapshotHasInMemoryModifications(_:) on DocumentManager.
Previously, test discovery used the semantic index as the primary
source and fell back to the syntactic index only for files where the
semantic index was out-of-date. This meant test locations came from the
semantic index, which only records a point position rather than the
full symbol range.
Flip the priority: use syntactic scan results as the primary source
(which have correct location ranges) and supplement with semantic index
results. The semantic results are range-fixed via
'textDocument/documentSymbol' before being returned.
This logic is unified into a single 'combineTests' helper shared by
both 'workspaceTests' and 'documentTests'.
Also fix 'SyntacticSwiftXCTestScanner' to emit extensions as proper
'AnnotatedTestItem' nodes (with 'isExtension: true') rather than a flat
list of methods, so extension test methods are correctly merged into
their class via 'mergingTestsInExtensions'. The class and extension
visitors are unified through a shared 'handleClassOrExtension' helper.
This enables hierarchical selection expansion in supported editors.
Selection ranges are computed from the AST by walking upward from the
smallest enclosing node to the root. This is implemented by AST nodes
conforming to the `SelectionRangeProvider` protocol. Most nodes use a
default implementation which returns the node's `trimmedRange`.
Other nodes are special-cased to adjust the returned selection ranges
based on other factors.
`IndexStoreDB` moves its index to the `saved` directory when it is deallocated. Because `IndexStoreDB` is primarily owned by `UncheckedIndex`, we rely on deallocating this object to save the index store. This is fairly brittle because various parts of the codebase may hold transient references to that object as reported in https://github.com/swiftlang/sourcekit-lsp/issues/2455#issuecomment-3873561003.
Explicitly remove the reference from `UncheckedIndex` to `IndexStoreDB`. While this still isn’t perfect because other parts of the code base may hold references to `IndexStoreDB` but those should be a lot rarer, resulting in a more consistent closing of the index.
- Add DefinitionLocations.swift to CMakeLists.txt
- Add proper documentation comments to functions in DefinitionLocations.swift
- Make indexToLSPLocation private since it's only used within the file
- Revert unrelated comment changes in InlayHintResolve.swift
- Use .only instead of .first in InlayHintResolve to avoid ambiguous types
- Refactor TypeDefinition.swift to use cleaner control flow with guard/else
- Add test for jumping to generated interface (String)
- Use cursorInfo USR lookup instead of index (more accurate)
- Add document version tracking to reject stale resolve requests
- Make InlayHintResolveData conform to LSPAnyCodable
- Reference swiftlang/swift#86432 for mangled type workaround
- cursorInfoFromTypeUSR takes DocumentSnapshot for version safety
- Remove TypeDefinition.swift (defer to follow-up PR)
- Remove unnecessary comments
- Tests work without index
Add support for the textDocument/typeDefinition LSP request, which
finds the type of the symbol at a given position and returns the
location of that type's definition.
This uses the same type definition lookup mechanism as the inlay hint
resolution feature, which queries cursorInfo for the new type
declaration location fields (typeDeclFilePath/Line/Column) with
fallback to index lookup using typeDeclUsr.
Fixes#548
Implements resolveProvider for inlay hints to enable navigating to type
definitions. When an inlay hint showing a type is resolved, the server
looks up the type's definition location using cursorInfo and the index.
- store variable position in InlayHint.data for resolution
- add inlayHintResolve to LanguageService protocol
- implement resolve handler using cursorInfo and index lookup
- enable resolveProvider: true in capabilities
- add test for resolve functionality
Addresses #2318
Shut down language services when a workspace is closed
- Added allLanguageServices property to Workspace to get all services it references
- Added shutdownOrphanedLanguageServices to clean up services no longer in use
- When workspace folders are removed, we now shut down their associated language services
- This properly terminates clangd and other language server processes when workspaces close
Closes#2209
- Only call `setLanguageServices` from `openDocument` to avoid race conditions
- Remove language services when documents are closed via `removeLanguageServices`
- `SourceKitLSPServer.languageServices` now just returns services without storing them
- Fixed a small typo (serveer -> server) while I was in there
This way the languageServices dictionary only tracks documents that are actually open,
and we avoid race conditions since openDocument is a blocking request for that document.
Currently, `indexBasedDefinition` relies heavily on IndexStoreDB. If a symbol
belongs to a binary framework or a library that hasn't been indexed (but has
module info provided by sourcekitd), the definition request fails or returns
empty results.
This change adds a fallback mechanism in `definitionLocations`. When no
occurrences are found in the index, we check if `systemModule` information
is available on the symbol. If so, we trigger `definitionInInterface` to
generate the textual interface (via `editor.open.interface`) and return that
location.
This improves navigation for binary dependencies (XCFrameworks) and SDKs
partially covered by the index.