Skip to content

Add SourceKitObject that represents sourcekitd_object_t in Swift #490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
8 changes: 4 additions & 4 deletions Source/SourceKittenFramework/File.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
Expand Down
167 changes: 74 additions & 93 deletions Source/SourceKittenFramework/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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") {
Expand All @@ -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)!
}

/**
Expand All @@ -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
}
Expand All @@ -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()
}

Expand All @@ -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!)
Expand Down Expand Up @@ -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 {
Expand Down
Loading