refactor language server using typescript

This commit is contained in:
全卓 2022-10-10 11:04:15 +08:00
parent 8fa5259d87
commit 7d6bbe529c
21 changed files with 1693 additions and 1034 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ node_modules
.vscode-test/
*.vsix
syntaxes/*.json
tsconfig.tsbuildinfo

208
client/package-lock.json generated Normal file
View File

@ -0,0 +1,208 @@
{
"name": "cmake-intellisence-client",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "cmake-intellisence-client",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"vscode-languageclient": "^8.0.2"
},
"devDependencies": {
"@types/vscode": "^1.68.0"
},
"engines": {
"vscode": "^1.68.0"
}
},
"node_modules/@types/vscode": {
"version": "1.72.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.72.0.tgz",
"integrity": "sha512-WvHluhUo+lQvE3I4wUagRpnkHuysB4qSyOQUyIAS9n9PYMJjepzTUD8Jyks0YeXoPD0UGctjqp2u84/b3v6Ydw==",
"dev": true
},
"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=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/vscode-jsonrpc": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz",
"integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/vscode-languageclient": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.2.tgz",
"integrity": "sha512-lHlthJtphG9gibGb/y72CKqQUxwPsMXijJVpHEC2bvbFqxmkj9LwQ3aGU9dwjBLqsX1S4KjShYppLvg1UJDF/Q==",
"dependencies": {
"minimatch": "^3.0.4",
"semver": "^7.3.5",
"vscode-languageserver-protocol": "3.17.2"
},
"engines": {
"vscode": "^1.67.0"
}
},
"node_modules/vscode-languageserver-protocol": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz",
"integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==",
"dependencies": {
"vscode-jsonrpc": "8.0.2",
"vscode-languageserver-types": "3.17.2"
}
},
"node_modules/vscode-languageserver-types": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
},
"dependencies": {
"@types/vscode": {
"version": "1.72.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.72.0.tgz",
"integrity": "sha512-WvHluhUo+lQvE3I4wUagRpnkHuysB4qSyOQUyIAS9n9PYMJjepzTUD8Jyks0YeXoPD0UGctjqp2u84/b3v6Ydw==",
"dev": true
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"requires": {
"lru-cache": "^6.0.0"
}
},
"vscode-jsonrpc": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz",
"integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ=="
},
"vscode-languageclient": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.2.tgz",
"integrity": "sha512-lHlthJtphG9gibGb/y72CKqQUxwPsMXijJVpHEC2bvbFqxmkj9LwQ3aGU9dwjBLqsX1S4KjShYppLvg1UJDF/Q==",
"requires": {
"minimatch": "^3.0.4",
"semver": "^7.3.5",
"vscode-languageserver-protocol": "3.17.2"
}
},
"vscode-languageserver-protocol": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz",
"integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==",
"requires": {
"vscode-jsonrpc": "8.0.2",
"vscode-languageserver-types": "3.17.2"
}
},
"vscode-languageserver-types": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
}

21
client/package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "cmake-intellisence-client",
"version": "1.0.0",
"description": "Language Client for CMake IntelliSence extension",
"author": "quanzhuo",
"license": "MIT",
"publisher": "openKylin",
"engines": {
"vscode": "^1.68.0"
},
"repository": {
"type": "git",
"url": "https://gitee.com/openkylin/cmake-intellisence"
},
"dependencies": {
"vscode-languageclient": "^8.0.2"
},
"devDependencies": {
"@types/vscode": "^1.68.0"
}
}

73
client/src/extension.ts Normal file
View File

@ -0,0 +1,73 @@
import * as path from 'path';
import { getConfigLogLevel, Logger } from './logging';
import { workspace, ExtensionContext } from 'vscode';
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
TransportKind
} from 'vscode-languageclient/node';
export const SERVER_ID = 'cmakeIntelliSence';
export const SERVER_NAME = 'CMake Language Server';
let client: LanguageClient;
export function activate(context: ExtensionContext) {
const config = workspace.getConfiguration(SERVER_ID);
const logger = new Logger();
logger.setLogLevel(getConfigLogLevel(config));
context.subscriptions.push(workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration(`${SERVER_ID}.loggingLevel`)) {
logger.setLogLevel(getConfigLogLevel(config));
}
}));
const serverModule = context.asAbsolutePath(
path.join('server', 'out', 'server.js')
);
// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
// If the extension is lanched 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: debugOptions
}
};
// Options to control the language client
const clientOptions: LanguageClientOptions = {
documentSelector: [
{ language: 'cmake', scheme: 'file' },
{ language: 'cmake', scheme: 'untitled' }
],
outputChannel: logger.getOutputChannel()
};
client = new LanguageClient(SERVER_ID, SERVER_NAME, serverOptions, clientOptions);
// start the client. This will also launch the server
logger.info(`Start ${SERVER_NAME} ...`);
client.start();
}
export function deactivate() {
if (!client) {
return undefined;
}
return client.stop();
}

10
client/tsconfig.json Normal file
View File

@ -0,0 +1,10 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "out",
"rootDir": "src",
},
"include": [
"src"
]
}

781
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,10 @@
"engines": {
"vscode": "^1.68.0"
},
"repository": {
"type": "git",
"url": "https://gitee.com/openkylin/cmake-intellisence"
},
"categories": [
"Programming Languages",
"Snippets",
@ -15,7 +19,7 @@
"onLanguage:cmake",
"workspaceContains:CMakeLists.txt"
],
"main": "./out/extension.js",
"main": "./client/out/extension",
"contributes": {
"grammars": [
{
@ -67,7 +71,7 @@
"path": "./snippets.json"
}
],
"configuration":[
"configuration": [
{
"title": "CMake IntelliSence",
"properties": {
@ -107,27 +111,21 @@
"grammar-cmakecache": "npx js-yaml ./syntaxes/cmakecache.tmLanguage.yml > ./syntaxes/cmakecache.tmLanguage.json",
"grammar-cmdsignature": "npx js-yaml ./syntaxes/cmdsignature.tmLanguage.yml > ./syntaxes/cmdsignature.tmLanguage.json",
"grammar": "node ./build/yaml-to-json.mjs",
"compile": "npm run grammar && tsc -p ./",
"watch": "npm run grammar && tsc -watch -p ./",
"compile": "npm run grammar && tsc -b . --verbose",
"watch": "npm run grammar && tsc -watch -b . --verbose",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
"test": "node ./out/test/runTest.js",
"postinstall": "cd client && npm install && cd ../server && npm install && cd .."
},
"devDependencies": {
"@types/glob": "^7.2.0",
"@types/mocha": "^9.1.1",
"@types/node": "16.x",
"@types/vscode": "^1.68.0",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
"@vscode/test-electron": "^2.1.5",
"eslint": "^8.20.0",
"glob": "^8.0.3",
"js-yaml": "^4.1.0",
"mocha": "^10.0.0",
"typescript": "^4.7.4"
},
"dependencies": {
"vscode-languageclient": "^8.0.2"
"typescript": "^4.8.4"
}
}

92
server/package-lock.json generated Normal file
View File

@ -0,0 +1,92 @@
{
"name": "cmake-intellisence-server",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "cmake-intellisence-server",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"vscode-languageserver": "^8.0.2",
"vscode-languageserver-textdocument": "^1.0.7"
},
"engines": {
"node": "*"
}
},
"node_modules/vscode-jsonrpc": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz",
"integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/vscode-languageserver": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.2.tgz",
"integrity": "sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==",
"dependencies": {
"vscode-languageserver-protocol": "3.17.2"
},
"bin": {
"installServerIntoExtension": "bin/installServerIntoExtension"
}
},
"node_modules/vscode-languageserver-protocol": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz",
"integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==",
"dependencies": {
"vscode-jsonrpc": "8.0.2",
"vscode-languageserver-types": "3.17.2"
}
},
"node_modules/vscode-languageserver-textdocument": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz",
"integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg=="
},
"node_modules/vscode-languageserver-types": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="
}
},
"dependencies": {
"vscode-jsonrpc": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz",
"integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ=="
},
"vscode-languageserver": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.2.tgz",
"integrity": "sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==",
"requires": {
"vscode-languageserver-protocol": "3.17.2"
}
},
"vscode-languageserver-protocol": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz",
"integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==",
"requires": {
"vscode-jsonrpc": "8.0.2",
"vscode-languageserver-types": "3.17.2"
}
},
"vscode-languageserver-textdocument": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz",
"integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg=="
},
"vscode-languageserver-types": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="
}
}
}

18
server/package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "cmake-intellisence-server",
"version": "1.0.0",
"description": "Language Server for CMake IntelliSence extension",
"author": "quanzhuo",
"license": "MIT",
"engines": {
"node": "*"
},
"repository": {
"type": "git",
"url": "https://gitee.com/openkylin/cmake-intellisence"
},
"dependencies": {
"vscode-languageserver": "^8.0.2",
"vscode-languageserver-textdocument": "^1.0.7"
}
}

1049
server/src/builtin-cmds.json Normal file

File diff suppressed because it is too large Load Diff

145
server/src/server.ts Normal file
View File

@ -0,0 +1,145 @@
import {
createConnection,
TextDocuments,
ProposedFeatures,
InitializeParams,
InitializeResult,
TextDocumentSyncKind,
HoverParams,
SignatureHelpParams
} from 'vscode-languageserver/node';
import { TextDocument, Range } from 'vscode-languageserver-textdocument';
import { Position } from 'vscode-languageserver-types';
import * as builtinCmds from './builtin-cmds.json';
import { Entries, getBuiltinEntries } from './utils';
import { exec } from 'child_process';
const entries: Entries = getBuiltinEntries();
const modules = entries[0].split('\n');
const policies = entries[1].split('\n');
const variables = entries[2].split('\n');
const properties = entries[3].split('\n');;
// Craete 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: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
connection.onInitialize((params: InitializeParams) => {
const result: InitializeResult = {
capabilities: {
textDocumentSync: TextDocumentSyncKind.Incremental,
hoverProvider: true,
signatureHelpProvider: {
triggerCharacters: ['('],
retriggerCharacters: [' ']
}
},
serverInfo: {
name: 'cmakels',
version: '0.1'
}
};
return result;
});
connection.onInitialized(() => {
console.log("Initialized");
});
connection.onHover((params: HoverParams) => {
const document: TextDocument = documents.get(params.textDocument.uri);
const word = getWordAtPosition(document, params.position);
if (word.length === 0) {
return undefined;
}
// check if the word is a builtin commands
if (word in builtinCmds) {
const sigs = '```cmdsignature\n'
+ builtinCmds[word]['sig'].join('\n')
+ '\n```';
const cmdHelp: string = builtinCmds[word]['doc'] + '\n' + sigs;
return {
contents: {
kind: 'markdown',
value: cmdHelp
}
};
}
let moduleArg = '';
if (modules.includes(word)) {
const line = document.getText({
start: { line: params.position.line, character: 0 },
end: { line: params.position.line, character: Number.MAX_VALUE }
});
if (line.trim().startsWith('include')) {
moduleArg = '--help-module ';
}
} else if (policies.includes(word)) {
moduleArg = '--help-policy ';
} else if (variables.includes(word)) {
moduleArg = '--help-variable ';
} else if (properties.includes(word)) {
moduleArg = '--help-property ';
}
if (moduleArg.length !== 0) {
const command = 'cmake ' + moduleArg + word;
return new Promise((resolve, rejects) => {
exec(command, (error, stdout, stderr) => {
if (error) {
rejects(error);
}
resolve({
contents: {
kind: 'plaintext',
value: stdout
}
});
});
});
}
});
connection.onSignatureHelp((params: SignatureHelpParams) => {
return null;
});
// 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(change => {
console.log('content changed');
});
function getWordAtPosition(textDocument: TextDocument, position: Position): string {
const lineRange: Range = {
start: { line: position.line, character: 0 },
end: { line: position.line, character: Number.MAX_VALUE }
};
const line = textDocument.getText(lineRange),
start = line.substring(0, position.character),
end = line.substring(position.character);
// TODO: the regex expression capture numbers, fix it.
const startReg = /[a-zA-Z0-9_]*$/,
endReg = /^[a-zA-Z0-9_]*/;
const startWord = start.match(startReg)[0],
endWord = end.match(endReg)[0];
return startWord + endWord;
}
// 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();

