diff --git a/Package.swift b/Package.swift index fafc27207..1a1fe770d 100644 --- a/Package.swift +++ b/Package.swift @@ -107,7 +107,7 @@ var targets: [Target] = [ .target( name: "SKLogging", dependencies: [ - "ToolsProtocolsSwiftExtensions", + "ToolsProtocolsSwiftExtensions" ], exclude: ["CMakeLists.txt"], swiftSettings: globalSwiftSettings + lspLoggingSwiftSettings @@ -123,7 +123,7 @@ var targets: [Target] = [ swiftSettings: globalSwiftSettings + lspLoggingSwiftSettings + [ .unsafeFlags([ "-module-alias", "ToolsProtocolsSwiftExtensions=_ToolsProtocolsSwiftExtensionsForPlugin", - ]), + ]) ] ), @@ -178,11 +178,13 @@ var targets: [Target] = [ // MARK: Command plugins .plugin( - name: "cmake-smoke-test", - capability: .command(intent: .custom( - verb: "cmake-smoke-test", - description: "Build Swift Build using CMake for validation purposes" - )) + name: "cmake-smoke-test", + capability: .command( + intent: .custom( + verb: "cmake-smoke-test", + description: "Build Swift Build using CMake for validation purposes" + ) + ) ), ] @@ -254,7 +256,7 @@ var dependencies: [Package.Dependency] { return [ // Not a build dependency. Used so the "Format Source Code" command plugin can be used to format sourcekit-lsp - .package(url: "https://github.com/swiftlang/swift-format.git", branch: relatedDependenciesBranch), + .package(url: "https://github.com/swiftlang/swift-format.git", branch: relatedDependenciesBranch) ] } } diff --git a/Plugins/cmake-smoke-test/cmake-smoke-test.swift b/Plugins/cmake-smoke-test/cmake-smoke-test.swift index e84a39c24..8de6163ea 100644 --- a/Plugins/cmake-smoke-test/cmake-smoke-test.swift +++ b/Plugins/cmake-smoke-test/cmake-smoke-test.swift @@ -10,156 +10,183 @@ // //===----------------------------------------------------------------------===// -import PackagePlugin import Foundation +import PackagePlugin @main struct CMakeSmokeTest: CommandPlugin { - func performCommand(context: PluginContext, arguments: [String]) async throws { - var args = ArgumentExtractor(arguments) + func performCommand(context: PluginContext, arguments: [String]) async throws { + var args = ArgumentExtractor(arguments) - guard args.extractFlag(named: "disable-sandbox") > 0 else { - throw Errors.missingRequiredOption("--disable-sandbox") - } - - guard let cmakePath = args.extractOption(named: "cmake-path").last else { throw Errors.missingRequiredOption("--cmake-path") } - Diagnostics.progress("using cmake at \(cmakePath)") - let cmakeURL = URL(filePath: cmakePath) - guard let ninjaPath = args.extractOption(named: "ninja-path").last else { throw Errors.missingRequiredOption("--ninja-path") } - Diagnostics.progress("using ninja at \(ninjaPath)") - let ninjaURL = URL(filePath: ninjaPath) - let sysrootPath = args.extractOption(named: "sysroot-path").last - if let sysrootPath { - Diagnostics.progress("using sysroot at \(sysrootPath)") - } + guard args.extractFlag(named: "disable-sandbox") > 0 else { + throw Errors.missingRequiredOption("--disable-sandbox") + } - let extraCMakeArgs = args.extractOption(named: "extra-cmake-arg") - Diagnostics.progress("Extra cmake args: \(extraCMakeArgs.joined(separator: " "))") + guard let cmakePath = args.extractOption(named: "cmake-path").last else { + throw Errors.missingRequiredOption("--cmake-path") + } + Diagnostics.progress("using cmake at \(cmakePath)") + let cmakeURL = URL(filePath: cmakePath) + guard let ninjaPath = args.extractOption(named: "ninja-path").last else { + throw Errors.missingRequiredOption("--ninja-path") + } + Diagnostics.progress("using ninja at \(ninjaPath)") + let ninjaURL = URL(filePath: ninjaPath) + let sysrootPath = args.extractOption(named: "sysroot-path").last + if let sysrootPath { + Diagnostics.progress("using sysroot at \(sysrootPath)") + } - let moduleCachePath = try context.pluginWorkDirectoryURL.appending(component: "module-cache").filePath + let extraCMakeArgs = args.extractOption(named: "extra-cmake-arg") + Diagnostics.progress("Extra cmake args: \(extraCMakeArgs.joined(separator: " "))") - let swiftToolsProtocolsURL = context.package.directoryURL - let swiftToolsProtocolsBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-build") - try Diagnostics.progress("swift-tools-protocols: \(swiftToolsProtocolsURL.filePath)") + let moduleCachePath = try context.pluginWorkDirectoryURL.appending(component: "module-cache").filePath - try FileManager.default.createDirectory(at: swiftToolsProtocolsBuildURL, withIntermediateDirectories: true) + let swiftToolsProtocolsURL = context.package.directoryURL + let swiftToolsProtocolsBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-build") + try Diagnostics.progress("swift-tools-protocols: \(swiftToolsProtocolsURL.filePath)") - var sharedSwiftFlags = [ - "-module-cache-path", moduleCachePath - ] + try FileManager.default.createDirectory(at: swiftToolsProtocolsBuildURL, withIntermediateDirectories: true) - if let sysrootPath { - sharedSwiftFlags += ["-sdk", sysrootPath] - } + var sharedSwiftFlags = [ + "-module-cache-path", moduleCachePath, + ] - let sharedCMakeArgs = [ - "-G", "Ninja", - "-DCMAKE_MAKE_PROGRAM=\(ninjaPath)", - "-DCMAKE_BUILD_TYPE:=Debug", - "-DCMAKE_Swift_FLAGS='\(sharedSwiftFlags.joined(separator: " "))'" - ] + extraCMakeArgs - - Diagnostics.progress("Building swift-tools-protocols") - try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftToolsProtocolsURL.filePath], workingDirectory: swiftToolsProtocolsBuildURL) - try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftToolsProtocolsBuildURL) - Diagnostics.progress("Built swift-tools-protocols") + if let sysrootPath { + sharedSwiftFlags += ["-sdk", sysrootPath] } + + let sharedCMakeArgs = + [ + "-G", "Ninja", + "-DCMAKE_MAKE_PROGRAM=\(ninjaPath)", + "-DCMAKE_BUILD_TYPE:=Debug", + "-DCMAKE_Swift_FLAGS='\(sharedSwiftFlags.joined(separator: " "))'", + ] + extraCMakeArgs + + Diagnostics.progress("Building swift-tools-protocols") + try await Process.checkNonZeroExit( + url: cmakeURL, + arguments: sharedCMakeArgs + [swiftToolsProtocolsURL.filePath], + workingDirectory: swiftToolsProtocolsBuildURL + ) + try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftToolsProtocolsBuildURL) + Diagnostics.progress("Built swift-tools-protocols") + } } enum Errors: Error { - case processError(terminationReason: Process.TerminationReason, terminationStatus: Int32) - case missingRequiredOption(String) - case miscError(String) + case processError(terminationReason: Process.TerminationReason, terminationStatus: Int32) + case missingRequiredOption(String) + case miscError(String) } extension URL { - var filePath: String { - get throws { - try withUnsafeFileSystemRepresentation { path in - guard let path else { - throw Errors.miscError("cannot get file path for URL: \(self)") - } - return String(cString: path) - } + var filePath: String { + get throws { + try withUnsafeFileSystemRepresentation { path in + guard let path else { + throw Errors.miscError("cannot get file path for URL: \(self)") } + return String(cString: path) + } } + } } extension Process { - func run() async throws { - try await withCheckedThrowingContinuation { continuation in - terminationHandler = { _ in - continuation.resume() - } - - do { - try run() - } catch { - terminationHandler = nil - continuation.resume(throwing: error) - } - } + func run() async throws { + try await withCheckedThrowingContinuation { continuation in + terminationHandler = { _ in + continuation.resume() + } + + do { + try run() + } catch { + terminationHandler = nil + continuation.resume(throwing: error) + } } + } - static func checkNonZeroExit(url: URL, arguments: [String], workingDirectory: URL, environment: [String: String]? = nil) async throws { - try Diagnostics.progress("\(url.filePath) \(arguments.joined(separator: " "))") - #if USE_PROCESS_SPAWNING_WORKAROUND && !os(Windows) - Diagnostics.progress("Using process spawning workaround") - // Linux workaround for https://github.com/swiftlang/swift-corelibs-foundation/issues/4772 - // Foundation.Process on Linux seems to inherit the Process.run()-calling thread's signal mask, creating processes that even have SIGTERM blocked - // This manifests as CMake getting stuck when invoking 'uname' with incorrectly configured signal handlers. - var fileActions = posix_spawn_file_actions_t() - defer { posix_spawn_file_actions_destroy(&fileActions) } - var attrs: posix_spawnattr_t = posix_spawnattr_t() - defer { posix_spawnattr_destroy(&attrs) } - posix_spawn_file_actions_init(&fileActions) - try posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory.filePath) - - posix_spawnattr_init(&attrs) - posix_spawnattr_setpgroup(&attrs, 0) - var noSignals = sigset_t() - sigemptyset(&noSignals) - posix_spawnattr_setsigmask(&attrs, &noSignals) - - var mostSignals = sigset_t() - sigemptyset(&mostSignals) - for i in 1 ..< SIGSYS { - if i == SIGKILL || i == SIGSTOP { - continue - } - sigaddset(&mostSignals, i) + static func checkNonZeroExit( + url: URL, + arguments: [String], + workingDirectory: URL, + environment: [String: String]? = nil + ) async throws { + try Diagnostics.progress("\(url.filePath) \(arguments.joined(separator: " "))") + #if USE_PROCESS_SPAWNING_WORKAROUND && !os(Windows) + Diagnostics.progress("Using process spawning workaround") + // Linux workaround for https://github.com/swiftlang/swift-corelibs-foundation/issues/4772 + // Foundation.Process on Linux seems to inherit the Process.run()-calling thread's signal mask, creating processes that even have SIGTERM blocked + // This manifests as CMake getting stuck when invoking 'uname' with incorrectly configured signal handlers. + var fileActions = posix_spawn_file_actions_t() + defer { posix_spawn_file_actions_destroy(&fileActions) } + var attrs: posix_spawnattr_t = posix_spawnattr_t() + defer { posix_spawnattr_destroy(&attrs) } + posix_spawn_file_actions_init(&fileActions) + try posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory.filePath) + + posix_spawnattr_init(&attrs) + posix_spawnattr_setpgroup(&attrs, 0) + var noSignals = sigset_t() + sigemptyset(&noSignals) + posix_spawnattr_setsigmask(&attrs, &noSignals) + + var mostSignals = sigset_t() + sigemptyset(&mostSignals) + for i in 1..( return try argsBuffer.withUnsafeMutableBufferPointer { (argsBuffer) in let ptr = UnsafeRawPointer(argsBuffer.baseAddress!).bindMemory( - to: Int8.self, capacity: argsBuffer.count) + to: Int8.self, + capacity: argsBuffer.count + ) var cStrings: [UnsafePointer?] = argsOffsets.map { ptr + $0 } cStrings[cStrings.count - 1] = nil return try cStrings.withUnsafeMutableBufferPointer { let unsafeString = UnsafeMutableRawPointer($0.baseAddress!).bindMemory( - to: UnsafeMutablePointer?.self, capacity: $0.count) + to: UnsafeMutablePointer?.self, + capacity: $0.count + ) return try body(unsafeString) } } diff --git a/Sources/SKLogging/NonDarwinLogging.swift b/Sources/SKLogging/NonDarwinLogging.swift index c93c05002..9741a48c9 100644 --- a/Sources/SKLogging/NonDarwinLogging.swift +++ b/Sources/SKLogging/NonDarwinLogging.swift @@ -184,7 +184,10 @@ import Foundation } } - @_spi(SourceKitLSP) public mutating func appendInterpolation(_ message: StaticString, privacy: NonDarwinLogPrivacy = .public) { + @_spi(SourceKitLSP) public mutating func appendInterpolation( + _ message: StaticString, + privacy: NonDarwinLogPrivacy = .public + ) { append(description: message.description, redactedDescription: "", privacy: privacy) } @@ -214,7 +217,8 @@ import Foundation } } - @_spi(SourceKitLSP) public mutating func appendInterpolation(_ type: Any.Type, privacy: NonDarwinLogPrivacy = .public) { + @_spi(SourceKitLSP) public mutating func appendInterpolation(_ type: Any.Type, privacy: NonDarwinLogPrivacy = .public) + { append(description: String(reflecting: type), redactedDescription: "", privacy: privacy) } @@ -225,7 +229,8 @@ import Foundation append(description: String(describing: message), redactedDescription: "", privacy: privacy) } - @_spi(SourceKitLSP) public mutating func appendInterpolation(_ message: Bool, privacy: NonDarwinLogPrivacy = .public) { + @_spi(SourceKitLSP) public mutating func appendInterpolation(_ message: Bool, privacy: NonDarwinLogPrivacy = .public) + { append(description: message.description, redactedDescription: "", privacy: privacy) } @@ -253,7 +258,8 @@ import Foundation /// sourcekit-lsp. /// /// This is used on platforms that don't have OSLog. -@_spi(SourceKitLSP) public struct NonDarwinLogMessage: ExpressibleByStringInterpolation, ExpressibleByStringLiteral, Sendable { +@_spi(SourceKitLSP) +public struct NonDarwinLogMessage: ExpressibleByStringInterpolation, ExpressibleByStringLiteral, Sendable { fileprivate let value: NonDarwinLogInterpolation @_spi(SourceKitLSP) public init(stringInterpolation: NonDarwinLogInterpolation) { @@ -435,7 +441,11 @@ private let nextSignpostID = AtomicUInt32(initialValue: 0) return NonDarwinSignpostIntervalState(id: id) } - @_spi(SourceKitLSP) public func emitEvent(_ name: StaticString, id: NonDarwinSignpostID, _ message: NonDarwinLogMessage = "") { + @_spi(SourceKitLSP) public func emitEvent( + _ name: StaticString, + id: NonDarwinSignpostID, + _ message: NonDarwinLogMessage = "" + ) { logger.log(level: .debug, "Signpost \(id.id) event: \(name) - \(message.value.string(for: logger.privacyLevel))") } diff --git a/Sources/SKLogging/SetGlobalLogFileHandler.swift b/Sources/SKLogging/SetGlobalLogFileHandler.swift index ac13ddd94..33f15f7f4 100644 --- a/Sources/SKLogging/SetGlobalLogFileHandler.swift +++ b/Sources/SKLogging/SetGlobalLogFileHandler.swift @@ -179,7 +179,11 @@ private func cleanOldLogFilesImpl(logFileDirectory: URL, maxAge: TimeInterval) { /// when it does. /// /// No-op when using OSLog. -@_spi(SourceKitLSP) public func setUpGlobalLogFileHandler(logFileDirectory: URL, logFileMaxBytes: Int, logRotateCount: Int) async { +@_spi(SourceKitLSP) public func setUpGlobalLogFileHandler( + logFileDirectory: URL, + logFileMaxBytes: Int, + logRotateCount: Int +) async { #if !canImport(os) || SOURCEKIT_LSP_FORCE_NON_DARWIN_LOGGER await setUpGlobalLogFileHandlerImpl( logFileDirectory: logFileDirectory, diff --git a/Sources/ToolsProtocolsSwiftExtensions/AsyncQueue.swift b/Sources/ToolsProtocolsSwiftExtensions/AsyncQueue.swift index b26c9d7f5..3aaf6d238 100644 --- a/Sources/ToolsProtocolsSwiftExtensions/AsyncQueue.swift +++ b/Sources/ToolsProtocolsSwiftExtensions/AsyncQueue.swift @@ -90,7 +90,7 @@ public final class AsyncQueue: Sendable { /// finish execution before the barrier is executed and all tasks that are /// added later will wait until the barrier finishes execution. @discardableResult - public func async( + public func async( priority: TaskPriority? = nil, metadata: TaskMetadata, @_inheritActorContext operation: @escaping @Sendable () async -> Success @@ -111,7 +111,7 @@ public final class AsyncQueue: Sendable { /// /// - Important: The caller is responsible for handling any errors thrown from /// the operation by awaiting the result of the returned task. -public func asyncThrowing( + public func asyncThrowing( priority: TaskPriority? = nil, metadata: TaskMetadata, @_inheritActorContext operation: @escaping @Sendable () async throws -> Success diff --git a/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift b/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift index 598284100..0e5a7511f 100644 --- a/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift +++ b/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift @@ -24,7 +24,10 @@ public import Foundation /// Whether the task has been cancelled. @_spi(SourceKitLSP) public private(set) var isCancelled: Bool = false - @_spi(SourceKitLSP) public init(priority: TaskPriority? = nil, operation: @escaping @Sendable @concurrent () async throws -> Success) { + @_spi(SourceKitLSP) public init( + priority: TaskPriority? = nil, + operation: @escaping @Sendable @concurrent () async throws -> Success + ) { self.task = Task(priority: priority, operation: operation) } diff --git a/Tests/LanguageServerProtocolTests/ConnectionTests.swift b/Tests/LanguageServerProtocolTests/ConnectionTests.swift index 3265f6bcb..efedee815 100644 --- a/Tests/LanguageServerProtocolTests/ConnectionTests.swift +++ b/Tests/LanguageServerProtocolTests/ConnectionTests.swift @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// import LanguageServerProtocol -import ToolsProtocolsTestSupport import SKLogging +import ToolsProtocolsTestSupport import XCTest class ConnectionTests: XCTestCase { diff --git a/Tests/LanguageServerProtocolTransportTests/ConnectionPerfTests.swift b/Tests/LanguageServerProtocolTransportTests/ConnectionPerfTests.swift index 9a404ced0..a259bc342 100644 --- a/Tests/LanguageServerProtocolTransportTests/ConnectionPerfTests.swift +++ b/Tests/LanguageServerProtocolTransportTests/ConnectionPerfTests.swift @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// import LanguageServerProtocolTransport -import ToolsProtocolsTestSupport import SKLogging +import ToolsProtocolsTestSupport import XCTest class ConnectionPerfTests: PerfTestCase { diff --git a/Tests/ToolsProtocolsSwiftExtensionsTests/AsyncUtilsTests.swift b/Tests/ToolsProtocolsSwiftExtensionsTests/AsyncUtilsTests.swift index 3e29f8025..5443151fc 100644 --- a/Tests/ToolsProtocolsSwiftExtensionsTests/AsyncUtilsTests.swift +++ b/Tests/ToolsProtocolsSwiftExtensionsTests/AsyncUtilsTests.swift @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// @_spi(SourceKitLSP) import SKLogging -import ToolsProtocolsTestSupport @_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions +import ToolsProtocolsTestSupport import XCTest #if os(Windows)