Skip to content

Add a SourceKit plugin to handle code completion requests #1906

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 18 commits into from
Jan 15, 2025
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
1 change: 1 addition & 0 deletions Documentation/Environment Variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ The following environment variables can be used to control some behavior in Sour
- `SOURCEKIT_LSP_KEEP_TEST_SCRATCH_DIR`: Does not delete the temporary files created during test execution. Allows inspection of the test projects after the test finishes.
- `SOURCEKIT_LSP_TEST_MODULE_CACHE`: Specifies where tests should store their shared module cache. Defaults to writing the module cache to a temporary directory. Intended so that CI systems can clean the module cache directory after running.
- `SOURCEKIT_LSP_TEST_TIMEOUT`: Override the timeout duration for tests, in seconds.
- `SOURCEKIT_LSP_TEST_PLUGIN_PATHS`: Load the SourceKit plugins from this path instead of relative to the package's build folder.
176 changes: 174 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ var products: [Product] = [
.executable(name: "sourcekit-lsp", targets: ["sourcekit-lsp"]),
.library(name: "_SourceKitLSP", targets: ["SourceKitLSP"]),
.library(name: "LSPBindings", targets: ["LanguageServerProtocol", "LanguageServerProtocolJSONRPC"]),
.library(name: "SwiftSourceKitPlugin", type: .dynamic, targets: ["SwiftSourceKitPlugin"]),
.library(name: "SwiftSourceKitClientPlugin", type: .dynamic, targets: ["SwiftSourceKitClientPlugin"]),
]

