Support qualified name queries in workspace/symbol#2715
Draft
rintaro wants to merge 1 commit into
Draft
Conversation
ahoppen
reviewed
Jul 9, 2026
rintaro
force-pushed
the
qualified-workspace-symbol-search
branch
from
July 9, 2026 19:28
d93ce01 to
c620b5a
Compare
ahoppen
reviewed
Jul 10, 2026
| current = "" | ||
| case ":": | ||
| // Must be a `::` separator; a lone `:` is invalid. | ||
| guard iterator.next() == ":" else { return nil } |
Member
There was a problem hiding this comment.
How about if you want to search for String.components(separatedBy:). That contains a lone but shouldn’t be invalid.
| in index: CheckedIndex | ||
| ) throws -> [SymbolOccurrence] { | ||
| guard let containerName = chain.last else { | ||
| throw ResponseError.internalError("members(ofContainerChain:matching:in:) requires a non-empty chain") |
Member
There was a problem hiding this comment.
Suggested change
| throw ResponseError.internalError("members(ofContainerChain:matching:in:) requires a non-empty chain") | |
| throw ResponseError.internalError("\(#function) requires a non-empty chain") |
`workspace/symbol` previously couldn't search for symbols by their qualified name (e.g. `String.description` or `Foo::bar`). The handler treated the query as a flat fuzzy match against bare symbol names, with no notion of containing types or namespaces. Add a small parser that splits queries on the trailing `.` or `::` separator into a parent chain + member, then in the handler: - Unqualified queries (no separator) take the existing flat-search path. - Qualified queries resolve the container named by the parent chain, then enumerate its members, keeping those whose name matches the member. An empty member (e.g. the query `Foo.`) lists all members of the container. Members declared in extensions are included by also enumerating the containers reached through the type's `extendedBy` relations. Both `.` and `::` are accepted and can be mixed in one query (`Foo::Bar.baz`). Multi-level chains (`Outer.Inner.method`) are matched by walking the `childOf` relation chain. Unlike the flat unqualified path, which filters out system symbols, qualified queries deliberately surface results from system SDK modules: naming an explicit container is a request for its members regardless of where they are defined, so `String.description` finds the standard library member. Such SDK/stdlib results point into the module's generated interface via a `sourcekit-lsp://generated-swift-interface` location (reusing the reference-document mechanism); only system *namespaces* (e.g. `std`) are skipped, to avoid enumerating an entire system scope. Qualified results are returned with the fully-qualified name in the symbol's `name` (e.g. `Foo.bar()`) and no `containerName`, so clients that filter workspace symbols by matching the query against the label (e.g. VS Code) keep them. No changes to `workspace/symbolNames` or `workspace/symbolInfo`, and no changes to the protocol or to IndexStoreDB.
rintaro
force-pushed
the
qualified-workspace-symbol-search
branch
from
July 25, 2026 07:06
c620b5a to
d7dc365
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
workspace/symbolpreviously matched the query as a flat fuzzy search against bare symbol names, so you couldn't search by qualified name (e.g.Foo.barorFoo::bar).Queries are now split on
./::into a parent chain + member. A qualified query resolves the container(s) named by the parent chain and returns their members whose name contains the member as a case-insensitive subsequence. An empty member (Foo.) lists all members. Both separators are accepted and can be mixed (Foo::Bar.baz), and a partial chain works (Inner.memberresolves a nested type without naming its outer scope). Unqualified queries take the flat-search path unchanged.Unlike the unqualified path, which filters out system symbols, a qualified query deliberately surfaces system SDK results —
String.descriptionfinds the standard-library member. Those results point into the module's generated interface via asourcekit-lsp://generated-swift-interfacelocation (reusing the existing reference-document mechanism); only system namespaces (e.g.std) are skipped, to avoid enumerating an entire system scope.Qualified results carry the fully-qualified name in
name(e.g.Foo.bar()) with nocontainerName, so clients that filter against the label (e.g. VS Code) don't drop them.No changes to the protocol,
workspace/symbolNames/symbolInfo, or IndexStoreDB.