Skip to content

Commit e4a3ab8

Browse files
committed
Merge branch 'handle-multiple-compile-commands' of github.com:yiftahw/vscode-cpptools into handle-multiple-compile-commands
2 parents ad3073c + d916822 commit e4a3ab8

File tree

13 files changed

+109
-49
lines changed

13 files changed

+109
-49
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* [Build and debug the extension](Documentation/Building%20the%20Extension.md).
66
* File an [issue](https://github.com/Microsoft/vscode-cpptools/issues) and a [pull request](https://github.com/Microsoft/vscode-cpptools/pulls) with the change and we will review it.
77
* If the change affects functionality, add a line describing the change to [**CHANGELOG.md**](Extension/CHANGELOG.md).
8-
* Try and add a test in [**test/extension.test.ts**](Extension/test/unitTests/extension.test.ts).
8+
* Try and add a test in [**test/extension.test.ts**](Extension/test/scenarios/SingleRootProject/tests/extension.test.ts).
99
* Run tests via opening the [**Extension**](https://github.com/Microsoft/vscode-cpptools/tree/main/Extension) folder in Visual Studio Code, selecting the "Launch Tests" configuration in the Debug pane, and choosing "Start Debugging".
1010

1111
## About the Code

Extension/i18n/chs/package.i18n.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
"c_cpp.configuration.vcFormat.space.removeBeforeSemicolon.description": "将移除每个分号前的空格。",
161161
"c_cpp.configuration.vcFormat.space.insertAfterSemicolon.description": "在每个分号后面插入一个空格。",
162162
"c_cpp.configuration.vcFormat.space.removeAroundUnaryOperator.description": "移除一元运算符和操作数之间的空格。",
163-
"c_cpp.configuration.vcFormat.space.aroundBinaryOperator.description": "二进制运算符周围的空格",
163+
"c_cpp.configuration.vcFormat.space.aroundBinaryOperator.description": "二元运算符周围的空格",
164164
"c_cpp.configuration.vcFormat.space.aroundAssignmentOperator.description": "赋值运算符周围的空格。",
165165
"c_cpp.configuration.vcFormat.space.pointerReferenceAlignment.description": "指针和引用运算符周围的空格。",
166166
"c_cpp.configuration.vcFormat.space.pointerReferenceAlignment.left.description": "指针和引用运算符左对齐。",
@@ -449,4 +449,4 @@
449449
"c_cpp.configuration.refactoring.includeHeader.never.description": "从不包含头文件。",
450450
"c_cpp.languageModelTools.configuration.displayName": "C/C++ 配置",
451451
"c_cpp.languageModelTools.configuration.userDescription": "活动 C 或 C++ 文件的配置,例如语言标准版本和目标平台。"
452-
}
452+
}

Extension/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,9 @@
707707
"default": []
708708
}
709709
],
710+
"default": [
711+
""
712+
],
710713
"markdownDescription": "%c_cpp.configuration.default.compileCommands.markdownDescription%",
711714
"scope": "machine-overridable"
712715
},

