Files
sourcekit-lsp/Tests/SourceKitLSPTests/StringFuzzilyContainsTests.swift
Rintaro Ishizaki b6d70e8c41 Support qualified name queries in workspace/symbol
`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.
2026-07-30 14:39:35 -07:00

39 lines
1.4 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@_spi(Testing) import SourceKitLSP
import XCTest
final class StringFuzzilyContainsTests: XCTestCase {
func testEmptySubsequenceAlwaysMatches() {
XCTAssertTrue("anything".fuzzilyContains(subsequence: ""))
XCTAssertTrue("".fuzzilyContains(subsequence: ""))
}
func testSubsequenceMatching() {
XCTAssertTrue("longMethodName()".fuzzilyContains(subsequence: "longMethod"))
XCTAssertTrue("longMethodName()".fuzzilyContains(subsequence: "lmn"))
XCTAssertTrue("bar()".fuzzilyContains(subsequence: "bar"))
}
func testCaseInsensitive() {
XCTAssertTrue("MyMethod".fuzzilyContains(subsequence: "mym"))
XCTAssertTrue("mymethod".fuzzilyContains(subsequence: "MYM"))
}
func testNonMatching() {
XCTAssertFalse("bar".fuzzilyContains(subsequence: "baz"))
XCTAssertFalse("bar".fuzzilyContains(subsequence: "barbar"))
XCTAssertFalse("".fuzzilyContains(subsequence: "a"))
}
}