diff --git a/package-lock.json b/package-lock.json index 4b193949..82a22c79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "chocolatey-vscode", "version": "0.2.2", "dependencies": { + "vscode-languageclient": "^6.1.3", "xml2js": "^0.4.23" }, "devDependencies": { @@ -489,6 +490,48 @@ "node": ">=4.2.0" } }, + "node_modules/vscode-jsonrpc": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", + "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.4.tgz", + "integrity": "sha512-EUOU+bJu6axmt0RFNo3nrglQLPXMfanbYViJee3Fbn2VuQoX0ZOI4uTYhSRvYLP2vfwTP/juV62P/mksCdTZMA==", + "dependencies": { + "semver": "^6.3.0", + "vscode-languageserver-protocol": "3.15.3" + }, + "engines": { + "vscode": "^1.41.0" + } + }, + "node_modules/vscode-languageclient/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", + "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", + "dependencies": { + "vscode-jsonrpc": "^5.0.1", + "vscode-languageserver-types": "3.15.1" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", + "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index effe8e04..c21fed98 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,29 @@ } } } + }, + "chocolatey.language": { + "type": "object", + "properties": { + "allowSuppressionOfRequirements": { + "title": "Allow requirements suppression", + "type": "boolean", + "default": false, + "description": "Allow the suppression of rules that are marked as requirements" + }, + "disableLanguageService": { + "title": "Disable language service", + "type": "boolean", + "default": false, + "description": "Prevent the Chocolatey Language Service from starting up" + }, + "suppressedRules": { + "title": "Suppress Rules", + "type": "array", + "description": "The codes for the Chocolatey Language Service rules that should be suppressed", + "default": [] + } + } } } } @@ -153,6 +176,7 @@ "typescript": "^3.8.3" }, "dependencies": { + "vscode-languageclient": "^6.1.3", "xml2js": "^0.4.23" }, "extensionPack": [ diff --git a/src/extension.ts b/src/extension.ts index 853babe1..2dc37dbc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,4 +1,6 @@ import { window, commands, workspace, QuickPickItem, ExtensionContext, Uri } from "vscode"; +import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient'; +import { Trace } from 'vscode-jsonrpc'; import * as chocolateyCli from "./ChocolateyCliManager"; import * as chocolateyOps from "./ChocolateyOperation"; import * as path from "path"; @@ -7,6 +9,13 @@ import * as fs from "fs"; var chocolateyManager : chocolateyCli.ChocolateyCliManager; var installed : boolean = false; +const languageServerPaths = [ + // TODO: Change path to the actually expected location of the language server + "out/.server/Chocolatey.Language.Server.dll", + "./src/Chocolatey.Language.Server/bin/Release/netcoreapp2.1/Chocolatey.Language.Server.dll", + "./src/Chocolatey.Language.Server/bin/Debug/netcoreapp2.1/Chocolatey.Language.Server.dll" +]; + export function activate(context: ExtensionContext): void { // register Commands context.subscriptions.push( @@ -18,6 +27,65 @@ export function activate(context: ExtensionContext): void { commands.registerCommand("chocolatey.apikey", () => execute("apikey")), commands.registerCommand("chocolatey.open", async (uri: string) => await commands.executeCommand('vscode.open', Uri.parse(uri))) ); + + let config = workspace.getConfiguration("chocolatey.language"); + let disableLanguageService: boolean | undefined = false; + + if(config !== undefined) { + disableLanguageService = config.get("disableLanguageService") + } + + // Only start the Language Service if configured to do so + if(!disableLanguageService) { + let serverExe = 'dotnet'; + let serverModule: string | null = null; + for (let p of languageServerPaths) { + p = context.asAbsolutePath(p); + // console.log/p); + if (fs.existsSync(p)) { + serverModule = p; + break; + } + } + + // TODO: Decision need to be made if the Language Server should + // be packed inside the vsix file, or downloaded during runtime. + + if (!serverModule) { throw new URIError("Cannot find the language server module."); } + let workPath = path.dirname(serverModule); + console.log(`Use ${serverModule} as server module.`); + console.log(`Work path: ${workPath}`); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run: { command: serverExe, args: [serverModule], options: { cwd: workPath } }, + debug: { command: serverExe, args: [serverModule, "--debug"], options: { cwd: workPath } } + }; + + // Options to control the language client + let clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [ + { + pattern: '**/*.nuspec', + } + ], + synchronize: { + configurationSection: 'chocolatey', + fileEvents: workspace.createFileSystemWatcher('**/*.nuspec') + }, + } + + // Create the language client and start the client. + const client = new LanguageClient('chocolatey', 'Chocolatey Language Server', serverOptions, clientOptions); + client.trace = Trace.Verbose; + let disposable = client.start(); + + // Push the disposable to the context's subscriptions so that the + // client can be deactivated on extension deactivation + context.subscriptions.push(disposable); + } } function deleteNupkgs():void {