get setting from client
This commit is contained in:
parent
0c4012b71c
commit
1140368757
|
@ -77,6 +77,11 @@
|
|||
{
|
||||
"title": "CMake IntelliSence",
|
||||
"properties": {
|
||||
"cmakeIntelliSence.cmakePath": {
|
||||
"type": "string",
|
||||
"default": "cmake",
|
||||
"description": "Set path to CMake executable"
|
||||
},
|
||||
"cmakeIntelliSence.loggingLevel": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import { LSPAny } from "vscode-languageserver";
|
||||
import { connection } from "./server";
|
||||
import ExtensionSettings, { extSettings } from "./settings";
|
||||
import * as cp from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
|
||||
type Modules = string[];
|
||||
type Policies = string[];
|
||||
type Variables = string[];
|
||||
type Properties = string[];
|
||||
|
||||
class CMakeInfo {
|
||||
public version: string;
|
||||
public major: number;
|
||||
public minor: number;
|
||||
public patch: number;
|
||||
public modules: string[];
|
||||
public policies: string[];
|
||||
public variables: string[];
|
||||
public properties: string[];
|
||||
|
||||
public async init() {
|
||||
[
|
||||
[this.version, this.major, this.minor, this.patch],
|
||||
[this.modules, this.policies, this.variables, this.properties]
|
||||
] = await Promise.all([this.getCMakeVersion(), this.getBuiltinEntries()]);
|
||||
}
|
||||
|
||||
private async getCMakeVersion(): Promise<[string, number, number, number]> {
|
||||
const command = extSettings.cmakePath + " --version";
|
||||
const { stdout, stderr } = await promisify(cp.exec)(command);
|
||||
const regexp: RegExp = /(\d+)\.(\d+)\.(\d+)/;
|
||||
const res = stdout.match(regexp);
|
||||
return [
|
||||
res[0],
|
||||
parseInt(res[1]),
|
||||
parseInt(res[2]),
|
||||
parseInt(res[3])
|
||||
];
|
||||
}
|
||||
|
||||
private async getBuiltinEntries(): Promise<[Modules, Policies, Variables, Properties]> {
|
||||
const command = extSettings.cmakePath + " --help-module-list --help-policy-list --help-variable-list --help-property-list";
|
||||
const { stdout, stderr } = await promisify(cp.exec)(command);
|
||||
const tmp = stdout.trim().split('\n\n\n');
|
||||
return [
|
||||
tmp[0].split('\n'),
|
||||
tmp[1].split('\n'),
|
||||
tmp[2].split('\n'),
|
||||
tmp[3].split('\n'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export const cmakeInfo = new CMakeInfo();
|
|
@ -2,8 +2,9 @@ import { SemanticTokens, SemanticTokensBuilder } from "vscode-languageserver";
|
|||
import { URI } from "vscode-uri";
|
||||
import Token from "./parser/antlr4/Token";
|
||||
import CMakeListener from "./parser/CMakeListener";
|
||||
import { initParams, variables } from "./server";
|
||||
import { initParams } from "./server";
|
||||
import * as builtinCmds from './builtin-cmds.json';
|
||||
import { cmakeInfo } from "./cmakeInfo";
|
||||
|
||||
export let tokenTypes = [
|
||||
'type',
|
||||
|
@ -105,7 +106,7 @@ export class SemanticListener extends CMakeListener {
|
|||
}
|
||||
|
||||
private isVariable(token: string): boolean {
|
||||
return variables.includes(token);
|
||||
return cmakeInfo.variables.includes(token);
|
||||
}
|
||||
|
||||
private getModifiers(modifiers: TokenModifiers[]): number {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import {
|
||||
createConnection, HoverParams, InitializeParams, InitializeResult,
|
||||
ProposedFeatures, SemanticTokensParams, SemanticTokensRequest, SignatureHelpParams, TextDocuments, TextDocumentSyncKind,
|
||||
_RemoteWindow
|
||||
createConnection, DidChangeConfigurationNotification, HoverParams, InitializeParams, InitializeResult,
|
||||
LSPAny,
|
||||
ProposedFeatures, SemanticTokensParams, SignatureHelpParams, TextDocuments, TextDocumentSyncKind
|
||||
} from 'vscode-languageserver/node';
|
||||
|
||||
import {
|
||||
CompletionItemKind, CompletionParams, DocumentFormattingParams,
|
||||
DocumentSymbolParams, SignatureHelpTriggerKind, DefinitionParams,
|
||||
WorkspaceFolder
|
||||
CompletionItemKind, CompletionParams, DefinitionParams, DocumentFormattingParams,
|
||||
DocumentSymbolParams, SignatureHelpTriggerKind
|
||||
} from 'vscode-languageserver-protocol';
|
||||
import { Range, TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import {
|
||||
|
@ -15,18 +14,19 @@ import {
|
|||
} from 'vscode-languageserver-types';
|
||||
|
||||
import { exec } from 'child_process';
|
||||
import { existsSync } from 'fs';
|
||||
import { URI, Utils } from 'vscode-uri';
|
||||
import * as builtinCmds from './builtin-cmds.json';
|
||||
import { SymbolListener } from './docSymbols';
|
||||
import { FormatListener } from './format';
|
||||
import antlr4 from './parser/antlr4/index.js';
|
||||
import CMakeLexer from './parser/CMakeLexer.js';
|
||||
import CMakeParser from './parser/CMakeParser.js';
|
||||
import { SymbolListener } from './docSymbols';
|
||||
import { Entries, getBuiltinEntries, getCMakeVersion, getFileContext } from './utils';
|
||||
import { DefinationListener, incToBaseDir, refToDef, topScope } from './symbolTable/goToDefination';
|
||||
import { existsSync } from 'fs';
|
||||
import { URI, Utils } from 'vscode-uri';
|
||||
import path = require('path');
|
||||
import { getTokenModifiers, getTokenTypes, SemanticListener, tokenBuilders } from './semanticTokens';
|
||||
import { DefinationListener, incToBaseDir, refToDef, topScope } from './symbolTable/goToDefination';
|
||||
import { getFileContext } from './utils';
|
||||
import ExtensionSettings, { extSettings } from './settings';
|
||||
import { cmakeInfo } from './cmakeInfo';
|
||||
|
||||
type Word = {
|
||||
text: string,
|
||||
|
@ -34,26 +34,21 @@ type Word = {
|
|||
col: number
|
||||
};
|
||||
|
||||
const entries: Entries = getBuiltinEntries();
|
||||
export const modules = entries[0].split('\n');
|
||||
export const policies = entries[1].split('\n');
|
||||
export const variables = entries[2].split('\n');
|
||||
export const properties = entries[3].split('\n');
|
||||
|
||||
|
||||
let contentChanged = true;
|
||||
|
||||
export let initParams: InitializeParams;
|
||||
|
||||
// Craete a connection for the server, using Node's IPC as a transport.
|
||||
// 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);
|
||||
export const connection = createConnection(ProposedFeatures.all);
|
||||
|
||||
// Create a simple text document manager.
|
||||
export const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
|
||||
|
||||
connection.onInitialize((params: InitializeParams) => {
|
||||
|
||||
connection.onInitialize(async (params: InitializeParams) => {
|
||||
initParams = params;
|
||||
|
||||
const result: InitializeResult = {
|
||||
capabilities: {
|
||||
textDocumentSync: TextDocumentSyncKind.Incremental,
|
||||
|
@ -83,11 +78,15 @@ connection.onInitialize((params: InitializeParams) => {
|
|||
return result;
|
||||
});
|
||||
|
||||
connection.onInitialized(() => {
|
||||
connection.onInitialized(async () => {
|
||||
console.log("Initialized");
|
||||
connection.client.register(DidChangeConfigurationNotification.type, undefined);
|
||||
await extSettings.getSettings();
|
||||
await cmakeInfo.init();
|
||||
});
|
||||
|
||||
connection.onHover((params: HoverParams) => {
|
||||
|
||||
connection.onHover(async (params: HoverParams) => {
|
||||
const document: TextDocument = documents.get(params.textDocument.uri);
|
||||
const word = getWordAtPosition(document, params.position).text;
|
||||
if (word.length === 0) {
|
||||
|
@ -110,7 +109,7 @@ connection.onHover((params: HoverParams) => {
|
|||
|
||||
let moduleArg = '';
|
||||
|
||||
if (modules.includes(word)) {
|
||||
if (cmakeInfo.modules.includes(word)) {
|
||||
const line = document.getText({
|
||||
start: { line: params.position.line, character: 0 },
|
||||
end: { line: params.position.line, character: Number.MAX_VALUE }
|
||||
|
@ -118,11 +117,11 @@ connection.onHover((params: HoverParams) => {
|
|||
if (line.trim().startsWith('include')) {
|
||||
moduleArg = '--help-module ';
|
||||
}
|
||||
} else if (policies.includes(word)) {
|
||||
} else if (cmakeInfo.policies.includes(word)) {
|
||||
moduleArg = '--help-policy ';
|
||||
} else if (variables.includes(word)) {
|
||||
} else if (cmakeInfo.variables.includes(word)) {
|
||||
moduleArg = '--help-variable ';
|
||||
} else if (properties.includes(word)) {
|
||||
} else if (cmakeInfo.properties.includes(word)) {
|
||||
moduleArg = '--help-property ';
|
||||
}
|
||||
|
||||
|
@ -153,10 +152,10 @@ connection.onCompletion(async (params: CompletionParams) => {
|
|||
|
||||
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)
|
||||
getProposals(word, CompletionItemKind.Module, cmakeInfo.modules),
|
||||
getProposals(word, CompletionItemKind.Constant, cmakeInfo.policies),
|
||||
getProposals(word, CompletionItemKind.Variable, cmakeInfo.variables),
|
||||
getProposals(word, CompletionItemKind.Property, cmakeInfo.properties)
|
||||
]);
|
||||
return results.flat();
|
||||
});
|
||||
|
@ -327,6 +326,26 @@ connection.languages.semanticTokens.on(async (params: SemanticTokensParams) => {
|
|||
return semanticListener.getSemanticTokens();
|
||||
});
|
||||
|
||||
/**
|
||||
* @param params This argument is null when configuration changed
|
||||
*
|
||||
* there are two different configuration models. A push model (the old) where
|
||||
* the client pushed settings to the server. In this model the client takes a
|
||||
* settings configuration which settings to push if they change. The new model
|
||||
* is the pull model where the server pulls for settings. This model has the
|
||||
* advantage that the pull can contain a scope (e.g. a resource). In this model
|
||||
* the clients simply sends an empty change event to signal that the settings
|
||||
* have changed and must be reread. The client can't send the changes in the event
|
||||
* since the settings might be different for different resources.
|
||||
*
|
||||
* see the following two issues for detail
|
||||
* https://github.com/microsoft/vscode/issues/54821
|
||||
* https://github.com/microsoft/vscode-languageserver-node/issues/380
|
||||
*/
|
||||
connection.onDidChangeConfiguration(params => {
|
||||
extSettings.getSettings();
|
||||
});
|
||||
|
||||
// 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 => {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { connection } from "./server";
|
||||
|
||||
export default class ExtensionSettings {
|
||||
public loggingLevel: string;
|
||||
public cmakePath: string;
|
||||
|
||||
public async getSettings() {
|
||||
[this.cmakePath, this.loggingLevel] = await connection.workspace.getConfiguration([
|
||||
{ section: 'cmakeIntelliSence.cmakePath' },
|
||||
{ section: 'cmakeIntelliSence.loggingLevel' }
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
export const extSettings: ExtensionSettings = new ExtensionSettings();
|
|
@ -1,5 +1,5 @@
|
|||
import * as cp from 'child_process';
|
||||
import { documents } from './server';
|
||||
import { documents} from './server';
|
||||
|
||||
import { existsSync } from 'fs';
|
||||
import * as os from 'os';
|
||||
|
@ -10,39 +10,43 @@ import CMakeLexer from "./parser/CMakeLexer";
|
|||
import CMakeParser from "./parser/CMakeParser";
|
||||
import InputStream from './parser/antlr4/InputStream';
|
||||
import { URI, Utils } from 'vscode-uri';
|
||||
import { cmakeInfo } from './cmakeInfo';
|
||||
|
||||
export type Entries = [string, string, string, string];
|
||||
// export type Entries = [string, string, string, string];
|
||||
|
||||
export type CMakeVersion = {
|
||||
version: string,
|
||||
major: number,
|
||||
minor: number,
|
||||
patch: number
|
||||
};
|
||||
// export type CMakeVersion = {
|
||||
// version: string,
|
||||
// major: number,
|
||||
// minor: number,
|
||||
// patch: number
|
||||
// };
|
||||
|
||||
export let cmakeVersion: CMakeVersion = getCMakeVersion();
|
||||
// export let cmakeVersion: CMakeVersion = getCMakeVersion();
|
||||
|
||||
export function getBuiltinEntries(): Entries {
|
||||
const args = ['cmake', '--help-module-list', '--help-policy-list',
|
||||
'--help-variable-list', '--help-property-list'];
|
||||
const cmd: string = args.join(' ');
|
||||
// TODO: execute command async
|
||||
const output = cp.execSync(cmd, { encoding: 'utf-8' });
|
||||
return output.trim().split('\n\n\n') as Entries;
|
||||
}
|
||||
// export function getBuiltinEntries(): Entries {
|
||||
// if (extSettings === undefined) {
|
||||
// getConfiguration();
|
||||
// }
|
||||
// const args = [extSettings[ExtSettings.cmakePath], '--help-module-list', '--help-policy-list',
|
||||
// '--help-variable-list', '--help-property-list'];
|
||||
// const cmd: string = args.join(' ');
|
||||
// // TODO: execute command async
|
||||
// const output = cp.execSync(cmd, { encoding: 'utf-8' });
|
||||
// return output.trim().split('\n\n\n') as Entries;
|
||||
// }
|
||||
|
||||
export function getCMakeVersion(): CMakeVersion {
|
||||
const args = ['cmake', '--version'];
|
||||
const output: string = cp.execSync(args.join(' '), { encoding: 'utf-8' });
|
||||
const regexp: RegExp = /(\d+)\.(\d+)\.(\d+)/;
|
||||
const res = output.match(regexp);
|
||||
return {
|
||||
version: res[0],
|
||||
major: parseInt(res[1]),
|
||||
minor: parseInt(res[2]),
|
||||
patch: parseInt(res[3])
|
||||
};
|
||||
}
|
||||
// export function getCMakeVersion(): CMakeVersion {
|
||||
// const args = [extSettings[ExtSettings.cmakePath], '--version'];
|
||||
// const output: string = cp.execSync(args.join(' '), { encoding: 'utf-8' });
|
||||
// const regexp: RegExp = /(\d+)\.(\d+)\.(\d+)/;
|
||||
// const res = output.match(regexp);
|
||||
// return {
|
||||
// version: res[0],
|
||||
// major: parseInt(res[1]),
|
||||
// minor: parseInt(res[2]),
|
||||
// patch: parseInt(res[3])
|
||||
// };
|
||||
// }
|
||||
|
||||
export function getFileContext(uri: URI) {
|
||||
const document = documents.get(uri.toString());
|
||||
|
@ -79,7 +83,7 @@ export function getIncludeFileUri(baseDir: URI, includeFileName: string): URI {
|
|||
return null;
|
||||
}
|
||||
|
||||
const moduleDir = 'cmake-' + cmakeVersion.major + '.' + cmakeVersion.minor;
|
||||
const moduleDir = 'cmake-' + cmakeInfo.major + '.' + cmakeInfo.minor;
|
||||
const resPath = path.join(cmakePath, '../..', 'share', moduleDir, 'Modules', includeFileName) + '.cmake';
|
||||
|
||||
if (existsSync(resPath)) {
|
||||
|
|
Loading…
Reference in New Issue