Skip to content

Commit

Permalink
Terraform Version LanguageStatusItem
Browse files Browse the repository at this point in the history
This uses a StaticFeature to provide a LanguageStatusItem that displays the version of terraform that terraform-ls knows about.
  • Loading branch information
jpogran committed Jan 17, 2023
1 parent 97e2ef1 commit d643836
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getInitializationOptions, migrateLegacySettings, previewExtensionPresen
import { TerraformLSCommands } from './commands/terraformls';
import { TerraformCommands } from './commands/terraform';
import { ExtensionErrorHandler } from './handlers/errorHandler';
import { TerraformVersionFeature } from './features/terraformVersion';

const id = 'terraform';
const brand = `HashiCorp Terraform`;
Expand Down Expand Up @@ -94,6 +95,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
new ModuleCallsFeature(client, new ModuleCallsDataProvider(context, client, reporter)),
new TelemetryFeature(client, reporter),
new ShowReferencesFeature(client),
new TerraformVersionFeature(client, reporter, outputChannel),
]);

// these need the LS to function, so are only registered if enabled
Expand Down
74 changes: 74 additions & 0 deletions src/features/terraformVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as vscode from 'vscode';
import * as terraform from '../terraform';
import { ClientCapabilities, ServerCapabilities, StaticFeature } from 'vscode-languageclient';
import { getActiveTextEditor } from '../utils/vscode';
import { ExperimentalClientCapabilities } from './types';
import { Utils } from 'vscode-uri';
import TelemetryReporter from '@vscode/extension-telemetry';
import { LanguageClient } from 'vscode-languageclient/node';

export class TerraformVersionFeature implements StaticFeature {
private disposables: vscode.Disposable[] = [];

private clientTerraformVersionCommandId = 'client.refreshTerraformVersion';

private terraformStatus = vscode.languages.createLanguageStatusItem('terraform.status', [
{ language: 'terraform' },
{ language: 'terraform-vars' },
]);

constructor(
private client: LanguageClient,
private reporter: TelemetryReporter,
private outputChannel: vscode.OutputChannel,
) {
this.terraformStatus.name = 'Terraform';
this.terraformStatus.detail = 'Terraform Version';
this.disposables.push(this.terraformStatus);
}

public fillClientCapabilities(capabilities: ClientCapabilities & ExperimentalClientCapabilities): void {
capabilities.experimental = capabilities.experimental || {};
capabilities.experimental.refreshTerraformVersionCommandId = this.clientTerraformVersionCommandId;
}

public async initialize(capabilities: ServerCapabilities): Promise<void> {
if (!capabilities.experimental?.refreshTerraformVersion) {
this.outputChannel.appendLine("Server doesn't support client.refreshTerraformVersion");
return;
}

await this.client.onReady();

const handler = this.client.onRequest(this.clientTerraformVersionCommandId, async () => {
const editor = getActiveTextEditor();
if (editor === undefined) {
return;
}

const moduleDir = Utils.dirname(editor.document.uri);

try {
const response = await terraform.terraformVersion(moduleDir.toString(), this.client, this.reporter);
this.terraformStatus.text = response.discovered_version;
} catch (error) {
let message = 'Unknown Error';
if (error instanceof Error) {
message = error.message;
} else if (typeof error === 'string') {
message = error;
}
this.outputChannel.appendLine(message);
}
});

this.disposables.push(handler);
}

public dispose(): void {
this.disposables.forEach((d: vscode.Disposable, index, things) => {
d.dispose();
things.splice(index, 1);
});
}
}
1 change: 1 addition & 0 deletions src/features/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export interface ExperimentalClientCapabilities {
showReferencesCommandId?: string;
refreshModuleProvidersCommandId?: string;
refreshModuleCallsCommandId?: string;
refreshTerraformVersionCommandId?: string;
};
}
18 changes: 18 additions & 0 deletions src/terraform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,26 @@ interface ModuleProvidersResponse {
[provider: string]: string;
};
}

export interface TerraformInfoResponse {
v: number;
required_version: string;
discovered_version: string;
}
/* eslint-enable @typescript-eslint/naming-convention */

export async function terraformVersion(
moduleUri: string,
client: LanguageClient,
reporter: TelemetryReporter,
): Promise<TerraformInfoResponse> {
const command = 'terraform-ls.module.terraform';

const response = await execWorkspaceLSCommand<TerraformInfoResponse>(command, moduleUri, client, reporter);

return response;
}

export async function moduleCallers(
moduleUri: string,
client: LanguageClient,
Expand Down

0 comments on commit d643836

Please sign in to comment.