mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Re-apply "SwiftSyntax: Teach SwiftSyntax to use SourceKitd to serialize syntax trees. (#14424)" (#14465)
This commit is contained in:
@@ -11,6 +11,8 @@ set_property(GLOBAL PROPERTY JOB_POOLS local_jobs=${localhost_logical_cores})
|
||||
# Put linking in that category
|
||||
set_property(GLOBAL PROPERTY JOB_POOL_LINK local_jobs)
|
||||
|
||||
ENABLE_LANGUAGE(C)
|
||||
|
||||
# First include general CMake utilities.
|
||||
include(SwiftUtils)
|
||||
include(CheckSymbolExists)
|
||||
@@ -748,10 +750,10 @@ if(swift_build_android AND NOT "${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
|
||||
|
||||
set(SWIFT_ANDROID_PREBUILT_PATH
|
||||
"${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-${SWIFT_ANDROID_NDK_GCC_VERSION}/prebuilt/${_swift_android_prebuilt_suffix}")
|
||||
|
||||
|
||||
# Resolve the correct linker based on the file name of CMAKE_LINKER (being 'ld' or 'ld.gold' the options)
|
||||
get_filename_component(SWIFT_ANDROID_LINKER_NAME "${CMAKE_LINKER}" NAME)
|
||||
set(SWIFT_SDK_ANDROID_ARCH_armv7_LINKER
|
||||
set(SWIFT_SDK_ANDROID_ARCH_armv7_LINKER
|
||||
"${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-${SWIFT_ANDROID_NDK_GCC_VERSION}/prebuilt/${_swift_android_prebuilt_suffix}/bin/arm-linux-androideabi-${SWIFT_ANDROID_LINKER_NAME}")
|
||||
|
||||
configure_sdk_unix(ANDROID "Android" "android" "android" "armv7" "armv7-none-linux-androideabi" "${SWIFT_ANDROID_SDK_PATH}")
|
||||
@@ -879,7 +881,7 @@ endif()
|
||||
###############
|
||||
#
|
||||
# We have to include stdlib/ before tools/.
|
||||
# Do not move add_subdirectory(stdlib) after add_subdirectory(tools)!
|
||||
# Do not move add_subdirectory(stdlib) after add_subdirectory(tools)!
|
||||
#
|
||||
# We must include stdlib/ before tools/ because stdlib/CMakeLists.txt
|
||||
# declares the swift-stdlib-* set of targets. These targets will then
|
||||
@@ -898,7 +900,7 @@ add_subdirectory(stdlib)
|
||||
if(SWIFT_INCLUDE_TOOLS)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
|
||||
|
||||
# Always include this after including stdlib/!
|
||||
# Refer to the large comment above the add_subdirectory(stdlib) call.
|
||||
# https://bugs.swift.org/browse/SR-5975
|
||||
|
||||
@@ -255,7 +255,7 @@ function(_add_variant_c_compile_flags)
|
||||
else()
|
||||
list(APPEND result "-DNDEBUG")
|
||||
endif()
|
||||
|
||||
|
||||
if(SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS)
|
||||
list(APPEND result "-DSWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS")
|
||||
endif()
|
||||
@@ -320,7 +320,7 @@ function(_add_variant_swift_compile_flags
|
||||
if (SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS)
|
||||
list(APPEND result "-Xfrontend" "-enable-guaranteed-normal-arguments")
|
||||
endif()
|
||||
|
||||
|
||||
if(SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS)
|
||||
list(APPEND result "-D" "SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS")
|
||||
endif()
|
||||
@@ -1605,7 +1605,7 @@ function(add_swift_library name)
|
||||
if(SWIFTLIB_IS_SDK_OVERLAY)
|
||||
list(APPEND swiftlib_swift_compile_flags_all "-Fsystem" "${SWIFT_SDK_${sdk}_PATH}/System/Library/PrivateFrameworks/")
|
||||
endif()
|
||||
|
||||
|
||||
if("${sdk}" STREQUAL "IOS_SIMULATOR")
|
||||
if("${name}" STREQUAL "swiftMediaPlayer")
|
||||
message("DISABLING AUTOLINK FOR swiftMediaPlayer")
|
||||
@@ -1854,7 +1854,7 @@ function(add_swift_library name)
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
RUNTIME DESTINATION bin)
|
||||
swift_is_installing_component(dev is_installing)
|
||||
|
||||
|
||||
if(NOT is_installing)
|
||||
set_property(GLOBAL APPEND PROPERTY SWIFT_BUILDTREE_EXPORTS ${name})
|
||||
else()
|
||||
@@ -2177,7 +2177,7 @@ function(add_swift_host_tool executable)
|
||||
|
||||
swift_is_installing_component(${ADDSWIFTHOSTTOOL_SWIFT_COMPONENT}
|
||||
is_installing)
|
||||
|
||||
|
||||
if(NOT is_installing)
|
||||
set_property(GLOBAL APPEND PROPERTY SWIFT_BUILDTREE_EXPORTS ${executable})
|
||||
else()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import StdlibUnittest
|
||||
import Foundation
|
||||
import SwiftSyntax
|
||||
import SwiftSourceKit
|
||||
|
||||
func getInput(_ file: String) -> URL {
|
||||
var result = URL(fileURLWithPath: #file)
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: OS=macosx
|
||||
// REQUIRES: objc_interop
|
||||
// REQUIRES: rdar36740859
|
||||
|
||||
import Foundation
|
||||
import StdlibUnittest
|
||||
import SwiftSyntax
|
||||
import SwiftSourceKit
|
||||
|
||||
var ParseFile = TestSuite("ParseFile")
|
||||
|
||||
@@ -31,7 +31,8 @@ ParseFile.test("ParseSingleFile") {
|
||||
let currentFile = URL(fileURLWithPath: #file)
|
||||
expectDoesNotThrow({
|
||||
let currentFileContents = try String(contentsOf: currentFile)
|
||||
let parsed = try SourceFileSyntax.parse(currentFile)
|
||||
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(try
|
||||
SourceKitdService.encodeSourceFileSyntax(currentFile))
|
||||
expectEqual("\(parsed)", currentFileContents)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
// REQUIRES: OS=macosx
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
// FIXME: This test fails occassionally in CI with invalid json.
|
||||
// REQUIRES: disabled
|
||||
|
||||
import StdlibUnittest
|
||||
import Foundation
|
||||
import SwiftSyntax
|
||||
import SwiftSourceKit
|
||||
|
||||
func getInput(_ file: String) -> URL {
|
||||
var result = URL(fileURLWithPath: #file)
|
||||
@@ -29,7 +27,8 @@ VisitorTests.test("Basic") {
|
||||
}
|
||||
}
|
||||
expectDoesNotThrow({
|
||||
let parsed = try SourceFileSyntax.parse(getInput("visitor.swift"))
|
||||
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(try
|
||||
SourceKitdService.encodeSourceFileSyntax(getInput("visitor.swift")))
|
||||
let counter = FuncCounter()
|
||||
let hashBefore = parsed.hashValue
|
||||
counter.visit(parsed)
|
||||
|
||||
@@ -286,6 +286,7 @@ else:
|
||||
test_resource_dir = os.path.join(config.swift_lib_dir, 'swift')
|
||||
resource_dir_opt = ""
|
||||
stdlib_resource_dir_opt = resource_dir_opt
|
||||
sourcekitd_framework_dir = config.swift_lib_dir
|
||||
lit_config.note('Using resource dir: ' + test_resource_dir)
|
||||
|
||||
# Parse the variant triple.
|
||||
@@ -670,12 +671,13 @@ if run_vendor == 'apple':
|
||||
(run_cpu, run_os, run_vers, clang_mcp_opt))
|
||||
|
||||
config.target_build_swift = (
|
||||
"%s %s %s -F %s -Xlinker -rpath -Xlinker %s %s %s %s %s"
|
||||
"%s %s %s -F %s -Xlinker -rpath -Xlinker %s %s %s %s %s -F %s -Xlinker -rpath -Xlinker %s"
|
||||
% (xcrun_prefix, config.swiftc, target_options,
|
||||
extra_frameworks_dir, extra_frameworks_dir,
|
||||
sdk_overlay_linker_opt, config.swift_test_options,
|
||||
config.swift_driver_test_options,
|
||||
swift_execution_tests_extra_flags))
|
||||
swift_execution_tests_extra_flags, sourcekitd_framework_dir,
|
||||
sourcekitd_framework_dir))
|
||||
config.target_run = ""
|
||||
|
||||
if 'interpret' in lit_config.params:
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
include(CheckIncludeFiles)
|
||||
check_include_files("xpc/xpc.h" HAVE_XPC_H)
|
||||
|
||||
swift_is_installing_component(sourcekit-inproc SOURCEKIT_INSTALLING_INPROC)
|
||||
|
||||
if(HAVE_XPC_H AND SWIFT_BUILD_SOURCEKIT AND NOT SOURCEKIT_INSTALLING_INPROC)
|
||||
set(BUILD_SOURCEKIT_XPC_SERVICE TRUE)
|
||||
else()
|
||||
set(BUILD_SOURCEKIT_XPC_SERVICE FALSE)
|
||||
endif()
|
||||
|
||||
# Add generated libSyntax headers to global dependencies.
|
||||
list(APPEND LLVM_COMMON_DEPENDS swift-syntax-generated-headers)
|
||||
|
||||
@@ -16,10 +27,18 @@ add_swift_tool_subdirectory(swift-api-digester)
|
||||
add_swift_tool_subdirectory(swift-syntax-test)
|
||||
add_swift_tool_subdirectory(swift-refactor)
|
||||
|
||||
if(SWIFT_BUILD_SOURCEKIT)
|
||||
add_swift_tool_subdirectory(SourceKit)
|
||||
if(SWIFT_BUILD_STDLIB AND SWIFT_BUILD_SDK_OVERLAY)
|
||||
set(BUILD_FOUNDATION TRUE)
|
||||
else()
|
||||
set(BUILD_FOUNDATION FALSE)
|
||||
endif()
|
||||
|
||||
if(SWIFT_BUILD_SOURCEKIT)
|
||||
add_swift_tool_subdirectory(SourceKit)
|
||||
if(BUILD_SOURCEKIT_XPC_SERVICE AND BUILD_FOUNDATION)
|
||||
add_subdirectory(SwiftSourceKitClient)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(SWIFT_HOST_VARIANT STREQUAL "macosx")
|
||||
# Only build Darwin-specific tools when deploying to OS X.
|
||||
@@ -28,7 +47,7 @@ if(SWIFT_HOST_VARIANT STREQUAL "macosx")
|
||||
# SwiftSyntax depends on both the standard library (because it's a
|
||||
# Swift module), and the SDK overlays (because it depends on Foundation).
|
||||
# Ensure we only build SwiftSyntax when we're building both.
|
||||
if(SWIFT_BUILD_STDLIB AND SWIFT_BUILD_SDK_OVERLAY)
|
||||
if(BUILD_FOUNDATION)
|
||||
add_subdirectory(SwiftSyntax)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -24,8 +24,6 @@ configure_file(
|
||||
set(SOURCEKIT_DEPLOYMENT_OS "${SWIFT_HOST_VARIANT}")
|
||||
set(SOURCEKIT_DEPLOYMENT_TARGET "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_DEPLOYMENT_VERSION}")
|
||||
|
||||
swift_is_installing_component(sourcekit-inproc SOURCEKIT_INSTALLING_INPROC)
|
||||
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin" AND NOT CMAKE_CROSSCOMPILING)
|
||||
set(CMAKE_OSX_SYSROOT "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_PATH}")
|
||||
set(CMAKE_OSX_ARCHITECTURES "${SWIFT_HOST_VARIANT_ARCH}")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
add_subdirectory(InProc)
|
||||
if (HAVE_XPC_H)
|
||||
if(HAVE_XPC_H)
|
||||
add_subdirectory(XPC)
|
||||
endif()
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
include(CheckIncludeFiles)
|
||||
|
||||
check_include_files("xpc/xpc.h" HAVE_XPC_H)
|
||||
|
||||
# If we were going to build for APPLE but don't have XPC, just build inproc.
|
||||
if(APPLE AND NOT HAVE_XPC_H)
|
||||
set(SWIFT_SOURCEKIT_USE_INPROC_LIBRARY TRUE)
|
||||
|
||||
17
tools/SwiftSourceKitClient/CMakeLists.txt
Normal file
17
tools/SwiftSourceKitClient/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
set(EXTRA_COMPILE_FLAGS "-F" "${SWIFT_LIBRARY_OUTPUT_INTDIR}")
|
||||
set(EXTRA_LINKER_FLAGS "-Xlinker" "-rpath" "-Xlinker" "${SWIFT_LIBRARY_OUTPUT_INTDIR}"
|
||||
"-Xlinker" "-F" "-Xlinker" "${SWIFT_LIBRARY_OUTPUT_INTDIR}")
|
||||
|
||||
add_swift_library(swiftSwiftSourceKit SHARED
|
||||
SourceKitdClient.swift
|
||||
SourceKitdRequest.swift
|
||||
SourceKitdResponse.swift
|
||||
SourceKitdUID.swift
|
||||
|
||||
DEPENDS SourceKitService
|
||||
SWIFT_COMPILE_FLAGS ${EXTRA_COMPILE_FLAGS}
|
||||
LINK_FLAGS ${EXTRA_LINKER_FLAGS}
|
||||
SWIFT_MODULE_DEPENDS Foundation
|
||||
INSTALL_IN_COMPONENT swift-syntax
|
||||
TARGET_SDKS OSX
|
||||
IS_STDLIB)
|
||||
48
tools/SwiftSourceKitClient/SourceKitdClient.swift
Normal file
48
tools/SwiftSourceKitClient/SourceKitdClient.swift
Normal file
@@ -0,0 +1,48 @@
|
||||
//===--------------------- 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
|
||||
import Foundation
|
||||
|
||||
public class SourceKitdService {
|
||||
|
||||
public init() {
|
||||
sourcekitd_initialize()
|
||||
}
|
||||
deinit {
|
||||
sourcekitd_shutdown()
|
||||
}
|
||||
public func sendSyn(request: SourceKitdRequest) -> SourceKitdResponse {
|
||||
return SourceKitdResponse(resp: sourcekitd_send_request_sync(request.rawRequest))
|
||||
}
|
||||
}
|
||||
|
||||
extension SourceKitdService {
|
||||
/// Parses the Swift file at the provided URL into a `Syntax` tree in Json
|
||||
/// serialization format by querying SourceKitd service.
|
||||
/// - Parameter url: The URL you wish to parse.
|
||||
/// - Returns: The syntax tree in Json format string.
|
||||
public static func encodeSourceFileSyntax(_ url: URL) throws -> String {
|
||||
let Service = SourceKitdService()
|
||||
let Request = SourceKitdRequest(uid: .source_request_editor_open)
|
||||
let Path = url.path
|
||||
Request.addParameter(.key_sourcefile, value: Path)
|
||||
Request.addParameter(.key_name, value: Path)
|
||||
Request.addParameter(.key_enable_syntax_tree, value: 1)
|
||||
|
||||
// FIXME: SourceKitd error handling.
|
||||
let Resp = Service.sendSyn(request: Request)
|
||||
return Resp.value.getString(.key_serialized_syntax_tree)
|
||||
}
|
||||
}
|
||||
154
tools/SwiftSourceKitClient/SourceKitdRequest.swift
Normal file
154
tools/SwiftSourceKitClient/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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
258
tools/SwiftSourceKitClient/SourceKitdResponse.swift
Normal file
258
tools/SwiftSourceKitClient/SourceKitdResponse.swift
Normal file
@@ -0,0 +1,258 @@
|
||||
//===--------------------- 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 {
|
||||
private let dict: sourcekitd_variant_t
|
||||
|
||||
public init(dict: sourcekitd_variant_t) {
|
||||
assert(sourcekitd_variant_get_type(dict).rawValue ==
|
||||
SOURCEKITD_VARIANT_TYPE_DICTIONARY.rawValue)
|
||||
self.dict = dict
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
public func getDictionary(_ key: SourceKitdUID) -> Dictionary {
|
||||
let value = sourcekitd_variant_dictionary_get_value(dict, key.uid)
|
||||
return Dictionary(dict: value)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return dict.description
|
||||
}
|
||||
|
||||
public var customMirror: Mirror {
|
||||
return Mirror(self, children: [:])
|
||||
}
|
||||
}
|
||||
|
||||
public struct Array: CustomStringConvertible {
|
||||
private let arr: sourcekitd_variant_t
|
||||
|
||||
public var count: Int {
|
||||
let count = sourcekitd_variant_array_get_count(arr)
|
||||
return Int(count)
|
||||
}
|
||||
|
||||
public init(arr: sourcekitd_variant_t) {
|
||||
assert(sourcekitd_variant_get_type(arr).rawValue ==
|
||||
SOURCEKITD_VARIANT_TYPE_ARRAY.rawValue)
|
||||
self.arr = arr
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
public func getDictionary(_ index: Int) -> Dictionary {
|
||||
let value = sourcekitd_variant_array_get_value(arr, index)
|
||||
return Dictionary(dict: value)
|
||||
}
|
||||
|
||||
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.
|
||||
withoutActuallyEscaping(applier) { escapingApplier in
|
||||
_ = sourcekitd_variant_array_apply(arr) { (index, elem) -> Bool in
|
||||
return escapingApplier(Int(index), Variant(val: elem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return arr.description
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public struct Variant: CustomStringConvertible {
|
||||
private let val: sourcekitd_variant_t
|
||||
|
||||
fileprivate init(val: sourcekitd_variant_t) {
|
||||
self.val = val
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
public func getDictionary() -> Dictionary {
|
||||
return Dictionary(dict: val)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
/// 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 NSString(bytes: ptr, length: length,
|
||||
encoding: String.Encoding.utf8.rawValue) as String?
|
||||
}
|
||||
52
tools/SwiftSourceKitClient/SourceKitdUID.swift
Normal file
52
tools/SwiftSourceKitClient/SourceKitdUID.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
//===------------------------ 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 var hashValue: Int {
|
||||
return uid.hashValue
|
||||
}
|
||||
}
|
||||
|
||||
extension SourceKitdUID {
|
||||
public static let key_request = SourceKitdUID(string: "key.request")
|
||||
public static let key_compilerargs = SourceKitdUID(string: "key.compilerargs")
|
||||
public static let key_notification = SourceKitdUID(string: "key.notification")
|
||||
public static let key_name = SourceKitdUID(string: "key.name")
|
||||
public static let key_enable_syntax_tree = SourceKitdUID(string: "key.enablesyntaxtree")
|
||||
public static let key_serialized_syntax_tree = SourceKitdUID(string: "key.serialized_syntax_tree")
|
||||
public static let key_sourcefile = SourceKitdUID(string: "key.sourcefile")
|
||||
public static let compilerCrashedNotification = SourceKitdUID(string: "notification.toolchain-compiler-crashed")
|
||||
public static let source_request_editor_open = SourceKitdUID(string: "source.request.editor.open")
|
||||
public static let source_notification_editor_documentupdate = SourceKitdUID(string: "source.notification.editor.documentupdate")
|
||||
}
|
||||
Reference in New Issue
Block a user