-
Notifications
You must be signed in to change notification settings - Fork 182
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds a new view to the Explorer view container in the activity bar that shows a list of modules referenced in the module opened. Each module is styled based on its type, and will show dependent modules that can be expanded. It also introduces two new commands, `refresh` and `open documentation`, that are tied to the view and can be used in the view title bar as well as in context menus for each module. This view will be only active when the extension activates, and will only display information when a module is open that references modules. If no modules are found, a note is left in the window. This also introduces a new approach to organizing the code in feature files instead of entirely inside the extension.ts file.
- Loading branch information
Showing
4 changed files
with
208 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import * as path from 'path'; | ||
import * as vscode from 'vscode'; | ||
import { ExecuteCommandParams, ExecuteCommandRequest } from 'vscode-languageclient'; | ||
import { Utils } from 'vscode-uri'; | ||
import { ClientHandler } from '../clientHandler'; | ||
|
||
const LOCALMODULE = new vscode.ThemeIcon('symbol-folder', new vscode.ThemeColor('terminal.ansiBrightBlue')); | ||
const TFREGISTRY = new vscode.ThemeIcon('extensions-view-icon', new vscode.ThemeColor('terminal.ansiBrightMagenta')); | ||
const GITHUBMODULE = new vscode.ThemeIcon('github'); | ||
|
||
class TerraformModule extends vscode.TreeItem { | ||
constructor( | ||
public label: string, | ||
public provider: string, | ||
public version: string, | ||
public type: string, | ||
public doclink: string, | ||
public state: vscode.TreeItemCollapsibleState, | ||
public readonly children?: [TerraformModule], | ||
) { | ||
super(label, state); | ||
this.tooltip = `${this.provider}@${this.version}`; | ||
this.description = `${this.provider}@${this.version}`; | ||
} | ||
|
||
iconPath = this.getIcon(this.type); | ||
|
||
getIcon(type: string) { | ||
const icon = this.terraformIcon(); | ||
switch (type) { | ||
case 'tfregistry': | ||
return icon; | ||
case 'local': | ||
return LOCALMODULE; | ||
case 'github': | ||
return GITHUBMODULE; | ||
default: | ||
return TFREGISTRY; | ||
} | ||
} | ||
|
||
private terraformIcon() { | ||
// need current extension path to find icon svg | ||
// could possibly make this a custom icon | ||
const myExtDir = vscode.extensions.getExtension('hashicorp.terraform').extensionPath; | ||
const svg = vscode.Uri.file(path.join(myExtDir, 'assets', 'icons', 'terraform.svg')); | ||
const icon = { | ||
light: svg, | ||
dark: svg, | ||
}; | ||
return icon; | ||
} | ||
} | ||
|
||
export class TerraformModuleProvider implements vscode.TreeDataProvider<TerraformModule> { | ||
private _onDidChangeTreeData: vscode.EventEmitter<TerraformModule | undefined | null | void> = | ||
new vscode.EventEmitter<TerraformModule | undefined | null | void>(); | ||
readonly onDidChangeTreeData: vscode.Event<TerraformModule | undefined | null | void> = | ||
this._onDidChangeTreeData.event; | ||
|
||
constructor(ctx: vscode.ExtensionContext, public handler: ClientHandler) { | ||
ctx.subscriptions.push( | ||
vscode.commands.registerCommand('terraform.modules.refreshList', () => this.refresh()), | ||
vscode.commands.registerCommand('terraform.modules.documentation', (module: TerraformModule) => { | ||
vscode.env.openExternal(vscode.Uri.parse(module.doclink)); | ||
}), | ||
vscode.window.onDidChangeActiveTextEditor(async (event: vscode.TextEditor | undefined) => { | ||
if (event && vscode.workspace.workspaceFolders[0]) { | ||
this.refresh(); | ||
} | ||
}), | ||
); | ||
} | ||
|
||
refresh(): void { | ||
this._onDidChangeTreeData.fire(); | ||
} | ||
|
||
getTreeItem(element: TerraformModule): TerraformModule | Thenable<TerraformModule> { | ||
return element; | ||
} | ||
|
||
getChildren(element?: TerraformModule): vscode.ProviderResult<TerraformModule[]> { | ||
if (element) { | ||
return Promise.resolve(element.children); | ||
} else { | ||
const m = this.getModules(); | ||
return Promise.resolve(m); | ||
} | ||
} | ||
|
||
getCollapseState(type: string): vscode.TreeItemCollapsibleState { | ||
switch (type) { | ||
case 'tfregistry': | ||
return vscode.TreeItemCollapsibleState.Collapsed; | ||
case 'local': | ||
return vscode.TreeItemCollapsibleState.None; | ||
case 'github': | ||
return vscode.TreeItemCollapsibleState.None; | ||
default: | ||
return vscode.TreeItemCollapsibleState.None; | ||
} | ||
} | ||
|
||
async getModules(): Promise<TerraformModule[]> { | ||
const activeEditor = vscode.window.activeTextEditor; | ||
if (activeEditor === undefined) { | ||
return Promise.resolve([]); | ||
} | ||
|
||
const document = activeEditor.document; | ||
if (document === undefined) { | ||
return Promise.resolve([]); | ||
} | ||
|
||
const editor = document.uri; | ||
const documentURI = Utils.dirname(editor); | ||
const handler = this.handler.getClient(editor); | ||
|
||
return await handler.client.onReady().then(async () => { | ||
const params: ExecuteCommandParams = { | ||
command: `${handler.commandPrefix}.terraform-ls.terraform.modulelist`, | ||
arguments: [`uri=${documentURI}`], | ||
}; | ||
|
||
const response = await handler.client.sendRequest(ExecuteCommandRequest.type, params); | ||
if (response == null) { | ||
return Promise.resolve([]); | ||
} | ||
|
||
const list = response.modules.map((m) => { | ||
let deps: [TerraformModule]; | ||
if (m.depmodules === null) { | ||
deps = null; | ||
} else { | ||
deps = m.depmodules.map((dp) => { | ||
return new TerraformModule( | ||
dp.name, | ||
dp.path, | ||
dp.version, | ||
dp.type, | ||
dp.docklink, | ||
vscode.TreeItemCollapsibleState.None, | ||
); | ||
}); | ||
} | ||
|
||
const state = this.getCollapseState(m.type); | ||
|
||
return new TerraformModule(m.name, m.path, m.version, m.type, m.docklink, state, deps); | ||
}); | ||
|
||
return list; | ||
}); | ||
} | ||
} |