mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-10-17 23:47:35 +02:00
`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.
39 lines
1.4 KiB
Swift
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"))
|
|
}
|
|
}
|