mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-06-24 12:21:58 +02:00
311 lines
7.6 KiB
Swift
311 lines
7.6 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_spi(SourceKitLSP) import LanguageServerProtocol
|
|
import SKLogging
|
|
import SKTestSupport
|
|
import TSCBasic
|
|
import XCTest
|
|
|
|
final class ImplementationTests: SourceKitLSPTestCase {
|
|
// MARK: - Utilities
|
|
|
|
private func testImplementation(
|
|
_ markedText: String,
|
|
expectedLocations expectedLocationMarkers: [String] = ["2️⃣"],
|
|
testName: String = #function,
|
|
line: UInt = #line
|
|
) async throws {
|
|
let project = try await IndexedSingleSwiftFileTestProject(markedText, testName: testName)
|
|
let response = try await project.testClient.send(
|
|
ImplementationRequest(
|
|
textDocument: TextDocumentIdentifier(project.fileURI),
|
|
position: project.positions["1️⃣"]
|
|
)
|
|
)
|
|
let expectedLocations = expectedLocationMarkers.map {
|
|
Location(uri: project.fileURI, range: Range(project.positions[$0]))
|
|
}
|
|
XCTAssertEqual(response?.locations, expectedLocations, line: line)
|
|
}
|
|
|
|
// MARK: - Tests
|
|
|
|
func testProtocolInheritance() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol 1️⃣Protocol {}
|
|
struct Struct: 2️⃣Protocol {}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testProtocolStaticVar() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol Protocol {
|
|
static var 1️⃣staticVar: Int { get }
|
|
}
|
|
struct Struct: Protocol {
|
|
static var 2️⃣staticVar: Int { 123 }
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testProtocolStaticFunc() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol Protocol {
|
|
static func 1️⃣staticFunction()
|
|
}
|
|
struct Struct: Protocol {
|
|
static func 2️⃣staticFunction() {}
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testProtocolVar() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol Protocol {
|
|
var 1️⃣variable: Int { get }
|
|
}
|
|
struct Struct: Protocol {
|
|
var 2️⃣variable: Int { 123 }
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testProtocolFunc() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol Protocol {
|
|
func 1️⃣function()
|
|
}
|
|
struct Struct: Protocol {
|
|
func 2️⃣function() {}
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testClassInheritance() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class 1️⃣Class {}
|
|
class Subclass: 2️⃣Class {}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testClassClassVar() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class Class {
|
|
class var 1️⃣classVar: Int { 123 }
|
|
}
|
|
class Subclass: Class {
|
|
override class var 2️⃣classVar: Int { 123 }
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testClassClassFunc() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class Class {
|
|
class func 1️⃣classFunction() {}
|
|
}
|
|
class Subclass: Class {
|
|
override class func 2️⃣classFunction() {}
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testClassVar() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class Class {
|
|
var 1️⃣variable: Int { 123 }
|
|
}
|
|
class Subclass: Class {
|
|
override var 2️⃣variable: Int { 123 }
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testClassFunc() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class Class {
|
|
func 1️⃣function() {}
|
|
}
|
|
class Subclass: Class {
|
|
override func 2️⃣function() {}
|
|
}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testClassHierarchy() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class 1️⃣MyClass {}
|
|
class SubA: 2️⃣MyClass {}
|
|
class SubASub: SubA {}
|
|
class SubB: 3️⃣MyClass {}
|
|
class SubC: 4️⃣MyClass {}
|
|
""",
|
|
expectedLocations: ["2️⃣", "3️⃣", "4️⃣"]
|
|
)
|
|
}
|
|
|
|
func testSubclassHierarchy() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class MyClass {}
|
|
class 1️⃣Subclass: MyClass {}
|
|
class SubSubClassA: 2️⃣Subclass {}
|
|
class SubSubClassB: 3️⃣Subclass {}
|
|
|
|
""",
|
|
expectedLocations: ["2️⃣", "3️⃣"]
|
|
)
|
|
}
|
|
|
|
func testProtocolHierarchy() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol 1️⃣MyProtocol {}
|
|
protocol OtherProtocol: 2️⃣MyProtocol {}
|
|
|
|
class ClassA: 3️⃣MyProtocol {}
|
|
class ClassB: OtherProtocol, 4️⃣MyProtocol {}
|
|
""",
|
|
expectedLocations: ["2️⃣", "3️⃣", "4️⃣"]
|
|
)
|
|
}
|
|
|
|
func testProtocolConformanceInExtension() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
protocol 1️⃣MyProtocol {}
|
|
class MyClass {}
|
|
extension MyClass: 2️⃣MyProtocol {}
|
|
"""
|
|
)
|
|
}
|
|
|
|
func testStandaloneClass() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class 1️⃣MyClass {}
|
|
""",
|
|
expectedLocations: []
|
|
)
|
|
}
|
|
|
|
func testStandaloneClassFunc() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class MyClass {
|
|
func 1️⃣myFunc() {}
|
|
}
|
|
""",
|
|
expectedLocations: []
|
|
)
|
|
}
|
|
|
|
func testOverrideClassVar() async throws {
|
|
try await testImplementation(
|
|
"""
|
|
class MyClass {
|
|
var 1️⃣member: String { "puszysta" }
|
|
}
|
|
class SubclassA: MyClass {
|
|
override var 2️⃣member: String { "glazurowana" }
|
|
}
|
|
class SubclassB: MyClass {
|
|
override var 3️⃣member: String { "piaskowana" }
|
|
}
|
|
""",
|
|
expectedLocations: ["2️⃣", "3️⃣"]
|
|
)
|
|
}
|
|
|
|
func testOverrideProtocolFunc() async throws {
|
|
// TODO: We should not be reporting locations 4, 5 and 7 because they don't actually contain myFunc.
|
|
// We should, however, be reporting location 6. (https://github.com/swiftlang/sourcekit-lsp/issues/1600)
|
|
|
|
try await testImplementation(
|
|
"""
|
|
protocol MyProto {
|
|
func 1️⃣myFunc()
|
|
}
|
|
|
|
class ClassA: MyProto {
|
|
func 2️⃣myFunc() {}
|
|
}
|
|
class ClassB: MyProto {
|
|
func 3️⃣myFunc() {}
|
|
}
|
|
class 4️⃣ClassBSubA: ClassB {}
|
|
class 5️⃣ClassBSubB: ClassB {}
|
|
|
|
class RetroactiveConformanceClassWithMyFuncInClassDecl {
|
|
func 6️⃣myFunc() { }
|
|
}
|
|
extension 7️⃣RetroactiveConformanceClassWithMyFuncInClassDecl: MyProto {}
|
|
|
|
class RetroactiveConformanceClassWithMyFuncInExtension {}
|
|
extension RetroactiveConformanceClassWithMyFuncInExtension: MyProto {
|
|
func 8️⃣myFunc() { }
|
|
}
|
|
""",
|
|
expectedLocations: ["2️⃣", "3️⃣", "4️⃣", "5️⃣", "7️⃣", "8️⃣"]
|
|
)
|
|
}
|
|
|
|
func testCrossFile() async throws {
|
|
let project = try await SwiftPMTestProject(
|
|
files: [
|
|
"a.swift": """
|
|
protocol 1️⃣MyProto {}
|
|
""",
|
|
"b.swift": """
|
|
struct MyStruct: 2️⃣MyProto {}
|
|
""",
|
|
],
|
|
enableBackgroundIndexing: true
|
|
)
|
|
|
|
let (aUri, aPositions) = try project.openDocument("a.swift")
|
|
|
|
let response = try await project.testClient.send(
|
|
ImplementationRequest(
|
|
textDocument: TextDocumentIdentifier(aUri),
|
|
position: aPositions["1️⃣"]
|
|
)
|
|
)
|
|
XCTAssertEqual(
|
|
response?.locations,
|
|
[Location(uri: try project.uri(for: "b.swift"), range: Range(try project.position(of: "2️⃣", in: "b.swift")))]
|
|
)
|
|
}
|
|
}
|