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/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) } } diff --git a/Source/SourceKittenFramework/SwiftDocs.swift b/Source/SourceKittenFramework/SwiftDocs.swift index 0d368d75..c57fda44 100644 --- a/Source/SourceKittenFramework/SwiftDocs.swift +++ b/Source/SourceKittenFramework/SwiftDocs.swift @@ -1,9 +1,13 @@ +import Foundation + #if SWIFT_PACKAGE import SourceKit #endif #if os(Linux) import Glibc +#elseif os(Windows) +import CRT #else import Darwin #endif @@ -68,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])) } } 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 diff --git a/Source/SourceKittenFramework/library_wrapper_Clang_C.swift b/Source/SourceKittenFramework/library_wrapper_Clang_C.swift index 03ac43e0..47161e11 100644 --- a/Source/SourceKittenFramework/library_wrapper_Clang_C.swift +++ b/Source/SourceKittenFramework/library_wrapper_Clang_C.swift @@ -1,10 +1,23 @@ #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") internal let clang_disposeStringSet: @convention(c) (UnsafeMutablePointer?) -> () = library.load(symbol: "clang_disposeStringSet") @@ -386,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 28e038a9..3df27d1e 100644 --- a/Source/SourceKittenFramework/library_wrapper_SourceKit.swift +++ b/Source/SourceKittenFramework/library_wrapper_SourceKit.swift @@ -1,13 +1,17 @@ #if SWIFT_PACKAGE import SourceKit #endif + #if os(Linux) -private let path = "libsourcekitdInProc.so" +private let library = toolchainLoader.load(path: "libsourcekitdInProc.so") +#elseif os(Windows) +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/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 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, 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/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) } 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 67080bf7..befa01e5 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 = [ @@ -35,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) }) @@ -228,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 ] @@ -284,7 +257,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 +269,7 @@ class SourceKitTests: XCTestCase { compareJSONString(withFixtureNamed: "BicycleSyntax", jsonString: syntaxJSON) } +#endif func testCompilerVersion() { XCTAssertTrue(SwiftVersion.current >= SwiftVersion.fiveDotOne) diff --git a/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift b/Tests/SourceKittenFrameworkTests/SwiftDocsTests.swift index f6cf043a..40ce6266 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"] @@ -76,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