built in commands variables auto complete

This commit is contained in:
全卓 2022-10-11 13:49:33 +08:00
parent 7d6bbe529c
commit cb0ccc155c
4 changed files with 106 additions and 39 deletions

View File

@ -13,7 +13,7 @@ function isGrammarOutdate(fileName) {
const yaml = json.replace('.json', '.yml'); const yaml = json.replace('.json', '.yml');
const jsonState = statSync(json); const jsonState = statSync(json);
const yamlState = statSync(yaml); const yamlState = statSync(yaml);
if (yamlState.mtime.toString() > jsonState.mtime.toString()) { if (yamlState.mtimeMs > jsonState.mtimeMs) {
console.log(`${yaml} changed, Grammar is outdate, re-generate it.`); console.log(`${yaml} changed, Grammar is outdate, re-generate it.`);
return true; return true;
} }

View File

@ -107,16 +107,16 @@
}, },
"scripts": { "scripts": {
"vscode:prepublish": "npm run compile", "vscode:prepublish": "npm run compile",
"grammar-cmake": "npx js-yaml ./syntaxes/cmake.tmLanguage.yml > ./syntaxes/cmake.tmLanguage.json",
"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 -b . --verbose", "compile": "npm run grammar && tsc -b . --verbose",
"watch": "npm run grammar && tsc -watch -b . --verbose", "watch": "npm run grammar && tsc -watch -b . --verbose",
"pretest": "npm run compile && npm run lint", "pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts", "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 .." "postinstall": "cd client && npm install && cd ../server && npm install && cd ..",
"grammar-cmake": "npx js-yaml ./syntaxes/cmake.tmLanguage.yml > ./syntaxes/cmake.tmLanguage.json",
"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"
}, },
"devDependencies": { "devDependencies": {
"@types/mocha": "^9.1.1", "@types/mocha": "^9.1.1",

View File

@ -98,7 +98,8 @@
"doc": "Disallowed since version 3.0. Sets the specified variable to a string representing the platform and compiler settings", "doc": "Disallowed since version 3.0. Sets the specified variable to a string representing the platform and compiler settings",
"sig": [ "sig": [
"build_name(variable)" "build_name(variable)"
] ],
"deprecated": true
}, },
"cmake_host_system_information": { "cmake_host_system_information": {
"doc": "Query various host system information.", "doc": "Query various host system information.",
@ -371,7 +372,8 @@
"doc": "Run an executable program during the processing of the CMakeList.txt file.", "doc": "Run an executable program during the processing of the CMakeList.txt file.",
"sig": [ "sig": [
"exec_program(Executable [directory in which to run] [ARGS <arguments to executable>] [OUTPUT_VARIABLE <var>] [RETURN_VALUE <var>])" "exec_program(Executable [directory in which to run] [ARGS <arguments to executable>] [OUTPUT_VARIABLE <var>] [RETURN_VALUE <var>])"
] ],
"deprecated": true
}, },
"execute_process": { "execute_process": {
"doc": "Execute one or more child processes.", "doc": "Execute one or more child processes.",
@ -392,7 +394,8 @@
"doc": "Disallowed since version 3.0. Create a file named <file> that can be included into a CMake listfile with the INCLUDE command.", "doc": "Disallowed since version 3.0. Create a file named <file> that can be included into a CMake listfile with the INCLUDE command.",
"sig": [ "sig": [
"export_library_dependencies(<file> [APPEND])" "export_library_dependencies(<file> [APPEND])"
] ],
"deprecated": true
}, },
"file": { "file": {
"doc": "File manipulation command.", "doc": "File manipulation command.",
@ -644,7 +647,8 @@
"install_files(<dir> extension file file ...)", "install_files(<dir> extension file file ...)",
"install_files(<dir> regexp)", "install_files(<dir> regexp)",
"install_files(<dir> FILES file file ...)" "install_files(<dir> FILES file file ...)"
] ],
"deprecated": true
}, },
"install_programs": { "install_programs": {
"doc": "Deprecated since version 3.0: Use the install(PROGRAMS) command instead.", "doc": "Deprecated since version 3.0: Use the install(PROGRAMS) command instead.",
@ -652,7 +656,8 @@
"install_programs(<dir> file1 file2 [file3 ...])", "install_programs(<dir> file1 file2 [file3 ...])",
"install_programs(<dir> FILES file1 [file2 ...])", "install_programs(<dir> FILES file1 [file2 ...])",
"install_programs(<dir> regexp)" "install_programs(<dir> regexp)"
] ],
"deprecated": true
}, },
"install_targets": { "install_targets": {
"doc": "Deprecated since version 3.0: Use the install(TARGETS) command instead.", "doc": "Deprecated since version 3.0: Use the install(TARGETS) command instead.",
@ -705,7 +710,8 @@
"doc": "Disallowed since version 3.0. See CMake Policy CMP0031. Load a command into a running CMake.", "doc": "Disallowed since version 3.0. See CMake Policy CMP0031. Load a command into a running CMake.",
"sig": [ "sig": [
"load_command(COMMAND_NAME <loc1> [loc2 ...])" "load_command(COMMAND_NAME <loc1> [loc2 ...])"
] ],
"deprecated": true
}, },
"macro": { "macro": {
"doc": "Start recording a macro for later invocation as a command.", "doc": "Start recording a macro for later invocation as a command.",
@ -717,7 +723,8 @@
"doc": "Deprecated since version 3.0: Use the file(MAKE_DIRECTORY) command instead.", "doc": "Deprecated since version 3.0: Use the file(MAKE_DIRECTORY) command instead.",
"sig": [ "sig": [
"make_directory(directory)" "make_directory(directory)"
] ],
"deprecated": true
}, },
"mark_as_advanced": { "mark_as_advanced": {
"doc": "Mark cmake cached variables as advanced.", "doc": "Mark cmake cached variables as advanced.",
@ -748,7 +755,8 @@
"doc": "Disallowed since version 3.0. See CMake Policy CMP0032.", "doc": "Disallowed since version 3.0. See CMake Policy CMP0032.",
"sig": [ "sig": [
"output_required_files(srcfile outputfile)" "output_required_files(srcfile outputfile)"
] ],
"deprecated": true
}, },
"project": { "project": {
"doc": "Set the name of the project.", "doc": "Set the name of the project.",
@ -762,19 +770,22 @@
"doc": "Deprecated since version 3.14: This command was originally added to support Qt 3 before the add_custom_command() command was sufficiently mature.", "doc": "Deprecated since version 3.14: This command was originally added to support Qt 3 before the add_custom_command() command was sufficiently mature.",
"sig": [ "sig": [
"qt_wrap_cpp(resultingLibraryName DestName SourceLists ...)" "qt_wrap_cpp(resultingLibraryName DestName SourceLists ...)"
] ],
"deprecated": true
}, },
"qt_wrap_ui": { "qt_wrap_ui": {
"doc": "Deprecated since version 3.14: This command was originally added to support Qt 3 before the add_custom_command() command was sufficiently mature.", "doc": "Deprecated since version 3.14: This command was originally added to support Qt 3 before the add_custom_command() command was sufficiently mature.",
"sig": [ "sig": [
"qt_wrap_ui(resultingLibraryName HeadersDestName SourcesDestName SourceLists ...)" "qt_wrap_ui(resultingLibraryName HeadersDestName SourcesDestName SourceLists ...)"
] ],
"deprecated": true
}, },
"remove": { "remove": {
"doc": "Deprecated since version 3.0: Use the list(REMOVE_ITEM) command instead.", "doc": "Deprecated since version 3.0: Use the list(REMOVE_ITEM) command instead.",
"sig": [ "sig": [
"remove(VAR VALUE VALUE ...)" "remove(VAR VALUE VALUE ...)"
] ],
"deprecated": true
}, },
"remove_definitions": { "remove_definitions": {
"doc": "Remove -D define flags added by add_definitions().", "doc": "Remove -D define flags added by add_definitions().",
@ -895,13 +906,15 @@
"doc": "Disallowed since version 3.0. See CMake Policy CMP0029.", "doc": "Disallowed since version 3.0. See CMake Policy CMP0029.",
"sig": [ "sig": [
"subdir_depends(subdir dep1 dep2 ...)" "subdir_depends(subdir dep1 dep2 ...)"
] ],
"deprecated": true
}, },
"subdirs": { "subdirs": {
"doc": "Deprecated since version 3.0: Use the add_subdirectory() command instead.", "doc": "Deprecated since version 3.0: Use the add_subdirectory() command instead.",
"sig": [ "sig": [
"subdirs(dir1 dir2 ...[EXCLUDE_FROM_ALL exclude_dir1 exclude_dir2 ...] [PREORDER])" "subdirs(dir1 dir2 ...[EXCLUDE_FROM_ALL exclude_dir1 exclude_dir2 ...] [PREORDER])"
] ],
"deprecated": true
}, },
"target_compile_definitions": { "target_compile_definitions": {
"doc": "Add compile definitions to a target.", "doc": "Add compile definitions to a target.",
@ -989,19 +1002,22 @@
"doc": "Disallowed since version 3.0. See CMake Policy CMP0030.", "doc": "Disallowed since version 3.0. See CMake Policy CMP0030.",
"sig": [ "sig": [
"use_mangled_mesa(PATH_TO_MESA OUTPUT_DIRECTORY)" "use_mangled_mesa(PATH_TO_MESA OUTPUT_DIRECTORY)"
] ],
"deprecated": true
}, },
"utility_source": { "utility_source": {
"doc": "Disallowed since version 3.0. See CMake Policy CMP0034.", "doc": "Disallowed since version 3.0. See CMake Policy CMP0034.",
"sig": [ "sig": [
"utility_source(cache_entry executable_name path_to_source [file1 file2 ...])" "utility_source(cache_entry executable_name path_to_source [file1 file2 ...])"
] ],
"deprecated": true
}, },
"variable_requires": { "variable_requires": {
"doc": "Disallowed since version 3.0. See CMake Policy CMP0035.", "doc": "Disallowed since version 3.0. See CMake Policy CMP0035.",
"sig": [ "sig": [
"variable_requires(TEST_VARIABLE RESULT_VARIABLE REQUIRED_VARIABLE1 REQUIRED_VARIABLE2 ...)" "variable_requires(TEST_VARIABLE RESULT_VARIABLE REQUIRED_VARIABLE1 REQUIRED_VARIABLE2 ...)"
] ],
"deprecated": true
}, },
"variable_watch": { "variable_watch": {
"doc": "Watch the CMake variable for change.", "doc": "Watch the CMake variable for change.",
@ -1044,6 +1060,7 @@
"doc": "Deprecated since version 3.0: Use the file(WRITE) command instead.", "doc": "Deprecated since version 3.0: Use the file(WRITE) command instead.",
"sig": [ "sig": [
"write_file(filename \"message to write\"... [APPEND])" "write_file(filename \"message to write\"... [APPEND])"
] ],
"deprecated": true
} }
} }

