Commit Graph

3100 Commits

Author SHA1 Message Date
Rintaro Ishizaki 009da9bdbe Merge pull request #2685 from rintaro/workspace-weak-captures-explicit 2026-06-03 03:40:16 -07:00
Rintaro Ishizaki 1b7f310e92 UncheckedIndex: mark IndexStoreDB? init param as sending
ThreadSafeBox.init takes `consuming sending Value`, so its argument
must be region-isolated. Without `sending` on this init's parameter,
callers in some build configurations couldn't satisfy the sending
requirement and triggered SendingRisksDataRace.
2026-06-02 11:08:51 -07:00
Rintaro Ishizaki f0231e287f Workspace: explicit weak captures in semanticIndexManager callbacks
Inner closures captured `sourceKitLSPServer` implicitly. The outer
`Task` already captures it weakly, making it a `var` in scope; inner
@Sendable closures that capture this `var` implicitly trigger the
`SendableClosureCaptures` diagnostic on compiler configurations
without `ImmutableWeakCaptures`.

Add explicit `[weak sourceKitLSPServer]` to each inner closure so the
capture binds cleanly to a fresh weak local.
2026-06-02 11:06:52 -07:00
Alex Hoppen 454d9f3f4d Merge pull request #2668 from ayush-that/feature/add-explicit-enum-raw-values
Add 'Add Explicit Raw Values' code action
2026-06-02 10:46:47 -07:00
Rintaro Ishizaki 153caaf63d Merge pull request #2678 from rintaro/withtimeout-continuation
Migrate to swift-tools-protocols's withTimeout family
2026-06-02 09:39:09 -07:00
Rintaro Ishizaki f18c4a4bab Add diagnostic logging for indexing scheduling investigation
Logs five points to diagnose flakes where indexing tasks stall in
the scheduling pipeline:

- when scheduleIndexing reaches the post-preparation withTaskGroup
- when schedulePreparation creates a QueuedTask, with priorities
- when updateIndexStore creates a QueuedTask, with priorities
- when poke() rejects a pending task because of budget
- when QueuedTask.resultTask body starts, capturing both the stored
  and runtime priorities to detect priority elevation races

Together these distinguish whether the indexTask body wedged, a
QueuedTask was never created, priority escalation never fired
poke() to retry, or the resultTask body started after an elevation
had already happened.
2026-06-01 20:35:52 -07:00
Rintaro Ishizaki 4d3348df85 Migrate to swift-tools-protocols's withTimeout family
Delete the local `withTimeout` and `withTaskPriorityChangedHandler`
copies in favor of the upstream versions.

Update callers of `withTaskPriorityChangedHandler` to receive the new
priority via the callback argument rather than reading
`Task.currentPriority`.
2026-06-01 19:55:34 -07:00
Rintaro Ishizaki b0df3fe35b Merge pull request #2681 from rintaro/fix-queuedtask-priority-race
TaskScheduler: use the actual initial priority for handler baseline
2026-06-01 16:54:11 -07:00
Alex Hoppen ef86a32e96 Merge pull request #2672 from bripeticca/spm-api-traits
Fix spm API usage for appropriate trait configuration
2026-06-01 23:47:38 +02:00
Rintaro Ishizaki 6cf8500d8b TaskScheduler: use the actual initial priority for handler baseline
`QueuedTask.resultTask` passed `self.priority` as `initialPriority` to
`withTaskPriorityChangedHandler`. If `elevatePriority(to:)` ran before
`resultTask`'s body started (e.g. the detached task hadn't been scheduled
yet), `self.priority` was already set to the elevated value, so the
polling baseline matched `Task.currentPriority` and `taskPriorityChanged`
never fired. The callback is what calls `poke()`, so the scheduler never
re-evaluated the elevated task and it could stall until an upstream 180s
timeout cancelled the chain.