var targets: [Target] = [
Expand Down Expand Up @@ -109,6 +111,45 @@ var targets: [Target] = [
dependencies: []
),

.target(
name: "CCompletionScoring",
dependencies: []
),

// MARK: CompletionScoring

.target(
name: "CompletionScoring",
dependencies: ["CCompletionScoring"],
swiftSettings: globalSwiftSettings
),

.target(
name: "CompletionScoringForPlugin",
dependencies: ["CCompletionScoring"],
swiftSettings: globalSwiftSettings
),

.testTarget(
name: "CompletionScoringTests",
dependencies: ["CompletionScoring", "CompletionScoringTestSupport", "SwiftExtensions"],
swiftSettings: globalSwiftSettings
),

.testTarget(
name: "CompletionScoringPerfTests",
dependencies: ["CompletionScoring", "CompletionScoringTestSupport", "SwiftExtensions"],
swiftSettings: globalSwiftSettings
),

// MARK: CompletionScoringTestSupport

.target(
name: "CompletionScoringTestSupport",
dependencies: ["CompletionScoring", "SwiftExtensions"],
swiftSettings: globalSwiftSettings
),

// MARK: CSKTestSupport

.target(
Expand Down Expand Up @@ -273,6 +314,21 @@ var targets: [Target] = [
swiftSettings: globalSwiftSettings + lspLoggingSwiftSettings
),

.target(
name: "SKLoggingForPlugin",
dependencies: [
"SwiftExtensionsForPlugin"
],
exclude: ["CMakeLists.txt"],
swiftSettings: globalSwiftSettings + lspLoggingSwiftSettings + [
// We can't depend on swift-crypto in the plugin because we can't module-alias it due to https://github.com/swiftlang/swift-package-manager/issues/8119
.define("NO_CRYPTO_DEPENDENCY"),
.unsafeFlags([
"-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin",
]),
]
),

.testTarget(
name: "SKLoggingTests",
dependencies: [
Expand Down Expand Up @@ -308,6 +364,21 @@ var targets: [Target] = [
swiftSettings: globalSwiftSettings
),

.target(
name: "SKUtilitiesForPlugin",
dependencies: [
"SKLoggingForPlugin",
"SwiftExtensionsForPlugin",
],
exclude: ["CMakeLists.txt"],
swiftSettings: globalSwiftSettings + [
.unsafeFlags([
"-module-alias", "SKLogging=SKLoggingForPlugin",
"-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin",
])
]
),

.testTarget(
name: "SKUtilitiesTests",
dependencies: [
Expand Down Expand Up @@ -354,6 +425,22 @@ var targets: [Target] = [
swiftSettings: globalSwiftSettings
),

.target(
name: "SourceKitDForPlugin",
dependencies: [
"Csourcekitd",
"SKLoggingForPlugin",
"SwiftExtensionsForPlugin",
],
exclude: ["CMakeLists.txt", "sourcekitd_uids.swift.gyb"],
swiftSettings: globalSwiftSettings + [
.unsafeFlags([
"-module-alias", "SKLogging=SKLoggingForPlugin",
"-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin",
])
]
),

.testTarget(
name: "SourceKitDTests",
dependencies: [
Expand Down Expand Up @@ -429,6 +516,13 @@ var targets: [Target] = [
swiftSettings: globalSwiftSettings
),

.target(
name: "SwiftExtensionsForPlugin",
dependencies: ["CAtomics"],
exclude: ["CMakeLists.txt"],
swiftSettings: globalSwiftSettings
),

.testTarget(
name: "SwiftExtensionsTests",
dependencies: [
Expand All @@ -439,6 +533,84 @@ var targets: [Target] = [
swiftSettings: globalSwiftSettings
),

// MARK: SwiftSourceKitClientPlugin

.target(
name: "SwiftSourceKitClientPlugin",
dependencies: [
"Csourcekitd",
"SourceKitDForPlugin",
"SwiftExtensionsForPlugin",
"SwiftSourceKitPluginCommon",
],
swiftSettings: globalSwiftSettings + [
.unsafeFlags([
"-module-alias", "SourceKitD=SourceKitDForPlugin",
"-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin",
])
],
linkerSettings: sourcekitLSPLinkSettings
),

// MARK: SwiftSourceKitPluginCommon

.target(
name: "SwiftSourceKitPluginCommon",
dependencies: [
"Csourcekitd",
"SourceKitDForPlugin",
"SwiftExtensionsForPlugin",
"SKLoggingForPlugin",
],
swiftSettings: globalSwiftSettings + [
.unsafeFlags([
"-module-alias", "SourceKitD=SourceKitDForPlugin",
"-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin",
"-module-alias", "SKLogging=SKLoggingForPlugin",
])
]
),

// MARK: SwiftSourceKitPlugin

.target(
name: "SwiftSourceKitPlugin",
dependencies: [
"Csourcekitd",
"CompletionScoringForPlugin",
"SKUtilitiesForPlugin",
"SKLoggingForPlugin",
"SourceKitDForPlugin",
"SwiftSourceKitPluginCommon",
"SwiftExtensionsForPlugin",
],
swiftSettings: globalSwiftSettings + [
.unsafeFlags([
"-module-alias", "CompletionScoring=CompletionScoringForPlugin",
"-module-alias", "SKUtilities=SKUtilitiesForPlugin",
"-module-alias", "SourceKitD=SourceKitDForPlugin",
"-module-alias", "SKLogging=SKLoggingForPlugin",
"-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin",
])
],
linkerSettings: sourcekitLSPLinkSettings
),

.testTarget(
name: "SwiftSourceKitPluginTests",
dependencies: [
"BuildSystemIntegration",
"CompletionScoring",
"Csourcekitd",
"LanguageServerProtocol",
"SKTestSupport",
"SourceKitD",
"SwiftExtensions",
"ToolchainRegistry",
],
swiftSettings: globalSwiftSettings
),

// MARK: ToolchainRegistry

.target(
Expand Down Expand Up @@ -494,11 +666,11 @@ var targets: [Target] = [
if buildOnlyTests {
products = []
targets = targets.compactMap { target in
guard target.isTest || target.name == "SKTestSupport" else {
guard target.isTest || target.name.contains("TestSupport") else {
return nil
}
target.dependencies = target.dependencies.filter { dependency in
if case .byNameItem(name: "SKTestSupport", _) = dependency {
if case .byNameItem(name: let name, _) = dependency, name.contains("TestSupport") {
return true
}
return false
Expand Down
2 changes: 2 additions & 0 deletions Sources/CCompletionScoring/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_library(CCompletionScoring INTERFACE)
target_include_directories(CCompletionScoring INTERFACE "include")
43 changes: 43 additions & 0 deletions Sources/CCompletionScoring/include/CCompletionScoring.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 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
//
//===----------------------------------------------------------------------===//

#ifndef SOURCEKITLSP_CCOMPLETIONSCORING_H
#define SOURCEKITLSP_CCOMPLETIONSCORING_H

#define _GNU_SOURCE
#include <string.h>

static inline void *sourcekitlsp_memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len) {
#if defined(_WIN32) && !defined(__CYGWIN__)
// memmem is not available on Windows
if (!haystack || haystack_len == 0) {
return NULL;
}
if (!needle || needle_len == 0) {
return NULL;
}
if (needle_len > haystack_len) {
return NULL;
}

for (size_t offset = 0; offset <= haystack_len - needle_len; ++offset) {
if (memcmp(haystack + offset, needle, needle_len) == 0) {
return (void *)haystack + offset;
}
}
return NULL;
#else
return memmem(haystack, haystack_len, needle, needle_len);
#endif
}

#endif // SOURCEKITLSP_CCOMPLETIONSCORING_H
4 changes: 4 additions & 0 deletions Sources/CCompletionScoring/include/module.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module CCompletionScoring {
header "CCompletionScoring.h"
export *
}
5 changes: 5 additions & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ add_compile_options("$<$<COMPILE_LANGUAGE:Swift>:SHELL:-swift-version 6>")
add_subdirectory(BuildServerProtocol)
add_subdirectory(BuildSystemIntegration)
add_subdirectory(CAtomics)
add_subdirectory(CCompletionScoring)
add_subdirectory(CompletionScoring)
add_subdirectory(Csourcekitd)
add_subdirectory(Diagnose)
add_subdirectory(InProcessClient)
Expand All @@ -18,5 +20,8 @@ add_subdirectory(SourceKitLSP)
add_subdirectory(SourceKitD)
add_subdirectory(sourcekit-lsp)
add_subdirectory(SwiftExtensions)
add_subdirectory(SwiftSourceKitClientPlugin)
add_subdirectory(SwiftSourceKitPlugin)
add_subdirectory(SwiftSourceKitPluginCommon)
add_subdirectory(ToolchainRegistry)
add_subdirectory(TSCExtensions)
51 changes: 51 additions & 0 deletions Sources/CompletionScoring/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
set(sources
Semantics/SemanticClassification.swift
Semantics/CompletionScore.swift
Semantics/Components
Semantics/Components/TypeCompatibility.swift
Semantics/Components/StructuralProximity.swift
Semantics/Components/Flair.swift
Semantics/Components/CompletionKind.swift
Semantics/Components/Popularity.swift
Semantics/Components/ScopeProximity.swift
Semantics/Components/Availability.swift
Semantics/Components/SynchronicityCompatibility.swift
Semantics/Components/PopularityIndex.swift
Semantics/Components/ModuleProximity.swift
Semantics/Components/PopularityTable.swift
Utilities/UnsafeStackAllocator.swift
Utilities/Serialization
Utilities/Serialization/BinaryCodable.swift
Utilities/Serialization/BinaryEncoder.swift
Utilities/Serialization/BinaryDecoder.swift
Utilities/Serialization/Conformances
Utilities/Serialization/Conformances/Dictionary+BinaryCodable.swift
Utilities/Serialization/Conformances/OptionSet+BinaryCodable.swift
Utilities/Serialization/Conformances/Optional+BinaryCodable.swift
Utilities/Serialization/Conformances/Scalars+BinaryCodable.swift
Utilities/Serialization/Conformances/String+BinaryCodable.swift
Utilities/Serialization/Conformances/Array+BinaryCodable.swift
Utilities/SwiftExtensions.swift
Utilities/SelectTopK.swift
Utilities/UnsafeArray.swift
Text/CandidateBatch.swift
Text/MatchCollator.Match.swift
Text/UTF8Byte.swift
Text/MatchCollator.swift
Text/InfluencingIdentifiers.swift
Text/MatchCollator.Selection.swift
Text/ScoredMatchSelector.swift
Text/RejectionFilter.swift
Text/Pattern.swift)

add_library(CompletionScoring STATIC ${sources})
set_target_properties(CompletionScoring PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
target_link_libraries(CompletionScoring PUBLIC
CCompletionScoring)

add_library(CompletionScoringForPlugin STATIC ${sources})
set_target_properties(CompletionScoringForPlugin PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
target_link_libraries(CompletionScoringForPlugin PUBLIC
CCompletionScoring)
Loading