mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
808 lines
23 KiB
Swift
808 lines
23 KiB
Swift
//===----------------------------------------------------------------------===//
|
||
//
|
||
// This source file is part of the Swift.org open source project
|
||
//
|
||
// Copyright (c) 2014 - 2019 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
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
import LanguageServerProtocol
|
||
import SKTestSupport
|
||
import SourceKitLSP
|
||
import XCTest
|
||
|
||
final class DocumentSymbolTests: XCTestCase {
|
||
// MARK: - Tests
|
||
|
||
func testEmpty() async throws {
|
||
try await assertDocumentSymbols("") { positions in [] }
|
||
}
|
||
|
||
func testUnicode1() async throws {
|
||
try await assertDocumentSymbols("1️⃣struct 2️⃣Żółć3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Żółć",
|
||
detail: nil,
|
||
kind: .struct,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testUnicode2() async throws {
|
||
try await assertDocumentSymbols("1️⃣struct 2️⃣🍰3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "🍰",
|
||
detail: nil,
|
||
kind: .struct,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testEnumCase() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣enum 2️⃣Foo3️⃣ {
|
||
case 4️⃣first5️⃣, 6️⃣second7️⃣
|
||
}8️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .enum,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["8️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "first",
|
||
detail: nil,
|
||
kind: .enumMember,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
),
|
||
DocumentSymbol(
|
||
name: "second",
|
||
detail: nil,
|
||
kind: .enumMember,
|
||
deprecated: nil,
|
||
range: positions["6️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["6️⃣"]..<positions["7️⃣"],
|
||
children: []
|
||
),
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testEnumCaseWithAssociatedValue() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣enum 2️⃣Foo3️⃣ {
|
||
case 4️⃣first(Int)5️⃣
|
||
}6️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .enum,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "first(_:)",
|
||
detail: nil,
|
||
kind: .enumMember,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testEnumCaseWithNamedAssociatedValue() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣enum 2️⃣Foo3️⃣ {
|
||
case 4️⃣first(someName: Int)5️⃣
|
||
}6️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .enum,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "first(someName:)",
|
||
detail: nil,
|
||
kind: .enumMember,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testExtension() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
// struct ThisIsCommentedOut { }
|
||
/* struct ThisOneToo { } */
|
||
1️⃣extension 2️⃣Int3️⃣ { }4️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Int",
|
||
detail: nil,
|
||
kind: .namespace,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testStruct() async throws {
|
||
try await assertDocumentSymbols("1️⃣struct 2️⃣Struct3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Struct",
|
||
detail: nil,
|
||
kind: .struct,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testClass() async throws {
|
||
try await assertDocumentSymbols("1️⃣class 2️⃣Class3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Class",
|
||
detail: nil,
|
||
kind: .class,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testEnum() async throws {
|
||
try await assertDocumentSymbols("1️⃣enum 2️⃣Enum3️⃣ { case 4️⃣enumMember5️⃣ }6️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Enum",
|
||
detail: nil,
|
||
kind: .enum,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "enumMember",
|
||
detail: nil,
|
||
kind: .enumMember,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testProtocol() async throws {
|
||
try await assertDocumentSymbols("1️⃣protocol 2️⃣Interface3️⃣ { 4️⃣func 5️⃣f()6️⃣ }7️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Interface",
|
||
detail: nil,
|
||
kind: .interface,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "f()",
|
||
detail: nil,
|
||
kind: .method,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["5️⃣"]..<positions["6️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testFunction() async throws {
|
||
try await assertDocumentSymbols("1️⃣func 2️⃣function()3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "function()",
|
||
detail: nil,
|
||
kind: .function,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testVariable() async throws {
|
||
try await assertDocumentSymbols("1️⃣var 2️⃣variable3️⃣ = 04️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "variable",
|
||
detail: nil,
|
||
kind: .variable,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testMultiplePatternsInVariable() async throws {
|
||
try await assertDocumentSymbols("var 1️⃣varA2️⃣: Int,3️⃣ 4️⃣varB5️⃣ = 06️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "varA",
|
||
detail: nil,
|
||
kind: .variable,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["3️⃣"],
|
||
selectionRange: positions["1️⃣"]..<positions["2️⃣"],
|
||
children: []
|
||
),
|
||
DocumentSymbol(
|
||
name: "varB",
|
||
detail: nil,
|
||
kind: .variable,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
),
|
||
]
|
||
}
|
||
}
|
||
|
||
func testConstant() async throws {
|
||
try await assertDocumentSymbols("1️⃣let 2️⃣constant3️⃣ = 04️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "constant",
|
||
detail: nil,
|
||
kind: .variable,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testComputedVariable() async throws {
|
||
try await assertDocumentSymbols("1️⃣var 2️⃣computedVariable3️⃣: Int { return 0 }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "computedVariable",
|
||
detail: nil,
|
||
kind: .variable,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testOperatorFunc() async throws {
|
||
try await assertDocumentSymbols("1️⃣func 2️⃣+(lhs: Struct, rhs: Struct)3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "+(lhs:rhs:)",
|
||
detail: nil,
|
||
kind: .operator,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testPrefixOperatorFunc() async throws {
|
||
try await assertDocumentSymbols("1️⃣prefix func 2️⃣-(rhs: Struct)3️⃣ { }4️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "-(rhs:)",
|
||
detail: nil,
|
||
kind: .operator,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testGenericFunc() async throws {
|
||
try await assertDocumentSymbols("1️⃣func 2️⃣f<3️⃣TypeParameter4️⃣>(type: TypeParameter.Type)5️⃣ { }6️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "f(type:)",
|
||
detail: nil,
|
||
kind: .function,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["5️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "TypeParameter",
|
||
detail: nil,
|
||
kind: .typeParameter,
|
||
deprecated: nil,
|
||
range: positions["3️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["3️⃣"]..<positions["4️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testGenericStruct() async throws {
|
||
try await assertDocumentSymbols("1️⃣struct 2️⃣S3️⃣<4️⃣TypeParameter5️⃣> { }6️⃣") { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "S",
|
||
detail: nil,
|
||
kind: .struct,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "TypeParameter",
|
||
detail: nil,
|
||
kind: .typeParameter,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testClassFunction() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣class 2️⃣Foo3️⃣ {
|
||
4️⃣func 5️⃣method()6️⃣ { }7️⃣
|
||
}8️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .class,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["8️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "method()",
|
||
detail: nil,
|
||
kind: .method,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["5️⃣"]..<positions["6️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testStaticClassFunction() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣class 2️⃣Foo3️⃣ {
|
||
4️⃣static func 5️⃣staticMethod()6️⃣ { }7️⃣
|
||
}8️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .class,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["8️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "staticMethod()",
|
||
detail: nil,
|
||
kind: .method,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["5️⃣"]..<positions["6️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testStaticClassProperty() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣class 2️⃣Foo3️⃣ {
|
||
4️⃣var 5️⃣property6️⃣ = 07️⃣
|
||
}8️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .class,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["8️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "property",
|
||
detail: nil,
|
||
kind: .property,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["5️⃣"]..<positions["6️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testInitializer() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣class 2️⃣Foo3️⃣ {
|
||
4️⃣init()5️⃣ { }6️⃣
|
||
}7️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .class,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "init()",
|
||
detail: nil,
|
||
kind: .constructor,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testInitializerWithParameters() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣class 2️⃣Foo3️⃣ {
|
||
4️⃣init(_ first: Int, second: Int)5️⃣ { }6️⃣
|
||
}7️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
detail: nil,
|
||
kind: .class,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "init(_:second:)",
|
||
detail: nil,
|
||
kind: .constructor,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testLocalVariable() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣func 2️⃣f()3️⃣ {
|
||
let localConstant = 0
|
||
}4️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "f()",
|
||
detail: nil,
|
||
kind: .function,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["4️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testLocalFunction() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣func 2️⃣f()3️⃣ {
|
||
4️⃣func 5️⃣localFunction()6️⃣ { }7️⃣
|
||
}8️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "f()",
|
||
detail: nil,
|
||
kind: .function,
|
||
deprecated: nil,
|
||
range: positions["1️⃣"]..<positions["8️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "localFunction()",
|
||
detail: nil,
|
||
kind: .function,
|
||
deprecated: nil,
|
||
range: positions["4️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["5️⃣"]..<positions["6️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testIncludeMarkComments() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣// MARK: Marker2️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Marker",
|
||
kind: .namespace,
|
||
range: positions["1️⃣"]..<positions["2️⃣"],
|
||
selectionRange: positions["1️⃣"]..<positions["2️⃣"]
|
||
)
|
||
]
|
||
}
|
||
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣// MARK: - Marker2️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "- Marker",
|
||
kind: .namespace,
|
||
range: positions["1️⃣"]..<positions["2️⃣"],
|
||
selectionRange: positions["1️⃣"]..<positions["2️⃣"]
|
||
)
|
||
]
|
||
}
|
||
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣/* MARK: Marker */2️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Marker",
|
||
kind: .namespace,
|
||
range: positions["1️⃣"]..<positions["2️⃣"],
|
||
selectionRange: positions["1️⃣"]..<positions["2️⃣"]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testNestedMarkComment() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣struct 2️⃣Foo3️⃣ {
|
||
4️⃣// MARK: Marker5️⃣
|
||
}6️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
kind: .struct,
|
||
range: positions["1️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "Marker",
|
||
kind: .namespace,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"]
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testNestedMarkCommentFollowedAttachedToChild() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣struct 2️⃣Foo3️⃣ {
|
||
4️⃣// MARK: Marker5️⃣
|
||
6️⃣func 7️⃣myFunc()8️⃣ { }9️⃣
|
||
}🔟
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
kind: .struct,
|
||
range: positions["1️⃣"]..<positions["🔟"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "Marker",
|
||
kind: .namespace,
|
||
range: positions["4️⃣"]..<positions["5️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"]
|
||
),
|
||
DocumentSymbol(
|
||
name: "myFunc()",
|
||
kind: .method,
|
||
range: positions["6️⃣"]..<positions["9️⃣"],
|
||
selectionRange: positions["7️⃣"]..<positions["8️⃣"],
|
||
children: []
|
||
),
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
|
||
func testShowDeinit() async throws {
|
||
try await assertDocumentSymbols(
|
||
"""
|
||
1️⃣class 2️⃣Foo3️⃣ {
|
||
4️⃣deinit5️⃣ {
|
||
}6️⃣
|
||
}7️⃣
|
||
"""
|
||
) { positions in
|
||
[
|
||
DocumentSymbol(
|
||
name: "Foo",
|
||
kind: .class,
|
||
range: positions["1️⃣"]..<positions["7️⃣"],
|
||
selectionRange: positions["2️⃣"]..<positions["3️⃣"],
|
||
children: [
|
||
DocumentSymbol(
|
||
name: "deinit",
|
||
kind: .constructor,
|
||
range: positions["4️⃣"]..<positions["6️⃣"],
|
||
selectionRange: positions["4️⃣"]..<positions["5️⃣"],
|
||
children: []
|
||
)
|
||
]
|
||
)
|
||
]
|
||
}
|
||
}
|
||
}
|
||
|
||
fileprivate func assertDocumentSymbols(
|
||
_ markedText: String,
|
||
_ expectedDocumentSymbols: (DocumentPositions) -> [DocumentSymbol],
|
||
file: StaticString = #filePath,
|
||
line: UInt = #line
|
||
) async throws {
|
||
let testClient = try await TestSourceKitLSPClient()
|
||
let uri = DocumentURI(for: .swift)
|
||
|
||
let positions = testClient.openDocument(markedText, uri: uri)
|
||
let symbols = try unwrap(try await testClient.send(DocumentSymbolRequest(textDocument: TextDocumentIdentifier(uri))))
|
||
|
||
XCTAssertEqual(symbols, .documentSymbols(expectedDocumentSymbols(positions)), file: file, line: line)
|
||
}
|