Use the captured `priority` parameter instead. It matches the priority
that `Task.detached(priority: priority)` uses to launch the resultTask
and isn't subject to mutation by `elevatePriority`.
2026-06-01 10:23:21 -07:00
Rintaro Ishizaki 4b724ea301 Drain pending tasks in TaskScheduler shutdown
`shutDown` only cancels `currentlyExecutingTasks`, leaving
`pendingTasks` untouched. External callers awaiting `waitToFinish()`
on a pending task hang forever — `resultTask` keeps awaiting an
`AsyncStream` that the scheduler will never yield into once
`isShutDown` is set — and each such `QueuedTask` is leaked via the
strong cycle through its `resultTask` closure.

Cancel pending tasks too: `task.cancel()` cancels `resultTask`, the
`for await` over the stream exits immediately on cancellation, and
`waitToFinish()` returns in microseconds.
2026-05-29 12:01:18 -07:00
Rintaro Ishizaki 13f842eb74 Bound task-scheduler shutdown wait and log process completion
Wrap each `task.waitToFinish()` in `TaskScheduler.shutDown()` with a
10s `withTimeout` so a stuck QueuedTask cannot block sourcekit-lsp's
shutdown indefinitely; on timeout, log the task description so the
offender is identifiable. The QueuedTask is already cancelled via
`task.cancel()` and continues winding down in the background.

Add debug logs after `Process.waitUntilExit()` returns and after
`Process.run` returns inside `prepare(singleTarget:)`, so a future
shutdown hang can be triaged: did the swift build process actually
exit, did `Process.run` propagate the result, or is the stall higher
up in the prepare chain.

Motivated by a recurring Windows CI hang in
BackgroundIndexingTests.testSymlinkedTargetReferringToSameSourceFile
where prepareForExit stalls for the full test timeout with no log
output during shutdown.
2026-05-28 21:45:23 -07:00
Bri Peticca cafbe12d95 Run formatter 2026-05-28 11:27:10 -04:00
Rintaro Ishizaki 99cac8f91d Update for the ThreadSafeBox.value setter removal 2026-05-27 14:36:56 -07:00
Rintaro Ishizaki 7c99f4f0e7 Use swift-tools-protocols's ThreadSafeBox
Delete sourcekit-lsp's `Sources/SwiftExtensions/ThreadSafeBox.swift`
and the now-unused `NSLock+WithLock.swift`.
Use the `Mutex`-backed `ThreadSafeBox` from swift-tools-protocols'

Adjust call sites for the new API: e.g.
`foo.value.mutate()` with `foo.withLock { $0.mutate() }` because it
doesn't provide `_modify` accessor.
2026-05-27 12:01:07 -07:00
Bri Peticca da0c9a9ad9 Fix spm API usage for appropriate trait configuration
The `WorkspaceConfiguration.default` was being used to populate
the `Workspace`; there was an extra step here needed to assure that
we are propagating the trait configuration to the workspace.

The added test assures that non-default traits that are enabled are
indeed processed as enabled.
2026-05-27 12:57:16 -04:00
Ayush Thakur 28e69b6c25 Add 'Add Explicit Raw Values' code action
Adds a syntactic refactoring action that converts implicit raw values to
explicit ones for enums whose first inherited type is an integer type
(any width up to Int128/UInt128) or String.

Resolves #2516.

Before:

    enum Status: Int {
        case active
        case inactive
        case pending = 10
        case archived
    }

After:

    enum Status: Int {
        case active = 0
        case inactive = 1
        case pending = 10
        case archived = 11
    }

The action is exposed through `SyntaxRefactoringCodeActionProvider` and
performs all transformations as a list of `SourceEdit`s, leaving the
rest of the enum (including trailing trivia and member ordering)
untouched.

### Motivation:

For enums with implicit raw values, making the values explicit is a
common refactoring step before serialising the values or relying on
their numeric identity. Doing the renumbering by hand is error-prone
once any cases already have explicit values, because the implicit
continuation rule has to be reapplied for every gap.

### Modifications:

- New `Sources/SwiftSyntaxCodeActions/AddExplicitEnumRawValues.swift`
  conforming to `EditRefactoringProvider` and
  `SyntaxRefactoringCodeActionProvider`. Handles negative integer
  literals, hex/binary/octal literals with underscore separators, and
  backticked case identifiers in String enums.
- Registered in `Sources/SwiftSyntaxCodeActions/SyntaxCodeActions.swift`
  and `Sources/SwiftSyntaxCodeActions/CMakeLists.txt`.
