Skip to content

Commit

Permalink
WIP - custom semantic tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Mar 16, 2022
1 parent bd7035a commit aff8a1f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 0 deletions.
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,39 @@
"path": "./syntaxes/terraform.tmGrammar.json"
}
],
"semanticTokenTypes": [
{"id": "hcl-attrName", "superType": "property"},
{"id": "hcl-blockType", "superType": "type"},
{"id": "hcl-blockLabel", "superType": "enumMember"},

{"id": "hcl-bool", "superType": "keyword"},
{"id": "hcl-string", "superType": "string"},
{"id": "hcl-number", "superType": "number"},
{"id": "hcl-objectKey", "superType": "parameter"},
{"id": "hcl-mapKey", "superType": "parameter"},
{"id": "hcl-keyword", "superType": "variable"},
{"id": "hcl-traversalStep", "superType": "variable"},
{"id": "hcl-typeCapsule", "superType": "function"},
{"id": "hcl-typePrimitive", "superType": "keyword"}
],
"semanticTokenModifiers": [
{"id": "hcl-dependent"},

{"id": "terraform-data"},
{"id": "terraform-locals"},
{"id": "terraform-module"},
{"id": "terraform-output"},
{"id": "terraform-provider"},
{"id": "terraform-resource"},
{"id": "terraform-provisioner"},
{"id": "terraform-connection"},
{"id": "terraform-variable"},
{"id": "terraform-terraform"},
{"id": "terraform-backend"},
{"id": "terraform-name"},
{"id": "terraform-type"},
{"id": "terraform-requiredProviders"}
],
"snippets": [
{
"language": "terraform",
Expand Down
8 changes: 8 additions & 0 deletions src/clientHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ServerPath } from './serverPath';
import { ShowReferencesFeature } from './showReferences';
import { TelemetryFeature } from './telemetry';
import { config } from './vscodeUtils';
import { CustomSemanticTokens } from './semanticTokens';

export interface TerraformLanguageClient {
commandPrefix: string;
Expand All @@ -29,6 +30,9 @@ export class ClientHandler {
private tfClient: TerraformLanguageClient | undefined;
private commands: string[] = [];

public extSemanticTokenTypes: string[] = [];
public extSemanticTokenModifiers: string[] = [];

constructor(
private lsPath: ServerPath,
private outputChannel: vscode.OutputChannel,
Expand Down Expand Up @@ -86,6 +90,10 @@ export class ClientHandler {
const id = `terraform`;
const client = new LanguageClient(id, serverOptions, clientOptions);

client.registerFeature(
new CustomSemanticTokens(client, this.extSemanticTokenTypes, this.extSemanticTokenModifiers),
);

const codeLensReferenceCount = config('terraform').get<boolean>('codelens.referenceCount');
if (codeLensReferenceCount) {
client.registerFeature(new ShowReferencesFeature(client));
Expand Down
21 changes: 21 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>

const lsPath = new ServerPath(context);
clientHandler = new ClientHandler(lsPath, outputChannel, reporter);
clientHandler.extSemanticTokenTypes = tokenTypesFromExtManifest(context.extension);
clientHandler.extSemanticTokenModifiers = tokenModifiersFromExtManifest(context.extension);

// get rid of pre-2.0.0 settings
if (config('terraform').has('languageServer.enabled')) {
Expand Down Expand Up @@ -293,6 +295,25 @@ async function terraformCommand(command: string, languageServerExec = true): Pro
}
}

interface ObjectWithId {
id: string;
}

function tokenTypesFromExtManifest(ext: vscode.Extension<unknown>): string[] {
if (!ext.packageJSON.contributes.semanticTokenTypes) {
return [];
}
return ext.packageJSON.contributes.semanticTokenTypes.map((token: ObjectWithId) => token.id);
}

function tokenModifiersFromExtManifest(ext: vscode.Extension<unknown>): string[] {
if (!ext.packageJSON.contributes.semanticTokenModifiers) {
return [];
}

return ext.packageJSON.contributes.semanticTokenModifiers.map((modifier: ObjectWithId) => modifier.id);
}

function enabled(): boolean {
return config('terraform').get('languageServer.external', false);
}
30 changes: 30 additions & 0 deletions src/semanticTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { BaseLanguageClient, ClientCapabilities, ServerCapabilities, StaticFeature } from 'vscode-languageclient';

export class CustomSemanticTokens implements StaticFeature {
constructor(
private _client: BaseLanguageClient,
private extTokenTypes: string[],
private extTokenModifiers: string[],
) {}

public fillClientCapabilities(capabilities: ClientCapabilities): void {
if (!capabilities.textDocument || !capabilities.textDocument.semanticTokens) {
return;
}

const tokenTypes = capabilities.textDocument.semanticTokens.tokenTypes;
capabilities.textDocument.semanticTokens.tokenTypes = tokenTypes.concat(this.extTokenTypes);

const tokenModifiers = capabilities.textDocument.semanticTokens.tokenModifiers;
capabilities.textDocument.semanticTokens.tokenModifiers = tokenModifiers.concat(this.extTokenModifiers);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
public initialize(capabilities: ServerCapabilities): void {
return;
}

public dispose(): void {
return;
}
}
1 change: 1 addition & 0 deletions src/vscodeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export function isTerraformFile(document?: vscode.TextDocument): boolean {
return false;
}

// TODO: check for supported language IDs here instead
if (document.fileName.endsWith('tf')) {
// For the purposes of this extension, anything with the tf file
// extension is a Terraform file
Expand Down

0 comments on commit aff8a1f

Please sign in to comment.