From 30ce3d440136deba5464a4b8a64e4248246fa700 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 10 May 2023 11:29:43 -0700 Subject: [PATCH 01/15] SourceKittenFramework: use `free` rather than `UMRP.deallocate` The `UMRP.deallocate` will bridge to `_aligned_free` which requires that the data be allocated with `_aligned_malloc`. This does not hold as the string is being duplicated via `strdup` and must be free'd explicitly with `free`. This happens to work on existing platforms as Darwin and Linux do not use a separate memory arena for aligned memory allocations. --- Source/SourceKittenFramework/SourceKitObject.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/SourceKittenFramework/SourceKitObject.swift b/Source/SourceKittenFramework/SourceKitObject.swift index 0af9f3f7..1660b61e 100644 --- a/Source/SourceKittenFramework/SourceKitObject.swift +++ b/Source/SourceKittenFramework/SourceKitObject.swift @@ -3,6 +3,14 @@ import Foundation import SourceKit #endif +#if os(Linux) +import Glibc +#elseif os(Windows) +import ucrt +#else +import Darwin +#endif + // MARK: - SourceKitObjectConvertible public protocol SourceKitObjectConvertible { @@ -136,7 +144,7 @@ extension SourceKitObject: SourceKitObjectConvertible { extension SourceKitObject: CustomStringConvertible { public var description: String { let bytes = sourcekitd_request_description_copy(sourcekitdObject)! - defer { bytes.deallocate() } + defer { free(bytes) } return String(cString: bytes) } } From 081c31eb77bbe8a3744107eaf544eaa87dbfaafa Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 10 May 2023 11:32:10 -0700 Subject: [PATCH 02/15] SourceKittenFramework: treat Windows more similar to Darwin Windows packages libclang however the library name is spelled differently. Adjust the library name for Windows support. --- .../library_wrapper_Clang_C.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/SourceKittenFramework/library_wrapper_Clang_C.swift b/Source/SourceKittenFramework/library_wrapper_Clang_C.swift index 03ac43e0..bfe42c91 100644 --- a/Source/SourceKittenFramework/library_wrapper_Clang_C.swift +++ b/Source/SourceKittenFramework/library_wrapper_Clang_C.swift @@ -1,9 +1,21 @@ #if !os(Linux) + +#if os(Windows) +import WinSDK +#else import Darwin +#endif + #if SWIFT_PACKAGE import Clang_C #endif + +#if os(Windows) +private let library = toolchainLoader.load(path: "libclang.dll") +#else private let library = toolchainLoader.load(path: "libclang.dylib") +#endif + // swiftlint:disable unused_declaration - We don't care if some of these are unused. internal let clang_getCString: @convention(c) (CXString) -> (UnsafePointer?) = library.load(symbol: "clang_getCString") internal let clang_disposeString: @convention(c) (CXString) -> () = library.load(symbol: "clang_disposeString") From c0e039b926a288258c452b34bdf06de74406af2f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 10 May 2023 11:33:23 -0700 Subject: [PATCH 03/15] SourceKittenFramework: add Windows spelling for sourcekitd The Source Kit library on Windows is spelt `sourcekitdInProc.dll`. Add the alternate spelling to support Windows. --- Source/SourceKittenFramework/library_wrapper_SourceKit.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/SourceKittenFramework/library_wrapper_SourceKit.swift b/Source/SourceKittenFramework/library_wrapper_SourceKit.swift index 28e038a9..c72b1293 100644 --- a/Source/SourceKittenFramework/library_wrapper_SourceKit.swift +++ b/Source/SourceKittenFramework/library_wrapper_SourceKit.swift @@ -1,11 +1,15 @@ #if SWIFT_PACKAGE import SourceKit #endif + #if os(Linux) private let path = "libsourcekitdInProc.so" +#elseif os(Windows) +private let path = "sourcekitdInProc.dll" #else private let path = "sourcekitdInProc.framework/Versions/A/sourcekitdInProc" #endif + private let library = toolchainLoader.load(path: path) // swiftlint:disable unused_declaration - We don't care if some of these are unused. internal let sourcekitd_initialize: @convention(c) () -> () = library.load(symbol: "sourcekitd_initialize") From 0d6321d7f075f4d671bc296b0e1c9293dc83ff57 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 10 May 2023 11:36:35 -0700 Subject: [PATCH 04/15] SourceKittenFramework: adjust import for Windows Add the Windows equivalent module name for the C library import that is needed to build this module. --- Source/SourceKittenFramework/SwiftDocs.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/SourceKittenFramework/SwiftDocs.swift b/Source/SourceKittenFramework/SwiftDocs.swift index 0d368d75..8a602d60 100644 --- a/Source/SourceKittenFramework/SwiftDocs.swift +++ b/Source/SourceKittenFramework/SwiftDocs.swift @@ -4,6 +4,8 @@ import SourceKit #if os(Linux) import Glibc +#elseif os(Windows) +import CRT #else import Darwin #endif From 326cefc7d8e2ce334dc4e062a77b9fc05e1d6c50 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 10 May 2023 11:39:27 -0700 Subject: [PATCH 05/15] SourceKittenFramework: support Windows SDK for Swift code Windows uses the environment variable `SDKROOT` to specify a default SDK to use for development. The user may override this by passing `-sdk ...` explicitly. Use the environment variable for the tests. --- Source/SourceKittenFramework/Xcode.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/SourceKittenFramework/Xcode.swift b/Source/SourceKittenFramework/Xcode.swift index c53eb857..06289c05 100755 --- a/Source/SourceKittenFramework/Xcode.swift +++ b/Source/SourceKittenFramework/Xcode.swift @@ -189,6 +189,8 @@ public func sdkPath() -> String { #if os(Linux) // xcrun does not exist on Linux return "" +#elseif os(Windows) + return ProcessInfo.processInfo.environment["SDKROOT"] ?? "" #else return Exec.run("/usr/bin/xcrun", "--show-sdk-path", "--sdk", "macosx").string ?? "" #endif From dd830a2cf3df43096ebe78ef42d3a6e8666c9ed9 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 May 2023 14:27:20 -0700 Subject: [PATCH 06/15] SourceKittenFramework: adjust source path computation Ensure that we convert to the real file path on the disk when we serialise out the information. Additionally, explicitly standardize the path for Windows as it will fail to resolve drive substitutions otherwise. --- Source/SourceKittenFramework/SwiftDocs.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/SourceKittenFramework/SwiftDocs.swift b/Source/SourceKittenFramework/SwiftDocs.swift index 8a602d60..c57fda44 100644 --- a/Source/SourceKittenFramework/SwiftDocs.swift +++ b/Source/SourceKittenFramework/SwiftDocs.swift @@ -1,3 +1,5 @@ +import Foundation + #if SWIFT_PACKAGE import SourceKit #endif @@ -70,6 +72,14 @@ public struct SwiftDocs { extension SwiftDocs: CustomStringConvertible { /// A textual JSON representation of `SwiftDocs`. public var description: String { - return toJSON(toNSDictionary([file.path ?? "": docsDictionary])) + let source: String + if let path = file.path { + source = URL(fileURLWithPath: path).standardizedFileURL.withUnsafeFileSystemRepresentation { + String(cString: $0!) + } + } else { + source = "" + } + return toJSON(toNSDictionary([source: docsDictionary])) } } From aa82725bb3e19818791c328943275ddf40dcdfbb Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 10 May 2023 11:37:17 -0700 Subject: [PATCH 07/15] sourcekitten: import the Windows C library The Windows platform uses msvcrt which has been replaced by the UCRT and is imported as `ucrt`. Alter the import for the C library for the `exit` function. --- Source/sourcekitten/main.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/sourcekitten/main.swift b/Source/sourcekitten/main.swift index a35a0029..cd7c22e2 100644 --- a/Source/sourcekitten/main.swift +++ b/Source/sourcekitten/main.swift @@ -3,6 +3,8 @@ import ArgumentParser import Darwin #elseif canImport(Glibc) import Glibc +#elseif os(Windows) +import ucrt #else #error("Unsupported platform") #endif From 02535daf3f4e6b1517515715acd64b472073f398 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 13 May 2023 09:04:15 -0700 Subject: [PATCH 08/15] Tests: disable syntaxtree tests on 5.9 This was removed on 5.9 in favour of swift-syntax. Disable the test on 5.9 or newer toolchain. --- Tests/SourceKittenFrameworkTests/SourceKitTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift index 67080bf7..97c6ef4f 100644 --- a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift +++ b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift @@ -284,7 +284,7 @@ class SourceKitTests: XCTestCase { let actualStructure = Structure(sourceKitResponse: output) XCTAssertEqual(expectedStructure, actualStructure) } - +#if compiler(<5.9) func testSyntaxTree() throws { let file = File(path: "\(fixturesDirectory)Bicycle.swift")! let request = Request.syntaxTree(file: file, byteTree: false) @@ -296,6 +296,7 @@ class SourceKitTests: XCTestCase { compareJSONString(withFixtureNamed: "BicycleSyntax", jsonString: syntaxJSON) } +#endif func testCompilerVersion() { XCTAssertTrue(SwiftVersion.current >= SwiftVersion.fiveDotOne) From a40695ddfe09d08a21a5792bd3afb9d6afe06b37 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 May 2023 15:42:38 -0700 Subject: [PATCH 09/15] Tests: add another version marker for Swift 5.9 (next?) SourceKit introduced the new attribute `reusingastcontext` on a cursor lookup. Add the ability to accommodate that by suffixing another version. --- Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift b/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift index f6cf043a..7c6fa8e2 100644 --- a/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift +++ b/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift @@ -59,7 +59,9 @@ private func compareDocs(withFixtureNamed name: String, file: StaticString = #fi } private func versionedExpectedFilename(for name: String) -> String { -#if compiler(>=5.6) +#if compiler(>=5.9) + let versions = ["swift-5.9", "swift-5.6", "swift-5.5.2", "swift-5.5", "swift-5.4", "swift-5.3.1", "swift-5.3", "swift-5.2", "swift-5.1", "swift-5.0"] +#elseif compiler(>=5.6) let versions = ["swift-5.6", "swift-5.5.2", "swift-5.5", "swift-5.4", "swift-5.3.1", "swift-5.3", "swift-5.2", "swift-5.1", "swift-5.0"] #elseif compiler(>=5.5.2) let versions = ["swift-5.5.2", "swift-5.5", "swift-5.4", "swift-5.3.1", "swift-5.3", "swift-5.2", "swift-5.1", "swift-5.0"] From 9ec783afd3ad3148456e268938f420c3bd2433c9 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 13 May 2023 12:03:45 -0700 Subject: [PATCH 10/15] Tests: prefer `XCTUnwrap` over forced unwrapping If there is a failure, the forced unwrapping will terminate the test suite. Prefer the `XCTUnwrap` to unwrap or fail instead. --- Tests/SourceKittenFrameworkTests/ModuleTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/SourceKittenFrameworkTests/ModuleTests.swift b/Tests/SourceKittenFrameworkTests/ModuleTests.swift index c64543e6..d5f25efb 100644 --- a/Tests/SourceKittenFrameworkTests/ModuleTests.swift +++ b/Tests/SourceKittenFrameworkTests/ModuleTests.swift @@ -46,7 +46,7 @@ class ModuleTests: XCTestCase { } let arguments = ["-workspace", "Commandant.xcworkspace", "-scheme", "Commandant"] - let commandantModule = Module(xcodeBuildArguments: arguments, name: nil, inPath: commandantPath)! + let commandantModule = try XCTUnwrap(Module(xcodeBuildArguments: arguments, name: nil, inPath: commandantPath)) compareJSONString(withFixtureNamed: "Commandant", jsonString: commandantModule.docs, rootDirectory: commandantPath) } @@ -73,7 +73,7 @@ class ModuleTests: XCTestCase { return } - let commandantModule = Module(spmArguments: [], spmName: "Commandant", inPath: commandantPath)! + let commandantModule = try XCTUnwrap(Module(spmArguments: [], spmName: "Commandant", inPath: commandantPath)) compareJSONString(withFixtureNamed: "CommandantSPM", jsonString: commandantModule.docs, rootDirectory: commandantPath) } From 3bceff2f272e9cf721b145cbf2b867d83173f3ff Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 12 May 2023 15:17:31 -0700 Subject: [PATCH 11/15] Tests: handle platform specific golden results Add a Windows specific expected results path. This allows us to exercise a greater number of tests on Windows than on Linux. --- Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift b/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift index 7c6fa8e2..40ce6266 100644 --- a/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift +++ b/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift @@ -78,6 +78,8 @@ private func versionedExpectedFilename(for name: String) -> String { #endif #if os(Linux) let platforms = ["Linux", ""] +#elseif os(Windows) + let platforms = ["Windows", ""] #else let platforms = [""] #endif From 057d71c34467d384e0a71d0e2736c08930c29511 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 13 May 2023 12:05:57 -0700 Subject: [PATCH 12/15] Tests: add the known set of strings for Windows This is a terrible workaround to deal with the fact that `strings` is not really available on Windows. Without this it is not possible to pass tests. --- .../SourceKitTests.swift | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift index 97c6ef4f..fe48af58 100644 --- a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift +++ b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift @@ -19,6 +19,208 @@ private let sourcekitStrings: [String] = { } fatalError("Could not find or load libsourcekitdInProc.so") }() +#elseif os(Windows) + return [ + "source.decl.attribute.__consuming", + "source.decl.attribute.__objc_bridged", + "source.decl.attribute.__raw_doc_comment", + "source.decl.attribute.__setter_access", + "source.decl.attribute.__synthesized_protocol", + "source.decl.attribute._alignment", + "source.decl.attribute._alwaysEmitIntoClient", + "source.decl.attribute._assemblyVision", + "source.decl.attribute._backDeploy", + "source.decl.attribute._borrowed", + "source.decl.attribute._cdecl", + "source.decl.attribute._clangImporterSynthesizedType", + "source.decl.attribute._compilerInitialized", + "source.decl.attribute._const", + "source.decl.attribute._custom", + "source.decl.attribute._disfavoredOverload", + "source.decl.attribute._dynamicReplacement", + "source.decl.attribute._effects", + "source.decl.attribute._exported", + "source.decl.attribute._fixed_layout", + "source.decl.attribute._forbidSerializingReference", + "source.decl.attribute._hasInitialValue", + "source.decl.attribute._hasMissingDesignatedInitializers", + "source.decl.attribute._hasStorage", + "source.decl.attribute._implementationOnly", + "source.decl.attribute._implements", + "source.decl.attribute._implicitSelfCapture", + "source.decl.attribute._inheritActorContext", + "source.decl.attribute._inheritsConvenienceInitializers", + "source.decl.attribute._local", + "source.decl.attribute._marker", + "source.decl.attribute._noAllocation", + "source.decl.attribute._noImplicitCopy", + "source.decl.attribute._noLocks", + "source.decl.attribute._nonEphemeral", + "source.decl.attribute._nonoverride", + "source.decl.attribute._nonSendable", + "source.decl.attribute._objc_non_lazy_realization", + "source.decl.attribute._objcRuntimeName", + "source.decl.attribute._optimize", + "source.decl.attribute._originallyDefinedIn", + "source.decl.attribute._private", + "source.decl.attribute._projectedValueProperty", + "source.decl.attribute._restatedObjCConformance", + "source.decl.attribute._semantics", + "source.decl.attribute._show_in_interface", + "source.decl.attribute._silgen_name", + "source.decl.attribute._specialize", + "source.decl.attribute._specializeExtension", + "source.decl.attribute._spi", + "source.decl.attribute._staticInitializeObjCMetadata", + "source.decl.attribute._swift_native_objc_runtime_base", + "source.decl.attribute._transparent", + "source.decl.attribute._typeEraser", + "source.decl.attribute._typeSequence", + "source.decl.attribute._unavailableFromAsync", + "source.decl.attribute._unsafeInheritExecutor", + "source.decl.attribute._weakLinked", + "source.decl.attribute.actor", + "source.decl.attribute.async", + "source.decl.attribute.available", + "source.decl.attribute.convenience", + "source.decl.attribute.derivative", + "source.decl.attribute.differentiable", + "source.decl.attribute.discardableResult", + "source.decl.attribute.distributed", + "source.decl.attribute.dynamic", + "source.decl.attribute.dynamicCallable", + "source.decl.attribute.dynamicMemberLookup", + "source.decl.attribute.exclusivity", + "source.decl.attribute.fileprivate", + "source.decl.attribute.final", + "source.decl.attribute.frozen", + "source.decl.attribute.gkinspectable", + "source.decl.attribute.globalActor", + "source.decl.attribute.ibaction", + "source.decl.attribute.ibdesignable", + "source.decl.attribute.ibinspectable", + "source.decl.attribute.iboutlet", + "source.decl.attribute.ibsegueaction", + "source.decl.attribute.IBSegueAction", + "source.decl.attribute.indirect", + "source.decl.attribute.infix", + "source.decl.attribute.inlinable", + "source.decl.attribute.inline", + "source.decl.attribute.internal", + "source.decl.attribute.isolated", + "source.decl.attribute.lazy", + "source.decl.attribute.LLDBDebuggerFunction", + "source.decl.attribute.main", + "source.decl.attribute.mutating", + "source.decl.attribute.noDerivative", + "source.decl.attribute.nonisolated", + "source.decl.attribute.nonmutating", + "source.decl.attribute.nonobjc", + "source.decl.attribute.NSApplicationMain", + "source.decl.attribute.NSCopying", + "source.decl.attribute.NSManaged", + "source.decl.attribute.objc.name", + "source.decl.attribute.objc", + "source.decl.attribute.objcMembers", + "source.decl.attribute.open", + "source.decl.attribute.optional", + "source.decl.attribute.override", + "source.decl.attribute.postfix", + "source.decl.attribute.preconcurrency", + "source.decl.attribute.prefix", + "source.decl.attribute.private", + "source.decl.attribute.propertyWrapper", + "source.decl.attribute.public", + "source.decl.attribute.reasync", + "source.decl.attribute.required", + "source.decl.attribute.requires_stored_property_inits", + "source.decl.attribute.resultBuilder", + "source.decl.attribute.rethrows", + "source.decl.attribute.Sendable", + "source.decl.attribute.setter_access.fileprivate", + "source.decl.attribute.setter_access.internal", + "source.decl.attribute.setter_access.open", + "source.decl.attribute.setter_access.private", + "source.decl.attribute.setter_access.public", + "source.decl.attribute.testable", + "source.decl.attribute.transpose", + "source.decl.attribute.UIApplicationMain", + "source.decl.attribute.unsafe_no_objc_tagged_pointer", + "source.decl.attribute.usableFromInline", + "source.decl.attribute.warn_unqualified_access", + "source.decl.attribute.weak", + "source.lang.swift.decl.actor", + "source.lang.swift.decl.associatedtype", + "source.lang.swift.decl.class", + "source.lang.swift.decl.enum", + "source.lang.swift.decl.enumcase", + "source.lang.swift.decl.enumelement", + "source.lang.swift.decl.extension.class", + "source.lang.swift.decl.extension.enum", + "source.lang.swift.decl.extension.protocol", + "source.lang.swift.decl.extension.struct", + "source.lang.swift.decl.extension", + "source.lang.swift.decl.function.accessor.address", + "source.lang.swift.decl.function.accessor.didset", + "source.lang.swift.decl.function.accessor.getter", + "source.lang.swift.decl.function.accessor.modify", + "source.lang.swift.decl.function.accessor.mutableaddress", + "source.lang.swift.decl.function.accessor.read", + "source.lang.swift.decl.function.accessor.setter", + "source.lang.swift.decl.function.accessor.willset", + "source.lang.swift.decl.function.constructor", + "source.lang.swift.decl.function.destructor", + "source.lang.swift.decl.function.free", + "source.lang.swift.decl.function.method.class", + "source.lang.swift.decl.function.method.instance", + "source.lang.swift.decl.function.method.static", + "source.lang.swift.decl.function.operator.infix", + "source.lang.swift.decl.function.operator.postfix", + "source.lang.swift.decl.function.operator.prefix", + "source.lang.swift.decl.function.subscript", + "source.lang.swift.decl.generic_type_param", + "source.lang.swift.decl.module", + "source.lang.swift.decl.opaquetype", + "source.lang.swift.decl.precedencegroup", + "source.lang.swift.decl.protocol", + "source.lang.swift.decl.struct", + "source.lang.swift.decl.typealias", + "source.lang.swift.decl.var.class", + "source.lang.swift.decl.var.global", + "source.lang.swift.decl.var.instance", + "source.lang.swift.decl.var.local", + "source.lang.swift.decl.var.parameter", + "source.lang.swift.decl.var.static", + "source.lang.swift.stmt.brace", + "source.lang.swift.stmt.case", + "source.lang.swift.stmt.for", + "source.lang.swift.stmt.foreach", + "source.lang.swift.stmt.guard", + "source.lang.swift.stmt.if", + "source.lang.swift.stmt.repeatwhile", + "source.lang.swift.stmt.switch", + "source.lang.swift.stmt.while", + "source.lang.swift.syntaxtype.argument", + "source.lang.swift.syntaxtype.attribute.builtin", + "source.lang.swift.syntaxtype.attribute.id", + "source.lang.swift.syntaxtype.buildconfig.id", + "source.lang.swift.syntaxtype.buildconfig.keyword", + "source.lang.swift.syntaxtype.comment.mark", + "source.lang.swift.syntaxtype.comment.url", + "source.lang.swift.syntaxtype.comment", + "source.lang.swift.syntaxtype.doccomment.field", + "source.lang.swift.syntaxtype.doccomment", + "source.lang.swift.syntaxtype.identifier", + "source.lang.swift.syntaxtype.keyword", + "source.lang.swift.syntaxtype.number", + "source.lang.swift.syntaxtype.objectliteral", + "source.lang.swift.syntaxtype.parameter", + "source.lang.swift.syntaxtype.placeholder", + "source.lang.swift.syntaxtype.pounddirective.keyword", + "source.lang.swift.syntaxtype.string_interpolation_anchor", + "source.lang.swift.syntaxtype.string", + "source.lang.swift.syntaxtype.typeidentifier", + ] #else // `sourcekitdInProc` doesn't exist on at least Xcode 11.7, and // `SourceKitService` doesn't contain the strings in Xcode 13. From d1ba00fb521b21653933709dff0563dc7c33b9c6 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Wed, 14 Jun 2023 10:12:46 -0400 Subject: [PATCH 13/15] Move `sourcekitStrings` definition to a separate file for Windows This keeps `SourceKitTests.swift` to a more reasonable length. --- .../SourceKitStrings+Windows.swift | 203 +++++++++++++++++ .../SourceKitTests.swift | 204 +----------------- 2 files changed, 205 insertions(+), 202 deletions(-) create mode 100644 Tests/SourceKittenFrameworkTests/SourceKitStrings+Windows.swift diff --git a/Tests/SourceKittenFrameworkTests/SourceKitStrings+Windows.swift b/Tests/SourceKittenFrameworkTests/SourceKitStrings+Windows.swift new file mode 100644 index 00000000..219e16ec --- /dev/null +++ b/Tests/SourceKittenFrameworkTests/SourceKitStrings+Windows.swift @@ -0,0 +1,203 @@ +#if os(Windows) +private let sourcekitStrings = [ + "source.decl.attribute.__consuming", + "source.decl.attribute.__objc_bridged", + "source.decl.attribute.__raw_doc_comment", + "source.decl.attribute.__setter_access", + "source.decl.attribute.__synthesized_protocol", + "source.decl.attribute._alignment", + "source.decl.attribute._alwaysEmitIntoClient", + "source.decl.attribute._assemblyVision", + "source.decl.attribute._backDeploy", + "source.decl.attribute._borrowed", + "source.decl.attribute._cdecl", + "source.decl.attribute._clangImporterSynthesizedType", + "source.decl.attribute._compilerInitialized", + "source.decl.attribute._const", + "source.decl.attribute._custom", + "source.decl.attribute._disfavoredOverload", + "source.decl.attribute._dynamicReplacement", + "source.decl.attribute._effects", + "source.decl.attribute._exported", + "source.decl.attribute._fixed_layout", + "source.decl.attribute._forbidSerializingReference", + "source.decl.attribute._hasInitialValue", + "source.decl.attribute._hasMissingDesignatedInitializers", + "source.decl.attribute._hasStorage", + "source.decl.attribute._implementationOnly", + "source.decl.attribute._implements", + "source.decl.attribute._implicitSelfCapture", + "source.decl.attribute._inheritActorContext", + "source.decl.attribute._inheritsConvenienceInitializers", + "source.decl.attribute._local", + "source.decl.attribute._marker", + "source.decl.attribute._noAllocation", + "source.decl.attribute._noImplicitCopy", + "source.decl.attribute._noLocks", + "source.decl.attribute._nonEphemeral", + "source.decl.attribute._nonoverride", + "source.decl.attribute._nonSendable", + "source.decl.attribute._objc_non_lazy_realization", + "source.decl.attribute._objcRuntimeName", + "source.decl.attribute._optimize", + "source.decl.attribute._originallyDefinedIn", + "source.decl.attribute._private", + "source.decl.attribute._projectedValueProperty", + "source.decl.attribute._restatedObjCConformance", + "source.decl.attribute._semantics", + "source.decl.attribute._show_in_interface", + "source.decl.attribute._silgen_name", + "source.decl.attribute._specialize", + "source.decl.attribute._specializeExtension", + "source.decl.attribute._spi", + "source.decl.attribute._staticInitializeObjCMetadata", + "source.decl.attribute._swift_native_objc_runtime_base", + "source.decl.attribute._transparent", + "source.decl.attribute._typeEraser", + "source.decl.attribute._typeSequence", + "source.decl.attribute._unavailableFromAsync", + "source.decl.attribute._unsafeInheritExecutor", + "source.decl.attribute._weakLinked", + "source.decl.attribute.actor", + "source.decl.attribute.async", + "source.decl.attribute.available", + "source.decl.attribute.convenience", + "source.decl.attribute.derivative", + "source.decl.attribute.differentiable", + "source.decl.attribute.discardableResult", + "source.decl.attribute.distributed", + "source.decl.attribute.dynamic", + "source.decl.attribute.dynamicCallable", + "source.decl.attribute.dynamicMemberLookup", + "source.decl.attribute.exclusivity", + "source.decl.attribute.fileprivate", + "source.decl.attribute.final", + "source.decl.attribute.frozen", + "source.decl.attribute.gkinspectable", + "source.decl.attribute.globalActor", + "source.decl.attribute.ibaction", + "source.decl.attribute.ibdesignable", + "source.decl.attribute.ibinspectable", + "source.decl.attribute.iboutlet", + "source.decl.attribute.ibsegueaction", + "source.decl.attribute.IBSegueAction", + "source.decl.attribute.indirect", + "source.decl.attribute.infix", + "source.decl.attribute.inlinable", + "source.decl.attribute.inline", + "source.decl.attribute.internal", + "source.decl.attribute.isolated", + "source.decl.attribute.lazy", + "source.decl.attribute.LLDBDebuggerFunction", + "source.decl.attribute.main", + "source.decl.attribute.mutating", + "source.decl.attribute.noDerivative", + "source.decl.attribute.nonisolated", + "source.decl.attribute.nonmutating", + "source.decl.attribute.nonobjc", + "source.decl.attribute.NSApplicationMain", + "source.decl.attribute.NSCopying", + "source.decl.attribute.NSManaged", + "source.decl.attribute.objc.name", + "source.decl.attribute.objc", + "source.decl.attribute.objcMembers", + "source.decl.attribute.open", + "source.decl.attribute.optional", + "source.decl.attribute.override", + "source.decl.attribute.postfix", + "source.decl.attribute.preconcurrency", + "source.decl.attribute.prefix", + "source.decl.attribute.private", + "source.decl.attribute.propertyWrapper", + "source.decl.attribute.public", + "source.decl.attribute.reasync", + "source.decl.attribute.required", + "source.decl.attribute.requires_stored_property_inits", + "source.decl.attribute.resultBuilder", + "source.decl.attribute.rethrows", + "source.decl.attribute.Sendable", + "source.decl.attribute.setter_access.fileprivate", + "source.decl.attribute.setter_access.internal", + "source.decl.attribute.setter_access.open", + "source.decl.attribute.setter_access.private", + "source.decl.attribute.setter_access.public", + "source.decl.attribute.testable", + "source.decl.attribute.transpose", + "source.decl.attribute.UIApplicationMain", + "source.decl.attribute.unsafe_no_objc_tagged_pointer", + "source.decl.attribute.usableFromInline", + "source.decl.attribute.warn_unqualified_access", + "source.decl.attribute.weak", + "source.lang.swift.decl.actor", + "source.lang.swift.decl.associatedtype", + "source.lang.swift.decl.class", + "source.lang.swift.decl.enum", + "source.lang.swift.decl.enumcase", + "source.lang.swift.decl.enumelement", + "source.lang.swift.decl.extension.class", + "source.lang.swift.decl.extension.enum", + "source.lang.swift.decl.extension.protocol", + "source.lang.swift.decl.extension.struct", + "source.lang.swift.decl.extension", + "source.lang.swift.decl.function.accessor.address", + "source.lang.swift.decl.function.accessor.didset", + "source.lang.swift.decl.function.accessor.getter", + "source.lang.swift.decl.function.accessor.modify", + "source.lang.swift.decl.function.accessor.mutableaddress", + "source.lang.swift.decl.function.accessor.read", + "source.lang.swift.decl.function.accessor.setter", + "source.lang.swift.decl.function.accessor.willset", + "source.lang.swift.decl.function.constructor", + "source.lang.swift.decl.function.destructor", + "source.lang.swift.decl.function.free", + "source.lang.swift.decl.function.method.class", + "source.lang.swift.decl.function.method.instance", + "source.lang.swift.decl.function.method.static", + "source.lang.swift.decl.function.operator.infix", + "source.lang.swift.decl.function.operator.postfix", + "source.lang.swift.decl.function.operator.prefix", + "source.lang.swift.decl.function.subscript", + "source.lang.swift.decl.generic_type_param", + "source.lang.swift.decl.module", + "source.lang.swift.decl.opaquetype", + "source.lang.swift.decl.precedencegroup", + "source.lang.swift.decl.protocol", + "source.lang.swift.decl.struct", + "source.lang.swift.decl.typealias", + "source.lang.swift.decl.var.class", + "source.lang.swift.decl.var.global", + "source.lang.swift.decl.var.instance", + "source.lang.swift.decl.var.local", + "source.lang.swift.decl.var.parameter", + "source.lang.swift.decl.var.static", + "source.lang.swift.stmt.brace", + "source.lang.swift.stmt.case", + "source.lang.swift.stmt.for", + "source.lang.swift.stmt.foreach", + "source.lang.swift.stmt.guard", + "source.lang.swift.stmt.if", + "source.lang.swift.stmt.repeatwhile", + "source.lang.swift.stmt.switch", + "source.lang.swift.stmt.while", + "source.lang.swift.syntaxtype.argument", + "source.lang.swift.syntaxtype.attribute.builtin", + "source.lang.swift.syntaxtype.attribute.id", + "source.lang.swift.syntaxtype.buildconfig.id", + "source.lang.swift.syntaxtype.buildconfig.keyword", + "source.lang.swift.syntaxtype.comment.mark", + "source.lang.swift.syntaxtype.comment.url", + "source.lang.swift.syntaxtype.comment", + "source.lang.swift.syntaxtype.doccomment.field", + "source.lang.swift.syntaxtype.doccomment", + "source.lang.swift.syntaxtype.identifier", + "source.lang.swift.syntaxtype.keyword", + "source.lang.swift.syntaxtype.number", + "source.lang.swift.syntaxtype.objectliteral", + "source.lang.swift.syntaxtype.parameter", + "source.lang.swift.syntaxtype.placeholder", + "source.lang.swift.syntaxtype.pounddirective.keyword", + "source.lang.swift.syntaxtype.string_interpolation_anchor", + "source.lang.swift.syntaxtype.string", + "source.lang.swift.syntaxtype.typeidentifier" +] +#endif diff --git a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift index fe48af58..d86ddeb8 100644 --- a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift +++ b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift @@ -2,6 +2,7 @@ import Foundation @testable import SourceKittenFramework import XCTest +#if !os(Windows) private let sourcekitStrings: [String] = { #if os(Linux) let searchPaths = [ @@ -19,208 +20,6 @@ private let sourcekitStrings: [String] = { } fatalError("Could not find or load libsourcekitdInProc.so") }() -#elseif os(Windows) - return [ - "source.decl.attribute.__consuming", - "source.decl.attribute.__objc_bridged", - "source.decl.attribute.__raw_doc_comment", - "source.decl.attribute.__setter_access", - "source.decl.attribute.__synthesized_protocol", - "source.decl.attribute._alignment", - "source.decl.attribute._alwaysEmitIntoClient", - "source.decl.attribute._assemblyVision", - "source.decl.attribute._backDeploy", - "source.decl.attribute._borrowed", - "source.decl.attribute._cdecl", - "source.decl.attribute._clangImporterSynthesizedType", - "source.decl.attribute._compilerInitialized", - "source.decl.attribute._const", - "source.decl.attribute._custom", - "source.decl.attribute._disfavoredOverload", - "source.decl.attribute._dynamicReplacement", - "source.decl.attribute._effects", - "source.decl.attribute._exported", - "source.decl.attribute._fixed_layout", - "source.decl.attribute._forbidSerializingReference", - "source.decl.attribute._hasInitialValue", - "source.decl.attribute._hasMissingDesignatedInitializers", - "source.decl.attribute._hasStorage", - "source.decl.attribute._implementationOnly", - "source.decl.attribute._implements", - "source.decl.attribute._implicitSelfCapture", - "source.decl.attribute._inheritActorContext", - "source.decl.attribute._inheritsConvenienceInitializers", - "source.decl.attribute._local", - "source.decl.attribute._marker", - "source.decl.attribute._noAllocation", - "source.decl.attribute._noImplicitCopy", - "source.decl.attribute._noLocks", - "source.decl.attribute._nonEphemeral", - "source.decl.attribute._nonoverride", - "source.decl.attribute._nonSendable", - "source.decl.attribute._objc_non_lazy_realization", - "source.decl.attribute._objcRuntimeName", - "source.decl.attribute._optimize", - "source.decl.attribute._originallyDefinedIn", - "source.decl.attribute._private", - "source.decl.attribute._projectedValueProperty", - "source.decl.attribute._restatedObjCConformance", - "source.decl.attribute._semantics", - "source.decl.attribute._show_in_interface", - "source.decl.attribute._silgen_name", - "source.decl.attribute._specialize", - "source.decl.attribute._specializeExtension", - "source.decl.attribute._spi", - "source.decl.attribute._staticInitializeObjCMetadata", - "source.decl.attribute._swift_native_objc_runtime_base", - "source.decl.attribute._transparent", - "source.decl.attribute._typeEraser", - "source.decl.attribute._typeSequence", - "source.decl.attribute._unavailableFromAsync", - "source.decl.attribute._unsafeInheritExecutor", - "source.decl.attribute._weakLinked", - "source.decl.attribute.actor", - "source.decl.attribute.async", - "source.decl.attribute.available", - "source.decl.attribute.convenience", - "source.decl.attribute.derivative", - "source.decl.attribute.differentiable", - "source.decl.attribute.discardableResult", - "source.decl.attribute.distributed", - "source.decl.attribute.dynamic", - "source.decl.attribute.dynamicCallable", - "source.decl.attribute.dynamicMemberLookup", - "source.decl.attribute.exclusivity", - "source.decl.attribute.fileprivate", - "source.decl.attribute.final", - "source.decl.attribute.frozen", - "source.decl.attribute.gkinspectable", - "source.decl.attribute.globalActor", - "source.decl.attribute.ibaction", - "source.decl.attribute.ibdesignable", - "source.decl.attribute.ibinspectable", - "source.decl.attribute.iboutlet", - "source.decl.attribute.ibsegueaction", - "source.decl.attribute.IBSegueAction", - "source.decl.attribute.indirect", - "source.decl.attribute.infix", - "source.decl.attribute.inlinable", - "source.decl.attribute.inline", - "source.decl.attribute.internal", - "source.decl.attribute.isolated", - "source.decl.attribute.lazy", - "source.decl.attribute.LLDBDebuggerFunction", - "source.decl.attribute.main", - "source.decl.attribute.mutating", - "source.decl.attribute.noDerivative", - "source.decl.attribute.nonisolated", - "source.decl.attribute.nonmutating", - "source.decl.attribute.nonobjc", - "source.decl.attribute.NSApplicationMain", - "source.decl.attribute.NSCopying", - "source.decl.attribute.NSManaged", - "source.decl.attribute.objc.name", - "source.decl.attribute.objc", - "source.decl.attribute.objcMembers", - "source.decl.attribute.open", - "source.decl.attribute.optional", - "source.decl.attribute.override", - "source.decl.attribute.postfix", - "source.decl.attribute.preconcurrency", - "source.decl.attribute.prefix", - "source.decl.attribute.private", - "source.decl.attribute.propertyWrapper", - "source.decl.attribute.public", - "source.decl.attribute.reasync", - "source.decl.attribute.required", - "source.decl.attribute.requires_stored_property_inits", - "source.decl.attribute.resultBuilder", - "source.decl.attribute.rethrows", - "source.decl.attribute.Sendable", - "source.decl.attribute.setter_access.fileprivate", - "source.decl.attribute.setter_access.internal", - "source.decl.attribute.setter_access.open", - "source.decl.attribute.setter_access.private", - "source.decl.attribute.setter_access.public", - "source.decl.attribute.testable", - "source.decl.attribute.transpose", - "source.decl.attribute.UIApplicationMain", - "source.decl.attribute.unsafe_no_objc_tagged_pointer", - "source.decl.attribute.usableFromInline", - "source.decl.attribute.warn_unqualified_access", - "source.decl.attribute.weak", - "source.lang.swift.decl.actor", - "source.lang.swift.decl.associatedtype", - "source.lang.swift.decl.class", - "source.lang.swift.decl.enum", - "source.lang.swift.decl.enumcase", - "source.lang.swift.decl.enumelement", - "source.lang.swift.decl.extension.class", - "source.lang.swift.decl.extension.enum", - "source.lang.swift.decl.extension.protocol", - "source.lang.swift.decl.extension.struct", - "source.lang.swift.decl.extension", - "source.lang.swift.decl.function.accessor.address", - "source.lang.swift.decl.function.accessor.didset", - "source.lang.swift.decl.function.accessor.getter", - "source.lang.swift.decl.function.accessor.modify", - "source.lang.swift.decl.function.accessor.mutableaddress", - "source.lang.swift.decl.function.accessor.read", - "source.lang.swift.decl.function.accessor.setter", - "source.lang.swift.decl.function.accessor.willset", - "source.lang.swift.decl.function.constructor", - "source.lang.swift.decl.function.destructor", - "source.lang.swift.decl.function.free", - "source.lang.swift.decl.function.method.class", - "source.lang.swift.decl.function.method.instance", - "source.lang.swift.decl.function.method.static", - "source.lang.swift.decl.function.operator.infix", - "source.lang.swift.decl.function.operator.postfix", - "source.lang.swift.decl.function.operator.prefix", - "source.lang.swift.decl.function.subscript", - "source.lang.swift.decl.generic_type_param", - "source.lang.swift.decl.module", - "source.lang.swift.decl.opaquetype", - "source.lang.swift.decl.precedencegroup", - "source.lang.swift.decl.protocol", - "source.lang.swift.decl.struct", - "source.lang.swift.decl.typealias", - "source.lang.swift.decl.var.class", - "source.lang.swift.decl.var.global", - "source.lang.swift.decl.var.instance", - "source.lang.swift.decl.var.local", - "source.lang.swift.decl.var.parameter", - "source.lang.swift.decl.var.static", - "source.lang.swift.stmt.brace", - "source.lang.swift.stmt.case", - "source.lang.swift.stmt.for", - "source.lang.swift.stmt.foreach", - "source.lang.swift.stmt.guard", - "source.lang.swift.stmt.if", - "source.lang.swift.stmt.repeatwhile", - "source.lang.swift.stmt.switch", - "source.lang.swift.stmt.while", - "source.lang.swift.syntaxtype.argument", - "source.lang.swift.syntaxtype.attribute.builtin", - "source.lang.swift.syntaxtype.attribute.id", - "source.lang.swift.syntaxtype.buildconfig.id", - "source.lang.swift.syntaxtype.buildconfig.keyword", - "source.lang.swift.syntaxtype.comment.mark", - "source.lang.swift.syntaxtype.comment.url", - "source.lang.swift.syntaxtype.comment", - "source.lang.swift.syntaxtype.doccomment.field", - "source.lang.swift.syntaxtype.doccomment", - "source.lang.swift.syntaxtype.identifier", - "source.lang.swift.syntaxtype.keyword", - "source.lang.swift.syntaxtype.number", - "source.lang.swift.syntaxtype.objectliteral", - "source.lang.swift.syntaxtype.parameter", - "source.lang.swift.syntaxtype.placeholder", - "source.lang.swift.syntaxtype.pounddirective.keyword", - "source.lang.swift.syntaxtype.string_interpolation_anchor", - "source.lang.swift.syntaxtype.string", - "source.lang.swift.syntaxtype.typeidentifier", - ] #else // `sourcekitdInProc` doesn't exist on at least Xcode 11.7, and // `SourceKitService` doesn't contain the strings in Xcode 13. @@ -237,6 +36,7 @@ private let sourcekitStrings: [String] = { let strings = Exec.run("/usr/bin/strings", sourceKitPath).string return strings!.components(separatedBy: "\n") }() +#endif private func sourcekitStrings(startingWith pattern: String) -> Set { return Set(sourcekitStrings.filter { $0.hasPrefix(pattern) }) From 41654fd1999115fc1b2dd2435f07371c9e4c21c0 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Wed, 14 Jun 2023 10:12:46 -0400 Subject: [PATCH 14/15] Update fixtures --- .../Fixtures/CommandantSPM.json | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Tests/SourceKittenFrameworkTests/Fixtures/CommandantSPM.json b/Tests/SourceKittenFrameworkTests/Fixtures/CommandantSPM.json index 8c3199b2..e6379832 100644 --- a/Tests/SourceKittenFrameworkTests/Fixtures/CommandantSPM.json +++ b/Tests/SourceKittenFrameworkTests/Fixtures/CommandantSPM.json @@ -1,5 +1,5 @@ [{ - "\/private\/Sources\/Commandant\/Argument.swift" : { + "\/Sources\/Commandant\/Argument.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 3858, "key.offset" : 0, @@ -746,7 +746,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/ArgumentParser.swift" : { + "\/Sources\/Commandant\/ArgumentParser.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 4637, "key.offset" : 0, @@ -1615,7 +1615,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/ArgumentProtocol.swift" : { + "\/Sources\/Commandant\/ArgumentProtocol.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 1141, "key.offset" : 0, @@ -2406,7 +2406,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/Command.swift" : { + "\/Sources\/Commandant\/Command.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 7522, "key.offset" : 0, @@ -3704,7 +3704,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/Errors.swift" : { + "\/Sources\/Commandant\/Errors.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 5739, "key.offset" : 0, @@ -5501,7 +5501,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/HelpCommand.swift" : { + "\/Sources\/Commandant\/HelpCommand.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 2203, "key.offset" : 0, @@ -6126,7 +6126,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/Option.swift" : { + "\/Sources\/Commandant\/Option.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 9661, "key.offset" : 0, @@ -7692,7 +7692,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/OrderedSet.swift" : { + "\/Sources\/Commandant\/OrderedSet.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 800, "key.offset" : 0, @@ -8255,7 +8255,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/Result+Additions.swift" : { + "\/Sources\/Commandant\/Result+Additions.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 421, "key.offset" : 0, @@ -8347,7 +8347,7 @@ ] } }, { - "\/private\/Sources\/Commandant\/Switch.swift" : { + "\/Sources\/Commandant\/Switch.swift" : { "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 2007, "key.offset" : 0, From d01d7084853beb7d1e0cf68e82ee07d8fc9d9878 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Wed, 14 Jun 2023 11:48:10 -0400 Subject: [PATCH 15/15] Update library wrapper codegen for Windows Now that we are adding support for a 3rd platform, we should make the library wrapper generation more robust. --- .../LibraryWrapperGenerator.swift | 145 ++++++++++++++++++ Source/SourceKittenFramework/Request.swift | 88 ----------- .../library_wrapper_Clang_C.swift | 2 + .../library_wrapper_SourceKit.swift | 8 +- .../LibraryWrapperGeneratorTests.swift | 25 +++ .../SourceKitTests.swift | 29 ---- 6 files changed, 176 insertions(+), 121 deletions(-) create mode 100644 Source/SourceKittenFramework/LibraryWrapperGenerator.swift create mode 100644 Tests/SourceKittenFrameworkTests/LibraryWrapperGeneratorTests.swift diff --git a/Source/SourceKittenFramework/LibraryWrapperGenerator.swift b/Source/SourceKittenFramework/LibraryWrapperGenerator.swift new file mode 100644 index 00000000..e7c40baf --- /dev/null +++ b/Source/SourceKittenFramework/LibraryWrapperGenerator.swift @@ -0,0 +1,145 @@ +import Foundation + +// MARK: - LibraryWrapperGenerator + +/// Generator for SourceKitten's library wrappers. +enum LibraryWrapperGenerator: CaseIterable { + case clang + case sourcekit + + /// The relative file path for this library wrapper's generated source file. + var filePath: String { + return "Source/SourceKittenFramework/library_wrapper_\(moduleName).swift" + } + + /// Generate the Swift source code for this library wrapper. + /// + /// - parameter compilerArguments: The compiler arguments to SourceKittenFramework. + /// + /// - returns: The generated Swift source code for this library wrapper. + func generate(compilerArguments: [String]) throws -> String { + let freeFunctions = try extractFreeFunctions(compilerArguments: compilerArguments) + .joined(separator: "\n") + return [ + fileHeader, + "// swiftlint:disable unused_declaration - We don't care if some of these are unused.", + freeFunctions, + self == .clang ? "#endif" : nil + ] + .compactMap { $0 } + .joined(separator: "\n\n") + "\n" + } +} + +// MARK: - Private + +private extension LibraryWrapperGenerator { + /// The wrapped module name. + var moduleName: String { + switch self { + case .clang: + return "Clang_C" + case .sourcekit: + return "SourceKit" + } + } + + /// The top section of the generated library wrapper. + var fileHeader: String { + switch self { + case .clang: + return """ + #if !os(Linux) + + #if os(Windows) + import WinSDK + #else + import Darwin + #endif + + #if SWIFT_PACKAGE + import Clang_C + #endif + + #if os(Windows) + private let library = toolchainLoader.load(path: "libclang.dll") + #else + private let library = toolchainLoader.load(path: "libclang.dylib") + #endif + """ + case .sourcekit: + return """ + #if SWIFT_PACKAGE + import SourceKit + #endif + + #if os(Linux) + private let library = toolchainLoader.load(path: "libsourcekitdInProc.so") + #elseif os(Windows) + private let library = toolchainLoader.load(path: "sourcekitdInProc.dll") + #else + private let library = toolchainLoader.load(path: "sourcekitdInProc.framework/Versions/A/sourcekitdInProc") + #endif + """ + } + } + + func extractFreeFunctions(compilerArguments: [String]) throws -> [String] { + let sourceKitResponse = try interfaceForModule(moduleName, compilerArguments: compilerArguments) + let substructure = SwiftDocKey.getSubstructure(Structure(sourceKitResponse: sourceKitResponse).dictionary)! + let source = sourceKitResponse["key.sourcetext"] as! String + return source.extractFreeFunctions(inSubstructure: substructure) + } +} + +private func interfaceForModule(_ module: String, compilerArguments: [String]) throws -> [String: SourceKitRepresentable] { + return try Request.customRequest(request: [ + "key.request": UID("source.request.editor.open.interface"), + "key.name": UUID().uuidString, + "key.compilerargs": compilerArguments, + "key.modulename": module + ]).send() +} + +private extension String { + func nameFromFullFunctionName() -> String { + return String(self[.. [String] { + substructure + .filter { SwiftDeclarationKind(rawValue: SwiftDocKey.getKind($0)!) == .functionFree } + .compactMap { function -> String? in + let name = (function["key.name"] as! String).nameFromFullFunctionName() + let unsupportedFunctions = [ + "clang_executeOnThread", + "sourcekitd_variant_dictionary_apply", + "sourcekitd_variant_array_apply" + ] + guard !unsupportedFunctions.contains(name) else { + return nil + } + + let parameters = SwiftDocKey.getSubstructure(function)?.map { parameterStructure in + return parameterStructure["key.typename"] as! String + } ?? [] + var returnTypes = [String]() + if let offset = SwiftDocKey.getOffset(function), let length = SwiftDocKey.getLength(function) { + let stringView = StringView(self) + if let functionDeclaration = stringView.substringWithByteRange(ByteRange(location: offset, length: length)), + let startOfReturnArrow = functionDeclaration.range(of: "->", options: .backwards)?.lowerBound { + let adjustedDistance = distance(from: startIndex, to: startOfReturnArrow) + let adjustedReturnTypeStartIndex = functionDeclaration.index(functionDeclaration.startIndex, + offsetBy: adjustedDistance + 3) + returnTypes.append(String(functionDeclaration[adjustedReturnTypeStartIndex...])) + } + } + + let joinedParameters = parameters.map({ $0.replacingOccurrences(of: "!", with: "?") }).joined(separator: ", ") + let joinedReturnTypes = returnTypes.map({ $0.replacingOccurrences(of: "!", with: "?") }).joined(separator: ", ") + let lhs = "internal let \(name): @convention(c) (\(joinedParameters)) -> (\(joinedReturnTypes))" + let rhs = "library.load(symbol: \"\(name)\")" + return "\(lhs) = \(rhs)".replacingOccurrences(of: "SourceKittenFramework.", with: "") + } + } +} diff --git a/Source/SourceKittenFramework/Request.swift b/Source/SourceKittenFramework/Request.swift index 65e1aac7..506d1719 100644 --- a/Source/SourceKittenFramework/Request.swift +++ b/Source/SourceKittenFramework/Request.swift @@ -416,91 +416,3 @@ extension Request: CustomStringConvertible { /// A textual representation of `Request`. public var description: String { return sourcekitObject.description } } - -private func interfaceForModule(_ module: String, compilerArguments: [String]) throws -> [String: SourceKitRepresentable] { - return try Request.customRequest(request: [ - "key.request": UID("source.request.editor.open.interface"), - "key.name": NSUUID().uuidString, - "key.compilerargs": compilerArguments, - "key.modulename": module - ]).send() -} - -extension String { - private func nameFromFullFunctionName() -> String { - return String(self[.. [String] { - return substructure.filter({ - SwiftDeclarationKind(rawValue: SwiftDocKey.getKind($0)!) == .functionFree - }).compactMap { function -> String? in - let name = (function["key.name"] as! String).nameFromFullFunctionName() - let unsupportedFunctions = [ - "clang_executeOnThread", - "sourcekitd_variant_dictionary_apply", - "sourcekitd_variant_array_apply" - ] - guard !unsupportedFunctions.contains(name) else { - return nil - } - - let parameters = SwiftDocKey.getSubstructure(function)?.map { parameterStructure in - return parameterStructure["key.typename"] as! String - } ?? [] - var returnTypes = [String]() - if let offset = SwiftDocKey.getOffset(function), let length = SwiftDocKey.getLength(function) { - let stringView = StringView(self) - if let functionDeclaration = stringView.substringWithByteRange(ByteRange(location: offset, length: length)), - let startOfReturnArrow = functionDeclaration.range(of: "->", options: .backwards)?.lowerBound { - let adjustedDistance = distance(from: startIndex, to: startOfReturnArrow) - let adjustedReturnTypeStartIndex = functionDeclaration.index(functionDeclaration.startIndex, - offsetBy: adjustedDistance + 3) - returnTypes.append(String(functionDeclaration[adjustedReturnTypeStartIndex...])) - } - } - - let joinedParameters = parameters.map({ $0.replacingOccurrences(of: "!", with: "?") }).joined(separator: ", ") - let joinedReturnTypes = returnTypes.map({ $0.replacingOccurrences(of: "!", with: "?") }).joined(separator: ", ") - let lhs = "internal let \(name): @convention(c) (\(joinedParameters)) -> (\(joinedReturnTypes))" - let rhs = "library.load(symbol: \"\(name)\")" - return "\(lhs) = \(rhs)".replacingOccurrences(of: "SourceKittenFramework.", with: "") - } - } -} - -internal func libraryWrapperForModule(_ module: String, - macOSPath: String, - linuxPath: String?, - compilerArguments: [String]) throws -> String { - let sourceKitResponse = try interfaceForModule(module, compilerArguments: compilerArguments) - let substructure = SwiftDocKey.getSubstructure(Structure(sourceKitResponse: sourceKitResponse).dictionary)! - let source = sourceKitResponse["key.sourcetext"] as! String - let freeFunctions = source.extractFreeFunctions(inSubstructure: substructure) - let spmImport = "#if SWIFT_PACKAGE\nimport \(module)\n#endif\n" - let library: String - if let linuxPath = linuxPath { - library = """ - #if os(Linux) - private let path = "\(linuxPath)" - #else - private let path = "\(macOSPath)" - #endif - private let library = toolchainLoader.load(path: path) - - """ - } else { - library = "private let library = toolchainLoader.load(path: \"\(macOSPath)\")\n" - } - let swiftlintDisableComment = "// swiftlint:disable unused_declaration - We don't care if some of these are unused.\n" - let startPlatformCheck: String - let endPlatformCheck: String - if linuxPath == nil { - startPlatformCheck = "#if !os(Linux)\nimport Darwin\n" - endPlatformCheck = "\n#endif\n" - } else { - startPlatformCheck = "" - endPlatformCheck = "\n" - } - return startPlatformCheck + spmImport + library + swiftlintDisableComment + freeFunctions.joined(separator: "\n") + endPlatformCheck -} diff --git a/Source/SourceKittenFramework/library_wrapper_Clang_C.swift b/Source/SourceKittenFramework/library_wrapper_Clang_C.swift index bfe42c91..47161e11 100644 --- a/Source/SourceKittenFramework/library_wrapper_Clang_C.swift +++ b/Source/SourceKittenFramework/library_wrapper_Clang_C.swift @@ -17,6 +17,7 @@ private let library = toolchainLoader.load(path: "libclang.dylib") #endif // swiftlint:disable unused_declaration - We don't care if some of these are unused. + internal let clang_getCString: @convention(c) (CXString) -> (UnsafePointer?) = library.load(symbol: "clang_getCString") internal let clang_disposeString: @convention(c) (CXString) -> () = library.load(symbol: "clang_disposeString") internal let clang_disposeStringSet: @convention(c) (UnsafeMutablePointer?) -> () = library.load(symbol: "clang_disposeStringSet") @@ -398,4 +399,5 @@ internal let clang_VerbatimLineComment_getText: @convention(c) (CXComment) -> (C internal let clang_HTMLTagComment_getAsString: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_HTMLTagComment_getAsString") internal let clang_FullComment_getAsHTML: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_FullComment_getAsHTML") internal let clang_FullComment_getAsXML: @convention(c) (CXComment) -> (CXString) = library.load(symbol: "clang_FullComment_getAsXML") + #endif diff --git a/Source/SourceKittenFramework/library_wrapper_SourceKit.swift b/Source/SourceKittenFramework/library_wrapper_SourceKit.swift index c72b1293..3df27d1e 100644 --- a/Source/SourceKittenFramework/library_wrapper_SourceKit.swift +++ b/Source/SourceKittenFramework/library_wrapper_SourceKit.swift @@ -3,15 +3,15 @@ import SourceKit #endif #if os(Linux) -private let path = "libsourcekitdInProc.so" +private let library = toolchainLoader.load(path: "libsourcekitdInProc.so") #elseif os(Windows) -private let path = "sourcekitdInProc.dll" +private let library = toolchainLoader.load(path: "sourcekitdInProc.dll") #else -private let path = "sourcekitdInProc.framework/Versions/A/sourcekitdInProc" +private let library = toolchainLoader.load(path: "sourcekitdInProc.framework/Versions/A/sourcekitdInProc") #endif -private let library = toolchainLoader.load(path: path) // swiftlint:disable unused_declaration - We don't care if some of these are unused. + internal let sourcekitd_initialize: @convention(c) () -> () = library.load(symbol: "sourcekitd_initialize") internal let sourcekitd_shutdown: @convention(c) () -> () = library.load(symbol: "sourcekitd_shutdown") internal let sourcekitd_set_interrupted_connection_handler: @convention(c) (@escaping sourcekitd_interrupted_connection_handler_t) -> () = library.load(symbol: "sourcekitd_set_interrupted_connection_handler") diff --git a/Tests/SourceKittenFrameworkTests/LibraryWrapperGeneratorTests.swift b/Tests/SourceKittenFrameworkTests/LibraryWrapperGeneratorTests.swift new file mode 100644 index 00000000..cbcc0afb --- /dev/null +++ b/Tests/SourceKittenFrameworkTests/LibraryWrapperGeneratorTests.swift @@ -0,0 +1,25 @@ +@testable import SourceKittenFramework +import XCTest + +final class LibraryWrapperGeneratorTests: XCTestCase { +#if compiler(>=5.4) && os(macOS) + func testLibraryWrappersAreUpToDate() throws { + let sourceKittenFrameworkModule = Module(xcodeBuildArguments: sourcekittenXcodebuildArguments, + name: "SourceKittenFramework", inPath: projectRoot)! + let docsJSON = sourceKittenFrameworkModule.docs.description + XCTAssert(docsJSON.range(of: "error type") == nil) + let jsonArray = try JSONSerialization.jsonObject(with: docsJSON.data(using: .utf8)!, options: []) as? NSArray + XCTAssertNotNil(jsonArray, "JSON should be properly parsed") + for wrapperConfig in LibraryWrapperGenerator.allCases { + let wrapperURL = URL(fileURLWithPath: "\(projectRoot)/\(wrapperConfig.filePath)") + let existingWrapper = try String(contentsOf: wrapperURL) + let generatedWrapper = try wrapperConfig.generate(compilerArguments: sourceKittenFrameworkModule.compilerArguments) + XCTAssertEqual(existingWrapper, generatedWrapper) + let overwrite = false // set this to true to overwrite existing wrappers with the generated ones + if existingWrapper != generatedWrapper && overwrite { + try generatedWrapper.data(using: .utf8)?.write(to: wrapperURL) + } + } + } +#endif +} diff --git a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift index d86ddeb8..befa01e5 100644 --- a/Tests/SourceKittenFrameworkTests/SourceKitTests.swift +++ b/Tests/SourceKittenFrameworkTests/SourceKitTests.swift @@ -230,35 +230,6 @@ class SourceKitTests: XCTestCase { } } - func testLibraryWrappersAreUpToDate() throws { -#if compiler(>=5.4) && os(macOS) - let sourceKittenFrameworkModule = Module(xcodeBuildArguments: sourcekittenXcodebuildArguments, - name: "SourceKittenFramework", inPath: projectRoot)! - let docsJSON = sourceKittenFrameworkModule.docs.description - XCTAssert(docsJSON.range(of: "error type") == nil) - let jsonArray = try JSONSerialization.jsonObject(with: docsJSON.data(using: .utf8)!, options: []) as? NSArray - XCTAssertNotNil(jsonArray, "JSON should be properly parsed") - let sourcekitd = "sourcekitdInProc.framework/Versions/A/sourcekitdInProc" - let modules: [(module: String, macOSPath: String, linuxPath: String?)] = [ - ("Clang_C", "libclang.dylib", nil), - ("SourceKit", sourcekitd, "libsourcekitdInProc.so") - ] - for (module, inProcPath, linuxPath) in modules { - let wrapperPath = "\(projectRoot)/Source/SourceKittenFramework/library_wrapper_\(module).swift" - let existingWrapper = try String(contentsOfFile: wrapperPath) - let generatedWrapper = try libraryWrapperForModule( - module, macOSPath: inProcPath, linuxPath: linuxPath, - compilerArguments: sourceKittenFrameworkModule.compilerArguments - ) - XCTAssertEqual(existingWrapper, generatedWrapper) - let overwrite = false // set this to true to overwrite existing wrappers with the generated ones - if existingWrapper != generatedWrapper && overwrite { - try generatedWrapper.data(using: .utf8)?.write(to: URL(fileURLWithPath: wrapperPath)) - } - } -#endif - } - func testIndex() throws { let file = "\(fixturesDirectory)Bicycle.swift" let arguments = ["-sdk", sdkPath(), "-j4", file ]