Files
sourcekit-lsp/Tests/SourceKitDTests/SourceKitDTests.swift

115 lines
3.4 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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 Foundation
import ISDBTestSupport
import ISDBTibs
import LSPTestSupport
import LanguageServerProtocol
import SKCore
import SKSupport
import SKTestSupport
import SourceKitD
import TSCBasic
import XCTest
import enum PackageLoading.Platform
import class TSCBasic.Process
final class SourceKitDTests: XCTestCase {
static var sourcekitdPath: AbsolutePath! = nil
static var sdkpath: String? = nil
override class func setUp() {
sourcekitdPath = ToolchainRegistry.shared.default!.sourcekitd!
guard case .darwin? = Platform.current else { return }
sdkpath = try? Process.checkNonZeroExit(args: "/usr/bin/xcrun", "--show-sdk-path", "--sdk", "macosx")
.trimmingCharacters(in: .whitespacesAndNewlines)
}
func testMultipleNotificationHandlers() async throws {
let sourcekitd = try SourceKitDImpl.getOrCreate(dylibPath: SourceKitDTests.sourcekitdPath)
let keys = sourcekitd.keys
let path = DocumentURI.for(.swift).pseudoPath
let isExpectedNotification = { (response: SKDResponse) -> Bool in
if let notification: sourcekitd_uid_t = response.value?[keys.notification],
let name: String = response.value?[keys.name]
{
return name == path && notification == sourcekitd.values.notification_documentupdate
}
return false
}
let expectation1 = expectation(description: "handler 1")
let handler1 = ClosureNotificationHandler { response in
if isExpectedNotification(response) {
expectation1.fulfill()
}
}
// SourceKitDImpl weakly references handlers
defer {
_fixLifetime(handler1)
}
sourcekitd.addNotificationHandler(handler1)
let expectation2 = expectation(description: "handler 2")
let handler2 = ClosureNotificationHandler { response in
if isExpectedNotification(response) {
expectation2.fulfill()
}
}
// SourceKitDImpl weakly references handlers
defer {
_fixLifetime(handler2)
}
sourcekitd.addNotificationHandler(handler2)
let args = SKDRequestArray(sourcekitd: sourcekitd)
if let sdkpath = SourceKitDTests.sdkpath {
args += ["-sdk", sdkpath]
}
args.append(path)
let req = sourcekitd.dictionary([
keys.request: sourcekitd.requests.editor_open,
keys.name: path,
keys.sourcetext: """
func foo() {}
""",
keys.compilerargs: args,
])
_ = try await sourcekitd.send(req, fileContents: nil)
try await fulfillmentOfOrThrow([expectation1, expectation2])
let close = sourcekitd.dictionary([
keys.request: sourcekitd.requests.editor_close,
keys.name: path,
])
_ = try await sourcekitd.send(close, fileContents: nil)
}
}
private class ClosureNotificationHandler: SKDNotificationHandler {
let f: (SKDResponse) -> Void
init(_ f: @escaping (SKDResponse) -> Void) {
self.f = f
}
func notification(_ response: SKDResponse) {
f(response)
}
}