diff --git a/CHANGELOG.md b/CHANGELOG.md index 204f80651..86a440958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,18 @@ ##### Breaking -* None. +* Change type of parameter from `sourcekitd_object_t` to `SourceKitObject?`. + - `File.process(dictionary:cursorInfoRequest:syntaxMap:)` + - `Request.customRequest(request:)` + - `SwiftDocs.init(file:dictionary:cursorInfoRequest:)` + [Norio Nomura](https://github.com/norio-nomura) ##### Enhancements +* Add `SourceKitObject` that represents `sourcekitd_object_t` in Swift. + [Norio Nomura](https://github.com/norio-nomura) + [#489](https://github.com/jpsim/SourceKitten/issues/489) + * Replaced linear index search with binary search in NSString extension. [Tamas Lustyik](https://github.com/lvsti) diff --git a/Source/SourceKittenFramework/File.swift b/Source/SourceKittenFramework/File.swift index 242cabe0f..8f821adfd 100644 --- a/Source/SourceKittenFramework/File.swift +++ b/Source/SourceKittenFramework/File.swift @@ -191,7 +191,7 @@ public final class File { - parameter dictionary: Dictionary to process. - parameter cursorInfoRequest: Cursor.Info request to get declaration information. */ - public func process(dictionary: [String: SourceKitRepresentable], cursorInfoRequest: sourcekitd_object_t? = nil, + public func process(dictionary: [String: SourceKitRepresentable], cursorInfoRequest: SourceKitObject? = nil, syntaxMap: SyntaxMap? = nil) -> [String: SourceKitRepresentable] { var dictionary = dictionary if let cursorInfoRequest = cursorInfoRequest { @@ -233,7 +233,7 @@ public final class File { - parameter cursorInfoRequest: Cursor.Info request to get declaration information. */ internal func furtherProcess(dictionary: [String: SourceKitRepresentable], documentedTokenOffsets: [Int], - cursorInfoRequest: sourcekitd_object_t, + cursorInfoRequest: SourceKitObject, syntaxMap: SyntaxMap) -> [String: SourceKitRepresentable] { var dictionary = dictionary let offsetMap = makeOffsetMap(documentedTokenOffsets: documentedTokenOffsets, dictionary: dictionary) @@ -261,7 +261,7 @@ public final class File { `processDictionary(_:cursorInfoRequest:syntaxMap:)` on its elements, only keeping comment marks and declarations. */ - private func newSubstructure(_ dictionary: [String: SourceKitRepresentable], cursorInfoRequest: sourcekitd_object_t?, + private func newSubstructure(_ dictionary: [String: SourceKitRepresentable], cursorInfoRequest: SourceKitObject?, syntaxMap: SyntaxMap?) -> [SourceKitRepresentable]? { return SwiftDocKey.getSubstructure(dictionary)? .filter(isDeclarationOrCommentMark) @@ -277,7 +277,7 @@ public final class File { - parameter cursorInfoRequest: Cursor.Info request to get declaration information. */ private func dictWithCommentMarkNamesCursorInfo(_ dictionary: [String: SourceKitRepresentable], - cursorInfoRequest: sourcekitd_object_t) -> [String: SourceKitRepresentable]? { + cursorInfoRequest: SourceKitObject) -> [String: SourceKitRepresentable]? { guard let kind = SwiftDocKey.getKind(dictionary) else { return nil } diff --git a/Source/SourceKittenFramework/Request.swift b/Source/SourceKittenFramework/Request.swift index 53ccc821a..72aaf41b6 100644 --- a/Source/SourceKittenFramework/Request.swift +++ b/Source/SourceKittenFramework/Request.swift @@ -195,8 +195,8 @@ public enum Request { case editorOpen(file: File) /// A `cursorinfo` request for an offset in the given file, using the `arguments` given. case cursorInfo(file: String, offset: Int64, arguments: [String]) - /// A custom request by passing in the sourcekitd_object_t directly. - case customRequest(request: sourcekitd_object_t) + /// A custom request by passing in the `SourceKitObject` directly. + case customRequest(request: SourceKitObject) /// A request generated by sourcekit using the yaml representation. case yamlRequest(yaml: String) /// A `codecomplete` request by passing in the file name, contents, offset @@ -217,45 +217,42 @@ public enum Request { /// A documentation request for the given module. case moduleInfo(module: String, arguments: [String]) - fileprivate var sourcekitObject: sourcekitd_object_t { - let dict: [sourcekitd_uid_t: sourcekitd_object_t?] + fileprivate var sourcekitObject: SourceKitObject { switch self { case .editorOpen(let file): if let path = file.path { - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.open")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(path), - sourcekitd_uid_get_from_cstr("key.sourcefile")!: sourcekitd_request_string_create(path) + return [ + "key.request": UID("source.request.editor.open"), + "key.name": path, + "key.sourcefile": path ] } else { - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.open")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(String(file.contents.hash)), - sourcekitd_uid_get_from_cstr("key.sourcetext")!: sourcekitd_request_string_create(file.contents) + return [ + "key.request": UID("source.request.editor.open"), + "key.name": String(file.contents.hash), + "key.sourcetext": file.contents ] } case .cursorInfo(let file, let offset, let arguments): - var compilerargs = arguments.map({ sourcekitd_request_string_create($0) }) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.cursorinfo")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.sourcefile")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.offset")!: sourcekitd_request_int64_create(offset), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count) + return [ + "key.request": UID("source.request.cursorinfo"), + "key.name": file, + "key.sourcefile": file, + "key.offset": offset, + "key.compilerargs": arguments ] case .customRequest(let request): return request case .yamlRequest(let yaml): - return sourcekitd_request_create_from_yaml(yaml, nil)! + return .init(sourcekitd_request_create_from_yaml(yaml, nil)!) case .codeCompletionRequest(let file, let contents, let offset, let arguments): - var compilerargs = arguments.map({ sourcekitd_request_string_create($0) }) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.codecomplete")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.sourcefile")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.sourcetext")!: sourcekitd_request_string_create(contents), - sourcekitd_uid_get_from_cstr("key.offset")!: sourcekitd_request_int64_create(offset), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count) + return [ + "key.request": UID("source.request.codecomplete"), + "key.name": file, + "key.sourcefile": file, + "key.sourcetext": contents, + "key.offset": offset, + "key.compilerargs": arguments ] case .interface(let file, let uuid, var arguments): if !arguments.contains("-x") { @@ -264,70 +261,58 @@ public enum Request { if !arguments.contains("-isysroot") { arguments.append(contentsOf: ["-isysroot", sdkPath()]) } - var compilerargs = ([file] + arguments).map({ sourcekitd_request_string_create($0) }) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: - sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.open.interface.header")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(uuid), - sourcekitd_uid_get_from_cstr("key.filepath")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count) + return [ + "key.request": UID("source.request.editor.open.interface.header"), + "key.name": uuid, + "key.filepath": file, + "key.compilerargs": [file] + arguments ] case .findUSR(let file, let usr): - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.find_usr")!), - sourcekitd_uid_get_from_cstr("key.usr")!: sourcekitd_request_string_create(usr), - sourcekitd_uid_get_from_cstr("key.sourcefile")!: sourcekitd_request_string_create(file) + return [ + "key.request": UID("source.request.editor.find_usr"), + "key.usr": usr, + "key.sourcefile": file ] case .index(let file, let arguments): - var compilerargs = arguments.map({ sourcekitd_request_string_create($0) }) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.indexsource")!), - sourcekitd_uid_get_from_cstr("key.sourcefile")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count) + return [ + "key.request": UID("source.request.indexsource"), + "key.sourcefile": file, + "key.compilerargs": arguments ] case .format(let file, let line, let useTabs, let indentWidth): - let formatOptions = [ - sourcekitd_uid_get_from_cstr("key.editor.format.indentwidth")!: sourcekitd_request_int64_create(indentWidth), - sourcekitd_uid_get_from_cstr("key.editor.format.tabwidth")!: sourcekitd_request_int64_create(indentWidth), - sourcekitd_uid_get_from_cstr("key.editor.format.usetabs")!: sourcekitd_request_int64_create(useTabs ? 1 : 0) - ] - var formatOptionsKeys = Array(formatOptions.keys.map({ $0 as sourcekitd_uid_t? })) - var formatOptionsValues = Array(formatOptions.values) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.formattext")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.line")!: sourcekitd_request_int64_create(line), - sourcekitd_uid_get_from_cstr("key.editor.format.options")!: - sourcekitd_request_dictionary_create(&formatOptionsKeys, &formatOptionsValues, formatOptions.count) + return [ + "key.request": UID("source.request.editor.formattext"), + "key.name": file, + "key.line": line, + "key.editor.format.options": [ + "key.editor.format.indentwidth": indentWidth, + "key.editor.format.tabwidth": indentWidth, + "key.editor.format.usetabs": useTabs ? 1 : 0 + ] ] case .replaceText(let file, let offset, let length, let sourceText): - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.replacetext")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(file), - sourcekitd_uid_get_from_cstr("key.offset")!: sourcekitd_request_int64_create(offset), - sourcekitd_uid_get_from_cstr("key.length")!: sourcekitd_request_int64_create(length), - sourcekitd_uid_get_from_cstr("key.sourcetext")!: sourcekitd_request_string_create(sourceText) + return [ + "key.request": UID("source.request.editor.replacetext"), + "key.name": file, + "key.offset": offset, + "key.length": length, + "key.sourcetext": sourceText ] case .docInfo(let text, let arguments): - var compilerargs = arguments.map({ sourcekitd_request_string_create($0) }) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.docinfo")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(NSUUID().uuidString), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count), - sourcekitd_uid_get_from_cstr("key.sourcetext")!: sourcekitd_request_string_create(text) + return [ + "key.request": UID("source.request.docinfo"), + "key.name": NSUUID().uuidString, + "key.compilerargs": arguments, + "key.sourcetext": text ] case .moduleInfo(let module, let arguments): - var compilerargs = arguments.map({ sourcekitd_request_string_create($0) }) - dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.docinfo")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(NSUUID().uuidString), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count), - sourcekitd_uid_get_from_cstr("key.modulename")!: sourcekitd_request_string_create(module) + return [ + "key.request": UID("source.request.docinfo"), + "key.name": NSUUID().uuidString, + "key.compilerargs": arguments, + "key.modulename": module ] } - var keys = Array(dict.keys.map({ $0 as sourcekitd_uid_t? })) - var values = Array(dict.values) - return sourcekitd_request_dictionary_create(&keys, &values, dict.count)! } /** @@ -338,7 +323,7 @@ public enum Request { - returns: sourcekitd_object_t representation of the Request, if successful. */ - internal static func cursorInfoRequest(filePath: String?, arguments: [String]) -> sourcekitd_object_t? { + internal static func cursorInfoRequest(filePath: String?, arguments: [String]) -> SourceKitObject? { if let path = filePath { return Request.cursorInfo(file: path, offset: 0, arguments: arguments).sourcekitObject } @@ -353,11 +338,11 @@ public enum Request { - returns: SourceKit response if successful. */ - internal static func send(cursorInfoRequest: sourcekitd_object_t, atOffset offset: Int64) -> [String: SourceKitRepresentable]? { + internal static func send(cursorInfoRequest: SourceKitObject, atOffset offset: Int64) -> [String: SourceKitRepresentable]? { if offset == 0 { return nil } - sourcekitd_request_dictionary_set_int64(cursorInfoRequest, sourcekitd_uid_get_from_cstr(SwiftDocKey.offset.rawValue)!, offset) + cursorInfoRequest.updateValue(offset, forKey: SwiftDocKey.offset) return try? Request.customRequest(request: cursorInfoRequest).send() } @@ -369,7 +354,7 @@ public enum Request { */ public func send() throws -> [String: SourceKitRepresentable] { initializeSourceKitFailable - let response = sourcekitd_send_request_sync(sourcekitObject) + let response = sourcekitd_send_request_sync(sourcekitObject.sourcekitdObject!) defer { sourcekitd_response_dispose(response!) } if sourcekitd_response_is_error(response!) { let error = Request.Error(response: response!) @@ -432,20 +417,16 @@ public enum Request { extension Request: CustomStringConvertible { /// A textual representation of `Request`. - public var description: String { return String(validatingUTF8: sourcekitd_request_description_copy(sourcekitObject)!)! } + public var description: String { return sourcekitObject.description } } private func interfaceForModule(_ module: String, compilerArguments: [String]) throws -> [String: SourceKitRepresentable] { - var compilerargs = compilerArguments.map { sourcekitd_request_string_create($0) } - let dict = [ - sourcekitd_uid_get_from_cstr("key.request")!: sourcekitd_request_uid_create(sourcekitd_uid_get_from_cstr("source.request.editor.open.interface")!), - sourcekitd_uid_get_from_cstr("key.name")!: sourcekitd_request_string_create(NSUUID().uuidString), - sourcekitd_uid_get_from_cstr("key.compilerargs")!: sourcekitd_request_array_create(&compilerargs, compilerargs.count), - sourcekitd_uid_get_from_cstr("key.modulename")!: sourcekitd_request_string_create("SourceKittenFramework.\(module)") - ] - var keys = Array(dict.keys.map({ $0 as sourcekitd_uid_t? })) - var values = Array(dict.values) - return try Request.customRequest(request: sourcekitd_request_dictionary_create(&keys, &values, dict.count)!).send() + return try Request.customRequest(request: [ + "key.request": UID("source.request.editor.open.interface"), + "key.name": NSUUID().uuidString, + "key.compilerargs": compilerArguments, + "key.modulename": "SourceKittenFramework.\(module)" + ]).send() } extension String { diff --git a/Source/SourceKittenFramework/SourceKitObject.swift b/Source/SourceKittenFramework/SourceKitObject.swift new file mode 100644 index 000000000..b3ea7e9f4 --- /dev/null +++ b/Source/SourceKittenFramework/SourceKitObject.swift @@ -0,0 +1,133 @@ +// +// SourceKitObject.swift +// SourceKitten +// +// Created by Norio Nomura on 2/7/18. +// Copyright © 2018 SourceKitten. All rights reserved. +// + +import Foundation +#if SWIFT_PACKAGE +import SourceKit +#endif + +// MARK: - SourceKitObjectConvertible + +public protocol SourceKitObjectConvertible { + var sourcekitdObject: sourcekitd_object_t? { get } +} + +extension Array: SourceKitObjectConvertible { + public var sourcekitdObject: sourcekitd_object_t? { + guard Element.self is SourceKitObjectConvertible.Type else { + fatalError("Array conforms to SourceKitObjectConvertible when Elements is SourceKitObjectConvertible!") + } + let objects: [sourcekitd_object_t?] = map { ($0 as! SourceKitObjectConvertible).sourcekitdObject } + return sourcekitd_request_array_create(objects, objects.count) + } +} + +extension Dictionary: SourceKitObjectConvertible { + public var sourcekitdObject: sourcekitd_object_t? { + let keys: [sourcekitd_uid_t?] + if Key.self is UID.Type { + keys = self.keys.map { ($0 as! UID).uid } + } else if Key.self is String.Type { + keys = self.keys.map { UID($0 as! String).uid } + } else { + fatalError("Dictionary conforms to SourceKitObjectConvertible when `Key` is `UID` or `String`!") + } + guard Value.self is SourceKitObjectConvertible.Type else { + fatalError("Dictionary conforms to SourceKitObjectConvertible when `Value` is `SourceKitObjectConvertible`!") + } + let values: [sourcekitd_object_t?] = self.map { ($0.value as! SourceKitObjectConvertible).sourcekitdObject } + return sourcekitd_request_dictionary_create(keys, values, count) + } +} + +extension Int: SourceKitObjectConvertible { + public var sourcekitdObject: sourcekitd_object_t? { + return sourcekitd_request_int64_create(Int64(self)) + } +} + +extension Int64: SourceKitObjectConvertible { + public var sourcekitdObject: sourcekitd_object_t? { + return sourcekitd_request_int64_create(self) + } +} + +extension String: SourceKitObjectConvertible { + public var sourcekitdObject: sourcekitd_object_t? { + return sourcekitd_request_string_create(self) + } +} + +// MARK: - SourceKitObject + +/// Swift representation of sourcekitd_object_t +public struct SourceKitObject { + public let sourcekitdObject: sourcekitd_object_t? + + public init(_ sourcekitdObject: sourcekitd_object_t) { + self.sourcekitdObject = sourcekitdObject + } + + /// Updates the value stored in the dictionary for the given key, + /// or adds a new key-value pair if the key does not exist. + /// + /// - Parameters: + /// - value: The new value to add to the dictionary. + /// - key: The key to associate with value. If key already exists in the dictionary, + /// value replaces the existing associated value. If key isn't already a key of the dictionary + public func updateValue(_ value: SourceKitObjectConvertible, forKey key: UID) { + precondition(sourcekitdObject != nil) + precondition(value.sourcekitdObject != nil) + sourcekitd_request_dictionary_set_value(sourcekitdObject!, key.uid, value.sourcekitdObject!) + } + + public func updateValue(_ value: SourceKitObjectConvertible, forKey key: String) { + updateValue(value, forKey: UID(key)) + } + + public func updateValue(_ value: SourceKitObjectConvertible, forKey key: T) where T: RawRepresentable, T.RawValue == String { + updateValue(value, forKey: UID(key.rawValue)) + } +} + +extension SourceKitObject: SourceKitObjectConvertible {} + +extension SourceKitObject: CustomStringConvertible { + public var description: String { + guard let object = sourcekitdObject else { return "" } + let bytes = sourcekitd_request_description_copy(object)! + let length = Int(strlen(bytes)) + return String(bytesNoCopy: bytes, length: length, encoding: .utf8, freeWhenDone: true)! + } +} + +extension SourceKitObject: ExpressibleByArrayLiteral { + public init(arrayLiteral elements: SourceKitObject...) { + sourcekitdObject = elements.sourcekitdObject + } +} + +extension SourceKitObject: ExpressibleByDictionaryLiteral { + public init(dictionaryLiteral elements: (UID, SourceKitObjectConvertible)...) { + let keys: [sourcekitd_uid_t?] = elements.map { $0.0.uid } + let values: [sourcekitd_object_t?] = elements.map { $0.1.sourcekitdObject } + sourcekitdObject = sourcekitd_request_dictionary_create(keys, values, elements.count) + } +} + +extension SourceKitObject: ExpressibleByIntegerLiteral { + public init(integerLiteral value: IntegerLiteralType) { + sourcekitdObject = value.sourcekitdObject + } +} + +extension SourceKitObject: ExpressibleByStringLiteral { + public init(stringLiteral value: StringLiteralType) { + sourcekitdObject = value.sourcekitdObject + } +} diff --git a/Source/SourceKittenFramework/SwiftDocs.swift b/Source/SourceKittenFramework/SwiftDocs.swift index 87afc45a0..fbc736c14 100644 --- a/Source/SourceKittenFramework/SwiftDocs.swift +++ b/Source/SourceKittenFramework/SwiftDocs.swift @@ -47,7 +47,7 @@ public struct SwiftDocs { - parameter dictionary: editor.open response from SourceKit. - parameter cursorInfoRequest: SourceKit dictionary to use to send cursorinfo request. */ - public init(file: File, dictionary: [String: SourceKitRepresentable], cursorInfoRequest: sourcekitd_object_t?) { + public init(file: File, dictionary: [String: SourceKitRepresentable], cursorInfoRequest: SourceKitObject?) { self.file = file var dictionary = dictionary let syntaxMapData = dictionary.removeValue(forKey: SwiftDocKey.syntaxMap.rawValue) as! [SourceKitRepresentable] diff --git a/Source/SourceKittenFramework/UID.swift b/Source/SourceKittenFramework/UID.swift new file mode 100644 index 000000000..4aeb288b2 --- /dev/null +++ b/Source/SourceKittenFramework/UID.swift @@ -0,0 +1,60 @@ +// +// UID.swift +// SourceKitten +// +// Created by Norio Nomura on 2/07/18. +// Copyright © 2018 SourceKitten. All rights reserved. +// + +import Foundation +#if SWIFT_PACKAGE +import SourceKit +#endif + +/// Swift representation of sourcekitd_uid_t +public struct UID { + let uid: sourcekitd_uid_t + init(_ uid: sourcekitd_uid_t) { + self.uid = uid + } + + public init(_ string: String) { + self.init(sourcekitd_uid_get_from_cstr(string)!) + } + + public init(_ rawRepresentable: T) where T: RawRepresentable, T.RawValue == String { + self.init(rawRepresentable.rawValue) + } + + var string: String { + return String(cString: sourcekitd_uid_get_string_ptr(uid)!) + } +} + +extension UID: CustomStringConvertible { + public var description: String { + return string + } +} + +extension UID: ExpressibleByStringLiteral { + public init(stringLiteral value: String) { + self.init(value) + } +} + +extension UID: Hashable { + public var hashValue: Int { + return uid.hashValue + } + + public static func == (lhs: UID, rhs: UID) -> Bool { + return lhs.uid == rhs.uid + } +} + +extension UID: SourceKitObjectConvertible { + public var sourcekitdObject: sourcekitd_object_t? { + return sourcekitd_request_uid_create(uid) + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 7e18fd776..24c35c3cb 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -8,6 +8,7 @@ XCTMain([ testCase(FileTests.allTests), testCase(ModuleTests.allTests), testCase(OffsetMapTests.allTests), + testCase(SourceKitObjectTests.allTests), testCase(SourceKitTests.allTests), testCase(StringTests.allTests), testCase(StructureTests.allTests), diff --git a/Tests/SourceKittenFrameworkTests/SourceKitObjectTests.swift b/Tests/SourceKittenFrameworkTests/SourceKitObjectTests.swift new file mode 100644 index 000000000..4687e705d --- /dev/null +++ b/Tests/SourceKittenFrameworkTests/SourceKitObjectTests.swift @@ -0,0 +1,38 @@ +// +// SourceKitObjectTests.swift +// SourceKitten +// +// Created by Norio Nomura on 2/7/18. +// Copyright © 2018 SourceKitten. All rights reserved. +// + +import SourceKittenFramework +import XCTest + +class SourceKitObjectTests: XCTestCase { + + func testExample() { + let path = #file + let object: SourceKitObject = [ + "key.request": UID("source.request.editor.open"), + "key.name": path, + "key.sourcefile": path + ] + let expected = """ + { + key.request: source.request.editor.open, + key.name: \"\(#file)\", + key.sourcefile: \"\(#file)\" + } + """ + XCTAssertEqual(object.description, expected) + } +} + +extension SourceKitObjectTests { + static var allTests: [(String, (SourceKitObjectTests) -> () throws -> Void)] { + return [ + ("testExample", testExample) + ] + } +} diff --git a/sourcekitten.xcodeproj/project.pbxproj b/sourcekitten.xcodeproj/project.pbxproj index faa903140..f1eed515b 100644 --- a/sourcekitten.xcodeproj/project.pbxproj +++ b/sourcekitten.xcodeproj/project.pbxproj @@ -18,6 +18,9 @@ 6C4CF6521C798082008532C5 /* library_wrapper_CXString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4CF6481C79802A008532C5 /* library_wrapper_CXString.swift */; }; 6C4CF6551C798086008532C5 /* library_wrapper_Documentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4CF6491C79802A008532C5 /* library_wrapper_Documentation.swift */; }; 6C4CF6581C79808C008532C5 /* library_wrapper_Index.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4CF6471C79802A008532C5 /* library_wrapper_Index.swift */; }; + 6CB68C23202AC40B00D82E91 /* SourceKitObjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CB68C22202AC40B00D82E91 /* SourceKitObjectTests.swift */; }; + 6CC1639C202AA3AF0086C459 /* SourceKitObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1639A202AA3AE0086C459 /* SourceKitObject.swift */; }; + 6CC1639D202AA3AF0086C459 /* UID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC1639B202AA3AE0086C459 /* UID.swift */; }; 6CC381641ECACB6F000C6F81 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC381621ECACB50000C6F81 /* Version.swift */; }; 6CCFCE891CFECFED003239EB /* SWXMLHash.framework in Embed Frameworks into SourceKittenFramework.framework */ = {isa = PBXBuildFile; fileRef = E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6CCFCE8C1CFECFF1003239EB /* Yams.framework in Embed Frameworks into SourceKittenFramework.framework */ = {isa = PBXBuildFile; fileRef = E80678041CF2749300AFC816 /* Yams.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -143,6 +146,9 @@ 6C4CF6481C79802A008532C5 /* library_wrapper_CXString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = library_wrapper_CXString.swift; sourceTree = ""; }; 6C4CF6491C79802A008532C5 /* library_wrapper_Documentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = library_wrapper_Documentation.swift; sourceTree = ""; }; 6C7F0A841EDB0AAD008EC581 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; + 6CB68C22202AC40B00D82E91 /* SourceKitObjectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceKitObjectTests.swift; sourceTree = ""; }; + 6CC1639A202AA3AE0086C459 /* SourceKitObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceKitObject.swift; sourceTree = ""; }; + 6CC1639B202AA3AE0086C459 /* UID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UID.swift; sourceTree = ""; }; 6CC381621ECACB50000C6F81 /* Version.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = ""; }; 6CFC18F01C7F2FB900CD70E1 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; B2FA804AA9D4427FF571EFB2 /* SwiftLangSyntax.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLangSyntax.swift; sourceTree = ""; }; @@ -408,6 +414,7 @@ E806D2901BE058C400D1BE41 /* Parameter.swift */, E86847391A587B4D0043DC65 /* Request.swift */, E8A9B8911B56D1B100CD17D4 /* SourceDeclaration.swift */, + 6CC1639A202AA3AE0086C459 /* SourceKitObject.swift */, D0D1217119E87B05005E4BAA /* SourceKittenFramework.h */, E806D28C1BE0589B00D1BE41 /* SourceLocation.swift */, E8AE53C61A5B5FCA0092D24A /* String+SourceKitten.swift */, @@ -420,6 +427,7 @@ E8CC8A2C1A587FD300D1FEC7 /* SyntaxMap.swift */, E80F236A1A5CB04100FD2352 /* SyntaxToken.swift */, E806D28E1BE058B100D1BE41 /* Text.swift */, + 6CC1639B202AA3AE0086C459 /* UID.swift */, 6CC381621ECACB50000C6F81 /* Version.swift */, E8A9B88F1B56CB5500CD17D4 /* Xcode.swift */, B2FA804AA9D4427FF571EFB2 /* SwiftLangSyntax.swift */, @@ -451,6 +459,7 @@ E805A0491B560FCA00EA654A /* FileTests.swift */, E8241CA21A5E01840047687E /* ModuleTests.swift */, E8C9EA091A5C9A2900A6D4D1 /* OffsetMapTests.swift */, + 6CB68C22202AC40B00D82E91 /* SourceKitObjectTests.swift */, E805A0471B55CBAF00EA654A /* SourceKitTests.swift */, E8C9EA071A5C99C400A6D4D1 /* StringTests.swift */, E8C9EA031A5C986A00A6D4D1 /* StructureTests.swift */, @@ -661,6 +670,7 @@ files = ( E82882541DAEEDD1002E0564 /* LinuxCompatibility.swift in Sources */, E806D2931BE058D600D1BE41 /* Documentation.swift in Sources */, + 6CC1639D202AA3AF0086C459 /* UID.swift in Sources */, 3F0CBB411BAAFF160015BBA8 /* Clang+SourceKitten.swift in Sources */, 2E8FF7101C6268C100F280F0 /* StatementKind.swift in Sources */, 6C4CF6551C798086008532C5 /* library_wrapper_Documentation.swift in Sources */, @@ -673,6 +683,7 @@ 3F56EAD01BAB251C006433D0 /* JSONOutput.swift in Sources */, E8A18A3B1A58971D000362B7 /* Language.swift in Sources */, E806D28F1BE058B100D1BE41 /* Text.swift in Sources */, + 6CC1639C202AA3AF0086C459 /* SourceKitObject.swift in Sources */, E8241CA51A5E01A10047687E /* Module.swift in Sources */, E877D9271B5693E70095BB2B /* ObjCDeclarationKind.swift in Sources */, 6C4CF6521C798082008532C5 /* library_wrapper_CXString.swift in Sources */, @@ -704,6 +715,7 @@ E845EFEC1B9941AA00CFA57B /* CodeCompletionTests.swift in Sources */, E805A04A1B560FCA00EA654A /* FileTests.swift in Sources */, E8241CA31A5E01840047687E /* ModuleTests.swift in Sources */, + 6CB68C23202AC40B00D82E91 /* SourceKitObjectTests.swift in Sources */, 3DEF4C591DBF9C2D00B3B54A /* DocInfoTests.swift in Sources */, E8C9EA0A1A5C9A2900A6D4D1 /* OffsetMapTests.swift in Sources */, E805A0481B55CBAF00EA654A /* SourceKitTests.swift in Sources */,