View File

@ -1,21 +1,15 @@
import { import {
createConnection, createConnection, HoverParams, InitializeParams, InitializeResult,
TextDocuments, ProposedFeatures, SignatureHelpParams, TextDocuments, TextDocumentSyncKind
ProposedFeatures,
InitializeParams,
InitializeResult,
TextDocumentSyncKind,
HoverParams,
SignatureHelpParams
} from 'vscode-languageserver/node'; } from 'vscode-languageserver/node';
import { TextDocument, Range } from 'vscode-languageserver-textdocument'; import { CompletionItemKind, CompletionParams } from 'vscode-languageserver-protocol';
import { Position } from 'vscode-languageserver-types'; import { Range, TextDocument } from 'vscode-languageserver-textdocument';
import { CompletionItem, CompletionItemTag, Position } from 'vscode-languageserver-types';
import * as builtinCmds from './builtin-cmds.json';
import { Entries, getBuiltinEntries } from './utils';
import { exec } from 'child_process'; import { exec } from 'child_process';
import { Entries, getBuiltinEntries } from './utils';
import * as builtinCmds from './builtin-cmds.json';
const entries: Entries = getBuiltinEntries(); const entries: Entries = getBuiltinEntries();
const modules = entries[0].split('\n'); const modules = entries[0].split('\n');
@ -38,7 +32,8 @@ connection.onInitialize((params: InitializeParams) => {
signatureHelpProvider: { signatureHelpProvider: {
triggerCharacters: ['('], triggerCharacters: ['('],
retriggerCharacters: [' '] retriggerCharacters: [' ']
} },
completionProvider: {}
}, },
serverInfo: { serverInfo: {
name: 'cmakels', name: 'cmakels',
@ -57,7 +52,7 @@ connection.onHover((params: HoverParams) => {
const document: TextDocument = documents.get(params.textDocument.uri); const document: TextDocument = documents.get(params.textDocument.uri);
const word = getWordAtPosition(document, params.position); const word = getWordAtPosition(document, params.position);
if (word.length === 0) { if (word.length === 0) {
return undefined; return null;
} }
// check if the word is a builtin commands // check if the word is a builtin commands
@ -110,6 +105,23 @@ connection.onHover((params: HoverParams) => {
} }
}); });
connection.onCompletion(async (params: CompletionParams) => {
const document = documents.get(params.textDocument.uri);
const word = getWordAtPosition(document, params.position);
if (word.length === 0) {
return null;
}
const results = await Promise.all([
getCommandProposals(word),
getProposals(word, CompletionItemKind.Module, modules),
getProposals(word, CompletionItemKind.Constant, policies),
getProposals(word, CompletionItemKind.Variable, variables),
getProposals(word, CompletionItemKind.Property, properties)
]);
return results.flat();
});
connection.onSignatureHelp((params: SignatureHelpParams) => { connection.onSignatureHelp((params: SignatureHelpParams) => {
return null; return null;
}); });
@ -131,12 +143,50 @@ function getWordAtPosition(textDocument: TextDocument, position: Position): stri
// TODO: the regex expression capture numbers, fix it. // TODO: the regex expression capture numbers, fix it.
const startReg = /[a-zA-Z0-9_]*$/, const startReg = /[a-zA-Z0-9_]*$/,
endReg = /^[a-zA-Z0-9_]*/; endReg = /^[a-zA-Z0-9_]*/;
const startWord = start.match(startReg)[0], const startWord = start.match(startReg)[0],
endWord = end.match(endReg)[0]; endWord = end.match(endReg)[0];
return startWord + endWord; return startWord + endWord;
} }
function getCommandProposals(word: string): Thenable<CompletionItem[]> {
return new Promise((resolve, rejects) => {
const similarCmds = Object.keys(builtinCmds).filter(cmd => {
return cmd.includes(word);
});
const proposalCmds: CompletionItem[] = similarCmds.map((value, index, array) => {
let item: CompletionItem = {
label: value,
kind: CompletionItemKind.Function,
};
if ("deprecated" in builtinCmds[value]) {
item.tags = [CompletionItemTag.Deprecated];
}
return item;
});
resolve(proposalCmds);
});
}
function getProposals(word: string, kind: CompletionItemKind, dataSource: string[]): Thenable<CompletionItem[]> {
return new Promise((resolve, rejects) => {
const similar = dataSource.filter(candidate => {
return candidate.includes(word);
});
const proposals: CompletionItem[] = similar.map((value, index, array) => {
return {
label: value,
kind: kind
};
});
resolve(proposals);
});
}
// Make the text document manager listen on the connection // Make the text document manager listen on the connection
// for open, change and close text document events // for open, change and close text document events
documents.listen(connection); documents.listen(connection);