Skip to content

Commit 8a940d4

Browse files
author
Jackson Dean
committed
feat: Add document links provider.
For css and sass, vscode provides a "jump to file" feature for @import and `url()` statements. For css-blocks, we only need to add this support for custom "at rules" (@block, @export). For `url()`, the builtin vscode css language server should still be providing that functionality.
1 parent ce11880 commit 8a940d4

File tree

4 files changed

+85
-2
lines changed

4 files changed

+85
-2
lines changed

packages/@css-blocks/language-server/src/Server.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { BlockFactory, CssBlockError, Options, resolveConfiguration } from "@css-blocks/core/dist/src";
22
import { BlockParser } from "@css-blocks/core/dist/src/BlockParser/BlockParser";
3-
import { CompletionItem, Definition, DidChangeConfigurationNotification, IConnection, InitializeParams, InitializeResult, TextDocumentChangeEvent, TextDocumentPositionParams, TextDocuments } from "vscode-languageserver";
3+
import { CompletionItem, Definition, DidChangeConfigurationNotification, DocumentLink, DocumentLinkParams, IConnection, InitializeParams, InitializeResult, TextDocumentChangeEvent, TextDocumentPositionParams, TextDocuments } from "vscode-languageserver";
44

55
import { emberCompletionProvider } from "./completionProviders/emberCompletionProvider";
66
import { createBlockFactory } from "./createBlockFactory";
77
import { createBlockParser } from "./createBlockParser";
88
import { emberDefinitionProvider } from "./definitionProviders/emberDefinitionProvider";
9+
import { blockLinksProvider } from "./documentLinksProviders/blockLinkProvider";
910
import { documentContentChange } from "./eventHandlers/documentContentChange";
1011
import { PathTransformer } from "./pathTransformers/PathTransformer";
1112
import { SERVER_CAPABILITIES } from "./serverCapabilities";
@@ -81,6 +82,10 @@ export class Server {
8182
this.connection.onDefinition(async (params: TextDocumentPositionParams): Promise<Definition> => {
8283
return await emberDefinitionProvider(this.documents, this.blockFactory, params, this.pathTransformer);
8384
});
85+
86+
this.connection.onDocumentLinks(async (params: DocumentLinkParams): Promise<DocumentLink[]> => {
87+
return await blockLinksProvider(this.documents, params);
88+
});
8489
}
8590

8691
private onConnectionInitialize(params: InitializeParams): InitializeResult {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import * as path from "path";
2+
import { DocumentLinkParams, TextDocuments } from "vscode-languageserver";
3+
import { DocumentLink } from "vscode-languageserver-types";
4+
import { URI } from "vscode-uri";
5+
6+
import { isBlockFile } from "../util/blockUtils";
7+
8+
const LINK_REGEX = /from\s+(['"])([^'"]+)\1;/;
9+
10+
export async function blockLinksProvider(documents: TextDocuments, params: DocumentLinkParams): Promise<DocumentLink[]> {
11+
let { uri } = params.textDocument;
12+
13+
if (!isBlockFile(uri)) {
14+
return [];
15+
}
16+
17+
let document = documents.get(uri);
18+
19+
if (!document) {
20+
return [];
21+
}
22+
23+
let links: DocumentLink[] = [];
24+
let lines = document.getText().split(/\r?\n/);
25+
let blockDirPath = path.dirname(URI.parse(uri).fsPath);
26+
27+
lines.forEach((line, lineIndex) => {
28+
let matches = line.match(LINK_REGEX);
29+
30+
if (!matches) {
31+
return;
32+
}
33+
34+
let relativeBlockReferencePath = matches[2];
35+
let absoluteBlockReferencePath = path.resolve(blockDirPath, relativeBlockReferencePath);
36+
let startColumn = line.indexOf(relativeBlockReferencePath);
37+
let endColumn = startColumn + relativeBlockReferencePath.length;
38+
39+
links.push({
40+
target: URI.file(absoluteBlockReferencePath).toString(),
41+
range: {
42+
start: { line: lineIndex, character: startColumn },
43+
end: { line: lineIndex, character: endColumn },
44+
},
45+
});
46+
});
47+
48+
return links;
49+
}

packages/@css-blocks/language-server/src/serverCapabilities.ts

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export const SERVER_CAPABILITIES: ServerCapabilities = {
55
definitionProvider: true,
66
// TODO: implement support for this for showing documentation
77
// hoverProvider: true,
8+
documentLinkProvider: {
9+
resolveProvider: true,
10+
},
811
documentSymbolProvider: false,
912
completionProvider: {
1013
resolveProvider: true,

packages/@css-blocks/language-server/src/test/server-test.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Syntax } from "@css-blocks/core/dist/src";
22
import { assert } from "chai";
33
import { skip, suite, test } from "mocha-typescript";
44
import * as path from "path";
5-
import { CompletionItemKind, CompletionRequest, DefinitionRequest, DiagnosticSeverity, DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DidSaveTextDocumentNotification, DidSaveTextDocumentParams, IConnection, TextDocument, TextDocumentPositionParams, TextDocuments, createConnection } from "vscode-languageserver";
5+
import { CompletionItemKind, CompletionRequest, DefinitionRequest, DiagnosticSeverity, DidOpenTextDocumentNotification, DidOpenTextDocumentParams, DidSaveTextDocumentNotification, DidSaveTextDocumentParams, DocumentLinkParams, DocumentLinkRequest, IConnection, TextDocument, TextDocumentPositionParams, TextDocuments, createConnection } from "vscode-languageserver";
66
import { URI } from "vscode-uri";
77

88
import { EmberClassicTransformer } from "../pathTransformers/EmberClassicTransformer";
@@ -351,4 +351,30 @@ export class LanguageServerServerTest {
351351
});
352352

353353
}
354+
355+
@test async "it returns the expected document links"() {
356+
this.startServer();
357+
358+
let params: DocumentLinkParams = {
359+
textDocument: {
360+
uri: pathToUri("fixtures/ember-classic/styles/components/a.block.css"),
361+
},
362+
};
363+
364+
let response = await this.mockClientConnection.sendRequest(DocumentLinkRequest.type, params);
365+
366+
assert.deepEqual(response, [{
367+
range: {
368+
start: {
369+
character: 19,
370+
line: 0,
371+
},
372+
end: {
373+
character: 44,
374+
line: 0,
375+
},
376+
},
377+
target: pathToUri("fixtures/ember-classic/styles/blocks/utils.block.css"),
378+
}]);
379+
}
354380
}

0 commit comments

Comments
 (0)