11
server/src/utils.ts Normal file
View File

@ -0,0 +1,11 @@
import * as cp from 'child_process';
export type Entries = [string, string, string, string];
export function getBuiltinEntries(): Entries {
const args = ['cmake', '--help-module-list', '--help-policy-list',
'--help-variable-list', '--help-property-list'];
const cmd: string = args.join(' ');
const output = cp.execSync(cmd, { encoding: 'utf-8' });
return output.trim().split('\n\n\n') as Entries;
}

12
server/tsconfig.json Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "out",
"rootDir": "src",
"resolveJsonModule": true
},
"files": [ "src/builtin-cmds.json" ],
"include": [
"src"
]
}

View File

@ -1,72 +0,0 @@
import * as net from 'net';
import * as vscode from 'vscode';
import { getConfigLogLevel, Logger } from './logging';
import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node';
export const SERVER_ID = 'cmakeIntelliSence';
export const SERVER_NAME = 'CMake Language Server';
let client: LanguageClient;
export function activate(context: vscode.ExtensionContext) {
const config = vscode.workspace.getConfiguration(SERVER_ID);
const logger = new Logger();
logger.setLogLevel(getConfigLogLevel(config));
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration(`${SERVER_ID}.loggingLevel`)) {
logger.setLogLevel(getConfigLogLevel(config));
}
}));
// Options to control the language client
const clientOptions: LanguageClientOptions = {
documentSelector: [
{ language: 'cmake', scheme: 'file' },
{ language: 'cmake', scheme: 'untitled' }
],
outputChannel: logger.getOutputChannel()
};
// language server options
let serverOptions: ServerOptions;
let mode: string;
if (context.extensionMode === vscode.ExtensionMode.Development) {
// Development - communicate using tcp
serverOptions = () => {
return new Promise((resolve) => {
const clientSocket = new net.Socket();
clientSocket.connect(2088, "127.0.0.1", () => {
resolve({
reader: clientSocket,
writer: clientSocket
});
});
clientSocket.on('connect', () => { logger.info('Connected'); });
clientSocket.on('error', (err) => { logger.info('error', err); });
clientSocket.on('close', () => { logger.info('connection closed'); });
});
};
mode = 'Development';
} else {
// Production - communicate using stdio
serverOptions = {
command: 'cmakels'
};
mode = 'Production';
}
client = new LanguageClient(SERVER_ID, SERVER_NAME, serverOptions, clientOptions);
// start the client. This will also launch the server
logger.info(`Start ${SERVER_NAME} in ${mode} mode...`);
client.start();
}
export function deactivate() {
if (!client) {
return undefined;
}
return client.stop();
}

