From 704334bd10f253cf43212757b4dc9da07e562d1b Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 24 Jun 2024 18:21:36 -0700 Subject: [PATCH 01/52] Add initial type and enum validation for extension settings --- Extension/package.json | 45 +- .../Providers/foldingRangeProvider.ts | 5 +- Extension/src/LanguageServer/client.ts | 25 +- Extension/src/LanguageServer/settings.ts | 618 +++++++++++++----- Extension/src/telemetry.ts | 2 +- 5 files changed, 477 insertions(+), 218 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index f978613e3a..d97d15fa22 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -530,13 +530,9 @@ "minimum": 500, "maximum": 3000 }, - "C_Cpp.codeFolding": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ], - "default": "enabled", + "C_Cpp.codeFolding.enabled": { + "type": "boolean", + "default": false, "description": "%c_cpp.configuration.codeFolding.description%", "scope": "window" }, @@ -552,13 +548,9 @@ "markdownDescription": "%c_cpp.configuration.suggestSnippets.markdownDescription%", "scope": "resource" }, - "C_Cpp.enhancedColorization": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ], - "default": "enabled", + "C_Cpp.enhancedColorization.enabled": { + "type": "boolean", + "default": false, "markdownDescription": "%c_cpp.configuration.enhancedColorization.markdownDescription%", "scope": "window" }, @@ -699,6 +691,7 @@ }, "C_Cpp.default.forcedInclude": { "type": "array", + "default": "undefined", "items": { "type": "string" }, @@ -877,13 +870,9 @@ "markdownDescription": "%c_cpp.configuration.default.dotConfig.markdownDescription%", "scope": "resource" }, - "C_Cpp.configurationWarnings": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ], - "default": "enabled", + "C_Cpp.configurationWarnings.enabled": { + "type": "boolean", + "default": false, "description": "%c_cpp.configuration.configurationWarnings.description%", "scope": "resource" }, @@ -915,13 +904,9 @@ ], "scope": "resource" }, - "C_Cpp.intelliSenseEngineFallback": { - "type": "string", - "enum": [ - "enabled", - "disabled" - ], - "default": "disabled", + "C_Cpp.intelliSenseEngineFallback.enabled": { + "type": "boolean", + "default": false, "markdownDescription": "%c_cpp.configuration.intelliSenseEngineFallback.markdownDescription%", "scope": "resource" }, @@ -3192,7 +3177,7 @@ "null" ], "markdownDescription": "%c_cpp.configuration.intelliSense.maxCachedProcesses.markdownDescription%", - "default": null, + "default": 128, "minimum": 2, "maximum": 128, "scope": "machine" @@ -3203,7 +3188,7 @@ "null" ], "markdownDescription": "%c_cpp.configuration.intelliSense.maxMemory.markdownDescription%", - "default": null, + "default": 65536, "minimum": 256, "maximum": 65536, "scope": "machine" diff --git a/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts b/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts index 73c7dfa50e..3498285f07 100644 --- a/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts +++ b/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts @@ -27,7 +27,7 @@ export class FoldingRangeProvider implements vscode.FoldingRangeProvider { async provideFoldingRanges(document: vscode.TextDocument, context: vscode.FoldingContext, token: vscode.CancellationToken): Promise { await this.client.ready; const settings: CppSettings = new CppSettings(); - if (!settings.codeFolding) { + if (!settings.codeFoldingEnabled) { return []; } @@ -57,8 +57,7 @@ export class FoldingRangeProvider implements vscode.FoldingRangeProvider { return promise; } - private async requestRanges(uri: string, token: vscode.CancellationToken): Promise - { + private async requestRanges(uri: string, token: vscode.CancellationToken): Promise { const params: GetFoldingRangesParams = { uri }; diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 95e11724ea..ad473c7c65 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -533,13 +533,11 @@ interface DidChangeActiveEditorParams { selection?: Range; } -interface GetIncludesParams -{ +interface GetIncludesParams { maxDepth: number; } -interface GetIncludesResult -{ +interface GetIncludesResult { includedFiles: string[]; } @@ -1274,7 +1272,7 @@ export class DefaultClient implements Client { this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, this.codeFoldingProvider); const settings: CppSettings = new CppSettings(); - if (settings.enhancedColorization && semanticTokensLegend) { + if (settings.enhancedColorizationEnabled && semanticTokensLegend) { this.semanticTokensProvider = new SemanticTokensProvider(); this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend); } @@ -1324,7 +1322,7 @@ export class DefaultClient implements Client { const result: WorkspaceFolderSettingsParams = { uri: workspaceFolderUri?.toString(), intelliSenseEngine: settings.intelliSenseEngine, - intelliSenseEngineFallback: settings.intelliSenseEngineFallback, + intelliSenseEngineFallback: settings.intelliSenseEngineFallbackEnabled, autocomplete: settings.autocomplete, autocompleteAddParentheses: settings.autocompleteAddParentheses, errorSquiggles: settings.errorSquiggles, @@ -1351,9 +1349,6 @@ export class DefaultClient implements Client { clangTidyHeaderFilter: settings.clangTidyHeaderFilter !== null ? util.resolveVariables(settings.clangTidyHeaderFilter, this.AdditionalEnvironment) : null, clangTidyArgs: util.resolveVariablesArray(settings.clangTidyArgs, this.AdditionalEnvironment), clangTidyUseBuildPath: settings.clangTidyUseBuildPath, - clangTidyFixWarnings: settings.clangTidyFixWarnings, - clangTidyFixErrors: settings.clangTidyFixErrors, - clangTidyFixNotes: settings.clangTidyFixNotes, clangTidyChecksEnabled: settings.clangTidyChecksEnabled, clangTidyChecksDisabled: settings.clangTidyChecksDisabled, markdownInComments: settings.markdownInComments, @@ -1448,6 +1443,7 @@ export class DefaultClient implements Client { private getAllSettings(): SettingsParams { const workspaceSettings: CppSettings = new CppSettings(); const workspaceOtherSettings: OtherSettings = new OtherSettings(); + console.log(workspaceOtherSettings.editorTabSize); const workspaceFolderSettingsParams: WorkspaceFolderSettingsParams[] = this.getAllWorkspaceFolderSettings(); return { filesAssociations: workspaceOtherSettings.filesAssociations, @@ -1461,8 +1457,8 @@ export class DefaultClient implements Client { workspaceSymbols: workspaceSettings.workspaceSymbols, simplifyStructuredComments: workspaceSettings.simplifyStructuredComments, intelliSenseUpdateDelay: workspaceSettings.intelliSenseUpdateDelay, - experimentalFeatures: workspaceSettings.experimentalFeatures, - enhancedColorization: workspaceSettings.enhancedColorization, + experimentalFeaturesEnabled: workspaceSettings.experimentalFeaturesEnabled, + enhancedColorizationEnabled: workspaceSettings.enhancedColorizationEnabled, intellisenseMaxCachedProcesses: workspaceSettings.intelliSenseMaxCachedProcesses, intellisenseMaxMemory: workspaceSettings.intelliSenseMaxMemory, referencesMaxConcurrentThreads: workspaceSettings.referencesMaxConcurrentThreads, @@ -1634,7 +1630,7 @@ export class DefaultClient implements Client { } const settings: CppSettings = new CppSettings(); if (changedSettings.enhancedColorization) { - if (settings.enhancedColorization && semanticTokensLegend) { + if (settings.enhancedColorizationEnabled && semanticTokensLegend) { this.semanticTokensProvider = new SemanticTokensProvider(); this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend); } else if (this.semanticTokensProviderDisposable) { @@ -2100,7 +2096,7 @@ export class DefaultClient implements Client { result = "timeout"; if (!requestFile) { const settings: CppSettings = new CppSettings(this.RootUri); - if (settings.configurationWarnings && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) { + if (settings.configurationWarningsEnabled && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) { const dismiss: string = localize("dismiss.button", "Dismiss"); const disable: string = localize("disable.warnings.button", "Disable Warnings"); const configName: string | undefined = this.configuration.CurrentConfiguration?.name; @@ -3472,8 +3468,7 @@ export class DefaultClient implements Client { } let formatParams: FormatParams | undefined; - if (cppSettings.useVcFormat(editor.document)) - { + if (cppSettings.useVcFormat(editor.document)) { const editorConfigSettings: any = getEditorConfigSettings(uri.fsPath); formatParams = { editorConfigSettings: editorConfigSettings, diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index a66a97c50c..aa77358478 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -14,7 +14,7 @@ import { quote } from 'shell-quote'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as which from 'which'; -import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; +import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArrayOfString, isBoolean, isNumber, isString, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; import { clients } from './extension'; @@ -58,9 +58,6 @@ export interface WorkspaceFolderSettingsParams { clangTidyHeaderFilter: string | undefined | null; clangTidyArgs: string[] | undefined; clangTidyUseBuildPath: boolean | undefined; - clangTidyFixWarnings: boolean | undefined; - clangTidyFixErrors: boolean | undefined; - clangTidyFixNotes: boolean | undefined; clangTidyChecksEnabled: string[] | undefined; clangTidyChecksDisabled: string[] | undefined; hover: string | undefined; @@ -148,8 +145,8 @@ export interface SettingsParams { workspaceSymbols: string | undefined; simplifyStructuredComments: boolean | undefined; intelliSenseUpdateDelay: number | undefined; - experimentalFeatures: boolean | undefined; - enhancedColorization: boolean | undefined; + experimentalFeaturesEnabled: boolean | undefined; + enhancedColorizationEnabled: boolean | undefined; intellisenseMaxCachedProcesses: number | null | undefined; intellisenseMaxMemory: number | null | undefined; referencesMaxConcurrentThreads: number | null | undefined; @@ -258,7 +255,7 @@ export class CppSettings extends Settings { } private getClangPath(isFormat: boolean): string | undefined { - let path: string | undefined = changeBlankStringToUndefined(super.Section.get(isFormat ? "clang_format_path" : "codeAnalysis.clangTidy.path")); + let path: string | undefined = changeBlankStringToUndefined(this.getAsString(isFormat ? "clang_format_path" : "codeAnalysis.clangTidy.path")); if (!path) { const cachedClangPath: string | undefined = isFormat ? getCachedClangFormatPath() : getCachedClangTidyPath(); if (cachedClangPath !== undefined) { @@ -312,36 +309,170 @@ export class CppSettings extends Settings { return path; } - public get maxConcurrentThreads(): number | undefined | null { return super.Section.get("maxConcurrentThreads"); } - public get maxMemory(): number | undefined | null { return super.Section.get("maxMemory"); } - public get maxSymbolSearchResults(): number | undefined { return super.Section.get("maxSymbolSearchResults"); } - public get maxCachedProcesses(): number | undefined | null { return super.Section.get("maxCachedProcesses"); } - public get intelliSenseMaxCachedProcesses(): number | undefined | null { return super.Section.get("intelliSense.maxCachedProcesses"); } - public get intelliSenseMaxMemory(): number | undefined | null { return super.Section.get("intelliSense.maxMemory"); } - public get referencesMaxConcurrentThreads(): number | undefined | null { return super.Section.get("references.maxConcurrentThreads"); } - public get referencesMaxCachedProcesses(): number | undefined | null { return super.Section.get("references.maxCachedProcesses"); } - public get referencesMaxMemory(): number | undefined | null { return super.Section.get("references.maxMemory"); } - public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { return super.Section.get("codeAnalysis.maxConcurrentThreads"); } - public get codeAnalysisMaxMemory(): number | undefined | null { return super.Section.get("codeAnalysis.maxMemory"); } - public get codeAnalysisUpdateDelay(): number | undefined { return super.Section.get("codeAnalysis.updateDelay"); } - public get codeAnalysisExclude(): vscode.WorkspaceConfiguration | undefined { return super.Section.get("codeAnalysis.exclude"); } - public get codeAnalysisRunAutomatically(): boolean | undefined { return super.Section.get("codeAnalysis.runAutomatically"); } - public get codeAnalysisRunOnBuild(): boolean | undefined { return false; } // super.Section.get("codeAnalysis.runOnBuild"); } - public get clangTidyEnabled(): boolean | undefined { return super.Section.get("codeAnalysis.clangTidy.enabled"); } - public get clangTidyConfig(): string | undefined { return changeBlankStringToUndefined(super.Section.get("codeAnalysis.clangTidy.config")); } - public get clangTidyFallbackConfig(): string | undefined { return changeBlankStringToUndefined(super.Section.get("codeAnalysis.clangTidy.fallbackConfig")); } - public get clangTidyFixWarnings(): boolean | undefined { return false; } // super.Section.get("codeAnalysis.clangTidy.fix.warnings"); } - public get clangTidyFixErrors(): boolean | undefined { return false; } // super.Section.get("codeAnalysis.clangTidy.fix.errors"); } - public get clangTidyFixNotes(): boolean | undefined { return false; } // super.Section.get("codeAnalysis.clangTidy.fix.notes"); } - public get clangTidyHeaderFilter(): string | undefined | null { return super.Section.get("codeAnalysis.clangTidy.headerFilter"); } - public get clangTidyArgs(): string[] | undefined { return super.Section.get("codeAnalysis.clangTidy.args"); } - public get clangTidyUseBuildPath(): boolean | undefined { return super.Section.get("codeAnalysis.clangTidy.useBuildPath"); } - public get clangTidyChecksEnabled(): string[] | undefined { return super.Section.get("codeAnalysis.clangTidy.checks.enabled"); } - public get clangTidyChecksDisabled(): string[] | undefined { return super.Section.get("codeAnalysis.clangTidy.checks.disabled"); } - public get clangTidyCodeActionShowDisable(): boolean | undefined { return super.Section.get("codeAnalysis.clangTidy.codeAction.showDisable"); } - public get clangTidyCodeActionShowClear(): string { return super.Section.get("codeAnalysis.clangTidy.codeAction.showClear") ?? "AllAndAllType"; } - public get clangTidyCodeActionShowDocumentation(): boolean | undefined { return super.Section.get("codeAnalysis.clangTidy.codeAction.showDocumentation"); } - public get clangTidyCodeActionFormatFixes(): boolean { return super.Section.get("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; } + private getAsBoolean(settingName: string): boolean { + const value: any | undefined = super.Section.get(settingName); + if (isBoolean(value)) { + return value; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; + } + + // TODO: Determine the behavior of settings that don't have default values set. Generally, they should return undefined. + // TODO: Persist the lowercasing of enum values. + private getAsString(settingName: string): string { + const value: any | undefined = super.Section.get(settingName); + if (isString(value)) { + return value; + } else if (this.isValidEnum(settingName, value)) { + + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; + } + + private getAsNumber(settingName: string): number { + const value: any | undefined | null = super.Section.get(settingName); + if (isNumber(value)) { + return value; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; + } + + private getAsArrayOfStrings(settingName: string): string[] { + const value: any | undefined | null = super.Section.get(settingName); + if (isArrayOfString(value)) { + return value; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; + } + + private isValidEnum(settingName: string, value: any): boolean { + const setting = getRawSetting("C_Cpp." + settingName); + for (let i: number = 0; i < setting.enum.length; i++) { + if (value.toLowerCase() == setting.enum[i]) { + return true; + } + } + return false; + } + + // TODO: Create a isValidEnum(setting, value) function, use this function in getAsString to remove the getAsEnum function and a getAsEnumArray() to get the enumArray if it is there. Use C_Cpp.codeAnalysis.clangTidy.checks.enabled as a test case. + + + public get maxConcurrentThreads(): number | undefined | null { + return this.getAsNumber("maxConcurrentThreads"); + } + + public get maxMemory(): number | undefined | null { + return this.getAsNumber("maxMemory"); + } + + public get maxSymbolSearchResults(): number | undefined { + return this.getAsNumber("maxSymbolSearchResults"); + } + + public get maxCachedProcesses(): number | undefined | null { + return this.getAsNumber("maxCachedProcesses"); + } + + public get intelliSenseMaxCachedProcesses(): number | undefined | null { + return this.getAsNumber("intelliSense.maxCachedProcesses"); + } + + public get intelliSenseMaxMemory(): number | undefined | null { + return this.getAsNumber("intelliSense.maxMemory"); + } + + public get referencesMaxConcurrentThreads(): number | undefined | null { + return this.getAsNumber("references.maxConcurrentThreads"); + } + + public get referencesMaxCachedProcesses(): number | undefined | null { + return this.getAsNumber("references.maxCachedProcesses"); + } + + public get referencesMaxMemory(): number | undefined | null { + return this.getAsNumber("references.maxMemory"); + } + + public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { + return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); + } + + public get codeAnalysisMaxMemory(): number | undefined | null { + return this.getAsNumber("codeAnalysis.maxMemory"); + } + + public get codeAnalysisUpdateDelay(): number | undefined { + return this.getAsNumber("codeAnalysis.updateDelay"); + } + + public get codeAnalysisExclude(): vscode.WorkspaceConfiguration | undefined { + const value = super.Section.get("codeAnalysis.exclude"); + console.log(value); + console.log(value?.key); + return typeof value?.key === "string" ? value : undefined; + } + + public get codeAnalysisRunAutomatically(): boolean | undefined { + return this.getAsBoolean("codeAnalysis.runAutomatically"); + } + + public get codeAnalysisRunOnBuild(): boolean | undefined { + return this.getAsBoolean("codeAnalysis.runOnBuild"); + } + + public get clangTidyEnabled(): boolean | undefined { + return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); + } + + public get clangTidyConfig(): string | undefined { + return this.getAsString("codeAnalysis.clangTidy.config"); + } + + public get clangTidyFallbackConfig(): string | undefined { + return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); + } + + public get clangTidyHeaderFilter(): string | undefined | null { + return this.getAsString("codeAnalysis.clangTidy.headerFilter"); + } + + public get clangTidyArgs(): string[] | undefined { + return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); + } + + public get clangTidyUseBuildPath(): boolean | undefined { + return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); + } + + public get clangTidyChecksEnabled(): string[] | undefined { + return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled"); + } + + public get clangTidyChecksDisabled(): string[] | undefined { + return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled"); + } + + public get clangTidyCodeActionShowDisable(): boolean | undefined { + return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); + } + + public get clangTidyCodeActionShowClear(): string { + return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); + } + public get clangTidyCodeActionShowDocumentation(): boolean | undefined { + return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); + } + + public get clangTidyCodeActionFormatFixes(): boolean { + return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; + } + + // TODO public addClangTidyChecksDisabled(value: string): void { const checks: string[] | undefined = this.clangTidyChecksDisabled; if (checks === undefined) { @@ -350,50 +481,196 @@ export class CppSettings extends Settings { checks.push(value); void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } - public get clangFormatStyle(): string | undefined { return changeBlankStringToUndefined(super.Section.get("clang_format_style")); } - public get clangFormatFallbackStyle(): string | undefined { return changeBlankStringToUndefined(super.Section.get("clang_format_fallbackStyle")); } - public get clangFormatSortIncludes(): boolean | undefined | null { return super.Section.get("clang_format_sortIncludes"); } - public get experimentalFeatures(): boolean | undefined { return super.Section.get("experimentalFeatures")?.toLowerCase() === "enabled"; } - public get suggestSnippets(): boolean | undefined { return super.Section.get("suggestSnippets"); } - public get intelliSenseEngine(): string | undefined { return super.Section.get("intelliSenseEngine")?.toLowerCase(); } - public get intelliSenseEngineFallback(): boolean | undefined { return super.Section.get("intelliSenseEngineFallback")?.toLowerCase() === "enabled"; } - public get intelliSenseCachePath(): string | undefined { return changeBlankStringToUndefined(super.Section.get("intelliSenseCachePath")); } - public get intelliSenseCacheSize(): number | undefined { return super.Section.get("intelliSenseCacheSize"); } - public get intelliSenseMemoryLimit(): number | undefined { return super.Section.get("intelliSenseMemoryLimit"); } - public get intelliSenseUpdateDelay(): number | undefined { return super.Section.get("intelliSenseUpdateDelay"); } - public get errorSquiggles(): string | undefined { return super.Section.get("errorSquiggles")?.toLowerCase(); } - public get inactiveRegionOpacity(): number | undefined { return super.Section.get("inactiveRegionOpacity"); } - public get inactiveRegionForegroundColor(): string | undefined { return changeBlankStringToUndefined(super.Section.get("inactiveRegionForegroundColor")); } - public get inactiveRegionBackgroundColor(): string | undefined { return changeBlankStringToUndefined(super.Section.get("inactiveRegionBackgroundColor")); } - public get autocomplete(): string | undefined { return super.Section.get("autocomplete"); } - public get autocompleteAddParentheses(): boolean | undefined { return super.Section.get("autocompleteAddParentheses"); } - public get loggingLevel(): string | undefined { return super.Section.get("loggingLevel"); } - public get autoAddFileAssociations(): boolean | undefined { return super.Section.get("autoAddFileAssociations"); } - public get workspaceParsingPriority(): string | undefined { return super.Section.get("workspaceParsingPriority"); } - public get workspaceSymbols(): string | undefined { return super.Section.get("workspaceSymbols"); } - public get exclusionPolicy(): string | undefined { return super.Section.get("exclusionPolicy"); } - public get refactoringIncludeHeader(): string | undefined { return super.Section.get("refactoring.includeHeader"); } - public get simplifyStructuredComments(): boolean | undefined { return super.Section.get("simplifyStructuredComments"); } - public get doxygenGeneratedCommentStyle(): string | undefined { return super.Section.get("doxygen.generatedStyle"); } - public get doxygenGenerateOnType(): boolean | undefined { return super.Section.get("doxygen.generateOnType"); } - // eslint-disable-next-line no-extra-parens - public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { return super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); } - public get configurationWarnings(): boolean | undefined { return super.Section.get("configurationWarnings")?.toLowerCase() !== "disabled"; } - public get preferredPathSeparator(): string | undefined { return super.Section.get("preferredPathSeparator"); } - public get updateChannel(): string | undefined { return super.Section.get("updateChannel"); } - public get vcpkgEnabled(): boolean | undefined { return super.Section.get("vcpkg.enabled"); } - public get addNodeAddonIncludePaths(): boolean | undefined { return super.Section.get("addNodeAddonIncludePaths"); } - public get renameRequiresIdentifier(): boolean | undefined { return super.Section.get("renameRequiresIdentifier"); } - public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return super.Section.get("files.exclude"); } - public get defaultIncludePath(): string[] | undefined { return super.getWithUndefinedDefault("default.includePath"); } - public get defaultDefines(): string[] | undefined { return super.getWithUndefinedDefault("default.defines"); } - public get defaultDotconfig(): string | undefined { return changeBlankStringToUndefined(super.Section.get("default.dotConfig")); } - public get defaultMacFrameworkPath(): string[] | undefined { return super.getWithUndefinedDefault("default.macFrameworkPath"); } - public get defaultWindowsSdkVersion(): string | undefined { return changeBlankStringToUndefined(super.Section.get("default.windowsSdkVersion")); } - public get defaultCompileCommands(): string | undefined { return changeBlankStringToUndefined(super.Section.get("default.compileCommands")); } - public get defaultForcedInclude(): string[] | undefined { return super.getWithUndefinedDefault("default.forcedInclude"); } - public get defaultIntelliSenseMode(): string | undefined { return super.Section.get("default.intelliSenseMode"); } - public get defaultCompilerPath(): string | undefined { return super.Section.get("default.compilerPath") ?? undefined; } + + public get clangFormatStyle(): string | undefined { + return this.getAsString("clang_format_style"); + } + + public get clangFormatFallbackStyle(): string | undefined { + return this.getAsString("clang_format_fallbackStyle"); + } + + public get clangFormatSortIncludes(): boolean | undefined | null { + return this.getAsBoolean("clang_format_sortIncludes"); + } + + // TODO: Refactor experimentalFeatures to experimentalFeaturesEnabled which is a boolean value in packagae.json. + public get experimentalFeaturesEnabled(): boolean | undefined { + return this.getAsBoolean("experimentalFeatures.enabled"); + } + + public get suggestSnippets(): boolean | undefined { + return this.getAsBoolean("suggestSnippets"); + } + + public get intelliSenseEngine(): string | undefined { + return this.getAsString("intelliSenseEngine"); + } + + public get intelliSenseEngineFallbackEnabled(): boolean | undefined { + return this.getAsBoolean("intelliSenseEngineFallback.enabled"); + } + + public get intelliSenseCachePath(): string | undefined { + return this.getAsString("intelliSenseEngine"); + } + + public get intelliSenseCacheSize(): number | undefined { + return this.getAsNumber("intelliSenseCachePath"); + } + + public get intelliSenseMemoryLimit(): number | undefined { + return this.getAsNumber("intelliSenseMemoryLimit"); + } + + public get intelliSenseUpdateDelay(): number | undefined { + return this.getAsNumber("intelliSenseUpdateDelay"); + } + + public get errorSquiggles(): string | undefined { + return this.getAsString("errorSquiggles"); + } + + public get inactiveRegionOpacity(): number | undefined { + return this.getAsNumber("inactiveRegionOpacity"); + + } + + public get inactiveRegionForegroundColor(): string | undefined { + return this.getAsString("inactiveRegionForegroundColor"); + } + + public get inactiveRegionBackgroundColor(): string | undefined { + return this.getAsString("inactiveRegionBackgroundColor"); + } + + public get autocomplete(): string | undefined { + return this.getAsString("autocomplete"); + } + + public get autocompleteAddParentheses(): boolean | undefined { + return this.getAsBoolean("autocompleteAddParentheses"); + } + + public get loggingLevel(): string | undefined { + return this.getAsString("loggingLevel"); + } + + public get autoAddFileAssociations(): boolean | undefined { + return this.getAsBoolean("autoAddFileAssociations"); + } + + public get workspaceParsingPriority(): string | undefined { + return this.getAsString("workspaceParsingPriority"); + } + + public get workspaceSymbols(): string | undefined { + return this.getAsString("workspaceSymbols"); + } + + public get exclusionPolicy(): string | undefined { + return this.getAsString("exclusionPolicy"); + } + + public get refactoringIncludeHeader(): string | undefined { + return this.getAsString("refactoring.includeHeader"); + } + + public get simplifyStructuredComments(): boolean | undefined { + return this.getAsBoolean("simplifyStructuredComments"); + + } + + public get doxygenGeneratedCommentStyle(): string | undefined { + return this.getAsString("doxygen.generatedStyle"); + } + + public get doxygenGenerateOnType(): boolean | undefined { + return this.getAsBoolean("doxygen.generateOnType"); + } + /* TODO Use*/ + public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { + const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); + if (Array.isArray(value)) { + return value; + } + return undefined; + } + + public get configurationWarningsEnabled(): boolean | undefined { + return this.getAsBoolean("configurationWarnings.enabled"); + } + + public get preferredPathSeparator(): string | undefined { + return this.getAsString("preferredPathSeparator"); + } + + public get updateChannel(): string | undefined { + return this.getAsString("updateChannel"); + } + + public get vcpkgEnabled(): boolean | undefined { + return this.getAsBoolean("vcpkg.enabled"); + } + + public get addNodeAddonIncludePaths(): boolean | undefined { + return this.getAsBoolean("addNodeAddonIncludePaths"); + } + + public get renameRequiresIdentifier(): boolean | undefined { + return this.getAsBoolean("renameRequiresIdentifier"); + } + + // TODO + public get filesExclude(): vscode.WorkspaceConfiguration | undefined { + const value = super.Section.get("files.exclude"); + if (value) { + return value; + } + return undefined; + } + + public get defaultIncludePath(): string[] | undefined { + return this.getAsArrayOfStrings("default.includePath"); + } + + public get defaultDefines(): string[] | undefined { + return this.getAsArrayOfStrings("default.defines"); + } + + public get defaultDotconfig(): string | undefined { + return this.getAsString("default.dotConfig"); + } + + public get defaultMacFrameworkPath(): string[] | undefined { + return this.getAsArrayOfStrings("default.macFrameworkPath"); + } + + public get defaultWindowsSdkVersion(): string | undefined { + return this.getAsString("default.windowsSdkVersion"); + } + + public get defaultCompileCommands(): string | undefined { + return this.getAsString("default.compileCommands"); + } + + public get defaultForcedInclude(): string[] | undefined { + return this.getAsArrayOfStrings("default.forcedInclude"); + } + + public get defaultIntelliSenseMode(): string | undefined { + const value = this.getAsString("default.intelliSenseMode"); + if (value) { + return value; + } + return undefined; + } + + public get defaultCompilerPath(): string | undefined { + return this.getAsString("default.compilerPath") ?? undefined; + } + + public set defaultCompilerPath(value: string | undefined) { const defaultCompilerPathStr: string = "default.compilerPath"; const compilerPathInfo: any = this.Section.inspect(defaultCompilerPathStr); @@ -414,337 +691,340 @@ export class CppSettings extends Settings { }); } } - public get defaultCompilerArgs(): string[] | undefined { return super.getWithUndefinedDefault("default.compilerArgs"); } - public get defaultCStandard(): string | undefined { return super.Section.get("default.cStandard"); } - public get defaultCppStandard(): string | undefined { return super.Section.get("default.cppStandard"); } - public get defaultConfigurationProvider(): string | undefined { return changeBlankStringToUndefined(super.Section.get("default.configurationProvider")); } - public get defaultMergeConfigurations(): boolean | undefined { return super.Section.get("default.mergeConfigurations"); } - public get defaultBrowsePath(): string[] | undefined { return super.getWithUndefinedDefault("default.browse.path") ?? undefined; } - public get defaultDatabaseFilename(): string | undefined { return changeBlankStringToUndefined(super.Section.get("default.browse.databaseFilename")); } - public get defaultLimitSymbolsToIncludedHeaders(): boolean | undefined { return super.Section.get("default.browse.limitSymbolsToIncludedHeaders"); } - public get defaultSystemIncludePath(): string[] | undefined { return super.getWithUndefinedDefault("default.systemIncludePath"); } - public get defaultEnableConfigurationSquiggles(): boolean | undefined { return super.Section.get("default.enableConfigurationSquiggles"); } + public get defaultCompilerArgs(): string[] | undefined { return this.getAsArrayOfStrings("default.compilerArgs"); } + public get defaultCStandard(): string | undefined { return this.getAsString("default.cStandard"); } + public get defaultCppStandard(): string | undefined { return this.getAsString("default.cppStandard"); } + public get defaultConfigurationProvider(): string | undefined { return this.getAsString("default.configurationProvider"); } + public get defaultMergeConfigurations(): boolean | undefined { return this.getAsBoolean("default.mergeConfigurations"); } + public get defaultBrowsePath(): string[] | undefined { return this.getAsArrayOfStrings("default.browse.path") ?? undefined; } + public get defaultDatabaseFilename(): string | undefined { return this.getAsString("default.browse.databaseFilename"); } + public get defaultLimitSymbolsToIncludedHeaders(): boolean | undefined { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } + public get defaultSystemIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.systemIncludePath"); } + public get defaultEnableConfigurationSquiggles(): boolean | undefined { return this.getAsBoolean("default.enableConfigurationSquiggles"); } + // TODO Ask Sean about validating this setting. public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined { return super.Section.get<{ [key: string]: string }>("default.customConfigurationVariables"); } - public get useBacktickCommandSubstitution(): boolean | undefined { return super.Section.get("debugger.useBacktickCommandSubstitution"); } - public get codeFolding(): boolean { return super.Section.get("codeFolding")?.toLowerCase() === "enabled"; } - public get caseSensitiveFileSupport(): boolean { return !isWindows || super.Section.get("caseSensitiveFileSupport") === "enabled"; } - public get doxygenSectionTags(): string[] | undefined { return super.Section.get("doxygen.sectionTags"); } - public get hover(): string | undefined { return super.Section.get("hover"); } - public get markdownInComments(): string | undefined { return super.Section.get("markdownInComments"); } - public get legacyCompilerArgsBehavior(): boolean | undefined { return super.Section.get("legacyCompilerArgsBehavior"); } + public get useBacktickCommandSubstitution(): boolean | undefined { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } + public get codeFoldingEnabled(): boolean { + return this.getAsBoolean("codeFolding.enabled"); + } + public get caseSensitiveFileSupport(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } + public get doxygenSectionTags(): string[] | undefined { return this.getAsArrayOfStrings("doxygen.sectionTags"); } + public get hover(): string | undefined { return this.getAsString("hover"); } + public get markdownInComments(): string | undefined { return this.getAsString("markdownInComments"); } + public get legacyCompilerArgsBehavior(): boolean | undefined { return this.getAsBoolean("legacyCompilerArgsBehavior"); } public get inlayHintsAutoDeclarationTypes(): boolean { - return super.Section.get("inlayHints.autoDeclarationTypes.enabled") === true; + return this.getAsBoolean("inlayHints.autoDeclarationTypes.enabled"); } public get inlayHintsAutoDeclarationTypesShowOnLeft(): boolean { - return super.Section.get("inlayHints.autoDeclarationTypes.showOnLeft") === true; + return this.getAsBoolean("inlayHints.autoDeclarationTypes.showOnLeft"); } public get inlayHintsParameterNames(): boolean { - return super.Section.get("inlayHints.parameterNames.enabled") === true; + return this.getAsBoolean("inlayHints.parameterNames.enabled"); } public get inlayHintsParameterNamesSuppressName(): boolean { - return super.Section.get("inlayHints.parameterNames.suppressWhenArgumentContainsName") === true; + return this.getAsBoolean("inlayHints.parameterNames.suppressWhenArgumentContainsName"); } public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean { - return super.Section.get("inlayHints.parameterNames.hideLeadingUnderscores") === true; + return this.getAsBoolean("inlayHints.parameterNames.hideLeadingUnderscores"); } public get inlayHintsReferenceOperator(): boolean { - return super.Section.get("inlayHints.referenceOperator.enabled") === true; + return this.getAsBoolean("inlayHints.referenceOperator.enabled"); } public get inlayHintsReferenceOperatorShowSpace(): boolean { - return super.Section.get("inlayHints.referenceOperator.showSpace") === true; + return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); } - public get enhancedColorization(): boolean { - return super.Section.get("enhancedColorization")?.toLowerCase() !== "disabled" + public get enhancedColorizationEnabled(): boolean { + return this.getAsBoolean("enhancedColorization") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get formattingEngine(): string | undefined { - return super.Section.get("formatting")?.toLowerCase(); + return this.getAsString("formatting")?.toLowerCase(); } public get vcFormatIndentBraces(): boolean { - return super.Section.get("vcFormat.indent.braces") === true; + return this.getAsBoolean("vcFormat.indent.braces"); } public get vcFormatIndentMultiLineRelativeTo(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.indent.multiLineRelativeTo")!; + return this.getAsString("vcFormat.indent.multiLineRelativeTo")!; } public get vcFormatIndentWithinParentheses(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.indent.withinParentheses")!; + return this.getAsString("vcFormat.indent.withinParentheses")!; } public get vcFormatIndentPreserveWithinParentheses(): boolean { - return super.Section.get("vcFormat.indent.preserveWithinParentheses") === true; + return this.getAsBoolean("vcFormat.indent.preserveWithinParentheses"); } public get vcFormatIndentCaseLabels(): boolean { - return super.Section.get("vcFormat.indent.caseLabels") === true; + return this.getAsBoolean("vcFormat.indent.caseLabels"); } public get vcFormatIndentCaseContents(): boolean { - return super.Section.get("vcFormat.indent.caseContents") === true; + return this.getAsBoolean("vcFormat.indent.caseContents"); } public get vcFormatIndentCaseContentsWhenBlock(): boolean { - return super.Section.get("vcFormat.indent.caseContentsWhenBlock") === true; + return this.getAsBoolean("vcFormat.indent.caseContentsWhenBlock"); } public get vcFormatIndentLambdaBracesWhenParameter(): boolean { - return super.Section.get("vcFormat.indent.lambdaBracesWhenParameter") === true; + return this.getAsBoolean("vcFormat.indent.lambdaBracesWhenParameter"); } public get vcFormatIndentGotoLabels(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.indent.gotoLabels")!; + return this.getAsString("vcFormat.indent.gotoLabels")!; } public get vcFormatIndentPreprocessor(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.indent.preprocessor")!; + return this.getAsString("vcFormat.indent.preprocessor")!; } public get vcFormatIndentAccessSpecifiers(): boolean { - return super.Section.get("vcFormat.indent.accessSpecifiers") === true; + return this.getAsBoolean("vcFormat.indent.accessSpecifiers"); } public get vcFormatIndentNamespaceContents(): boolean { - return super.Section.get("vcFormat.indent.namespaceContents") === true; + return this.getAsBoolean("vcFormat.indent.namespaceContents"); } public get vcFormatIndentPreserveComments(): boolean { - return super.Section.get("vcFormat.indent.preserveComments") === true; + return this.getAsBoolean("vcFormat.indent.preserveComments"); } public get vcFormatNewlineBeforeOpenBraceNamespace(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.newLine.beforeOpenBrace.namespace")!; + return this.getAsString("vcFormat.newLine.beforeOpenBrace.namespace")!; } public get vcFormatNewlineBeforeOpenBraceType(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.newLine.beforeOpenBrace.type")!; + return this.getAsString("vcFormat.newLine.beforeOpenBrace.type")!; } public get vcFormatNewlineBeforeOpenBraceFunction(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.newLine.beforeOpenBrace.function")!; + return this.getAsString("vcFormat.newLine.beforeOpenBrace.function")!; } public get vcFormatNewlineBeforeOpenBraceBlock(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.newLine.beforeOpenBrace.block")!; + return this.getAsString("vcFormat.newLine.beforeOpenBrace.block")!; } public get vcFormatNewlineBeforeOpenBraceLambda(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.newLine.beforeOpenBrace.lambda")!; + return this.getAsString("vcFormat.newLine.beforeOpenBrace.lambda")!; } public get vcFormatNewlineScopeBracesOnSeparateLines(): boolean { - return super.Section.get("vcFormat.newLine.scopeBracesOnSeparateLines") === true; + return this.getAsBoolean("vcFormat.newLine.scopeBracesOnSeparateLines"); } public get vcFormatNewlineCloseBraceSameLineEmptyType(): boolean { - return super.Section.get("vcFormat.newLine.closeBraceSameLine.emptyType") === true; + return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyType"); } public get vcFormatNewlineCloseBraceSameLineEmptyFunction(): boolean { - return super.Section.get("vcFormat.newLine.closeBraceSameLine.emptyFunction") === true; + return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyFunction"); } public get vcFormatNewlineBeforeCatch(): boolean { - return super.Section.get("vcFormat.newLine.beforeCatch") === true; + return this.getAsBoolean("vcFormat.newLine.beforeCatch"); } public get vcFormatNewlineBeforeElse(): boolean { - return super.Section.get("vcFormat.newLine.beforeElse") === true; + return this.getAsBoolean("vcFormat.newLine.beforeElse"); } public get vcFormatNewlineBeforeWhileInDoWhile(): boolean { - return super.Section.get("vcFormat.newLine.beforeWhileInDoWhile") === true; + return this.getAsBoolean("vcFormat.newLine.beforeWhileInDoWhile"); } public get vcFormatSpaceBeforeFunctionOpenParenthesis(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.space.beforeFunctionOpenParenthesis")!; + return this.getAsString("vcFormat.space.beforeFunctionOpenParenthesis")!; } public get vcFormatSpaceWithinParameterListParentheses(): boolean { - return super.Section.get("vcFormat.space.withinParameterListParentheses") === true; + return this.getAsBoolean("vcFormat.space.withinParameterListParentheses"); } public get vcFormatSpaceBetweenEmptyParameterListParentheses(): boolean { - return super.Section.get("vcFormat.space.betweenEmptyParameterListParentheses") === true; + return this.getAsBoolean("vcFormat.space.betweenEmptyParameterListParentheses"); } public get vcFormatSpaceAfterKeywordsInControlFlowStatements(): boolean { - return super.Section.get("vcFormat.space.afterKeywordsInControlFlowStatements") === true; + return this.getAsBoolean("vcFormat.space.afterKeywordsInControlFlowStatements"); } public get vcFormatSpaceWithinControlFlowStatementParentheses(): boolean { - return super.Section.get("vcFormat.space.withinControlFlowStatementParentheses") === true; + return this.getAsBoolean("vcFormat.space.withinControlFlowStatementParentheses"); } public get vcFormatSpaceBeforeLambdaOpenParenthesis(): boolean { - return super.Section.get("vcFormat.space.beforeLambdaOpenParenthesis") === true; + return this.getAsBoolean("vcFormat.space.beforeLambdaOpenParenthesis"); } public get vcFormatSpaceWithinCastParentheses(): boolean { - return super.Section.get("vcFormat.space.withinCastParentheses") === true; + return this.getAsBoolean("vcFormat.space.withinCastParentheses"); } public get vcFormatSpaceAfterCastCloseParenthesis(): boolean { - return super.Section.get("vcFormat.space.afterCastCloseParenthesis") === true; + return this.getAsBoolean("vcFormat.space.afterCastCloseParenthesis"); } public get vcFormatSpaceWithinExpressionParentheses(): boolean { - return super.Section.get("vcFormat.space.withinExpressionParentheses") === true; + return this.getAsBoolean("vcFormat.space.withinExpressionParentheses"); } public get vcFormatSpaceBeforeBlockOpenBrace(): boolean { - return super.Section.get("vcFormat.space.beforeBlockOpenBrace") === true; + return this.getAsBoolean("vcFormat.space.beforeBlockOpenBrace"); } public get vcFormatSpaceBetweenEmptyBraces(): boolean { - return super.Section.get("vcFormat.space.betweenEmptyBraces") === true; + return this.getAsBoolean("vcFormat.space.betweenEmptyBraces"); } public get vcFormatSpaceBeforeInitializerListOpenBrace(): boolean { - return super.Section.get("vcFormat.space.beforeInitializerListOpenBrace") === true; + return this.getAsBoolean("vcFormat.space.beforeInitializerListOpenBrace"); } public get vcFormatSpaceWithinInitializerListBraces(): boolean { - return super.Section.get("vcFormat.space.withinInitializerListBraces") === true; + return this.getAsBoolean("vcFormat.space.withinInitializerListBraces"); } public get vcFormatSpacePreserveInInitializerList(): boolean { - return super.Section.get("vcFormat.space.preserveInInitializerList") === true; + return this.getAsBoolean("vcFormat.space.preserveInInitializerList"); } public get vcFormatSpaceBeforeOpenSquareBracket(): boolean { - return super.Section.get("vcFormat.space.beforeOpenSquareBracket") === true; + return this.getAsBoolean("vcFormat.space.beforeOpenSquareBracket"); } public get vcFormatSpaceWithinSquareBrackets(): boolean { - return super.Section.get("vcFormat.space.withinSquareBrackets") === true; + return this.getAsBoolean("vcFormat.space.withinSquareBrackets"); } public get vcFormatSpaceBeforeEmptySquareBrackets(): boolean { - return super.Section.get("vcFormat.space.beforeEmptySquareBrackets") === true; + return this.getAsBoolean("vcFormat.space.beforeEmptySquareBrackets"); } public get vcFormatSpaceBetweenEmptySquareBrackets(): boolean { - return super.Section.get("vcFormat.space.betweenEmptySquareBrackets") === true; + return this.getAsBoolean("vcFormat.space.betweenEmptySquareBrackets"); } public get vcFormatSpaceGroupSquareBrackets(): boolean { - return super.Section.get("vcFormat.space.groupSquareBrackets") === true; + return this.getAsBoolean("vcFormat.space.groupSquareBrackets"); } public get vcFormatSpaceWithinLambdaBrackets(): boolean { - return super.Section.get("vcFormat.space.withinLambdaBrackets") === true; + return this.getAsBoolean("vcFormat.space.withinLambdaBrackets"); } public get vcFormatSpaceBetweenEmptyLambdaBrackets(): boolean { - return super.Section.get("vcFormat.space.betweenEmptyLambdaBrackets") === true; + return this.getAsBoolean("vcFormat.space.betweenEmptyLambdaBrackets"); } public get vcFormatSpaceBeforeComma(): boolean { - return super.Section.get("vcFormat.space.beforeComma") === true; + return this.getAsBoolean("vcFormat.space.beforeComma"); } public get vcFormatSpaceAfterComma(): boolean { - return super.Section.get("vcFormat.space.afterComma") === true; + return this.getAsBoolean("vcFormat.space.afterComma"); } public get vcFormatSpaceRemoveAroundMemberOperators(): boolean { - return super.Section.get("vcFormat.space.removeAroundMemberOperators") === true; + return this.getAsBoolean("vcFormat.space.removeAroundMemberOperators"); } public get vcFormatSpaceBeforeInheritanceColon(): boolean { - return super.Section.get("vcFormat.space.beforeInheritanceColon") === true; + return this.getAsBoolean("vcFormat.space.beforeInheritanceColon"); } public get vcFormatSpaceBeforeConstructorColon(): boolean { - return super.Section.get("vcFormat.space.beforeConstructorColon") === true; + return this.getAsBoolean("vcFormat.space.beforeConstructorColon"); } public get vcFormatSpaceRemoveBeforeSemicolon(): boolean { - return super.Section.get("vcFormat.space.removeBeforeSemicolon") === true; + return this.getAsBoolean("vcFormat.space.removeBeforeSemicolon"); } public get vcFormatSpaceInsertAfterSemicolon(): boolean { - return super.Section.get("vcFormat.space.insertAfterSemicolon") === true; + return this.getAsBoolean("vcFormat.space.insertAfterSemicolon"); } public get vcFormatSpaceRemoveAroundUnaryOperator(): boolean { - return super.Section.get("vcFormat.space.removeAroundUnaryOperator") === true; + return this.getAsBoolean("vcFormat.space.removeAroundUnaryOperator"); } public get vcFormatSpaceAroundBinaryOperator(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.space.aroundBinaryOperator")!; + return this.getAsString("vcFormat.space.aroundBinaryOperator")!; } public get vcFormatSpaceAroundAssignmentOperator(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.space.aroundAssignmentOperator")!; + return this.getAsString("vcFormat.space.aroundAssignmentOperator")!; } public get vcFormatSpacePointerReferenceAlignment(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.space.pointerReferenceAlignment")!; + return this.getAsString("vcFormat.space.pointerReferenceAlignment")!; } public get vcFormatSpaceAroundTernaryOperator(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.space.aroundTernaryOperator")!; + return this.getAsString("vcFormat.space.aroundTernaryOperator")!; } public get vcFormatWrapPreserveBlocks(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return super.Section.get("vcFormat.wrap.preserveBlocks")!; + return this.getAsString("vcFormat.wrap.preserveBlocks")!; } public get dimInactiveRegions(): boolean { - return super.Section.get("dimInactiveRegions") === true + return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get sshTargetsView(): string { - return super.Section.get("sshTargetsView") ?? 'default'; + return this.getAsString("sshTargetsView") ?? 'default'; } public toggleSetting(name: string, value1: string, value2: string): void { - const value: string | undefined = super.Section.get(name); + const value: string | undefined = this.getAsString(name); void super.Section.update(name, value?.toLowerCase() === value1.toLowerCase() ? value2 : value1, getTarget()); } diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index dc6a1c199f..f367b93bfb 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -80,7 +80,7 @@ export function getExperimentationService(): Promise | } export async function isExperimentEnabled(experimentName: string): Promise { - if (new CppSettings().experimentalFeatures) { + if (new CppSettings().experimentalFeaturesEnabled) { return true; } const experimentationService: IExperimentationService | undefined = await getExperimentationService(); From 9bce0a4e2c6735e21c08e495e0d80c338766c757 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 26 Jun 2024 07:19:18 -0700 Subject: [PATCH 02/52] Add Enum Validation --- Extension/src/LanguageServer/settings.ts | 35 ++++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index aa77358478..d81c2f9e86 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -14,7 +14,7 @@ import { quote } from 'shell-quote'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as which from 'which'; -import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArrayOfString, isBoolean, isNumber, isString, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; +import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; import { clients } from './extension'; @@ -322,10 +322,10 @@ export class CppSettings extends Settings { // TODO: Persist the lowercasing of enum values. private getAsString(settingName: string): string { const value: any | undefined = super.Section.get(settingName); - if (isString(value)) { + if (this.isValidEnum(settingName, value)) { + return value; + } else if (isString(value)) { return value; - } else if (this.isValidEnum(settingName, value)) { - } const setting = getRawSetting("C_Cpp." + settingName); return setting.default; @@ -340,27 +340,38 @@ export class CppSettings extends Settings { return setting.default; } + // TODO: Add a boolean for enums that we don't want to validate. private getAsArrayOfStrings(settingName: string): string[] { + const setting = getRawSetting("C_Cpp." + settingName); const value: any | undefined | null = super.Section.get(settingName); + // TODO: Validate that the array is an array of enums before an array of strings. if (isArrayOfString(value)) { + if (setting.items.enum !== undefined){ + if (!value.every(x => this.validateEnum(setting.items.enum, x))){ + return setting.default; + } else { + return value; + } + } return value; } - const setting = getRawSetting("C_Cpp." + settingName); return setting.default; } private isValidEnum(settingName: string, value: any): boolean { const setting = getRawSetting("C_Cpp." + settingName); - for (let i: number = 0; i < setting.enum.length; i++) { - if (value.toLowerCase() == setting.enum[i]) { - return true; - } + if (this.validateEnum(setting.enum, value)){ + return value; } - return false; + return setting.default; } - // TODO: Create a isValidEnum(setting, value) function, use this function in getAsString to remove the getAsEnum function and a getAsEnumArray() to get the enumArray if it is there. Use C_Cpp.codeAnalysis.clangTidy.checks.enabled as a test case. - + private validateEnum(enumDescription: any, value: any){ + if (isArray(enumDescription) && enumDescription.length > 0){ + return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); + } + return false; + } public get maxConcurrentThreads(): number | undefined | null { return this.getAsNumber("maxConcurrentThreads"); From cd24fbfadd5c497961061c717718e89f859854f6 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 26 Jun 2024 11:53:18 -0700 Subject: [PATCH 03/52] Reformat settings and add ToLowerCase to enum values --- Extension/src/LanguageServer/settings.ts | 399 +++++------------------ 1 file changed, 86 insertions(+), 313 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index d81c2f9e86..51ba4282c3 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -318,12 +318,10 @@ export class CppSettings extends Settings { return setting.default; } - // TODO: Determine the behavior of settings that don't have default values set. Generally, they should return undefined. - // TODO: Persist the lowercasing of enum values. private getAsString(settingName: string): string { const value: any | undefined = super.Section.get(settingName); if (this.isValidEnum(settingName, value)) { - return value; + return value.toLowerCase(); // Return enum values in lowercase. } else if (isString(value)) { return value; } @@ -340,11 +338,9 @@ export class CppSettings extends Settings { return setting.default; } - // TODO: Add a boolean for enums that we don't want to validate. private getAsArrayOfStrings(settingName: string): string[] { const setting = getRawSetting("C_Cpp." + settingName); const value: any | undefined | null = super.Section.get(settingName); - // TODO: Validate that the array is an array of enums before an array of strings. if (isArrayOfString(value)) { if (setting.items.enum !== undefined){ if (!value.every(x => this.validateEnum(setting.items.enum, x))){ @@ -373,313 +369,92 @@ export class CppSettings extends Settings { return false; } - public get maxConcurrentThreads(): number | undefined | null { - return this.getAsNumber("maxConcurrentThreads"); - } - - public get maxMemory(): number | undefined | null { - return this.getAsNumber("maxMemory"); - } - - public get maxSymbolSearchResults(): number | undefined { - return this.getAsNumber("maxSymbolSearchResults"); - } - - public get maxCachedProcesses(): number | undefined | null { - return this.getAsNumber("maxCachedProcesses"); - } - - public get intelliSenseMaxCachedProcesses(): number | undefined | null { - return this.getAsNumber("intelliSense.maxCachedProcesses"); - } - - public get intelliSenseMaxMemory(): number | undefined | null { - return this.getAsNumber("intelliSense.maxMemory"); - } - - public get referencesMaxConcurrentThreads(): number | undefined | null { - return this.getAsNumber("references.maxConcurrentThreads"); - } - - public get referencesMaxCachedProcesses(): number | undefined | null { - return this.getAsNumber("references.maxCachedProcesses"); - } - - public get referencesMaxMemory(): number | undefined | null { - return this.getAsNumber("references.maxMemory"); - } - - public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { - return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); - } - - public get codeAnalysisMaxMemory(): number | undefined | null { - return this.getAsNumber("codeAnalysis.maxMemory"); - } - - public get codeAnalysisUpdateDelay(): number | undefined { - return this.getAsNumber("codeAnalysis.updateDelay"); - } - - public get codeAnalysisExclude(): vscode.WorkspaceConfiguration | undefined { - const value = super.Section.get("codeAnalysis.exclude"); - console.log(value); - console.log(value?.key); - return typeof value?.key === "string" ? value : undefined; - } - - public get codeAnalysisRunAutomatically(): boolean | undefined { - return this.getAsBoolean("codeAnalysis.runAutomatically"); - } - - public get codeAnalysisRunOnBuild(): boolean | undefined { - return this.getAsBoolean("codeAnalysis.runOnBuild"); - } - - public get clangTidyEnabled(): boolean | undefined { - return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); - } - - public get clangTidyConfig(): string | undefined { - return this.getAsString("codeAnalysis.clangTidy.config"); - } - - public get clangTidyFallbackConfig(): string | undefined { - return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); - } - - public get clangTidyHeaderFilter(): string | undefined | null { - return this.getAsString("codeAnalysis.clangTidy.headerFilter"); - } - - public get clangTidyArgs(): string[] | undefined { - return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); - } - - public get clangTidyUseBuildPath(): boolean | undefined { - return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); - } - - public get clangTidyChecksEnabled(): string[] | undefined { - return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled"); - } - - public get clangTidyChecksDisabled(): string[] | undefined { - return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled"); - } - - public get clangTidyCodeActionShowDisable(): boolean | undefined { - return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); - } - - public get clangTidyCodeActionShowClear(): string { - return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); - } - public get clangTidyCodeActionShowDocumentation(): boolean | undefined { - return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); - } - - public get clangTidyCodeActionFormatFixes(): boolean { - return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; - } - - // TODO - public addClangTidyChecksDisabled(value: string): void { - const checks: string[] | undefined = this.clangTidyChecksDisabled; - if (checks === undefined) { - return; - } - checks.push(value); - void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); - } - - public get clangFormatStyle(): string | undefined { - return this.getAsString("clang_format_style"); - } - - public get clangFormatFallbackStyle(): string | undefined { - return this.getAsString("clang_format_fallbackStyle"); - } - - public get clangFormatSortIncludes(): boolean | undefined | null { - return this.getAsBoolean("clang_format_sortIncludes"); - } - - // TODO: Refactor experimentalFeatures to experimentalFeaturesEnabled which is a boolean value in packagae.json. - public get experimentalFeaturesEnabled(): boolean | undefined { - return this.getAsBoolean("experimentalFeatures.enabled"); - } - - public get suggestSnippets(): boolean | undefined { - return this.getAsBoolean("suggestSnippets"); - } - - public get intelliSenseEngine(): string | undefined { - return this.getAsString("intelliSenseEngine"); - } - - public get intelliSenseEngineFallbackEnabled(): boolean | undefined { - return this.getAsBoolean("intelliSenseEngineFallback.enabled"); - } - - public get intelliSenseCachePath(): string | undefined { - return this.getAsString("intelliSenseEngine"); - } - - public get intelliSenseCacheSize(): number | undefined { - return this.getAsNumber("intelliSenseCachePath"); - } - - public get intelliSenseMemoryLimit(): number | undefined { - return this.getAsNumber("intelliSenseMemoryLimit"); - } - - public get intelliSenseUpdateDelay(): number | undefined { - return this.getAsNumber("intelliSenseUpdateDelay"); - } - - public get errorSquiggles(): string | undefined { - return this.getAsString("errorSquiggles"); - } - - public get inactiveRegionOpacity(): number | undefined { - return this.getAsNumber("inactiveRegionOpacity"); - - } - - public get inactiveRegionForegroundColor(): string | undefined { - return this.getAsString("inactiveRegionForegroundColor"); - } - - public get inactiveRegionBackgroundColor(): string | undefined { - return this.getAsString("inactiveRegionBackgroundColor"); - } - - public get autocomplete(): string | undefined { - return this.getAsString("autocomplete"); - } - - public get autocompleteAddParentheses(): boolean | undefined { - return this.getAsBoolean("autocompleteAddParentheses"); - } - - public get loggingLevel(): string | undefined { - return this.getAsString("loggingLevel"); - } - - public get autoAddFileAssociations(): boolean | undefined { - return this.getAsBoolean("autoAddFileAssociations"); - } - - public get workspaceParsingPriority(): string | undefined { - return this.getAsString("workspaceParsingPriority"); - } - - public get workspaceSymbols(): string | undefined { - return this.getAsString("workspaceSymbols"); - } - - public get exclusionPolicy(): string | undefined { - return this.getAsString("exclusionPolicy"); - } - - public get refactoringIncludeHeader(): string | undefined { - return this.getAsString("refactoring.includeHeader"); - } - - public get simplifyStructuredComments(): boolean | undefined { - return this.getAsBoolean("simplifyStructuredComments"); - - } - - public get doxygenGeneratedCommentStyle(): string | undefined { - return this.getAsString("doxygen.generatedStyle"); - } - - public get doxygenGenerateOnType(): boolean | undefined { - return this.getAsBoolean("doxygen.generateOnType"); - } - /* TODO Use*/ - public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { - const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); - if (Array.isArray(value)) { - return value; - } - return undefined; - } - - public get configurationWarningsEnabled(): boolean | undefined { - return this.getAsBoolean("configurationWarnings.enabled"); - } - - public get preferredPathSeparator(): string | undefined { - return this.getAsString("preferredPathSeparator"); - } - - public get updateChannel(): string | undefined { - return this.getAsString("updateChannel"); - } - - public get vcpkgEnabled(): boolean | undefined { - return this.getAsBoolean("vcpkg.enabled"); - } - - public get addNodeAddonIncludePaths(): boolean | undefined { - return this.getAsBoolean("addNodeAddonIncludePaths"); - } - - public get renameRequiresIdentifier(): boolean | undefined { - return this.getAsBoolean("renameRequiresIdentifier"); - } - - // TODO - public get filesExclude(): vscode.WorkspaceConfiguration | undefined { + public get maxConcurrentThreads(): number | undefined | null { return this.getAsNumber("maxConcurrentThreads"); } + public get maxMemory(): number | undefined | null { return this.getAsNumber("maxMemory"); } + public get maxSymbolSearchResults(): number | undefined { return this.getAsNumber("maxSymbolSearchResults"); } + public get maxCachedProcesses(): number | undefined | null { return this.getAsNumber("maxCachedProcesses"); } + public get intelliSenseMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("intelliSense.maxCachedProcesses"); } + public get intelliSenseMaxMemory(): number | undefined | null { return this.getAsNumber("intelliSense.maxMemory"); } + public get referencesMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("references.maxConcurrentThreads"); } + public get referencesMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("references.maxCachedProcesses"); } + public get referencesMaxMemory(): number | undefined | null { return this.getAsNumber("references.maxMemory"); } + public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } + public get codeAnalysisMaxMemory(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxMemory"); } + public get codeAnalysisUpdateDelay(): number | undefined { return this.getAsNumber("codeAnalysis.updateDelay"); } + public get codeAnalysisExclude(): vscode.WorkspaceConfiguration | undefined { + const value = super.Section.get("codeAnalysis.exclude"); + console.log(value); console.log(value?.key); + return typeof value?.key === "string" ? value : undefined; + } + public get codeAnalysisRunAutomatically(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runAutomatically"); } + public get codeAnalysisRunOnBuild(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runOnBuild"); } + public get clangTidyEnabled(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } + public get clangTidyConfig(): string | undefined { return this.getAsString("codeAnalysis.clangTidy.config"); } + public get clangTidyFallbackConfig(): string | undefined { return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); } + public get clangTidyHeaderFilter(): string | undefined | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter"); } + public get clangTidyArgs(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } + public get clangTidyUseBuildPath(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } + public get clangTidyChecksEnabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled"); } + public get clangTidyChecksDisabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled"); } + public get clangTidyCodeActionShowDisable(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); } + public get clangTidyCodeActionShowClear(): string { return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); } + public get clangTidyCodeActionShowDocumentation(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); } + public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; } + public addClangTidyChecksDisabled(value: string): void { + const checks: string[] | undefined = this.clangTidyChecksDisabled; + if (checks === undefined) { return; } checks.push(value); + void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); + } + public get clangFormatStyle(): string | undefined { return this.getAsString("clang_format_style"); } + public get clangFormatFallbackStyle(): string | undefined { return this.getAsString("clang_format_fallbackStyle"); } + public get clangFormatSortIncludes(): boolean | undefined | null { return this.getAsBoolean("clang_format_sortIncludes"); } + public get experimentalFeaturesEnabled(): boolean | undefined { return this.getAsBoolean("experimentalFeatures.enabled"); } + public get suggestSnippets(): boolean | undefined { return this.getAsBoolean("suggestSnippets"); } + public get intelliSenseEngine(): string | undefined { return this.getAsString("intelliSenseEngine"); } + public get intelliSenseEngineFallbackEnabled(): boolean | undefined { return this.getAsBoolean("intelliSenseEngineFallback.enabled"); } + public get intelliSenseCachePath(): string | undefined { return this.getAsString("intelliSenseEngine"); } + public get intelliSenseCacheSize(): number | undefined { return this.getAsNumber("intelliSenseCachePath"); } + public get intelliSenseMemoryLimit(): number | undefined { return this.getAsNumber("intelliSenseMemoryLimit"); } + public get intelliSenseUpdateDelay(): number | undefined { return this.getAsNumber("intelliSenseUpdateDelay"); } + public get errorSquiggles(): string | undefined { return this.getAsString("errorSquiggles"); } + public get inactiveRegionOpacity(): number | undefined { return this.getAsNumber("inactiveRegionOpacity"); } + public get inactiveRegionForegroundColor(): string | undefined { return this.getAsString("inactiveRegionForegroundColor"); } + public get inactiveRegionBackgroundColor(): string | undefined { return this.getAsString("inactiveRegionBackgroundColor"); } + public get autocomplete(): string | undefined { return this.getAsString("autocomplete"); } + public get autocompleteAddParentheses(): boolean | undefined { return this.getAsBoolean("autocompleteAddParentheses"); } + public get loggingLevel(): string | undefined { return this.getAsString("loggingLevel"); } + public get autoAddFileAssociations(): boolean | undefined { return this.getAsBoolean("autoAddFileAssociations"); } + public get workspaceParsingPriority(): string | undefined { return this.getAsString("workspaceParsingPriority"); } + public get workspaceSymbols(): string | undefined { return this.getAsString("workspaceSymbols"); } + public get exclusionPolicy(): string | undefined { return this.getAsString("exclusionPolicy"); } + public get refactoringIncludeHeader(): string | undefined { return this.getAsString("refactoring.includeHeader"); } + public get simplifyStructuredComments(): boolean | undefined { return this.getAsBoolean("simplifyStructuredComments"); } + public get doxygenGeneratedCommentStyle(): string | undefined { return this.getAsString("doxygen.generatedStyle"); } + public get doxygenGenerateOnType(): boolean | undefined { return this.getAsBoolean("doxygen.generateOnType"); } + public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { + const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); + if (Array.isArray(value)) { return value; } return undefined; + } + public get configurationWarningsEnabled(): boolean | undefined { return this.getAsBoolean("configurationWarnings.enabled"); } + public get preferredPathSeparator(): string | undefined { return this.getAsString("preferredPathSeparator"); } + public get updateChannel(): string | undefined { return this.getAsString("updateChannel"); } + public get vcpkgEnabled(): boolean | undefined { return this.getAsBoolean("vcpkg.enabled"); } + public get addNodeAddonIncludePaths(): boolean | undefined { return this.getAsBoolean("addNodeAddonIncludePaths"); } + public get renameRequiresIdentifier(): boolean | undefined { return this.getAsBoolean("renameRequiresIdentifier"); } + public get filesExclude(): vscode.WorkspaceConfiguration | undefined { const value = super.Section.get("files.exclude"); - if (value) { - return value; - } - return undefined; - } - - public get defaultIncludePath(): string[] | undefined { - return this.getAsArrayOfStrings("default.includePath"); - } - - public get defaultDefines(): string[] | undefined { - return this.getAsArrayOfStrings("default.defines"); - } - - public get defaultDotconfig(): string | undefined { - return this.getAsString("default.dotConfig"); - } - - public get defaultMacFrameworkPath(): string[] | undefined { - return this.getAsArrayOfStrings("default.macFrameworkPath"); - } - - public get defaultWindowsSdkVersion(): string | undefined { - return this.getAsString("default.windowsSdkVersion"); - } - - public get defaultCompileCommands(): string | undefined { - return this.getAsString("default.compileCommands"); - } - - public get defaultForcedInclude(): string[] | undefined { - return this.getAsArrayOfStrings("default.forcedInclude"); - } - - public get defaultIntelliSenseMode(): string | undefined { - const value = this.getAsString("default.intelliSenseMode"); - if (value) { - return value; - } - return undefined; - } - - public get defaultCompilerPath(): string | undefined { - return this.getAsString("default.compilerPath") ?? undefined; + console.log(value?.Object); if (value) { return value; } + return undefined; } + public get defaultIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.includePath"); } + public get defaultDefines(): string[] | undefined { return this.getAsArrayOfStrings("default.defines"); } + public get defaultDotconfig(): string | undefined { return this.getAsString("default.dotConfig"); } + public get defaultMacFrameworkPath(): string[] | undefined { return this.getAsArrayOfStrings("default.macFrameworkPath"); } + public get defaultWindowsSdkVersion(): string | undefined { return this.getAsString("default.windowsSdkVersion"); } + public get defaultCompileCommands(): string | undefined { return this.getAsString("default.compileCommands"); } + public get defaultForcedInclude(): string[] | undefined { return this.getAsArrayOfStrings("default.forcedInclude"); } + public get defaultIntelliSenseMode(): string | undefined { return this.getAsString("default.intelliSenseMode"); } + public get defaultCompilerPath(): string | undefined { return this.getAsString("default.compilerPath") ?? undefined; } public set defaultCompilerPath(value: string | undefined) { @@ -715,9 +490,7 @@ export class CppSettings extends Settings { // TODO Ask Sean about validating this setting. public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined { return super.Section.get<{ [key: string]: string }>("default.customConfigurationVariables"); } public get useBacktickCommandSubstitution(): boolean | undefined { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } - public get codeFoldingEnabled(): boolean { - return this.getAsBoolean("codeFolding.enabled"); - } + public get codeFoldingEnabled(): boolean {return this.getAsBoolean("codeFolding.enabled"); } public get caseSensitiveFileSupport(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } public get doxygenSectionTags(): string[] | undefined { return this.getAsArrayOfStrings("doxygen.sectionTags"); } public get hover(): string | undefined { return this.getAsString("hover"); } From dafb549c2330245bbd5bc8682a32c7e37da5404c Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 26 Jun 2024 15:12:13 -0700 Subject: [PATCH 04/52] Revert package.json changes and add Object type validation. --- Extension/package.json | 45 ++++++++++++++++-------- Extension/src/LanguageServer/settings.ts | 36 ++++++++++++++----- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index d97d15fa22..f978613e3a 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -530,9 +530,13 @@ "minimum": 500, "maximum": 3000 }, - "C_Cpp.codeFolding.enabled": { - "type": "boolean", - "default": false, + "C_Cpp.codeFolding": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "default": "enabled", "description": "%c_cpp.configuration.codeFolding.description%", "scope": "window" }, @@ -548,9 +552,13 @@ "markdownDescription": "%c_cpp.configuration.suggestSnippets.markdownDescription%", "scope": "resource" }, - "C_Cpp.enhancedColorization.enabled": { - "type": "boolean", - "default": false, + "C_Cpp.enhancedColorization": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "default": "enabled", "markdownDescription": "%c_cpp.configuration.enhancedColorization.markdownDescription%", "scope": "window" }, @@ -691,7 +699,6 @@ }, "C_Cpp.default.forcedInclude": { "type": "array", - "default": "undefined", "items": { "type": "string" }, @@ -870,9 +877,13 @@ "markdownDescription": "%c_cpp.configuration.default.dotConfig.markdownDescription%", "scope": "resource" }, - "C_Cpp.configurationWarnings.enabled": { - "type": "boolean", - "default": false, + "C_Cpp.configurationWarnings": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "default": "enabled", "description": "%c_cpp.configuration.configurationWarnings.description%", "scope": "resource" }, @@ -904,9 +915,13 @@ ], "scope": "resource" }, - "C_Cpp.intelliSenseEngineFallback.enabled": { - "type": "boolean", - "default": false, + "C_Cpp.intelliSenseEngineFallback": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "default": "disabled", "markdownDescription": "%c_cpp.configuration.intelliSenseEngineFallback.markdownDescription%", "scope": "resource" }, @@ -3177,7 +3192,7 @@ "null" ], "markdownDescription": "%c_cpp.configuration.intelliSense.maxCachedProcesses.markdownDescription%", - "default": 128, + "default": null, "minimum": 2, "maximum": 128, "scope": "machine" @@ -3188,7 +3203,7 @@ "null" ], "markdownDescription": "%c_cpp.configuration.intelliSense.maxMemory.markdownDescription%", - "default": 65536, + "default": null, "minimum": 256, "maximum": 65536, "scope": "machine" diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 51ba4282c3..5a390bccee 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -25,7 +25,7 @@ nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFo const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export interface Excludes { - [key: string]: boolean | { when: string }; + [key: string]: (boolean | { when: string }); } export interface WorkspaceFolderSettingsParams { @@ -381,10 +381,15 @@ export class CppSettings extends Settings { public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } public get codeAnalysisMaxMemory(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxMemory"); } public get codeAnalysisUpdateDelay(): number | undefined { return this.getAsNumber("codeAnalysis.updateDelay"); } - public get codeAnalysisExclude(): vscode.WorkspaceConfiguration | undefined { - const value = super.Section.get("codeAnalysis.exclude"); - console.log(value); console.log(value?.key); - return typeof value?.key === "string" ? value : undefined; + public get codeAnalysisExclude(): Excludes | undefined { + let value = super.Section.get("codeAnalysis.exclude"); + if (value === undefined) { return undefined; } + for (let key of Object.keys(value)) { + if (typeof key === "string" && typeof value[key] === "boolean") { + return value; + } + } + return undefined; } public get codeAnalysisRunAutomatically(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runAutomatically"); } public get codeAnalysisRunOnBuild(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runOnBuild"); } @@ -443,8 +448,13 @@ export class CppSettings extends Settings { public get renameRequiresIdentifier(): boolean | undefined { return this.getAsBoolean("renameRequiresIdentifier"); } public get filesExclude(): vscode.WorkspaceConfiguration | undefined { const value = super.Section.get("files.exclude"); - console.log(value?.Object); if (value) { return value; } - return undefined; + if (value === undefined) { return undefined; } + for (let key of Object.keys(value)) { + if (typeof key === "string" && typeof value[key] === "boolean") { + return value; + } + } + return undefined; } public get defaultIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.includePath"); } public get defaultDefines(): string[] | undefined { return this.getAsArrayOfStrings("default.defines"); } @@ -487,8 +497,16 @@ export class CppSettings extends Settings { public get defaultLimitSymbolsToIncludedHeaders(): boolean | undefined { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } public get defaultSystemIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean | undefined { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - // TODO Ask Sean about validating this setting. - public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined { return super.Section.get<{ [key: string]: string }>("default.customConfigurationVariables"); } + public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined { + const value = super.Section.get<{ [key: string]: string }>("default.customConfigurationVariables"); + if (value === undefined) { return undefined; } + for (let key of Object.keys(value)) { + if (typeof key === "string" && typeof value[key] === "string") { + return value; + } + } + return undefined; + } public get useBacktickCommandSubstitution(): boolean | undefined { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } public get codeFoldingEnabled(): boolean {return this.getAsBoolean("codeFolding.enabled"); } public get caseSensitiveFileSupport(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } From cf9d1fc354836885a46c269a2195d2f888f8fb74 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 8 Jul 2024 14:33:59 -0700 Subject: [PATCH 05/52] Refactor settings to account for min/max values and handle vs code standard settings + minor fixes --- .../Providers/foldingRangeProvider.ts | 2 +- Extension/src/LanguageServer/client.ts | 14 +- Extension/src/LanguageServer/settings.ts | 471 ++++++------------ Extension/src/telemetry.ts | 2 +- 4 files changed, 173 insertions(+), 316 deletions(-) diff --git a/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts b/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts index 3498285f07..be2a571aa5 100644 --- a/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts +++ b/Extension/src/LanguageServer/Providers/foldingRangeProvider.ts @@ -27,7 +27,7 @@ export class FoldingRangeProvider implements vscode.FoldingRangeProvider { async provideFoldingRanges(document: vscode.TextDocument, context: vscode.FoldingContext, token: vscode.CancellationToken): Promise { await this.client.ready; const settings: CppSettings = new CppSettings(); - if (!settings.codeFoldingEnabled) { + if (!settings.codeFolding) { return []; } diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index ad473c7c65..4aee62c41c 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1272,7 +1272,7 @@ export class DefaultClient implements Client { this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, this.codeFoldingProvider); const settings: CppSettings = new CppSettings(); - if (settings.enhancedColorizationEnabled && semanticTokensLegend) { + if (settings.enhancedColorization && semanticTokensLegend) { this.semanticTokensProvider = new SemanticTokensProvider(); this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend); } @@ -1322,7 +1322,7 @@ export class DefaultClient implements Client { const result: WorkspaceFolderSettingsParams = { uri: workspaceFolderUri?.toString(), intelliSenseEngine: settings.intelliSenseEngine, - intelliSenseEngineFallback: settings.intelliSenseEngineFallbackEnabled, + intelliSenseEngineFallback: settings.intelliSenseEngineFallback, autocomplete: settings.autocomplete, autocompleteAddParentheses: settings.autocompleteAddParentheses, errorSquiggles: settings.errorSquiggles, @@ -1457,8 +1457,8 @@ export class DefaultClient implements Client { workspaceSymbols: workspaceSettings.workspaceSymbols, simplifyStructuredComments: workspaceSettings.simplifyStructuredComments, intelliSenseUpdateDelay: workspaceSettings.intelliSenseUpdateDelay, - experimentalFeaturesEnabled: workspaceSettings.experimentalFeaturesEnabled, - enhancedColorizationEnabled: workspaceSettings.enhancedColorizationEnabled, + experimentalFeatures: workspaceSettings.experimentalFeatures, + enhancedColorization: workspaceSettings.enhancedColorization, intellisenseMaxCachedProcesses: workspaceSettings.intelliSenseMaxCachedProcesses, intellisenseMaxMemory: workspaceSettings.intelliSenseMaxMemory, referencesMaxConcurrentThreads: workspaceSettings.referencesMaxConcurrentThreads, @@ -1630,7 +1630,7 @@ export class DefaultClient implements Client { } const settings: CppSettings = new CppSettings(); if (changedSettings.enhancedColorization) { - if (settings.enhancedColorizationEnabled && semanticTokensLegend) { + if (settings.enhancedColorization && semanticTokensLegend) { this.semanticTokensProvider = new SemanticTokensProvider(); this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend); } else if (this.semanticTokensProviderDisposable) { @@ -2096,7 +2096,7 @@ export class DefaultClient implements Client { result = "timeout"; if (!requestFile) { const settings: CppSettings = new CppSettings(this.RootUri); - if (settings.configurationWarningsEnabled && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) { + if (settings.configurationWarnings && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) { const dismiss: string = localize("dismiss.button", "Dismiss"); const disable: string = localize("disable.warnings.button", "Disable Warnings"); const configName: string | undefined = this.configuration.CurrentConfiguration?.name; @@ -2166,7 +2166,7 @@ export class DefaultClient implements Client { public getVcpkgEnabled(): Promise { const cppSettings: CppSettings = new CppSettings(this.RootUri); - return Promise.resolve(!!cppSettings.vcpkgEnabled); + return Promise.resolve(!!cppSettings.vcpkg); } public async getKnownCompilers(): Promise { diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 5a390bccee..63f592e5c0 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -145,8 +145,8 @@ export interface SettingsParams { workspaceSymbols: string | undefined; simplifyStructuredComments: boolean | undefined; intelliSenseUpdateDelay: number | undefined; - experimentalFeaturesEnabled: boolean | undefined; - enhancedColorizationEnabled: boolean | undefined; + experimentalFeatures: boolean | undefined; + enhancedColorization: boolean | undefined; intellisenseMaxCachedProcesses: number | null | undefined; intellisenseMaxMemory: number | null | undefined; referencesMaxConcurrentThreads: number | null | undefined; @@ -331,10 +331,12 @@ export class CppSettings extends Settings { private getAsNumber(settingName: string): number { const value: any | undefined | null = super.Section.get(settingName); - if (isNumber(value)) { + const setting = getRawSetting("C_Cpp." + settingName); + + if (isNumber(value) && (value >= setting.minimum && value <= setting.maximum)) { return value; } - const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; } @@ -342,8 +344,8 @@ export class CppSettings extends Settings { const setting = getRawSetting("C_Cpp." + settingName); const value: any | undefined | null = super.Section.get(settingName); if (isArrayOfString(value)) { - if (setting.items.enum !== undefined){ - if (!value.every(x => this.validateEnum(setting.items.enum, x))){ + if (setting.items.enum !== undefined) { + if (!value.every(x => this.validateEnum(setting.items.enum, x))) { return setting.default; } else { return value; @@ -354,43 +356,67 @@ export class CppSettings extends Settings { return setting.default; } + private getAsKeyValueObject(settingName: string, keyType: string, valueType: string): any { + const setting = getRawSetting("C_Cpp." + settingName); + const value: any = super.Section.get(settingName); + if (this.isValidMapping(value, keyType, valueType)) { + return value; + } + return setting.default; + } + private isValidEnum(settingName: string, value: any): boolean { const setting = getRawSetting("C_Cpp." + settingName); - if (this.validateEnum(setting.enum, value)){ + if (this.validateEnum(setting.enum, value)) { return value; } return setting.default; } - private validateEnum(enumDescription: any, value: any){ - if (isArray(enumDescription) && enumDescription.length > 0){ + private isValidMapping(value: any, keyType: string, valueType: string): boolean { + if (value === undefined || value === null) { return false; } + for (const key of Object.keys(value)) { + if (typeof key !== keyType && typeof value[key] !== valueType) { + return false; + } + } + return true; + } + + private validateEnum(enumDescription: any, value: any) { + if (isArray(enumDescription) && enumDescription.length > 0) { return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); } return false; } - public get maxConcurrentThreads(): number | undefined | null { return this.getAsNumber("maxConcurrentThreads"); } - public get maxMemory(): number | undefined | null { return this.getAsNumber("maxMemory"); } - public get maxSymbolSearchResults(): number | undefined { return this.getAsNumber("maxSymbolSearchResults"); } - public get maxCachedProcesses(): number | undefined | null { return this.getAsNumber("maxCachedProcesses"); } - public get intelliSenseMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("intelliSense.maxCachedProcesses"); } - public get intelliSenseMaxMemory(): number | undefined | null { return this.getAsNumber("intelliSense.maxMemory"); } - public get referencesMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("references.maxConcurrentThreads"); } + public get maxConcurrentThreads(): number | undefined | null { + return this.getAsNumber("maxConcurrentThreads"); + } + public get maxMemory(): number | undefined | null { + return this.getAsNumber("maxMemory"); + } + public get maxSymbolSearchResults(): number | undefined { + return this.getAsNumber("maxSymbolSearchResults"); + } + public get maxCachedProcesses(): number | undefined | null { + return this.getAsNumber("maxCachedProcesses"); + } + public get intelliSenseMaxCachedProcesses(): number | undefined | null { + return this.getAsNumber("intelliSense.maxCachedProcesses"); + } + public get intelliSenseMaxMemory(): number | undefined | null { + return this.getAsNumber("intelliSense.maxMemory"); + } + public get referencesMaxConcurrentThreads(): number | undefined | null { + return this.getAsNumber("references.maxConcurrentThreads"); + } public get referencesMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("references.maxCachedProcesses"); } public get referencesMaxMemory(): number | undefined | null { return this.getAsNumber("references.maxMemory"); } public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } public get codeAnalysisMaxMemory(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxMemory"); } public get codeAnalysisUpdateDelay(): number | undefined { return this.getAsNumber("codeAnalysis.updateDelay"); } - public get codeAnalysisExclude(): Excludes | undefined { - let value = super.Section.get("codeAnalysis.exclude"); - if (value === undefined) { return undefined; } - for (let key of Object.keys(value)) { - if (typeof key === "string" && typeof value[key] === "boolean") { - return value; - } - } - return undefined; - } + public get codeAnalysisExclude(): Excludes | undefined { return this.getAsKeyValueObject("codeAnalysis.exclude", "string", "boolean"); } public get codeAnalysisRunAutomatically(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runAutomatically"); } public get codeAnalysisRunOnBuild(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runOnBuild"); } public get clangTidyEnabled(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } @@ -405,18 +431,18 @@ export class CppSettings extends Settings { public get clangTidyCodeActionShowClear(): string { return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); } public get clangTidyCodeActionShowDocumentation(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); } public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; } - public addClangTidyChecksDisabled(value: string): void { - const checks: string[] | undefined = this.clangTidyChecksDisabled; - if (checks === undefined) { return; } checks.push(value); - void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); + public addClangTidyChecksDisabled(value: string): void { + const checks: string[] | undefined = this.clangTidyChecksDisabled; + if (checks === undefined) { return; } checks.push(value); + void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } public get clangFormatStyle(): string | undefined { return this.getAsString("clang_format_style"); } public get clangFormatFallbackStyle(): string | undefined { return this.getAsString("clang_format_fallbackStyle"); } public get clangFormatSortIncludes(): boolean | undefined | null { return this.getAsBoolean("clang_format_sortIncludes"); } - public get experimentalFeaturesEnabled(): boolean | undefined { return this.getAsBoolean("experimentalFeatures.enabled"); } + public get experimentalFeatures(): boolean | undefined { return this.getAsString("experimentalFeatures") === "enabled"; } public get suggestSnippets(): boolean | undefined { return this.getAsBoolean("suggestSnippets"); } public get intelliSenseEngine(): string | undefined { return this.getAsString("intelliSenseEngine"); } - public get intelliSenseEngineFallbackEnabled(): boolean | undefined { return this.getAsBoolean("intelliSenseEngineFallback.enabled"); } + public get intelliSenseEngineFallback(): boolean | undefined { return this.getAsString("intelliSenseEngineFallback") === "enabled"; } public get intelliSenseCachePath(): string | undefined { return this.getAsString("intelliSenseEngine"); } public get intelliSenseCacheSize(): number | undefined { return this.getAsNumber("intelliSenseCachePath"); } public get intelliSenseMemoryLimit(): number | undefined { return this.getAsNumber("intelliSenseMemoryLimit"); } @@ -436,26 +462,26 @@ export class CppSettings extends Settings { public get simplifyStructuredComments(): boolean | undefined { return this.getAsBoolean("simplifyStructuredComments"); } public get doxygenGeneratedCommentStyle(): string | undefined { return this.getAsString("doxygen.generatedStyle"); } public get doxygenGenerateOnType(): boolean | undefined { return this.getAsBoolean("doxygen.generateOnType"); } - public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { - const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); - if (Array.isArray(value)) { return value; } return undefined; + public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { + // eslint-disable-next-line no-extra-parens + const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); + if (value === undefined) { return undefined; } + if (isArrayOfString(value)) { + return value; + } + + if (value.every(x => typeof x === "object" && typeof x.begin === "string" && typeof x.continue === "string")) { + return value; + } + return undefined; } - public get configurationWarningsEnabled(): boolean | undefined { return this.getAsBoolean("configurationWarnings.enabled"); } + public get configurationWarnings(): boolean | undefined { return this.getAsString("configurationWarnings") === "enabled"; } public get preferredPathSeparator(): string | undefined { return this.getAsString("preferredPathSeparator"); } public get updateChannel(): string | undefined { return this.getAsString("updateChannel"); } - public get vcpkgEnabled(): boolean | undefined { return this.getAsBoolean("vcpkg.enabled"); } + public get vcpkg(): boolean | undefined { return this.getAsString("vcpkg") === "enabled"; } public get addNodeAddonIncludePaths(): boolean | undefined { return this.getAsBoolean("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean | undefined { return this.getAsBoolean("renameRequiresIdentifier"); } - public get filesExclude(): vscode.WorkspaceConfiguration | undefined { - const value = super.Section.get("files.exclude"); - if (value === undefined) { return undefined; } - for (let key of Object.keys(value)) { - if (typeof key === "string" && typeof value[key] === "boolean") { - return value; - } - } - return undefined; - } + public get filesExclude(): Excludes | undefined {return this.getAsKeyValueObject("files.exclude", "string", "boolean");} public get defaultIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.includePath"); } public get defaultDefines(): string[] | undefined { return this.getAsArrayOfStrings("default.defines"); } public get defaultDotconfig(): string | undefined { return this.getAsString("default.dotConfig"); } @@ -466,7 +492,6 @@ export class CppSettings extends Settings { public get defaultIntelliSenseMode(): string | undefined { return this.getAsString("default.intelliSenseMode"); } public get defaultCompilerPath(): string | undefined { return this.getAsString("default.compilerPath") ?? undefined; } - public set defaultCompilerPath(value: string | undefined) { const defaultCompilerPathStr: string = "default.compilerPath"; const compilerPathInfo: any = this.Section.inspect(defaultCompilerPathStr); @@ -497,333 +522,144 @@ export class CppSettings extends Settings { public get defaultLimitSymbolsToIncludedHeaders(): boolean | undefined { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } public get defaultSystemIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean | undefined { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined { - const value = super.Section.get<{ [key: string]: string }>("default.customConfigurationVariables"); - if (value === undefined) { return undefined; } - for (let key of Object.keys(value)) { - if (typeof key === "string" && typeof value[key] === "string") { - return value; - } - } - return undefined; - } + public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined {return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string");} public get useBacktickCommandSubstitution(): boolean | undefined { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } - public get codeFoldingEnabled(): boolean {return this.getAsBoolean("codeFolding.enabled"); } + public get codeFolding(): boolean {return this.getAsString("codeFolding.enabled") === "enabled"; } public get caseSensitiveFileSupport(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } public get doxygenSectionTags(): string[] | undefined { return this.getAsArrayOfStrings("doxygen.sectionTags"); } public get hover(): string | undefined { return this.getAsString("hover"); } public get markdownInComments(): string | undefined { return this.getAsString("markdownInComments"); } public get legacyCompilerArgsBehavior(): boolean | undefined { return this.getAsBoolean("legacyCompilerArgsBehavior"); } - public get inlayHintsAutoDeclarationTypes(): boolean { - return this.getAsBoolean("inlayHints.autoDeclarationTypes.enabled"); - } - - public get inlayHintsAutoDeclarationTypesShowOnLeft(): boolean { - return this.getAsBoolean("inlayHints.autoDeclarationTypes.showOnLeft"); - } - - public get inlayHintsParameterNames(): boolean { - return this.getAsBoolean("inlayHints.parameterNames.enabled"); - } - - public get inlayHintsParameterNamesSuppressName(): boolean { - return this.getAsBoolean("inlayHints.parameterNames.suppressWhenArgumentContainsName"); - } - - public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean { - return this.getAsBoolean("inlayHints.parameterNames.hideLeadingUnderscores"); - } - - public get inlayHintsReferenceOperator(): boolean { - return this.getAsBoolean("inlayHints.referenceOperator.enabled"); - } - - public get inlayHintsReferenceOperatorShowSpace(): boolean { - return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); - } - - public get enhancedColorizationEnabled(): boolean { - return this.getAsBoolean("enhancedColorization") - && this.intelliSenseEngine === "default" - && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; - } - - public get formattingEngine(): string | undefined { - return this.getAsString("formatting")?.toLowerCase(); - } - - public get vcFormatIndentBraces(): boolean { - return this.getAsBoolean("vcFormat.indent.braces"); - } - + public get inlayHintsAutoDeclarationTypes(): boolean { return this.getAsBoolean("inlayHints.autoDeclarationTypes.enabled"); } + public get inlayHintsAutoDeclarationTypesShowOnLeft(): boolean { return this.getAsBoolean("inlayHints.autoDeclarationTypes.showOnLeft"); } + public get inlayHintsParameterNames(): boolean { return this.getAsBoolean("inlayHints.parameterNames.enabled"); } + public get inlayHintsParameterNamesSuppressName(): boolean { return this.getAsBoolean("inlayHints.parameterNames.suppressWhenArgumentContainsName"); } + public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean { return this.getAsBoolean("inlayHints.parameterNames.hideLeadingUnderscores"); } + public get inlayHintsReferenceOperator(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.enabled"); } + public get inlayHintsReferenceOperatorShowSpace(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); } + public get enhancedColorization(): boolean { return this.getAsString("enhancedColorization") === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } + public get formattingEngine(): string | undefined { return this.getAsString("formatting")?.toLowerCase(); } + public get vcFormatIndentBraces(): boolean { return this.getAsBoolean("vcFormat.indent.braces"); } public get vcFormatIndentMultiLineRelativeTo(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.indent.multiLineRelativeTo")!; } - public get vcFormatIndentWithinParentheses(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.indent.withinParentheses")!; } - - public get vcFormatIndentPreserveWithinParentheses(): boolean { - return this.getAsBoolean("vcFormat.indent.preserveWithinParentheses"); - } - - public get vcFormatIndentCaseLabels(): boolean { - return this.getAsBoolean("vcFormat.indent.caseLabels"); - } - - public get vcFormatIndentCaseContents(): boolean { - return this.getAsBoolean("vcFormat.indent.caseContents"); - } - - public get vcFormatIndentCaseContentsWhenBlock(): boolean { - return this.getAsBoolean("vcFormat.indent.caseContentsWhenBlock"); - } - - public get vcFormatIndentLambdaBracesWhenParameter(): boolean { - return this.getAsBoolean("vcFormat.indent.lambdaBracesWhenParameter"); - } - + public get vcFormatIndentPreserveWithinParentheses(): boolean { return this.getAsBoolean("vcFormat.indent.preserveWithinParentheses"); } + public get vcFormatIndentCaseLabels(): boolean { return this.getAsBoolean("vcFormat.indent.caseLabels"); } + public get vcFormatIndentCaseContents(): boolean { return this.getAsBoolean("vcFormat.indent.caseContents"); } + public get vcFormatIndentCaseContentsWhenBlock(): boolean { return this.getAsBoolean("vcFormat.indent.caseContentsWhenBlock"); } + public get vcFormatIndentLambdaBracesWhenParameter(): boolean { return this.getAsBoolean("vcFormat.indent.lambdaBracesWhenParameter"); } public get vcFormatIndentGotoLabels(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.indent.gotoLabels")!; } - public get vcFormatIndentPreprocessor(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.indent.preprocessor")!; } - - public get vcFormatIndentAccessSpecifiers(): boolean { - return this.getAsBoolean("vcFormat.indent.accessSpecifiers"); - } - - public get vcFormatIndentNamespaceContents(): boolean { - return this.getAsBoolean("vcFormat.indent.namespaceContents"); - } - - public get vcFormatIndentPreserveComments(): boolean { - return this.getAsBoolean("vcFormat.indent.preserveComments"); - } - + public get vcFormatIndentAccessSpecifiers(): boolean { return this.getAsBoolean("vcFormat.indent.accessSpecifiers"); } + public get vcFormatIndentNamespaceContents(): boolean { return this.getAsBoolean("vcFormat.indent.namespaceContents"); } + public get vcFormatIndentPreserveComments(): boolean { return this.getAsBoolean("vcFormat.indent.preserveComments"); } public get vcFormatNewlineBeforeOpenBraceNamespace(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.newLine.beforeOpenBrace.namespace")!; } - public get vcFormatNewlineBeforeOpenBraceType(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.newLine.beforeOpenBrace.type")!; } - public get vcFormatNewlineBeforeOpenBraceFunction(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.newLine.beforeOpenBrace.function")!; } - public get vcFormatNewlineBeforeOpenBraceBlock(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.newLine.beforeOpenBrace.block")!; } - public get vcFormatNewlineBeforeOpenBraceLambda(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.newLine.beforeOpenBrace.lambda")!; } - - public get vcFormatNewlineScopeBracesOnSeparateLines(): boolean { - return this.getAsBoolean("vcFormat.newLine.scopeBracesOnSeparateLines"); - } - - public get vcFormatNewlineCloseBraceSameLineEmptyType(): boolean { - return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyType"); - } - - public get vcFormatNewlineCloseBraceSameLineEmptyFunction(): boolean { - return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyFunction"); - } - - public get vcFormatNewlineBeforeCatch(): boolean { - return this.getAsBoolean("vcFormat.newLine.beforeCatch"); - } - - public get vcFormatNewlineBeforeElse(): boolean { - return this.getAsBoolean("vcFormat.newLine.beforeElse"); - } - - public get vcFormatNewlineBeforeWhileInDoWhile(): boolean { - return this.getAsBoolean("vcFormat.newLine.beforeWhileInDoWhile"); - } - + public get vcFormatNewlineScopeBracesOnSeparateLines(): boolean { return this.getAsBoolean("vcFormat.newLine.scopeBracesOnSeparateLines"); } + public get vcFormatNewlineCloseBraceSameLineEmptyType(): boolean { return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyType"); } + public get vcFormatNewlineCloseBraceSameLineEmptyFunction(): boolean { return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyFunction"); } + public get vcFormatNewlineBeforeCatch(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeCatch"); } + public get vcFormatNewlineBeforeElse(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeElse"); } + public get vcFormatNewlineBeforeWhileInDoWhile(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeWhileInDoWhile"); } public get vcFormatSpaceBeforeFunctionOpenParenthesis(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.space.beforeFunctionOpenParenthesis")!; } - - public get vcFormatSpaceWithinParameterListParentheses(): boolean { - return this.getAsBoolean("vcFormat.space.withinParameterListParentheses"); - } - - public get vcFormatSpaceBetweenEmptyParameterListParentheses(): boolean { - return this.getAsBoolean("vcFormat.space.betweenEmptyParameterListParentheses"); - } - - public get vcFormatSpaceAfterKeywordsInControlFlowStatements(): boolean { - return this.getAsBoolean("vcFormat.space.afterKeywordsInControlFlowStatements"); - } - - public get vcFormatSpaceWithinControlFlowStatementParentheses(): boolean { - return this.getAsBoolean("vcFormat.space.withinControlFlowStatementParentheses"); - } - - public get vcFormatSpaceBeforeLambdaOpenParenthesis(): boolean { - return this.getAsBoolean("vcFormat.space.beforeLambdaOpenParenthesis"); - } - - public get vcFormatSpaceWithinCastParentheses(): boolean { - return this.getAsBoolean("vcFormat.space.withinCastParentheses"); - } - - public get vcFormatSpaceAfterCastCloseParenthesis(): boolean { - return this.getAsBoolean("vcFormat.space.afterCastCloseParenthesis"); - } - - public get vcFormatSpaceWithinExpressionParentheses(): boolean { - return this.getAsBoolean("vcFormat.space.withinExpressionParentheses"); - } - - public get vcFormatSpaceBeforeBlockOpenBrace(): boolean { - return this.getAsBoolean("vcFormat.space.beforeBlockOpenBrace"); - } - - public get vcFormatSpaceBetweenEmptyBraces(): boolean { - return this.getAsBoolean("vcFormat.space.betweenEmptyBraces"); - } - - public get vcFormatSpaceBeforeInitializerListOpenBrace(): boolean { - return this.getAsBoolean("vcFormat.space.beforeInitializerListOpenBrace"); - } - - public get vcFormatSpaceWithinInitializerListBraces(): boolean { - return this.getAsBoolean("vcFormat.space.withinInitializerListBraces"); - } - - public get vcFormatSpacePreserveInInitializerList(): boolean { - return this.getAsBoolean("vcFormat.space.preserveInInitializerList"); - } - - public get vcFormatSpaceBeforeOpenSquareBracket(): boolean { - return this.getAsBoolean("vcFormat.space.beforeOpenSquareBracket"); - } - - public get vcFormatSpaceWithinSquareBrackets(): boolean { - return this.getAsBoolean("vcFormat.space.withinSquareBrackets"); - } - - public get vcFormatSpaceBeforeEmptySquareBrackets(): boolean { - return this.getAsBoolean("vcFormat.space.beforeEmptySquareBrackets"); - } - - public get vcFormatSpaceBetweenEmptySquareBrackets(): boolean { - return this.getAsBoolean("vcFormat.space.betweenEmptySquareBrackets"); - } - - public get vcFormatSpaceGroupSquareBrackets(): boolean { - return this.getAsBoolean("vcFormat.space.groupSquareBrackets"); - } - - public get vcFormatSpaceWithinLambdaBrackets(): boolean { - return this.getAsBoolean("vcFormat.space.withinLambdaBrackets"); - } - - public get vcFormatSpaceBetweenEmptyLambdaBrackets(): boolean { - return this.getAsBoolean("vcFormat.space.betweenEmptyLambdaBrackets"); - } - - public get vcFormatSpaceBeforeComma(): boolean { - return this.getAsBoolean("vcFormat.space.beforeComma"); - } - - public get vcFormatSpaceAfterComma(): boolean { - return this.getAsBoolean("vcFormat.space.afterComma"); - } - - public get vcFormatSpaceRemoveAroundMemberOperators(): boolean { - return this.getAsBoolean("vcFormat.space.removeAroundMemberOperators"); - } - - public get vcFormatSpaceBeforeInheritanceColon(): boolean { - return this.getAsBoolean("vcFormat.space.beforeInheritanceColon"); - } - - public get vcFormatSpaceBeforeConstructorColon(): boolean { - return this.getAsBoolean("vcFormat.space.beforeConstructorColon"); - } - - public get vcFormatSpaceRemoveBeforeSemicolon(): boolean { - return this.getAsBoolean("vcFormat.space.removeBeforeSemicolon"); - } - - public get vcFormatSpaceInsertAfterSemicolon(): boolean { - return this.getAsBoolean("vcFormat.space.insertAfterSemicolon"); - } - - public get vcFormatSpaceRemoveAroundUnaryOperator(): boolean { - return this.getAsBoolean("vcFormat.space.removeAroundUnaryOperator"); - } - + public get vcFormatSpaceWithinParameterListParentheses(): boolean { return this.getAsBoolean("vcFormat.space.withinParameterListParentheses"); } + public get vcFormatSpaceBetweenEmptyParameterListParentheses(): boolean { return this.getAsBoolean("vcFormat.space.betweenEmptyParameterListParentheses"); } + public get vcFormatSpaceAfterKeywordsInControlFlowStatements(): boolean { return this.getAsBoolean("vcFormat.space.afterKeywordsInControlFlowStatements"); } + public get vcFormatSpaceWithinControlFlowStatementParentheses(): boolean { return this.getAsBoolean("vcFormat.space.withinControlFlowStatementParentheses"); } + public get vcFormatSpaceBeforeLambdaOpenParenthesis(): boolean { return this.getAsBoolean("vcFormat.space.beforeLambdaOpenParenthesis"); } + public get vcFormatSpaceWithinCastParentheses(): boolean { return this.getAsBoolean("vcFormat.space.withinCastParentheses"); } + public get vcFormatSpaceAfterCastCloseParenthesis(): boolean { return this.getAsBoolean("vcFormat.space.afterCastCloseParenthesis"); } + public get vcFormatSpaceWithinExpressionParentheses(): boolean { return this.getAsBoolean("vcFormat.space.withinExpressionParentheses"); } + public get vcFormatSpaceBeforeBlockOpenBrace(): boolean { return this.getAsBoolean("vcFormat.space.beforeBlockOpenBrace"); } + public get vcFormatSpaceBetweenEmptyBraces(): boolean { return this.getAsBoolean("vcFormat.space.betweenEmptyBraces"); } + public get vcFormatSpaceBeforeInitializerListOpenBrace(): boolean { return this.getAsBoolean("vcFormat.space.beforeInitializerListOpenBrace"); } + public get vcFormatSpaceWithinInitializerListBraces(): boolean { return this.getAsBoolean("vcFormat.space.withinInitializerListBraces"); } + public get vcFormatSpacePreserveInInitializerList(): boolean { return this.getAsBoolean("vcFormat.space.preserveInInitializerList"); } + public get vcFormatSpaceBeforeOpenSquareBracket(): boolean { return this.getAsBoolean("vcFormat.space.beforeOpenSquareBracket"); } + public get vcFormatSpaceWithinSquareBrackets(): boolean { return this.getAsBoolean("vcFormat.space.withinSquareBrackets"); } + public get vcFormatSpaceBeforeEmptySquareBrackets(): boolean { return this.getAsBoolean("vcFormat.space.beforeEmptySquareBrackets"); } + public get vcFormatSpaceBetweenEmptySquareBrackets(): boolean { return this.getAsBoolean("vcFormat.space.betweenEmptySquareBrackets"); } + public get vcFormatSpaceGroupSquareBrackets(): boolean { return this.getAsBoolean("vcFormat.space.groupSquareBrackets"); } + public get vcFormatSpaceWithinLambdaBrackets(): boolean { return this.getAsBoolean("vcFormat.space.withinLambdaBrackets"); } + public get vcFormatSpaceBetweenEmptyLambdaBrackets(): boolean { return this.getAsBoolean("vcFormat.space.betweenEmptyLambdaBrackets"); } + public get vcFormatSpaceBeforeComma(): boolean { return this.getAsBoolean("vcFormat.space.beforeComma"); } + public get vcFormatSpaceAfterComma(): boolean { return this.getAsBoolean("vcFormat.space.afterComma"); } + public get vcFormatSpaceRemoveAroundMemberOperators(): boolean { return this.getAsBoolean("vcFormat.space.removeAroundMemberOperators"); } + public get vcFormatSpaceBeforeInheritanceColon(): boolean { return this.getAsBoolean("vcFormat.space.beforeInheritanceColon"); } + public get vcFormatSpaceBeforeConstructorColon(): boolean { return this.getAsBoolean("vcFormat.space.beforeConstructorColon"); } + public get vcFormatSpaceRemoveBeforeSemicolon(): boolean { return this.getAsBoolean("vcFormat.space.removeBeforeSemicolon"); } + public get vcFormatSpaceInsertAfterSemicolon(): boolean { return this.getAsBoolean("vcFormat.space.insertAfterSemicolon"); } + public get vcFormatSpaceRemoveAroundUnaryOperator(): boolean { return this.getAsBoolean("vcFormat.space.removeAroundUnaryOperator"); } public get vcFormatSpaceAroundBinaryOperator(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.space.aroundBinaryOperator")!; } - public get vcFormatSpaceAroundAssignmentOperator(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.space.aroundAssignmentOperator")!; } - public get vcFormatSpacePointerReferenceAlignment(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.space.pointerReferenceAlignment")!; } - public get vcFormatSpaceAroundTernaryOperator(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.space.aroundTernaryOperator")!; } - public get vcFormatWrapPreserveBlocks(): string { // These strings have default values in package.json, so should never be undefined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.getAsString("vcFormat.wrap.preserveBlocks")!; } - - public get dimInactiveRegions(): boolean { - return this.getAsBoolean("dimInactiveRegions") - && this.intelliSenseEngine === "default" - && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; - } - - public get sshTargetsView(): string { - return this.getAsString("sshTargetsView") ?? 'default'; - } + public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } + public get sshTargetsView(): string { return this.getAsString("sshTargetsView") ?? 'default'; } public toggleSetting(name: string, value1: string, value2: string): void { const value: string | undefined = this.getAsString(name); @@ -1078,24 +914,45 @@ export class OtherSettings { this.resource = resource; } - public get editorTabSize(): number | undefined { return vscode.workspace.getConfiguration("editor", this.resource).get("tabSize"); } - public get editorInsertSpaces(): boolean | undefined { return vscode.workspace.getConfiguration("editor", this.resource).get("insertSpaces"); } - public get editorAutoClosingBrackets(): string | undefined { return vscode.workspace.getConfiguration("editor", this.resource).get("autoClosingBrackets"); } - public get filesEncoding(): string | undefined { return vscode.workspace.getConfiguration("files", { uri: this.resource, languageId: "cpp" }).get("encoding"); } - public get filesAssociations(): any { return vscode.workspace.getConfiguration("files").get("associations"); } - public set filesAssociations(value: any) { - void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); + private getVSCodeSettingAsString(setting: string, configuration: string, resource: any, defaultString?: string): string | undefined { + const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); + if (isString(value)) { + return value; + } + return defaultString; + } + + private getVSCodeSettingAsBoolean(setting: string, configuration: string, resource: any, defaultBoolean?: boolean): boolean | undefined { + const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); + if (isBoolean(value)) { + return value; + } + return defaultBoolean; } + + private getAsNumber(setting: string, configuration: string, resource: any, defaultNumber?: number): number | undefined { + const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); + if (isNumber(value)) { + return value; + } + return defaultNumber; + } + + public get editorTabSize(): number | undefined { return this.getAsNumber("editor", "tabSize", this.resource, 4); } + public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } + public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } + public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "UTF-8"); } + public get filesAssociations(): any { const value = vscode.workspace.getConfiguration("files").get("associations"); return value; } + public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); } - public get filesAutoSaveAfterDelay(): boolean { return vscode.workspace.getConfiguration("files").get("autoSave") === "afterDelay"; } - public get editorInlayHintsEnabled(): boolean { return vscode.workspace.getConfiguration("editor.inlayHints").get("enabled") !== "off"; } - public get editorParameterHintsEnabled(): boolean | undefined { return vscode.workspace.getConfiguration("editor.parameterHints").get("enabled"); } + public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } + public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } + public get editorParameterHintsEnabled(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } - public get workbenchSettingsEditor(): string | undefined { return vscode.workspace.getConfiguration("workbench.settings").get("editor"); } - - public get colorTheme(): string | undefined { return vscode.workspace.getConfiguration("workbench").get("colorTheme"); } + public get workbenchSettingsEditor(): string | undefined { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource, "ui"); } + public get colorTheme(): string | undefined { return this.getVSCodeSettingAsString("workbench", "colorTheme", this.resource, "Dark Modern"); } - public getCustomColorToken(colorTokenName: string): string | undefined { return vscode.workspace.getConfiguration("editor.tokenColorCustomizations").get(colorTokenName); } + public getCustomColorToken(colorTokenName: string): string | undefined { return this.getVSCodeSettingAsString("editor.tokenColorCustomizations", colorTokenName, this.resource); } public getCustomThemeSpecificColorToken(themeName: string, colorTokenName: string): string | undefined { return vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource).get(colorTokenName); } public get customTextMateRules(): TextMateRule[] | undefined { return vscode.workspace.getConfiguration("editor.tokenColorCustomizations").get("textMateRules"); } diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index f367b93bfb..dc6a1c199f 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -80,7 +80,7 @@ export function getExperimentationService(): Promise | } export async function isExperimentEnabled(experimentName: string): Promise { - if (new CppSettings().experimentalFeaturesEnabled) { + if (new CppSettings().experimentalFeatures) { return true; } const experimentationService: IExperimentationService | undefined = await getExperimentationService(); From 1e913c98344c9250b8685d34a5adfe110e903132 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 8 Jul 2024 14:40:35 -0700 Subject: [PATCH 06/52] Add comments + fix formatting --- Extension/src/LanguageServer/settings.ts | 39 +++++++++++------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 63f592e5c0..19037368dd 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -333,13 +333,15 @@ export class CppSettings extends Settings { const value: any | undefined | null = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (isNumber(value) && (value >= setting.minimum && value <= setting.maximum)) { + if (isNumber(value) && (value >= setting.minimum && value <= setting.maximum)) { // Check if the value is within the valid range. return value; } return setting.default; } + // This helper function returns the value of a setting as an array of strings with proper type validation. + // Additionally, it checks for valid enum values if an array of enums is detected. private getAsArrayOfStrings(settingName: string): string[] { const setting = getRawSetting("C_Cpp." + settingName); const value: any | undefined | null = super.Section.get(settingName); @@ -356,6 +358,7 @@ export class CppSettings extends Settings { return setting.default; } + // This helper function returns the value of a setting as a key-value object with proper type validation. private getAsKeyValueObject(settingName: string, keyType: string, valueType: string): any { const setting = getRawSetting("C_Cpp." + settingName); const value: any = super.Section.get(settingName); @@ -365,6 +368,7 @@ export class CppSettings extends Settings { return setting.default; } + // This helper function validates whether the given value is a valid enum value for the given setting. private isValidEnum(settingName: string, value: any): boolean { const setting = getRawSetting("C_Cpp." + settingName); if (this.validateEnum(setting.enum, value)) { @@ -373,6 +377,8 @@ export class CppSettings extends Settings { return setting.default; } + // This helper function validates whether the given object is a valid mapping of key and value type. + // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. private isValidMapping(value: any, keyType: string, valueType: string): boolean { if (value === undefined || value === null) { return false; } for (const key of Object.keys(value)) { @@ -383,6 +389,7 @@ export class CppSettings extends Settings { return true; } + // This helper function checks a given enum value against a list of valid enum values from package.json. private validateEnum(enumDescription: any, value: any) { if (isArray(enumDescription) && enumDescription.length > 0) { return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); @@ -390,27 +397,13 @@ export class CppSettings extends Settings { return false; } - public get maxConcurrentThreads(): number | undefined | null { - return this.getAsNumber("maxConcurrentThreads"); - } - public get maxMemory(): number | undefined | null { - return this.getAsNumber("maxMemory"); - } - public get maxSymbolSearchResults(): number | undefined { - return this.getAsNumber("maxSymbolSearchResults"); - } - public get maxCachedProcesses(): number | undefined | null { - return this.getAsNumber("maxCachedProcesses"); - } - public get intelliSenseMaxCachedProcesses(): number | undefined | null { - return this.getAsNumber("intelliSense.maxCachedProcesses"); - } - public get intelliSenseMaxMemory(): number | undefined | null { - return this.getAsNumber("intelliSense.maxMemory"); - } - public get referencesMaxConcurrentThreads(): number | undefined | null { - return this.getAsNumber("references.maxConcurrentThreads"); - } + public get maxConcurrentThreads(): number | undefined | null { return this.getAsNumber("maxConcurrentThreads"); } + public get maxMemory(): number | undefined | null { return this.getAsNumber("maxMemory"); } + public get maxSymbolSearchResults(): number | undefined { return this.getAsNumber("maxSymbolSearchResults"); } + public get maxCachedProcesses(): number | undefined | null { return this.getAsNumber("maxCachedProcesses"); } + public get intelliSenseMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("intelliSense.maxCachedProcesses"); } + public get intelliSenseMaxMemory(): number | undefined | null { return this.getAsNumber("intelliSense.maxMemory"); } + public get referencesMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("references.maxConcurrentThreads"); } public get referencesMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("references.maxCachedProcesses"); } public get referencesMaxMemory(): number | undefined | null { return this.getAsNumber("references.maxMemory"); } public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } @@ -470,6 +463,7 @@ export class CppSettings extends Settings { return value; } + // To validate the types of the array of comment patterns, we need to check each property of the object specifically. This cannot be generalized. if (value.every(x => typeof x === "object" && typeof x.begin === "string" && typeof x.continue === "string")) { return value; } @@ -938,6 +932,7 @@ export class OtherSettings { return defaultNumber; } + // All default values are obtained from the VS Code settings UI. Please update the default values as needed. public get editorTabSize(): number | undefined { return this.getAsNumber("editor", "tabSize", this.resource, 4); } public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } From 3d388a88cb7ae95f26c659178b4b34f88ccf4448 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 8 Jul 2024 14:47:46 -0700 Subject: [PATCH 07/52] Fix lint issues --- Extension/src/LanguageServer/settings.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 19037368dd..8f7b8e4db5 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -377,7 +377,7 @@ export class CppSettings extends Settings { return setting.default; } - // This helper function validates whether the given object is a valid mapping of key and value type. + // This helper function validates whether the given object is a valid mapping of key and value type. // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. private isValidMapping(value: any, keyType: string, valueType: string): boolean { if (value === undefined || value === null) { return false; } @@ -934,7 +934,7 @@ export class OtherSettings { // All default values are obtained from the VS Code settings UI. Please update the default values as needed. public get editorTabSize(): number | undefined { return this.getAsNumber("editor", "tabSize", this.resource, 4); } - public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } + public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "UTF-8"); } public get filesAssociations(): any { const value = vscode.workspace.getConfiguration("files").get("associations"); return value; } From 0a9b17e55782df17fb49899b2bca8ad5935c0dbf Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 9 Jul 2024 11:42:22 -0700 Subject: [PATCH 08/52] Fix minor issues found in initial code review --- Extension/src/LanguageServer/client.ts | 1 - Extension/src/LanguageServer/settings.ts | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 4aee62c41c..0988c0323f 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1443,7 +1443,6 @@ export class DefaultClient implements Client { private getAllSettings(): SettingsParams { const workspaceSettings: CppSettings = new CppSettings(); const workspaceOtherSettings: OtherSettings = new OtherSettings(); - console.log(workspaceOtherSettings.editorTabSize); const workspaceFolderSettingsParams: WorkspaceFolderSettingsParams[] = this.getAllWorkspaceFolderSettings(); return { filesAssociations: workspaceOtherSettings.filesAssociations, diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 8f7b8e4db5..2332fe66a9 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -426,7 +426,10 @@ export class CppSettings extends Settings { public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; } public addClangTidyChecksDisabled(value: string): void { const checks: string[] | undefined = this.clangTidyChecksDisabled; - if (checks === undefined) { return; } checks.push(value); + if (checks === undefined) { + return; + } + checks.push(value); void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } public get clangFormatStyle(): string | undefined { return this.getAsString("clang_format_style"); } @@ -533,7 +536,7 @@ export class CppSettings extends Settings { public get inlayHintsReferenceOperator(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.enabled"); } public get inlayHintsReferenceOperatorShowSpace(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); } public get enhancedColorization(): boolean { return this.getAsString("enhancedColorization") === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } - public get formattingEngine(): string | undefined { return this.getAsString("formatting")?.toLowerCase(); } + public get formattingEngine(): string | undefined { return this.getAsString("formatting"); } public get vcFormatIndentBraces(): boolean { return this.getAsBoolean("vcFormat.indent.braces"); } public get vcFormatIndentMultiLineRelativeTo(): string { // These strings have default values in package.json, so should never be undefined. From f37af58eb0ce2e098dbddf3036e7689e55a8c3f4 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 10 Jul 2024 13:50:58 -0700 Subject: [PATCH 09/52] Add minor refactors to validation logic --- Extension/src/LanguageServer/settings.ts | 45 +++++++++++++++--------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 2332fe66a9..f3cf78282f 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -333,22 +333,32 @@ export class CppSettings extends Settings { const value: any | undefined | null = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (isNumber(value) && (value >= setting.minimum && value <= setting.maximum)) { // Check if the value is within the valid range. - return value; - } + if (isNumber(value)) { + if (setting.minimum !== undefined && setting.maximum !== undefined) { + if (value >= setting.minimum && value <= setting.maximum) { // Check if the value is within the valid range. + return value; + } + } else { + return value; + } + } return setting.default; } // This helper function returns the value of a setting as an array of strings with proper type validation. // Additionally, it checks for valid enum values if an array of enums is detected. - private getAsArrayOfStrings(settingName: string): string[] { + private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { const setting = getRawSetting("C_Cpp." + settingName); const value: any | undefined | null = super.Section.get(settingName); if (isArrayOfString(value)) { if (setting.items.enum !== undefined) { if (!value.every(x => this.validateEnum(setting.items.enum, x))) { - return setting.default; + if (allowUndefinedEnums) { + return value + } else { + return setting.default; + } } else { return value; } @@ -360,11 +370,11 @@ export class CppSettings extends Settings { // This helper function returns the value of a setting as a key-value object with proper type validation. private getAsKeyValueObject(settingName: string, keyType: string, valueType: string): any { - const setting = getRawSetting("C_Cpp." + settingName); const value: any = super.Section.get(settingName); if (this.isValidMapping(value, keyType, valueType)) { return value; } + const setting = getRawSetting("C_Cpp." + settingName); return setting.default; } @@ -397,6 +407,14 @@ export class CppSettings extends Settings { return false; } + private isArrayOfCommentContinuationPatterns(x: any): x is (string | CommentPattern)[] { + return isArray(x) && x.every(y => isString(y) || this.isCommentPattern(y)); + } + + private isCommentPattern(x: any): x is CommentPattern { + return isString(x.begin) && isString(x.continue); + } + public get maxConcurrentThreads(): number | undefined | null { return this.getAsNumber("maxConcurrentThreads"); } public get maxMemory(): number | undefined | null { return this.getAsNumber("maxMemory"); } public get maxSymbolSearchResults(): number | undefined { return this.getAsNumber("maxSymbolSearchResults"); } @@ -418,8 +436,8 @@ export class CppSettings extends Settings { public get clangTidyHeaderFilter(): string | undefined | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter"); } public get clangTidyArgs(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } - public get clangTidyChecksEnabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled"); } - public get clangTidyChecksDisabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled"); } + public get clangTidyChecksEnabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } + public get clangTidyChecksDisabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled", true); } public get clangTidyCodeActionShowDisable(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); } public get clangTidyCodeActionShowClear(): string { return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); } public get clangTidyCodeActionShowDocumentation(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); } @@ -462,12 +480,7 @@ export class CppSettings extends Settings { // eslint-disable-next-line no-extra-parens const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); if (value === undefined) { return undefined; } - if (isArrayOfString(value)) { - return value; - } - - // To validate the types of the array of comment patterns, we need to check each property of the object specifically. This cannot be generalized. - if (value.every(x => typeof x === "object" && typeof x.begin === "string" && typeof x.continue === "string")) { + if (isArrayOfString(value) || this.isArrayOfCommentContinuationPatterns(value)) { return value; } return undefined; @@ -927,7 +940,7 @@ export class OtherSettings { return defaultBoolean; } - private getAsNumber(setting: string, configuration: string, resource: any, defaultNumber?: number): number | undefined { + private getVSCodeSettingAsNumber(setting: string, configuration: string, resource: any, defaultNumber?: number): number | undefined { const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); if (isNumber(value)) { return value; @@ -936,7 +949,7 @@ export class OtherSettings { } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. - public get editorTabSize(): number | undefined { return this.getAsNumber("editor", "tabSize", this.resource, 4); } + public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "UTF-8"); } From 013e1f70530166cd663c69a20e0052fa6633c186 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Thu, 11 Jul 2024 14:42:18 -0700 Subject: [PATCH 10/52] Provide minor refactoring + minor fixes --- Extension/src/LanguageServer/settings.ts | 104 +++++++++++------------ 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index f3cf78282f..bae2394a46 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -310,7 +310,7 @@ export class CppSettings extends Settings { } private getAsBoolean(settingName: string): boolean { - const value: any | undefined = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (isBoolean(value)) { return value; } @@ -318,10 +318,12 @@ export class CppSettings extends Settings { return setting.default; } + // This helper function returns the value of a setting as a string with proper type validation. + // Additionally, it checks for valid enum values if an enum is detected. It will return enums as lowrcase strings. private getAsString(settingName: string): string { - const value: any | undefined = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (this.isValidEnum(settingName, value)) { - return value.toLowerCase(); // Return enum values in lowercase. + return value.toLowerCase(); } else if (isString(value)) { return value; } @@ -330,18 +332,18 @@ export class CppSettings extends Settings { } private getAsNumber(settingName: string): number { - const value: any | undefined | null = super.Section.get(settingName); + const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); if (isNumber(value)) { - if (setting.minimum !== undefined && setting.maximum !== undefined) { + if (setting.minimum !== undefined && setting.maximum !== undefined) { if (value >= setting.minimum && value <= setting.maximum) { // Check if the value is within the valid range. return value; } } else { return value; } - } + } return setting.default; } @@ -349,18 +351,14 @@ export class CppSettings extends Settings { // This helper function returns the value of a setting as an array of strings with proper type validation. // Additionally, it checks for valid enum values if an array of enums is detected. private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { + const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - const value: any | undefined | null = super.Section.get(settingName); if (isArrayOfString(value)) { - if (setting.items.enum !== undefined) { - if (!value.every(x => this.validateEnum(setting.items.enum, x))) { - if (allowUndefinedEnums) { - return value - } else { + if (!allowUndefinedEnums) { + if (setting.items.enum !== undefined) { + if (!value.every(x => this.validateEnum(setting.items.enum, x))) { return setting.default; } - } else { - return value; } } return value; @@ -378,39 +376,36 @@ export class CppSettings extends Settings { return setting.default; } - // This helper function validates whether the given value is a valid enum value for the given setting. - private isValidEnum(settingName: string, value: any): boolean { - const setting = getRawSetting("C_Cpp." + settingName); - if (this.validateEnum(setting.enum, value)) { - return value; - } - return setting.default; - } - // This helper function validates whether the given object is a valid mapping of key and value type. // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. private isValidMapping(value: any, keyType: string, valueType: string): boolean { - if (value === undefined || value === null) { return false; } - for (const key of Object.keys(value)) { - if (typeof key !== keyType && typeof value[key] !== valueType) { - return false; - } + if (value === undefined || value === null) { + return false; } - return true; + return Object.entries(value).every(([key, val]) => typeof key === keyType && typeof val === valueType); } // This helper function checks a given enum value against a list of valid enum values from package.json. - private validateEnum(enumDescription: any, value: any) { + private validateEnum(enumDescription: any, value: any): boolean { if (isArray(enumDescription) && enumDescription.length > 0) { return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); } return false; } + // This helper function validates whether the given value is a valid enum value for the given setting. + private isValidEnum(settingName: string, value: any): boolean { + const setting = getRawSetting("C_Cpp." + settingName); + if (this.validateEnum(setting.enum, value)) { + return value; + } + return setting.default; + } + private isArrayOfCommentContinuationPatterns(x: any): x is (string | CommentPattern)[] { return isArray(x) && x.every(y => isString(y) || this.isCommentPattern(y)); - } - + } + private isCommentPattern(x: any): x is CommentPattern { return isString(x.begin) && isString(x.continue); } @@ -444,9 +439,9 @@ export class CppSettings extends Settings { public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; } public addClangTidyChecksDisabled(value: string): void { const checks: string[] | undefined = this.clangTidyChecksDisabled; - if (checks === undefined) { + if (checks === undefined) { return; - } + } checks.push(value); void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } @@ -924,44 +919,49 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(setting: string, configuration: string, resource: any, defaultString?: string): string | undefined { - const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); + private getVSCodeSettingAsString(setting: string, configuration: string, resource: any): string | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); + const value = fullConfiguration.get(configuration); if (isString(value)) { return value; } - return defaultString; + const config = fullConfiguration.inspect(configuration); + return config?.defaultValue; } - private getVSCodeSettingAsBoolean(setting: string, configuration: string, resource: any, defaultBoolean?: boolean): boolean | undefined { - const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); + private getVSCodeSettingAsBoolean(setting: string, configuration: string, resource: any): boolean | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); + const value = fullConfiguration.get(configuration); if (isBoolean(value)) { return value; } - return defaultBoolean; + const config = fullConfiguration.inspect(configuration); + return config?.defaultValue; } - private getVSCodeSettingAsNumber(setting: string, configuration: string, resource: any, defaultNumber?: number): number | undefined { - const value = vscode.workspace.getConfiguration(configuration, resource).get(setting); + private getVSCodeSettingAsNumber(setting: string, configuration: string, resource: any): number | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); + const value = fullConfiguration.get(configuration); if (isNumber(value)) { return value; } - return defaultNumber; - } + const config = fullConfiguration.inspect(configuration); + return config?.defaultValue; } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. - public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } - public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } - public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } - public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "UTF-8"); } + public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource); } + public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource); } + public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource); } + public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }); } public get filesAssociations(): any { const value = vscode.workspace.getConfiguration("files").get("associations"); return value; } public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); } - public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } - public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } + public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource) === "afterDelay"; } + public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource) !== "off"; } public get editorParameterHintsEnabled(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } - public get workbenchSettingsEditor(): string | undefined { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource, "ui"); } - public get colorTheme(): string | undefined { return this.getVSCodeSettingAsString("workbench", "colorTheme", this.resource, "Dark Modern"); } + public get workbenchSettingsEditor(): string | undefined { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource); } + public get colorTheme(): string | undefined { return this.getVSCodeSettingAsString("workbench", "colorTheme", this.resource); } public getCustomColorToken(colorTokenName: string): string | undefined { return this.getVSCodeSettingAsString("editor.tokenColorCustomizations", colorTokenName, this.resource); } public getCustomThemeSpecificColorToken(themeName: string, colorTokenName: string): string | undefined { return vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource).get(colorTokenName); } From 6398d45e53d7ff63672df65b8ff04aadedf66784 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 12 Jul 2024 14:41:09 -0700 Subject: [PATCH 11/52] Provide refactoring, add helper functions + minor fixes --- Extension/src/LanguageServer/client.ts | 16 +- Extension/src/LanguageServer/settings.ts | 357 ++++++++++------------- Extension/src/common.ts | 9 + 3 files changed, 178 insertions(+), 204 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 9b0172a3f1..d8c69daa16 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1273,7 +1273,7 @@ export class DefaultClient implements Client { this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, this.codeFoldingProvider); const settings: CppSettings = new CppSettings(); - if (settings.enhancedColorization && semanticTokensLegend) { + if (settings.isEnhancedColorizationEnabled && semanticTokensLegend) { this.semanticTokensProvider = new SemanticTokensProvider(); this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend); } @@ -1458,7 +1458,7 @@ export class DefaultClient implements Client { simplifyStructuredComments: workspaceSettings.simplifyStructuredComments, intelliSenseUpdateDelay: workspaceSettings.intelliSenseUpdateDelay, experimentalFeatures: workspaceSettings.experimentalFeatures, - enhancedColorization: workspaceSettings.enhancedColorization, + enhancedColorization: workspaceSettings.isEnhancedColorizationEnabled, intellisenseMaxCachedProcesses: workspaceSettings.intelliSenseMaxCachedProcesses, intellisenseMaxMemory: workspaceSettings.intelliSenseMaxMemory, referencesMaxConcurrentThreads: workspaceSettings.referencesMaxConcurrentThreads, @@ -1515,9 +1515,9 @@ export class DefaultClient implements Client { } const workspaceSettings: CppSettings = new CppSettings(); - if (workspaceSettings.caseSensitiveFileSupport !== currentCaseSensitiveFileSupport.Value) { + if (workspaceSettings.isCaseSensitiveFileSupportEnabled !== currentCaseSensitiveFileSupport.Value) { resetDatabase = true; - currentCaseSensitiveFileSupport.Value = workspaceSettings.caseSensitiveFileSupport; + currentCaseSensitiveFileSupport.Value = workspaceSettings.isCaseSensitiveFileSupportEnabled; } const cacheStoragePath: string = util.getCacheStoragePath(); @@ -1532,7 +1532,7 @@ export class DefaultClient implements Client { cacheStoragePath: cacheStoragePath, vcpkgRoot: util.getVcpkgRoot(), intelliSenseCacheDisabled: intelliSenseCacheDisabled, - caseSensitiveFileSupport: workspaceSettings.caseSensitiveFileSupport, + caseSensitiveFileSupport: workspaceSettings.isCaseSensitiveFileSupportEnabled, resetDatabase: resetDatabase, edgeMessagesDirectory: path.join(util.getExtensionFilePath("bin"), "messages", getLocaleId()), localizedStrings: localizedStrings, @@ -1630,7 +1630,7 @@ export class DefaultClient implements Client { } const settings: CppSettings = new CppSettings(); if (changedSettings.enhancedColorization) { - if (settings.enhancedColorization && semanticTokensLegend) { + if (settings.isEnhancedColorizationEnabled && semanticTokensLegend) { this.semanticTokensProvider = new SemanticTokensProvider(); this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend); } else if (this.semanticTokensProviderDisposable) { @@ -2096,7 +2096,7 @@ export class DefaultClient implements Client { result = "timeout"; if (!requestFile) { const settings: CppSettings = new CppSettings(this.RootUri); - if (settings.configurationWarnings && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) { + if (settings.isConfigurationWarningsEnabled && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) { const dismiss: string = localize("dismiss.button", "Dismiss"); const disable: string = localize("disable.warnings.button", "Disable Warnings"); const configName: string | undefined = this.configuration.CurrentConfiguration?.name; @@ -2166,7 +2166,7 @@ export class DefaultClient implements Client { public getVcpkgEnabled(): Promise { const cppSettings: CppSettings = new CppSettings(this.RootUri); - return Promise.resolve(!!cppSettings.vcpkg); + return Promise.resolve(!!cppSettings.isVcpkgEnabled); } public async getKnownCompilers(): Promise { diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index bae2394a46..ad2b16196d 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -14,7 +14,7 @@ import { quote } from 'shell-quote'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as which from 'which'; -import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; +import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; import { clients } from './extension'; @@ -323,7 +323,7 @@ export class CppSettings extends Settings { private getAsString(settingName: string): string { const value: any = super.Section.get(settingName); if (this.isValidEnum(settingName, value)) { - return value.toLowerCase(); + return value; } else if (isString(value)) { return value; } @@ -369,22 +369,13 @@ export class CppSettings extends Settings { // This helper function returns the value of a setting as a key-value object with proper type validation. private getAsKeyValueObject(settingName: string, keyType: string, valueType: string): any { const value: any = super.Section.get(settingName); - if (this.isValidMapping(value, keyType, valueType)) { + if (isValidMapping(value, keyType, valueType)) { return value; } const setting = getRawSetting("C_Cpp." + settingName); return setting.default; } - // This helper function validates whether the given object is a valid mapping of key and value type. - // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. - private isValidMapping(value: any, keyType: string, valueType: string): boolean { - if (value === undefined || value === null) { - return false; - } - return Object.entries(value).every(([key, val]) => typeof key === keyType && typeof val === valueType); - } - // This helper function checks a given enum value against a list of valid enum values from package.json. private validateEnum(enumDescription: any, value: any): boolean { if (isArray(enumDescription) && enumDescription.length > 0) { @@ -410,94 +401,94 @@ export class CppSettings extends Settings { return isString(x.begin) && isString(x.continue); } - public get maxConcurrentThreads(): number | undefined | null { return this.getAsNumber("maxConcurrentThreads"); } - public get maxMemory(): number | undefined | null { return this.getAsNumber("maxMemory"); } - public get maxSymbolSearchResults(): number | undefined { return this.getAsNumber("maxSymbolSearchResults"); } - public get maxCachedProcesses(): number | undefined | null { return this.getAsNumber("maxCachedProcesses"); } - public get intelliSenseMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("intelliSense.maxCachedProcesses"); } - public get intelliSenseMaxMemory(): number | undefined | null { return this.getAsNumber("intelliSense.maxMemory"); } - public get referencesMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("references.maxConcurrentThreads"); } - public get referencesMaxCachedProcesses(): number | undefined | null { return this.getAsNumber("references.maxCachedProcesses"); } - public get referencesMaxMemory(): number | undefined | null { return this.getAsNumber("references.maxMemory"); } - public get codeAnalysisMaxConcurrentThreads(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } - public get codeAnalysisMaxMemory(): number | undefined | null { return this.getAsNumber("codeAnalysis.maxMemory"); } - public get codeAnalysisUpdateDelay(): number | undefined { return this.getAsNumber("codeAnalysis.updateDelay"); } - public get codeAnalysisExclude(): Excludes | undefined { return this.getAsKeyValueObject("codeAnalysis.exclude", "string", "boolean"); } - public get codeAnalysisRunAutomatically(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runAutomatically"); } - public get codeAnalysisRunOnBuild(): boolean | undefined { return this.getAsBoolean("codeAnalysis.runOnBuild"); } - public get clangTidyEnabled(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } - public get clangTidyConfig(): string | undefined { return this.getAsString("codeAnalysis.clangTidy.config"); } - public get clangTidyFallbackConfig(): string | undefined { return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); } - public get clangTidyHeaderFilter(): string | undefined | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter"); } - public get clangTidyArgs(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } - public get clangTidyUseBuildPath(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } - public get clangTidyChecksEnabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } - public get clangTidyChecksDisabled(): string[] | undefined { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled", true); } - public get clangTidyCodeActionShowDisable(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); } + public get maxConcurrentThreads(): number | null { return this.getAsNumber("maxConcurrentThreads"); } + public get maxMemory(): number | null { return this.getAsNumber("maxMemory"); } + public get maxSymbolSearchResults(): number { return this.getAsNumber("maxSymbolSearchResults"); } + public get maxCachedProcesses(): number { return this.getAsNumber("maxCachedProcesses"); } + public get intelliSenseMaxCachedProcesses(): number | null { return this.getAsNumber("intelliSense.maxCachedProcesses"); } + public get intelliSenseMaxMemory(): number | null { return this.getAsNumber("intelliSense.maxMemory"); } + public get referencesMaxConcurrentThreads(): number | null { return this.getAsNumber("references.maxConcurrentThreads"); } + public get referencesMaxCachedProcesses(): number { return this.getAsNumber("references.maxCachedProcesses"); } + public get referencesMaxMemory(): number | null { return this.getAsNumber("references.maxMemory"); } + public get codeAnalysisMaxConcurrentThreads(): number | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } + public get codeAnalysisMaxMemory(): number | null { return this.getAsNumber("codeAnalysis.maxMemory"); } + public get codeAnalysisUpdateDelay(): number { return this.getAsNumber("codeAnalysis.updateDelay"); } + public get codeAnalysisExclude(): Excludes { return this.getAsKeyValueObject("codeAnalysis.exclude", "string", "boolean"); } + public get codeAnalysisRunAutomatically(): boolean { return this.getAsBoolean("codeAnalysis.runAutomatically"); } + public get codeAnalysisRunOnBuild(): boolean { return this.getAsBoolean("codeAnalysis.runOnBuild"); } + public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } + public get clangTidyConfig(): string { return this.getAsString("codeAnalysis.clangTidy.config"); } + public get clangTidyFallbackConfig(): string { return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); } + public get clangTidyHeaderFilter(): string | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter"); } + public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } + public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } + public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } + public get clangTidyChecksDisabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled", true); } + public get clangTidyCodeActionShowDisable(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); } public get clangTidyCodeActionShowClear(): string { return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); } - public get clangTidyCodeActionShowDocumentation(): boolean | undefined { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); } - public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes") ?? true; } + public get clangTidyCodeActionShowDocumentation(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); } + public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes"); } public addClangTidyChecksDisabled(value: string): void { - const checks: string[] | undefined = this.clangTidyChecksDisabled; + const checks: string[] = this.clangTidyChecksDisabled; if (checks === undefined) { return; } checks.push(value); void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } - public get clangFormatStyle(): string | undefined { return this.getAsString("clang_format_style"); } - public get clangFormatFallbackStyle(): string | undefined { return this.getAsString("clang_format_fallbackStyle"); } - public get clangFormatSortIncludes(): boolean | undefined | null { return this.getAsBoolean("clang_format_sortIncludes"); } - public get experimentalFeatures(): boolean | undefined { return this.getAsString("experimentalFeatures") === "enabled"; } - public get suggestSnippets(): boolean | undefined { return this.getAsBoolean("suggestSnippets"); } - public get intelliSenseEngine(): string | undefined { return this.getAsString("intelliSenseEngine"); } - public get intelliSenseEngineFallback(): boolean | undefined { return this.getAsString("intelliSenseEngineFallback") === "enabled"; } - public get intelliSenseCachePath(): string | undefined { return this.getAsString("intelliSenseEngine"); } - public get intelliSenseCacheSize(): number | undefined { return this.getAsNumber("intelliSenseCachePath"); } - public get intelliSenseMemoryLimit(): number | undefined { return this.getAsNumber("intelliSenseMemoryLimit"); } - public get intelliSenseUpdateDelay(): number | undefined { return this.getAsNumber("intelliSenseUpdateDelay"); } - public get errorSquiggles(): string | undefined { return this.getAsString("errorSquiggles"); } - public get inactiveRegionOpacity(): number | undefined { return this.getAsNumber("inactiveRegionOpacity"); } - public get inactiveRegionForegroundColor(): string | undefined { return this.getAsString("inactiveRegionForegroundColor"); } - public get inactiveRegionBackgroundColor(): string | undefined { return this.getAsString("inactiveRegionBackgroundColor"); } - public get autocomplete(): string | undefined { return this.getAsString("autocomplete"); } - public get autocompleteAddParentheses(): boolean | undefined { return this.getAsBoolean("autocompleteAddParentheses"); } - public get loggingLevel(): string | undefined { return this.getAsString("loggingLevel"); } - public get autoAddFileAssociations(): boolean | undefined { return this.getAsBoolean("autoAddFileAssociations"); } - public get workspaceParsingPriority(): string | undefined { return this.getAsString("workspaceParsingPriority"); } - public get workspaceSymbols(): string | undefined { return this.getAsString("workspaceSymbols"); } - public get exclusionPolicy(): string | undefined { return this.getAsString("exclusionPolicy"); } - public get refactoringIncludeHeader(): string | undefined { return this.getAsString("refactoring.includeHeader"); } - public get simplifyStructuredComments(): boolean | undefined { return this.getAsBoolean("simplifyStructuredComments"); } - public get doxygenGeneratedCommentStyle(): string | undefined { return this.getAsString("doxygen.generatedStyle"); } - public get doxygenGenerateOnType(): boolean | undefined { return this.getAsBoolean("doxygen.generateOnType"); } - public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { + public get clangFormatStyle(): string { return this.getAsString("clang_format_style"); } + public get clangFormatFallbackStyle(): string { return this.getAsString("clang_format_fallbackStyle"); } + public get clangFormatSortIncludes(): boolean | null { return this.getAsBoolean("clang_format_sortIncludes"); } + public get experimentalFeatures(): boolean { return this.getAsString("experimentalFeatures").toLowerCase() === "enabled"; } + public get suggestSnippets(): boolean { return this.getAsBoolean("suggestSnippets"); } + public get intelliSenseEngine(): string { return this.getAsString("intelliSenseEngine"); } + public get intelliSenseEngineFallback(): boolean { return this.getAsString("intelliSenseEngineFallback") === "enabled"; } + public get intelliSenseCachePath(): string { return this.getAsString("intelliSenseCachePath"); } + public get intelliSenseCacheSize(): number { return this.getAsNumber("intelliSenseCacheSize"); } + public get intelliSenseMemoryLimit(): number { return this.getAsNumber("intelliSenseMemoryLimit"); } + public get intelliSenseUpdateDelay(): number { return this.getAsNumber("intelliSenseUpdateDelay"); } + public get errorSquiggles(): string { return this.getAsString("errorSquiggles"); } + public get inactiveRegionOpacity(): number { return this.getAsNumber("inactiveRegionOpacity"); } + public get inactiveRegionForegroundColor(): string { return this.getAsString("inactiveRegionForegroundColor"); } + public get inactiveRegionBackgroundColor(): string { return this.getAsString("inactiveRegionBackgroundColor"); } + public get autocomplete(): string { return this.getAsString("autocomplete"); } + public get autocompleteAddParentheses(): boolean { return this.getAsBoolean("autocompleteAddParentheses"); } + public get loggingLevel(): string { return this.getAsString("loggingLevel"); } + public get autoAddFileAssociations(): boolean { return this.getAsBoolean("autoAddFileAssociations"); } + public get workspaceParsingPriority(): string { return this.getAsString("workspaceParsingPriority"); } + public get workspaceSymbols(): string { return this.getAsString("workspaceSymbols"); } + public get exclusionPolicy(): string { return this.getAsString("exclusionPolicy"); } + public get refactoringIncludeHeader(): string { return this.getAsString("refactoring.includeHeader"); } + public get simplifyStructuredComments(): boolean { return this.getAsBoolean("simplifyStructuredComments"); } + public get doxygenGeneratedCommentStyle(): string { return this.getAsString("doxygen.generatedStyle"); } + public get doxygenGenerateOnType(): boolean { return this.getAsBoolean("doxygen.generateOnType"); } + public get commentContinuationPatterns(): (string | CommentPattern)[] { // eslint-disable-next-line no-extra-parens const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); - if (value === undefined) { return undefined; } - if (isArrayOfString(value) || this.isArrayOfCommentContinuationPatterns(value)) { + if (this.isArrayOfCommentContinuationPatterns(value)) { return value; } - return undefined; + const setting = getRawSetting("C_Cpp." + "commentContinuationPatterns"); + return setting.default; } - public get configurationWarnings(): boolean | undefined { return this.getAsString("configurationWarnings") === "enabled"; } - public get preferredPathSeparator(): string | undefined { return this.getAsString("preferredPathSeparator"); } - public get updateChannel(): string | undefined { return this.getAsString("updateChannel"); } - public get vcpkg(): boolean | undefined { return this.getAsString("vcpkg") === "enabled"; } - public get addNodeAddonIncludePaths(): boolean | undefined { return this.getAsBoolean("addNodeAddonIncludePaths"); } - public get renameRequiresIdentifier(): boolean | undefined { return this.getAsBoolean("renameRequiresIdentifier"); } - public get filesExclude(): Excludes | undefined {return this.getAsKeyValueObject("files.exclude", "string", "boolean");} - public get defaultIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.includePath"); } - public get defaultDefines(): string[] | undefined { return this.getAsArrayOfStrings("default.defines"); } - public get defaultDotconfig(): string | undefined { return this.getAsString("default.dotConfig"); } - public get defaultMacFrameworkPath(): string[] | undefined { return this.getAsArrayOfStrings("default.macFrameworkPath"); } - public get defaultWindowsSdkVersion(): string | undefined { return this.getAsString("default.windowsSdkVersion"); } - public get defaultCompileCommands(): string | undefined { return this.getAsString("default.compileCommands"); } - public get defaultForcedInclude(): string[] | undefined { return this.getAsArrayOfStrings("default.forcedInclude"); } - public get defaultIntelliSenseMode(): string | undefined { return this.getAsString("default.intelliSenseMode"); } - public get defaultCompilerPath(): string | undefined { return this.getAsString("default.compilerPath") ?? undefined; } - - public set defaultCompilerPath(value: string | undefined) { + public get isConfigurationWarningsEnabled(): boolean { return this.getAsString("configurationWarnings").toLowerCase() === "enabled"; } + public get preferredPathSeparator(): string { return this.getAsString("preferredPathSeparator"); } + public get updateChannel(): string { return this.getAsString("updateChannel"); } + public get isVcpkgEnabled(): boolean { return this.getAsString("vcpkg") === "enabled"; } + public get addNodeAddonIncludePaths(): boolean { return this.getAsBoolean("addNodeAddonIncludePaths"); } + public get renameRequiresIdentifier(): boolean { return this.getAsBoolean("renameRequiresIdentifier"); } + public get filesExclude(): Excludes {return this.getAsKeyValueObject("files.exclude", "string", "boolean");} + public get defaultIncludePath(): string[] { return this.getAsArrayOfStrings("default.includePath"); } + public get defaultDefines(): string[] { return this.getAsArrayOfStrings("default.defines"); } + public get defaultDotconfig(): string { return this.getAsString("default.dotConfig"); } + public get defaultMacFrameworkPath(): string[] { return this.getAsArrayOfStrings("default.macFrameworkPath"); } + public get defaultWindowsSdkVersion(): string { return this.getAsString("default.windowsSdkVersion"); } + public get defaultCompileCommands(): string { return this.getAsString("default.compileCommands"); } + public get defaultForcedInclude(): string[] { return this.getAsArrayOfStrings("default.forcedInclude"); } + public get defaultIntelliSenseMode(): string { return this.getAsString("default.intelliSenseMode"); } + public get defaultCompilerPath(): string { return this.getAsString("default.compilerPath") ?? undefined; } + + public set defaultCompilerPath(value: string) { const defaultCompilerPathStr: string = "default.compilerPath"; const compilerPathInfo: any = this.Section.inspect(defaultCompilerPathStr); let target: vscode.ConfigurationTarget = vscode.ConfigurationTarget.Global; @@ -517,25 +508,24 @@ export class CppSettings extends Settings { }); } } - public get defaultCompilerArgs(): string[] | undefined { return this.getAsArrayOfStrings("default.compilerArgs"); } - public get defaultCStandard(): string | undefined { return this.getAsString("default.cStandard"); } - public get defaultCppStandard(): string | undefined { return this.getAsString("default.cppStandard"); } - public get defaultConfigurationProvider(): string | undefined { return this.getAsString("default.configurationProvider"); } - public get defaultMergeConfigurations(): boolean | undefined { return this.getAsBoolean("default.mergeConfigurations"); } - public get defaultBrowsePath(): string[] | undefined { return this.getAsArrayOfStrings("default.browse.path") ?? undefined; } - public get defaultDatabaseFilename(): string | undefined { return this.getAsString("default.browse.databaseFilename"); } - public get defaultLimitSymbolsToIncludedHeaders(): boolean | undefined { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } - public get defaultSystemIncludePath(): string[] | undefined { return this.getAsArrayOfStrings("default.systemIncludePath"); } - public get defaultEnableConfigurationSquiggles(): boolean | undefined { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - public get defaultCustomConfigurationVariables(): { [key: string]: string } | undefined {return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string");} - public get useBacktickCommandSubstitution(): boolean | undefined { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } + public get defaultCompilerArgs(): string[] { return this.getAsArrayOfStrings("default.compilerArgs"); } + public get defaultCStandard(): string { return this.getAsString("default.cStandard"); } + public get defaultCppStandard(): string { return this.getAsString("default.cppStandard"); } + public get defaultConfigurationProvider(): string { return this.getAsString("default.configurationProvider"); } + public get defaultMergeConfigurations(): boolean { return this.getAsBoolean("default.mergeConfigurations"); } + public get defaultBrowsePath(): string[] { return this.getAsArrayOfStrings("default.browse.path") ?? undefined; } + public get defaultDatabaseFilename(): string { return this.getAsString("default.browse.databaseFilename"); } + public get defaultLimitSymbolsToIncludedHeaders(): boolean { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } + public get defaultSystemIncludePath(): string[] { return this.getAsArrayOfStrings("default.systemIncludePath"); } + public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } + public get defaultCustomConfigurationVariables(): { [key: string]: string } {return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string");} + public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } public get codeFolding(): boolean {return this.getAsString("codeFolding.enabled") === "enabled"; } - public get caseSensitiveFileSupport(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } - public get doxygenSectionTags(): string[] | undefined { return this.getAsArrayOfStrings("doxygen.sectionTags"); } - public get hover(): string | undefined { return this.getAsString("hover"); } - public get markdownInComments(): string | undefined { return this.getAsString("markdownInComments"); } - public get legacyCompilerArgsBehavior(): boolean | undefined { return this.getAsBoolean("legacyCompilerArgsBehavior"); } - + public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } + public get doxygenSectionTags(): string[] { return this.getAsArrayOfStrings("doxygen.sectionTags"); } + public get hover(): string { return this.getAsString("hover"); } + public get markdownInComments(): string { return this.getAsString("markdownInComments"); } + public get legacyCompilerArgsBehavior(): boolean { return this.getAsBoolean("legacyCompilerArgsBehavior"); } public get inlayHintsAutoDeclarationTypes(): boolean { return this.getAsBoolean("inlayHints.autoDeclarationTypes.enabled"); } public get inlayHintsAutoDeclarationTypesShowOnLeft(): boolean { return this.getAsBoolean("inlayHints.autoDeclarationTypes.showOnLeft"); } public get inlayHintsParameterNames(): boolean { return this.getAsBoolean("inlayHints.parameterNames.enabled"); } @@ -543,73 +533,33 @@ export class CppSettings extends Settings { public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean { return this.getAsBoolean("inlayHints.parameterNames.hideLeadingUnderscores"); } public get inlayHintsReferenceOperator(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.enabled"); } public get inlayHintsReferenceOperatorShowSpace(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); } - public get enhancedColorization(): boolean { return this.getAsString("enhancedColorization") === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } - public get formattingEngine(): string | undefined { return this.getAsString("formatting"); } + public get isEnhancedColorizationEnabled(): boolean { return this.getAsString("enhancedColorization") === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } + public get formattingEngine(): string { return this.getAsString("formatting"); } public get vcFormatIndentBraces(): boolean { return this.getAsBoolean("vcFormat.indent.braces"); } - public get vcFormatIndentMultiLineRelativeTo(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.indent.multiLineRelativeTo")!; - } - public get vcFormatIndentWithinParentheses(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.indent.withinParentheses")!; - } + public get vcFormatIndentMultiLineRelativeTo(): string {return this.getAsString("vcFormat.indent.multiLineRelativeTo");} + public get vcFormatIndentWithinParentheses(): string {return this.getAsString("vcFormat.indent.withinParentheses");} public get vcFormatIndentPreserveWithinParentheses(): boolean { return this.getAsBoolean("vcFormat.indent.preserveWithinParentheses"); } public get vcFormatIndentCaseLabels(): boolean { return this.getAsBoolean("vcFormat.indent.caseLabels"); } public get vcFormatIndentCaseContents(): boolean { return this.getAsBoolean("vcFormat.indent.caseContents"); } public get vcFormatIndentCaseContentsWhenBlock(): boolean { return this.getAsBoolean("vcFormat.indent.caseContentsWhenBlock"); } public get vcFormatIndentLambdaBracesWhenParameter(): boolean { return this.getAsBoolean("vcFormat.indent.lambdaBracesWhenParameter"); } - public get vcFormatIndentGotoLabels(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.indent.gotoLabels")!; - } - public get vcFormatIndentPreprocessor(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.indent.preprocessor")!; - } + public get vcFormatIndentGotoLabels(): string {return this.getAsString("vcFormat.indent.gotoLabels");} + public get vcFormatIndentPreprocessor(): string {return this.getAsString("vcFormat.indent.preprocessor");} public get vcFormatIndentAccessSpecifiers(): boolean { return this.getAsBoolean("vcFormat.indent.accessSpecifiers"); } public get vcFormatIndentNamespaceContents(): boolean { return this.getAsBoolean("vcFormat.indent.namespaceContents"); } public get vcFormatIndentPreserveComments(): boolean { return this.getAsBoolean("vcFormat.indent.preserveComments"); } - public get vcFormatNewlineBeforeOpenBraceNamespace(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.newLine.beforeOpenBrace.namespace")!; - } - public get vcFormatNewlineBeforeOpenBraceType(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.newLine.beforeOpenBrace.type")!; - } - public get vcFormatNewlineBeforeOpenBraceFunction(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.newLine.beforeOpenBrace.function")!; - } - public get vcFormatNewlineBeforeOpenBraceBlock(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.newLine.beforeOpenBrace.block")!; - } - public get vcFormatNewlineBeforeOpenBraceLambda(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.newLine.beforeOpenBrace.lambda")!; - } + public get vcFormatNewlineBeforeOpenBraceNamespace(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.namespace");} + public get vcFormatNewlineBeforeOpenBraceType(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.type");} + public get vcFormatNewlineBeforeOpenBraceFunction(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.function");} + public get vcFormatNewlineBeforeOpenBraceBlock(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.block");} + public get vcFormatNewlineBeforeOpenBraceLambda(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.lambda");} public get vcFormatNewlineScopeBracesOnSeparateLines(): boolean { return this.getAsBoolean("vcFormat.newLine.scopeBracesOnSeparateLines"); } public get vcFormatNewlineCloseBraceSameLineEmptyType(): boolean { return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyType"); } public get vcFormatNewlineCloseBraceSameLineEmptyFunction(): boolean { return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyFunction"); } public get vcFormatNewlineBeforeCatch(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeCatch"); } public get vcFormatNewlineBeforeElse(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeElse"); } public get vcFormatNewlineBeforeWhileInDoWhile(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeWhileInDoWhile"); } - public get vcFormatSpaceBeforeFunctionOpenParenthesis(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.space.beforeFunctionOpenParenthesis")!; - } + public get vcFormatSpaceBeforeFunctionOpenParenthesis(): string {return this.getAsString("vcFormat.space.beforeFunctionOpenParenthesis");} public get vcFormatSpaceWithinParameterListParentheses(): boolean { return this.getAsBoolean("vcFormat.space.withinParameterListParentheses"); } public get vcFormatSpaceBetweenEmptyParameterListParentheses(): boolean { return this.getAsBoolean("vcFormat.space.betweenEmptyParameterListParentheses"); } public get vcFormatSpaceAfterKeywordsInControlFlowStatements(): boolean { return this.getAsBoolean("vcFormat.space.afterKeywordsInControlFlowStatements"); } @@ -638,36 +588,16 @@ export class CppSettings extends Settings { public get vcFormatSpaceRemoveBeforeSemicolon(): boolean { return this.getAsBoolean("vcFormat.space.removeBeforeSemicolon"); } public get vcFormatSpaceInsertAfterSemicolon(): boolean { return this.getAsBoolean("vcFormat.space.insertAfterSemicolon"); } public get vcFormatSpaceRemoveAroundUnaryOperator(): boolean { return this.getAsBoolean("vcFormat.space.removeAroundUnaryOperator"); } - public get vcFormatSpaceAroundBinaryOperator(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.space.aroundBinaryOperator")!; - } - public get vcFormatSpaceAroundAssignmentOperator(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.space.aroundAssignmentOperator")!; - } - public get vcFormatSpacePointerReferenceAlignment(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.space.pointerReferenceAlignment")!; - } - public get vcFormatSpaceAroundTernaryOperator(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.space.aroundTernaryOperator")!; - } - public get vcFormatWrapPreserveBlocks(): string { - // These strings have default values in package.json, so should never be undefined. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getAsString("vcFormat.wrap.preserveBlocks")!; - } + public get vcFormatSpaceAroundBinaryOperator(): string {return this.getAsString("vcFormat.space.aroundBinaryOperator");} + public get vcFormatSpaceAroundAssignmentOperator(): string {return this.getAsString("vcFormat.space.aroundAssignmentOperator");} + public get vcFormatSpacePointerReferenceAlignment(): string { return this.getAsString("vcFormat.space.pointerReferenceAlignment");} + public get vcFormatSpaceAroundTernaryOperator(): string {return this.getAsString("vcFormat.space.aroundTernaryOperator");} + public get vcFormatWrapPreserveBlocks(): string {return this.getAsString("vcFormat.wrap.preserveBlocks");} public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } - public get sshTargetsView(): string { return this.getAsString("sshTargetsView") ?? 'default'; } + public get sshTargetsView(): string { return this.getAsString("sshTargetsView"); } public toggleSetting(name: string, value1: string, value2: string): void { - const value: string | undefined = this.getAsString(name); + const value: string = this.getAsString(name); void super.Section.update(name, value?.toLowerCase() === value1.toLowerCase() ? value2 : value1, getTarget()); } @@ -919,43 +849,71 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(setting: string, configuration: string, resource: any): string | undefined { + private getVSCodeSettingAsString(setting: string, configuration: string, resource: any, defaultString?: string): string | undefined { const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); const value = fullConfiguration.get(configuration); if (isString(value)) { return value; } const config = fullConfiguration.inspect(configuration); - return config?.defaultValue; + return config?.defaultValue ?? defaultString; } - private getVSCodeSettingAsBoolean(setting: string, configuration: string, resource: any): boolean | undefined { + private getVSCodeSettingAsBoolean(setting: string, configuration: string, resource: any, defaultBoolean?: boolean): boolean | undefined { const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); const value = fullConfiguration.get(configuration); if (isBoolean(value)) { return value; } const config = fullConfiguration.inspect(configuration); - return config?.defaultValue; + return config?.defaultValue ?? defaultBoolean; } - private getVSCodeSettingAsNumber(setting: string, configuration: string, resource: any): number | undefined { + private getVSCodeSettingAsNumber(setting: string, configuration: string, resource: any, defaultNumber?: number): number | undefined { const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); const value = fullConfiguration.get(configuration); if (isNumber(value)) { return value; } const config = fullConfiguration.inspect(configuration); - return config?.defaultValue; } + return config?.defaultValue ?? defaultNumber; + } + + private getVSCodeSettingAsKeyValueObject(setting: string, configuration: string, keyType: string, valueType: string, resource?: any): any { + const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); + const value = fullConfiguration.get(configuration); + if (isValidMapping(value, keyType, valueType)) { + return value; + } + const config = fullConfiguration.inspect(configuration); + return config?.defaultValue; + } + + private isArrayOfTextMateRules(x: any): x is TextMateRule[] { + return isArray(x) && x.every(y => this.isTextMateRule(y)); + } + + private isTextMateRule(x: any): x is TextMateRule { + return this.isTextMateRuleScope(x.scope) && this.isTextMateRuleSettings(x.settings); + } + + private isTextMateRuleScope(x: any): boolean { + // Assuming scope can be either a string or an array of strings + return isString(x) || (isArray(x) && x.every(isString)); + } + + private isTextMateRuleSettings(x: any): x is TextMateRuleSettings { + return isString(x.foreground) && isString(x.background) && isString(x.fontStyle); + } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. - public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource); } + public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource); } public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource); } public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }); } - public get filesAssociations(): any { const value = vscode.workspace.getConfiguration("files").get("associations"); return value; } + public get filesAssociations(): any { return this.getVSCodeSettingAsKeyValueObject("files", "associations", "string", "string"); } public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } - public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); } + public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return this.getVSCodeSettingAsKeyValueObject("files", "exclude", "string", "boolean", this.resource); } public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource) === "afterDelay"; } public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource) !== "off"; } public get editorParameterHintsEnabled(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } @@ -964,10 +922,17 @@ export class OtherSettings { public get colorTheme(): string | undefined { return this.getVSCodeSettingAsString("workbench", "colorTheme", this.resource); } public getCustomColorToken(colorTokenName: string): string | undefined { return this.getVSCodeSettingAsString("editor.tokenColorCustomizations", colorTokenName, this.resource); } - public getCustomThemeSpecificColorToken(themeName: string, colorTokenName: string): string | undefined { return vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource).get(colorTokenName); } - + public getCustomThemeSpecificColorToken(themeName: string, colorTokenName: string): string | undefined { return this.getVSCodeSettingAsString(`editor.tokenColorCustomizations.[${themeName}]`, colorTokenName, this.resource); } public get customTextMateRules(): TextMateRule[] | undefined { return vscode.workspace.getConfiguration("editor.tokenColorCustomizations").get("textMateRules"); } - public getCustomThemeSpecificTextMateRules(themeName: string): TextMateRule[] | undefined { return vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource).get("textMateRules"); } + public getCustomThemeSpecificTextMateRules(themeName: string): TextMateRule[] | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource); + const value = fullConfiguration.get("textMateRules"); + if (this.isArrayOfTextMateRules(value)) { + return value; + } + const config = fullConfiguration.inspect("textMateRules"); + return config?.defaultValue; + } } function mapIndentationReferenceToEditorConfig(value: string | undefined): string { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index f2ac8ecf9c..8fcbc5c393 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -333,6 +333,15 @@ export function isArrayOfString(input: any): input is string[] { return isArray(input) && input.every(isString); } +// This helper function validates whether the given object is a valid mapping of key and value type. +// EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. +export function isValidMapping(value: any, keyType: string, valueType: string): boolean { + if (value === undefined || value === null) { + return false; + } + return Object.entries(value).every(([key, val]) => typeof key === keyType && typeof val === valueType); +} + export function isOptionalArrayOfString(input: any): input is string[] | undefined { return input === undefined || isArrayOfString(input); } From f1b6f098f2e9cb7857f9cdf678abb8718d922317 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 12 Jul 2024 14:51:18 -0700 Subject: [PATCH 12/52] Add missing toLowerCase calls --- Extension/src/LanguageServer/settings.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index ad2b16196d..a564603ff4 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -442,7 +442,7 @@ export class CppSettings extends Settings { public get experimentalFeatures(): boolean { return this.getAsString("experimentalFeatures").toLowerCase() === "enabled"; } public get suggestSnippets(): boolean { return this.getAsBoolean("suggestSnippets"); } public get intelliSenseEngine(): string { return this.getAsString("intelliSenseEngine"); } - public get intelliSenseEngineFallback(): boolean { return this.getAsString("intelliSenseEngineFallback") === "enabled"; } + public get intelliSenseEngineFallback(): boolean { return this.getAsString("intelliSenseEngineFallback").toLowerCase() === "enabled"; } public get intelliSenseCachePath(): string { return this.getAsString("intelliSenseCachePath"); } public get intelliSenseCacheSize(): number { return this.getAsNumber("intelliSenseCacheSize"); } public get intelliSenseMemoryLimit(): number { return this.getAsNumber("intelliSenseMemoryLimit"); } @@ -474,7 +474,7 @@ export class CppSettings extends Settings { public get isConfigurationWarningsEnabled(): boolean { return this.getAsString("configurationWarnings").toLowerCase() === "enabled"; } public get preferredPathSeparator(): string { return this.getAsString("preferredPathSeparator"); } public get updateChannel(): string { return this.getAsString("updateChannel"); } - public get isVcpkgEnabled(): boolean { return this.getAsString("vcpkg") === "enabled"; } + public get isVcpkgEnabled(): boolean { return this.getAsString("vcpkg").toLowerCase() === "enabled"; } public get addNodeAddonIncludePaths(): boolean { return this.getAsBoolean("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean { return this.getAsBoolean("renameRequiresIdentifier"); } public get filesExclude(): Excludes {return this.getAsKeyValueObject("files.exclude", "string", "boolean");} @@ -520,8 +520,8 @@ export class CppSettings extends Settings { public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } public get defaultCustomConfigurationVariables(): { [key: string]: string } {return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string");} public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } - public get codeFolding(): boolean {return this.getAsString("codeFolding.enabled") === "enabled"; } - public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport") === "enabled"; } + public get codeFolding(): boolean {return this.getAsString("codeFolding").toLowerCase() === "enabled"; } + public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport").toLowerCase() === "enabled"; } public get doxygenSectionTags(): string[] { return this.getAsArrayOfStrings("doxygen.sectionTags"); } public get hover(): string { return this.getAsString("hover"); } public get markdownInComments(): string { return this.getAsString("markdownInComments"); } @@ -533,7 +533,7 @@ export class CppSettings extends Settings { public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean { return this.getAsBoolean("inlayHints.parameterNames.hideLeadingUnderscores"); } public get inlayHintsReferenceOperator(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.enabled"); } public get inlayHintsReferenceOperatorShowSpace(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); } - public get isEnhancedColorizationEnabled(): boolean { return this.getAsString("enhancedColorization") === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } + public get isEnhancedColorizationEnabled(): boolean { return this.getAsString("enhancedColorization").toLowerCase() === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get formattingEngine(): string { return this.getAsString("formatting"); } public get vcFormatIndentBraces(): boolean { return this.getAsBoolean("vcFormat.indent.braces"); } public get vcFormatIndentMultiLineRelativeTo(): string {return this.getAsString("vcFormat.indent.multiLineRelativeTo");} From 0fd0d77cf7cb25a957542121c05fe9b857b006f6 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 12 Jul 2024 15:49:18 -0700 Subject: [PATCH 13/52] Fix function comment --- Extension/src/LanguageServer/settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index a564603ff4..e33a0f55fd 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -319,7 +319,7 @@ export class CppSettings extends Settings { } // This helper function returns the value of a setting as a string with proper type validation. - // Additionally, it checks for valid enum values if an enum is detected. It will return enums as lowrcase strings. + // Additionally, it checks for valid enum values if an enum is detected. private getAsString(settingName: string): string { const value: any = super.Section.get(settingName); if (this.isValidEnum(settingName, value)) { From d8c8ea84d779cda580f4278d9faf20f8ec61cb10 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 15 Jul 2024 13:21:49 -0700 Subject: [PATCH 14/52] Remove unused setting getters, minor refactorings + minor fixes. --- Extension/src/LanguageServer/client.ts | 2 +- Extension/src/LanguageServer/settings.ts | 170 ++++++++++------------- Extension/src/common.ts | 5 +- 3 files changed, 76 insertions(+), 101 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 61f255c533..6d56e4538f 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -2166,7 +2166,7 @@ export class DefaultClient implements Client { public getVcpkgEnabled(): Promise { const cppSettings: CppSettings = new CppSettings(this.RootUri); - return Promise.resolve(!!cppSettings.isVcpkgEnabled); + return Promise.resolve(cppSettings.isVcpkgEnabled); } public async getKnownCompilers(): Promise { diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index e33a0f55fd..e6f0eb4572 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -308,9 +308,14 @@ export class CppSettings extends Settings { } return path; } - - private getAsBoolean(settingName: string): boolean { + // Returns the value of a setting as a boolean with proper type validation. + private getAsBoolean(settingName: string): boolean; + private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; + private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } if (isBoolean(value)) { return value; } @@ -318,10 +323,14 @@ export class CppSettings extends Settings { return setting.default; } - // This helper function returns the value of a setting as a string with proper type validation. - // Additionally, it checks for valid enum values if an enum is detected. - private getAsString(settingName: string): string { + // Returns the value of a setting as a string with proper type validation and checks for valid enum values. + private getAsString(settingName: string): string; + private getAsString(settingName: string, allowNull: boolean): string | null; + private getAsString(settingName: string, allowNull: boolean = false): string | null { const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } if (this.isValidEnum(settingName, value)) { return value; } else if (isString(value)) { @@ -331,25 +340,23 @@ export class CppSettings extends Settings { return setting.default; } - private getAsNumber(settingName: string): number { + // Returns the value of a setting as a number with proper type validation and checks if value falls within the specified range. + private getAsNumber(settingName: string): number; + private getAsNumber(settingName: string, allowNull: boolean): number | null; + private getAsNumber(settingName: string, allowNull: boolean = false): number | null { const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } const setting = getRawSetting("C_Cpp." + settingName); - - if (isNumber(value)) { - if (setting.minimum !== undefined && setting.maximum !== undefined) { - if (value >= setting.minimum && value <= setting.maximum) { // Check if the value is within the valid range. - return value; - } - } else { - return value; - } + // Validates the value is a number and falls within the specified range. Allows for undefined maximum or minimum values. + if ((isNumber(value) || value === null) && (setting.minimum === undefined || value >= setting.minimum) && (setting.maximum === undefined || value <= setting.maximum)) { + return value; } - return setting.default; } - // This helper function returns the value of a setting as an array of strings with proper type validation. - // Additionally, it checks for valid enum values if an array of enums is detected. + // Returns the value of a setting as an array of strings with proper type validation and checks for valid enum values. private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); @@ -366,7 +373,7 @@ export class CppSettings extends Settings { return setting.default; } - // This helper function returns the value of a setting as a key-value object with proper type validation. + // Returns the value of a setting as a key-value object with proper type validation. private getAsKeyValueObject(settingName: string, keyType: string, valueType: string): any { const value: any = super.Section.get(settingName); if (isValidMapping(value, keyType, valueType)) { @@ -376,7 +383,7 @@ export class CppSettings extends Settings { return setting.default; } - // This helper function checks a given enum value against a list of valid enum values from package.json. + // Checks a given enum value against a list of valid enum values from package.json. private validateEnum(enumDescription: any, value: any): boolean { if (isArray(enumDescription) && enumDescription.length > 0) { return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); @@ -384,7 +391,7 @@ export class CppSettings extends Settings { return false; } - // This helper function validates whether the given value is a valid enum value for the given setting. + // Validates whether the given value is a valid enum value for the given setting. private isValidEnum(settingName: string, value: any): boolean { const setting = getRawSetting("C_Cpp." + settingName); if (this.validateEnum(setting.enum, value)) { @@ -401,17 +408,17 @@ export class CppSettings extends Settings { return isString(x.begin) && isString(x.continue); } - public get maxConcurrentThreads(): number | null { return this.getAsNumber("maxConcurrentThreads"); } - public get maxMemory(): number | null { return this.getAsNumber("maxMemory"); } + public get maxConcurrentThreads(): number | null { return this.getAsNumber("maxConcurrentThreads", true); } + public get maxMemory(): number | null { return this.getAsNumber("maxMemory", true); } public get maxSymbolSearchResults(): number { return this.getAsNumber("maxSymbolSearchResults"); } public get maxCachedProcesses(): number { return this.getAsNumber("maxCachedProcesses"); } - public get intelliSenseMaxCachedProcesses(): number | null { return this.getAsNumber("intelliSense.maxCachedProcesses"); } - public get intelliSenseMaxMemory(): number | null { return this.getAsNumber("intelliSense.maxMemory"); } - public get referencesMaxConcurrentThreads(): number | null { return this.getAsNumber("references.maxConcurrentThreads"); } + public get intelliSenseMaxCachedProcesses(): number | null { return this.getAsNumber("intelliSense.maxCachedProcesses", true); } + public get intelliSenseMaxMemory(): number | null { return this.getAsNumber("intelliSense.maxMemory", true); } + public get referencesMaxConcurrentThreads(): number | null { return this.getAsNumber("references.maxConcurrentThreads", true); } public get referencesMaxCachedProcesses(): number { return this.getAsNumber("references.maxCachedProcesses"); } - public get referencesMaxMemory(): number | null { return this.getAsNumber("references.maxMemory"); } - public get codeAnalysisMaxConcurrentThreads(): number | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads"); } - public get codeAnalysisMaxMemory(): number | null { return this.getAsNumber("codeAnalysis.maxMemory"); } + public get referencesMaxMemory(): number | null { return this.getAsNumber("references.maxMemory", true); } + public get codeAnalysisMaxConcurrentThreads(): number | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads", true); } + public get codeAnalysisMaxMemory(): number | null { return this.getAsNumber("codeAnalysis.maxMemory", true); } public get codeAnalysisUpdateDelay(): number { return this.getAsNumber("codeAnalysis.updateDelay"); } public get codeAnalysisExclude(): Excludes { return this.getAsKeyValueObject("codeAnalysis.exclude", "string", "boolean"); } public get codeAnalysisRunAutomatically(): boolean { return this.getAsBoolean("codeAnalysis.runAutomatically"); } @@ -419,7 +426,7 @@ export class CppSettings extends Settings { public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } public get clangTidyConfig(): string { return this.getAsString("codeAnalysis.clangTidy.config"); } public get clangTidyFallbackConfig(): string { return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); } - public get clangTidyHeaderFilter(): string | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter"); } + public get clangTidyHeaderFilter(): string | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter", true); } public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } @@ -438,7 +445,7 @@ export class CppSettings extends Settings { } public get clangFormatStyle(): string { return this.getAsString("clang_format_style"); } public get clangFormatFallbackStyle(): string { return this.getAsString("clang_format_fallbackStyle"); } - public get clangFormatSortIncludes(): boolean | null { return this.getAsBoolean("clang_format_sortIncludes"); } + public get clangFormatSortIncludes(): boolean | null { return this.getAsBoolean("clang_format_sortIncludes", true); } public get experimentalFeatures(): boolean { return this.getAsString("experimentalFeatures").toLowerCase() === "enabled"; } public get suggestSnippets(): boolean { return this.getAsBoolean("suggestSnippets"); } public get intelliSenseEngine(): string { return this.getAsString("intelliSenseEngine"); } @@ -477,7 +484,7 @@ export class CppSettings extends Settings { public get isVcpkgEnabled(): boolean { return this.getAsString("vcpkg").toLowerCase() === "enabled"; } public get addNodeAddonIncludePaths(): boolean { return this.getAsBoolean("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean { return this.getAsBoolean("renameRequiresIdentifier"); } - public get filesExclude(): Excludes {return this.getAsKeyValueObject("files.exclude", "string", "boolean");} + public get filesExclude(): Excludes { return this.getAsKeyValueObject("files.exclude", "string", "boolean"); } public get defaultIncludePath(): string[] { return this.getAsArrayOfStrings("default.includePath"); } public get defaultDefines(): string[] { return this.getAsArrayOfStrings("default.defines"); } public get defaultDotconfig(): string { return this.getAsString("default.dotConfig"); } @@ -518,9 +525,9 @@ export class CppSettings extends Settings { public get defaultLimitSymbolsToIncludedHeaders(): boolean { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } public get defaultSystemIncludePath(): string[] { return this.getAsArrayOfStrings("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - public get defaultCustomConfigurationVariables(): { [key: string]: string } {return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string");} + public get defaultCustomConfigurationVariables(): { [key: string]: string } { return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string"); } public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } - public get codeFolding(): boolean {return this.getAsString("codeFolding").toLowerCase() === "enabled"; } + public get codeFolding(): boolean { return this.getAsString("codeFolding").toLowerCase() === "enabled"; } public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport").toLowerCase() === "enabled"; } public get doxygenSectionTags(): string[] { return this.getAsArrayOfStrings("doxygen.sectionTags"); } public get hover(): string { return this.getAsString("hover"); } @@ -536,30 +543,30 @@ export class CppSettings extends Settings { public get isEnhancedColorizationEnabled(): boolean { return this.getAsString("enhancedColorization").toLowerCase() === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get formattingEngine(): string { return this.getAsString("formatting"); } public get vcFormatIndentBraces(): boolean { return this.getAsBoolean("vcFormat.indent.braces"); } - public get vcFormatIndentMultiLineRelativeTo(): string {return this.getAsString("vcFormat.indent.multiLineRelativeTo");} - public get vcFormatIndentWithinParentheses(): string {return this.getAsString("vcFormat.indent.withinParentheses");} + public get vcFormatIndentMultiLineRelativeTo(): string { return this.getAsString("vcFormat.indent.multiLineRelativeTo"); } + public get vcFormatIndentWithinParentheses(): string { return this.getAsString("vcFormat.indent.withinParentheses"); } public get vcFormatIndentPreserveWithinParentheses(): boolean { return this.getAsBoolean("vcFormat.indent.preserveWithinParentheses"); } public get vcFormatIndentCaseLabels(): boolean { return this.getAsBoolean("vcFormat.indent.caseLabels"); } public get vcFormatIndentCaseContents(): boolean { return this.getAsBoolean("vcFormat.indent.caseContents"); } public get vcFormatIndentCaseContentsWhenBlock(): boolean { return this.getAsBoolean("vcFormat.indent.caseContentsWhenBlock"); } public get vcFormatIndentLambdaBracesWhenParameter(): boolean { return this.getAsBoolean("vcFormat.indent.lambdaBracesWhenParameter"); } - public get vcFormatIndentGotoLabels(): string {return this.getAsString("vcFormat.indent.gotoLabels");} - public get vcFormatIndentPreprocessor(): string {return this.getAsString("vcFormat.indent.preprocessor");} + public get vcFormatIndentGotoLabels(): string { return this.getAsString("vcFormat.indent.gotoLabels"); } + public get vcFormatIndentPreprocessor(): string { return this.getAsString("vcFormat.indent.preprocessor"); } public get vcFormatIndentAccessSpecifiers(): boolean { return this.getAsBoolean("vcFormat.indent.accessSpecifiers"); } public get vcFormatIndentNamespaceContents(): boolean { return this.getAsBoolean("vcFormat.indent.namespaceContents"); } public get vcFormatIndentPreserveComments(): boolean { return this.getAsBoolean("vcFormat.indent.preserveComments"); } - public get vcFormatNewlineBeforeOpenBraceNamespace(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.namespace");} - public get vcFormatNewlineBeforeOpenBraceType(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.type");} - public get vcFormatNewlineBeforeOpenBraceFunction(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.function");} - public get vcFormatNewlineBeforeOpenBraceBlock(): string {return this.getAsString("vcFormat.newLine.beforeOpenBrace.block");} - public get vcFormatNewlineBeforeOpenBraceLambda(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.lambda");} + public get vcFormatNewlineBeforeOpenBraceNamespace(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.namespace"); } + public get vcFormatNewlineBeforeOpenBraceType(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.type"); } + public get vcFormatNewlineBeforeOpenBraceFunction(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.function"); } + public get vcFormatNewlineBeforeOpenBraceBlock(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.block"); } + public get vcFormatNewlineBeforeOpenBraceLambda(): string { return this.getAsString("vcFormat.newLine.beforeOpenBrace.lambda"); } public get vcFormatNewlineScopeBracesOnSeparateLines(): boolean { return this.getAsBoolean("vcFormat.newLine.scopeBracesOnSeparateLines"); } public get vcFormatNewlineCloseBraceSameLineEmptyType(): boolean { return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyType"); } public get vcFormatNewlineCloseBraceSameLineEmptyFunction(): boolean { return this.getAsBoolean("vcFormat.newLine.closeBraceSameLine.emptyFunction"); } public get vcFormatNewlineBeforeCatch(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeCatch"); } public get vcFormatNewlineBeforeElse(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeElse"); } public get vcFormatNewlineBeforeWhileInDoWhile(): boolean { return this.getAsBoolean("vcFormat.newLine.beforeWhileInDoWhile"); } - public get vcFormatSpaceBeforeFunctionOpenParenthesis(): string {return this.getAsString("vcFormat.space.beforeFunctionOpenParenthesis");} + public get vcFormatSpaceBeforeFunctionOpenParenthesis(): string { return this.getAsString("vcFormat.space.beforeFunctionOpenParenthesis"); } public get vcFormatSpaceWithinParameterListParentheses(): boolean { return this.getAsBoolean("vcFormat.space.withinParameterListParentheses"); } public get vcFormatSpaceBetweenEmptyParameterListParentheses(): boolean { return this.getAsBoolean("vcFormat.space.betweenEmptyParameterListParentheses"); } public get vcFormatSpaceAfterKeywordsInControlFlowStatements(): boolean { return this.getAsBoolean("vcFormat.space.afterKeywordsInControlFlowStatements"); } @@ -588,11 +595,11 @@ export class CppSettings extends Settings { public get vcFormatSpaceRemoveBeforeSemicolon(): boolean { return this.getAsBoolean("vcFormat.space.removeBeforeSemicolon"); } public get vcFormatSpaceInsertAfterSemicolon(): boolean { return this.getAsBoolean("vcFormat.space.insertAfterSemicolon"); } public get vcFormatSpaceRemoveAroundUnaryOperator(): boolean { return this.getAsBoolean("vcFormat.space.removeAroundUnaryOperator"); } - public get vcFormatSpaceAroundBinaryOperator(): string {return this.getAsString("vcFormat.space.aroundBinaryOperator");} - public get vcFormatSpaceAroundAssignmentOperator(): string {return this.getAsString("vcFormat.space.aroundAssignmentOperator");} - public get vcFormatSpacePointerReferenceAlignment(): string { return this.getAsString("vcFormat.space.pointerReferenceAlignment");} - public get vcFormatSpaceAroundTernaryOperator(): string {return this.getAsString("vcFormat.space.aroundTernaryOperator");} - public get vcFormatWrapPreserveBlocks(): string {return this.getAsString("vcFormat.wrap.preserveBlocks");} + public get vcFormatSpaceAroundBinaryOperator(): string { return this.getAsString("vcFormat.space.aroundBinaryOperator"); } + public get vcFormatSpaceAroundAssignmentOperator(): string { return this.getAsString("vcFormat.space.aroundAssignmentOperator"); } + public get vcFormatSpacePointerReferenceAlignment(): string { return this.getAsString("vcFormat.space.pointerReferenceAlignment"); } + public get vcFormatSpaceAroundTernaryOperator(): string { return this.getAsString("vcFormat.space.aroundTernaryOperator"); } + public get vcFormatWrapPreserveBlocks(): string { return this.getAsString("vcFormat.wrap.preserveBlocks"); } public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get sshTargetsView(): string { return this.getAsString("sshTargetsView"); } @@ -835,7 +842,7 @@ export interface TextMateRuleSettings { } export interface TextMateRule { - scope: any; + scope: string[]; settings: TextMateRuleSettings; } @@ -849,63 +856,46 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(setting: string, configuration: string, resource: any, defaultString?: string): string | undefined { - const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); - const value = fullConfiguration.get(configuration); + private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString?: string): string | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); + const value = fullConfiguration.get(setting); if (isString(value)) { return value; } - const config = fullConfiguration.inspect(configuration); + const config = fullConfiguration.inspect(setting); return config?.defaultValue ?? defaultString; } - private getVSCodeSettingAsBoolean(setting: string, configuration: string, resource: any, defaultBoolean?: boolean): boolean | undefined { - const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); - const value = fullConfiguration.get(configuration); + private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean?: boolean): boolean | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); + const value = fullConfiguration.get(setting); if (isBoolean(value)) { return value; } - const config = fullConfiguration.inspect(configuration); + const config = fullConfiguration.inspect(setting); return config?.defaultValue ?? defaultBoolean; } - private getVSCodeSettingAsNumber(setting: string, configuration: string, resource: any, defaultNumber?: number): number | undefined { - const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); - const value = fullConfiguration.get(configuration); + private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber?: number): number | undefined { + const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); + const value = fullConfiguration.get(setting); if (isNumber(value)) { return value; } - const config = fullConfiguration.inspect(configuration); + const config = fullConfiguration.inspect(setting); return config?.defaultValue ?? defaultNumber; } - private getVSCodeSettingAsKeyValueObject(setting: string, configuration: string, keyType: string, valueType: string, resource?: any): any { - const fullConfiguration = vscode.workspace.getConfiguration(setting, resource); - const value = fullConfiguration.get(configuration); + private getVSCodeSettingAsKeyValueObject(settingName: string, setting: string, keyType: string, valueType: string, resource?: any): any { + const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); + const value = fullConfiguration.get(setting); if (isValidMapping(value, keyType, valueType)) { return value; } - const config = fullConfiguration.inspect(configuration); + const config = fullConfiguration.inspect(setting); return config?.defaultValue; } - private isArrayOfTextMateRules(x: any): x is TextMateRule[] { - return isArray(x) && x.every(y => this.isTextMateRule(y)); - } - - private isTextMateRule(x: any): x is TextMateRule { - return this.isTextMateRuleScope(x.scope) && this.isTextMateRuleSettings(x.settings); - } - - private isTextMateRuleScope(x: any): boolean { - // Assuming scope can be either a string or an array of strings - return isString(x) || (isArray(x) && x.every(isString)); - } - - private isTextMateRuleSettings(x: any): x is TextMateRuleSettings { - return isString(x.foreground) && isString(x.background) && isString(x.fontStyle); - } - // All default values are obtained from the VS Code settings UI. Please update the default values as needed. public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource); } @@ -919,20 +909,6 @@ export class OtherSettings { public get editorParameterHintsEnabled(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } public get workbenchSettingsEditor(): string | undefined { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource); } - public get colorTheme(): string | undefined { return this.getVSCodeSettingAsString("workbench", "colorTheme", this.resource); } - - public getCustomColorToken(colorTokenName: string): string | undefined { return this.getVSCodeSettingAsString("editor.tokenColorCustomizations", colorTokenName, this.resource); } - public getCustomThemeSpecificColorToken(themeName: string, colorTokenName: string): string | undefined { return this.getVSCodeSettingAsString(`editor.tokenColorCustomizations.[${themeName}]`, colorTokenName, this.resource); } - public get customTextMateRules(): TextMateRule[] | undefined { return vscode.workspace.getConfiguration("editor.tokenColorCustomizations").get("textMateRules"); } - public getCustomThemeSpecificTextMateRules(themeName: string): TextMateRule[] | undefined { - const fullConfiguration = vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource); - const value = fullConfiguration.get("textMateRules"); - if (this.isArrayOfTextMateRules(value)) { - return value; - } - const config = fullConfiguration.inspect("textMateRules"); - return config?.defaultValue; - } } function mapIndentationReferenceToEditorConfig(value: string | undefined): string { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 8fcbc5c393..73afb12560 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -333,7 +333,7 @@ export function isArrayOfString(input: any): input is string[] { return isArray(input) && input.every(isString); } -// This helper function validates whether the given object is a valid mapping of key and value type. +// Validates whether the given object is a valid mapping of key and value type. // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. export function isValidMapping(value: any, keyType: string, valueType: string): boolean { if (value === undefined || value === null) { @@ -1775,8 +1775,7 @@ export function buildShellCommandLine(originalCommand: CommandString, command: C let commandLine = result.join(' '); // There are special rules quoted command line in cmd.exe - if (isWindows) - { + if (isWindows) { commandLine = `chcp 65001>nul && ${commandLine}`; if (commandQuoted && argQuoted) { commandLine = '"' + commandLine + '"'; From 806a5ade6500c4b9ad00ae2dc0de3e5410cd501c Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 15 Jul 2024 16:49:00 -0700 Subject: [PATCH 15/52] Remove usage of the undefined type where possible --- Extension/src/LanguageServer/settings.ts | 285 ++++++++++++----------- 1 file changed, 153 insertions(+), 132 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index e6f0eb4572..5c70282f46 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -30,131 +30,131 @@ export interface Excludes { export interface WorkspaceFolderSettingsParams { uri: string | undefined; - intelliSenseEngine: string | undefined; - intelliSenseEngineFallback: boolean | undefined; - autocomplete: string | undefined; - autocompleteAddParentheses: boolean | undefined; - errorSquiggles: string | undefined; - exclusionPolicy: string | undefined; - preferredPathSeparator: string | undefined; - intelliSenseCachePath: string | undefined; - intelliSenseCacheSize: number | undefined; - intelliSenseMemoryLimit: number | undefined; - dimInactiveRegions: boolean | undefined; - suggestSnippets: boolean | undefined; - legacyCompilerArgsBehavior: boolean | undefined; - defaultSystemIncludePath: string[] | undefined; - cppFilesExclude: Excludes | undefined; - clangFormatPath: string | undefined; + intelliSenseEngine: string; + intelliSenseEngineFallback: boolean; + autocomplete: string; + autocompleteAddParentheses: boolean; + errorSquiggles: string; + exclusionPolicy: string; + preferredPathSeparator: string; + intelliSenseCachePath: string; + intelliSenseCacheSize: number; + intelliSenseMemoryLimit: number; + dimInactiveRegions: boolean; + suggestSnippets: boolean; + legacyCompilerArgsBehavior: boolean; + defaultSystemIncludePath: string[]; + cppFilesExclude: Excludes; + clangFormatPath: string; clangFormatStyle: string | undefined; - clangFormatFallbackStyle: string | undefined; - clangFormatSortIncludes: boolean | undefined | null; - codeAnalysisRunAutomatically: boolean | undefined; - codeAnalysisExclude: Excludes | undefined; - clangTidyEnabled: boolean | undefined; - clangTidyPath: string | undefined; - clangTidyConfig: string | undefined; - clangTidyFallbackConfig: string | undefined; - clangTidyHeaderFilter: string | undefined | null; - clangTidyArgs: string[] | undefined; - clangTidyUseBuildPath: boolean | undefined; - clangTidyChecksEnabled: string[] | undefined; - clangTidyChecksDisabled: string[] | undefined; - hover: string | undefined; - markdownInComments: string | undefined; - vcFormatIndentBraces: boolean | undefined; - vcFormatIndentMultiLineRelativeTo: string | undefined; - vcFormatIndentWithinParentheses: string | undefined; + clangFormatFallbackStyle: string; + clangFormatSortIncludes: boolean | null; + codeAnalysisRunAutomatically: boolean; + codeAnalysisExclude: Excludes; + clangTidyEnabled: boolean; + clangTidyPath: string; + clangTidyConfig: string; + clangTidyFallbackConfig: string; + clangTidyHeaderFilter: string | null; + clangTidyArgs: string[]; + clangTidyUseBuildPath: boolean; + clangTidyChecksEnabled: string[]; + clangTidyChecksDisabled: string[]; + hover: string; + markdownInComments: string; + vcFormatIndentBraces: boolean; + vcFormatIndentMultiLineRelativeTo: string; + vcFormatIndentWithinParentheses: string; vcFormatIndentPreserveWithinParentheses: boolean; - vcFormatIndentCaseLabels: boolean | undefined; - vcFormatIndentCaseContents: boolean | undefined; - vcFormatIndentCaseContentsWhenBlock: boolean | undefined; - vcFormatIndentLambdaBracesWhenParameter: boolean | undefined; - vcFormatIndentGotoLabels: string | undefined; - vcFormatIndentPreprocessor: string | undefined; - vcFormatIndentAccesSpecifiers: boolean | undefined; - vcFormatIndentNamespaceContents: boolean | undefined; - vcFormatIndentPreserveComments: boolean | undefined; - vcFormatNewLineScopeBracesOnSeparateLines: boolean | undefined; - vcFormatNewLineBeforeOpenBraceNamespace: string | undefined; - vcFormatNewLineBeforeOpenBraceType: string | undefined; - vcFormatNewLineBeforeOpenBraceFunction: string | undefined; - vcFormatNewLineBeforeOpenBraceBlock: string | undefined; - vcFormatNewLineBeforeOpenBraceLambda: string | undefined; - vcFormatNewLineBeforeCatch: boolean | undefined; - vcFormatNewLineBeforeElse: boolean | undefined; - vcFormatNewLineBeforeWhileInDoWhile: boolean | undefined; - vcFormatNewLineCloseBraceSameLineEmptyType: boolean | undefined; - vcFormatNewLineCloseBraceSameLineEmptyFunction: boolean | undefined; - vcFormatSpaceWithinParameterListParentheses: boolean | undefined; - vcFormatSpaceBetweenEmptyParameterListParentheses: boolean | undefined; - vcFormatSpaceAfterKeywordsInControlFlowStatements: boolean | undefined; - vcFormatSpaceWithinControlFlowStatementParentheses: boolean | undefined; - vcFormatSpaceBeforeLambdaOpenParenthesis: boolean | undefined; - vcFormatSpaceWithinCastParentheses: boolean | undefined; - vcFormatSpaceAfterCastCloseParenthesis: boolean | undefined; - vcFormatSpaceWithinExpressionParentheses: boolean | undefined; - vcFormatSpaceBeforeBlockOpenBrace: boolean | undefined; - vcFormatSpaceBetweenEmptyBraces: boolean | undefined; - vcFormatSpaceBeforeInitializerListOpenBrace: boolean | undefined; - vcFormatSpaceWithinInitializerListBraces: boolean | undefined; - vcFormatSpacePreserveInInitializerList: boolean | undefined; - vcFormatSpaceBeforeOpenSquareBracket: boolean | undefined; - vcFormatSpaceWithinSquareBrackets: boolean | undefined; - vcFormatSpaceBeforeEmptySquareBrackets: boolean | undefined; - vcFormatSpaceBetweenEmptySquareBrackets: boolean | undefined; - vcFormatSpaceGroupSquareBrackets: boolean | undefined; - vcFormatSpaceWithinLambdaBrackets: boolean | undefined; - vcFormatSpaceBetweenEmptyLambdaBrackets: boolean | undefined; - vcFormatSpaceBeforeComma: boolean | undefined; - vcFormatSpaceAfterComma: boolean | undefined; - vcFormatSpaceRemoveAroundMemberOperators: boolean | undefined; - vcFormatSpaceBeforeInheritanceColon: boolean | undefined; - vcFormatSpaceBeforeConstructorColon: boolean | undefined; - vcFormatSpaceRemoveBeforeSemicolon: boolean | undefined; - vcFormatSpaceInsertAfterSemicolon: boolean | undefined; - vcFormatSpaceRemoveAroundUnaryOperator: boolean | undefined; - vcFormatSpaceBeforeFunctionOpenParenthesis: string | undefined; - vcFormatSpaceAroundBinaryOperator: string | undefined; - vcFormatSpaceAroundAssignmentOperator: string | undefined; - vcFormatSpacePointerReferenceAlignment: string | undefined; - vcFormatSpaceAroundTernaryOperator: string | undefined; - vcFormatWrapPreserveBlocks: string | undefined; - doxygenGenerateOnType: boolean | undefined; - doxygenGeneratedStyle: string | undefined; - doxygenSectionTags: string[] | undefined; - filesExclude: Excludes | undefined; - filesAutoSaveAfterDelay: boolean | undefined; - filesEncoding: string | undefined; + vcFormatIndentCaseLabels: boolean; + vcFormatIndentCaseContents: boolean; + vcFormatIndentCaseContentsWhenBlock: boolean; + vcFormatIndentLambdaBracesWhenParameter: boolean; + vcFormatIndentGotoLabels: string; + vcFormatIndentPreprocessor: string; + vcFormatIndentAccesSpecifiers: boolean; + vcFormatIndentNamespaceContents: boolean; + vcFormatIndentPreserveComments: boolean; + vcFormatNewLineScopeBracesOnSeparateLines: boolean; + vcFormatNewLineBeforeOpenBraceNamespace: string; + vcFormatNewLineBeforeOpenBraceType: string; + vcFormatNewLineBeforeOpenBraceFunction: string; + vcFormatNewLineBeforeOpenBraceBlock: string; + vcFormatNewLineBeforeOpenBraceLambda: string; + vcFormatNewLineBeforeCatch: boolean; + vcFormatNewLineBeforeElse: boolean; + vcFormatNewLineBeforeWhileInDoWhile: boolean; + vcFormatNewLineCloseBraceSameLineEmptyType: boolean; + vcFormatNewLineCloseBraceSameLineEmptyFunction: boolean; + vcFormatSpaceWithinParameterListParentheses: boolean; + vcFormatSpaceBetweenEmptyParameterListParentheses: boolean; + vcFormatSpaceAfterKeywordsInControlFlowStatements: boolean; + vcFormatSpaceWithinControlFlowStatementParentheses: boolean; + vcFormatSpaceBeforeLambdaOpenParenthesis: boolean; + vcFormatSpaceWithinCastParentheses: boolean; + vcFormatSpaceAfterCastCloseParenthesis: boolean; + vcFormatSpaceWithinExpressionParentheses: boolean; + vcFormatSpaceBeforeBlockOpenBrace: boolean; + vcFormatSpaceBetweenEmptyBraces: boolean; + vcFormatSpaceBeforeInitializerListOpenBrace: boolean; + vcFormatSpaceWithinInitializerListBraces: boolean; + vcFormatSpacePreserveInInitializerList: boolean; + vcFormatSpaceBeforeOpenSquareBracket: boolean; + vcFormatSpaceWithinSquareBrackets: boolean; + vcFormatSpaceBeforeEmptySquareBrackets: boolean; + vcFormatSpaceBetweenEmptySquareBrackets: boolean; + vcFormatSpaceGroupSquareBrackets: boolean; + vcFormatSpaceWithinLambdaBrackets: boolean; + vcFormatSpaceBetweenEmptyLambdaBrackets: boolean; + vcFormatSpaceBeforeComma: boolean; + vcFormatSpaceAfterComma: boolean; + vcFormatSpaceRemoveAroundMemberOperators: boolean; + vcFormatSpaceBeforeInheritanceColon: boolean; + vcFormatSpaceBeforeConstructorColon: boolean; + vcFormatSpaceRemoveBeforeSemicolon: boolean; + vcFormatSpaceInsertAfterSemicolon: boolean; + vcFormatSpaceRemoveAroundUnaryOperator: boolean; + vcFormatSpaceBeforeFunctionOpenParenthesis: string; + vcFormatSpaceAroundBinaryOperator: string; + vcFormatSpaceAroundAssignmentOperator: string; + vcFormatSpacePointerReferenceAlignment: string; + vcFormatSpaceAroundTernaryOperator: string; + vcFormatWrapPreserveBlocks: string; + doxygenGenerateOnType: boolean; + doxygenGeneratedStyle: string; + doxygenSectionTags: string[]; + filesExclude: Excludes; + filesAutoSaveAfterDelay: boolean; + filesEncoding: string; searchExclude: Excludes | undefined; - editorAutoClosingBrackets: string | undefined; - editorInlayHintsEnabled: boolean | undefined; - editorParameterHintsEnabled: boolean | undefined; - refactoringIncludeHeader: string | undefined; + editorAutoClosingBrackets: string; + editorInlayHintsEnabled: boolean; + editorParameterHintsEnabled: boolean; + refactoringIncludeHeader: string; } export interface SettingsParams { - filesAssociations: { [key: string]: string } | undefined; - workspaceFallbackEncoding: string | undefined; - maxConcurrentThreads: number | null | undefined; - maxCachedProcesses: number | null | undefined; - maxMemory: number | null | undefined; - maxSymbolSearchResults: number | undefined; - loggingLevel: string | undefined; - workspaceParsingPriority: string | undefined; - workspaceSymbols: string | undefined; - simplifyStructuredComments: boolean | undefined; - intelliSenseUpdateDelay: number | undefined; - experimentalFeatures: boolean | undefined; - enhancedColorization: boolean | undefined; - intellisenseMaxCachedProcesses: number | null | undefined; - intellisenseMaxMemory: number | null | undefined; - referencesMaxConcurrentThreads: number | null | undefined; - referencesMaxCachedProcesses: number | null | undefined; - referencesMaxMemory: number | null | undefined; - codeAnalysisMaxConcurrentThreads: number | null | undefined; - codeAnalysisMaxMemory: number | null | undefined; - codeAnalysisUpdateDelay: number | undefined; + filesAssociations: { [key: string]: string }; + workspaceFallbackEncoding: string; + maxConcurrentThreads: number | null; + maxCachedProcesses: number | null; + maxMemory: number | null; + maxSymbolSearchResults: number; + loggingLevel: string; + workspaceParsingPriority: string; + workspaceSymbols: string; + simplifyStructuredComments: boolean; + intelliSenseUpdateDelay: number; + experimentalFeatures: boolean; + enhancedColorization: boolean; + intellisenseMaxCachedProcesses: number | null; + intellisenseMaxMemory: number | null; + referencesMaxConcurrentThreads: number | null; + referencesMaxCachedProcesses: number | null; + referencesMaxMemory: number | null; + codeAnalysisMaxConcurrentThreads: number | null; + codeAnalysisMaxMemory: number | null; + codeAnalysisUpdateDelay: number; workspaceFolderSettings: WorkspaceFolderSettingsParams[]; } @@ -856,34 +856,55 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString?: string): string | undefined { + private getVSCodeSettingAsString(settingName: string, setting: string, resource: any): string; + private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string): string; + private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string = ''): string { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); + if (isString(value)) { return value; } + const config = fullConfiguration.inspect(setting); - return config?.defaultValue ?? defaultString; + + if (config?.defaultValue !== undefined) { + return config.defaultValue; + } + + return defaultString; } - private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean?: boolean): boolean | undefined { + private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any): boolean; + private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean): boolean; + private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean = false): boolean { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); if (isBoolean(value)) { return value; } const config = fullConfiguration.inspect(setting); - return config?.defaultValue ?? defaultBoolean; + if (config?.defaultValue !== undefined) { + return config.defaultValue; + } + + return defaultBoolean; } - private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber?: number): number | undefined { + private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any): number; + private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number): number; + private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number = 0): number { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); if (isNumber(value)) { return value; } const config = fullConfiguration.inspect(setting); - return config?.defaultValue ?? defaultNumber; + if (config?.defaultValue !== undefined) { + return config.defaultValue; + } + + return defaultNumber; } private getVSCodeSettingAsKeyValueObject(settingName: string, setting: string, keyType: string, valueType: string, resource?: any): any { @@ -897,18 +918,18 @@ export class OtherSettings { } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. - public get editorTabSize(): number | undefined { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } - public get editorInsertSpaces(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource); } - public get editorAutoClosingBrackets(): string | undefined { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource); } - public get filesEncoding(): string | undefined { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }); } + public get editorTabSize(): number { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } + public get editorInsertSpaces(): boolean { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource); } + public get editorAutoClosingBrackets(): string { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource); } + public get filesEncoding(): string { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }); } public get filesAssociations(): any { return this.getVSCodeSettingAsKeyValueObject("files", "associations", "string", "string"); } public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } - public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return this.getVSCodeSettingAsKeyValueObject("files", "exclude", "string", "boolean", this.resource); } + public get filesExclude(): vscode.WorkspaceConfiguration { return this.getVSCodeSettingAsKeyValueObject("files", "exclude", "string", "boolean", this.resource); } public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource) === "afterDelay"; } public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource) !== "off"; } - public get editorParameterHintsEnabled(): boolean | undefined { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } + public get editorParameterHintsEnabled(): boolean { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } - public get workbenchSettingsEditor(): string | undefined { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource); } + public get workbenchSettingsEditor(): string { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource); } } function mapIndentationReferenceToEditorConfig(value: string | undefined): string { From 6f48a0546b0618ce857d00a40b0ec7e191d2b829 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 15 Jul 2024 17:07:35 -0700 Subject: [PATCH 16/52] Refactor unnessecary overloads caught by linter --- Extension/src/LanguageServer/settings.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 5c70282f46..8c2422d1d3 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -856,8 +856,6 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(settingName: string, setting: string, resource: any): string; - private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string): string; private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string = ''): string { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); @@ -875,8 +873,6 @@ export class OtherSettings { return defaultString; } - private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any): boolean; - private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean): boolean; private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean = false): boolean { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); @@ -891,8 +887,6 @@ export class OtherSettings { return defaultBoolean; } - private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any): number; - private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number): number; private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number = 0): number { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); From 945b77f743259dd6595aa606974cc2fc90412fa4 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Tue, 16 Jul 2024 10:02:14 -0700 Subject: [PATCH 17/52] minor changes --- Extension/src/LanguageServer/settings.ts | 19 +++---------------- Extension/src/common.ts | 8 ++++---- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 8c2422d1d3..660a4f49d0 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -865,12 +865,7 @@ export class OtherSettings { } const config = fullConfiguration.inspect(setting); - - if (config?.defaultValue !== undefined) { - return config.defaultValue; - } - - return defaultString; + return config?.defaultValue ?? defaultString; } private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean = false): boolean { @@ -880,11 +875,7 @@ export class OtherSettings { return value; } const config = fullConfiguration.inspect(setting); - if (config?.defaultValue !== undefined) { - return config.defaultValue; - } - - return defaultBoolean; + return config?.defaultValue ?? defaultBoolean; } private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number = 0): number { @@ -894,11 +885,7 @@ export class OtherSettings { return value; } const config = fullConfiguration.inspect(setting); - if (config?.defaultValue !== undefined) { - return config.defaultValue; - } - - return defaultNumber; + return config?.defaultValue ?? defaultNumber; } private getVSCodeSettingAsKeyValueObject(settingName: string, setting: string, keyType: string, valueType: string, resource?: any): any { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 73afb12560..247aee538d 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -335,11 +335,11 @@ export function isArrayOfString(input: any): input is string[] { // Validates whether the given object is a valid mapping of key and value type. // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. -export function isValidMapping(value: any, keyType: string, valueType: string): boolean { - if (value === undefined || value === null) { - return false; +export function isValidMapping(value: any, keyType: string, valueType: string): value is object { + if (isObject(value)) { + return Object.entries(value).every(([key, val]) => typeof key === keyType && typeof val === valueType); } - return Object.entries(value).every(([key, val]) => typeof key === keyType && typeof val === valueType); + return false; } export function isOptionalArrayOfString(input: any): input is string[] | undefined { From c9b50ca8b3803afea3d5b12f27bc2e33fe9a57ce Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 16 Jul 2024 13:07:12 -0700 Subject: [PATCH 18/52] Update the default values for editor settings and make them required. --- Extension/src/LanguageServer/settings.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 660a4f49d0..c8e02ae930 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -856,7 +856,7 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string = ''): string { + private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string): string { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); @@ -868,7 +868,7 @@ export class OtherSettings { return config?.defaultValue ?? defaultString; } - private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean = false): boolean { + private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean): boolean { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); if (isBoolean(value)) { @@ -878,7 +878,7 @@ export class OtherSettings { return config?.defaultValue ?? defaultBoolean; } - private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number = 0): number { + private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number): number { const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); const value = fullConfiguration.get(setting); if (isNumber(value)) { @@ -900,17 +900,17 @@ export class OtherSettings { // All default values are obtained from the VS Code settings UI. Please update the default values as needed. public get editorTabSize(): number { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } - public get editorInsertSpaces(): boolean { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource); } - public get editorAutoClosingBrackets(): string { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource); } - public get filesEncoding(): string { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }); } + public get editorInsertSpaces(): boolean { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } + public get editorAutoClosingBrackets(): string { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } + public get filesEncoding(): string { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "utf8"); } public get filesAssociations(): any { return this.getVSCodeSettingAsKeyValueObject("files", "associations", "string", "string"); } public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } public get filesExclude(): vscode.WorkspaceConfiguration { return this.getVSCodeSettingAsKeyValueObject("files", "exclude", "string", "boolean", this.resource); } - public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource) === "afterDelay"; } - public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource) !== "off"; } - public get editorParameterHintsEnabled(): boolean { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource); } + public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } + public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } + public get editorParameterHintsEnabled(): boolean { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource , true); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } - public get workbenchSettingsEditor(): string { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource); } + public get workbenchSettingsEditor(): string { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource, "ui"); } } function mapIndentationReferenceToEditorConfig(value: string | undefined): string { From 74074666f0a1e72baecb4896770ebd640c01b85f Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 16 Jul 2024 13:07:52 -0700 Subject: [PATCH 19/52] Fix lint issues --- Extension/src/LanguageServer/settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index c8e02ae930..a665314750 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -908,7 +908,7 @@ export class OtherSettings { public get filesExclude(): vscode.WorkspaceConfiguration { return this.getVSCodeSettingAsKeyValueObject("files", "exclude", "string", "boolean", this.resource); } public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } - public get editorParameterHintsEnabled(): boolean { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource , true); } + public get editorParameterHintsEnabled(): boolean { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource, true); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } public get workbenchSettingsEditor(): string { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource, "ui"); } } From 3eaecdb1bcdba1f1b2f640e1bbd0a23129d88663 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 16 Jul 2024 15:32:47 -0700 Subject: [PATCH 20/52] Remove unused TextMateRule interface, Refactor KeyValueObject validation + minor fixes and renames --- Extension/src/LanguageServer/settings.ts | 120 +++++++++++++---------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index a665314750..1311fef3f6 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -28,6 +28,10 @@ export interface Excludes { [key: string]: (boolean | { when: string }); } +export interface Associations { + [key: string]: string; +} + export interface WorkspaceFolderSettingsParams { uri: string | undefined; intelliSenseEngine: string; @@ -134,7 +138,7 @@ export interface WorkspaceFolderSettingsParams { } export interface SettingsParams { - filesAssociations: { [key: string]: string }; + filesAssociations: Associations; workspaceFallbackEncoding: string; maxConcurrentThreads: number | null; maxCachedProcesses: number | null; @@ -349,8 +353,11 @@ export class CppSettings extends Settings { return null; } const setting = getRawSetting("C_Cpp." + settingName); + if (value === null){ + return setting.default; + } // Validates the value is a number and falls within the specified range. Allows for undefined maximum or minimum values. - if ((isNumber(value) || value === null) && (setting.minimum === undefined || value >= setting.minimum) && (setting.maximum === undefined || value <= setting.maximum)) { + if (isNumber(value) && (setting.minimum === undefined || value >= setting.minimum) && (setting.maximum === undefined || value <= setting.maximum)) { return value; } return setting.default; @@ -373,14 +380,22 @@ export class CppSettings extends Settings { return setting.default; } - // Returns the value of a setting as a key-value object with proper type validation. - private getAsKeyValueObject(settingName: string, keyType: string, valueType: string): any { + private getAsExcludes(settingName: string): Excludes { const value: any = super.Section.get(settingName); - if (isValidMapping(value, keyType, valueType)) { - return value; + if (isValidMapping(value, 'string', 'boolean')) { + return value as Excludes; } const setting = getRawSetting("C_Cpp." + settingName); - return setting.default; + return setting.default as Excludes; + } + + private getAsAssociations(settingName: string): Associations { + const value: any = super.Section.get(settingName); + if (isValidMapping(value, 'string', 'string')) { + return value as Associations; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default as Associations; } // Checks a given enum value against a list of valid enum values from package.json. @@ -420,7 +435,7 @@ export class CppSettings extends Settings { public get codeAnalysisMaxConcurrentThreads(): number | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads", true); } public get codeAnalysisMaxMemory(): number | null { return this.getAsNumber("codeAnalysis.maxMemory", true); } public get codeAnalysisUpdateDelay(): number { return this.getAsNumber("codeAnalysis.updateDelay"); } - public get codeAnalysisExclude(): Excludes { return this.getAsKeyValueObject("codeAnalysis.exclude", "string", "boolean"); } + public get codeAnalysisExclude(): Excludes { return this.getAsExcludes("codeAnalysis.exclude"); } public get codeAnalysisRunAutomatically(): boolean { return this.getAsBoolean("codeAnalysis.runAutomatically"); } public get codeAnalysisRunOnBuild(): boolean { return this.getAsBoolean("codeAnalysis.runOnBuild"); } public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } @@ -484,7 +499,7 @@ export class CppSettings extends Settings { public get isVcpkgEnabled(): boolean { return this.getAsString("vcpkg").toLowerCase() === "enabled"; } public get addNodeAddonIncludePaths(): boolean { return this.getAsBoolean("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean { return this.getAsBoolean("renameRequiresIdentifier"); } - public get filesExclude(): Excludes { return this.getAsKeyValueObject("files.exclude", "string", "boolean"); } + public get filesExclude(): Excludes { return this.getAsExcludes("files.exclude"); } public get defaultIncludePath(): string[] { return this.getAsArrayOfStrings("default.includePath"); } public get defaultDefines(): string[] { return this.getAsArrayOfStrings("default.defines"); } public get defaultDotconfig(): string { return this.getAsString("default.dotConfig"); } @@ -525,7 +540,7 @@ export class CppSettings extends Settings { public get defaultLimitSymbolsToIncludedHeaders(): boolean { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } public get defaultSystemIncludePath(): string[] { return this.getAsArrayOfStrings("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - public get defaultCustomConfigurationVariables(): { [key: string]: string } { return this.getAsKeyValueObject("default.customConfigurationVariables", "string", "string"); } + public get defaultCustomConfigurationVariables(): Associations { return this.getAsAssociations("default.customConfigurationVariables"); } public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } public get codeFolding(): boolean { return this.getAsString("codeFolding").toLowerCase() === "enabled"; } public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport").toLowerCase() === "enabled"; } @@ -835,17 +850,6 @@ export class CppSettings extends Settings { } } -export interface TextMateRuleSettings { - foreground?: string; - background?: string; - fontStyle?: string; -} - -export interface TextMateRule { - scope: string[]; - settings: TextMateRuleSettings; -} - export class OtherSettings { private resource: vscode.Uri | undefined; @@ -856,61 +860,71 @@ export class OtherSettings { this.resource = resource; } - private getVSCodeSettingAsString(settingName: string, setting: string, resource: any, defaultString: string): string { - const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); - const value = fullConfiguration.get(setting); + private getAsString(sectionName: string, settingName: string, resource: any, defaultString: string): string { + const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); + const value = fullConfiguration.get(settingName); if (isString(value)) { return value; } - const config = fullConfiguration.inspect(setting); - return config?.defaultValue ?? defaultString; + const section = fullConfiguration.inspect(settingName); + return section ?.defaultValue ?? defaultString; } - private getVSCodeSettingAsBoolean(settingName: string, setting: string, resource: any, defaultBoolean: boolean): boolean { - const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); - const value = fullConfiguration.get(setting); + private getAsBoolean(sectionName: string, settingName: string, resource: any, defaultBoolean: boolean): boolean { + const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); + const value = fullConfiguration.get(settingName); if (isBoolean(value)) { return value; } - const config = fullConfiguration.inspect(setting); - return config?.defaultValue ?? defaultBoolean; + const section = fullConfiguration.inspect(settingName); + return section ?.defaultValue ?? defaultBoolean; } - private getVSCodeSettingAsNumber(settingName: string, setting: string, resource: any, defaultNumber: number): number { - const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); - const value = fullConfiguration.get(setting); + private getAsNumber(sectionName: string, settingName: string, resource: any, defaultNumber: number): number { + const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); + const value = fullConfiguration.get(settingName); if (isNumber(value)) { return value; } - const config = fullConfiguration.inspect(setting); - return config?.defaultValue ?? defaultNumber; + const section = fullConfiguration.inspect(settingName); + return section ?.defaultValue ?? defaultNumber; } - private getVSCodeSettingAsKeyValueObject(settingName: string, setting: string, keyType: string, valueType: string, resource?: any): any { - const fullConfiguration = vscode.workspace.getConfiguration(settingName, resource); - const value = fullConfiguration.get(setting); - if (isValidMapping(value, keyType, valueType)) { - return value; + private getAsAssociations(sectionName: string, settingName: string, resource?: any): Associations { + const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); + const value = fullConfiguration.get(settingName); + if (isValidMapping(value, 'string', 'string')) { + return value as Associations; + } + const section = fullConfiguration.inspect(settingName); + return section ?.defaultValue as Associations; + } + + private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { + const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); + const value = fullConfiguration.get(settingName); + if (isValidMapping(value, 'string', 'boolean')) { + return value as Excludes; } - const config = fullConfiguration.inspect(setting); - return config?.defaultValue; + const section = fullConfiguration.inspect(settingName); + return section ?.defaultValue as Excludes; } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. - public get editorTabSize(): number { return this.getVSCodeSettingAsNumber("editor", "tabSize", this.resource, 4); } - public get editorInsertSpaces(): boolean { return this.getVSCodeSettingAsBoolean("editor", "insertSpaces", this.resource, true); } - public get editorAutoClosingBrackets(): string { return this.getVSCodeSettingAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } - public get filesEncoding(): string { return this.getVSCodeSettingAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "utf8"); } - public get filesAssociations(): any { return this.getVSCodeSettingAsKeyValueObject("files", "associations", "string", "string"); } + public get editorTabSize(): number { return this.getAsNumber("editor", "tabSize", this.resource, 4); } + public get editorInsertSpaces(): boolean { return this.getAsBoolean("editor", "insertSpaces", this.resource, true); } + public get editorAutoClosingBrackets(): string { return this.getAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } + public get filesEncoding(): string { return this.getAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "utf8"); } + public get filesAssociations(): Associations { return this.getAsAssociations("files", "associations"); } public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } - public get filesExclude(): vscode.WorkspaceConfiguration { return this.getVSCodeSettingAsKeyValueObject("files", "exclude", "string", "boolean", this.resource); } - public get filesAutoSaveAfterDelay(): boolean { return this.getVSCodeSettingAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } - public get editorInlayHintsEnabled(): boolean { return this.getVSCodeSettingAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } - public get editorParameterHintsEnabled(): boolean { return this.getVSCodeSettingAsBoolean("editor.parameterHints", "enabled", this.resource, true); } + public get filesExclude(): Excludes { return this.getAsExcludes("files", "exclude", this.resource); } + public get filesAutoSaveAfterDelay(): boolean { return this.getAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } + public get editorInlayHintsEnabled(): boolean { return this.getAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } + public get editorParameterHintsEnabled(): boolean { return this.getAsBoolean("editor.parameterHints", "enabled", this.resource, true); } public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } - public get workbenchSettingsEditor(): string { return this.getVSCodeSettingAsString("workbench.settings", "editor", this.resource, "ui"); } + public get workbenchSettingsEditor(): string { return this.getAsString("workbench.settings", "editor", this.resource, "ui"); } } function mapIndentationReferenceToEditorConfig(value: string | undefined): string { From f0e0e347d714cc876a951c561c005560658bb4b4 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 16 Jul 2024 15:33:15 -0700 Subject: [PATCH 21/52] Fix lint issues --- Extension/src/LanguageServer/settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 1311fef3f6..8403d96e3b 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -353,7 +353,7 @@ export class CppSettings extends Settings { return null; } const setting = getRawSetting("C_Cpp." + settingName); - if (value === null){ + if (value === null) { return setting.default; } // Validates the value is a number and falls within the specified range. Allows for undefined maximum or minimum values. From 728a9911e309f4172bc893656f5f046c132cab09 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 17 Jul 2024 13:43:12 -0700 Subject: [PATCH 22/52] Use clamping to process min and max value, add null types + minor refactoring. --- .../src/LanguageServer/configurations.ts | 30 +++--- Extension/src/LanguageServer/settings.ts | 93 ++++++++++++------- 2 files changed, 74 insertions(+), 49 deletions(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 02a76906f3..a630687362 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -988,7 +988,7 @@ export class CppProperties { } else { // However, if compileCommands are used and compilerPath is explicitly set, it's still necessary to resolve variables in it. if (configuration.compilerPath === "${default}") { - configuration.compilerPath = settings.defaultCompilerPath; + configuration.compilerPath = settings.defaultCompilerPath ?? undefined; } if (configuration.compilerPath === null) { configuration.compilerPath = undefined; @@ -1001,7 +1001,9 @@ export class CppProperties { } } - configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); + if (settings.defaultCustomConfigurationVariables !== null) { + configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); + } configuration.configurationProvider = this.updateConfigurationString(configuration.configurationProvider, settings.defaultConfigurationProvider, env); if (!configuration.browse) { @@ -1023,7 +1025,9 @@ export class CppProperties { configuration.browse.path = ["${workspaceFolder}"]; } } else { - configuration.browse.path = this.updateConfigurationPathsArray(configuration.browse.path, settings.defaultBrowsePath, env); + if (settings.defaultBrowsePath) { + configuration.browse.path = this.updateConfigurationPathsArray(configuration.browse.path, settings.defaultBrowsePath, env); + } } configuration.browse.limitSymbolsToIncludedHeaders = this.updateConfigurationStringOrBoolean(configuration.browse.limitSymbolsToIncludedHeaders, settings.defaultLimitSymbolsToIncludedHeaders, env); @@ -1640,15 +1644,15 @@ export class CppProperties { } // Validate paths (directories) - errors.includePath = this.validatePath(config.includePath, {globPaths: true}); + errors.includePath = this.validatePath(config.includePath, { globPaths: true }); errors.macFrameworkPath = this.validatePath(config.macFrameworkPath); errors.browsePath = this.validatePath(config.browse ? config.browse.path : undefined); // Validate files - errors.forcedInclude = this.validatePath(config.forcedInclude, {isDirectory: false, assumeRelative: false}); - errors.compileCommands = this.validatePath(config.compileCommands, {isDirectory: false}); - errors.dotConfig = this.validatePath(config.dotConfig, {isDirectory: false}); - errors.databaseFilename = this.validatePath(config.browse ? config.browse.databaseFilename : undefined, {isDirectory: false}); + errors.forcedInclude = this.validatePath(config.forcedInclude, { isDirectory: false, assumeRelative: false }); + errors.compileCommands = this.validatePath(config.compileCommands, { isDirectory: false }); + errors.dotConfig = this.validatePath(config.dotConfig, { isDirectory: false }); + errors.databaseFilename = this.validatePath(config.browse ? config.browse.databaseFilename : undefined, { isDirectory: false }); // Validate intelliSenseMode if (isWindows) { @@ -1661,7 +1665,7 @@ export class CppProperties { return errors; } - private validatePath(input: string | string[] | undefined, {isDirectory = true, assumeRelative = true, globPaths = false} = {}): string | undefined { + private validatePath(input: string | string[] | undefined, { isDirectory = true, assumeRelative = true, globPaths = false } = {}): string | undefined { if (!input) { return undefined; } @@ -1877,8 +1881,8 @@ export class CppProperties { // Check for path-related squiggles. const paths: string[] = []; let compilerPath: string | undefined; - for (const pathArray of [ currentConfiguration.browse ? currentConfiguration.browse.path : undefined, - currentConfiguration.includePath, currentConfiguration.macFrameworkPath ]) { + for (const pathArray of [currentConfiguration.browse ? currentConfiguration.browse.path : undefined, + currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { if (pathArray) { for (const curPath of pathArray) { paths.push(`${curPath}`); @@ -2075,7 +2079,7 @@ export class CppProperties { let message: string = ""; if (!pathExists) { if (curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd - && !path.isAbsolute(expandedPaths[0])) { + && !path.isAbsolute(expandedPaths[0])) { continue; // Skip the error, because it could be resolved recursively. } let badPath = ""; @@ -2089,7 +2093,7 @@ export class CppProperties { } else { // Check for file versus path mismatches. if ((curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd) || - (curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd)) { + (curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd)) { if (expandedPaths.length > 1) { message = localize("multiple.paths.not.allowed", "Multiple paths are not allowed."); newSquiggleMetrics.MultiplePathsNotAllowed++; diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 8403d96e3b..af829abe1f 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -356,8 +356,14 @@ export class CppSettings extends Settings { if (value === null) { return setting.default; } - // Validates the value is a number and falls within the specified range. Allows for undefined maximum or minimum values. - if (isNumber(value) && (setting.minimum === undefined || value >= setting.minimum) && (setting.maximum === undefined || value <= setting.maximum)) { + // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. + if (isNumber(value)) { + if (setting.minimum !== undefined && value < setting.minimum) { + return setting.minimum; + } + if (setting.maximum !== undefined && value > setting.maximum) { + return setting.maximum; + } return value; } return setting.default; @@ -380,8 +386,13 @@ export class CppSettings extends Settings { return setting.default; } - private getAsExcludes(settingName: string): Excludes { + private getAsExcludes(settingName: string): Excludes; + private getAsExcludes(settingName: string, allowNull: boolean): Excludes | null; + private getAsExcludes(settingName: string, allowNull: boolean = false): Excludes | null { const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } if (isValidMapping(value, 'string', 'boolean')) { return value as Excludes; } @@ -389,8 +400,13 @@ export class CppSettings extends Settings { return setting.default as Excludes; } - private getAsAssociations(settingName: string): Associations { + private getAsAssociations(settingName: string): Associations; + private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; + private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } if (isValidMapping(value, 'string', 'string')) { return value as Associations; } @@ -426,11 +442,11 @@ export class CppSettings extends Settings { public get maxConcurrentThreads(): number | null { return this.getAsNumber("maxConcurrentThreads", true); } public get maxMemory(): number | null { return this.getAsNumber("maxMemory", true); } public get maxSymbolSearchResults(): number { return this.getAsNumber("maxSymbolSearchResults"); } - public get maxCachedProcesses(): number { return this.getAsNumber("maxCachedProcesses"); } + public get maxCachedProcesses(): number | null { return this.getAsNumber("maxCachedProcesses", true); } public get intelliSenseMaxCachedProcesses(): number | null { return this.getAsNumber("intelliSense.maxCachedProcesses", true); } public get intelliSenseMaxMemory(): number | null { return this.getAsNumber("intelliSense.maxMemory", true); } public get referencesMaxConcurrentThreads(): number | null { return this.getAsNumber("references.maxConcurrentThreads", true); } - public get referencesMaxCachedProcesses(): number { return this.getAsNumber("references.maxCachedProcesses"); } + public get referencesMaxCachedProcesses(): number | null { return this.getAsNumber("references.maxCachedProcesses", true); } public get referencesMaxMemory(): number | null { return this.getAsNumber("references.maxMemory", true); } public get codeAnalysisMaxConcurrentThreads(): number | null { return this.getAsNumber("codeAnalysis.maxConcurrentThreads", true); } public get codeAnalysisMaxMemory(): number | null { return this.getAsNumber("codeAnalysis.maxMemory", true); } @@ -508,7 +524,7 @@ export class CppSettings extends Settings { public get defaultCompileCommands(): string { return this.getAsString("default.compileCommands"); } public get defaultForcedInclude(): string[] { return this.getAsArrayOfStrings("default.forcedInclude"); } public get defaultIntelliSenseMode(): string { return this.getAsString("default.intelliSenseMode"); } - public get defaultCompilerPath(): string { return this.getAsString("default.compilerPath") ?? undefined; } + public get defaultCompilerPath(): string | null { return this.getAsString("default.compilerPath", true) ?? null; } public set defaultCompilerPath(value: string) { const defaultCompilerPathStr: string = "default.compilerPath"; @@ -535,12 +551,12 @@ export class CppSettings extends Settings { public get defaultCppStandard(): string { return this.getAsString("default.cppStandard"); } public get defaultConfigurationProvider(): string { return this.getAsString("default.configurationProvider"); } public get defaultMergeConfigurations(): boolean { return this.getAsBoolean("default.mergeConfigurations"); } - public get defaultBrowsePath(): string[] { return this.getAsArrayOfStrings("default.browse.path") ?? undefined; } + public get defaultBrowsePath(): string[] | null { return this.getAsArrayOfStrings("default.browse.path", true); } public get defaultDatabaseFilename(): string { return this.getAsString("default.browse.databaseFilename"); } public get defaultLimitSymbolsToIncludedHeaders(): boolean { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } public get defaultSystemIncludePath(): string[] { return this.getAsArrayOfStrings("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - public get defaultCustomConfigurationVariables(): Associations { return this.getAsAssociations("default.customConfigurationVariables"); } + public get defaultCustomConfigurationVariables(): Associations | null { return this.getAsAssociations("default.customConfigurationVariables", true); } public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } public get codeFolding(): boolean { return this.getAsString("codeFolding").toLowerCase() === "enabled"; } public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport").toLowerCase() === "enabled"; } @@ -860,60 +876,65 @@ export class OtherSettings { this.resource = resource; } - private getAsString(sectionName: string, settingName: string, resource: any, defaultString: string): string { - const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); - const value = fullConfiguration.get(settingName); - + private getAsString(sectionName: string, settingName: string, resource: any, defaultValue: string): string { + const section = vscode.workspace.getConfiguration(sectionName, resource); + const value = section.get(settingName); if (isString(value)) { return value; } - - const section = fullConfiguration.inspect(settingName); - return section ?.defaultValue ?? defaultString; + const setting = section.inspect(settingName); + return setting?.defaultValue ?? defaultValue; } - private getAsBoolean(sectionName: string, settingName: string, resource: any, defaultBoolean: boolean): boolean { - const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); - const value = fullConfiguration.get(settingName); + private getAsBoolean(sectionName: string, settingName: string, resource: any, defaultValue: boolean): boolean { + const section = vscode.workspace.getConfiguration(sectionName, resource); + const value = section.get(settingName); if (isBoolean(value)) { return value; } - const section = fullConfiguration.inspect(settingName); - return section ?.defaultValue ?? defaultBoolean; + const setting = section.inspect(settingName); + return setting?.defaultValue ?? defaultValue; } - private getAsNumber(sectionName: string, settingName: string, resource: any, defaultNumber: number): number { - const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); - const value = fullConfiguration.get(settingName); + private getAsNumber(sectionName: string, settingName: string, resource: any, defaultValue: number, minimum?: number, maximum?: number): number { + const section = vscode.workspace.getConfiguration(sectionName, resource); + const value = section.get(settingName); + // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. if (isNumber(value)) { + if (minimum !== undefined && value < minimum) { + return minimum; + } + if (maximum !== undefined && value > maximum) { + return maximum; + } return value; } - const section = fullConfiguration.inspect(settingName); - return section ?.defaultValue ?? defaultNumber; + const setting = section.inspect(settingName); + return setting?.defaultValue ?? defaultValue; } private getAsAssociations(sectionName: string, settingName: string, resource?: any): Associations { - const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); - const value = fullConfiguration.get(settingName); + const section = vscode.workspace.getConfiguration(sectionName, resource); + const value = section.get(settingName); if (isValidMapping(value, 'string', 'string')) { return value as Associations; } - const section = fullConfiguration.inspect(settingName); - return section ?.defaultValue as Associations; + const setting = section.inspect(settingName); + return setting?.defaultValue as Associations; } private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { - const fullConfiguration = vscode.workspace.getConfiguration(sectionName, resource); - const value = fullConfiguration.get(settingName); + const section = vscode.workspace.getConfiguration(sectionName, resource); + const value = section.get(settingName); if (isValidMapping(value, 'string', 'boolean')) { return value as Excludes; } - const section = fullConfiguration.inspect(settingName); - return section ?.defaultValue as Excludes; + const setting = section.inspect(settingName); + return setting?.defaultValue as Excludes; } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. - public get editorTabSize(): number { return this.getAsNumber("editor", "tabSize", this.resource, 4); } + public get editorTabSize(): number { return this.getAsNumber("editor", "tabSize", this.resource, 4, 1); } public get editorInsertSpaces(): boolean { return this.getAsBoolean("editor", "insertSpaces", this.resource, true); } public get editorAutoClosingBrackets(): string { return this.getAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } public get filesEncoding(): string { return this.getAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "utf8"); } @@ -923,7 +944,7 @@ export class OtherSettings { public get filesAutoSaveAfterDelay(): boolean { return this.getAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } public get editorInlayHintsEnabled(): boolean { return this.getAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } public get editorParameterHintsEnabled(): boolean { return this.getAsBoolean("editor.parameterHints", "enabled", this.resource, true); } - public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); } + public get searchExclude(): Excludes { return this.getAsExcludes("search", "exclude", this.resource); } public get workbenchSettingsEditor(): string { return this.getAsString("workbench.settings", "editor", this.resource, "ui"); } } From 77dcd1761bc36d9e510ccffb70b9a65cde0b65f4 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Thu, 18 Jul 2024 16:22:37 -0700 Subject: [PATCH 23/52] Properly propagate null types from null related settings. --- .../src/LanguageServer/configurations.ts | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index a630687362..4e2b0ab32d 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -71,7 +71,7 @@ export interface Configuration { cStandardIsExplicit?: boolean; cppStandard?: string; cppStandardIsExplicit?: boolean; - includePath?: string[]; + includePath?: string[] | null; macFrameworkPath?: string[]; windowsSdkVersion?: string; dotConfig?: string; @@ -80,7 +80,7 @@ export interface Configuration { intelliSenseModeIsExplicit?: boolean; compileCommandsInCppPropertiesJson?: string; compileCommands?: string; - forcedInclude?: string[]; + forcedInclude?: string[] | null; configurationProviderInCppPropertiesJson?: string; configurationProvider?: string; mergeConfigurations?: boolean; @@ -102,7 +102,7 @@ export interface ConfigurationErrors { } export interface Browse { - path?: string[]; + path?: string[] | null; limitSymbolsToIncludedHeaders?: boolean | string; databaseFilename?: string; } @@ -618,7 +618,7 @@ export class CppProperties { if (config.includePath === undefined) { config.includePath = ["${default}"]; } - config.includePath.splice(config.includePath.length, 0, path); + config.includePath?.splice(config.includePath.length, 0, path); this.writeToJson(); } // Any time parsePropertiesFile is called, configurationJson gets @@ -711,7 +711,7 @@ export class CppProperties { this.onSelectionChanged(); } - private resolveDefaults(entries: string[], defaultValue?: string[]): string[] { + private resolveDefaults(entries: string[], defaultValue?: string[] | null): string[] { let result: string[] = []; entries.forEach(entry => { if (entry === "${default}") { @@ -727,7 +727,7 @@ export class CppProperties { return result; } - private resolveDefaultsDictionary(entries: { [key: string]: string }, defaultValue: { [key: string]: string } | undefined, env: Environment): { [key: string]: string } { + private resolveDefaultsDictionary(entries: { [key: string]: string }, defaultValue: { [key: string]: string } | undefined | null, env: Environment): { [key: string]: string } { const result: { [key: string]: string } = {}; for (const property in entries) { if (property === "${default}") { @@ -758,9 +758,9 @@ export class CppProperties { return result; } - private resolveAndSplit(paths: string[] | undefined, defaultValue: string[] | undefined, env: Environment, assumeRelative: boolean = true, glob: boolean = false): string[] { + private resolveAndSplit(paths: string[] | undefined, defaultValue: string[] | undefined | null, env: Environment, assumeRelative: boolean = true, glob: boolean = false): string[] { const resolvedVariables: string[] = []; - if (paths === undefined) { + if (paths === undefined || paths === null) { return resolvedVariables; } paths = this.resolveDefaults(paths, defaultValue); @@ -841,7 +841,7 @@ export class CppProperties { return property; } - private updateConfigurationPathsArray(paths: string[] | undefined, defaultValue: string[] | undefined, env: Environment, assumeRelative: boolean = true): string[] | undefined { + private updateConfigurationPathsArray(paths: string[] | undefined | null, defaultValue: string[] | undefined | null, env: Environment, assumeRelative: boolean = true): string[] | undefined | null { if (paths) { return this.resolveAndSplit(paths, defaultValue, env, assumeRelative, true); } @@ -876,7 +876,7 @@ export class CppProperties { return property; } - private updateConfigurationStringDictionary(property: { [key: string]: string } | undefined, defaultValue: { [key: string]: string } | undefined, env: Environment): { [key: string]: string } | undefined { + private updateConfigurationStringDictionary(property: { [key: string]: string } | undefined | null, defaultValue: { [key: string]: string } | undefined | null, env: Environment): { [key: string]: string } | undefined { if (!property || Object.keys(property).length === 0) { property = defaultValue; } @@ -921,7 +921,7 @@ export class CppProperties { configuration.configurationProviderInCppPropertiesJson = configuration.configurationProvider; configuration.includePath = this.updateConfigurationPathsArray(configuration.includePath, settings.defaultIncludePath, env); // in case includePath is reset below - const origIncludePath: string[] | undefined = configuration.includePath; + const origIncludePath: string[] | undefined | null = configuration.includePath; if (userSettings.addNodeAddonIncludePaths) { const includePath: string[] = origIncludePath || []; configuration.includePath = includePath.concat(this.nodeAddonIncludes.filter(i => includePath.indexOf(i) < 0)); @@ -987,8 +987,8 @@ export class CppProperties { } } else { // However, if compileCommands are used and compilerPath is explicitly set, it's still necessary to resolve variables in it. - if (configuration.compilerPath === "${default}") { - configuration.compilerPath = settings.defaultCompilerPath ?? undefined; + if (configuration.compilerPath === "${default}" && settings.defaultCompilerPath) { + configuration.compilerPath = settings.defaultCompilerPath; } if (configuration.compilerPath === null) { configuration.compilerPath = undefined; @@ -1001,9 +1001,8 @@ export class CppProperties { } } - if (settings.defaultCustomConfigurationVariables !== null) { - configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); - } + configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); + configuration.configurationProvider = this.updateConfigurationString(configuration.configurationProvider, settings.defaultConfigurationProvider, env); if (!configuration.browse) { @@ -1025,9 +1024,8 @@ export class CppProperties { configuration.browse.path = ["${workspaceFolder}"]; } } else { - if (settings.defaultBrowsePath) { - configuration.browse.path = this.updateConfigurationPathsArray(configuration.browse.path, settings.defaultBrowsePath, env); - } + configuration.browse.path = this.updateConfigurationPathsArray(configuration.browse.path, settings.defaultBrowsePath, env); + } configuration.browse.limitSymbolsToIncludedHeaders = this.updateConfigurationStringOrBoolean(configuration.browse.limitSymbolsToIncludedHeaders, settings.defaultLimitSymbolsToIncludedHeaders, env); @@ -1263,8 +1261,8 @@ export class CppProperties { } } - private trimPathWhitespace(paths: string[] | undefined): string[] | undefined { - if (paths === undefined) { + private trimPathWhitespace(paths: string[] | undefined | null): string[] | undefined { + if (paths === undefined || paths === null) { return undefined; } const trimmedPaths = []; @@ -1665,7 +1663,7 @@ export class CppProperties { return errors; } - private validatePath(input: string | string[] | undefined, { isDirectory = true, assumeRelative = true, globPaths = false } = {}): string | undefined { + private validatePath(input: string | string[] | undefined | null, { isDirectory = true, assumeRelative = true, globPaths = false } = {}): string | undefined { if (!input) { return undefined; } From 64e0d6ea28cf0b66cf33d73c3bcebcc9011d65fa Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 19 Jul 2024 14:36:34 -0700 Subject: [PATCH 24/52] Refactor usage of null and undefined types in settings. --- Extension/src/LanguageServer/client.ts | 6 ++-- .../src/LanguageServer/configurations.ts | 31 ++++++++++--------- .../LanguageServer/cppBuildTaskProvider.ts | 2 +- Extension/src/LanguageServer/settings.ts | 4 +-- Extension/src/common.ts | 6 ++-- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 6d56e4538f..33cc5cd65c 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1338,7 +1338,7 @@ export class DefaultClient implements Client { defaultSystemIncludePath: settings.defaultSystemIncludePath, cppFilesExclude: settings.filesExclude, clangFormatPath: util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment), - clangFormatStyle: settings.clangFormatStyle ? util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment) : undefined, + clangFormatStyle: util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment), clangFormatFallbackStyle: settings.clangFormatFallbackStyle, clangFormatSortIncludes: settings.clangFormatSortIncludes, codeAnalysisRunAutomatically: settings.codeAnalysisRunAutomatically, @@ -3052,7 +3052,7 @@ export class DefaultClient implements Client { providerVersion < Version.v6, itemConfig.compilerPath, util.isArrayOfString(itemConfig.compilerArgs) ? itemConfig.compilerArgs : undefined); - itemConfig.compilerPath = compilerPathAndArgs.compilerPath; + itemConfig.compilerPath = compilerPathAndArgs.compilerPath ?? undefined; if (itemConfig.compilerPath !== undefined) { void this.addTrustedCompiler(itemConfig.compilerPath).catch(logAndReturn.undefined); } @@ -3156,7 +3156,7 @@ export class DefaultClient implements Client { providerVersion < Version.v6, sanitized.compilerPath, util.isArrayOfString(sanitized.compilerArgs) ? sanitized.compilerArgs : undefined); - sanitized.compilerPath = compilerPathAndArgs.compilerPath; + sanitized.compilerPath = compilerPathAndArgs.compilerPath ?? undefined; if (sanitized.compilerPath !== undefined) { void this.addTrustedCompiler(sanitized.compilerPath).catch(logAndReturn.undefined); } diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 4e2b0ab32d..ec1a6443b5 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -62,8 +62,8 @@ export interface ConfigurationJson { export interface Configuration { name: string; - compilerPathInCppPropertiesJson?: string; - compilerPath?: string; + compilerPathInCppPropertiesJson?: string | null; + compilerPath?: string | null; compilerPathIsExplicit?: boolean; compilerArgs?: string[]; compilerArgsLegacy?: string[]; @@ -71,7 +71,7 @@ export interface Configuration { cStandardIsExplicit?: boolean; cppStandard?: string; cppStandardIsExplicit?: boolean; - includePath?: string[] | null; + includePath?: string[]; macFrameworkPath?: string[]; windowsSdkVersion?: string; dotConfig?: string; @@ -594,7 +594,7 @@ export class CppProperties { configuration.intelliSenseMode === "${default}") { return ""; } - const resolvedCompilerPath: string = this.resolvePath(configuration.compilerPath); + const resolvedCompilerPath: string = this.resolvePath(configuration.compilerPath ?? undefined ); const settings: CppSettings = new CppSettings(this.rootUri); const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(!!settings.legacyCompilerArgsBehavior, resolvedCompilerPath); @@ -618,7 +618,7 @@ export class CppProperties { if (config.includePath === undefined) { config.includePath = ["${default}"]; } - config.includePath?.splice(config.includePath.length, 0, path); + config.includePath.splice(config.includePath.length, 0, path); this.writeToJson(); } // Any time parsePropertiesFile is called, configurationJson gets @@ -841,7 +841,10 @@ export class CppProperties { return property; } - private updateConfigurationPathsArray(paths: string[] | undefined | null, defaultValue: string[] | undefined | null, env: Environment, assumeRelative: boolean = true): string[] | undefined | null { + private updateConfigurationPathsArray(paths: string[] | undefined | null, defaultValue: string[] | undefined | null, env: Environment, assumeRelative: boolean = true): string[] | undefined { + if (paths === null) { + return undefined; + } if (paths) { return this.resolveAndSplit(paths, defaultValue, env, assumeRelative, true); } @@ -921,7 +924,7 @@ export class CppProperties { configuration.configurationProviderInCppPropertiesJson = configuration.configurationProvider; configuration.includePath = this.updateConfigurationPathsArray(configuration.includePath, settings.defaultIncludePath, env); // in case includePath is reset below - const origIncludePath: string[] | undefined | null = configuration.includePath; + const origIncludePath: string[] | undefined = configuration.includePath; if (userSettings.addNodeAddonIncludePaths) { const includePath: string[] = origIncludePath || []; configuration.includePath = includePath.concat(this.nodeAddonIncludes.filter(i => includePath.indexOf(i) < 0)); @@ -987,7 +990,7 @@ export class CppProperties { } } else { // However, if compileCommands are used and compilerPath is explicitly set, it's still necessary to resolve variables in it. - if (configuration.compilerPath === "${default}" && settings.defaultCompilerPath) { + if (configuration.compilerPath === "${default}") { configuration.compilerPath = settings.defaultCompilerPath; } if (configuration.compilerPath === null) { @@ -1001,8 +1004,7 @@ export class CppProperties { } } - configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); - + configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); configuration.configurationProvider = this.updateConfigurationString(configuration.configurationProvider, settings.defaultConfigurationProvider, env); if (!configuration.browse) { @@ -1025,7 +1027,6 @@ export class CppProperties { } } else { configuration.browse.path = this.updateConfigurationPathsArray(configuration.browse.path, settings.defaultBrowsePath, env); - } configuration.browse.limitSymbolsToIncludedHeaders = this.updateConfigurationStringOrBoolean(configuration.browse.limitSymbolsToIncludedHeaders, settings.defaultLimitSymbolsToIncludedHeaders, env); @@ -1261,7 +1262,7 @@ export class CppProperties { } } - private trimPathWhitespace(paths: string[] | undefined | null): string[] | undefined { + private trimPathWhitespace(paths: string[] | undefined): string[] | undefined { if (paths === undefined || paths === null) { return undefined; } @@ -1576,7 +1577,7 @@ export class CppProperties { } if (resolvedCompilerPath === undefined) { - resolvedCompilerPath = this.resolvePath(config.compilerPath); + resolvedCompilerPath = this.resolvePath(config.compilerPath ?? undefined); } const settings: CppSettings = new CppSettings(this.rootUri); const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(!!settings.legacyCompilerArgsBehavior, resolvedCompilerPath); @@ -1591,7 +1592,7 @@ export class CppProperties { const compilerPathNeedsQuotes: boolean = (compilerPathAndArgs.compilerArgsFromCommandLineInPath && compilerPathAndArgs.compilerArgsFromCommandLineInPath.length > 0) && !resolvedCompilerPath.startsWith('"') && - compilerPathAndArgs.compilerPath !== undefined && + compilerPathAndArgs.compilerPath !== undefined && compilerPathAndArgs.compilerPath !== null && compilerPathAndArgs.compilerPath.includes(" "); const compilerPathErrors: string[] = []; @@ -1600,7 +1601,7 @@ export class CppProperties { } // Get compiler path without arguments before checking if it exists - resolvedCompilerPath = compilerPathAndArgs.compilerPath; + resolvedCompilerPath = compilerPathAndArgs.compilerPath ?? undefined; if (resolvedCompilerPath) { let pathExists: boolean = true; const existsWithExeAdded: (path: string) => boolean = (path: string) => isWindows && !path.startsWith("/") && fs.existsSync(path + ".exe"); diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index d7afd71d2a..35837a8406 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -98,7 +98,7 @@ export class CppBuildTaskProvider implements TaskProvider { // Get user compiler path. const userCompilerPathAndArgs: util.CompilerPathAndArgs | undefined = await activeClient.getCurrentCompilerPathAndArgs(); - let userCompilerPath: string | undefined; + let userCompilerPath: string | undefined | null; if (userCompilerPathAndArgs) { userCompilerPath = userCompilerPathAndArgs.compilerPath; if (userCompilerPath && userCompilerPathAndArgs.compilerName) { diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index af829abe1f..b0024990d9 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -50,7 +50,7 @@ export interface WorkspaceFolderSettingsParams { defaultSystemIncludePath: string[]; cppFilesExclude: Excludes; clangFormatPath: string; - clangFormatStyle: string | undefined; + clangFormatStyle: string; clangFormatFallbackStyle: string; clangFormatSortIncludes: boolean | null; codeAnalysisRunAutomatically: boolean; @@ -130,7 +130,7 @@ export interface WorkspaceFolderSettingsParams { filesExclude: Excludes; filesAutoSaveAfterDelay: boolean; filesEncoding: string; - searchExclude: Excludes | undefined; + searchExclude: Excludes; editorAutoClosingBrackets: string; editorInlayHintsEnabled: boolean; editorParameterHintsEnabled: boolean; diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 247aee538d..17cab2dde8 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -1090,15 +1090,15 @@ export function isCl(compilerPath: string): boolean { /** CompilerPathAndArgs retains original casing of text input for compiler path and args */ export interface CompilerPathAndArgs { - compilerPath?: string; + compilerPath?: string | null; compilerName: string; compilerArgs?: string[]; compilerArgsFromCommandLineInPath: string[]; allCompilerArgs: string[]; } -export function extractCompilerPathAndArgs(useLegacyBehavior: boolean, inputCompilerPath?: string, compilerArgs?: string[]): CompilerPathAndArgs { - let compilerPath: string | undefined = inputCompilerPath; +export function extractCompilerPathAndArgs(useLegacyBehavior: boolean, inputCompilerPath?: string | null, compilerArgs?: string[]): CompilerPathAndArgs { + let compilerPath: string | undefined | null = inputCompilerPath; let compilerName: string = ""; let compilerArgsFromCommandLineInPath: string[] = []; if (compilerPath) { From 50216320684e019aa25cd349d352608a031aa9c7 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 19 Jul 2024 14:40:24 -0700 Subject: [PATCH 25/52] Fix lint issues and formatting. --- Extension/src/LanguageServer/configurations.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index ec1a6443b5..95f6a22247 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -594,7 +594,7 @@ export class CppProperties { configuration.intelliSenseMode === "${default}") { return ""; } - const resolvedCompilerPath: string = this.resolvePath(configuration.compilerPath ?? undefined ); + const resolvedCompilerPath: string = this.resolvePath(configuration.compilerPath ?? undefined); const settings: CppSettings = new CppSettings(this.rootUri); const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(!!settings.legacyCompilerArgsBehavior, resolvedCompilerPath); @@ -1004,7 +1004,7 @@ export class CppProperties { } } - configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); + configuration.customConfigurationVariables = this.updateConfigurationStringDictionary(configuration.customConfigurationVariables, settings.defaultCustomConfigurationVariables, env); configuration.configurationProvider = this.updateConfigurationString(configuration.configurationProvider, settings.defaultConfigurationProvider, env); if (!configuration.browse) { @@ -1881,7 +1881,7 @@ export class CppProperties { const paths: string[] = []; let compilerPath: string | undefined; for (const pathArray of [currentConfiguration.browse ? currentConfiguration.browse.path : undefined, - currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { + currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { if (pathArray) { for (const curPath of pathArray) { paths.push(`${curPath}`); From 5186b16a29063b56c05dfd1c491e91ba58448677 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 19 Jul 2024 14:43:46 -0700 Subject: [PATCH 26/52] Fix lint issues --- Extension/src/LanguageServer/configurations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 95f6a22247..fd92c48cb7 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -1881,7 +1881,7 @@ export class CppProperties { const paths: string[] = []; let compilerPath: string | undefined; for (const pathArray of [currentConfiguration.browse ? currentConfiguration.browse.path : undefined, - currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { + currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { if (pathArray) { for (const curPath of pathArray) { paths.push(`${curPath}`); From 85d28254a5034f98de0168373e07bbcfdd48c46c Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 19 Jul 2024 15:03:04 -0700 Subject: [PATCH 27/52] Remove uneeded null value --- Extension/src/LanguageServer/configurations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index fd92c48cb7..dee9e886c5 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -80,7 +80,7 @@ export interface Configuration { intelliSenseModeIsExplicit?: boolean; compileCommandsInCppPropertiesJson?: string; compileCommands?: string; - forcedInclude?: string[] | null; + forcedInclude?: string[]; configurationProviderInCppPropertiesJson?: string; configurationProvider?: string; mergeConfigurations?: boolean; From 4eb61d761872538d2ecb37eb2c7fdb84804f1864 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 22 Jul 2024 20:53:15 -0700 Subject: [PATCH 28/52] Revert null propogation and refactor helper functions to allow null inputs --- Extension/src/LanguageServer/client.ts | 4 +-- .../src/LanguageServer/configurations.ts | 35 +++++++++---------- Extension/src/LanguageServer/settings.ts | 16 ++++----- Extension/src/common.ts | 6 ++-- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 33cc5cd65c..8ce8f9e3bf 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -3052,7 +3052,7 @@ export class DefaultClient implements Client { providerVersion < Version.v6, itemConfig.compilerPath, util.isArrayOfString(itemConfig.compilerArgs) ? itemConfig.compilerArgs : undefined); - itemConfig.compilerPath = compilerPathAndArgs.compilerPath ?? undefined; + itemConfig.compilerPath = compilerPathAndArgs.compilerPath; if (itemConfig.compilerPath !== undefined) { void this.addTrustedCompiler(itemConfig.compilerPath).catch(logAndReturn.undefined); } @@ -3156,7 +3156,7 @@ export class DefaultClient implements Client { providerVersion < Version.v6, sanitized.compilerPath, util.isArrayOfString(sanitized.compilerArgs) ? sanitized.compilerArgs : undefined); - sanitized.compilerPath = compilerPathAndArgs.compilerPath ?? undefined; + sanitized.compilerPath = compilerPathAndArgs.compilerPath; if (sanitized.compilerPath !== undefined) { void this.addTrustedCompiler(sanitized.compilerPath).catch(logAndReturn.undefined); } diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index dee9e886c5..f7d3b16453 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -62,8 +62,8 @@ export interface ConfigurationJson { export interface Configuration { name: string; - compilerPathInCppPropertiesJson?: string | null; - compilerPath?: string | null; + compilerPathInCppPropertiesJson?: string; + compilerPath?: string; compilerPathIsExplicit?: boolean; compilerArgs?: string[]; compilerArgsLegacy?: string[]; @@ -102,7 +102,7 @@ export interface ConfigurationErrors { } export interface Browse { - path?: string[] | null; + path?: string[]; limitSymbolsToIncludedHeaders?: boolean | string; databaseFilename?: string; } @@ -594,7 +594,7 @@ export class CppProperties { configuration.intelliSenseMode === "${default}") { return ""; } - const resolvedCompilerPath: string = this.resolvePath(configuration.compilerPath ?? undefined); + const resolvedCompilerPath: string = this.resolvePath(configuration.compilerPath); const settings: CppSettings = new CppSettings(this.rootUri); const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(!!settings.legacyCompilerArgsBehavior, resolvedCompilerPath); @@ -711,7 +711,7 @@ export class CppProperties { this.onSelectionChanged(); } - private resolveDefaults(entries: string[], defaultValue?: string[] | null): string[] { + private resolveDefaults(entries: string[], defaultValue?: string[]): string[] { let result: string[] = []; entries.forEach(entry => { if (entry === "${default}") { @@ -727,7 +727,7 @@ export class CppProperties { return result; } - private resolveDefaultsDictionary(entries: { [key: string]: string }, defaultValue: { [key: string]: string } | undefined | null, env: Environment): { [key: string]: string } { + private resolveDefaultsDictionary(entries: { [key: string]: string }, defaultValue: { [key: string]: string } | undefined, env: Environment): { [key: string]: string } { const result: { [key: string]: string } = {}; for (const property in entries) { if (property === "${default}") { @@ -758,9 +758,9 @@ export class CppProperties { return result; } - private resolveAndSplit(paths: string[] | undefined, defaultValue: string[] | undefined | null, env: Environment, assumeRelative: boolean = true, glob: boolean = false): string[] { + private resolveAndSplit(paths: string[] | undefined, defaultValue: string[] | undefined, env: Environment, assumeRelative: boolean = true, glob: boolean = false): string[] { const resolvedVariables: string[] = []; - if (paths === undefined || paths === null) { + if (paths === undefined) { return resolvedVariables; } paths = this.resolveDefaults(paths, defaultValue); @@ -841,10 +841,7 @@ export class CppProperties { return property; } - private updateConfigurationPathsArray(paths: string[] | undefined | null, defaultValue: string[] | undefined | null, env: Environment, assumeRelative: boolean = true): string[] | undefined { - if (paths === null) { - return undefined; - } + private updateConfigurationPathsArray(paths: string[] | undefined, defaultValue: string[] | undefined, env: Environment, assumeRelative: boolean = true): string[] | undefined { if (paths) { return this.resolveAndSplit(paths, defaultValue, env, assumeRelative, true); } @@ -879,7 +876,7 @@ export class CppProperties { return property; } - private updateConfigurationStringDictionary(property: { [key: string]: string } | undefined | null, defaultValue: { [key: string]: string } | undefined | null, env: Environment): { [key: string]: string } | undefined { + private updateConfigurationStringDictionary(property: { [key: string]: string } | undefined, defaultValue: { [key: string]: string } | undefined, env: Environment): { [key: string]: string } | undefined { if (!property || Object.keys(property).length === 0) { property = defaultValue; } @@ -1263,7 +1260,7 @@ export class CppProperties { } private trimPathWhitespace(paths: string[] | undefined): string[] | undefined { - if (paths === undefined || paths === null) { + if (paths === undefined) { return undefined; } const trimmedPaths = []; @@ -1577,7 +1574,7 @@ export class CppProperties { } if (resolvedCompilerPath === undefined) { - resolvedCompilerPath = this.resolvePath(config.compilerPath ?? undefined); + resolvedCompilerPath = this.resolvePath(config.compilerPath); } const settings: CppSettings = new CppSettings(this.rootUri); const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(!!settings.legacyCompilerArgsBehavior, resolvedCompilerPath); @@ -1592,7 +1589,7 @@ export class CppProperties { const compilerPathNeedsQuotes: boolean = (compilerPathAndArgs.compilerArgsFromCommandLineInPath && compilerPathAndArgs.compilerArgsFromCommandLineInPath.length > 0) && !resolvedCompilerPath.startsWith('"') && - compilerPathAndArgs.compilerPath !== undefined && compilerPathAndArgs.compilerPath !== null && + compilerPathAndArgs.compilerPath !== undefined && compilerPathAndArgs.compilerPath.includes(" "); const compilerPathErrors: string[] = []; @@ -1601,7 +1598,7 @@ export class CppProperties { } // Get compiler path without arguments before checking if it exists - resolvedCompilerPath = compilerPathAndArgs.compilerPath ?? undefined; + resolvedCompilerPath = compilerPathAndArgs.compilerPath; if (resolvedCompilerPath) { let pathExists: boolean = true; const existsWithExeAdded: (path: string) => boolean = (path: string) => isWindows && !path.startsWith("/") && fs.existsSync(path + ".exe"); @@ -1664,7 +1661,7 @@ export class CppProperties { return errors; } - private validatePath(input: string | string[] | undefined | null, { isDirectory = true, assumeRelative = true, globPaths = false } = {}): string | undefined { + private validatePath(input: string | string[] | undefined, { isDirectory = true, assumeRelative = true, globPaths = false } = {}): string | undefined { if (!input) { return undefined; } @@ -1881,7 +1878,7 @@ export class CppProperties { const paths: string[] = []; let compilerPath: string | undefined; for (const pathArray of [currentConfiguration.browse ? currentConfiguration.browse.path : undefined, - currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { + currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { if (pathArray) { for (const curPath of pathArray) { paths.push(`${curPath}`); diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index b0024990d9..682279bdf7 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -316,7 +316,7 @@ export class CppSettings extends Settings { private getAsBoolean(settingName: string): boolean; private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } @@ -331,7 +331,7 @@ export class CppSettings extends Settings { private getAsString(settingName: string): string; private getAsString(settingName: string, allowNull: boolean): string | null; private getAsString(settingName: string, allowNull: boolean = false): string | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } @@ -348,7 +348,7 @@ export class CppSettings extends Settings { private getAsNumber(settingName: string): number; private getAsNumber(settingName: string, allowNull: boolean): number | null; private getAsNumber(settingName: string, allowNull: boolean = false): number | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } @@ -403,7 +403,7 @@ export class CppSettings extends Settings { private getAsAssociations(settingName: string): Associations; private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } @@ -457,7 +457,7 @@ export class CppSettings extends Settings { public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } public get clangTidyConfig(): string { return this.getAsString("codeAnalysis.clangTidy.config"); } public get clangTidyFallbackConfig(): string { return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); } - public get clangTidyHeaderFilter(): string | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter", true); } + public get clangTidyHeaderFilter(): string | undefined { return this.getAsString("codeAnalysis.clangTidy.headerFilter", true) ?? undefined; } public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } @@ -524,7 +524,7 @@ export class CppSettings extends Settings { public get defaultCompileCommands(): string { return this.getAsString("default.compileCommands"); } public get defaultForcedInclude(): string[] { return this.getAsArrayOfStrings("default.forcedInclude"); } public get defaultIntelliSenseMode(): string { return this.getAsString("default.intelliSenseMode"); } - public get defaultCompilerPath(): string | null { return this.getAsString("default.compilerPath", true) ?? null; } + public get defaultCompilerPath(): string | undefined { return this.getAsString("default.compilerPath", true) ?? undefined; } public set defaultCompilerPath(value: string) { const defaultCompilerPathStr: string = "default.compilerPath"; @@ -551,12 +551,12 @@ export class CppSettings extends Settings { public get defaultCppStandard(): string { return this.getAsString("default.cppStandard"); } public get defaultConfigurationProvider(): string { return this.getAsString("default.configurationProvider"); } public get defaultMergeConfigurations(): boolean { return this.getAsBoolean("default.mergeConfigurations"); } - public get defaultBrowsePath(): string[] | null { return this.getAsArrayOfStrings("default.browse.path", true); } + public get defaultBrowsePath(): string[] { return this.getAsArrayOfStrings("default.browse.path", true); } public get defaultDatabaseFilename(): string { return this.getAsString("default.browse.databaseFilename"); } public get defaultLimitSymbolsToIncludedHeaders(): boolean { return this.getAsBoolean("default.browse.limitSymbolsToIncludedHeaders"); } public get defaultSystemIncludePath(): string[] { return this.getAsArrayOfStrings("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } - public get defaultCustomConfigurationVariables(): Associations | null { return this.getAsAssociations("default.customConfigurationVariables", true); } + public get defaultCustomConfigurationVariables(): Associations | undefined { return this.getAsAssociations("default.customConfigurationVariables", true) ?? undefined; } public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } public get codeFolding(): boolean { return this.getAsString("codeFolding").toLowerCase() === "enabled"; } public get isCaseSensitiveFileSupportEnabled(): boolean { return !isWindows || this.getAsString("caseSensitiveFileSupport").toLowerCase() === "enabled"; } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 17cab2dde8..247aee538d 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -1090,15 +1090,15 @@ export function isCl(compilerPath: string): boolean { /** CompilerPathAndArgs retains original casing of text input for compiler path and args */ export interface CompilerPathAndArgs { - compilerPath?: string | null; + compilerPath?: string; compilerName: string; compilerArgs?: string[]; compilerArgsFromCommandLineInPath: string[]; allCompilerArgs: string[]; } -export function extractCompilerPathAndArgs(useLegacyBehavior: boolean, inputCompilerPath?: string | null, compilerArgs?: string[]): CompilerPathAndArgs { - let compilerPath: string | undefined | null = inputCompilerPath; +export function extractCompilerPathAndArgs(useLegacyBehavior: boolean, inputCompilerPath?: string, compilerArgs?: string[]): CompilerPathAndArgs { + let compilerPath: string | undefined = inputCompilerPath; let compilerName: string = ""; let compilerArgsFromCommandLineInPath: string[] = []; if (compilerPath) { From 440625b9553984c5301f6fa3bd28ed5cbbce2334 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 23 Jul 2024 09:05:17 -0700 Subject: [PATCH 29/52] Fix lint issues --- Extension/src/LanguageServer/configurations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index f7d3b16453..428ccc2eec 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -1878,7 +1878,7 @@ export class CppProperties { const paths: string[] = []; let compilerPath: string | undefined; for (const pathArray of [currentConfiguration.browse ? currentConfiguration.browse.path : undefined, - currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { + currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) { if (pathArray) { for (const curPath of pathArray) { paths.push(`${curPath}`); From 8ceb992028cd4e2a6bf0ac02981e102378a46388 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Tue, 23 Jul 2024 16:56:53 -0700 Subject: [PATCH 30/52] move the helper functions down to try to help the diff --- Extension/src/LanguageServer/settings.ts | 253 ++++++++++++----------- 1 file changed, 127 insertions(+), 126 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 682279bdf7..54327e777e 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -312,132 +312,6 @@ export class CppSettings extends Settings { } return path; } - // Returns the value of a setting as a boolean with proper type validation. - private getAsBoolean(settingName: string): boolean; - private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; - private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { - const value: any = super.Section.get(settingName); - if (allowNull && value === null) { - return null; - } - if (isBoolean(value)) { - return value; - } - const setting = getRawSetting("C_Cpp." + settingName); - return setting.default; - } - - // Returns the value of a setting as a string with proper type validation and checks for valid enum values. - private getAsString(settingName: string): string; - private getAsString(settingName: string, allowNull: boolean): string | null; - private getAsString(settingName: string, allowNull: boolean = false): string | null { - const value: any = super.Section.get(settingName); - if (allowNull && value === null) { - return null; - } - if (this.isValidEnum(settingName, value)) { - return value; - } else if (isString(value)) { - return value; - } - const setting = getRawSetting("C_Cpp." + settingName); - return setting.default; - } - - // Returns the value of a setting as a number with proper type validation and checks if value falls within the specified range. - private getAsNumber(settingName: string): number; - private getAsNumber(settingName: string, allowNull: boolean): number | null; - private getAsNumber(settingName: string, allowNull: boolean = false): number | null { - const value: any = super.Section.get(settingName); - if (allowNull && value === null) { - return null; - } - const setting = getRawSetting("C_Cpp." + settingName); - if (value === null) { - return setting.default; - } - // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. - if (isNumber(value)) { - if (setting.minimum !== undefined && value < setting.minimum) { - return setting.minimum; - } - if (setting.maximum !== undefined && value > setting.maximum) { - return setting.maximum; - } - return value; - } - return setting.default; - } - - // Returns the value of a setting as an array of strings with proper type validation and checks for valid enum values. - private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { - const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); - if (isArrayOfString(value)) { - if (!allowUndefinedEnums) { - if (setting.items.enum !== undefined) { - if (!value.every(x => this.validateEnum(setting.items.enum, x))) { - return setting.default; - } - } - } - return value; - } - return setting.default; - } - - private getAsExcludes(settingName: string): Excludes; - private getAsExcludes(settingName: string, allowNull: boolean): Excludes | null; - private getAsExcludes(settingName: string, allowNull: boolean = false): Excludes | null { - const value: any = super.Section.get(settingName); - if (allowNull && value === null) { - return null; - } - if (isValidMapping(value, 'string', 'boolean')) { - return value as Excludes; - } - const setting = getRawSetting("C_Cpp." + settingName); - return setting.default as Excludes; - } - - private getAsAssociations(settingName: string): Associations; - private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; - private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { - const value: any = super.Section.get(settingName); - if (allowNull && value === null) { - return null; - } - if (isValidMapping(value, 'string', 'string')) { - return value as Associations; - } - const setting = getRawSetting("C_Cpp." + settingName); - return setting.default as Associations; - } - - // Checks a given enum value against a list of valid enum values from package.json. - private validateEnum(enumDescription: any, value: any): boolean { - if (isArray(enumDescription) && enumDescription.length > 0) { - return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); - } - return false; - } - - // Validates whether the given value is a valid enum value for the given setting. - private isValidEnum(settingName: string, value: any): boolean { - const setting = getRawSetting("C_Cpp." + settingName); - if (this.validateEnum(setting.enum, value)) { - return value; - } - return setting.default; - } - - private isArrayOfCommentContinuationPatterns(x: any): x is (string | CommentPattern)[] { - return isArray(x) && x.every(y => isString(y) || this.isCommentPattern(y)); - } - - private isCommentPattern(x: any): x is CommentPattern { - return isString(x.begin) && isString(x.continue); - } public get maxConcurrentThreads(): number | null { return this.getAsNumber("maxConcurrentThreads", true); } public get maxMemory(): number | null { return this.getAsNumber("maxMemory", true); } @@ -634,6 +508,133 @@ export class CppSettings extends Settings { public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get sshTargetsView(): string { return this.getAsString("sshTargetsView"); } + // Returns the value of a setting as a boolean with proper type validation. + private getAsBoolean(settingName: string): boolean; + private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; + private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { + const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } + if (isBoolean(value)) { + return value; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; + } + + // Returns the value of a setting as a string with proper type validation and checks for valid enum values. + private getAsString(settingName: string): string; + private getAsString(settingName: string, allowNull: boolean): string | null; + private getAsString(settingName: string, allowNull: boolean = false): string | null { + const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } + if (this.isValidEnum(settingName, value)) { + return value; + } else if (isString(value)) { + return value; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default; + } + + // Returns the value of a setting as a number with proper type validation and checks if value falls within the specified range. + private getAsNumber(settingName: string): number; + private getAsNumber(settingName: string, allowNull: boolean): number | null; + private getAsNumber(settingName: string, allowNull: boolean = false): number | null { + const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } + const setting = getRawSetting("C_Cpp." + settingName); + if (value === null) { + return setting.default; + } + // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. + if (isNumber(value)) { + if (setting.minimum !== undefined && value < setting.minimum) { + return setting.minimum; + } + if (setting.maximum !== undefined && value > setting.maximum) { + return setting.maximum; + } + return value; + } + return setting.default; + } + + // Returns the value of a setting as an array of strings with proper type validation and checks for valid enum values. + private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { + const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (isArrayOfString(value)) { + if (!allowUndefinedEnums) { + if (setting.items.enum !== undefined) { + if (!value.every(x => this.validateEnum(setting.items.enum, x))) { + return setting.default; + } + } + } + return value; + } + return setting.default; + } + + private getAsExcludes(settingName: string): Excludes; + private getAsExcludes(settingName: string, allowNull: boolean): Excludes | null; + private getAsExcludes(settingName: string, allowNull: boolean = false): Excludes | null { + const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } + if (isValidMapping(value, 'string', 'boolean')) { + return value as Excludes; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default as Excludes; + } + + private getAsAssociations(settingName: string): Associations; + private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; + private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { + const value: any = super.Section.get(settingName); + if (allowNull && value === null) { + return null; + } + if (isValidMapping(value, 'string', 'string')) { + return value as Associations; + } + const setting = getRawSetting("C_Cpp." + settingName); + return setting.default as Associations; + } + + // Checks a given enum value against a list of valid enum values from package.json. + private validateEnum(enumDescription: any, value: any): boolean { + if (isArray(enumDescription) && enumDescription.length > 0) { + return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); + } + return false; + } + + // Validates whether the given value is a valid enum value for the given setting. + private isValidEnum(settingName: string, value: any): boolean { + const setting = getRawSetting("C_Cpp." + settingName); + if (this.validateEnum(setting.enum, value)) { + return value; + } + return setting.default; + } + + private isArrayOfCommentContinuationPatterns(x: any): x is (string | CommentPattern)[] { + return isArray(x) && x.every(y => isString(y) || this.isCommentPattern(y)); + } + + private isCommentPattern(x: any): x is CommentPattern { + return isString(x.begin) && isString(x.continue); + } + public toggleSetting(name: string, value1: string, value2: string): void { const value: string = this.getAsString(name); void super.Section.update(name, value?.toLowerCase() === value1.toLowerCase() ? value2 : value1, getTarget()); From 845f25a0bb7f60a9ba8828817a3774a40d22d177 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 29 Jul 2024 10:46:52 -0700 Subject: [PATCH 31/52] Add oneOf to package.json --- Extension/package.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Extension/package.json b/Extension/package.json index d2d8104b99..bc639fa6e9 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -823,7 +823,14 @@ "scope": "resource" }, "C_Cpp.default.browse.path": { - "type": "array", + "oneOf": [ + { + "type": "string" + }, + { + "type": null + } + ], "items": { "type": "string" }, From e67442220e1581585b41530e7fb25709a2239b6f Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 29 Jul 2024 10:47:39 -0700 Subject: [PATCH 32/52] change type to array --- Extension/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/package.json b/Extension/package.json index b02375071b..c9c7e62b98 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -825,7 +825,7 @@ "C_Cpp.default.browse.path": { "oneOf": [ { - "type": "string" + "type": "array" }, { "type": null From 6012a440d471d3eb23fe068da83fb9f9cfc0e837 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 30 Jul 2024 17:26:33 -0700 Subject: [PATCH 33/52] Add undefined types to neccessary settings + minor refactoring + fixes --- Extension/package.json | 10 +- .../Providers/inlayHintProvider.ts | 5 +- Extension/src/LanguageServer/extension.ts | 2 +- Extension/src/LanguageServer/settings.ts | 142 +++++++++++------- 4 files changed, 98 insertions(+), 61 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index c9c7e62b98..539a9bbc91 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -825,17 +825,17 @@ "C_Cpp.default.browse.path": { "oneOf": [ { - "type": "array" + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true }, { "type": null } ], - "items": { - "type": "string" - }, "default": null, - "uniqueItems": true, "markdownDescription": "%c_cpp.configuration.default.browse.path.markdownDescription%", "scope": "machine-overridable" }, diff --git a/Extension/src/LanguageServer/Providers/inlayHintProvider.ts b/Extension/src/LanguageServer/Providers/inlayHintProvider.ts index 984587cba0..9b427bc2cd 100644 --- a/Extension/src/LanguageServer/Providers/inlayHintProvider.ts +++ b/Extension/src/LanguageServer/Providers/inlayHintProvider.ts @@ -6,8 +6,7 @@ import * as vscode from 'vscode'; import { ManualPromise } from '../../Utility/Async/manualPromise'; import { CppSettings } from '../settings'; -interface FileData -{ +interface FileData { version: number; promise: ManualPromise; typeHints: CppInlayHint[]; @@ -204,7 +203,7 @@ export class InlayHintsProvider implements vscode.InlayHintsProvider { private resolveTypeHints(settings: CppSettings, hints: CppInlayHint[]): vscode.InlayHint[] { const resolvedHints: vscode.InlayHint[] = []; for (const hint of hints) { - const showOnLeft: boolean = settings.inlayHintsAutoDeclarationTypesShowOnLeft && hint.identifierLength > 0; + const showOnLeft: boolean | undefined = settings.inlayHintsAutoDeclarationTypesShowOnLeft && hint.identifierLength > 0; const inlayHint: vscode.InlayHint = new vscode.InlayHint( new vscode.Position(hint.line, hint.character + (showOnLeft ? 0 : hint.identifierLength)), diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 76e5642d02..48f46ca749 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -1319,7 +1319,7 @@ export function UpdateInsidersAccess(): void { const insidersMitigationDone: PersistentState = new PersistentState("CPP.insidersMitigationDone", false); if (!insidersMitigationDone.Value) { if (vscode.workspace.getConfiguration("extensions", null).get("autoUpdate")) { - if (settings.getWithUndefinedDefault("updateChannel") === undefined) { + if (settings.getStringwithUndefinedDefault("updateChannel") === undefined) { installPrerelease = true; } } diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 54327e777e..92a3e44527 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -32,6 +32,7 @@ export interface Associations { [key: string]: string; } +// Settings that can be undefined have default values assigned in the native code or are meant to return undefined. export interface WorkspaceFolderSettingsParams { uri: string | undefined; intelliSenseEngine: string; @@ -41,24 +42,24 @@ export interface WorkspaceFolderSettingsParams { errorSquiggles: string; exclusionPolicy: string; preferredPathSeparator: string; - intelliSenseCachePath: string; + intelliSenseCachePath: string | undefined; intelliSenseCacheSize: number; intelliSenseMemoryLimit: number; dimInactiveRegions: boolean; suggestSnippets: boolean; legacyCompilerArgsBehavior: boolean; - defaultSystemIncludePath: string[]; + defaultSystemIncludePath: string[] | undefined; cppFilesExclude: Excludes; - clangFormatPath: string; + clangFormatPath: string | undefined; clangFormatStyle: string; - clangFormatFallbackStyle: string; + clangFormatFallbackStyle: string | undefined; clangFormatSortIncludes: boolean | null; codeAnalysisRunAutomatically: boolean; codeAnalysisExclude: Excludes; clangTidyEnabled: boolean; - clangTidyPath: string; - clangTidyConfig: string; - clangTidyFallbackConfig: string; + clangTidyPath: string | undefined; + clangTidyConfig: string | undefined; + clangTidyFallbackConfig: string | undefined; clangTidyHeaderFilter: string | null; clangTidyArgs: string[]; clangTidyUseBuildPath: boolean; @@ -179,43 +180,51 @@ class Settings { protected get Section(): vscode.WorkspaceConfiguration { return this.settings; } - protected getWithFallback(section: string, deprecatedSection: string): T { - const info: any = this.settings.inspect(section); + // If the setting has an undefined default, look for the workspaceFolder, workspace and global values as well. + public getArrayOfStringsWithUndefinedDefault(section: string): string[] | undefined; + public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean): string[] | undefined | null; + public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean = false): string[] | undefined | null { + const info: any = this.settings.inspect(section); + if (allowNull && info === null) { + return null; + } if (info.workspaceFolderValue !== undefined) { - return info.workspaceFolderValue; + if (isArrayOfString(info.workspaceFolderValue)) { + return info.workspaceFolderValue; + } } else if (info.workspaceValue !== undefined) { - return info.workspaceValue; + if (isArrayOfString(info.workspaceValue)) { + return info.workspaceValue; + } } else if (info.globalValue !== undefined) { - return info.globalValue; - } - const value: T | undefined = this.settings.get(deprecatedSection); - if (value !== undefined) { - return value; + if (isArrayOfString(info.globalValue)) { + return info.globalValue; + } } - return info.defaultValue; + return undefined; } - protected getWithNullAsUndefined(section: string): T | undefined { - const result: T | undefined | null = this.settings.get(section); - if (result === null) { - return undefined; - } - return result; - } + public getStringwithUndefinedDefault(section: string): string | undefined { + const info: any = this.settings.inspect(section); - public getWithUndefinedDefault(section: string): T | undefined { - const info: any = this.settings.inspect(section); if (info.workspaceFolderValue !== undefined) { - return info.workspaceFolderValue; + if (isString(info.workspaceFolderValue)) { + return info.workspaceFolderValue; + } } else if (info.workspaceValue !== undefined) { - return info.workspaceValue; + if (isString(info.workspaceValue)) { + return info.workspaceValue; + } } else if (info.globalValue !== undefined) { - return info.globalValue; + if (isString(info.globalValue)) { + return info.globalValue; + } } return undefined; } } +// If a setting is undefined, a blank string, or null, return undefined instead. function changeBlankStringToUndefined(input: string | undefined): string | undefined { // Although null is not a valid type, user could enter a null anyway. return (input === undefined || input === null || input.trim() === "") ? undefined : input; @@ -329,9 +338,9 @@ export class CppSettings extends Settings { public get codeAnalysisRunAutomatically(): boolean { return this.getAsBoolean("codeAnalysis.runAutomatically"); } public get codeAnalysisRunOnBuild(): boolean { return this.getAsBoolean("codeAnalysis.runOnBuild"); } public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } - public get clangTidyConfig(): string { return this.getAsString("codeAnalysis.clangTidy.config"); } - public get clangTidyFallbackConfig(): string { return this.getAsString("codeAnalysis.clangTidy.fallbackConfig"); } - public get clangTidyHeaderFilter(): string | undefined { return this.getAsString("codeAnalysis.clangTidy.headerFilter", true) ?? undefined; } + public get clangTidyConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.config")); } + public get clangTidyFallbackConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.fallbackConfig")); } + public get clangTidyHeaderFilter(): string | undefined { return this.getAsStringOrUndefined("codeAnalysis.clangTidy.headerFilter") ?? undefined; } public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } @@ -348,21 +357,21 @@ export class CppSettings extends Settings { checks.push(value); void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } - public get clangFormatStyle(): string { return this.getAsString("clang_format_style"); } - public get clangFormatFallbackStyle(): string { return this.getAsString("clang_format_fallbackStyle"); } + public get clangFormatStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("clang_format_style")); } + public get clangFormatFallbackStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsString("clang_format_fallbackStyle")); } public get clangFormatSortIncludes(): boolean | null { return this.getAsBoolean("clang_format_sortIncludes", true); } public get experimentalFeatures(): boolean { return this.getAsString("experimentalFeatures").toLowerCase() === "enabled"; } public get suggestSnippets(): boolean { return this.getAsBoolean("suggestSnippets"); } public get intelliSenseEngine(): string { return this.getAsString("intelliSenseEngine"); } public get intelliSenseEngineFallback(): boolean { return this.getAsString("intelliSenseEngineFallback").toLowerCase() === "enabled"; } - public get intelliSenseCachePath(): string { return this.getAsString("intelliSenseCachePath"); } + public get intelliSenseCachePath(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("intelliSenseCachePath")); } public get intelliSenseCacheSize(): number { return this.getAsNumber("intelliSenseCacheSize"); } public get intelliSenseMemoryLimit(): number { return this.getAsNumber("intelliSenseMemoryLimit"); } public get intelliSenseUpdateDelay(): number { return this.getAsNumber("intelliSenseUpdateDelay"); } public get errorSquiggles(): string { return this.getAsString("errorSquiggles"); } public get inactiveRegionOpacity(): number { return this.getAsNumber("inactiveRegionOpacity"); } - public get inactiveRegionForegroundColor(): string { return this.getAsString("inactiveRegionForegroundColor"); } - public get inactiveRegionBackgroundColor(): string { return this.getAsString("inactiveRegionBackgroundColor"); } + public get inactiveRegionForegroundColor(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("inactiveRegionForegroundColor")); } + public get inactiveRegionBackgroundColor(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("inactiveRegionBackgroundColor")); } public get autocomplete(): string { return this.getAsString("autocomplete"); } public get autocompleteAddParentheses(): boolean { return this.getAsBoolean("autocompleteAddParentheses"); } public get loggingLevel(): string { return this.getAsString("loggingLevel"); } @@ -390,15 +399,15 @@ export class CppSettings extends Settings { public get addNodeAddonIncludePaths(): boolean { return this.getAsBoolean("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean { return this.getAsBoolean("renameRequiresIdentifier"); } public get filesExclude(): Excludes { return this.getAsExcludes("files.exclude"); } - public get defaultIncludePath(): string[] { return this.getAsArrayOfStrings("default.includePath"); } - public get defaultDefines(): string[] { return this.getAsArrayOfStrings("default.defines"); } - public get defaultDotconfig(): string { return this.getAsString("default.dotConfig"); } - public get defaultMacFrameworkPath(): string[] { return this.getAsArrayOfStrings("default.macFrameworkPath"); } - public get defaultWindowsSdkVersion(): string { return this.getAsString("default.windowsSdkVersion"); } - public get defaultCompileCommands(): string { return this.getAsString("default.compileCommands"); } - public get defaultForcedInclude(): string[] { return this.getAsArrayOfStrings("default.forcedInclude"); } - public get defaultIntelliSenseMode(): string { return this.getAsString("default.intelliSenseMode"); } - public get defaultCompilerPath(): string | undefined { return this.getAsString("default.compilerPath", true) ?? undefined; } + public get defaultIncludePath(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.includePath"); } + public get defaultDefines(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.defines"); } + public get defaultDotconfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.dotConfig")); } + public get defaultMacFrameworkPath(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.macFrameworkPath"); } + public get defaultWindowsSdkVersion(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.windowsSdkVersion")); } + public get defaultCompileCommands(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.compileCommands")); } + public get defaultForcedInclude(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.forcedInclude"); } + public get defaultIntelliSenseMode(): string | undefined { return this.getAsStringOrUndefined("default.intelliSenseMode"); } + public get defaultCompilerPath(): string | undefined { return this.getAsStringOrUndefined("default.compilerPath"); } public set defaultCompilerPath(value: string) { const defaultCompilerPathStr: string = "default.compilerPath"; @@ -420,15 +429,15 @@ export class CppSettings extends Settings { }); } } - public get defaultCompilerArgs(): string[] { return this.getAsArrayOfStrings("default.compilerArgs"); } + public get defaultCompilerArgs(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.compilerArgs"); } public get defaultCStandard(): string { return this.getAsString("default.cStandard"); } public get defaultCppStandard(): string { return this.getAsString("default.cppStandard"); } - public get defaultConfigurationProvider(): string { return this.getAsString("default.configurationProvider"); } - public get defaultMergeConfigurations(): boolean { return this.getAsBoolean("default.mergeConfigurations"); } - public get defaultBrowsePath(): string[] { return this.getAsArrayOfStrings("default.browse.path", true); } - public get defaultDatabaseFilename(): string { return this.getAsString("default.browse.databaseFilename"); } + public get defaultConfigurationProvider(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.configurationProvider")); } + public get defaultMergeConfigurations(): boolean | undefined { return this.getAsBooleanOrUndefined("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"); } - public get defaultSystemIncludePath(): string[] { return this.getAsArrayOfStrings("default.systemIncludePath"); } + public get defaultSystemIncludePath(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.systemIncludePath"); } public get defaultEnableConfigurationSquiggles(): boolean { return this.getAsBoolean("default.enableConfigurationSquiggles"); } public get defaultCustomConfigurationVariables(): Associations | undefined { return this.getAsAssociations("default.customConfigurationVariables", true) ?? undefined; } public get useBacktickCommandSubstitution(): boolean { return this.getAsBoolean("debugger.useBacktickCommandSubstitution"); } @@ -508,6 +517,35 @@ export class CppSettings extends Settings { public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get sshTargetsView(): string { return this.getAsString("sshTargetsView"); } + // Returns the value of a setting as a string with proper type validation and checks for valid enum values while returning an undefined value if neccessary. + private getAsStringOrUndefined(settingName: string): string | undefined { + const value: any = super.Section.get(settingName); + if (value === undefined) { + return undefined; + } + if (this.isValidEnum(settingName, value)) { + return value; + } else if (isString(value)) { + return value; + } else { + 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 neccessary. + private getAsBooleanOrUndefined(settingName: string): boolean | undefined { + const value: any = super.Section.get(settingName); + if (value === undefined) { + return undefined; + } + if (isBoolean(value)) { + return value; + } else { + return undefined; + } + } + // Returns the value of a setting as a boolean with proper type validation. private getAsBoolean(settingName: string): boolean; private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; From 7f3970d88ad0a38bcf2dbb5029700fd5812a4be3 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 31 Jul 2024 09:59:17 -0700 Subject: [PATCH 34/52] Change string to correct case --- Extension/src/LanguageServer/extension.ts | 2 +- Extension/src/LanguageServer/settings.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 48f46ca749..5c6bc11240 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -1319,7 +1319,7 @@ export function UpdateInsidersAccess(): void { const insidersMitigationDone: PersistentState = new PersistentState("CPP.insidersMitigationDone", false); if (!insidersMitigationDone.Value) { if (vscode.workspace.getConfiguration("extensions", null).get("autoUpdate")) { - if (settings.getStringwithUndefinedDefault("updateChannel") === undefined) { + if (settings.getStringWithUndefinedDefault("updateChannel") === undefined) { installPrerelease = true; } } diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 92a3e44527..3282027575 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -204,7 +204,7 @@ class Settings { return undefined; } - public getStringwithUndefinedDefault(section: string): string | undefined { + public getStringWithUndefinedDefault(section: string): string | undefined { const info: any = this.settings.inspect(section); if (info.workspaceFolderValue !== undefined) { From 240559771459c2e6455281277d4f7cd8ca85d299 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 31 Jul 2024 14:03:00 -0700 Subject: [PATCH 35/52] Correct package.json syntax and refactor settings.ts --- Extension/package.json | 18 ++++++--------- Extension/src/LanguageServer/settings.ts | 29 ++++++++++++------------ 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 57001829c9..2968e80ae1 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -823,18 +823,14 @@ "scope": "resource" }, "C_Cpp.default.browse.path": { - "oneOf": [ - { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - { - "type": null - } + "type": [ + "array", + "null" ], + "items": { + "type": "string" + }, + "uniqueItems": true, "default": null, "markdownDescription": "%c_cpp.configuration.default.browse.path.markdownDescription%", "scope": "machine-overridable" diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 3282027575..2d1d8151f3 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -185,18 +185,19 @@ class Settings { public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean): string[] | undefined | null; public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean = false): string[] | undefined | null { const info: any = this.settings.inspect(section); - if (allowNull && info === null) { - return null; - } if (info.workspaceFolderValue !== undefined) { - if (isArrayOfString(info.workspaceFolderValue)) { + if ((allowNull && info.workspaceFolderValue == null) || isArrayOfString(info.workspaceFolderValue)) { return info.workspaceFolderValue; } - } else if (info.workspaceValue !== undefined) { + } + + if ((allowNull && info.workspaceValue == null) || info.workspaceValue !== undefined) { if (isArrayOfString(info.workspaceValue)) { return info.workspaceValue; } - } else if (info.globalValue !== undefined) { + } + + if ((allowNull && info.globalValue == null) || info.globalValue !== undefined) { if (isArrayOfString(info.globalValue)) { return info.globalValue; } @@ -211,11 +212,15 @@ class Settings { if (isString(info.workspaceFolderValue)) { return info.workspaceFolderValue; } - } else if (info.workspaceValue !== undefined) { + } + + if (info.workspaceValue !== undefined) { if (isString(info.workspaceValue)) { return info.workspaceValue; } - } else if (info.globalValue !== undefined) { + } + + if (info.globalValue !== undefined) { if (isString(info.globalValue)) { return info.globalValue; } @@ -340,7 +345,7 @@ export class CppSettings extends Settings { public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } public get clangTidyConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.config")); } public get clangTidyFallbackConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.fallbackConfig")); } - public get clangTidyHeaderFilter(): string | undefined { return this.getAsStringOrUndefined("codeAnalysis.clangTidy.headerFilter") ?? undefined; } + public get clangTidyHeaderFilter(): string | undefined { return this.getAsStringOrUndefined("codeAnalysis.clangTidy.headerFilter"); } public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } @@ -520,9 +525,6 @@ export class CppSettings extends Settings { // Returns the value of a setting as a string with proper type validation and checks for valid enum values while returning an undefined value if neccessary. private getAsStringOrUndefined(settingName: string): string | undefined { const value: any = super.Section.get(settingName); - if (value === undefined) { - return undefined; - } if (this.isValidEnum(settingName, value)) { return value; } else if (isString(value)) { @@ -536,9 +538,6 @@ export class CppSettings extends Settings { // 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 neccessary. private getAsBooleanOrUndefined(settingName: string): boolean | undefined { const value: any = super.Section.get(settingName); - if (value === undefined) { - return undefined; - } if (isBoolean(value)) { return value; } else { From 54028014c22df9783b57a7541a4c299382e127b7 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 31 Jul 2024 14:05:22 -0700 Subject: [PATCH 36/52] Fix lint issues --- Extension/src/LanguageServer/settings.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 2d1d8151f3..eb7b7b356b 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -186,18 +186,18 @@ class Settings { public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean = false): string[] | undefined | null { const info: any = this.settings.inspect(section); if (info.workspaceFolderValue !== undefined) { - if ((allowNull && info.workspaceFolderValue == null) || isArrayOfString(info.workspaceFolderValue)) { + if ((allowNull && info.workspaceFolderValue === null) || isArrayOfString(info.workspaceFolderValue)) { return info.workspaceFolderValue; } } - if ((allowNull && info.workspaceValue == null) || info.workspaceValue !== undefined) { + if ((allowNull && info.workspaceValue === null) || info.workspaceValue !== undefined) { if (isArrayOfString(info.workspaceValue)) { return info.workspaceValue; } - } + } - if ((allowNull && info.globalValue == null) || info.globalValue !== undefined) { + if ((allowNull && info.globalValue === null) || info.globalValue !== undefined) { if (isArrayOfString(info.globalValue)) { return info.globalValue; } @@ -212,7 +212,7 @@ class Settings { if (isString(info.workspaceFolderValue)) { return info.workspaceFolderValue; } - } + } if (info.workspaceValue !== undefined) { if (isString(info.workspaceValue)) { From 11df9d42dced309eb556d762f8be81e809b2c508 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Thu, 1 Aug 2024 11:41:18 -0700 Subject: [PATCH 37/52] Refactor helper functions + minor fixes --- Extension/package.json | 5 +- Extension/src/LanguageServer/settings.ts | 82 ++++++++++-------------- 2 files changed, 36 insertions(+), 51 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 2968e80ae1..fc4af51162 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -823,10 +823,7 @@ "scope": "resource" }, "C_Cpp.default.browse.path": { - "type": [ - "array", - "null" - ], + "type": "array", "items": { "type": "string" }, diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index eb7b7b356b..64902b70e9 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -53,7 +53,7 @@ export interface WorkspaceFolderSettingsParams { clangFormatPath: string | undefined; clangFormatStyle: string; clangFormatFallbackStyle: string | undefined; - clangFormatSortIncludes: boolean | null; + clangFormatSortIncludes: boolean | undefined; codeAnalysisRunAutomatically: boolean; codeAnalysisExclude: Excludes; clangTidyEnabled: boolean; @@ -185,22 +185,17 @@ class Settings { public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean): string[] | undefined | null; public getArrayOfStringsWithUndefinedDefault(section: string, allowNull: boolean = false): string[] | undefined | null { const info: any = this.settings.inspect(section); - if (info.workspaceFolderValue !== undefined) { - if ((allowNull && info.workspaceFolderValue === null) || isArrayOfString(info.workspaceFolderValue)) { - return info.workspaceFolderValue; - } + + if ((allowNull && info.workspaceFolderValue === null) || isArrayOfString(info.workspaceFolderValue)) { + return info.workspaceFolderValue; } - if ((allowNull && info.workspaceValue === null) || info.workspaceValue !== undefined) { - if (isArrayOfString(info.workspaceValue)) { - return info.workspaceValue; - } + if ((allowNull && info.workspaceValue === null) || isArrayOfString(info.workspaceValue)) { + return info.workspaceValue; } - if ((allowNull && info.globalValue === null) || info.globalValue !== undefined) { - if (isArrayOfString(info.globalValue)) { - return info.globalValue; - } + if ((allowNull && info.globalValue === null) || isArrayOfString(info.globalValue)) { + return info.globalValue; } return undefined; } @@ -208,22 +203,16 @@ class Settings { public getStringWithUndefinedDefault(section: string): string | undefined { const info: any = this.settings.inspect(section); - if (info.workspaceFolderValue !== undefined) { - if (isString(info.workspaceFolderValue)) { - return info.workspaceFolderValue; - } + if (isString(info.workspaceFolderValue)) { + return info.workspaceFolderValue; } - if (info.workspaceValue !== undefined) { - if (isString(info.workspaceValue)) { - return info.workspaceValue; - } + if (isString(info.workspaceValue)) { + return info.workspaceValue; } - if (info.globalValue !== undefined) { - if (isString(info.globalValue)) { - return info.globalValue; - } + if (isString(info.globalValue)) { + return info.globalValue; } return undefined; } @@ -364,7 +353,7 @@ export class CppSettings extends Settings { } public get clangFormatStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("clang_format_style")); } public get clangFormatFallbackStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsString("clang_format_fallbackStyle")); } - public get clangFormatSortIncludes(): boolean | null { return this.getAsBoolean("clang_format_sortIncludes", true); } + public get clangFormatSortIncludes(): boolean | undefined { return this.getAsBooleanOrUndefined("clang_format_sortIncludes"); } public get experimentalFeatures(): boolean { return this.getAsString("experimentalFeatures").toLowerCase() === "enabled"; } public get suggestSnippets(): boolean { return this.getAsBoolean("suggestSnippets"); } public get intelliSenseEngine(): string { return this.getAsString("intelliSenseEngine"); } @@ -522,20 +511,24 @@ export class CppSettings extends Settings { public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } public get sshTargetsView(): string { return this.getAsString("sshTargetsView"); } - // Returns the value of a setting as a string with proper type validation and checks for valid enum values while returning an undefined value if neccessary. + // Returns the value of a setting as a string with proper type validation and checks for valid enum values while returning an undefined value if necessary. private getAsStringOrUndefined(settingName: string): string | undefined { const value: any = super.Section.get(settingName); - if (this.isValidEnum(settingName, value)) { - return value; - } else if (isString(value)) { + const setting = getRawSetting("C_Cpp." + settingName); + if (setting.enum !== undefined) { + if (this.isValidEnum(setting.enum, value)) { + return value; + } + return setting.default; + } + if (isString(value)) { return value; } else { 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 neccessary. + // 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(settingName); if (isBoolean(value)) { @@ -568,12 +561,16 @@ export class CppSettings extends Settings { if (allowNull && value === null) { return null; } - if (this.isValidEnum(settingName, value)) { - return value; - } else if (isString(value)) { + const setting = getRawSetting("C_Cpp." + settingName); + if (setting.enum !== undefined) { + if (this.isValidEnum(setting.enum, value)) { + return value; + } + return setting.default; + } + if (isString(value)) { return value; } - const setting = getRawSetting("C_Cpp." + settingName); return setting.default; } @@ -609,7 +606,7 @@ export class CppSettings extends Settings { if (isArrayOfString(value)) { if (!allowUndefinedEnums) { if (setting.items.enum !== undefined) { - if (!value.every(x => this.validateEnum(setting.items.enum, x))) { + if (!value.every(x => this.isValidEnum(setting.items.enum, x))) { return setting.default; } } @@ -648,22 +645,13 @@ export class CppSettings extends Settings { } // Checks a given enum value against a list of valid enum values from package.json. - private validateEnum(enumDescription: any, value: any): boolean { + private isValidEnum(enumDescription: any, value: any): boolean { if (isArray(enumDescription) && enumDescription.length > 0) { return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); } return false; } - // Validates whether the given value is a valid enum value for the given setting. - private isValidEnum(settingName: string, value: any): boolean { - const setting = getRawSetting("C_Cpp." + settingName); - if (this.validateEnum(setting.enum, value)) { - return value; - } - return setting.default; - } - private isArrayOfCommentContinuationPatterns(x: any): x is (string | CommentPattern)[] { return isArray(x) && x.every(y => isString(y) || this.isCommentPattern(y)); } From ddfc7034dc29203ec299dd770642483ccf5db12a Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Fri, 2 Aug 2024 10:04:34 -0700 Subject: [PATCH 38/52] Remove null type --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 35837a8406..de08d6e436 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -98,7 +98,7 @@ export class CppBuildTaskProvider implements TaskProvider { // Get user compiler path. const userCompilerPathAndArgs: util.CompilerPathAndArgs | undefined = await activeClient.getCurrentCompilerPathAndArgs(); - let userCompilerPath: string | undefined | null; + let userCompilerPath: string | undefined; if (userCompilerPathAndArgs) { userCompilerPath = userCompilerPathAndArgs.compilerPath; if (userCompilerPath && userCompilerPathAndArgs.compilerName) { @@ -414,7 +414,7 @@ class CustomBuildTaskTerminal implements Pseudoterminal { } }); if (this.options === undefined) { - this.options = { }; + this.options = {}; } if (this.options.cwd) { this.options.cwd = util.resolveVariables(this.options.cwd.toString()); From a4f15016cc6eee37f100ace68875e296dbf5b8a8 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 5 Aug 2024 12:42:23 -0700 Subject: [PATCH 39/52] Refactor setting validation for VS Code settings to include telemetry, add exception for logging level setting, refactor isValidMapping function to use lambda params. --- Extension/src/LanguageServer/settings.ts | 145 +++++++++++++++++++---- Extension/src/common.ts | 4 +- 2 files changed, 121 insertions(+), 28 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 64902b70e9..48b775b854 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -16,6 +16,7 @@ import * as nls from 'vscode-nls'; import * as which from 'which'; import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; +import * as telemetry from '../telemetry'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; import { clients } from './extension'; import { CommentPattern } from './languageConfig'; @@ -330,7 +331,7 @@ export class CppSettings extends Settings { public get codeAnalysisUpdateDelay(): number { return this.getAsNumber("codeAnalysis.updateDelay"); } public get codeAnalysisExclude(): Excludes { return this.getAsExcludes("codeAnalysis.exclude"); } public get codeAnalysisRunAutomatically(): boolean { return this.getAsBoolean("codeAnalysis.runAutomatically"); } - public get codeAnalysisRunOnBuild(): boolean { return this.getAsBoolean("codeAnalysis.runOnBuild"); } + public get codeAnalysisRunOnBuild(): boolean | undefined { return false; } // return this.getAsBoolean("codeAnalysis.runOnBuild"); public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } public get clangTidyConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.config")); } public get clangTidyFallbackConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.fallbackConfig")); } @@ -379,7 +380,7 @@ export class CppSettings extends Settings { public get doxygenGenerateOnType(): boolean { return this.getAsBoolean("doxygen.generateOnType"); } public get commentContinuationPatterns(): (string | CommentPattern)[] { // eslint-disable-next-line no-extra-parens - const value = super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); + const value: any = super.Section.get<(any)[]>("commentContinuationPatterns"); if (this.isArrayOfCommentContinuationPatterns(value)) { return value; } @@ -448,7 +449,11 @@ export class CppSettings extends Settings { public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean { return this.getAsBoolean("inlayHints.parameterNames.hideLeadingUnderscores"); } public get inlayHintsReferenceOperator(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.enabled"); } public get inlayHintsReferenceOperatorShowSpace(): boolean { return this.getAsBoolean("inlayHints.referenceOperator.showSpace"); } - public get isEnhancedColorizationEnabled(): boolean { return this.getAsString("enhancedColorization").toLowerCase() === "enabled" && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } + public get isEnhancedColorizationEnabled(): boolean { + return this.getAsString("enhancedColorization").toLowerCase() === "enabled" + && this.intelliSenseEngine === "default" + && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; + } public get formattingEngine(): string { return this.getAsString("formatting"); } public get vcFormatIndentBraces(): boolean { return this.getAsBoolean("vcFormat.indent.braces"); } public get vcFormatIndentMultiLineRelativeTo(): string { return this.getAsString("vcFormat.indent.multiLineRelativeTo"); } @@ -508,12 +513,15 @@ export class CppSettings extends Settings { public get vcFormatSpacePointerReferenceAlignment(): string { return this.getAsString("vcFormat.space.pointerReferenceAlignment"); } public get vcFormatSpaceAroundTernaryOperator(): string { return this.getAsString("vcFormat.space.aroundTernaryOperator"); } public get vcFormatWrapPreserveBlocks(): string { return this.getAsString("vcFormat.wrap.preserveBlocks"); } - public get dimInactiveRegions(): boolean { return this.getAsBoolean("dimInactiveRegions") && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; } + public get dimInactiveRegions(): boolean { + return this.getAsBoolean("dimInactiveRegions") + && this.intelliSenseEngine === "default" && vscode.workspace.getConfiguration("workbench").get("colorTheme") !== "Default High Contrast"; + } public get sshTargetsView(): string { return this.getAsString("sshTargetsView"); } // Returns the value of a setting as a string with proper type validation and checks for valid enum values while returning an undefined value if necessary. private getAsStringOrUndefined(settingName: string): string | undefined { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); if (setting.enum !== undefined) { if (this.isValidEnum(setting.enum, value)) { @@ -530,7 +538,7 @@ export class CppSettings extends Settings { // 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(settingName); + const value: any = super.Section.get(settingName); if (isBoolean(value)) { return value; } else { @@ -542,7 +550,7 @@ export class CppSettings extends Settings { private getAsBoolean(settingName: string): boolean; private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } @@ -557,12 +565,16 @@ export class CppSettings extends Settings { private getAsString(settingName: string): string; private getAsString(settingName: string, allowNull: boolean): string | null; private getAsString(settingName: string, allowNull: boolean = false): string | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } const setting = getRawSetting("C_Cpp." + settingName); + if (setting.enum !== undefined) { + if (settingName === "loggingLevel" && isNumber(Number(value)) && Number(value) >= 0) { + return value; + } if (this.isValidEnum(setting.enum, value)) { return value; } @@ -578,14 +590,11 @@ export class CppSettings extends Settings { private getAsNumber(settingName: string): number; private getAsNumber(settingName: string, allowNull: boolean): number | null; private getAsNumber(settingName: string, allowNull: boolean = false): number | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } const setting = getRawSetting("C_Cpp." + settingName); - if (value === null) { - return setting.default; - } // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. if (isNumber(value)) { if (setting.minimum !== undefined && value < setting.minimum) { @@ -623,7 +632,7 @@ export class CppSettings extends Settings { if (allowNull && value === null) { return null; } - if (isValidMapping(value, 'string', 'boolean')) { + if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'boolean')) { return value as Excludes; } const setting = getRawSetting("C_Cpp." + settingName); @@ -633,11 +642,11 @@ export class CppSettings extends Settings { private getAsAssociations(settingName: string): Associations; private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { - const value: any = super.Section.get(settingName); + const value: any = super.Section.get(settingName); if (allowNull && value === null) { return null; } - if (isValidMapping(value, 'string', 'string')) { + if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'string')) { return value as Associations; } const setting = getRawSetting("C_Cpp." + settingName); @@ -904,27 +913,70 @@ export class OtherSettings { private getAsString(sectionName: string, settingName: string, resource: any, defaultValue: string): string { const section = vscode.workspace.getConfiguration(sectionName, resource); - const value = section.get(settingName); + if (section === undefined || section === null) { + const message = "Configuration not found"; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } + const value = section.get(settingName); if (isString(value)) { return value; } - const setting = section.inspect(settingName); - return setting?.defaultValue ?? defaultValue; + const setting = section.inspect(settingName); + + if (setting?.defaultValue === undefined || setting.defaultValue === null) { + const message = "Default value not found."; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + return defaultValue; + } + return setting.defaultValue; } private getAsBoolean(sectionName: string, settingName: string, resource: any, defaultValue: boolean): boolean { const section = vscode.workspace.getConfiguration(sectionName, resource); - const value = section.get(settingName); + if (section === undefined || section === null) { + const message = "Configuration not found"; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } + const value = section.get(settingName); if (isBoolean(value)) { return value; } - const setting = section.inspect(settingName); - return setting?.defaultValue ?? defaultValue; + const setting = section.inspect(settingName); + if (setting?.defaultValue === undefined || setting.defaultValue === null) { + const message = "Default value not found."; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + return defaultValue; + } + return setting.defaultValue; } private getAsNumber(sectionName: string, settingName: string, resource: any, defaultValue: number, minimum?: number, maximum?: number): number { const section = vscode.workspace.getConfiguration(sectionName, resource); - const value = section.get(settingName); + if (section === undefined || section === null) { + const message = "Configuration not found"; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } + const value = section.get(settingName); // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. if (isNumber(value)) { if (minimum !== undefined && value < minimum) { @@ -935,27 +987,68 @@ export class OtherSettings { } return value; } - const setting = section.inspect(settingName); - return setting?.defaultValue ?? defaultValue; + const setting = section.inspect(settingName); + if (setting?.defaultValue === undefined || setting.defaultValue === null) { + const message = "Default value not found."; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + return defaultValue; + } + return setting.defaultValue; } private getAsAssociations(sectionName: string, settingName: string, resource?: any): Associations { const section = vscode.workspace.getConfiguration(sectionName, resource); + if (section === undefined || section === null) { + const message = "Configuration not found"; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } const value = section.get(settingName); - if (isValidMapping(value, 'string', 'string')) { + if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'string')) { return value as Associations; } const setting = section.inspect(settingName); + if (setting?.defaultValue === undefined || setting.defaultValue === null) { + const message = "Default value not found."; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } return setting?.defaultValue as Associations; } private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { const section = vscode.workspace.getConfiguration(sectionName, resource); + if (section === undefined || section === null) { + const message = "Configuration not found"; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } const value = section.get(settingName); - if (isValidMapping(value, 'string', 'boolean')) { + if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'boolean')) { return value as Excludes; } const setting = section.inspect(settingName); + if (setting?.defaultValue === undefined || setting.defaultValue === null) { + const message = "Default value not found."; + const record: Record = { + [sectionName + "." + settingName]: message + }; + + telemetry.logLanguageServerEvent("settingsValidation", record); + } return setting?.defaultValue as Excludes; } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 247aee538d..b2bb204545 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -335,9 +335,9 @@ export function isArrayOfString(input: any): input is string[] { // Validates whether the given object is a valid mapping of key and value type. // EX: {"key": true, "key2": false} should return true for keyType = string and valueType = boolean. -export function isValidMapping(value: any, keyType: string, valueType: string): value is object { +export function isValidMapping(value: any, isValidKey: (key: any) => boolean, isValidValue: (value: any) => boolean): value is object { if (isObject(value)) { - return Object.entries(value).every(([key, val]) => typeof key === keyType && typeof val === valueType); + return Object.entries(value).every(([key, val]) => isValidKey(key) && isValidValue(val)); } return false; } From 92e99dcd48d697aa6d9284d7e918be8941b1e061 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Mon, 5 Aug 2024 18:16:21 -0700 Subject: [PATCH 40/52] Refactor loggingLevel fix, refactor setting telemetry into helper function, Add isValidWhenObject helper funciton for isValidMapping --- .../Providers/inlayHintProvider.ts | 2 +- Extension/src/LanguageServer/settings.ts | 98 ++++++------------- 2 files changed, 31 insertions(+), 69 deletions(-) diff --git a/Extension/src/LanguageServer/Providers/inlayHintProvider.ts b/Extension/src/LanguageServer/Providers/inlayHintProvider.ts index 9b427bc2cd..257703f770 100644 --- a/Extension/src/LanguageServer/Providers/inlayHintProvider.ts +++ b/Extension/src/LanguageServer/Providers/inlayHintProvider.ts @@ -203,7 +203,7 @@ export class InlayHintsProvider implements vscode.InlayHintsProvider { private resolveTypeHints(settings: CppSettings, hints: CppInlayHint[]): vscode.InlayHint[] { const resolvedHints: vscode.InlayHint[] = []; for (const hint of hints) { - const showOnLeft: boolean | undefined = settings.inlayHintsAutoDeclarationTypesShowOnLeft && hint.identifierLength > 0; + const showOnLeft: boolean = settings.inlayHintsAutoDeclarationTypesShowOnLeft && hint.identifierLength > 0; const inlayHint: vscode.InlayHint = new vscode.InlayHint( new vscode.Position(hint.line, hint.character + (showOnLeft ? 0 : hint.identifierLength)), diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 48b775b854..f2dfb97a81 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -14,7 +14,7 @@ import { quote } from 'shell-quote'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as which from 'which'; -import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; +import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getNumericLoggingLevel, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; import * as telemetry from '../telemetry'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; @@ -168,6 +168,15 @@ function getTarget(): vscode.ConfigurationTarget { return vscode.workspace.workspaceFolders ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Global; } +function isValidWhenObject(obj: unknown): obj is { when: string } { + return ( + typeof obj === 'object' && + obj !== null && + 'when' in obj && + typeof (obj as { when: unknown }).when === 'string' + ); +} + class Settings { private readonly settings: vscode.WorkspaceConfiguration; @@ -379,8 +388,7 @@ export class CppSettings extends Settings { public get doxygenGeneratedCommentStyle(): string { return this.getAsString("doxygen.generatedStyle"); } public get doxygenGenerateOnType(): boolean { return this.getAsBoolean("doxygen.generateOnType"); } public get commentContinuationPatterns(): (string | CommentPattern)[] { - // eslint-disable-next-line no-extra-parens - const value: any = super.Section.get<(any)[]>("commentContinuationPatterns"); + const value: any = super.Section.get("commentContinuationPatterns"); if (this.isArrayOfCommentContinuationPatterns(value)) { return value; } @@ -572,7 +580,7 @@ export class CppSettings extends Settings { const setting = getRawSetting("C_Cpp." + settingName); if (setting.enum !== undefined) { - if (settingName === "loggingLevel" && isNumber(Number(value)) && Number(value) >= 0) { + if (getNumericLoggingLevel(value) >= 0) { return value; } if (this.isValidEnum(setting.enum, value)) { @@ -632,7 +640,7 @@ export class CppSettings extends Settings { if (allowNull && value === null) { return null; } - if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'boolean')) { + if (isValidMapping(value, isString, (val) => typeof val === 'boolean' || isValidWhenObject(val))) { return value as Excludes; } const setting = getRawSetting("C_Cpp." + settingName); @@ -646,7 +654,7 @@ export class CppSettings extends Settings { if (allowNull && value === null) { return null; } - if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'string')) { + if (isValidMapping(value, isString, isString)) { return value as Associations; } const setting = getRawSetting("C_Cpp." + settingName); @@ -911,15 +919,14 @@ export class OtherSettings { this.resource = resource; } + private logSettingTelemetry(sectionName: string, settingName: string, error: string): void { + telemetry.logLanguageServerEvent("settingsValidation", { setting: sectionName + '.' + settingName, error }); + } + private getAsString(sectionName: string, settingName: string, resource: any, defaultValue: string): string { const section = vscode.workspace.getConfiguration(sectionName, resource); if (section === undefined || section === null) { - const message = "Configuration not found"; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); } const value = section.get(settingName); if (isString(value)) { @@ -928,12 +935,7 @@ export class OtherSettings { const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - const message = "Default value not found."; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "no default value"); return defaultValue; } return setting.defaultValue; @@ -942,12 +944,7 @@ export class OtherSettings { private getAsBoolean(sectionName: string, settingName: string, resource: any, defaultValue: boolean): boolean { const section = vscode.workspace.getConfiguration(sectionName, resource); if (section === undefined || section === null) { - const message = "Configuration not found"; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); } const value = section.get(settingName); if (isBoolean(value)) { @@ -955,12 +952,7 @@ export class OtherSettings { } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - const message = "Default value not found."; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "no default value"); return defaultValue; } return setting.defaultValue; @@ -969,12 +961,7 @@ export class OtherSettings { private getAsNumber(sectionName: string, settingName: string, resource: any, defaultValue: number, minimum?: number, maximum?: number): number { const section = vscode.workspace.getConfiguration(sectionName, resource); if (section === undefined || section === null) { - const message = "Configuration not found"; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); } const value = section.get(settingName); // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. @@ -989,12 +976,7 @@ export class OtherSettings { } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - const message = "Default value not found."; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "no default value"); return defaultValue; } return setting.defaultValue; @@ -1003,25 +985,15 @@ export class OtherSettings { private getAsAssociations(sectionName: string, settingName: string, resource?: any): Associations { const section = vscode.workspace.getConfiguration(sectionName, resource); if (section === undefined || section === null) { - const message = "Configuration not found"; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); } const value = section.get(settingName); - if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'string')) { + if (isValidMapping(value, isString, isString)) { return value as Associations; } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - const message = "Default value not found."; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "no default value"); } return setting?.defaultValue as Associations; } @@ -1029,25 +1001,15 @@ export class OtherSettings { private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { const section = vscode.workspace.getConfiguration(sectionName, resource); if (section === undefined || section === null) { - const message = "Configuration not found"; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); } const value = section.get(settingName); - if (isValidMapping(value, (key) => typeof key === 'string', (val) => typeof val === 'boolean')) { + if (isValidMapping(value, isString, (val) => typeof val === 'boolean' || isValidWhenObject(val))) { return value as Excludes; } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - const message = "Default value not found."; - const record: Record = { - [sectionName + "." + settingName]: message - }; - - telemetry.logLanguageServerEvent("settingsValidation", record); + this.logSettingTelemetry(sectionName, settingName, "no default value"); } return setting?.defaultValue as Excludes; } From 7b21861a24432c437b820187563b35f5ca3ab28b Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 6 Aug 2024 10:46:33 -0700 Subject: [PATCH 41/52] Remove unneeded checks for undefined section values. --- Extension/src/LanguageServer/settings.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index f2dfb97a81..e68925d4a2 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -925,9 +925,6 @@ export class OtherSettings { private getAsString(sectionName: string, settingName: string, resource: any, defaultValue: string): string { const section = vscode.workspace.getConfiguration(sectionName, resource); - if (section === undefined || section === null) { - this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); - } const value = section.get(settingName); if (isString(value)) { return value; @@ -943,9 +940,6 @@ export class OtherSettings { private getAsBoolean(sectionName: string, settingName: string, resource: any, defaultValue: boolean): boolean { const section = vscode.workspace.getConfiguration(sectionName, resource); - if (section === undefined || section === null) { - this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); - } const value = section.get(settingName); if (isBoolean(value)) { return value; @@ -960,9 +954,6 @@ export class OtherSettings { private getAsNumber(sectionName: string, settingName: string, resource: any, defaultValue: number, minimum?: number, maximum?: number): number { const section = vscode.workspace.getConfiguration(sectionName, resource); - if (section === undefined || section === null) { - this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); - } const value = section.get(settingName); // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. if (isNumber(value)) { @@ -984,9 +975,6 @@ export class OtherSettings { private getAsAssociations(sectionName: string, settingName: string, resource?: any): Associations { const section = vscode.workspace.getConfiguration(sectionName, resource); - if (section === undefined || section === null) { - this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); - } const value = section.get(settingName); if (isValidMapping(value, isString, isString)) { return value as Associations; @@ -1000,9 +988,6 @@ export class OtherSettings { private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { const section = vscode.workspace.getConfiguration(sectionName, resource); - if (section === undefined || section === null) { - this.logSettingTelemetry(sectionName, settingName, "setting does not exist'"); - } const value = section.get(settingName); if (isValidMapping(value, isString, (val) => typeof val === 'boolean' || isValidWhenObject(val))) { return value as Excludes; From 5bd191ddfc3a5eba2415c4e7a6fecd7ea325e07a Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 6 Aug 2024 14:03:59 -0700 Subject: [PATCH 42/52] Minor refactorings and renamings --- Extension/src/LanguageServer/settings.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index e68925d4a2..0b68338c36 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -14,7 +14,7 @@ import { quote } from 'shell-quote'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as which from 'which'; -import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getNumericLoggingLevel, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; +import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; import * as telemetry from '../telemetry'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; @@ -580,7 +580,7 @@ export class CppSettings extends Settings { const setting = getRawSetting("C_Cpp." + settingName); if (setting.enum !== undefined) { - if (getNumericLoggingLevel(value) >= 0) { + if (settingName === "loggingLevel" && isNumber(Number(value)) && Number(value) >= 0) { return value; } if (this.isValidEnum(setting.enum, value)) { @@ -640,7 +640,7 @@ export class CppSettings extends Settings { if (allowNull && value === null) { return null; } - if (isValidMapping(value, isString, (val) => typeof val === 'boolean' || isValidWhenObject(val))) { + if (isValidMapping(value, isString, (val) => isBoolean(val) || isValidWhenObject(val))) { return value as Excludes; } const setting = getRawSetting("C_Cpp." + settingName); @@ -919,7 +919,7 @@ export class OtherSettings { this.resource = resource; } - private logSettingTelemetry(sectionName: string, settingName: string, error: string): void { + private logValidationError(sectionName: string, settingName: string, error: string): void { telemetry.logLanguageServerEvent("settingsValidation", { setting: sectionName + '.' + settingName, error }); } @@ -932,7 +932,7 @@ export class OtherSettings { const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - this.logSettingTelemetry(sectionName, settingName, "no default value"); + this.logValidationError(sectionName, settingName, "no default value"); return defaultValue; } return setting.defaultValue; @@ -946,7 +946,7 @@ export class OtherSettings { } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - this.logSettingTelemetry(sectionName, settingName, "no default value"); + this.logValidationError(sectionName, settingName, "no default value"); return defaultValue; } return setting.defaultValue; @@ -967,7 +967,7 @@ export class OtherSettings { } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - this.logSettingTelemetry(sectionName, settingName, "no default value"); + this.logValidationError(sectionName, settingName, "no default value"); return defaultValue; } return setting.defaultValue; @@ -981,7 +981,7 @@ export class OtherSettings { } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - this.logSettingTelemetry(sectionName, settingName, "no default value"); + this.logValidationError(sectionName, settingName, "no default value"); } return setting?.defaultValue as Associations; } @@ -989,12 +989,12 @@ export class OtherSettings { private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { const section = vscode.workspace.getConfiguration(sectionName, resource); const value = section.get(settingName); - if (isValidMapping(value, isString, (val) => typeof val === 'boolean' || isValidWhenObject(val))) { + if (isValidMapping(value, isString, (val) => isBoolean(val) || isValidWhenObject(val))) { return value as Excludes; } const setting = section.inspect(settingName); if (setting?.defaultValue === undefined || setting.defaultValue === null) { - this.logSettingTelemetry(sectionName, settingName, "no default value"); + this.logValidationError(sectionName, settingName, "no default value"); } return setting?.defaultValue as Excludes; } From 31cb93953d6e3c78bcc3834dec439b16ddd79cd7 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 6 Aug 2024 15:05:28 -0700 Subject: [PATCH 43/52] Ensure clangFormatStyle and clangFormatFallbackStyle returns undefined to the native code. --- Extension/src/LanguageServer/client.ts | 4 ++-- Extension/src/LanguageServer/settings.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 8ce8f9e3bf..cf5c0a0853 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1338,8 +1338,8 @@ export class DefaultClient implements Client { defaultSystemIncludePath: settings.defaultSystemIncludePath, cppFilesExclude: settings.filesExclude, clangFormatPath: util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment), - clangFormatStyle: util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment), - clangFormatFallbackStyle: settings.clangFormatFallbackStyle, + clangFormatStyle: settings.clangFormatStyle ? util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment) : undefined, + clangFormatFallbackStyle: settings.clangFormatFallbackStyle ? settings.clangFormatFallbackStyle : undefined, clangFormatSortIncludes: settings.clangFormatSortIncludes, codeAnalysisRunAutomatically: settings.codeAnalysisRunAutomatically, codeAnalysisExclude: settings.codeAnalysisExclude, diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 0b68338c36..3f509945eb 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -52,7 +52,7 @@ export interface WorkspaceFolderSettingsParams { defaultSystemIncludePath: string[] | undefined; cppFilesExclude: Excludes; clangFormatPath: string | undefined; - clangFormatStyle: string; + clangFormatStyle: string | undefined; clangFormatFallbackStyle: string | undefined; clangFormatSortIncludes: boolean | undefined; codeAnalysisRunAutomatically: boolean; From 4748320eae7ffa284b57bd553cdf998ae9d2d305 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Tue, 6 Aug 2024 15:20:11 -0700 Subject: [PATCH 44/52] Fix linting issue --- Extension/src/LanguageServer/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index cf5c0a0853..1858682b5b 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1338,7 +1338,7 @@ export class DefaultClient implements Client { defaultSystemIncludePath: settings.defaultSystemIncludePath, cppFilesExclude: settings.filesExclude, clangFormatPath: util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment), - clangFormatStyle: settings.clangFormatStyle ? util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment) : undefined, + clangFormatStyle: settings.clangFormatStyle ? util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment) : undefined, clangFormatFallbackStyle: settings.clangFormatFallbackStyle ? settings.clangFormatFallbackStyle : undefined, clangFormatSortIncludes: settings.clangFormatSortIncludes, codeAnalysisRunAutomatically: settings.codeAnalysisRunAutomatically, From 306e7419f0a6c355eb7fde74b14767990ce964c6 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 7 Aug 2024 11:33:46 -0700 Subject: [PATCH 45/52] Fix issues with sending clangtidy settings. --- Extension/src/LanguageServer/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 1858682b5b..dd2e53c709 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1339,7 +1339,7 @@ export class DefaultClient implements Client { cppFilesExclude: settings.filesExclude, clangFormatPath: util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment), clangFormatStyle: settings.clangFormatStyle ? util.resolveVariables(settings.clangFormatStyle, this.AdditionalEnvironment) : undefined, - clangFormatFallbackStyle: settings.clangFormatFallbackStyle ? settings.clangFormatFallbackStyle : undefined, + clangFormatFallbackStyle: settings.clangFormatFallbackStyle, clangFormatSortIncludes: settings.clangFormatSortIncludes, codeAnalysisRunAutomatically: settings.codeAnalysisRunAutomatically, codeAnalysisExclude: settings.codeAnalysisExclude, @@ -1347,7 +1347,7 @@ export class DefaultClient implements Client { clangTidyPath: util.resolveVariables(settings.clangTidyPath, this.AdditionalEnvironment), clangTidyConfig: settings.clangTidyConfig, clangTidyFallbackConfig: settings.clangTidyFallbackConfig, - clangTidyHeaderFilter: settings.clangTidyHeaderFilter !== null ? util.resolveVariables(settings.clangTidyHeaderFilter, this.AdditionalEnvironment) : null, + clangTidyHeaderFilter: settings.clangTidyHeaderFilter !== undefined ? util.resolveVariables(settings.clangTidyHeaderFilter, this.AdditionalEnvironment) : null, clangTidyArgs: util.resolveVariablesArray(settings.clangTidyArgs, this.AdditionalEnvironment), clangTidyUseBuildPath: settings.clangTidyUseBuildPath, clangTidyChecksEnabled: settings.clangTidyChecksEnabled, From b982174e92b0f10dbf24b20150a45b03109ae666 Mon Sep 17 00:00:00 2001 From: Tarik Brown Date: Wed, 7 Aug 2024 12:17:40 -0700 Subject: [PATCH 46/52] Refactor clangtidyheaderfilter to return a null typing. --- Extension/src/LanguageServer/client.ts | 2 +- Extension/src/LanguageServer/settings.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index dd2e53c709..6d56e4538f 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1347,7 +1347,7 @@ export class DefaultClient implements Client { clangTidyPath: util.resolveVariables(settings.clangTidyPath, this.AdditionalEnvironment), clangTidyConfig: settings.clangTidyConfig, clangTidyFallbackConfig: settings.clangTidyFallbackConfig, - clangTidyHeaderFilter: settings.clangTidyHeaderFilter !== undefined ? util.resolveVariables(settings.clangTidyHeaderFilter, this.AdditionalEnvironment) : null, + clangTidyHeaderFilter: settings.clangTidyHeaderFilter !== null ? util.resolveVariables(settings.clangTidyHeaderFilter, this.AdditionalEnvironment) : null, clangTidyArgs: util.resolveVariablesArray(settings.clangTidyArgs, this.AdditionalEnvironment), clangTidyUseBuildPath: settings.clangTidyUseBuildPath, clangTidyChecksEnabled: settings.clangTidyChecksEnabled, diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 3f509945eb..310552fe38 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -344,7 +344,7 @@ export class CppSettings extends Settings { public get clangTidyEnabled(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.enabled"); } public get clangTidyConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.config")); } public get clangTidyFallbackConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.fallbackConfig")); } - public get clangTidyHeaderFilter(): string | undefined { return this.getAsStringOrUndefined("codeAnalysis.clangTidy.headerFilter"); } + public get clangTidyHeaderFilter(): string | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter", true); } public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } From 9379b2e0c4f8e359d3561e8ddd37688b13b28296 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Thu, 8 Aug 2024 17:02:56 -0700 Subject: [PATCH 47/52] Address PR feedback --- .../Providers/codeActionProvider.ts | 2 +- Extension/src/LanguageServer/client.ts | 4 +- .../src/LanguageServer/configurations.ts | 8 +- Extension/src/LanguageServer/settings.ts | 163 ++++++++++++------ Extension/src/common.ts | 6 +- 5 files changed, 122 insertions(+), 61 deletions(-) diff --git a/Extension/src/LanguageServer/Providers/codeActionProvider.ts b/Extension/src/LanguageServer/Providers/codeActionProvider.ts index 505b5171a4..6de47e15b9 100644 --- a/Extension/src/LanguageServer/Providers/codeActionProvider.ts +++ b/Extension/src/LanguageServer/Providers/codeActionProvider.ts @@ -80,7 +80,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider { let hasSelectIntelliSenseConfiguration: boolean = false; const settings: CppSettings = new CppSettings(this.client.RootUri); - const hasConfigurationSet: boolean = settings.defaultCompilerPath !== undefined || + const hasConfigurationSet: boolean = settings.defaultCompilerPath !== null || !!settings.defaultCompileCommands || !!settings.defaultConfigurationProvider || this.client.configuration.CurrentConfiguration?.compilerPath !== undefined || !!this.client.configuration.CurrentConfiguration?.compileCommands || diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 6d56e4538f..434901f82e 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -2166,7 +2166,7 @@ export class DefaultClient implements Client { public getVcpkgEnabled(): Promise { const cppSettings: CppSettings = new CppSettings(this.RootUri); - return Promise.resolve(cppSettings.isVcpkgEnabled); + return Promise.resolve(cppSettings.vcpkgEnabled); } public async getKnownCompilers(): Promise { @@ -2726,7 +2726,7 @@ export class DefaultClient implements Client { showConfigStatus = ask.Value; } - const compilerPathNotSet: boolean = settings.defaultCompilerPath === undefined && this.configuration.CurrentConfiguration?.compilerPath === undefined && this.configuration.CurrentConfiguration?.compilerPathInCppPropertiesJson === undefined; + const compilerPathNotSet: boolean = settings.defaultCompilerPath === null && this.configuration.CurrentConfiguration?.compilerPath === undefined && this.configuration.CurrentConfiguration?.compilerPathInCppPropertiesJson === undefined; const configurationNotSet: boolean = configProviderNotSetAndNoCache && compileCommandsNotSet && compilerPathNotSet; showConfigStatus = showConfigStatus || (configurationNotSet && diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 428ccc2eec..4aa5dea1cb 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -951,7 +951,7 @@ export class CppProperties { // compile_commands.json already specifies a compiler. compilerPath overrides the compile_commands.json compiler so // don't set a default when compileCommands is in use. configuration.compilerPath = this.updateConfigurationString(configuration.compilerPath, settings.defaultCompilerPath, env, true); - configuration.compilerPathIsExplicit = configuration.compilerPathIsExplicit || settings.defaultCompilerPath !== undefined; + configuration.compilerPathIsExplicit = configuration.compilerPathIsExplicit || settings.defaultCompilerPath !== null; if (configuration.compilerPath === undefined) { if (!!this.defaultCompilerPath && this.trustedCompilerFound) { // If no config value yet set for these, pick up values from the defaults, but don't consider them explicit. @@ -988,7 +988,7 @@ export class CppProperties { } else { // However, if compileCommands are used and compilerPath is explicitly set, it's still necessary to resolve variables in it. if (configuration.compilerPath === "${default}") { - configuration.compilerPath = settings.defaultCompilerPath; + configuration.compilerPath = settings.defaultCompilerPath ?? undefined; } if (configuration.compilerPath === null) { configuration.compilerPath = undefined; @@ -1041,8 +1041,8 @@ export class CppProperties { && !settings.defaultForcedInclude && !settings.defaultCompileCommands && !settings.defaultCompilerArgs - && settings.defaultCStandard === "" - && settings.defaultCppStandard === "" + && (!settings.defaultCStandard || settings.defaultCStandard === "") + && (!settings.defaultCppStandard || settings.defaultCppStandard === "") && settings.defaultIntelliSenseMode === "" && !settings.defaultConfigurationProvider; diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 310552fe38..9036f564af 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -14,7 +14,7 @@ import { quote } from 'shell-quote'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as which from 'which'; -import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; +import { getCachedClangFormatPath, getCachedClangTidyPath, getExtensionFilePath, getRawSetting, isArray, isArrayOfString, isBoolean, isNumber, isObject, isString, isValidMapping, setCachedClangFormatPath, setCachedClangTidyPath } from '../common'; import { isWindows } from '../constants'; import * as telemetry from '../telemetry'; import { DefaultClient, cachedEditorConfigLookups, cachedEditorConfigSettings, hasTrustedCompilerPaths } from './client'; @@ -54,7 +54,7 @@ export interface WorkspaceFolderSettingsParams { clangFormatPath: string | undefined; clangFormatStyle: string | undefined; clangFormatFallbackStyle: string | undefined; - clangFormatSortIncludes: boolean | undefined; + clangFormatSortIncludes: boolean | null; codeAnalysisRunAutomatically: boolean; codeAnalysisExclude: Excludes; clangTidyEnabled: boolean; @@ -64,8 +64,8 @@ export interface WorkspaceFolderSettingsParams { clangTidyHeaderFilter: string | null; clangTidyArgs: string[]; clangTidyUseBuildPath: boolean; - clangTidyChecksEnabled: string[]; - clangTidyChecksDisabled: string[]; + clangTidyChecksEnabled: string[] | undefined; + clangTidyChecksDisabled: string[] | undefined; hover: string; markdownInComments: string; vcFormatIndentBraces: boolean; @@ -272,7 +272,7 @@ export class CppSettings extends Settings { } private getClangPath(isFormat: boolean): string | undefined { - let path: string | undefined = changeBlankStringToUndefined(this.getAsString(isFormat ? "clang_format_path" : "codeAnalysis.clangTidy.path")); + let path: string | undefined = changeBlankStringToUndefined(this.getAsStringOrUndefined(isFormat ? "clang_format_path" : "codeAnalysis.clangTidy.path")); if (!path) { const cachedClangPath: string | undefined = isFormat ? getCachedClangFormatPath() : getCachedClangTidyPath(); if (cachedClangPath !== undefined) { @@ -345,25 +345,25 @@ export class CppSettings extends Settings { public get clangTidyConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.config")); } public get clangTidyFallbackConfig(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("codeAnalysis.clangTidy.fallbackConfig")); } public get clangTidyHeaderFilter(): string | null { return this.getAsString("codeAnalysis.clangTidy.headerFilter", true); } - public get clangTidyArgs(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.args"); } + public get clangTidyArgs(): string[] | undefined { return this.getAsArrayOfStringsOrUndefined("codeAnalysis.clangTidy.args"); } public get clangTidyUseBuildPath(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.useBuildPath"); } - public get clangTidyChecksEnabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.enabled", true); } - public get clangTidyChecksDisabled(): string[] { return this.getAsArrayOfStrings("codeAnalysis.clangTidy.checks.disabled", true); } + public get clangTidyChecksEnabled(): string[] | undefined { return this.getAsArrayOfStringsOrUndefined("codeAnalysis.clangTidy.checks.enabled", true); } + public get clangTidyChecksDisabled(): string[] | undefined { return this.getAsArrayOfStringsOrUndefined("codeAnalysis.clangTidy.checks.disabled", true); } public get clangTidyCodeActionShowDisable(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDisable"); } public get clangTidyCodeActionShowClear(): string { return this.getAsString("codeAnalysis.clangTidy.codeAction.showClear"); } public get clangTidyCodeActionShowDocumentation(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.showDocumentation"); } public get clangTidyCodeActionFormatFixes(): boolean { return this.getAsBoolean("codeAnalysis.clangTidy.codeAction.formatFixes"); } public addClangTidyChecksDisabled(value: string): void { - const checks: string[] = this.clangTidyChecksDisabled; + const checks: string[] | undefined = this.clangTidyChecksDisabled; if (checks === undefined) { return; } checks.push(value); void super.Section.update("codeAnalysis.clangTidy.checks.disabled", checks, vscode.ConfigurationTarget.WorkspaceFolder); } - public get clangFormatStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("clang_format_style")); } + public get clangFormatStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsString("clang_format_style")); } public get clangFormatFallbackStyle(): string | undefined { return changeBlankStringToUndefined(this.getAsString("clang_format_fallbackStyle")); } - public get clangFormatSortIncludes(): boolean | undefined { return this.getAsBooleanOrUndefined("clang_format_sortIncludes"); } + public get clangFormatSortIncludes(): boolean | null { return this.getAsBoolean("clang_format_sortIncludes", true); } public get experimentalFeatures(): boolean { return this.getAsString("experimentalFeatures").toLowerCase() === "enabled"; } public get suggestSnippets(): boolean { return this.getAsBoolean("suggestSnippets"); } public get intelliSenseEngine(): string { return this.getAsString("intelliSenseEngine"); } @@ -392,13 +392,13 @@ export class CppSettings extends Settings { if (this.isArrayOfCommentContinuationPatterns(value)) { return value; } - const setting = getRawSetting("C_Cpp." + "commentContinuationPatterns"); + const setting = getRawSetting("C_Cpp.commentContinuationPatterns"); return setting.default; } public get isConfigurationWarningsEnabled(): boolean { return this.getAsString("configurationWarnings").toLowerCase() === "enabled"; } public get preferredPathSeparator(): string { return this.getAsString("preferredPathSeparator"); } public get updateChannel(): string { return this.getAsString("updateChannel"); } - public get isVcpkgEnabled(): boolean { return this.getAsString("vcpkg").toLowerCase() === "enabled"; } + public get vcpkgEnabled(): boolean { return this.getAsBoolean("vcpkg.enabled"); } public get addNodeAddonIncludePaths(): boolean { return this.getAsBoolean("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean { return this.getAsBoolean("renameRequiresIdentifier"); } public get filesExclude(): Excludes { return this.getAsExcludes("files.exclude"); } @@ -410,7 +410,7 @@ export class CppSettings extends Settings { public get defaultCompileCommands(): string | undefined { return changeBlankStringToUndefined(this.getAsStringOrUndefined("default.compileCommands")); } public get defaultForcedInclude(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.forcedInclude"); } public get defaultIntelliSenseMode(): string | undefined { return this.getAsStringOrUndefined("default.intelliSenseMode"); } - public get defaultCompilerPath(): string | undefined { return this.getAsStringOrUndefined("default.compilerPath"); } + public get defaultCompilerPath(): string | null { return this.getAsString("default.compilerPath", true); } public set defaultCompilerPath(value: string) { const defaultCompilerPathStr: string = "default.compilerPath"; @@ -433,8 +433,8 @@ export class CppSettings extends Settings { } } public get defaultCompilerArgs(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.compilerArgs"); } - public get defaultCStandard(): string { return this.getAsString("default.cStandard"); } - public get defaultCppStandard(): string { return this.getAsString("default.cppStandard"); } + 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 defaultBrowsePath(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.browse.path"); } @@ -531,27 +531,34 @@ export class CppSettings extends Settings { private getAsStringOrUndefined(settingName: string): string | undefined { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); + if (setting.default !== undefined) { + console.error(`Default value for ${settingName} is expected to be undefined.`); + } + if (setting.enum !== undefined) { if (this.isValidEnum(setting.enum, value)) { return value; } - return setting.default; - } - if (isString(value)) { + } else if (isString(value)) { return value; - } else { - return undefined; } + + 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(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (setting.default !== undefined) { + console.error(`Default value for ${settingName} is expected to be undefined.`); + } + if (isBoolean(value)) { return value; - } else { - return undefined; } + + return undefined; } // Returns the value of a setting as a boolean with proper type validation. @@ -559,13 +566,18 @@ export class CppSettings extends Settings { private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (!isBoolean(setting.default) && !(allowNull && setting.default === null)) { + console.error(`Default value for ${settingName} is expected to be boolean or null.`); + } + if (allowNull && value === null) { return null; } + if (isBoolean(value)) { return value; } - const setting = getRawSetting("C_Cpp." + settingName); return setting.default; } @@ -574,24 +586,26 @@ export class CppSettings extends Settings { private getAsString(settingName: string, allowNull: boolean): string | null; private getAsString(settingName: string, allowNull: boolean = false): string | null { const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (!isString(setting.default) && !(allowNull && setting.default === null)) { + console.error(`Default value for ${settingName} is expected to be string or null.`); + } + if (allowNull && value === null) { return null; } - const setting = getRawSetting("C_Cpp." + settingName); if (setting.enum !== undefined) { - if (settingName === "loggingLevel" && isNumber(Number(value)) && Number(value) >= 0) { + if (settingName === "loggingLevel" && isString(value) && isNumber(Number(value)) && Number(value) >= 0) { return value; } if (this.isValidEnum(setting.enum, value)) { return value; } - return setting.default; - } - if (isString(value)) { + } else if (isString(value)) { return value; } - return setting.default; + return setting.default as string; } // Returns the value of a setting as a number with proper type validation and checks if value falls within the specified range. @@ -599,10 +613,14 @@ export class CppSettings extends Settings { private getAsNumber(settingName: string, allowNull: boolean): number | null; private getAsNumber(settingName: string, allowNull: boolean = false): number | null { const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (!isNumber(setting.default) && !(allowNull && setting.default === null)) { + console.error(`Default value for ${settingName} is expected to be number or null.`); + } + if (allowNull && value === null) { return null; } - const setting = getRawSetting("C_Cpp." + settingName); // Validates the value is a number and clamps it to the specified range. Allows for undefined maximum or minimum values. if (isNumber(value)) { if (setting.minimum !== undefined && value < setting.minimum) { @@ -613,37 +631,63 @@ export class CppSettings extends Settings { } return value; } - return setting.default; + return setting.default as number; + } + + private getAsArrayOfStringsOrUndefined(settingName: string, allowUndefinedEnums: boolean = false): string[] | undefined { + const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (setting.default !== undefined) { + console.error(`Default value for ${settingName} is expected to be undefined.`); + } + + if (isArrayOfString(value)) { + if (setting.items.enum && !allowUndefinedEnums) { + if (!value.every(x => this.isValidEnum(setting.items.enum, x))) { + return setting.default; + } + } + return value; + } + return setting.default as string[]; } + + // Returns the value of a setting as an array of strings with proper type validation and checks for valid enum values. private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); + if (!isArrayOfString(setting.default)) { + console.error(`Default value for ${settingName} is expected to be string[].`); + } + if (isArrayOfString(value)) { - if (!allowUndefinedEnums) { - if (setting.items.enum !== undefined) { - if (!value.every(x => this.isValidEnum(setting.items.enum, x))) { - return setting.default; - } + if (setting.items.enum && !allowUndefinedEnums) { + if (!value.every(x => this.isValidEnum(setting.items.enum, x))) { + return setting.default; } } return value; } - return setting.default; + return setting.default as string[]; } private getAsExcludes(settingName: string): Excludes; private getAsExcludes(settingName: string, allowNull: boolean): Excludes | null; private getAsExcludes(settingName: string, allowNull: boolean = false): Excludes | null { const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (!isValidMapping(setting.default, isString, val => isBoolean(val) || isValidWhenObject(val)) && !(allowNull && setting.default === null)) { + console.error(`Default value for ${settingName} is expected to be Excludes or null.`); + } + if (allowNull && value === null) { return null; } - if (isValidMapping(value, isString, (val) => isBoolean(val) || isValidWhenObject(val))) { + if (isValidMapping(value, isString, val => isBoolean(val) || isValidWhenObject(val))) { return value as Excludes; } - const setting = getRawSetting("C_Cpp." + settingName); return setting.default as Excludes; } @@ -651,19 +695,23 @@ export class CppSettings extends Settings { private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { const value: any = super.Section.get(settingName); + const setting = getRawSetting("C_Cpp." + settingName); + if (!isValidMapping(setting.default, isString, isString) && !(allowNull && setting.default === null)) { + console.error(`Default value for ${settingName} is expected to be Associations or null.`); + } + if (allowNull && value === null) { return null; } if (isValidMapping(value, isString, isString)) { return value as Associations; } - const setting = getRawSetting("C_Cpp." + settingName); return setting.default as Associations; } // Checks a given enum value against a list of valid enum values from package.json. - private isValidEnum(enumDescription: any, value: any): boolean { - if (isArray(enumDescription) && enumDescription.length > 0) { + private isValidEnum(enumDescription: any, value: any): value is string { + if (isString(value) && isArray(enumDescription) && enumDescription.length > 0) { return enumDescription.some(x => x.toLowerCase() === value.toLowerCase()); } return false; @@ -674,7 +722,7 @@ export class CppSettings extends Settings { } private isCommentPattern(x: any): x is CommentPattern { - return isString(x.begin) && isString(x.continue); + return isObject(x) && isString(x.begin) && isString(x.continue); } public toggleSetting(name: string, value1: string, value2: string): void { @@ -973,7 +1021,7 @@ export class OtherSettings { return setting.defaultValue; } - private getAsAssociations(sectionName: string, settingName: string, resource?: any): Associations { + private getAsAssociations(sectionName: string, settingName: string, defaultValue: Associations, resource?: any): Associations { const section = vscode.workspace.getConfiguration(sectionName, resource); const value = section.get(settingName); if (isValidMapping(value, isString, isString)) { @@ -983,10 +1031,10 @@ export class OtherSettings { if (setting?.defaultValue === undefined || setting.defaultValue === null) { this.logValidationError(sectionName, settingName, "no default value"); } - return setting?.defaultValue as Associations; + return setting?.defaultValue ?? defaultValue; } - private getAsExcludes(sectionName: string, settingName: string, resource?: any): Excludes { + private getAsExcludes(sectionName: string, settingName: string, defaultValue: Excludes, resource?: any): Excludes { const section = vscode.workspace.getConfiguration(sectionName, resource); const value = section.get(settingName); if (isValidMapping(value, isString, (val) => isBoolean(val) || isValidWhenObject(val))) { @@ -996,7 +1044,7 @@ export class OtherSettings { if (setting?.defaultValue === undefined || setting.defaultValue === null) { this.logValidationError(sectionName, settingName, "no default value"); } - return setting?.defaultValue as Excludes; + return setting?.defaultValue ?? defaultValue; } // All default values are obtained from the VS Code settings UI. Please update the default values as needed. @@ -1004,13 +1052,26 @@ export class OtherSettings { public get editorInsertSpaces(): boolean { return this.getAsBoolean("editor", "insertSpaces", this.resource, true); } public get editorAutoClosingBrackets(): string { return this.getAsString("editor", "autoClosingBrackets", this.resource, "languageDefined"); } public get filesEncoding(): string { return this.getAsString("files", "encoding", { uri: this.resource, languageId: "cpp" }, "utf8"); } - public get filesAssociations(): Associations { return this.getAsAssociations("files", "associations"); } + public get filesAssociations(): Associations { return this.getAsAssociations("files", "associations", {}); } public set filesAssociations(value: any) { void vscode.workspace.getConfiguration("files").update("associations", value, vscode.ConfigurationTarget.Workspace); } - public get filesExclude(): Excludes { return this.getAsExcludes("files", "exclude", this.resource); } + private readonly defaultFilesExcludes = { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true + }; + public get filesExclude(): Excludes { return this.getAsExcludes("files", "exclude", this.defaultFilesExcludes, this.resource); } public get filesAutoSaveAfterDelay(): boolean { return this.getAsString("files", "autoSave", this.resource, "off") === "afterDelay"; } public get editorInlayHintsEnabled(): boolean { return this.getAsString("editor.inlayHints", "enabled", this.resource, "on") !== "off"; } public get editorParameterHintsEnabled(): boolean { return this.getAsBoolean("editor.parameterHints", "enabled", this.resource, true); } - public get searchExclude(): Excludes { return this.getAsExcludes("search", "exclude", this.resource); } + private readonly defaultSearchExcludes = { + "**/node_modules": true, + "**/bower_components": true, + "**/*.code-search": true + }; + public get searchExclude(): Excludes { return this.getAsExcludes("search", "exclude", this.defaultSearchExcludes, this.resource); } public get workbenchSettingsEditor(): string { return this.getAsString("workbench.settings", "editor", this.resource, "ui"); } } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index b2bb204545..c91749f240 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -317,12 +317,12 @@ export function isBoolean(input: any): input is boolean { return typeof input === "boolean"; } -export function isObject(input: any): input is object { - return typeof input === "object"; +export function isObject(input: any): boolean { + return input !== null && typeof input === "object" && !isArray(input); } export function isArray(input: any): input is any[] { - return input instanceof Array; + return Array.isArray(input); } export function isOptionalString(input: any): input is string | undefined { From fe539d5552ae28a72a37b64dc35db7db0b1a27f3 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Thu, 8 Aug 2024 17:03:41 -0700 Subject: [PATCH 48/52] lint --- Extension/src/LanguageServer/settings.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 9036f564af..a8ca1361ac 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -433,7 +433,7 @@ export class CppSettings extends Settings { } } public get defaultCompilerArgs(): string[] | undefined { return this.getArrayOfStringsWithUndefinedDefault("default.compilerArgs"); } - public get defaultCStandard(): string | undefined{ return this.getAsStringOrUndefined("default.cStandard"); } + 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"); } @@ -652,8 +652,6 @@ export class CppSettings extends Settings { return setting.default as string[]; } - - // Returns the value of a setting as an array of strings with proper type validation and checks for valid enum values. private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { const value: any = super.Section.get(settingName); From 986655277b5356ce6f5337256bbca3bff7d4f9b1 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 9 Aug 2024 10:32:32 -0700 Subject: [PATCH 49/52] PR feedback --- .../src/LanguageServer/configurations.ts | 4 ++-- Extension/src/LanguageServer/settings.ts | 24 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 4aa5dea1cb..6411895642 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -1041,8 +1041,8 @@ export class CppProperties { && !settings.defaultForcedInclude && !settings.defaultCompileCommands && !settings.defaultCompilerArgs - && (!settings.defaultCStandard || settings.defaultCStandard === "") - && (!settings.defaultCppStandard || settings.defaultCppStandard === "") + && !settings.defaultCStandard + && !settings.defaultCppStandard && settings.defaultIntelliSenseMode === "" && !settings.defaultConfigurationProvider; diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index a8ca1361ac..2b1557631a 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -561,14 +561,18 @@ export class CppSettings extends Settings { return undefined; } + private isValidDefault(isValid: (x: any) => boolean, value: any, allowNull: boolean): boolean { + return isValid(value) || (allowNull && value === null); + } + // Returns the value of a setting as a boolean with proper type validation. private getAsBoolean(settingName: string): boolean; private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (!isBoolean(setting.default) && !(allowNull && setting.default === null)) { - console.error(`Default value for ${settingName} is expected to be boolean or null.`); + if (!this.isValidDefault(isBoolean, setting.default, allowNull)) { + console.error(`Default value for ${settingName} is expected to be boolean${allowNull ? ' or null' : ''}.`); } if (allowNull && value === null) { @@ -587,8 +591,8 @@ export class CppSettings extends Settings { private getAsString(settingName: string, allowNull: boolean = false): string | null { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (!isString(setting.default) && !(allowNull && setting.default === null)) { - console.error(`Default value for ${settingName} is expected to be string or null.`); + if (!this.isValidDefault(isString, setting.default, allowNull)) { + console.error(`Default value for ${settingName} is expected to be string${allowNull ? ' or null' : ''}.`); } if (allowNull && value === null) { @@ -614,8 +618,8 @@ export class CppSettings extends Settings { private getAsNumber(settingName: string, allowNull: boolean = false): number | null { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (!isNumber(setting.default) && !(allowNull && setting.default === null)) { - console.error(`Default value for ${settingName} is expected to be number or null.`); + if (!this.isValidDefault(isNumber, setting.default, allowNull)) { + console.error(`Default value for ${settingName} is expected to be number${allowNull ? ' or null' : ''}.`); } if (allowNull && value === null) { @@ -676,8 +680,8 @@ export class CppSettings extends Settings { private getAsExcludes(settingName: string, allowNull: boolean = false): Excludes | null { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (!isValidMapping(setting.default, isString, val => isBoolean(val) || isValidWhenObject(val)) && !(allowNull && setting.default === null)) { - console.error(`Default value for ${settingName} is expected to be Excludes or null.`); + if (!this.isValidDefault(x => isValidMapping(x, isString, val => isBoolean(val) || isValidWhenObject(val)), setting.default, allowNull)) { + console.error(`Default value for ${settingName} is expected to be Excludes${allowNull ? ' or null' : ''}.`); } if (allowNull && value === null) { @@ -694,8 +698,8 @@ export class CppSettings extends Settings { private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { const value: any = super.Section.get(settingName); const setting = getRawSetting("C_Cpp." + settingName); - if (!isValidMapping(setting.default, isString, isString) && !(allowNull && setting.default === null)) { - console.error(`Default value for ${settingName} is expected to be Associations or null.`); + if (!this.isValidDefault(x => isValidMapping(x, isString, isString), setting.default, allowNull)) { + console.error(`Default value for ${settingName} is expected to be Associations${allowNull ? ' or null' : ''}.`); } if (allowNull && value === null) { From 29d0bca2833b84309079f0fb8cd5d1cc95da81e6 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 9 Aug 2024 10:48:15 -0700 Subject: [PATCH 50/52] Revised break for getRawSetting --- Extension/src/LanguageServer/settings.ts | 20 ++++++++++---------- Extension/src/common.ts | 8 ++++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 2b1557631a..b9925ffa5c 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -392,7 +392,7 @@ export class CppSettings extends Settings { if (this.isArrayOfCommentContinuationPatterns(value)) { return value; } - const setting = getRawSetting("C_Cpp.commentContinuationPatterns"); + const setting = getRawSetting("C_Cpp.commentContinuationPatterns", true); return setting.default; } public get isConfigurationWarningsEnabled(): boolean { return this.getAsString("configurationWarnings").toLowerCase() === "enabled"; } @@ -530,7 +530,7 @@ export class CppSettings extends Settings { // Returns the value of a setting as a string with proper type validation and checks for valid enum values while returning an undefined value if necessary. private getAsStringOrUndefined(settingName: string): string | undefined { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (setting.default !== undefined) { console.error(`Default value for ${settingName} is expected to be undefined.`); } @@ -549,7 +549,7 @@ export class CppSettings extends Settings { // 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(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (setting.default !== undefined) { console.error(`Default value for ${settingName} is expected to be undefined.`); } @@ -570,7 +570,7 @@ export class CppSettings extends Settings { private getAsBoolean(settingName: string, allowNull: boolean): boolean | null; private getAsBoolean(settingName: string, allowNull: boolean = false): boolean | null { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (!this.isValidDefault(isBoolean, setting.default, allowNull)) { console.error(`Default value for ${settingName} is expected to be boolean${allowNull ? ' or null' : ''}.`); } @@ -590,7 +590,7 @@ export class CppSettings extends Settings { private getAsString(settingName: string, allowNull: boolean): string | null; private getAsString(settingName: string, allowNull: boolean = false): string | null { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (!this.isValidDefault(isString, setting.default, allowNull)) { console.error(`Default value for ${settingName} is expected to be string${allowNull ? ' or null' : ''}.`); } @@ -617,7 +617,7 @@ export class CppSettings extends Settings { private getAsNumber(settingName: string, allowNull: boolean): number | null; private getAsNumber(settingName: string, allowNull: boolean = false): number | null { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (!this.isValidDefault(isNumber, setting.default, allowNull)) { console.error(`Default value for ${settingName} is expected to be number${allowNull ? ' or null' : ''}.`); } @@ -640,7 +640,7 @@ export class CppSettings extends Settings { private getAsArrayOfStringsOrUndefined(settingName: string, allowUndefinedEnums: boolean = false): string[] | undefined { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (setting.default !== undefined) { console.error(`Default value for ${settingName} is expected to be undefined.`); } @@ -659,7 +659,7 @@ export class CppSettings extends Settings { // Returns the value of a setting as an array of strings with proper type validation and checks for valid enum values. private getAsArrayOfStrings(settingName: string, allowUndefinedEnums: boolean = false): string[] { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (!isArrayOfString(setting.default)) { console.error(`Default value for ${settingName} is expected to be string[].`); } @@ -679,7 +679,7 @@ export class CppSettings extends Settings { private getAsExcludes(settingName: string, allowNull: boolean): Excludes | null; private getAsExcludes(settingName: string, allowNull: boolean = false): Excludes | null { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (!this.isValidDefault(x => isValidMapping(x, isString, val => isBoolean(val) || isValidWhenObject(val)), setting.default, allowNull)) { console.error(`Default value for ${settingName} is expected to be Excludes${allowNull ? ' or null' : ''}.`); } @@ -697,7 +697,7 @@ export class CppSettings extends Settings { private getAsAssociations(settingName: string, allowNull: boolean): Associations | null; private getAsAssociations(settingName: string, allowNull: boolean = false): Associations | null { const value: any = super.Section.get(settingName); - const setting = getRawSetting("C_Cpp." + settingName); + const setting = getRawSetting("C_Cpp." + settingName, true); if (!this.isValidDefault(x => isValidMapping(x, isString, isString), setting.default, allowNull)) { console.error(`Default value for ${settingName} is expected to be Associations${allowNull ? ' or null' : ''}.`); } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index c91749f240..b926db3ac3 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -65,7 +65,7 @@ export const packageJson: any = vscode.extensions.getExtension("ms-vscode.cpptoo // Use getRawSetting to get subcategorized settings from package.json. // This prevents having to iterate every time we search. let flattenedPackageJson: Map; -export function getRawSetting(key: string): any { +export function getRawSetting(key: string, breakIfMissing: boolean = false): any { if (flattenedPackageJson === undefined) { flattenedPackageJson = new Map(); for (const subheading of packageJson.contributes.configuration) { @@ -74,7 +74,11 @@ export function getRawSetting(key: string): any { } } } - return flattenedPackageJson.get(key); + const result = flattenedPackageJson.get(key); + if (result === undefined && breakIfMissing) { + debugger; // The setting does not exist in package.json. Check the `key`. + } + return result; } export async function getRawJson(path: string | undefined): Promise { From f3dbe08a2f54f378403fd8e6f5ddfb0039c3ccf8 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 9 Aug 2024 11:07:31 -0700 Subject: [PATCH 51/52] lint --- Extension/src/common.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/Extension/src/common.ts b/Extension/src/common.ts index b926db3ac3..bf2f6adcaf 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -76,6 +76,7 @@ export function getRawSetting(key: string, breakIfMissing: boolean = false): any } const result = flattenedPackageJson.get(key); if (result === undefined && breakIfMissing) { + // eslint-disable-next-line no-debugger debugger; // The setting does not exist in package.json. Check the `key`. } return result; From 43ce5f9ccfc2e1290232593ad4b0a4b8c1851662 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 9 Aug 2024 11:47:19 -0700 Subject: [PATCH 52/52] Fix a few remaining types --- Extension/src/LanguageServer/settings.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index b9925ffa5c..95afd2c480 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -43,7 +43,7 @@ export interface WorkspaceFolderSettingsParams { errorSquiggles: string; exclusionPolicy: string; preferredPathSeparator: string; - intelliSenseCachePath: string | undefined; + intelliSenseCachePath: string; intelliSenseCacheSize: number; intelliSenseMemoryLimit: number; dimInactiveRegions: boolean; @@ -51,14 +51,14 @@ export interface WorkspaceFolderSettingsParams { legacyCompilerArgsBehavior: boolean; defaultSystemIncludePath: string[] | undefined; cppFilesExclude: Excludes; - clangFormatPath: string | undefined; + clangFormatPath: string; clangFormatStyle: string | undefined; clangFormatFallbackStyle: string | undefined; clangFormatSortIncludes: boolean | null; codeAnalysisRunAutomatically: boolean; codeAnalysisExclude: Excludes; clangTidyEnabled: boolean; - clangTidyPath: string | undefined; + clangTidyPath: string; clangTidyConfig: string | undefined; clangTidyFallbackConfig: string | undefined; clangTidyHeaderFilter: string | null;