- Twelve LSP-level tests in `Tests/SourceKitLSPTests/CodeActionTests.swift`
  covering positive cases (Int, String, negative continuation, hex
  continuation, backtick stripping) and negative cases (no raw value
  type, raw value type not first in inheritance clause, all cases
  already explicit, unsupported raw value expression, #if directives,
  freestanding macro expansions, associated value cases).

### Result:

When the cursor is on an enum declaration whose raw value type is
supported and at least one case is missing an explicit raw value,
SourceKit-LSP offers the "Add Explicit Raw Values" code action and
inserts the missing raw values in place. The action is suppressed in
situations where the implicit numbering cannot be computed safely
(unsupported raw value expression, #if blocks, freestanding macros,
associated value cases).
2026-05-26 20:07:03 +05:30
Rintaro Ishizaki 70f4c333ea Merge pull request #2662 from rintaro/migrate-atomics-to-synchronization
Migrate atomic call sites to Synchronization.Atomic
2026-05-22 11:34:13 -07:00
Alex Hoppen f53b3eaaf0 Merge pull request #2659 from Steffeeen/rename-fix 2026-05-21 21:50:15 +02:00
Rintaro Ishizaki a6c926fa34 Relax atomic memory orderings; switch semaphore to release/acquire
For ID counters and standalone flags (most sites), drop to .relaxed
since nothing reads other memory based on the atomic's value.

MultiEntrySemaphore.signaled is the exception: it is used as a
signal/wait primitive where waiters proceed to use state set up
before signal(). Use .releasing on store and .acquiring on load so
that pre-signal writes are visible to waiters that observe `true`.
.relaxed there would be incorrect on weakly-ordered architectures.
2026-05-21 11:16:17 -07:00
Rintaro Ishizaki 83de30d29f Migrate atomic call sites to Synchronization.Atomic and ThreadSafeBox
Replace AtomicBool/UInt8/UInt32/Int32 from
ToolsProtocolsSwiftExtensions with Synchronization.Atomic<T> where
the storage is a static, module-level let, or class stored property.
For local lets captured by @Sendable closures (where Atomic's
~Copyable nature prevents capture), use ThreadSafeBox<T> instead.
2026-05-21 10:58:34 -07:00
Steffeeen a7f43dc54c Fix rename target selection for initializer calls
When rename is invoked on a type name in an initializer call, prefer
renaming the nominal type symbol instead of the constructor symbol.
2026-05-21 10:55:47 +02:00
Rintaro Ishizaki a39c92022f Add forOpenDocument label to language service lookup methods
Rename languageServices(for:), primaryLanguageService(for:), and their
internal counterparts to use the `forOpenDocument` label, so the
precondition that the document must already be open is visible at call
sites.

Also make primaryLanguageService(forOpenDocument:) throw instead of
returning an optional, and switch several resolve-style handlers from
the find-or-create primaryLanguageService(for:_:) to
primaryLanguageService(forOpenDocument:), since those call sites already
have an open document in hand.
2026-05-20 10:31:44 -07:00
Rintaro Ishizaki 876fbad114 Merge pull request #2658 from rintaro/warnings-20260518
Fix build warnings
2026-05-19 05:37:48 -07:00
Rintaro Ishizaki b7fc4b5f1b Merge pull request #2655 from femaref/feature/proper-end
provide proper start and end positions in the LSP protocol
2026-05-18 21:03:48 -07:00
Rintaro Ishizaki f56a27b996 Fix build warnings 2026-05-18 18:04:44 -07:00
femaref c4c552203a provide proper start and end positions in the LSP protocol
vscode provides an alternative action if the target of goto definition is in the same character range we requested.
this requires the start and end in the LSP response to be properly set, so vscode can see that the current character
is actually part of the request
2026-05-19 00:02:17 +02:00
Rintaro Ishizaki 626861d316 Merge pull request #2654 from rintaro/per-workspace-language-services
Scope language service lifetime to workspace
2026-05-18 14:59:47 -07:00
Rintaro Ishizaki f84abc1eb2 Use 'weak let' for immutable weak references (SE-0481)
Replace 'weak var' with 'weak let' for weak reference properties that are
set in init and never reassigned, using the Swift 6.3 feature introduced
by SE-0481.
2026-05-18 09:28:10 -07:00
Rintaro Ishizaki f2a121453d Scope language service instances per workspace
Previously, language services were held in a global registry on
SourceKitLSPServer and shared across workspaces, requiring complex
lifetime tracking (isImmortal, shutdownOrphanedLanguageServices) to
decide when to tear them down. In practice, every language service
already stored workspace-specific properties (buildServerManager,
semanticIndexManagerTask), so sharing them across workspaces was never
truly safe. Giving each Workspace its own service instances simplifies
lifetime management: services are created when needed and shut down
with their workspace.

