Files
sourcekit-lsp/Sources/SourceKit/sourcekitd/SwiftSourceKitFramework.swift
Ben Langmuir 1def01e634 Use RTLD_DEEP_BIND on Linux when opening libsourcekitdInProc
We have multiple copies of llvm symbols (indexstoredb, indexstore,
llbuild via swiftpm, and sourcekitd), so it's important to keep them
isolated. In practice this seems to have started breaking after we
updated swiftpm and llbuild was added, but it was already a potential
issue before that. The most egregious issue is if you build sourcekit
with assertions, it enables ABI-breaking checks in llvm. On macOS this
dlopen behaviour is already the default.
2018-11-16 16:17:40 -08:00

607 lines
28 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import LanguageServerProtocol
import Basic
import SKSupport
import sourcekitd
/// A wrapper for accessing the API of a sourcekitd library loaded via `dlopen`.
final class SwiftSourceKitFramework {
/// The path to the sourcekitd dylib.
let path: AbsolutePath
/// The handle to the dylib.
let dylib: DLHandle
/// The sourcekitd API functions.
let api: sourcekitd_functions_t
/// Convenience for accessing known keys.
let keys: sourcekitd_keys
/// Convenience for accessing known keys.
let requests: sourcekitd_requests
/// Convenience for accessing known keys.
let values: sourcekitd_values
enum Error: Swift.Error {
case missingRequiredSymbol(String)
}
init(dylib path: AbsolutePath) throws {
self.path = path
self.dylib = try dlopen(path.asString, mode: [.lazy, .local, .first, .deepBind])
func dlsym_required<T>(_ handle: DLHandle, symbol: String) throws -> T {
guard let sym: T = dlsym(handle, symbol: symbol) else {
throw Error.missingRequiredSymbol(symbol)
}
return sym
}
// Workaround rdar://problem/43656704 by not constructing the value directly.
// self.api = sourcekitd_functions_t(
let ptr = UnsafeMutablePointer<sourcekitd_functions_t>.allocate(capacity: 1)
bzero(UnsafeMutableRawPointer(ptr), MemoryLayout<sourcekitd_functions_t>.stride)
var api = ptr.pointee
ptr.deallocate()
// The following crashes the compiler rdar://43658464
// api.variant_dictionary_apply = try dlsym_required(dylib, symbol: "sourcekitd_variant_dictionary_apply")
// api.variant_array_apply = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_apply")
api.initialize = try dlsym_required(dylib, symbol: "sourcekitd_initialize")
api.shutdown = try dlsym_required(dylib, symbol: "sourcekitd_shutdown")
api.uid_get_from_cstr = try dlsym_required(dylib, symbol: "sourcekitd_uid_get_from_cstr")
api.uid_get_from_buf = try dlsym_required(dylib, symbol: "sourcekitd_uid_get_from_buf")
api.uid_get_length = try dlsym_required(dylib, symbol: "sourcekitd_uid_get_length")
api.uid_get_string_ptr = try dlsym_required(dylib, symbol: "sourcekitd_uid_get_string_ptr")
api.request_retain = try dlsym_required(dylib, symbol: "sourcekitd_request_retain")
api.request_release = try dlsym_required(dylib, symbol: "sourcekitd_request_release")
api.request_dictionary_create = try dlsym_required(dylib, symbol: "sourcekitd_request_dictionary_create")
api.request_dictionary_set_value = try dlsym_required(dylib, symbol: "sourcekitd_request_dictionary_set_value")
api.request_dictionary_set_string = try dlsym_required(dylib, symbol: "sourcekitd_request_dictionary_set_string")
api.request_dictionary_set_stringbuf = try dlsym_required(dylib, symbol: "sourcekitd_request_dictionary_set_stringbuf")
api.request_dictionary_set_int64 = try dlsym_required(dylib, symbol: "sourcekitd_request_dictionary_set_int64")
api.request_dictionary_set_uid = try dlsym_required(dylib, symbol: "sourcekitd_request_dictionary_set_uid")
api.request_array_create = try dlsym_required(dylib, symbol: "sourcekitd_request_array_create")
api.request_array_set_value = try dlsym_required(dylib, symbol: "sourcekitd_request_array_set_value")
api.request_array_set_string = try dlsym_required(dylib, symbol: "sourcekitd_request_array_set_string")
api.request_array_set_stringbuf = try dlsym_required(dylib, symbol: "sourcekitd_request_array_set_stringbuf")
api.request_array_set_int64 = try dlsym_required(dylib, symbol: "sourcekitd_request_array_set_int64")
api.request_array_set_uid = try dlsym_required(dylib, symbol: "sourcekitd_request_array_set_uid")
api.request_int64_create = try dlsym_required(dylib, symbol: "sourcekitd_request_int64_create")
api.request_string_create = try dlsym_required(dylib, symbol: "sourcekitd_request_string_create")
api.request_uid_create = try dlsym_required(dylib, symbol: "sourcekitd_request_uid_create")
api.request_create_from_yaml = try dlsym_required(dylib, symbol: "sourcekitd_request_create_from_yaml")
api.request_description_dump = try dlsym_required(dylib, symbol: "sourcekitd_request_description_dump")
api.request_description_copy = try dlsym_required(dylib, symbol: "sourcekitd_request_description_copy")
api.response_dispose = try dlsym_required(dylib, symbol: "sourcekitd_response_dispose")
api.response_is_error = try dlsym_required(dylib, symbol: "sourcekitd_response_is_error")
api.response_error_get_kind = try dlsym_required(dylib, symbol: "sourcekitd_response_error_get_kind")
api.response_error_get_description = try dlsym_required(dylib, symbol: "sourcekitd_response_error_get_description")
api.response_get_value = try dlsym_required(dylib, symbol: "sourcekitd_response_get_value")
api.variant_get_type = try dlsym_required(dylib, symbol: "sourcekitd_variant_get_type")
api.variant_dictionary_get_value = try dlsym_required(dylib, symbol: "sourcekitd_variant_dictionary_get_value")
api.variant_dictionary_get_string = try dlsym_required(dylib, symbol: "sourcekitd_variant_dictionary_get_string")
api.variant_dictionary_get_int64 = try dlsym_required(dylib, symbol: "sourcekitd_variant_dictionary_get_int64")
api.variant_dictionary_get_bool = try dlsym_required(dylib, symbol: "sourcekitd_variant_dictionary_get_bool")
api.variant_dictionary_get_uid = try dlsym_required(dylib, symbol: "sourcekitd_variant_dictionary_get_uid")
api.variant_array_get_count = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_get_count")
api.variant_array_get_value = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_get_value")
api.variant_array_get_string = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_get_string")
api.variant_array_get_int64 = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_get_int64")
api.variant_array_get_bool = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_get_bool")
api.variant_array_get_uid = try dlsym_required(dylib, symbol: "sourcekitd_variant_array_get_uid")
api.variant_int64_get_value = try dlsym_required(dylib, symbol: "sourcekitd_variant_int64_get_value")
api.variant_bool_get_value = try dlsym_required(dylib, symbol: "sourcekitd_variant_bool_get_value")
api.variant_string_get_length = try dlsym_required(dylib, symbol: "sourcekitd_variant_string_get_length")
api.variant_string_get_ptr = try dlsym_required(dylib, symbol: "sourcekitd_variant_string_get_ptr")
api.variant_data_get_size = dlsym(dylib, symbol: "sourcekitd_variant_data_get_size") // Optional
api.variant_data_get_ptr = dlsym(dylib, symbol: "sourcekitd_variant_data_get_ptr") // Optional
api.variant_uid_get_value = try dlsym_required(dylib, symbol: "sourcekitd_variant_uid_get_value")
api.response_description_dump = try dlsym_required(dylib, symbol: "sourcekitd_response_description_dump")
api.response_description_dump_filedesc = try dlsym_required(dylib, symbol: "sourcekitd_response_description_dump_filedesc")
api.response_description_copy = try dlsym_required(dylib, symbol: "sourcekitd_response_description_copy")
api.variant_description_dump = try dlsym_required(dylib, symbol: "sourcekitd_variant_description_dump")
api.variant_description_dump_filedesc = try dlsym_required(dylib, symbol: "sourcekitd_variant_description_dump_filedesc")
api.variant_description_copy = try dlsym_required(dylib, symbol: "sourcekitd_variant_description_copy")
api.send_request_sync = try dlsym_required(dylib, symbol: "sourcekitd_send_request_sync")
api.send_request = try dlsym_required(dylib, symbol: "sourcekitd_send_request")
api.cancel_request = try dlsym_required(dylib, symbol: "sourcekitd_cancel_request")
api.set_notification_handler = try dlsym_required(dylib, symbol: "sourcekitd_set_notification_handler")
api.set_uid_handlers = try dlsym_required(dylib, symbol: "sourcekitd_set_uid_handlers")
self.api = api
self.keys = sourcekitd_keys(api: self.api)
self.requests = sourcekitd_requests(api: self.api)
self.values = sourcekitd_values(api: self.api)
}
deinit {
// FIXME: is it safe to dlclose() sourcekitd? If so, do that here. For now, let the handle leak.
dylib.leak()
}
}
extension SwiftSourceKitFramework {
// MARK: - Convenience API for requests.
/// Send the given request and synchronously receive a reply dictionary (or error).
func sendSync(_ req: SKRequestDictionary) -> LSPResult<SKResponseDictionary> {
logAsync { _ in req.description }
let resp = SKResponse(api.send_request_sync(req.dict), sourcekitd: self)
guard let dict = resp.value else {
log(resp.description, level: .error)
return .failure(resp.error!)
}
logAsync(level: .debug) { _ in dict.description }
return .success(dict)
}
/// Send the given request and synchronously receive a reply dictionary (or error).
func send(_ req: SKRequestDictionary, reply: @escaping (LSPResult<SKResponseDictionary>) -> ()) -> sourcekitd_request_handle_t? {
logAsync { _ in req.description }
var handle: sourcekitd_request_handle_t? = nil
api.send_request(req.dict, &handle) { [weak self] _resp in
guard let self = self else { return }
let resp = SKResponse(_resp, sourcekitd: self)
guard let dict = resp.value else {
log(resp.description, level: .error)
reply(.failure(resp.error!))
return
}
logAsync(level: .debug) { _ in dict.description }
reply(.success(dict))
}
return handle
}
}
struct sourcekitd_keys {
let request: sourcekitd_uid_t
let compilerargs: sourcekitd_uid_t
let offset: sourcekitd_uid_t
let length: sourcekitd_uid_t
let sourcefile: sourcekitd_uid_t
let sourcetext: sourcekitd_uid_t
let results: sourcekitd_uid_t
let description: sourcekitd_uid_t
let name: sourcekitd_uid_t
let kind: sourcekitd_uid_t
let notification: sourcekitd_uid_t
let diagnostics: sourcekitd_uid_t
let severity: sourcekitd_uid_t
let line: sourcekitd_uid_t
let column: sourcekitd_uid_t
let filepath: sourcekitd_uid_t
let ranges: sourcekitd_uid_t
let usr: sourcekitd_uid_t
let annotated_decl: sourcekitd_uid_t
let doc_full_as_xml: sourcekitd_uid_t
init(api: sourcekitd_functions_t) {
request = api.uid_get_from_cstr("key.request")!
compilerargs = api.uid_get_from_cstr("key.compilerargs")!
offset = api.uid_get_from_cstr("key.offset")!
length = api.uid_get_from_cstr("key.length")!
sourcefile = api.uid_get_from_cstr("key.sourcefile")!
sourcetext = api.uid_get_from_cstr("key.sourcetext")!
results = api.uid_get_from_cstr("key.results")!
description = api.uid_get_from_cstr("key.description")!
name = api.uid_get_from_cstr("key.name")!
kind = api.uid_get_from_cstr("key.kind")!
notification = api.uid_get_from_cstr("key.notification")!
diagnostics = api.uid_get_from_cstr("key.diagnostics")!
severity = api.uid_get_from_cstr("key.severity")!
line = api.uid_get_from_cstr("key.line")!
column = api.uid_get_from_cstr("key.column")!
filepath = api.uid_get_from_cstr("key.filepath")!
ranges = api.uid_get_from_cstr("key.ranges")!
usr = api.uid_get_from_cstr("key.usr")!
annotated_decl = api.uid_get_from_cstr("key.annotated_decl")!
doc_full_as_xml = api.uid_get_from_cstr("key.doc.full_as_xml")!
}
}
struct sourcekitd_requests {
let editor_open: sourcekitd_uid_t
let editor_close: sourcekitd_uid_t
let editor_replacetext: sourcekitd_uid_t
let codecomplete: sourcekitd_uid_t
let cursorinfo: sourcekitd_uid_t
let relatedidents: sourcekitd_uid_t
init(api: sourcekitd_functions_t) {
editor_open = api.uid_get_from_cstr("source.request.editor.open")!
editor_close = api.uid_get_from_cstr("source.request.editor.close")!
editor_replacetext = api.uid_get_from_cstr("source.request.editor.replacetext")!
codecomplete = api.uid_get_from_cstr("source.request.codecomplete")!
cursorinfo = api.uid_get_from_cstr("source.request.cursorinfo")!
relatedidents = api.uid_get_from_cstr("source.request.relatedidents")!
}
}
struct sourcekitd_values {
let notification_documentupdate: sourcekitd_uid_t
let diag_error: sourcekitd_uid_t
let diag_warning: sourcekitd_uid_t
let diag_note: sourcekitd_uid_t
// MARK: Symbol Kinds
let decl_function_free: sourcekitd_uid_t
let ref_function_free: sourcekitd_uid_t
let decl_function_method_instance: sourcekitd_uid_t
let ref_function_method_instance: sourcekitd_uid_t
let decl_function_method_static: sourcekitd_uid_t
let ref_function_method_static: sourcekitd_uid_t
let decl_function_method_class: sourcekitd_uid_t
let ref_function_method_class: sourcekitd_uid_t
let decl_function_accessor_getter: sourcekitd_uid_t
let ref_function_accessor_getter: sourcekitd_uid_t
let decl_function_accessor_setter: sourcekitd_uid_t
let ref_function_accessor_setter: sourcekitd_uid_t
let decl_function_accessor_willset: sourcekitd_uid_t
let ref_function_accessor_willset: sourcekitd_uid_t
let decl_function_accessor_didset: sourcekitd_uid_t
let ref_function_accessor_didset: sourcekitd_uid_t
let decl_function_accessor_address: sourcekitd_uid_t
let ref_function_accessor_address: sourcekitd_uid_t
let decl_function_accessor_mutableaddress: sourcekitd_uid_t
let ref_function_accessor_mutableaddress: sourcekitd_uid_t
let decl_function_accessor_read: sourcekitd_uid_t
let ref_function_accessor_read: sourcekitd_uid_t
let decl_function_accessor_modify: sourcekitd_uid_t
let ref_function_accessor_modify: sourcekitd_uid_t
let decl_function_constructor: sourcekitd_uid_t
let ref_function_constructor: sourcekitd_uid_t
let decl_function_destructor: sourcekitd_uid_t
let ref_function_destructor: sourcekitd_uid_t
let decl_function_operator_prefix: sourcekitd_uid_t
let decl_function_operator_postfix: sourcekitd_uid_t
let decl_function_operator_infix: sourcekitd_uid_t
let ref_function_operator_prefix: sourcekitd_uid_t
let ref_function_operator_postfix: sourcekitd_uid_t
let ref_function_operator_infix: sourcekitd_uid_t
let decl_precedencegroup: sourcekitd_uid_t
let ref_precedencegroup: sourcekitd_uid_t
let decl_function_subscript: sourcekitd_uid_t
let ref_function_subscript: sourcekitd_uid_t
let decl_var_global: sourcekitd_uid_t
let ref_var_global: sourcekitd_uid_t
let decl_var_instance: sourcekitd_uid_t
let ref_var_instance: sourcekitd_uid_t
let decl_var_static: sourcekitd_uid_t
let ref_var_static: sourcekitd_uid_t
let decl_var_class: sourcekitd_uid_t
let ref_var_class: sourcekitd_uid_t
let decl_var_local: sourcekitd_uid_t
let ref_var_local: sourcekitd_uid_t
let decl_var_parameter: sourcekitd_uid_t
let decl_module: sourcekitd_uid_t
let decl_class: sourcekitd_uid_t
let ref_class: sourcekitd_uid_t
let decl_struct: sourcekitd_uid_t
let ref_struct: sourcekitd_uid_t
let decl_enum: sourcekitd_uid_t
let ref_enum: sourcekitd_uid_t
let decl_enumcase: sourcekitd_uid_t
let decl_enumelement: sourcekitd_uid_t
let ref_enumelement: sourcekitd_uid_t
let decl_protocol: sourcekitd_uid_t
let ref_protocol: sourcekitd_uid_t
let decl_extension: sourcekitd_uid_t
let decl_extension_struct: sourcekitd_uid_t
let decl_extension_class: sourcekitd_uid_t
let decl_extension_enum: sourcekitd_uid_t
let decl_extension_protocol: sourcekitd_uid_t
let decl_associatedtype: sourcekitd_uid_t
let ref_associatedtype: sourcekitd_uid_t
let decl_typealias: sourcekitd_uid_t
let ref_typealias: sourcekitd_uid_t
let decl_generic_type_param: sourcekitd_uid_t
let ref_generic_type_param: sourcekitd_uid_t
let ref_module: sourcekitd_uid_t
let kind_keyword: sourcekitd_uid_t
init(api: sourcekitd_functions_t) {
notification_documentupdate = api.uid_get_from_cstr("source.notification.editor.documentupdate")!
diag_error = api.uid_get_from_cstr("source.diagnostic.severity.error")!
diag_warning = api.uid_get_from_cstr("source.diagnostic.severity.warning")!
diag_note = api.uid_get_from_cstr("source.diagnostic.severity.note")!
// MARK: Symbol Kinds
decl_function_free = api.uid_get_from_cstr("source.lang.swift.decl.function.free")!
ref_function_free = api.uid_get_from_cstr("source.lang.swift.ref.function.free")!
decl_function_method_instance = api.uid_get_from_cstr("source.lang.swift.decl.function.method.instance")!
ref_function_method_instance = api.uid_get_from_cstr("source.lang.swift.ref.function.method.instance")!
decl_function_method_static = api.uid_get_from_cstr("source.lang.swift.decl.function.method.static")!
ref_function_method_static = api.uid_get_from_cstr("source.lang.swift.ref.function.method.static")!
decl_function_method_class = api.uid_get_from_cstr("source.lang.swift.decl.function.method.class")!
ref_function_method_class = api.uid_get_from_cstr("source.lang.swift.ref.function.method.class")!
decl_function_accessor_getter = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.getter")!
ref_function_accessor_getter = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.getter")!
decl_function_accessor_setter = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.setter")!
ref_function_accessor_setter = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.setter")!
decl_function_accessor_willset = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.willset")!
ref_function_accessor_willset = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.willset")!
decl_function_accessor_didset = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.didset")!
ref_function_accessor_didset = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.didset")!
decl_function_accessor_address = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.address")!
ref_function_accessor_address = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.address")!
decl_function_accessor_mutableaddress = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.mutableaddress")!
ref_function_accessor_mutableaddress = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.mutableaddress")!
decl_function_accessor_read = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.read")!
ref_function_accessor_read = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.read")!
decl_function_accessor_modify = api.uid_get_from_cstr("source.lang.swift.decl.function.accessor.modify")!
ref_function_accessor_modify = api.uid_get_from_cstr("source.lang.swift.ref.function.accessor.modify")!
decl_function_constructor = api.uid_get_from_cstr("source.lang.swift.decl.function.constructor")!
ref_function_constructor = api.uid_get_from_cstr("source.lang.swift.ref.function.constructor")!
decl_function_destructor = api.uid_get_from_cstr("source.lang.swift.decl.function.destructor")!
ref_function_destructor = api.uid_get_from_cstr("source.lang.swift.ref.function.destructor")!
decl_function_operator_prefix = api.uid_get_from_cstr("source.lang.swift.decl.function.operator.prefix")!
decl_function_operator_postfix = api.uid_get_from_cstr("source.lang.swift.decl.function.operator.postfix")!
decl_function_operator_infix = api.uid_get_from_cstr("source.lang.swift.decl.function.operator.infix")!
ref_function_operator_prefix = api.uid_get_from_cstr("source.lang.swift.ref.function.operator.prefix")!
ref_function_operator_postfix = api.uid_get_from_cstr("source.lang.swift.ref.function.operator.postfix")!
ref_function_operator_infix = api.uid_get_from_cstr("source.lang.swift.ref.function.operator.infix")!
decl_precedencegroup = api.uid_get_from_cstr("source.lang.swift.decl.precedencegroup")!
ref_precedencegroup = api.uid_get_from_cstr("source.lang.swift.ref.precedencegroup")!
decl_function_subscript = api.uid_get_from_cstr("source.lang.swift.decl.function.subscript")!
ref_function_subscript = api.uid_get_from_cstr("source.lang.swift.ref.function.subscript")!
decl_var_global = api.uid_get_from_cstr("source.lang.swift.decl.var.global")!
ref_var_global = api.uid_get_from_cstr("source.lang.swift.ref.var.global")!
decl_var_instance = api.uid_get_from_cstr("source.lang.swift.decl.var.instance")!
ref_var_instance = api.uid_get_from_cstr("source.lang.swift.ref.var.instance")!
decl_var_static = api.uid_get_from_cstr("source.lang.swift.decl.var.static")!
ref_var_static = api.uid_get_from_cstr("source.lang.swift.ref.var.static")!
decl_var_class = api.uid_get_from_cstr("source.lang.swift.decl.var.class")!
ref_var_class = api.uid_get_from_cstr("source.lang.swift.ref.var.class")!
decl_var_local = api.uid_get_from_cstr("source.lang.swift.decl.var.local")!
ref_var_local = api.uid_get_from_cstr("source.lang.swift.ref.var.local")!
decl_var_parameter = api.uid_get_from_cstr("source.lang.swift.decl.var.parameter")!
decl_module = api.uid_get_from_cstr("source.lang.swift.decl.module")!
decl_class = api.uid_get_from_cstr("source.lang.swift.decl.class")!
ref_class = api.uid_get_from_cstr("source.lang.swift.ref.class")!
decl_struct = api.uid_get_from_cstr("source.lang.swift.decl.struct")!
ref_struct = api.uid_get_from_cstr("source.lang.swift.ref.struct")!
decl_enum = api.uid_get_from_cstr("source.lang.swift.decl.enum")!
ref_enum = api.uid_get_from_cstr("source.lang.swift.ref.enum")!
decl_enumcase = api.uid_get_from_cstr("source.lang.swift.decl.enumcase")!
decl_enumelement = api.uid_get_from_cstr("source.lang.swift.decl.enumelement")!
ref_enumelement = api.uid_get_from_cstr("source.lang.swift.ref.enumelement")!
decl_protocol = api.uid_get_from_cstr("source.lang.swift.decl.protocol")!
ref_protocol = api.uid_get_from_cstr("source.lang.swift.ref.protocol")!
decl_extension = api.uid_get_from_cstr("source.lang.swift.decl.extension")!
decl_extension_struct = api.uid_get_from_cstr("source.lang.swift.decl.extension.struct")!
decl_extension_class = api.uid_get_from_cstr("source.lang.swift.decl.extension.class")!
decl_extension_enum = api.uid_get_from_cstr("source.lang.swift.decl.extension.enum")!
decl_extension_protocol = api.uid_get_from_cstr("source.lang.swift.decl.extension.protocol")!
decl_associatedtype = api.uid_get_from_cstr("source.lang.swift.decl.associatedtype")!
ref_associatedtype = api.uid_get_from_cstr("source.lang.swift.ref.associatedtype")!
decl_typealias = api.uid_get_from_cstr("source.lang.swift.decl.typealias")!
ref_typealias = api.uid_get_from_cstr("source.lang.swift.ref.typealias")!
decl_generic_type_param = api.uid_get_from_cstr("source.lang.swift.decl.generic_type_param")!
ref_generic_type_param = api.uid_get_from_cstr("source.lang.swift.ref.generic_type_param")!
ref_module = api.uid_get_from_cstr("source.lang.swift.ref.module")!
kind_keyword = api.uid_get_from_cstr("source.lang.swift.keyword")!
}
}
final class SKRequestDictionary {
let dict: sourcekitd_object_t?
let sourcekitd: SwiftSourceKitFramework
init(_ dict: sourcekitd_object_t? = nil, sourcekitd: SwiftSourceKitFramework) {
self.dict = dict ?? sourcekitd.api.request_dictionary_create(nil, nil, 0)
self.sourcekitd = sourcekitd
}
deinit {
sourcekitd.api.request_release(dict)
}
subscript(key: sourcekitd_uid_t?) -> String {
get { fatalError("request is set-only") }
set { sourcekitd.api.request_dictionary_set_string(dict, key, newValue) }
}
subscript(key: sourcekitd_uid_t?) -> Int {
get { fatalError("request is set-only") }
set { sourcekitd.api.request_dictionary_set_int64(dict, key, Int64(newValue)) }
}
subscript(key: sourcekitd_uid_t?) -> sourcekitd_uid_t? {
get { fatalError("request is set-only") }
set { sourcekitd.api.request_dictionary_set_uid(dict, key, newValue) }
}
subscript(key: sourcekitd_uid_t?) -> SKRequestDictionary {
get { fatalError("request is set-only") }
set { sourcekitd.api.request_dictionary_set_value(dict, key, newValue.dict) }
}
subscript<S>(key: sourcekitd_uid_t?) -> S where S: Sequence, S.Element == String {
get { fatalError("request is set-only") }
set {
let array = SKRequestArray(sourcekitd: sourcekitd)
newValue.forEach { array.append($0) }
sourcekitd.api.request_dictionary_set_value(dict, key, array.array)
}
}
subscript(key: sourcekitd_uid_t?) -> SKRequestArray {
get { fatalError("request is set-only") }
set { sourcekitd.api.request_dictionary_set_value(dict, key, newValue.array) }
}
}
final class SKRequestArray {
let array: sourcekitd_object_t?
let sourcekitd: SwiftSourceKitFramework
init(_ array: sourcekitd_object_t? = nil, sourcekitd: SwiftSourceKitFramework) {
self.array = array ?? sourcekitd.api.request_array_create(nil, 0)
self.sourcekitd = sourcekitd
}
deinit {
sourcekitd.api.request_release(array)
}
func append(_ value: String) {
sourcekitd.api.request_array_set_string(array, -1, value)
}
}
final class SKResponse {
let response: sourcekitd_response_t?
let sourcekitd: SwiftSourceKitFramework
init(_ response: sourcekitd_response_t?, sourcekitd: SwiftSourceKitFramework) {
self.response = response
self.sourcekitd = sourcekitd
}
deinit {
sourcekitd.api.response_dispose(response)
}
var error: ResponseError? {
if !sourcekitd.api.response_is_error(response) {
return nil
}
switch sourcekitd.api.response_error_get_kind(response) {
case SOURCEKITD_ERROR_REQUEST_CANCELLED:
return .cancelled
default:
return .unknown(description)
}
}
var value: SKResponseDictionary? {
if sourcekitd.api.response_is_error(response) {
return nil
}
return SKResponseDictionary(sourcekitd.api.response_get_value(response), response: self)
}
}
final class SKResponseDictionary {
let dict: sourcekitd_variant_t
let resp: SKResponse
var sourcekitd: SwiftSourceKitFramework { return resp.sourcekitd }
init(_ dict: sourcekitd_variant_t, response: SKResponse) {
self.dict = dict
self.resp = response
}
subscript(key: sourcekitd_uid_t?) -> String? {
return sourcekitd.api.variant_dictionary_get_string(dict, key).map(String.init(cString:))
}
subscript(key: sourcekitd_uid_t?) -> Int? {
return Int(sourcekitd.api.variant_dictionary_get_int64(dict, key))
}
subscript(key: sourcekitd_uid_t?) -> sourcekitd_uid_t? {
return sourcekitd.api.variant_dictionary_get_uid(dict, key)
}
subscript(key: sourcekitd_uid_t?) -> SKResponseArray? {
return SKResponseArray(sourcekitd.api.variant_dictionary_get_value(dict, key), response: resp)
}
}
final class SKResponseArray {
let array: sourcekitd_variant_t
let resp: SKResponse
var sourcekitd: SwiftSourceKitFramework { return resp.sourcekitd }
init(_ array: sourcekitd_variant_t, response: SKResponse) {
self.array = array
self.resp = response
}
var count: Int { return sourcekitd.api.variant_array_get_count(array) }
/// If the `applier` returns `false`, iteration terminates.
@discardableResult
func forEach(_ applier: (Int, SKResponseDictionary) -> Bool) -> Bool {
for i in 0..<count {
if !applier(i, SKResponseDictionary(sourcekitd.api.variant_array_get_value(array, i), response: resp)) {
return false
}
}
return true
}
}
extension SKRequestDictionary: CustomStringConvertible {
var description: String {
let ptr = sourcekitd.api.request_description_copy(dict)!
defer { free(ptr) }
return String(cString: ptr)
}
}
extension SKRequestArray: CustomStringConvertible {
var description: String {
let ptr = sourcekitd.api.request_description_copy(array)!
defer { free(ptr) }
return String(cString: ptr)
}
}
extension SKResponse: CustomStringConvertible {
var description: String {
let ptr = sourcekitd.api.response_description_copy(response)!
defer { free(ptr) }
return String(cString: ptr)
}
}
extension SKResponseDictionary: CustomStringConvertible {
var description: String {
let ptr = sourcekitd.api.variant_description_copy(dict)!
defer { free(ptr) }
return String(cString: ptr)
}
}
extension SKResponseArray: CustomStringConvertible {
var description: String {
let ptr = sourcekitd.api.variant_description_copy(array)!
defer { free(ptr) }
return String(cString: ptr)
}
}