Skip to content

Commit 4551de6

Browse files
Add setting to enable/disable our built-in language services (#4364)
* add setting to enable/disable language services, enabled by default, still needs testing * update test * add changelog entry
1 parent 65b9a94 commit 4551de6

File tree

6 files changed

+113
-48
lines changed

6 files changed

+113
-48
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Features:
66

77
- Add an option to specify the launch target for debugging CTest tests. [#4273](https://github.com/microsoft/vscode-cmake-tools/pull/4273)
8+
- Add a setting to enable/disable our built-in language services. [#4290](https://github.com/microsoft/vscode-cmake-tools/issues/4290)
89

910
Improvements:
1011

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3624,6 +3624,12 @@
36243624
"description": "%cmake-tools.configuration.cmake.enableAutomaticKitScan.description%",
36253625
"scope": "resource"
36263626
},
3627+
"cmake.enableLanguageServices": {
3628+
"type": "boolean",
3629+
"default": true,
3630+
"description": "%cmake-tools.configuration.cmake.enableLanguageServices.description%",
3631+
"scope": "machine"
3632+
},
36273633
"cmake.preRunCoverageTarget": {
36283634
"type": "string",
36293635
"default": null,

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@
294294
]
295295
},
296296
"cmake-tools.configuration.cmake.enableAutomaticKitScan.description": "Enable automatic scanning for kits when a kit isn't selected. This will only take affect when CMake Presets aren't being used.",
297+
"cmake-tools.configuration.cmake.enableLanguageServices.description": "Enable language services for CMake files. This will enable syntax highlighting, code completion, and other features.",
297298
"cmake-tools.configuration.cmake.preRunCoverageTarget.description": "Target to build before running tests with coverage using the test explorer",
298299
"cmake-tools.configuration.cmake.postRunCoverageTarget.description": "Target to build after running tests with coverage using the test explorer",
299300
"cmake-tools.configuration.cmake.coverageInfoFiles.description": "LCOV coverage info files to be processed after running tests with coverage using the test explorer.",

src/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ export interface ExtensionConfigurationSettings {
217217
automaticReconfigure: boolean;
218218
pinnedCommands: string[];
219219
enableAutomaticKitScan: boolean;
220+
enableLanguageServices: boolean;
220221
preRunCoverageTarget: string | null;
221222
postRunCoverageTarget: string | null;
222223
coverageInfoFiles: string[];
@@ -571,6 +572,10 @@ export class ConfigurationReader implements vscode.Disposable {
571572
return this.configData.enableAutomaticKitScan;
572573
}
573574

575+
get enableLanguageServices(): boolean {
576+
return this.configData.enableLanguageServices;
577+
}
578+
574579
get preRunCoverageTarget(): string | null {
575580
return this.configData.preRunCoverageTarget;
576581
}
@@ -648,6 +653,7 @@ export class ConfigurationReader implements vscode.Disposable {
648653
automaticReconfigure: new vscode.EventEmitter<boolean>(),
649654
pinnedCommands: new vscode.EventEmitter<string[]>(),
650655
enableAutomaticKitScan: new vscode.EventEmitter<boolean>(),
656+
enableLanguageServices: new vscode.EventEmitter<boolean>(),
651657
preRunCoverageTarget: new vscode.EventEmitter<string | null>(),
652658
postRunCoverageTarget: new vscode.EventEmitter<string | null>(),
653659
coverageInfoFiles: new vscode.EventEmitter<string[]>()

src/extension.ts

Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ export class ExtensionManager implements vscode.Disposable {
106106
private onDidChangeActiveTextEditorSub: vscode.Disposable = new DummyDisposable();
107107
private readonly extensionActiveCommandsEmitter = new vscode.EventEmitter<void>();
108108
private readonly workspaceConfig: ConfigurationReader = ConfigurationReader.create();
109+
private readonly CMAKE_LANGUAGE = "cmake";
110+
private readonly CMAKE_SELECTOR: vscode.DocumentSelector = [
111+
{ language: this.CMAKE_LANGUAGE, scheme: "file" },
112+
{ language: this.CMAKE_LANGUAGE, scheme: "untitled" }
113+
];
114+
private languageServicesDisposables: vscode.Disposable[] = [];
109115

110116
private updateTouchBarVisibility(config: TouchBarConfig) {
111117
const touchBarVisible = config.visibility === "default";
@@ -119,6 +125,17 @@ export class ExtensionManager implements vscode.Disposable {
119125
* Second-phase async init
120126
*/
121127
public async init() {
128+
if (this.workspaceConfig.enableLanguageServices) {
129+
await this.enableLanguageServices();
130+
this.workspaceConfig.onChange('enableLanguageServices', async (value) => {
131+
if (value) {
132+
await this.enableLanguageServices();
133+
} else {
134+
this.disposeLanguageServices();
135+
}
136+
});
137+
}
138+
122139
this.updateTouchBarVisibility(this.workspaceConfig.touchbar);
123140
this.workspaceConfig.onChange('touchbar', config => this.updateTouchBarVisibility(config));
124141

@@ -357,6 +374,7 @@ export class ExtensionManager implements vscode.Disposable {
357374
private activeTestPresetSub: vscode.Disposable = new DummyDisposable();
358375
private activePackagePresetSub: vscode.Disposable = new DummyDisposable();
359376
private activeWorkflowPresetSub: vscode.Disposable = new DummyDisposable();
377+
private enableLanguageServicesSub: vscode.Disposable = new DummyDisposable();
360378

361379
// Watch the code model so that we may update the tree view
362380
// <fspath, sub>
@@ -379,6 +397,83 @@ export class ExtensionManager implements vscode.Disposable {
379397
private cppToolsAPI?: cpt.CppToolsApi;
380398
private configProviderRegistered?: boolean = false;
381399

400+
private async enableLanguageServices() {
401+
try {
402+
const languageServices = await LanguageServiceData.create();
403+
this.languageServicesDisposables.push(vscode.languages.registerHoverProvider(
404+
this.CMAKE_SELECTOR,
405+
languageServices
406+
));
407+
this.languageServicesDisposables.push(vscode.languages.registerCompletionItemProvider(
408+
this.CMAKE_SELECTOR,
409+
languageServices
410+
));
411+
} catch {
412+
log.error(
413+
localize(
414+
"language.service.failed",
415+
"Failed to initialize language services"
416+
)
417+
);
418+
}
419+
420+
this.languageServicesDisposables.push(vscode.languages.setLanguageConfiguration(
421+
this.CMAKE_LANGUAGE,
422+
{
423+
indentationRules: {
424+
// ^(.*\*/)?\s*\}.*$
425+
decreaseIndentPattern: /^(.*\*\/)?\s*\}.*$/,
426+
// ^.*\{[^}"']*$
427+
increaseIndentPattern: /^.*\{[^}"']*$/
428+
},
429+
wordPattern:
430+
/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
431+
comments: {
432+
lineComment: "#"
433+
},
434+
brackets: [
435+
["{", "}"],
436+
["(", ")"]
437+
],
438+
439+
__electricCharacterSupport: {
440+
brackets: [
441+
{
442+
tokenType: "delimiter.curly.ts",
443+
open: "{",
444+
close: "}",
445+
isElectric: true
446+
},
447+
{
448+
tokenType: "delimiter.square.ts",
449+
open: "[",
450+
close: "]",
451+
isElectric: true
452+
},
453+
{
454+
tokenType: "delimiter.paren.ts",
455+
open: "(",
456+
close: ")",
457+
isElectric: true
458+
}
459+
]
460+
},
461+
462+
__characterPairSupport: {
463+
autoClosingPairs: [
464+
{ open: "{", close: "}" },
465+
{ open: "(", close: ")" },
466+
{ open: '"', close: '"', notIn: ["string"] }
467+
]
468+
}
469+
}
470+
));
471+
}
472+
473+
private disposeLanguageServices() {
474+
this.languageServicesDisposables.forEach(sub => sub.dispose());
475+
}
476+
382477
private getProjectsForWorkspaceFolder(folder?: vscode.WorkspaceFolder): CMakeProject[] | undefined {
383478
folder = this.getWorkspaceFolder(folder);
384479
return this.projectController.getProjectsForWorkspaceFolder(folder);
@@ -554,6 +649,7 @@ export class ExtensionManager implements vscode.Disposable {
554649
*/
555650
async asyncDispose() {
556651
this.disposeSubs();
652+
this.disposeLanguageServices();
557653
this.codeModelUpdateSubs.forEach(
558654
subs => subs.forEach(
559655
sub => sub.dispose()
@@ -736,7 +832,7 @@ export class ExtensionManager implements vscode.Disposable {
736832

737833
private disposeSubs() {
738834
util.disposeAll(this.projectSubscriptions);
739-
for (const sub of [this.statusMessageSub, this.targetNameSub, this.buildTypeSub, this.launchTargetSub, this.ctestEnabledSub, this.isBusySub, this.activeConfigurePresetSub, this.activeBuildPresetSub, this.activeTestPresetSub, this.activePackagePresetSub, this.activeWorkflowPresetSub]) {
835+
for (const sub of [this.statusMessageSub, this.targetNameSub, this.buildTypeSub, this.launchTargetSub, this.ctestEnabledSub, this.isBusySub, this.activeConfigurePresetSub, this.activeBuildPresetSub, this.activeTestPresetSub, this.activePackagePresetSub, this.activeWorkflowPresetSub, this.enableLanguageServicesSub]) {
740836
sub.dispose();
741837
}
742838
}
@@ -834,6 +930,7 @@ export class ExtensionManager implements vscode.Disposable {
834930
this.activeTestPresetSub = new DummyDisposable();
835931
this.activePackagePresetSub = new DummyDisposable();
836932
this.activeWorkflowPresetSub = new DummyDisposable();
933+
this.enableLanguageServicesSub = new DummyDisposable();
837934
this.statusBar.setActiveKitName('');
838935
this.statusBar.setConfigurePresetName('');
839936
this.statusBar.setBuildPresetName('');
@@ -2400,53 +2497,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<api.CM
24002497
});
24012498
}
24022499

2403-
const CMAKE_LANGUAGE = "cmake";
2404-
const CMAKE_SELECTOR: vscode.DocumentSelector = [
2405-
{ language: CMAKE_LANGUAGE, scheme: 'file'},
2406-
{ language: CMAKE_LANGUAGE, scheme: 'untitled'}
2407-
];
2408-
2409-
try {
2410-
const languageServices = await LanguageServiceData.create();
2411-
vscode.languages.registerHoverProvider(CMAKE_SELECTOR, languageServices);
2412-
vscode.languages.registerCompletionItemProvider(CMAKE_SELECTOR, languageServices);
2413-
} catch {
2414-
log.error(localize('language.service.failed', 'Failed to initialize language services'));
2415-
}
2416-
2417-
vscode.languages.setLanguageConfiguration(CMAKE_LANGUAGE, {
2418-
indentationRules: {
2419-
// ^(.*\*/)?\s*\}.*$
2420-
decreaseIndentPattern: /^(.*\*\/)?\s*\}.*$/,
2421-
// ^.*\{[^}"']*$
2422-
increaseIndentPattern: /^.*\{[^}"']*$/
2423-
},
2424-
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
2425-
comments: {
2426-
lineComment: '#'
2427-
},
2428-
brackets: [
2429-
['{', '}'],
2430-
['(', ')']
2431-
],
2432-
2433-
__electricCharacterSupport: {
2434-
brackets: [
2435-
{ tokenType: 'delimiter.curly.ts', open: '{', close: '}', isElectric: true },
2436-
{ tokenType: 'delimiter.square.ts', open: '[', close: ']', isElectric: true },
2437-
{ tokenType: 'delimiter.paren.ts', open: '(', close: ')', isElectric: true }
2438-
]
2439-
},
2440-
2441-
__characterPairSupport: {
2442-
autoClosingPairs: [
2443-
{ open: '{', close: '}' },
2444-
{ open: '(', close: ')' },
2445-
{ open: '"', close: '"', notIn: ['string'] }
2446-
]
2447-
}
2448-
});
2449-
24502500
if (vscode.workspace.getConfiguration('cmake').get('showOptionsMovedNotification')) {
24512501
void vscode.window.showInformationMessage(
24522502
localize('options.moved.notification.body', "Some status bar options in CMake Tools have now moved to the Project Status View in the CMake Tools sidebar. You can customize your view with the 'cmake.options' property in settings."),

test/unit-tests/config.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ function createConfig(conf: Partial<ExtensionConfigurationSettings>): Configurat
7878
ignoreCMakeListsMissing: false,
7979
automaticReconfigure: false,
8080
enableAutomaticKitScan: true,
81+
enableLanguageServices: true,
8182
preRunCoverageTarget: null,
8283
postRunCoverageTarget: null,
8384
coverageInfoFiles: []

0 commit comments

Comments
 (0)