Skip to content

Commit be6caee

Browse files
change LSP request name to convertDocumentation
1 parent b574367 commit be6caee

File tree

12 files changed

+213
-121
lines changed

12 files changed

+213
-121
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"VSCODE_DEBUG": "1"
1515
},
1616
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
17-
"preLaunchTask": "build"
17+
"preLaunchTask": "Build Extension"
1818
},
1919
{
2020
"name": "Extension Tests",

package.json

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
],
2525
"activationEvents": [
2626
"onLanguage:swift",
27-
"onLanguage:swift-docc-markdown",
28-
"onLanguage:swift-docc-tutorial",
2927
"workspaceContains:Package.swift",
3028
"workspaceContains:compile_commands.json",
3129
"workspaceContains:compile_flags.txt",
@@ -63,21 +61,12 @@
6361
]
6462
},
6563
{
66-
"id": "swift-docc-markdown",
64+
"id": "tutorial",
6765
"aliases": [
68-
"Swift DocC Markdown"
66+
"Tutorial"
6967
],
7068
"filenamePatterns": [
71-
"**/*.docc/**/*.md"
72-
]
73-
},
74-
{
75-
"id": "swift-docc-tutorial",
76-
"aliases": [
77-
"Swift DocC Tutorial"
78-
],
79-
"filenamePatterns": [
80-
"**/*.docc/**/*.tutorial"
69+
"*.tutorial"
8170
]
8271
}
8372
],
@@ -690,7 +679,7 @@
690679
"commandPalette": [
691680
{
692681
"command": "swift.previewDocumentation",
693-
"when": "swift.supportsDocumentationRendering"
682+
"when": "swift.supportsDocumentationLivePreview"
694683
},
695684
{
696685
"command": "swift.createNewProject",

src/WorkspaceContext.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,13 @@ export class WorkspaceContext implements vscode.Disposable {
235235
const experimentalCaps = client.initializeResult?.capabilities.experimental;
236236
if (!experimentalCaps) {
237237
contextKeys.supportsReindexing = false;
238-
contextKeys.supportsDocumentationRendering = false;
238+
contextKeys.supportsDocumentationLivePreview = false;
239239
return;
240240
}
241241
contextKeys.supportsReindexing =
242242
experimentalCaps["workspace/triggerReindex"] !== undefined;
243-
contextKeys.supportsDocumentationRendering =
244-
experimentalCaps["textDocument/renderDocumentation"] !== undefined;
243+
contextKeys.supportsDocumentationLivePreview =
244+
experimentalCaps["textDocument/convertDocumentation"] !== undefined;
245245
});
246246

247247
setSnippetContextKey(this);

src/contextKeys.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ interface ContextKeys {
6969
supportsReindexing: boolean;
7070

7171
/**
72-
* Whether the SourceKit-LSP server supports documentation rendering.
72+
* Whether the SourceKit-LSP server supports documentation live preview.
7373
*/
74-
supportsDocumentationRendering: boolean;
74+
supportsDocumentationLivePreview: boolean;
7575
}
7676

7777
/** Creates the getters and setters for the VS Code Swift extension's context keys. */
@@ -85,7 +85,7 @@ function createContextKeys(): ContextKeys {
8585
let lldbVSCodeAvailable: boolean = false;
8686
let createNewProjectAvailable: boolean = false;
8787
let supportsReindexing: boolean = false;
88-
let supportsDocumentationRendering: boolean = false;
88+
let supportsDocumentationLivePreview: boolean = false;
8989

9090
return {
9191
get isActivated() {
@@ -173,15 +173,15 @@ function createContextKeys(): ContextKeys {
173173
vscode.commands.executeCommand("setContext", "swift.supportsReindexing", value);
174174
},
175175

176-
get supportsDocumentationRendering() {
177-
return supportsDocumentationRendering;
176+
get supportsDocumentationLivePreview() {
177+
return supportsDocumentationLivePreview;
178178
},
179179

180-
set supportsDocumentationRendering(value: boolean) {
181-
supportsDocumentationRendering = value;
180+
set supportsDocumentationLivePreview(value: boolean) {
181+
supportsDocumentationLivePreview = value;
182182
vscode.commands.executeCommand(
183183
"setContext",
184-
"swift.supportsDocumentationRendering",
184+
"swift.supportsDocumentationLivePreview",
185185
value
186186
);
187187
},

src/documentation/DocumentationManager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
import * as vscode from "vscode";
1616
import { DocumentationPreviewEditor } from "./DocumentationPreviewEditor";
1717
import { WorkspaceContext } from "../WorkspaceContext";
18-
import { RenderNode } from "./webview/WebviewMessage";
18+
import { WebviewContent } from "./webview/WebviewMessage";
1919
import contextKeys from "../contextKeys";
2020

2121
export class DocumentationManager implements vscode.Disposable {
2222
private previewEditor?: DocumentationPreviewEditor;
23-
private editorUpdatedContentEmitter = new vscode.EventEmitter<RenderNode>();
23+
private editorUpdatedContentEmitter = new vscode.EventEmitter<WebviewContent>();
2424
private editorRenderedEmitter = new vscode.EventEmitter<void>();
2525

2626
constructor(
@@ -32,7 +32,7 @@ export class DocumentationManager implements vscode.Disposable {
3232
onPreviewDidRenderContent = this.editorRenderedEmitter.event;
3333

3434
async launchDocumentationPreview(): Promise<boolean> {
35-
if (!contextKeys.supportsDocumentationRendering) {
35+
if (!contextKeys.supportsDocumentationLivePreview) {
3636
return false;
3737
}
3838

src/documentation/DocumentationPreviewEditor.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
import * as vscode from "vscode";
1616
import * as fs from "fs/promises";
1717
import * as path from "path";
18-
import { RenderNode, WebviewMessage } from "./webview/WebviewMessage";
18+
import { RenderNode, WebviewContent, WebviewMessage } from "./webview/WebviewMessage";
1919
import { WorkspaceContext } from "../WorkspaceContext";
20-
import { RenderDocumentationRequest } from "../sourcekit-lsp/extensions/RenderDocumentationRequest";
20+
import { ConvertDocumentationRequest } from "../sourcekit-lsp/extensions/ConvertDocumentationRequest";
2121

2222
export enum PreviewEditorConstant {
2323
VIEW_TYPE = "swift.previewDocumentationEditor",
@@ -30,7 +30,7 @@ export class DocumentationPreviewEditor implements vscode.Disposable {
3030

3131
private disposeEmitter = new vscode.EventEmitter<void>();
3232
private renderEmitter = new vscode.EventEmitter<void>();
33-
private updateContentEmitter = new vscode.EventEmitter<RenderNode>();
33+
private updateContentEmitter = new vscode.EventEmitter<WebviewContent>();
3434

3535
constructor(
3636
private readonly extension: vscode.ExtensionContext,
@@ -66,10 +66,10 @@ export class DocumentationPreviewEditor implements vscode.Disposable {
6666
this.subscriptions.push(
6767
this.webviewPanel.webview.onDidReceiveMessage(this.receiveMessage.bind(this)),
6868
vscode.window.onDidChangeActiveTextEditor(editor => {
69-
this.renderDocumentation(editor);
69+
this.convertDocumentation(editor);
7070
}),
7171
vscode.window.onDidChangeTextEditorSelection(event => {
72-
this.renderDocumentation(event.textEditor);
72+
this.convertDocumentation(event.textEditor);
7373
}),
7474
this.webviewPanel.onDidDispose(this.dispose.bind(this))
7575
);
@@ -109,36 +109,46 @@ export class DocumentationPreviewEditor implements vscode.Disposable {
109109
private receiveMessage(message: WebviewMessage) {
110110
switch (message.type) {
111111
case "loaded":
112-
this.renderDocumentation(vscode.window.activeTextEditor);
112+
this.convertDocumentation(vscode.window.activeTextEditor);
113113
break;
114114
case "rendered":
115115
this.renderEmitter.fire();
116116
break;
117117
}
118118
}
119119

120-
private async renderDocumentation(editor: vscode.TextEditor | undefined): Promise<void> {
120+
private async convertDocumentation(editor: vscode.TextEditor | undefined): Promise<void> {
121121
const document = editor?.document;
122122
if (!document || document.uri.scheme !== "file") {
123123
return undefined;
124124
}
125125

126126
const response = await this.context.languageClientManager.useLanguageClient(
127127
async client => {
128-
return await client.sendRequest(RenderDocumentationRequest.type, {
128+
return await client.sendRequest(ConvertDocumentationRequest.type, {
129129
textDocument: {
130130
uri: document.uri.toString(),
131131
},
132132
position: editor.selection.start,
133133
});
134134
}
135135
);
136-
if (!response.content) {
136+
if (response.type === "error") {
137+
this.postMessage({
138+
type: "update-content",
139+
content: {
140+
type: "error",
141+
errorMessage: response.error.message,
142+
},
143+
});
137144
return;
138145
}
139146
this.postMessage({
140147
type: "update-content",
141-
content: this.parseRenderNode(response.content),
148+
content: {
149+
type: "render-node",
150+
renderNode: this.parseRenderNode(response.renderNode),
151+
},
142152
});
143153
}
144154

src/documentation/webview/WebviewMessage.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,34 @@ export interface RenderedMessage {
3737
* Sent from the extension to the webview to update its contents. The data
3838
* format is the same as DocC's JSON index.
3939
*
40+
* Automatically removes any other loading/error messages.
41+
*
4042
* This must be sent AFTER the webview has done at least one render.
4143
*/
4244
export interface UpdateContentMessage {
4345
type: "update-content";
44-
content: RenderNode;
46+
content: WebviewContent;
4547
}
4648

49+
export type WebviewContent = RenderNodeContent | ErrorContent;
50+
51+
export interface RenderNodeContent {
52+
type: "render-node";
53+
renderNode: RenderNode;
54+
}
55+
56+
export interface ErrorContent {
57+
type: "error";
58+
errorMessage: string;
59+
}
60+
61+
/**
62+
* A Swift DocC render node that represents a single page of documentation.
63+
*
64+
* In order to maintain maximum compatibility this interface only exposes the bare minimum
65+
* that we need to support live preview. This interface must be kept up to date with
66+
* https://github.com/swiftlang/swift-docc/blob/main/Sources/SwiftDocC/Model/Rendering/RenderNode.swift
67+
*/
4768
export interface RenderNode {
4869
schemaVersion: {
4970
major: number;

src/documentation/webview/webview.ts

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
import { RenderNode, WebviewMessage } from "./WebviewMessage";
15+
import { RenderNode, WebviewContent, WebviewMessage } from "./WebviewMessage";
1616
import { createCommunicationBridge } from "./CommunicationBridge";
1717

1818
createCommunicationBridge().then(async bridge => {
1919
const vscode = acquireVsCodeApi();
2020
let activeDocumentationPath: string | undefined;
2121
let contentToApplyOnRender: RenderNode | undefined;
2222

23+
window.document.getElementById("app");
24+
2325
// Handle messages coming from swift-docc-render
2426
bridge.onDidReceiveMessage(message => {
2527
switch (message.type) {
@@ -49,27 +51,32 @@ createCommunicationBridge().then(async bridge => {
4951
break;
5052
}
5153
});
52-
function handleUpdateContentMessage(renderNode: RenderNode) {
53-
const documentationPath: string = (() => {
54-
switch (renderNode.kind) {
55-
case "symbol":
56-
case "article":
57-
return "/live/documentation";
58-
case "overview":
59-
return "/live/tutorials-overview";
60-
default:
61-
return "/live/tutorials";
54+
function handleUpdateContentMessage(content: WebviewContent) {
55+
if (content.type === "render-node") {
56+
const renderNode = content.renderNode;
57+
const documentationPath: string = (() => {
58+
switch (renderNode.kind) {
59+
case "symbol":
60+
case "article":
61+
return "/live/documentation";
62+
case "overview":
63+
return "/live/tutorials-overview";
64+
default:
65+
return "/live/tutorials";
66+
}
67+
})();
68+
if (activeDocumentationPath !== documentationPath) {
69+
activeDocumentationPath = documentationPath;
70+
contentToApplyOnRender = renderNode;
71+
bridge.send({
72+
type: "navigation",
73+
data: documentationPath,
74+
});
75+
} else {
76+
bridge.send({ type: "contentUpdate", data: renderNode });
6277
}
63-
})();
64-
if (activeDocumentationPath !== documentationPath) {
65-
activeDocumentationPath = documentationPath;
66-
contentToApplyOnRender = renderNode;
67-
bridge.send({
68-
type: "navigation",
69-
data: documentationPath,
70-
});
7178
} else {
72-
bridge.send({ type: "contentUpdate", data: renderNode });
79+
// Show the error message
7380
}
7481
}
7582

src/sourcekit-lsp/LanguageClientManager.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ export class LanguageClientManager implements vscode.Disposable {
7575
];
7676
// document selector for swift-docc documentation
7777
static documentationDocumentSelector: SourceKitDocumentSelector = [
78-
{ scheme: "file", language: "swift-docc-markdown" },
79-
{ scheme: "untitled", language: "swift-docc-markdown" },
80-
{ scheme: "file", language: "swift-docc-tutorial" },
81-
{ scheme: "untitiled", language: "swift-docc-tutorial" },
78+
{ scheme: "file", language: "markdown" },
79+
{ scheme: "untitled", language: "markdown" },
80+
{ scheme: "file", language: "tutorial" },
81+
{ scheme: "untitiled", language: "tutorial" },
8282
];
8383
static get documentSelector(): DocumentSelector {
8484
let documentSelector: SourceKitDocumentSelector;

0 commit comments

Comments
 (0)