Skip to content

Commit 970b215

Browse files
committed
Allow VS Code to recognise files with "sourcekit-lsp" scheme and pass it to SourceKitLSP inorder to provide Semantic Functionality (#990)
1 parent 0747917 commit 970b215

File tree

5 files changed

+85
-8
lines changed

5 files changed

+85
-8
lines changed

src/WorkspaceContext.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,10 @@ export class WorkspaceContext implements vscode.Disposable {
518518
async focusUri(uri?: vscode.Uri) {
519519
this.currentDocument = uri ?? null;
520520
this.updateContextKeysForFile();
521-
if (this.currentDocument?.scheme === "file") {
521+
if (
522+
this.currentDocument?.scheme === "file" ||
523+
this.currentDocument?.scheme === "sourcekit-lsp"
524+
) {
522525
await this.focusPackageUri(this.currentDocument);
523526
}
524527
}

src/sourcekit-lsp/LanguageClientManager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { LSPLogger, LSPOutputChannel } from "./LSPOutputChannel";
3030
import { SwiftOutputChannel } from "../ui/SwiftOutputChannel";
3131
import { promptForDiagnostics } from "../commands/captureDiagnostics";
3232
import { activateGetReferenceDocument } from "./getReferenceDocument";
33+
import { uriConverters } from "./uriConverters";
3334

3435
interface SourceKitLogMessageParams extends langclient.LogMessageParams {
3536
logName?: string;
@@ -44,6 +45,7 @@ export class LanguageClientManager {
4445

4546
// document selector used by language client
4647
static appleLangDocumentSelector = [
48+
{ scheme: "sourcekit-lsp", language: "swift" },
4749
{ scheme: "file", language: "swift" },
4850
{ scheme: "untitled", language: "swift" },
4951
{ scheme: "file", language: "objective-c" },
@@ -573,6 +575,7 @@ export class LanguageClientManager {
573575
};
574576
})(),
575577
},
578+
uriConverters: uriConverters,
576579
errorHandler,
577580
// Avoid attempting to reinitialize multiple times. If we fail to initialize
578581
// we aren't doing anything different the second time and so will fail again.

src/sourcekit-lsp/getReferenceDocument.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function activateGetReferenceDocument(client: langclient.LanguageClient):
2222
{
2323
provideTextDocumentContent: async (uri, token) => {
2424
const params: GetReferenceDocumentParams = {
25-
uri: uri.toString(true),
25+
uri: client.code2ProtocolConverter.asUri(uri),
2626
};
2727

2828
const result = await client.sendRequest(GetReferenceDocumentRequest, params, token);

src/sourcekit-lsp/peekDocuments.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ export function activatePeekDocuments(client: langclient.LanguageClient): vscode
2121
PeekDocumentsRequest.method,
2222
async (params: PeekDocumentsParams) => {
2323
const locations = params.locations.map(uri => {
24-
const url = new URL(uri);
2524
const location = new vscode.Location(
26-
vscode.Uri.parse(url.href, true),
25+
client.protocol2CodeConverter.asUri(uri),
2726
new vscode.Position(0, 0)
2827
);
2928

@@ -32,10 +31,7 @@ export function activatePeekDocuments(client: langclient.LanguageClient): vscode
3231

3332
await vscode.commands.executeCommand(
3433
"editor.action.peekLocations",
35-
vscode.Uri.from({
36-
scheme: "file",
37-
path: new URL(params.uri).pathname,
38-
}),
34+
client.protocol2CodeConverter.asUri(params.uri),
3935
new vscode.Position(params.position.line, params.position.character),
4036
locations,
4137
"peek"

src/sourcekit-lsp/uriConverters.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import * as vscode from "vscode";
16+
17+
export const uriConverters = {
18+
code2Protocol: (value: vscode.Uri) => {
19+
if (value.scheme === "sourcekit-lsp") {
20+
// Custom encoding for `sourcekit-lsp://` requests having a `parent` parameter which
21+
// can be a `file://` URL or a `sourcekit-lsp://` URL.
22+
const scheme = value.scheme;
23+
const authority = value.authority;
24+
const path = value.path;
25+
const fragment = value.fragment;
26+
27+
let query = value.query;
28+
29+
const parentParameter = "parent=";
30+
const parentParameterIndex = query.indexOf("parent=");
31+
32+
if (parentParameterIndex === -1) {
33+
// No need to do this encoding if there's no parent parameter in the
34+
// reference document URL
35+
36+
// Same as the default implementation
37+
return value.toString();
38+
}
39+
40+
// Apply encoding from the start of the value of the `parent` parameter's value
41+
// till the end of the url string (`parent` parameter is the last parameter of the
42+
// reference document url)
43+
44+
const startIndex = parentParameterIndex + parentParameter.length;
45+
46+
const before = query.slice(0, startIndex);
47+
const toEncode = query.slice(startIndex);
48+
49+
// Replace only the percent, equals, ampersand signs
50+
// This is inline with how sourcekit-lsp handles the URLs in its test cases.
51+
const encoded = toEncode.replace(/%/g, "%25").replace(/=/g, "%3D").replace(/&/g, "%26");
52+
53+
query = before + encoded;
54+
55+
let uriString = scheme + "://" + authority + path;
56+
57+
if (query !== "" && query !== null) {
58+
uriString += "?" + query;
59+
}
60+
61+
if (fragment !== "" && fragment !== null) {
62+
uriString += "#" + fragment;
63+
}
64+
65+
return uriString;
66+
} else {
67+
// Same as the default implementation
68+
return value.toString();
69+
}
70+
},
71+
protocol2Code: (value: string) => {
72+
// Same as the default implementation
73+
return vscode.Uri.parse(value);
74+
},
75+
};

0 commit comments

Comments
 (0)