Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions Extension/c_cpp_properties.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,9 @@
"type": "string"
},
"mergeConfigurations": {
"markdownDescription": "Set to `true` to merge include paths, defines, and forced includes with those from a configuration provider.",
"descriptionHint": "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.",
"type": [
"boolean",
"string"
]
"markdownDescription": "Set to `true` to merge `includePath`, `defines`, `forcedInclude`, and `browse.path` with those received from the configuration provider.",
"descriptionHint": "{Locked=\"`true`\"} {Locked=\"`includePath`\"} {Locked=\"`defines`\"} {Locked=\"`forcedInclude`\"} {Locked=\"`browse.path`\"}",
"type": "boolean"
},
"browse": {
"type": "object",
Expand Down
1 change: 1 addition & 0 deletions Extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,7 @@
},
"C_Cpp.default.mergeConfigurations": {
"type": "boolean",
"default": false,
"markdownDescription": "%c_cpp.configuration.default.mergeConfigurations.markdownDescription%",
"scope": "resource"
},
Expand Down
48 changes: 44 additions & 4 deletions Extension/src/LanguageServer/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { CloseAction, DidOpenTextDocumentParams, ErrorAction, LanguageClientOpti
import { LanguageClient, ServerOptions } from 'vscode-languageclient/node';
import * as nls from 'vscode-nls';
import { DebugConfigurationProvider } from '../Debugger/configurationProvider';
import { CustomConfigurationProvider1, getCustomConfigProviders, isSameProviderExtensionId } from '../LanguageServer/customProviders';
import { ManualPromise } from '../Utility/Async/manualPromise';
import { ManualSignal } from '../Utility/Async/manualSignal';
import { logAndReturn } from '../Utility/Async/returns';
Expand All @@ -57,6 +56,7 @@ import {
import { Location, TextEdit, WorkspaceEdit } from './commonTypes';
import * as configs from './configurations';
import { CopilotCompletionContextFeatures, CopilotCompletionContextProvider } from './copilotCompletionContextProvider';
import { CustomConfigurationProvider1, getCustomConfigProviders, isSameProviderExtensionId } from './customProviders';
import { DataBinding } from './dataBinding';
import { cachedEditorConfigSettings, getEditorConfigSettings } from './editorConfig';
import { CppSourceStr, clients, configPrefix, initializeIntervalTimer, updateLanguageConfigurations, usesCrashHandler, watchForCrashes } from './extension';
Expand Down Expand Up @@ -889,6 +889,11 @@ export class DefaultClient implements Client {
private settingsTracker: SettingsTracker;
private loggingLevel: number = 1;
private configurationProvider?: string;
private mergeConfigurations: boolean = false;
private includePath?: string[];
private defines?: string[];
private forcedInclude?: string[];
private browsePath?: string[];
private hoverProvider: HoverProvider | undefined;
private copilotHoverProvider: CopilotHoverProvider | undefined;
private copilotCompletionProvider?: CopilotCompletionContextProvider;
Expand Down Expand Up @@ -2181,6 +2186,7 @@ export class DefaultClient implements Client {
if (configs && configs.length > 0 && configs[0]) {
const fileConfiguration: configs.Configuration | undefined = this.configuration.CurrentConfiguration;
if (fileConfiguration?.mergeConfigurations) {
configs = deepCopy(configs);
configs.forEach(config => {
if (fileConfiguration.includePath) {
fileConfiguration.includePath.forEach(p => {
Expand Down Expand Up @@ -3139,11 +3145,45 @@ export class DefaultClient implements Client {
const configName: string | undefined = configurations[params.currentConfiguration].name ?? "";
this.model.activeConfigName.setValueIfActive(configName);
const newProvider: string | undefined = this.configuration.CurrentConfigurationProvider;
if (!isSameProviderExtensionId(newProvider, this.configurationProvider)) {
if (this.configurationProvider) {
const previousProvider: string | undefined = this.configurationProvider;
let updateCustomConfigs: boolean = false;
if (!isSameProviderExtensionId(previousProvider, newProvider)) {
this.configurationProvider = newProvider;
updateCustomConfigs = true;
}
if (newProvider !== undefined) {
const newMergeConfigurations: boolean = this.configuration.CurrentMergeConfigurations;
if (this.mergeConfigurations !== newMergeConfigurations) {
this.mergeConfigurations = newMergeConfigurations;
updateCustomConfigs = true;
}
if (newMergeConfigurations) {
const newIncludePath: string[] | undefined = this.configuration.CurrentIncludePath;
if (!util.equals(this.includePath, newIncludePath)) {
this.includePath = newIncludePath;
updateCustomConfigs = true;
}
const newDefines: string[] | undefined = this.configuration.CurrentDefines;
if (!util.equals(this.defines, newDefines)) {
this.defines = newDefines;
updateCustomConfigs = true;
}
const newForcedInclude: string[] | undefined = this.configuration.CurrentForcedInclude;
if (!util.equals(this.forcedInclude, newForcedInclude)) {
this.forcedInclude = newForcedInclude;
updateCustomConfigs = true;
}
const newBrowsePath: string[] | undefined = this.configuration.CurrentBrowsePath;
if (!util.equals(this.browsePath, newBrowsePath)) {
this.browsePath = newBrowsePath;
updateCustomConfigs = true;
}
}
}
if (updateCustomConfigs) {
if (previousProvider) {
void this.clearCustomBrowseConfiguration().catch(logAndReturn.undefined);
}
this.configurationProvider = newProvider;
void this.updateCustomBrowseConfiguration().catch(logAndReturn.undefined);
void this.updateCustomConfigurations().catch(logAndReturn.undefined);
}
Expand Down
37 changes: 36 additions & 1 deletion Extension/src/LanguageServer/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export interface Configuration {
forcedInclude?: string[];
configurationProviderInCppPropertiesJson?: string;
configurationProvider?: string;
mergeConfigurations?: boolean | string;
mergeConfigurations?: boolean;
browse?: Browse;
recursiveIncludes?: RecursiveIncludes;
customConfigurationVariables?: { [key: string]: string };
Expand Down Expand Up @@ -204,6 +204,41 @@ export class CppProperties {
return new CppSettings(this.rootUri).defaultConfigurationProvider;
}

public get CurrentMergeConfigurations(): boolean {
if (this.CurrentConfiguration?.mergeConfigurations) {
return this.CurrentConfiguration.mergeConfigurations;
}
return new CppSettings(this.rootUri).defaultMergeConfigurations;
}

public get CurrentIncludePath(): string[] | undefined {
if (this.CurrentConfiguration?.includePath) {
return this.CurrentConfiguration.includePath;
}
return new CppSettings(this.rootUri).defaultIncludePath;
}

public get CurrentDefines(): string[] | undefined {
if (this.CurrentConfiguration?.defines) {
return this.CurrentConfiguration.defines;
}
return new CppSettings(this.rootUri).defaultDefines;
}

public get CurrentForcedInclude(): string[] | undefined {
if (this.CurrentConfiguration?.forcedInclude) {
return this.CurrentConfiguration.forcedInclude;
}
return new CppSettings(this.rootUri).defaultForcedInclude;
}

public get CurrentBrowsePath(): string[] | undefined {
if (this.CurrentConfiguration?.browse?.path) {
return this.CurrentConfiguration.browse.path;
}
return new CppSettings(this.rootUri).defaultBrowsePath;
}

public get ConfigurationNames(): string[] | undefined {
const result: string[] = [];
if (this.configurationJson) {
Expand Down
17 changes: 1 addition & 16 deletions Extension/src/LanguageServer/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ export class CppSettings extends Settings {
public get defaultCStandard(): string | undefined { return this.getAsStringOrUndefined("default.cStandard"); }
public get defaultCppStandard(): string | undefined { return this.getAsStringOrUndefined("default.cppStandard"); }
public get defaultConfigurationProvider(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.configurationProvider")); }
public get defaultMergeConfigurations(): boolean | undefined { return this.getAsBooleanOrUndefined("default.mergeConfigurations"); }
public get defaultMergeConfigurations(): boolean { return this.getAsBoolean("default.mergeConfigurations"); }
public get defaultBrowsePath(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.browse.path"); }
public get defaultDatabaseFilename(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.browse.databaseFilename")); }
public get defaultLimitSymbolsToIncludedHeaders(): boolean { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); }
Expand Down Expand Up @@ -569,21 +569,6 @@ export class CppSettings extends Settings {
return undefined;
}

// Returns the value of a setting as a boolean with proper type validation and checks for valid enum values while returning an undefined value if necessary.
private getAsBooleanOrUndefined(settingName: string): boolean | undefined {
const value: any = super.Section.get<any>(settingName);
const setting = getRawSetting("C_Cpp." + settingName, true);
if (setting.default !== undefined) {
console.error(`Default value for ${settingName} is expected to be undefined.`);
}

if (isBoolean(value)) {
return value;
}

return undefined;
}

private isValidDefault(isValid: (x: any) => boolean, value: any, allowNull: boolean): boolean {
return isValid(value) || (allowNull && value === null);
}
Expand Down
18 changes: 18 additions & 0 deletions Extension/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1810,3 +1810,21 @@ export function findExePathInArgs(args: CommandString[]): string | undefined {
export function getVsCodeVersion(): number[] {
return vscode.version.split('.').map(num => parseInt(num, undefined));
}

export function equals(array1: string[] | undefined, array2: string[] | undefined): boolean {
if (array1 === undefined && array2 === undefined) {
return true;
}
if (array1 === undefined || array2 === undefined) {
return false;
}
if (array1.length !== array2.length) {
return false;
}
for (let i: number = 0; i < array1.length; ++i) {
if (array1[i] !== array2[i]) {
return false;
}
}
return true;
}
2 changes: 1 addition & 1 deletion Extension/ui/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@
<div class="section-title" data-loc-id="merge.configurations">Merge configurations</div>
<div>
<input type="checkbox" id="mergeConfigurations" style="vertical-align: middle; transform: scale(1.5)">
<span data-loc-id="merge.configurations.description">When <code>true</code> (or checked), merge include paths, defines, and forced includes with those from a configuration provider.</span>
<span data-loc-id="merge.configurations.description">When <code>true</code> (or checked), merge <code>includePath</code>, <code>defines</code>, <code>forcedInclude</code>, and <code>browse.path</code> with those received from the configuration provider.</span>
</input>
</div>
</div>
Expand Down