Remove LanguageService.isImmortal, the workspace parameter from
canHandle(toolchain:), and the initialize/clientInitialized protocol
requirements.
2026-05-18 09:21:01 -07:00
Alex Hoppen 0cacc26db3 Merge pull request #2591 from ahoppen/require-6.3
Require Swift 6.3
2026-05-18 15:27:18 +02:00
Rintaro Ishizaki a559d60451 Merge pull request #2648 from rintaro/language-service-close
Preserve language service when closing generated interface
2026-05-14 16:26:50 -07:00
Rintaro Ishizaki 1d20e3f32e Merge pull request #2647 from rintaro/open-quickly-revise
Move Open Quickly and Jump to Definition docs to Contributor Documentation
2026-05-14 06:41:48 -07:00
Rintaro Ishizaki b60b9582ac Move language-service retention check into Workspace
The buildSettingsFile key is an implementation detail of Workspace's
language-service dictionary, so the guard that prevents removing a
still-needed service belongs there rather than in SourceKitLSPServer.
2026-05-13 20:59:29 -07:00
Edward Lee ca91f5ff4f Preserve language service when closing generated interface documents
Closing a generated interface document (sourcekit-lsp:// URI) was
removing the language service for the originating source file because
both share the same buildSettingsFile key. Guard the removal so it
only happens when no other open document shares that key.

Relates to #2209
2026-05-13 15:56:27 -07:00
Rintaro Ishizaki 292985e7dd Remove redundant fragment-clearing when constructing moduleFileURI 2026-05-13 10:25:09 -07:00
25harsh 90ceac197d Use ExpressibleByLiteral conformances for LSPAny 2026-05-13 16:19:42 +05:30
Rintaro Ishizaki 223a88cb8c Add workspace/symbolNames and workspace/symbolInfo LSP extensions (#2619)
- **`sourcekit/workspace/symbolNames`** — returns a flat, deduplicated
list of every symbol name in the workspace index (source and indexed
system modules). Clients use this to drive their search UI locally.

- **`sourcekit/workspace/symbolInfo`** — given a list of exact symbol
names, returns `WorkspaceSymbolItem` for each occurrence across all
workspaces, for display in the search result list. Source-file symbols
get `SymbolInformation` with a `file://` location. SDK/stdlib symbols
get a `WorkspaceSymbol` with `location: .uri(…)` The client must call
`workspaceSymbol/resolve` after the user selects an SDK/stdlib symbol to
obtain the concrete interface location.

- **`workspaceSymbol/resolve`** — resolves the deferred
`WorkspaceSymbol` location from `sourcekit/workspace/symbolInfo`. Parses
the `?module=` value into `moduleName`/`groupName`, finds a real source
file via `mainFiles(containing:)`, calls `openGeneratedInterface`, and
returns the symbol with `location` replaced by a full
`sourcekit-lsp://generated-swift-interface/` URI + range (or a temp
`file://` path for clients without `workspace/getReferenceDocument`
support).
2026-05-12 22:21:17 -07:00
Alex Hoppen 0dbad3f7fe Merge pull request #2642 from 25harsh/code-actions-to-module
[SwiftSyntaxCodeActions] Moved syntactic code actions into a new module
2026-05-12 15:49:34 +02:00
Rintaro Ishizaki 127492d655 Merge pull request #2640 from rintaro/copied-file-map-missing-adjustment
Fix and simplify CopiedFileMap adjustments
2026-05-11 09:32:57 -07:00
25harsh f185bc404f [SwiftSyntaxCodeActions] Moved syntactic code actions into a new module 2026-05-11 11:10:40 +05:30
Rintaro Ishizaki e638498119 Merge pull request #2580 from Steffeeen/local-sourcekit-build-docs
[ContributorDoc] Add detailed docs for using a local build of SourceKit
2026-05-10 17:59:30 -07:00
Rintaro Ishizaki eab4f58f32 Simplify adjusted(for:) implementations in LSP+CopiedFileMap
The range is never changed by URI adjustment, so there's no need to
construct intermediate Location values just to extract the URI.
2026-05-10 17:12:15 -07:00
Rintaro Ishizaki 2d320b288c Fix missing CopiedFileMap adjustments for WorkspaceEdit and TypeHierarchyItem
- WorkspaceEdit.adjusted(for:) was using originalURI(for:) ?? uri, which
  skips the file-existence check; switch to adjustedURI(for:)
- TypeHierarchyItem.adjusted(for:) was not adjusting the URI stored in
  data, unlike CallHierarchyItem
2026-05-10 17:12:12 -07:00
Rintaro Ishizaki 01b793dab4 Merge pull request #2637 from rintaro/lsp-messsage-metadata-structs
Replace manual LSPAny data handling with typed structs
2026-05-10 11:22:35 -07:00
Steffeeen 7166514240 Add SOURCEKIT_LSP_RUN_SOURCEKITD_IN_PROCESS environment variable
This environment variable can be used to force SourceKit-LSP to run
SourceKitD in-process on macOS. This can be useful for debugging.
2026-05-10 16:40:40 +02:00
Rintaro Ishizaki 2773bcdfa2 Merge pull request #2633 from rintaro/sourcekitd-inject
Allow injection of a pre-initialized sourcekitd connection
2026-05-07 19:57:41 -07:00
Rintaro Ishizaki 83afc9d1e1 Move CopiedFileMap LSP adjustments to extensions on LSP types
`CopiedFileMap` previously held methods like
`workspaceEditAdjustedForCopiedFiles`,
`callHierarchyItemAdjustedForCopiedFiles`, etc. that encoded knowledge
of high-level LSP message types into `BuildServerIntegration`.

Replace them with `adjusted(for:)` methods on each LSP type
(`Location`, `[Location]`, `LocationsOrLocationLinksResponse`,
`WorkspaceEdit`, `CallHierarchyItem`, `TypeHierarchyItem`) in a new
`LSP+CopiedFileMap.swift` in the SourceKitLSP module. The primitive
URI remapping is extracted into `CopiedFileMap.adjustedURI(for:)`
which remains in `BuildServerIntegration`.

`CallHierarchyItem.adjusted(for:)` also drops manual `LSPAny`
dictionary construction in favour of `HierarchyItemData`.
2026-05-07 16:10:02 -07:00
Rintaro Ishizaki 070bc52b8c Use typed structs for LSP item data fields instead of manual LSPAny 2026-05-07 15:25:18 -07:00
Rintaro Ishizaki 4b2fa3193a Allow injection of a pre-initialized sourcekitd connection
Introduce `SourceKitDCore` as the protocol boundary between dylib
lifecycle management and the high-level `SourceKitD` API. Its single
lifecycle entry point, `initializeService(api:notificationCallback:)`,
receives the already-loaded `sourcekitd_api_functions_t` from
`SourceKitD.init(core:)`.

`SourceKitDCoreImpl` is the standard implementation: `init` opens the
dylib; `initializeService` registers any plugin paths, calls
`api.initialize()`, and wires the notification handler; `deinit` calls
`shutdown()` and closes the handle. Pre-initialized conformances
implement `initializeService` as a no-op.

Wire a `sourcekitdCoreInjector` hook through `Hooks` so an embedding
host can return a pre-initialized `SourceKitDCore` for a given toolchain
path, preventing `sourcekitd_initialize()` from being called a second
time.

Declare `SourceKitDCoreForPlugin` at its use sites so each call site
can express the exact deinit behavior it needs: `dlclose` for handles
acquired via `RTLD_NOLOAD`, and `leak` for externally-owned handles.
2026-05-07 09:58:47 -07:00