Extension/package.nls.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173
]
174174
},
175175
"c_cpp.configuration.codeAnalysis.clangTidy.path.markdownDescription": {
176-
"message": "The full path of the `clang-tidy` executable. If not specified, and `clang-tidy` is available in the environment path, that is used. If not found in the environment path, the `clang-tidy` bundled with the extension will be used.",
176+
"message": "The full path of the `clang-tidy` executable. If not specified, and `clang-tidy` is available in the environment path, that is used unless the version bundled with the extension is newer. If not found in the environment path, the `clang-tidy` bundled with the extension will be used.",
177177
"comment": [
178178
"Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered."
179179
]
@@ -410,7 +410,12 @@
410410
"c_cpp.configuration.vcFormat.space.removeBeforeSemicolon.description": "Spaces are removed before every semicolon.",
411411
"c_cpp.configuration.vcFormat.space.insertAfterSemicolon.description": "A space is inserted after every semicolon.",
412412
"c_cpp.configuration.vcFormat.space.removeAroundUnaryOperator.description": "Spaces between unary operators and operands are removed.",
413-
"c_cpp.configuration.vcFormat.space.aroundBinaryOperator.description": "Spaces around binary operators.",
413+
"c_cpp.configuration.vcFormat.space.aroundBinaryOperator.description": {
414+
"message": "Spaces around binary operators.",
415+
"comment": [
416+
"The term \"binary operators\" refers to operators that takes two operands and not operators on binary numbers."
417+
]
418+
},
414419
"c_cpp.configuration.vcFormat.space.aroundAssignmentOperator.description": "Spaces around assignment operators.",
415420
"c_cpp.configuration.vcFormat.space.pointerReferenceAlignment.description": "Spaces around pointer and reference operators.",
416421
"c_cpp.configuration.vcFormat.space.pointerReferenceAlignment.left.description": "Pointer and reference operators are aligned to the left.",
@@ -441,7 +446,7 @@
441446
]
442447
},
443448
"c_cpp.configuration.clang_format_path.markdownDescription": {
444-
"message": "The full path of the `clang-format` executable. If not specified, and `clang-format` is available in the environment path, that is used. If not found in the environment path, the `clang-format` bundled with the extension will be used.",
449+
"message": "The full path of the `clang-format` executable. If not specified, and `clang-format` is available in the environment path, that is used unless the version bundled with the extension is newer. If not found in the environment path, the `clang-format` bundled with the extension will be used.",
445450
"comment": [
446451
"Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered."
447452
]

Extension/src/LanguageServer/client.ts

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import { DataBinding } from './dataBinding';
5858
import { cachedEditorConfigSettings, getEditorConfigSettings } from './editorConfig';
5959
import { CppSourceStr, clients, configPrefix, updateLanguageConfigurations, usesCrashHandler, watchForCrashes } from './extension';
6060
import { LocalizeStringParams, getLocaleId, getLocalizedString } from './localization';
61-
import { PersistentFolderState, PersistentWorkspaceState } from './persistentState';
61+
import { PersistentFolderState, PersistentState, PersistentWorkspaceState } from './persistentState';
6262
import { RequestCancelled, ServerCancelled, createProtocolFilter } from './protocolFilter';
6363
import * as refs from './references';
6464
import { CppSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams } from './settings';
@@ -527,6 +527,7 @@ interface DidChangeActiveEditorParams {
527527
}
528528

529529
interface GetIncludesParams {
530+
fileUri: string;
530531
maxDepth: number;
531532
}
532533

@@ -564,6 +565,16 @@ export interface ProjectContextResult {
564565
fileContext: FileContextResult;
565566
}
566567

568+
interface FolderFilesEncodingChanged {
569+
uri: string;
570+
filesEncoding: string;
571+
}
572+
573+
interface FilesEncodingChanged {
574+
workspaceFallbackEncoding?: string;
575+
foldersFilesEncoding: FolderFilesEncodingChanged[];
576+
}
577+
567578
// Requests
568579
const PreInitializationRequest: RequestType<void, string, void> = new RequestType<void, string, void>('cpptools/preinitialize');
569580
const InitializationRequest: RequestType<CppInitializationParams, void, void> = new RequestType<CppInitializationParams, void, void>('cpptools/initialize');
@@ -642,6 +653,7 @@ const ReportCodeAnalysisTotalNotification: NotificationType<number> = new Notifi
642653
const DoxygenCommentGeneratedNotification: NotificationType<GenerateDoxygenCommentResult> = new NotificationType<GenerateDoxygenCommentResult>('cpptools/insertDoxygenComment');
643654
const CanceledReferencesNotification: NotificationType<void> = new NotificationType<void>('cpptools/canceledReferences');
644655
const IntelliSenseResultNotification: NotificationType<IntelliSenseResult> = new NotificationType<IntelliSenseResult>('cpptools/intelliSenseResult');
656+
const FilesEncodingChangedNotification: NotificationType<FilesEncodingChanged> = new NotificationType<FilesEncodingChanged>('cpptools/filesEncodingChanged');
645657

646658
let failureMessageShown: boolean = false;
647659

@@ -816,9 +828,10 @@ export interface Client {
816828
setShowConfigureIntelliSenseButton(show: boolean): void;
817829
addTrustedCompiler(path: string): Promise<void>;
818830
getCopilotHoverProvider(): CopilotHoverProvider | undefined;
819-
getIncludes(maxDepth: number): Promise<GetIncludesResult>;
831+
getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult>;
820832
getChatContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ChatContextResult>;
821833
getProjectContext(uri: vscode.Uri): Promise<ProjectContextResult>;
834+
filesEncodingChanged(filesEncodingChanged: FilesEncodingChanged): void;
822835
}
823836

824837
export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client {
@@ -1367,7 +1380,13 @@ export class DefaultClient implements Client {
13671380
DefaultClient.isStarted.resolve();
13681381
}
13691382

1370-
private getWorkspaceFolderSettings(workspaceFolderUri: vscode.Uri | undefined, settings: CppSettings, otherSettings: OtherSettings): WorkspaceFolderSettingsParams {
1383+
private getWorkspaceFolderSettings(workspaceFolderUri: vscode.Uri | undefined, workspaceFolder: vscode.WorkspaceFolder | undefined, settings: CppSettings, otherSettings: OtherSettings): WorkspaceFolderSettingsParams {
1384+
const filesEncoding: string = otherSettings.filesEncoding;
1385+
let filesEncodingChanged: boolean = false;
1386+
if (workspaceFolder) {
1387+
const lastFilesEncoding: PersistentFolderState<string> = new PersistentFolderState<string>("CPP.lastFilesEncoding", filesEncoding, workspaceFolder);
1388+
filesEncodingChanged = lastFilesEncoding.Value !== filesEncoding;
1389+
}
13711390
const result: WorkspaceFolderSettingsParams = {
13721391
uri: workspaceFolderUri?.toString(),
13731392
intelliSenseEngine: settings.intelliSenseEngine,
@@ -1464,7 +1483,8 @@ export class DefaultClient implements Client {
14641483
doxygenSectionTags: settings.doxygenSectionTags,
14651484
filesExclude: otherSettings.filesExclude,
14661485
filesAutoSaveAfterDelay: otherSettings.filesAutoSaveAfterDelay,
1467-
filesEncoding: otherSettings.filesEncoding,
1486+
filesEncoding: filesEncoding,
1487+
filesEncodingChanged: filesEncodingChanged,
14681488
searchExclude: otherSettings.searchExclude,
14691489
editorAutoClosingBrackets: otherSettings.editorAutoClosingBrackets,
14701490
editorInlayHintsEnabled: otherSettings.editorInlayHintsEnabled,
@@ -1480,10 +1500,10 @@ export class DefaultClient implements Client {
14801500
const workspaceFolderSettingsParams: WorkspaceFolderSettingsParams[] = [];
14811501
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
14821502
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
1483-
workspaceFolderSettingsParams.push(this.getWorkspaceFolderSettings(workspaceFolder.uri, new CppSettings(workspaceFolder.uri), new OtherSettings(workspaceFolder.uri)));
1503+
workspaceFolderSettingsParams.push(this.getWorkspaceFolderSettings(workspaceFolder.uri, workspaceFolder, new CppSettings(workspaceFolder.uri), new OtherSettings(workspaceFolder.uri)));
14841504
}
14851505
} else {
1486-
workspaceFolderSettingsParams.push(this.getWorkspaceFolderSettings(this.RootUri, workspaceSettings, workspaceOtherSettings));
1506+
workspaceFolderSettingsParams.push(this.getWorkspaceFolderSettings(this.RootUri, undefined, workspaceSettings, workspaceOtherSettings));
14871507
}
14881508
return workspaceFolderSettingsParams;
14891509
}
@@ -1498,9 +1518,13 @@ export class DefaultClient implements Client {
14981518
if (this.currentCopilotHoverEnabled && workspaceSettings.copilotHover !== this.currentCopilotHoverEnabled.Value) {
14991519
void util.promptForReloadWindowDueToSettingsChange();
15001520
}
1521+
const workspaceFallbackEncoding: string = workspaceOtherSettings.filesEncoding;
1522+
const lastWorkspaceFallbackEncoding: PersistentState<string> = new PersistentState<string>("CPP.lastWorkspaceFallbackEncoding", workspaceFallbackEncoding);
1523+
const workspaceFallbackEncodingChanged = lastWorkspaceFallbackEncoding.Value !== workspaceFallbackEncoding;
15011524
return {
15021525
filesAssociations: workspaceOtherSettings.filesAssociations,
1503-
workspaceFallbackEncoding: workspaceOtherSettings.filesEncoding,
1526+
workspaceFallbackEncoding: workspaceFallbackEncoding,
1527+
workspaceFallbackEncodingChanged: workspaceFallbackEncodingChanged,
15041528
maxConcurrentThreads: workspaceSettings.maxConcurrentThreads,
15051529
maxCachedProcesses: workspaceSettings.maxCachedProcesses,
15061530
maxMemory: workspaceSettings.maxMemory,
@@ -1646,6 +1670,7 @@ export class DefaultClient implements Client {
16461670
languageClient = new LanguageClient(`cpptools`, serverOptions, clientOptions);
16471671
languageClient.onNotification(DebugProtocolNotification, logDebugProtocol);
16481672
languageClient.onNotification(DebugLogNotification, logLocalized);
1673+
languageClient.onNotification(LogTelemetryNotification, (e) => this.logTelemetry(e));
16491674
languageClient.registerProposedFeatures();
16501675
await languageClient.start();
16511676

@@ -2268,8 +2293,8 @@ export class DefaultClient implements Client {
22682293
* the UI results and always re-requests (no caching).
22692294
*/
22702295

2271-
public async getIncludes(maxDepth: number): Promise<GetIncludesResult> {
2272-
const params: GetIncludesParams = { maxDepth: maxDepth };
2296+
public async getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> {
2297+
const params: GetIncludesParams = { fileUri: uri.toString(), maxDepth };
22732298
await this.ready;
22742299
return this.languageClient.sendRequest(IncludesRequest, params);
22752300
}
@@ -2419,7 +2444,6 @@ export class DefaultClient implements Client {
24192444

24202445
this.languageClient.onNotification(ReloadWindowNotification, () => void util.promptForReloadWindowDueToSettingsChange());
24212446
this.languageClient.onNotification(UpdateTrustedCompilersNotification, (e) => void this.addTrustedCompiler(e.compilerPath));
2422-
this.languageClient.onNotification(LogTelemetryNotification, (e) => this.logTelemetry(e));
24232447
this.languageClient.onNotification(ReportStatusNotification, (e) => void this.updateStatus(e));
24242448
this.languageClient.onNotification(ReportTagParseStatusNotification, (e) => this.updateTagParseStatus(e));
24252449
this.languageClient.onNotification(CompileCommandsPathsNotification, (e) => void this.promptCompileCommands(e));
@@ -2438,6 +2462,7 @@ export class DefaultClient implements Client {
24382462
this.languageClient.onNotification(ReportCodeAnalysisTotalNotification, (e) => this.updateCodeAnalysisTotal(e));
24392463
this.languageClient.onNotification(DoxygenCommentGeneratedNotification, (e) => void this.insertDoxygenComment(e));
24402464
this.languageClient.onNotification(CanceledReferencesNotification, this.serverCanceledReferences);
2465+
this.languageClient.onNotification(FilesEncodingChangedNotification, (e) => this.filesEncodingChanged(e));
24412466
}
24422467

24432468
private handleIntelliSenseResult(intelliSenseResult: IntelliSenseResult): void {
@@ -4085,6 +4110,20 @@ export class DefaultClient implements Client {
40854110
public getCopilotHoverProvider(): CopilotHoverProvider | undefined {
40864111
return this.copilotHoverProvider;
40874112
}
4113+
4114+
public filesEncodingChanged(filesEncodingChanged: FilesEncodingChanged): void {
4115+
if (filesEncodingChanged.workspaceFallbackEncoding !== undefined) {
4116+
const lastWorkspaceFallbackEncoding: PersistentState<string> = new PersistentState<string>("CPP.lastWorkspaceFallbackEncoding", "");
4117+
lastWorkspaceFallbackEncoding.Value = filesEncodingChanged.workspaceFallbackEncoding;
4118+
}
4119+
for (const folderFilesEncoding of filesEncodingChanged.foldersFilesEncoding) {
4120+
const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(vscode.Uri.parse(folderFilesEncoding.uri));
4121+
if (workspaceFolder !== undefined) {
4122+
const lastFilesEncoding: PersistentFolderState<string> = new PersistentFolderState<string>("CPP.lastFilesEncoding", "", workspaceFolder);
4123+
lastFilesEncoding.Value = folderFilesEncoding.filesEncoding;
4124+
}
4125+
}
4126+
}
40884127
}
40894128

40904129
function getLanguageServerFileName(): string {
@@ -4197,7 +4236,8 @@ class NullClient implements Client {
41974236
setShowConfigureIntelliSenseButton(show: boolean): void { }
41984237
addTrustedCompiler(path: string): Promise<void> { return Promise.resolve(); }
41994238
getCopilotHoverProvider(): CopilotHoverProvider | undefined { return undefined; }
4200-
getIncludes(maxDepth: number): Promise<GetIncludesResult> { return Promise.resolve({} as GetIncludesResult); }
4239+
getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> { return Promise.resolve({} as GetIncludesResult); }
42014240
getChatContext(uri: vscode.Uri, token: vscode.CancellationToken): Promise<ChatContextResult> { return Promise.resolve({} as ChatContextResult); }
42024241
getProjectContext(uri: vscode.Uri): Promise<ProjectContextResult> { return Promise.resolve({} as ProjectContextResult); }
4242+
filesEncodingChanged(filesEncodingChanged: FilesEncodingChanged): void { }
42034243
}

Extension/src/LanguageServer/copilotProviders.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as util from '../common';
1010
import * as logger from '../logger';
1111
import * as telemetry from '../telemetry';
1212
import { GetIncludesResult } from './client';
13-
import { getActiveClient } from './extension';
13+
import { getClients } from './extension';
1414
import { getCompilerArgumentFilterMap, getProjectContext } from './lmTool';
1515

1616
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
@@ -46,7 +46,7 @@ export async function registerRelatedFilesProvider(): Promise<void> {
4646
const telemetryProperties: Record<string, string> = {};
4747
const telemetryMetrics: Record<string, number> = {};
4848
try {
49-
const getIncludesHandler = async () => (await getIncludes(1))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [];
49+
const getIncludesHandler = async () => (await getIncludes(uri, 1))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [];
5050
const getTraitsHandler = async () => {
5151
const projectContext = await getProjectContext(uri, context);
5252

@@ -157,10 +157,10 @@ export async function registerRelatedFilesProvider(): Promise<void> {
157157
}
158158
}
159159

160-
async function getIncludes(maxDepth: number): Promise<GetIncludesResult> {
161-
const activeClient = getActiveClient();
162-
const includes = await activeClient.getIncludes(maxDepth);
163-
const wksFolder = activeClient.RootUri?.toString();
160+
async function getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> {
161+
const client = getClients().getClientFor(uri);
162+
const includes = await client.getIncludes(uri, maxDepth);
163+
const wksFolder = client.RootUri?.toString();
164164

165165
if (!wksFolder) {
166166
return includes;

Extension/src/LanguageServer/persistentState.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ class PersistentStateBase<T> {
1919
this.defaultvalue = defaultValue;
2020
this.state = state;
2121
this.curvalue = defaultValue;
22+
23+
// Ensure the default is written to the state store.
24+
if (this.state && this.state.get<T>(this.key) === undefined) {
25+
void this.state.update(this.key, this.defaultvalue);
26+
}
2227
}
2328

2429
public get Value(): T {

0 commit comments

Comments
 (0)