View File

@ -1,101 +0,0 @@
# This file is used to test the cmake-ls extension
cmake_minimum_required(VERSION 3.0)
project(Demo
VERSION 1.0
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
#[=[
This is bracket block comment
The second line in comment
]=]
# test bracket parameter
set(BRAKET_PARA [=[
First line in bracket parameter
Second line in bracket parameter
]=])
# numbers
set(DIGIT 100)
set(DIGIT 100.1)
# boolean constant
set(BOOL_TRUE YES)
set(BOOL_TRUE TRUE)
set(BOOL_FALSE NO)
set(BOOL_FALSE NOTFOUND)
set(BOOL_FALSE A-NOTFOUND)
# deprecated command
exec_program(dir)
install_files(dest so libc.so)
# flow control commands
if(TRUE)
message(STATUS "This message will print")
endif()
set(INDEX 1)
while(TRUE)
message(STATUS ${INDEX})
math(EXPR INDEX "${INDEX} + 1")
if (INDEX EQUAL 11)
break()
endif()
endwhile()
foreach(INDEX RANGE 10)
message(STATUS ${INDEX})
endforeach()
# operator
if(DEFINED undefined_function)
endif()
if ("gaga" STRLESS_EQUAL "haha")
endif()
if (TRUE AND FALSE)
endif()
# usr defined functions
function(print)
foreach(ARG IN LISTS ARGV)
endforeach()
endfunction()
macro(macro_print)
endmacro()
# test for cache variable
set(STR_VAR "demo string" CACHE STRING "This is docstring" FORCE)
set(BOOL_VAR "demo bool" CACHE BOOL "This is docstring" FORCE)
set(FILEPATH_VAR "demo filepath" CACHE FILEPATH "This is docstring" FORCE)
set(PATH_VAR "demo path" CACHE PATH "This is docstring" FORCE)
set(INTERNAL_VAR "demo internal" CACHE INTERNAL "This is docstring" FORCE)
# variable reference
message(STATUS $ENV{PATH})
message(STATUS $CACHE{CMAKE_BUILD_TYPE})
message(STATUS "$ENV{PATH} plain strings")
message(STATUS "$CACHE{CMAKE_BUILD_TYPE}")
message(STATUS "${PATH}")
message(STATUS "${CMAKE_BUILD_TYPE}")
# generator expression
# The $<BOOL:...> check prevents adding anything if the property is empty,
# assuming the property value cannot be one of CMake's false constants.
set(prop $<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>)
set(prop "$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>")
add_custom_target(run_some_tool
COMMAND some_tool "$<$<BOOL:${prop}>:-I$<JOIN:${prop},;-I>>"
COMMAND_EXPAND_LISTS
VERBATIM
)
# string escape
set(VAR "This a \"in string")

