diff --git a/configurations/.eslintrc.js b/configurations/.eslintrc.js index 6df302e..19a8d5c 100644 --- a/configurations/.eslintrc.js +++ b/configurations/.eslintrc.js @@ -10,7 +10,8 @@ module.exports = { parserOptions: { ecmaVersion: 6, sourceType: "module", - project: "./tsconfig.json", + // I need to create another dummy tsconfig within this folder for these files to be linted + project: ["./tsconfig.json", "lsp-task-expression/tsconfig.json"], }, plugins: ["@typescript-eslint", "unused-imports", "prettier"], @@ -68,8 +69,8 @@ module.exports = { "out", "dist", "**/*.d.ts", - "**/*.js", - "**/*.mjs", + "**/out", "testing-sandbox", + "configurations" ], }; diff --git a/configurations/webpack.config.js b/configurations/webpack.config.js index 25dc530..5f8ddb2 100644 --- a/configurations/webpack.config.js +++ b/configurations/webpack.config.js @@ -1,57 +1,63 @@ /* eslint-disable @typescript-eslint/no-var-requires */ //@ts-check -"use strict"; +'use strict' -const resolve = require("path").resolve; -const fs = require("fs"); +const path = require('path') +const fs = require('fs') // Assumes the script is executed from the root of the project -const projectRoot = process.cwd(); +const projectRoot = process.cwd() -// Generate the alias object for all the folders in the 'src' folder to use absolute import paths -const srcDir = resolve(projectRoot, "src"); +/* Generate the alias object for all the folders in the 'src' folder to use + absolute import paths */ +const srcDir = path.resolve(projectRoot, 'src') -// Read the directories in the 'src' folder -// To allow absolute imports from all the folders in 'src' -// For example instead of using 'src/extension' we can use 'extension' +/* Read the directories in the 'src' folder + To allow absolute imports from all the folders in 'src' + For example instead of using 'src/extension' we can use 'extension' */ const dirs = fs .readdirSync(srcDir, { withFileTypes: true }) .filter((dirent) => dirent.isDirectory()) - .map((dirent) => dirent.name); + .map((dirent) => dirent.name) -// Augment with the 'src' folder itself for files like 'src/execution-context.ts'?. -// Ignoring this problem for now and disallowing top level files +/* Augment with the 'src' folder itself for files like + 'src/execution-context.ts'?. Ignoring this problem for now and disallowing + top level files */ // Generate the alias object const aliasForAllSrcFolders = dirs.reduce((acc, dir) => { - acc[dir] = resolve(srcDir, dir); - return acc; -}, {}); + acc[dir] = path.resolve(srcDir, dir) + return acc +}, {}) //@ts-check /** @typedef {import('webpack').Configuration} WebpackConfig **/ /** @type WebpackConfig */ const extensionConfig = { - target: "node", // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ - mode: "none", // this leaves the source code as close as possible to the original (when packaging we set this to 'production') + target: 'node', // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ + mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') - entry: "./src/extension.ts", // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ + // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ + entry: { + extension: './src/extension.ts', + server: './lsp-task-expression/src/server.ts', + }, output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ - path: resolve(projectRoot, "dist"), - filename: "extension.js", - libraryTarget: "commonjs2", + path: path.resolve(projectRoot, 'dist'), + filename: '[name].js', + libraryTarget: 'commonjs2', clean: true, // clean the output folder before building }, externals: { - vscode: "commonjs vscode", // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ + vscode: 'commonjs vscode', // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ // modules added here also need to be added in the .vscodeignore file }, resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader - extensions: [".ts", ".js"], + extensions: ['.ts', '.js'], alias: aliasForAllSrcFolders, }, @@ -59,18 +65,34 @@ const extensionConfig = { rules: [ { test: /src\/.*\.ts$/, - exclude: /node_modules/, + exclude: [/node_modules/, /lsp-task-expression/], + use: [ + { + loader: 'ts-loader', + }, + ], + }, + { + test: /lsp-task-expression\/.*\.ts$/, + include: path.resolve(projectRoot, 'lsp-task-expression/src'), + exclude: path.resolve(projectRoot, 'lsp-task-expression/node_modules'), use: [ { - loader: "ts-loader", + loader: 'ts-loader', + options: { + configFile: path.resolve( + projectRoot, + 'lsp-task-expression/tsconfig.json', + ), + }, }, ], }, ], }, - devtool: "nosources-source-map", + devtool: 'inline-source-map', infrastructureLogging: { - level: "log", // enables logging required for problem matchers + level: 'log', // enables logging required for problem matchers }, -}; -module.exports = [extensionConfig]; +} +module.exports = [extensionConfig] diff --git a/lsp-task-expression/package-lock.json b/lsp-task-expression/package-lock.json new file mode 100644 index 0000000..33ef84a --- /dev/null +++ b/lsp-task-expression/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "lsp-sample-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lsp-sample-server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "vscode-languageserver": "^8.1.0", + "vscode-languageserver-textdocument": "^1.0.8" + }, + "engines": { + "node": "*" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.1.0.tgz", + "integrity": "sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.1.0.tgz", + "integrity": "sha512-eUt8f1z2N2IEUDBsKaNapkz7jl5QpskN2Y0G01T/ItMxBxw1fJwvtySGB9QMecatne8jFIWJGWI61dWjyTLQsw==", + "dependencies": { + "vscode-languageserver-protocol": "3.17.3" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.3.tgz", + "integrity": "sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==", + "dependencies": { + "vscode-jsonrpc": "8.1.0", + "vscode-languageserver-types": "3.17.3" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.3.tgz", + "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==" + } + } +} diff --git a/lsp-task-expression/package.json b/lsp-task-expression/package.json new file mode 100644 index 0000000..fc48396 --- /dev/null +++ b/lsp-task-expression/package.json @@ -0,0 +1,19 @@ +{ + "name": "lsp-sample-server", + "description": "Example implementation of a language server in node.", + "version": "1.0.0", + "author": "Microsoft Corporation", + "license": "MIT", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "dependencies": { + "vscode-languageserver": "^8.1.0", + "vscode-languageserver-textdocument": "^1.0.8" + }, + "scripts": {} +} diff --git a/lsp-task-expression/src/server.ts b/lsp-task-expression/src/server.ts new file mode 100644 index 0000000..cddc250 --- /dev/null +++ b/lsp-task-expression/src/server.ts @@ -0,0 +1,234 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * ------------------------------------------------------------------------------------------ + */ +import { + createConnection, + TextDocuments, + Diagnostic, + DiagnosticSeverity, + ProposedFeatures, + InitializeParams, + DidChangeConfigurationNotification, + CompletionItem, + CompletionItemKind, + TextDocumentPositionParams, + TextDocumentSyncKind, + InitializeResult, +} from 'vscode-languageserver/node' + +import { TextDocument } from 'vscode-languageserver-textdocument' + +///////////// Copied over from lsp-sample, vscode-extension-samples/lsp-sample/server/src/server.ts ////////// + +/* Create a connection for the server, using Node's IPC as a transport. + Also include all preview / proposed LSP features. */ +const connection = createConnection(ProposedFeatures.all) + +// Create a simple text document manager. +const documents = new TextDocuments(TextDocument) + +let hasConfigurationCapability = false +let hasWorkspaceFolderCapability = false +let hasDiagnosticRelatedInformationCapability = false + +connection.onInitialize((params: InitializeParams) => { + const capabilities = params.capabilities + + /* Does the client support the `workspace/configuration` request? + If not, we fall back using global settings. */ + hasConfigurationCapability = !!( + capabilities.workspace && !!capabilities.workspace.configuration + ) + hasWorkspaceFolderCapability = !!( + capabilities.workspace && !!capabilities.workspace.workspaceFolders + ) + hasDiagnosticRelatedInformationCapability = + !!capabilities.textDocument?.publishDiagnostics?.relatedInformation + + const result: InitializeResult = { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Incremental, + // Tell the client that this server supports code completion. + completionProvider: { + resolveProvider: true, + }, + }, + } + if (hasWorkspaceFolderCapability) { + result.capabilities.workspace = { + workspaceFolders: { + supported: true, + }, + } + } + return result +}) + +connection.onInitialized(() => { + if (hasConfigurationCapability) { + // Register for all configuration changes. + void connection.client.register( + DidChangeConfigurationNotification.type, + undefined, + ) + } + if (hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders((_event) => { + connection.console.log('Workspace folder change event received.') + }) + } +}) + +// The example settings +interface ExampleSettings { + maxNumberOfProblems: number +} + +/* The global settings, used when the `workspace/configuration` request is not + supported by the client. Please note that this is not the case when using + this server with the client provided in this example but could happen with + other clients. */ +const defaultSettings: ExampleSettings = { maxNumberOfProblems: 1000 } +let globalSettings: ExampleSettings = defaultSettings + +// Cache the settings of all open documents +const documentSettings = new Map>() + +connection.onDidChangeConfiguration((change) => { + if (hasConfigurationCapability) { + // Reset all cached document settings + documentSettings.clear() + } else { + globalSettings = + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + (change?.settings?.languageServerExample as ExampleSettings) ?? + defaultSettings + } + + // Revalidate all open text documents + for (const document of documents.all()) { + void validateTextDocument(document) + } +}) + +function getDocumentSettings(resource: string): Thenable { + if (!hasConfigurationCapability) { + return Promise.resolve(globalSettings) + } + let result = documentSettings.get(resource) + // eslint-disable-next-line @typescript-eslint/no-misused-promises + if (!result) { + result = connection.workspace.getConfiguration({ + scopeUri: resource, + section: 'languageServerExample', + }) + documentSettings.set(resource, result) + } + return result +} + +// Only keep settings for open documents +documents.onDidClose((e) => { + documentSettings.delete(e.document.uri) +}) + +/* The content of a text document has changed. This event is emitted + when the text document first opened or when its content has changed. */ +documents.onDidChangeContent(async (change) => { + await validateTextDocument(change.document) +}) + +async function validateTextDocument(textDocument: TextDocument): Promise { + // In this simple example we get the settings for every validate run. + const settings = await getDocumentSettings(textDocument.uri) + + // The validator creates diagnostics for all uppercase words length 2 and more + const text = textDocument.getText() + const pattern = /\b[A-Z]{2,}\b/g + let m: RegExpExecArray | null + + let problems = 0 + const diagnostics: Diagnostic[] = [] + while ((m = pattern.exec(text)) && problems < settings.maxNumberOfProblems) { + problems++ + const diagnostic: Diagnostic = { + severity: DiagnosticSeverity.Warning, + range: { + start: textDocument.positionAt(m.index), + end: textDocument.positionAt(m.index + m[0].length), + }, + message: `${m[0]} is all uppercase.`, + source: 'ex', + } + if (hasDiagnosticRelatedInformationCapability) { + diagnostic.relatedInformation = [ + { + location: { + uri: textDocument.uri, + range: Object.assign({}, diagnostic.range), + }, + message: 'Spelling matters', + }, + { + location: { + uri: textDocument.uri, + range: Object.assign({}, diagnostic.range), + }, + message: 'Particularly for names', + }, + ] + } + diagnostics.push(diagnostic) + } + + // Send the computed diagnostics to VSCode. + await connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }) +} + +connection.onDidChangeWatchedFiles((_change) => { + // Monitored files have change in VSCode + connection.console.log('We received an file change event') +}) + +/* https://github.com/microsoft/vscode/blob/ba36ae4dcca57ba64a9b61e5f4eca88b6e0bc4db/extensions/typescript-language-features/src/languageFeatures/directiveCommentCompletions.ts#L20 + Directives might be different from completions, + This handler provides the initial list of the completion items. */ +connection.onCompletion( + (_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => { + /* WARNING FAILURE, @ prefixed keywords are not being suggested, + * I have also realized there is a much easier way to provide completions + * with completion providers. I NEVER NEEDED THE LANGUAGE SERVER GODDAMN + * IT. Putting on a branch and forgetting about it + */ + const keywords = ['@' + 'taskkkkkk', 'runningShoes', 'tabs', 'errors'] + + return keywords.map((keyword, index) => ({ + label: `${keyword}`, + kind: CompletionItemKind.Text, + data: index + 1, + })) + }, +) + +/* This handler resolves additional information for the item selected in + the completion list. */ +connection.onCompletionResolve((item: CompletionItem): CompletionItem => { + if (item.data === 1) { + item.detail = 'TypeScript details' + item.documentation = 'TypeScript documentation' + } else if (item.data === 2) { + item.detail = 'JavaScript details' + item.documentation = 'JavaScript documentation' + } + return item +}) + +/* Make the text document manager listen on the connection + for open, change and close text document events */ +documents.listen(connection) + +// Listen on the connection +connection.listen() diff --git a/lsp-task-expression/tsconfig.json b/lsp-task-expression/tsconfig.json new file mode 100644 index 0000000..c28f985 --- /dev/null +++ b/lsp-task-expression/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020" + ], + "module": "commonjs", + "moduleResolution": "node", + "inlineSourceMap": true, + "strictNullChecks": true, + // "strict": true, + "outDir": "out", + "rootDir": "src", + "composite": true, + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ee878fb..1b7a434 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "ai-task", - "version": "0.0.11", + "version": "0.0.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ai-task", - "version": "0.0.11", + "version": "0.0.13", "license": "Business Source License 1.1", "dependencies": { "dedent": "^1.5.1", "ix": "^5.0.0", - "openai": "^4.0.0" + "openai": "^4.0.0", + "vscode-languageclient": "^9.0.1" }, "devDependencies": { "@types/glob": "^8.1.0", @@ -989,8 +990,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base-64": { "version": "0.1.0", @@ -3302,7 +3302,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4545,7 +4544,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -5246,6 +5244,60 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -5543,8 +5595,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "16.2.0", diff --git a/package.json b/package.json index 408233f..d1467b0 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "dependencies": { "dedent": "^1.5.1", "ix": "^5.0.0", - "openai": "^4.0.0" + "openai": "^4.0.0", + "vscode-languageclient": "^9.0.1" } } \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index e274c01..d6bb7a1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,16 @@ import { completeInlineTasksCommand } from 'commands/completeInlineTasks' import { SessionContext } from 'session' import * as vscode from 'vscode' +import * as path from 'path' + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from 'vscode-languageclient/node' + +let client: LanguageClient | undefined export function activate(context: vscode.ExtensionContext) { console.log('activating bread extension') @@ -62,4 +72,48 @@ export function activate(context: vscode.ExtensionContext) { } }), ) + + /* Kickoff language server + The server is implemented in node */ + const serverModule = context.asAbsolutePath(path.join('dist', 'server.js')) + + /* If the extension is launched in debug mode then the debug server options + are used Otherwise the run options are used */ + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + }, + } + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for all types of text documents + documentSelector: [{ scheme: 'file', language: '*' }], + synchronize: { + /* + * IS THIS UNUSED? Notify the server about file changes to '.clientrc + * files contained in + the workspace */ + fileEvents: vscode.workspace.createFileSystemWatcher('**/.clientrc'), + }, + } + + // Create the language client and start the client. + client = new LanguageClient( + 'languageServerAiTask', + 'Language Server AI Task', + serverOptions, + clientOptions, + ) + + // Start the client. This will also launch the server + void client.start().catch((err) => { + console.error('error starting language server', err) + }) +} + +export async function deactivate() { + await client?.stop() } diff --git a/tsconfig.json b/tsconfig.json index 8ae7594..0fb21b6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,15 @@ "baseUrl": "src", }, "include": [ - "src/**/*", + "src/", + // eslint is giving me a hard time because it wants to reference a single project configuration, but we have a composite project + // "configurations/" ], + // We have a dependency typescript package that creates a language server bundle that needs to be rebuild when we are creating the extension + // https://www.typescriptlang.org/docs/handbook/project-references.html#what-is-a-project-reference + "references": [ + { + "path": "lsp-task-expression" + } + ] } \ No newline at end of file