Skip to content

Commit 1145a49

Browse files
show a Squiggle if there is a duplicate configuration name (#6752)
* change master to main * check for duplicate names * check duplicates before removing the later configs * spelling check * fix spelling error * add configNameInvalid for UI error(won't show yet) * show the UI error * squiggle for all duplicates * change let to const * squiggle for first one as well * let to const
1 parent 02c547b commit 1145a49

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

Extension/src/LanguageServer/configurations.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export interface Configuration {
7878
}
7979

8080
export interface ConfigurationErrors {
81+
name?: string;
8182
compilerPath?: string;
8283
includePath?: string;
8384
intelliSenseMode?: string;
@@ -1145,6 +1146,9 @@ export class CppProperties {
11451146
const isWindows: boolean = os.platform() === 'win32';
11461147
const config: Configuration = this.configurationJson.configurations[configIndex];
11471148

1149+
// Check if config name is unique.
1150+
errors.name = this.isConfigNameUnique(config.name);
1151+
11481152
// Validate compilerPath
11491153
let resolvedCompilerPath: string | undefined = this.resolvePath(config.compilerPath, isWindows);
11501154
const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(resolvedCompilerPath);
@@ -1293,6 +1297,15 @@ export class CppProperties {
12931297
return errorMsg;
12941298
}
12951299

1300+
private isConfigNameUnique(configName: string): string | undefined {
1301+
let errorMsg: string | undefined;
1302+
const occurrences: number | undefined = this.ConfigurationNames?.filter(function (name): boolean { return name === configName; }).length;
1303+
if (occurrences) {
1304+
errorMsg = localize('duplicate.name', "{0} is a duplicate. The configuration name should be unique.", configName);
1305+
}
1306+
return errorMsg;
1307+
}
1308+
12961309
private handleSquiggles(): void {
12971310
if (!this.propertiesFile) {
12981311
return;
@@ -1334,8 +1347,49 @@ export class CppProperties {
13341347
envText = curText.substr(envStart, envEnd);
13351348
const envTextStartOffSet: number = envStart + 1;
13361349

1350+
// Check if all config names are unique.
1351+
let allConfigText: string = curText;
1352+
let allConfigTextOffset: number = envTextStartOffSet;
1353+
const nameRegex: RegExp = new RegExp(`{\\s*"name"\\s*:\\s*".*"`);
1354+
let configStart: number = allConfigText.search(new RegExp(nameRegex));
1355+
let configNameStart: number;
1356+
let configNameEnd: number;
1357+
let configName: string;
1358+
const configNames: Map<string, vscode.Range[]> = new Map<string, []>();
1359+
let dupErrorMsg: string;
1360+
while (configStart !== -1) {
1361+
allConfigText = allConfigText.substr(configStart);
1362+
allConfigTextOffset += configStart;
1363+
configNameStart = allConfigText.indexOf('"', allConfigText.indexOf(':') + 1) + 1;
1364+
configNameEnd = allConfigText.indexOf('"', configNameStart);
1365+
configName = allConfigText.substr(configNameStart, configNameEnd - configNameStart);
1366+
const newRange: vscode.Range = new vscode.Range(0, allConfigTextOffset + configNameStart, 0, allConfigTextOffset + configNameEnd);
1367+
const allRanges: vscode.Range[] | undefined = configNames.get(configName);
1368+
if (allRanges) {
1369+
allRanges.push(newRange);
1370+
configNames.set(configName, allRanges);
1371+
} else {
1372+
configNames.set(configName, [newRange]);
1373+
}
1374+
allConfigText = allConfigText.substr(configNameEnd + 1);
1375+
allConfigTextOffset += configNameEnd + 1;
1376+
configStart = allConfigText.search(new RegExp(nameRegex));
1377+
}
1378+
for (const [configName, allRanges] of configNames) {
1379+
if (allRanges && allRanges.length > 1) {
1380+
dupErrorMsg = localize('duplicate.name', "{0} is a duplicate. The configuration name should be unique.", configName);
1381+
allRanges.forEach(nameRange => {
1382+
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(
1383+
new vscode.Range(document.positionAt(nameRange.start.character),
1384+
document.positionAt(nameRange.end.character)),
1385+
dupErrorMsg, vscode.DiagnosticSeverity.Warning);
1386+
diagnostics.push(diagnostic);
1387+
});
1388+
}
1389+
}
1390+
13371391
// Get current config text
1338-
const configStart: number = curText.search(new RegExp(`{\\s*"name"\\s*:\\s*"${escapeStringRegExp(currentConfiguration.name)}"`));
1392+
configStart = curText.search(new RegExp(`{\\s*"name"\\s*:\\s*"${escapeStringRegExp(currentConfiguration.name)}"`));
13391393
if (configStart === -1) {
13401394
telemetry.logLanguageServerEvent("ConfigSquiggles", { "error": "config name not first" });
13411395
return;

Extension/src/LanguageServer/settingsPanel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import * as telemetry from '../telemetry';
1515
const elementId: { [key: string]: string } = {
1616
// Basic settings
1717
configName: "configName",
18+
configNameInvalid: "configNameInvalid",
1819
configSelection: "configSelection",
1920
addConfigBtn: "addConfigBtn",
2021
addConfigOk: "addConfigOk",

Extension/ui/settings.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@
455455
<tr>
456456
<!-- select configuration name -->
457457
<td>
458-
<div class="select-editable" style="width: 300px; margin-right: 10px">
458+
<div class="select-editable" style="width: 300px; margin-left: -3px; margin-right: 7px">
459459
<select id="configSelection" style="width: 300px"></select>
460460
<input id=configName style="width: 267px" type="text"/>
461461
</div>
@@ -473,6 +473,7 @@
473473
</td>
474474
</tr>
475475
</table>
476+
<div id="configNameInvalid" class="error" style="width: 290px"></div>
476477
</div>
477478
</div>
478479

Extension/ui/settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
const elementId: { [key: string]: string } = {
88
// Basic settings
99
configName: "configName",
10+
configNameInvalid: "configNameInvalid",
1011
configSelection: "configSelection",
1112
addConfigDiv: "addConfigDiv",
1213
addConfigBtn: "addConfigBtn",
@@ -285,6 +286,7 @@ class SettingsApp {
285286
private updateErrors(errors: any): void {
286287
this.updating = true;
287288
try {
289+
this.showErrorWithInfo(elementId.configNameInvalid, errors.name);
288290
this.showErrorWithInfo(elementId.intelliSenseModeInvalid, errors.intelliSenseMode);
289291
this.showErrorWithInfo(elementId.compilerPathInvalid, errors.compilerPath);
290292
this.showErrorWithInfo(elementId.includePathInvalid, errors.includePath);

0 commit comments

Comments
 (0)