Skip to content

Commit a35c711

Browse files
authored
Handle malformed educational note link in nightlies (#1607)
* Handle malformed educational note link in nightlies The sourcekit-lsp in nightly toolchains is returning a malformed educational note URL. Add a workaround that handles parsing this malformed URL. If the URL is ultimately a web url, open the docs website, otherwise open the .md file inline. * Windows fix
1 parent 705a3da commit a35c711

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

src/DiagnosticsManager.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import * as vscode from "vscode";
1616
import * as fs from "fs";
17+
import * as path from "path";
1718
// eslint-disable-next-line @typescript-eslint/no-require-imports
1819
import stripAnsi = require("strip-ansi");
1920
import configuration from "./configuration";
@@ -149,7 +150,24 @@ export class DiagnosticsManager implements vscode.Disposable {
149150
typeof diagnostic.code !== "string" &&
150151
typeof diagnostic.code !== "number"
151152
) {
152-
if (diagnostic.code.target.fsPath.endsWith(".md")) {
153+
const fsPath = diagnostic.code.target.fsPath;
154+
155+
// Work around a bug in the nightlies where the URL comes back looking like:
156+
// `/path/to/TestPackage/https:/docs.swift.org/compiler/documentation/diagnostics/nominal-types`
157+
// Transform this in to a valid docs.swift.org URL which the openEducationalNote command
158+
// will open in a browser.
159+
// FIXME: This can be removed when the bug is fixed in sourcekit-lsp.
160+
let open = false;
161+
const needle = `https:${path.sep}docs.swift.org${path.sep}`;
162+
if (fsPath.indexOf(needle) !== -1) {
163+
const extractedPath = `https://docs.swift.org/${fsPath.split(needle).pop()}/`;
164+
diagnostic.code.target = vscode.Uri.parse(extractedPath.replace(/\\/g, "/"));
165+
open = true;
166+
} else if (diagnostic.code.target.fsPath.endsWith(".md")) {
167+
open = true;
168+
}
169+
170+
if (open) {
153171
diagnostic.code = {
154172
target: vscode.Uri.parse(
155173
`command:swift.openEducationalNote?${encodeURIComponent(JSON.stringify(diagnostic.code.target))}`

src/commands/openEducationalNote.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@ import * as vscode from "vscode";
2020
* The default behaviour is to open it in a markdown preview to the side.
2121
*/
2222
export async function openEducationalNote(markdownFile: vscode.Uri | undefined): Promise<void> {
23-
await vscode.commands.executeCommand("markdown.showPreviewToSide", markdownFile);
23+
if (markdownFile?.fsPath.endsWith(".md")) {
24+
await vscode.commands.executeCommand("markdown.showPreviewToSide", markdownFile);
25+
} else if (markdownFile !== undefined) {
26+
await vscode.env.openExternal(markdownFile);
27+
}
2428
}

test/integration-tests/DiagnosticsManager.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,45 @@ suite("DiagnosticsManager Test Suite", function () {
690690
assert.fail("Diagnostic target not replaced with markdown command");
691691
}
692692
});
693+
694+
test("target with malformed nightly link", async () => {
695+
const malformedUri =
696+
"/path/to/TestPackage/https:/docs.swift.org/compiler/documentation/diagnostics/nominal-types";
697+
const expectedUri =
698+
"https://docs.swift.org/compiler/documentation/diagnostics/nominal-types/";
699+
diagnostic.code = {
700+
value: "string",
701+
target: vscode.Uri.file(malformedUri),
702+
};
703+
704+
workspaceContext.diagnostics.handleDiagnostics(
705+
mainUri,
706+
DiagnosticsManager.isSourcekit,
707+
[diagnostic]
708+
);
709+
710+
const diagnostics = vscode.languages.getDiagnostics(mainUri);
711+
const matchingDiagnostic = diagnostics.find(findDiagnostic(diagnostic));
712+
713+
expect(matchingDiagnostic).to.have.property("code");
714+
expect(matchingDiagnostic?.code).to.have.property("value", "More Information...");
715+
716+
if (
717+
matchingDiagnostic &&
718+
matchingDiagnostic.code &&
719+
typeof matchingDiagnostic.code !== "string" &&
720+
typeof matchingDiagnostic.code !== "number"
721+
) {
722+
expect(matchingDiagnostic.code.target.scheme).to.equal("command");
723+
expect(matchingDiagnostic.code.target.path).to.equal(
724+
"swift.openEducationalNote"
725+
);
726+
const parsed = JSON.parse(matchingDiagnostic.code.target.query);
727+
expect(vscode.Uri.from(parsed).toString()).to.equal(expectedUri);
728+
} else {
729+
assert.fail("Diagnostic target not replaced with markdown command");
730+
}
731+
});
693732
});
694733

695734
suite("keepAll", () => {

0 commit comments

Comments
 (0)