mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Revert "Revert "swift-lang: shuffle the source directory structure (NFC)""
This reverts commit beb8ecd8cc. Add a
workaround for the dependency issue.
It is unclear why `sourcekitd` is getting added improperly as a
dependency on `lib/sourcekitd.framework/sourcekitd`. This workaround
adjusts the dependency such that we end up with a dependency on
`lib/sourcekitd.framework/Versions/A/sourcekitd` as an order-only
dependency. This should fix the compile issue. I am unable to
reproduce this issue with the `add_library` usage for adding a Swift
library. This allows us to cleave the host and target libraries, and so
the workaround is sufficient to make progress and the problem will be
resolved with the migration towards CMake for handling the dependencies.
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
if(SWIFT_BUILD_DYNAMIC_STDLIB AND SWIFT_INCLUDE_TESTS)
|
||||
add_subdirectory(swift-reflection-test)
|
||||
endif()
|
||||
if(SWIFT_BUILD_SDK_OVERLAY)
|
||||
include(CheckIncludeFiles)
|
||||
check_include_files("xpc/xpc.h" HAVE_XPC_H)
|
||||
|
||||
if(SWIFT_BUILD_SOURCEKIT AND CMAKE_SYSTEM_NAME STREQUAL Darwin AND HAVE_XPC_H)
|
||||
add_subdirectory(swift-lang)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
28
stdlib/tools/swift-lang/CMakeLists.txt
Normal file
28
stdlib/tools/swift-lang/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
if(SWIFT_HOST_VARIANT MATCHES "^iphoneos")
|
||||
set(SWIFT_LANG_TARGET_SDK "IOS")
|
||||
elseif(SWIFT_HOST_VARIANT MATCHES "^iphonesimulator")
|
||||
set(SWIFT_LANG_TARGET_SDK "IOS_SIMULATOR")
|
||||
elseif(SWIFT_HOST_VARIANT MATCHES "^macosx")
|
||||
set(SWIFT_LANG_TARGET_SDK "OSX")
|
||||
else()
|
||||
message(SEND_ERROR "Unknown SDK for SwiftLang")
|
||||
endif()
|
||||
|
||||
add_swift_target_library(swiftSwiftLang SHARED
|
||||
SwiftLang.swift
|
||||
SourceKitdClient.swift
|
||||
SourceKitdRequest.swift
|
||||
SourceKitdResponse.swift
|
||||
SourceKitdUID.swift
|
||||
|
||||
GYB_SOURCES
|
||||
UIDs.swift.gyb
|
||||
|
||||
DEPENDS sourcekitd
|
||||
SWIFT_MODULE_DEPENDS_OSX Darwin Foundation
|
||||
PRIVATE_LINK_LIBRARIES sourcekitd
|
||||
SWIFT_COMPILE_FLAGS -F${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib
|
||||
INSTALL_IN_COMPONENT sourcekit-xpc-service
|
||||
DARWIN_INSTALL_NAME_DIR "@rpath"
|
||||
TARGET_SDKS ${SWIFT_LANG_TARGET_SDK}
|
||||
IS_STDLIB)
|
||||
43
stdlib/tools/swift-lang/SourceKitdClient.swift
Normal file
43
stdlib/tools/swift-lang/SourceKitdClient.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
//===--------------------- SourceKitdClient.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file provides a wrapper of SourceKitd service.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import sourcekitd
|
||||
|
||||
public class SourceKitdService {
|
||||
|
||||
public init() {
|
||||
sourcekitd_initialize()
|
||||
}
|
||||
deinit {
|
||||
sourcekitd_shutdown()
|
||||
}
|
||||
|
||||
/// Send a request synchronously with a handler for its response.
|
||||
/// - Parameter request: The request to send.
|
||||
/// - Returns: The response from the sourcekitd service.
|
||||
public func sendSyn(request: SourceKitdRequest) -> SourceKitdResponse {
|
||||
return SourceKitdResponse(resp: sourcekitd_send_request_sync(request.rawRequest))
|
||||
}
|
||||
|
||||
/// Send a request asynchronously with a handler for its response.
|
||||
/// - Parameter request: The request to send.
|
||||
/// - Parameter handler: The handler for the response in the future.
|
||||
public func send(request: SourceKitdRequest,
|
||||
handler: @escaping (SourceKitdResponse) -> ()) {
|
||||
sourcekitd_send_request(request.rawRequest, nil) { response in
|
||||
guard let response = response else { return }
|
||||
handler(SourceKitdResponse(resp: response))
|
||||
}
|
||||
}
|
||||
}
|
||||
154
stdlib/tools/swift-lang/SourceKitdRequest.swift
Normal file
154
stdlib/tools/swift-lang/SourceKitdRequest.swift
Normal file
@@ -0,0 +1,154 @@
|
||||
//===--------------- SourceKitdRequest.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file provides a convenient way to build a sourcekitd request.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import sourcekitd
|
||||
|
||||
public struct SourceKitdRequest: CustomStringConvertible {
|
||||
|
||||
public class Dictionary: CustomStringConvertible {
|
||||
let dict: sourcekitd_object_t
|
||||
|
||||
public init() {
|
||||
dict = sourcekitd_request_dictionary_create(nil, nil, 0)
|
||||
}
|
||||
|
||||
deinit {
|
||||
sourcekitd_request_release(UnsafeMutableRawPointer(dict))
|
||||
}
|
||||
|
||||
public func add(_ key: SourceKitdUID, value: String) {
|
||||
sourcekitd_request_dictionary_set_string(dict, key.uid, value)
|
||||
}
|
||||
|
||||
public func add(_ key: SourceKitdUID, value: Int) {
|
||||
sourcekitd_request_dictionary_set_int64(dict, key.uid, Int64(value))
|
||||
}
|
||||
|
||||
public func add(_ key: SourceKitdUID, value: SourceKitdUID) {
|
||||
sourcekitd_request_dictionary_set_uid(dict, key.uid, value.uid)
|
||||
}
|
||||
|
||||
public func add(_ key: SourceKitdUID, value: Array) {
|
||||
sourcekitd_request_dictionary_set_value(dict, key.uid, value.arr)
|
||||
}
|
||||
|
||||
public func add(_ key: SourceKitdUID, value: Dictionary) {
|
||||
sourcekitd_request_dictionary_set_value(dict, key.uid, value.dict)
|
||||
}
|
||||
|
||||
public func add(_ key: SourceKitdUID, value: Bool) {
|
||||
sourcekitd_request_dictionary_set_int64(dict, key.uid, value ? 1 : 0)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
let utf8Str = sourcekitd_request_description_copy(dict)!
|
||||
let result = String(cString: utf8Str)
|
||||
free(utf8Str)
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Array: CustomStringConvertible {
|
||||
let arr: sourcekitd_object_t
|
||||
private let Append: Int = -1
|
||||
|
||||
public init() {
|
||||
arr = sourcekitd_request_array_create(nil, 0)
|
||||
}
|
||||
|
||||
deinit {
|
||||
sourcekitd_request_release(arr)
|
||||
}
|
||||
|
||||
public func add(_ value: String) {
|
||||
sourcekitd_request_array_set_string(arr, Append, value)
|
||||
}
|
||||
|
||||
public func add(_ value: Int) {
|
||||
sourcekitd_request_array_set_int64(arr, Append, Int64(value))
|
||||
}
|
||||
|
||||
public func add(_ value: SourceKitdUID) {
|
||||
sourcekitd_request_array_set_uid(arr, Append, value.uid)
|
||||
}
|
||||
|
||||
public func add(_ value: Dictionary) {
|
||||
sourcekitd_request_array_set_value(arr, Append, value.dict)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
let utf8Str = sourcekitd_request_description_copy(arr)!
|
||||
let result = String(cString: utf8Str)
|
||||
free(utf8Str)
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private let req = Dictionary()
|
||||
|
||||
public init(uid: SourceKitdUID) {
|
||||
req.add(SourceKitdUID.key_Request, value: uid)
|
||||
}
|
||||
|
||||
public func addParameter(_ key: SourceKitdUID, value: String) {
|
||||
req.add(key, value: value)
|
||||
}
|
||||
|
||||
public func addParameter(_ key: SourceKitdUID, value: Int) {
|
||||
req.add(key, value: value)
|
||||
}
|
||||
|
||||
public func addParameter(_ key: SourceKitdUID, value: SourceKitdUID) {
|
||||
req.add(key, value: value)
|
||||
}
|
||||
|
||||
public func addArrayParameter(_ key: SourceKitdUID) -> Array {
|
||||
let arr = Array()
|
||||
req.add(key, value: arr)
|
||||
return arr
|
||||
}
|
||||
|
||||
public func addDictionaryParameter(_ key: SourceKitdUID) -> Dictionary {
|
||||
let dict = Dictionary()
|
||||
req.add(key, value: dict)
|
||||
return dict
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return req.description
|
||||
}
|
||||
|
||||
public var rawRequest: sourcekitd_object_t {
|
||||
return req.dict
|
||||
}
|
||||
|
||||
public func addCompilerArgsToRequest(_ compilerArguments: [String]?,
|
||||
_ bufferName: String? = nil) {
|
||||
let args = self.addArrayParameter(SourceKitdUID.key_CompilerArgs)
|
||||
|
||||
if let compilerArguments = compilerArguments {
|
||||
for argument in compilerArguments {
|
||||
switch argument {
|
||||
// Exclude some arguments which SourceKit doesn't want or need.
|
||||
case "-Xfrontend":
|
||||
break
|
||||
default:
|
||||
args.add(argument)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
289
stdlib/tools/swift-lang/SourceKitdResponse.swift
Normal file
289
stdlib/tools/swift-lang/SourceKitdResponse.swift
Normal file
@@ -0,0 +1,289 @@
|
||||
//===--------------------- SourceKitdResponse.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file provides convenient APIs to interpret a SourceKitd response.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
import sourcekitd
|
||||
|
||||
public class SourceKitdResponse: CustomStringConvertible {
|
||||
|
||||
public struct Dictionary: CustomStringConvertible, CustomReflectable {
|
||||
// The lifetime of this sourcekitd_variant_t is tied to the response it came
|
||||
// from, so keep a reference to the response too.
|
||||
private let dict: sourcekitd_variant_t
|
||||
private let context: SourceKitdResponse
|
||||
|
||||
|
||||
public init(dict: sourcekitd_variant_t, context: SourceKitdResponse) {
|
||||
assert(sourcekitd_variant_get_type(dict).rawValue ==
|
||||
SOURCEKITD_VARIANT_TYPE_DICTIONARY.rawValue)
|
||||
self.dict = dict
|
||||
self.context = context
|
||||
}
|
||||
|
||||
public func getString(_ key: SourceKitdUID) -> String {
|
||||
let value = sourcekitd_variant_dictionary_get_string(dict, key.uid)!
|
||||
return String(cString: value)
|
||||
}
|
||||
|
||||
public func getInt(_ key: SourceKitdUID) -> Int {
|
||||
let value = sourcekitd_variant_dictionary_get_int64(dict, key.uid)
|
||||
return Int(value)
|
||||
}
|
||||
|
||||
public func getBool(_ key: SourceKitdUID) -> Bool {
|
||||
let value = sourcekitd_variant_dictionary_get_bool(dict, key.uid)
|
||||
return value
|
||||
}
|
||||
|
||||
public func getUID(_ key: SourceKitdUID) -> SourceKitdUID {
|
||||
let value = sourcekitd_variant_dictionary_get_uid(dict, key.uid)!
|
||||
return SourceKitdUID(uid: value)
|
||||
}
|
||||
|
||||
public func getArray(_ key: SourceKitdUID) -> Array {
|
||||
let value = sourcekitd_variant_dictionary_get_value(dict, key.uid)
|
||||
return Array(arr: value, context: context)
|
||||
}
|
||||
|
||||
public func getDictionary(_ key: SourceKitdUID) -> Dictionary {
|
||||
let value = sourcekitd_variant_dictionary_get_value(dict, key.uid)
|
||||
return Dictionary(dict: value, context: context)
|
||||
}
|
||||
|
||||
public func getData(_ key: SourceKitdUID) -> Data {
|
||||
let value = sourcekitd_variant_dictionary_get_value(dict, key.uid)
|
||||
let size = sourcekitd_variant_data_get_size(value)
|
||||
guard let ptr = sourcekitd_variant_data_get_ptr(value), size > 0 else {
|
||||
return Data()
|
||||
}
|
||||
return Data(bytes: ptr, count: size)
|
||||
}
|
||||
|
||||
public func getOptional(_ key: SourceKitdUID) -> Variant? {
|
||||
let value = sourcekitd_variant_dictionary_get_value(dict, key.uid)
|
||||
if sourcekitd_variant_get_type(value).rawValue ==
|
||||
SOURCEKITD_VARIANT_TYPE_NULL.rawValue {
|
||||
return nil
|
||||
}
|
||||
return Variant(val: value, context: context)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return dict.description
|
||||
}
|
||||
|
||||
public var customMirror: Mirror {
|
||||
return Mirror(self, children: [:])
|
||||
}
|
||||
}
|
||||
|
||||
public struct Array: CustomStringConvertible {
|
||||
// The lifetime of this sourcekitd_variant_t is tied to the response it came
|
||||
// from, so keep a reference to the response too.
|
||||
private let arr: sourcekitd_variant_t
|
||||
private let context: SourceKitdResponse
|
||||
|
||||
public var count: Int {
|
||||
let count = sourcekitd_variant_array_get_count(arr)
|
||||
return Int(count)
|
||||
}
|
||||
|
||||
public init(arr: sourcekitd_variant_t, context: SourceKitdResponse) {
|
||||
assert(sourcekitd_variant_get_type(arr).rawValue ==
|
||||
SOURCEKITD_VARIANT_TYPE_ARRAY.rawValue)
|
||||
self.arr = arr
|
||||
self.context = context
|
||||
}
|
||||
|
||||
public func getString(_ index: Int) -> String {
|
||||
let value = sourcekitd_variant_array_get_string(arr, index)!
|
||||
return String(cString: value)
|
||||
}
|
||||
|
||||
public func getInt(_ index: Int) -> Int {
|
||||
let value = sourcekitd_variant_array_get_int64(arr, index)
|
||||
return Int(value)
|
||||
}
|
||||
|
||||
public func getBool(_ index: Int) -> Bool {
|
||||
let value = sourcekitd_variant_array_get_bool(arr, index)
|
||||
return value
|
||||
}
|
||||
|
||||
public func getUID(_ index: Int) -> SourceKitdUID {
|
||||
let value = sourcekitd_variant_array_get_uid(arr, index)!
|
||||
return SourceKitdUID(uid: value)
|
||||
}
|
||||
|
||||
public func getArray(_ index: Int) -> Array {
|
||||
let value = sourcekitd_variant_array_get_value(arr, index)
|
||||
return Array(arr: value, context: context)
|
||||
}
|
||||
|
||||
public func getDictionary(_ index: Int) -> Dictionary {
|
||||
let value = sourcekitd_variant_array_get_value(arr, index)
|
||||
return Dictionary(dict: value, context: context)
|
||||
}
|
||||
|
||||
public func enumerate(_ applier: (_ index: Int, _ value: Variant) -> Bool) {
|
||||
// The block passed to sourcekit_variant_array_apply() does not actually
|
||||
// escape, it's synchronous and not called after returning.
|
||||
let context = self.context
|
||||
withoutActuallyEscaping(applier) { escapingApplier in
|
||||
_ = sourcekitd_variant_array_apply(arr) { (index, elem) -> Bool in
|
||||
return escapingApplier(Int(index), Variant(val: elem, context: context))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return arr.description
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public struct Variant: CustomStringConvertible {
|
||||
// The lifetime of this sourcekitd_variant_t is tied to the response it came
|
||||
// from, so keep a reference to the response too.
|
||||
private let val: sourcekitd_variant_t
|
||||
fileprivate let context: SourceKitdResponse
|
||||
|
||||
fileprivate init(val: sourcekitd_variant_t, context: SourceKitdResponse) {
|
||||
self.val = val
|
||||
self.context = context
|
||||
}
|
||||
|
||||
public func getString() -> String {
|
||||
let value = sourcekitd_variant_string_get_ptr(val)!
|
||||
let length = sourcekitd_variant_string_get_length(val)
|
||||
return fromCStringLen(value, length: length)!
|
||||
}
|
||||
|
||||
public func getStringBuffer() -> UnsafeBufferPointer<Int8> {
|
||||
return UnsafeBufferPointer(start: sourcekitd_variant_string_get_ptr(val),
|
||||
count: sourcekitd_variant_string_get_length(val))
|
||||
}
|
||||
|
||||
public func getInt() -> Int {
|
||||
let value = sourcekitd_variant_int64_get_value(val)
|
||||
return Int(value)
|
||||
}
|
||||
|
||||
public func getBool() -> Bool {
|
||||
let value = sourcekitd_variant_bool_get_value(val)
|
||||
return value
|
||||
}
|
||||
|
||||
public func getUID() -> SourceKitdUID {
|
||||
let value = sourcekitd_variant_uid_get_value(val)!
|
||||
return SourceKitdUID(uid:value)
|
||||
}
|
||||
|
||||
public func getArray() -> Array {
|
||||
return Array(arr: val, context: context)
|
||||
}
|
||||
|
||||
public func getDictionary() -> Dictionary {
|
||||
return Dictionary(dict: val, context: context)
|
||||
}
|
||||
|
||||
public func getData() -> Data {
|
||||
let size = sourcekitd_variant_data_get_size(val)
|
||||
guard let ptr = sourcekitd_variant_data_get_ptr(val), size > 0 else {
|
||||
return Data()
|
||||
}
|
||||
return Data(bytes: ptr, count: size)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return val.description
|
||||
}
|
||||
}
|
||||
|
||||
private let resp: sourcekitd_response_t
|
||||
|
||||
public var value: Dictionary {
|
||||
return Dictionary(dict: sourcekitd_response_get_value(resp), context: self)
|
||||
}
|
||||
|
||||
/// Copies the raw bytes of the JSON description of this documentation item.
|
||||
/// The caller is responsible for freeing the associated memory.
|
||||
public func copyRawJSONDocumentation() -> UnsafeMutablePointer<Int8>? {
|
||||
return sourcekitd_variant_json_description_copy(
|
||||
sourcekitd_response_get_value(resp))
|
||||
}
|
||||
|
||||
/// Whether or not this response represents an error.
|
||||
public var isError: Bool {
|
||||
return sourcekitd_response_is_error(resp)
|
||||
}
|
||||
|
||||
/// Whether or not this response represents a notification.
|
||||
public var isNotification: Bool {
|
||||
return value.getOptional(.key_Notification) != nil
|
||||
}
|
||||
|
||||
/// Whether or not this response represents a connection interruption error.
|
||||
public var isConnectionInterruptionError: Bool {
|
||||
return sourcekitd_response_is_error(resp) &&
|
||||
sourcekitd_response_error_get_kind(resp) ==
|
||||
SOURCEKITD_ERROR_CONNECTION_INTERRUPTED
|
||||
}
|
||||
|
||||
/// Whether or not this response represents a compiler crash.
|
||||
public var isCompilerCrash: Bool {
|
||||
guard let notification = value.getOptional(.key_Notification)?.getUID()
|
||||
else { return false }
|
||||
return notification == .compilerCrashedNotification
|
||||
}
|
||||
|
||||
/// If this is a document update notification, returns the name of the
|
||||
/// document to which this update applies. Otherwise, returns `nil`.
|
||||
public var documentUpdateNotificationDocumentName: String? {
|
||||
let response = value
|
||||
guard let notification = response.getOptional(.key_Notification)?.getUID(),
|
||||
notification == .source_notification_editor_documentupdate
|
||||
else { return nil }
|
||||
return response.getOptional(.key_Name)?.getString()
|
||||
}
|
||||
|
||||
public init(resp: sourcekitd_response_t) {
|
||||
self.resp = resp
|
||||
}
|
||||
|
||||
deinit {
|
||||
sourcekitd_response_dispose(resp)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
let utf8Str = sourcekitd_response_description_copy(resp)!
|
||||
let result = String(cString: utf8Str)
|
||||
free(utf8Str)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
extension sourcekitd_variant_t: CustomStringConvertible {
|
||||
public var description: String {
|
||||
let utf8Str = sourcekitd_variant_description_copy(self)!
|
||||
let result = String(cString: utf8Str)
|
||||
free(utf8Str)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private func fromCStringLen(_ ptr: UnsafePointer<Int8>, length: Int) -> String? {
|
||||
return String(decoding: Array(UnsafeBufferPointer(start: ptr, count: length)).map {
|
||||
UInt8(bitPattern: $0) }, as: UTF8.self)
|
||||
}
|
||||
39
stdlib/tools/swift-lang/SourceKitdUID.swift
Normal file
39
stdlib/tools/swift-lang/SourceKitdUID.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
//===------------------------ SourceKitdUID.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file provides SourceKitd UIDs.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import sourcekitd
|
||||
|
||||
public struct SourceKitdUID: Equatable, Hashable, CustomStringConvertible {
|
||||
public let uid: sourcekitd_uid_t
|
||||
|
||||
init(uid: sourcekitd_uid_t) {
|
||||
self.uid = uid
|
||||
}
|
||||
|
||||
public init(string: String) {
|
||||
self.uid = sourcekitd_uid_get_from_cstr(string)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return String(cString: sourcekitd_uid_get_string_ptr(uid))
|
||||
}
|
||||
|
||||
public var asString: String {
|
||||
return String(cString: sourcekitd_uid_get_string_ptr(uid))
|
||||
}
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(uid)
|
||||
}
|
||||
}
|
||||
183
stdlib/tools/swift-lang/SwiftLang.swift
Normal file
183
stdlib/tools/swift-lang/SwiftLang.swift
Normal file
@@ -0,0 +1,183 @@
|
||||
//===--------------------- SwiftLang.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file provides Swift language support by invoking SourceKit internally.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum SourceKitdError: Error, CustomStringConvertible {
|
||||
case editorOpenError(message: String)
|
||||
case editorCloseError(message: String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .editorOpenError(let message):
|
||||
return "cannot open document: \(message)"
|
||||
case .editorCloseError(let message):
|
||||
return "cannot close document: \(message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Public APIs
|
||||
|
||||
public enum SwiftLang {
|
||||
/// Synchronously parses Swift source code into a syntax tree.
|
||||
///
|
||||
/// - Parameter url: A file URL pointing to a Swift source file.
|
||||
/// - Parameter format: The format to use for the returned syntax tree.
|
||||
/// - Returns: The syntax tree in the indicated format.
|
||||
/// - Throws: If SourceKit responds to the request with an error. This is
|
||||
/// usually a communication or configuration error, not a
|
||||
/// syntax error in the code being parsed.
|
||||
/// - Precondition: `url` must be a file URL.
|
||||
public static func parse<Tree>(
|
||||
contentsOf url: URL, into format: SyntaxTreeFormat<Tree>
|
||||
) throws -> Tree {
|
||||
precondition(url.isFileURL, "Can only parse files at file URLs")
|
||||
return try parse(SourceFile(path: url.path), into: format)
|
||||
}
|
||||
}
|
||||
|
||||
extension SwiftLang.SyntaxTreeFormat {
|
||||
/// Return the syntax tree serialized in JSON format. JSON is easy to inspect
|
||||
/// and test with but very inefficient to deserialize. Use it for testing and
|
||||
/// debugging.
|
||||
public static var json: SwiftLang.SyntaxTreeFormat<Data> {
|
||||
return jsonString.withTreeMapped { $0.data(using: .utf8)! }
|
||||
}
|
||||
|
||||
/// Return the syntax tree serialized as ByteTree. ByteTree is fast and
|
||||
/// compact but difficult to inspect or manipulate with textual tools.
|
||||
/// It's recommended in production.
|
||||
public static var byteTree: SwiftLang.SyntaxTreeFormat<Data> {
|
||||
return .init(kind: .kind_SyntaxTreeSerializationByteTree) { dict in
|
||||
dict.getData(syntaxTreeKey)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `SyntaxTreeFormat` instance which converts the tree of an
|
||||
/// existing format.
|
||||
///
|
||||
/// You can use this method to add new `SyntaxTreeFormat`s; simply declare a
|
||||
/// new static constant in an extension of `SyntaxTreeFormat` which maps one
|
||||
/// of the existing formats.
|
||||
///
|
||||
/// - Parameter transform: A function which converts `self`'s Tree type to
|
||||
/// the result type's Tree type.
|
||||
/// - Returns: A new format which creates a tree in `self`'s format, then
|
||||
/// applies `transform` to the tree to convert it.
|
||||
public func withTreeMapped<NewTree>(
|
||||
by transform: @escaping (Tree) throws -> NewTree
|
||||
) -> SwiftLang.SyntaxTreeFormat<NewTree> {
|
||||
return .init(kind: kind) { [makeTree] dict in
|
||||
try transform(makeTree(dict))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Deprecated APIs
|
||||
|
||||
extension SwiftLang {
|
||||
/// Parses the Swift file at the provided URL into a `Syntax` tree in Json
|
||||
/// serialization format by querying SourceKitd service. This function isn't
|
||||
/// thread safe.
|
||||
/// - Parameter path: The URL you wish to parse.
|
||||
/// - Returns: The syntax tree in Json format string.
|
||||
@available(swift, deprecated: 5.0, renamed: "parse(_:into:)")
|
||||
public static func parse(path: String) throws -> String {
|
||||
return try parse(SourceFile(path: path), into: .jsonString)
|
||||
}
|
||||
|
||||
/// Parses a given source buffer into a `Syntax` tree in Json serialization
|
||||
/// format by querying SourceKitd service. This function isn't thread safe.
|
||||
/// - Parameter source: The source buffer you wish to parse.
|
||||
/// - Returns: The syntax tree in Json format string.
|
||||
@available(swift, deprecated: 5.0, message: "use parse(_:into:) with a file instead")
|
||||
public static func parse(source: String) throws -> String {
|
||||
let content = SourceFile(
|
||||
name: "foo", contentKey: .key_SourceText, contentValue: source
|
||||
)
|
||||
return try parse(content, into: .jsonString)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Internals
|
||||
|
||||
extension SwiftLang {
|
||||
/// The format to serialize the syntax tree in.
|
||||
public struct SyntaxTreeFormat<Tree> {
|
||||
/// Value for EditorOpen's key_SyntaxTreeSerializationFormat key.
|
||||
fileprivate let kind: SourceKitdUID
|
||||
|
||||
/// Extracts the syntax tree from the response dictionary and converts it
|
||||
/// into a value of type Tree.
|
||||
fileprivate let makeTree: (SourceKitdResponse.Dictionary) throws -> Tree
|
||||
|
||||
/// Serialize the syntax tree into a JSON string. For backwards
|
||||
/// compatibility only.
|
||||
fileprivate static var jsonString: SyntaxTreeFormat<String> {
|
||||
return .init(kind: .kind_SyntaxTreeSerializationJSON) { dict in
|
||||
dict.getString(syntaxTreeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SwiftLang {
|
||||
fileprivate struct SourceFile {
|
||||
let name: String
|
||||
let contentKey: SourceKitdUID
|
||||
let contentValue: String
|
||||
}
|
||||
|
||||
/// Parses the SourceFile in question using the provided serialization format.
|
||||
fileprivate static func parse<Tree>(
|
||||
_ content: SourceFile, into format: SyntaxTreeFormat<Tree>
|
||||
) throws -> Tree {
|
||||
let Service = SourceKitdService()
|
||||
let Request = SourceKitdRequest(uid: .request_EditorOpen)
|
||||
|
||||
Request.addParameter(content.contentKey, value: content.contentValue)
|
||||
Request.addParameter(.key_Name, value: content.name)
|
||||
|
||||
Request.addParameter(.key_SyntaxTreeTransferMode,
|
||||
value: .kind_SyntaxTreeFull)
|
||||
Request.addParameter(.key_SyntaxTreeSerializationFormat,
|
||||
value: format.kind)
|
||||
Request.addParameter(.key_EnableSyntaxMap, value: 0)
|
||||
Request.addParameter(.key_EnableStructure, value: 0)
|
||||
Request.addParameter(.key_SyntacticOnly, value: 1)
|
||||
|
||||
// FIXME: SourceKitd error handling.
|
||||
let Resp = Service.sendSyn(request: Request)
|
||||
if Resp.isError {
|
||||
throw SourceKitdError.editorOpenError(message: Resp.description)
|
||||
}
|
||||
|
||||
let CloseReq = SourceKitdRequest(uid: .request_EditorClose)
|
||||
CloseReq.addParameter(.key_Name, value: content.name)
|
||||
let CloseResp = Service.sendSyn(request: CloseReq)
|
||||
if CloseResp.isError {
|
||||
throw SourceKitdError.editorCloseError(message: CloseResp.description)
|
||||
}
|
||||
return try format.makeTree(Resp.value)
|
||||
}
|
||||
}
|
||||
|
||||
extension SwiftLang.SourceFile {
|
||||
init(path: String) {
|
||||
self.init(name: path, contentKey: .key_SourceFile, contentValue: path)
|
||||
}
|
||||
}
|
||||
|
||||
private let syntaxTreeKey = SourceKitdUID.key_SerializedSyntaxTree
|
||||
37
stdlib/tools/swift-lang/UIDs.swift.gyb
Normal file
37
stdlib/tools/swift-lang/UIDs.swift.gyb
Normal file
@@ -0,0 +1,37 @@
|
||||
%{
|
||||
# -*- mode: Swift -*-
|
||||
from gyb_sourcekit_support.UIDs import UID_KEYS
|
||||
from gyb_sourcekit_support.UIDs import UID_REQUESTS
|
||||
from gyb_sourcekit_support.UIDs import UID_KINDS
|
||||
# Ignore the following admonition; it applies to the resulting .swift file only
|
||||
}%
|
||||
//// Automatically Generated From UIDs.swift.gyb.
|
||||
//// Do Not Edit Directly!
|
||||
//===--------------- UIDs.swift - Sourcekitd UIDs in 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
extension SourceKitdUID {
|
||||
% for K in UID_KEYS:
|
||||
public static let key_${K.internalName} = SourceKitdUID(string: "${K.externalName}")
|
||||
% end
|
||||
|
||||
% for R in UID_REQUESTS:
|
||||
public static let request_${R.internalName} = SourceKitdUID(string: "${R.externalName}")
|
||||
% end
|
||||
|
||||
% for K in UID_KINDS:
|
||||
public static let kind_${K.internalName} = SourceKitdUID(string: "${K.externalName}")
|
||||
% end
|
||||
|
||||
public static let compilerCrashedNotification = SourceKitdUID(string: "notification.toolchain-compiler-crashed")
|
||||
public static let source_notification_editor_documentupdate = SourceKitdUID(string: "source.notification.editor.documentupdate")
|
||||
}
|
||||
Reference in New Issue
Block a user