View File

@ -1,23 +0,0 @@
import * as path from 'path';
import { runTests } from '@vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
// The path to test runner
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './suite/index');
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.error('Failed to run tests');
process.exit(1);
}
}
main();

View File

@ -1,15 +0,0 @@
import * as assert from 'assert';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../../extension';
suite('Extension Test Suite', () => {
vscode.window.showInformationMessage('Start all tests.');
test('Sample test', () => {
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
});
});

View File

@ -1,38 +0,0 @@
import * as path from 'path';
import * as Mocha from 'mocha';
import * as glob from 'glob';
export function run(): Promise<void> {
// Create the mocha test
const mocha = new Mocha({
ui: 'tdd',
color: true
});
const testsRoot = path.resolve(__dirname, '..');
return new Promise((c, e) => {
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
if (err) {
return e(err);
}
// Add files to the test suite
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
try {
// Run the mocha test
mocha.run(failures => {
if (failures > 0) {
e(new Error(`${failures} tests failed.`));
} else {
c();
}
});
} catch (err) {
console.error(err);
e(err);
}
});
});
}

11
tsconfig.base.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2020",
"lib": [
"es2020"
],
"sourceMap": true,
"composite": true
}
}

View File

@ -1,17 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"outDir": "out",
"lib": [
"ES2020"
],
"sourceMap": true,
"rootDir": "src",
"strict": true /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
}
"include": [],
"references": [
{ "path": "./client" },
{ "path": "./server" }
]
}