From f88bae28fe36829dd12ff8078b28ac598a7e0f63 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Wed, 30 Sep 2026 18:15:08 -0700 Subject: [PATCH 1/2] Send include cleanup editorconfig preferences --- Extension/src/LanguageServer/client.ts | 26 +++++++++------ .../includeCleanupEditorConfig.ts | 20 ++++++++++++ .../unit/includeCleanupEditorConfig.test.ts | 32 +++++++++++++++++++ 3 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 Extension/src/LanguageServer/includeCleanupEditorConfig.ts create mode 100644 Extension/test/unit/includeCleanupEditorConfig.test.ts diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 77ac15102..83599391c 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -55,6 +55,7 @@ import { CustomConfigurationProvider1, getCustomConfigProviders, isSameProviderE import { DataBinding } from './dataBinding'; import { cachedEditorConfigSettings, getEditorConfigSettings } from './editorConfig'; import { CppSourceStr, clients, configPrefix, initializeIntervalTimer, isWritingCrashCallStack, updateLanguageConfigurations, usesCrashHandler, watchForCrashes } from './extension'; +import { IncludeCleanupPreferences, getIncludeCleanupPreferences } from './includeCleanupEditorConfig'; import { LanguageClient } from './languageClient'; import { LocalizeStringParams, getLocaleId, getLocalizedString } from './localization'; import { PersistentFolderState, PersistentState, PersistentWorkspaceState } from './persistentState'; @@ -511,6 +512,7 @@ interface TagParseStatus { interface VisibleEditorInfo { visibleRanges: Range[]; originalEncoding: string; + includeCleanupPreferences: IncludeCleanupPreferences; } interface DidChangeVisibleTextEditorsParams { @@ -1929,9 +1931,11 @@ export class DefaultClient implements Client { // First, we just concat all ranges for the same file. const uri: string = editor.document.uri.toString(); if (!visibileEditorInfo[uri]) { + const editorConfigSettings: any = getEditorConfigSettings(editor.document.uri.fsPath); visibileEditorInfo[uri] = { visibleRanges: [], - originalEncoding: editor.document.encoding + originalEncoding: editor.document.encoding, + includeCleanupPreferences: getIncludeCleanupPreferences(editorConfigSettings) }; } visibileEditorInfo[uri].visibleRanges = visibileEditorInfo[uri].visibleRanges.concat(editor.visibleRanges.map(makeLspRange)); @@ -2684,6 +2688,15 @@ export class DefaultClient implements Client { private associations_for_did_change?: Set; + private refreshEditorConfigSettings(): void { + cachedEditorConfigSettings.clear(); + cachedEditorConfigLookups.clear(); + this.updateActiveDocumentTextOptions(); + + const cppEditors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(editor => util.isCpp(editor.document)); + void this.onDidChangeVisibleTextEditors(cppEditors).catch(logAndReturn.undefined); + } + /** * listen for file created/deleted events under the ${workspaceFolder} folder */ @@ -2704,9 +2717,7 @@ export class DefaultClient implements Client { } const fileName: string = path.basename(uri.fsPath).toLowerCase(); if (fileName === ".editorconfig") { - cachedEditorConfigSettings.clear(); - cachedEditorConfigLookups.clear(); - this.updateActiveDocumentTextOptions(); + this.refreshEditorConfigSettings(); } if (fileName === ".clang-format" || fileName === "_clang-format") { cachedEditorConfigLookups.clear(); @@ -2732,9 +2743,7 @@ export class DefaultClient implements Client { const dotIndex: number = uri.fsPath.lastIndexOf('.'); const fileName: string = path.basename(uri.fsPath).toLowerCase(); if (fileName === ".editorconfig") { - cachedEditorConfigSettings.clear(); - cachedEditorConfigLookups.clear(); - this.updateActiveDocumentTextOptions(); + this.refreshEditorConfigSettings(); } const ext: string | undefined = dotIndex !== -1 ? uri.fsPath.substring(dotIndex + 1) : undefined; const isTrackedFile: boolean = hasNativeFileTypeMappings() @@ -2759,8 +2768,7 @@ export class DefaultClient implements Client { } const fileName: string = path.basename(uri.fsPath).toLowerCase(); if (fileName === ".editorconfig") { - cachedEditorConfigSettings.clear(); - cachedEditorConfigLookups.clear(); + this.refreshEditorConfigSettings(); } if (fileName === ".clang-format" || fileName === "_clang-format") { cachedEditorConfigLookups.clear(); diff --git a/Extension/src/LanguageServer/includeCleanupEditorConfig.ts b/Extension/src/LanguageServer/includeCleanupEditorConfig.ts new file mode 100644 index 000000000..a78f19cdc --- /dev/null +++ b/Extension/src/LanguageServer/includeCleanupEditorConfig.ts @@ -0,0 +1,20 @@ +export interface IncludeCleanupPreferences { + alternateFiles: string; + excludedFiles: string; + replacementFiles: string; + requiredFiles: string; +} + +function getStringSetting(settings: any, key: string): string { + const value: unknown = settings?.[key]; + return typeof value === 'string' && value.toLowerCase() !== 'unset' ? value : ''; +} + +export function getIncludeCleanupPreferences(settings: any): IncludeCleanupPreferences { + return { + alternateFiles: getStringSetting(settings, 'cpp_include_cleanup_alternate_files'), + excludedFiles: getStringSetting(settings, 'cpp_include_cleanup_excluded_files'), + replacementFiles: getStringSetting(settings, 'cpp_include_cleanup_replacement_files'), + requiredFiles: getStringSetting(settings, 'cpp_include_cleanup_required_files') + }; +} \ No newline at end of file diff --git a/Extension/test/unit/includeCleanupEditorConfig.test.ts b/Extension/test/unit/includeCleanupEditorConfig.test.ts new file mode 100644 index 000000000..54d64ea68 --- /dev/null +++ b/Extension/test/unit/includeCleanupEditorConfig.test.ts @@ -0,0 +1,32 @@ +import { deepStrictEqual } from 'assert'; +import { describe, it } from 'mocha'; +import { getIncludeCleanupPreferences } from '../../src/LanguageServer/includeCleanupEditorConfig'; + +describe('Include Cleanup editorconfig settings', () => { + it('maps semantic preference strings', () => { + deepStrictEqual(getIncludeCleanupPreferences({ + cpp_include_cleanup_alternate_files: 'umbrella.h:internal.h', + cpp_include_cleanup_excluded_files: 'generated.h', + cpp_include_cleanup_replacement_files: 'stdio.h:cstdio', + cpp_include_cleanup_required_files: 'atlwin.h:atlbase.h' + }), { + alternateFiles: 'umbrella.h:internal.h', + excludedFiles: 'generated.h', + replacementFiles: 'stdio.h:cstdio', + requiredFiles: 'atlwin.h:atlbase.h' + }); + }); + + it('ignores unset and non-string values', () => { + deepStrictEqual(getIncludeCleanupPreferences({ + cpp_include_cleanup_alternate_files: 'unset', + cpp_include_cleanup_excluded_files: true, + cpp_include_cleanup_replacement_files: 42 + }), { + alternateFiles: '', + excludedFiles: '', + replacementFiles: '', + requiredFiles: '' + }); + }); +}); \ No newline at end of file From bfd9f5ec7bd9bb42af9ac89f516f0d395468fcc8 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Wed, 30 Sep 2026 18:23:19 -0700 Subject: [PATCH 2/2] Fix editorconfig helper lint --- Extension/src/LanguageServer/includeCleanupEditorConfig.ts | 7 +++++-- Extension/test/unit/includeCleanupEditorConfig.test.ts | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Extension/src/LanguageServer/includeCleanupEditorConfig.ts b/Extension/src/LanguageServer/includeCleanupEditorConfig.ts index a78f19cdc..69cc3f31c 100644 --- a/Extension/src/LanguageServer/includeCleanupEditorConfig.ts +++ b/Extension/src/LanguageServer/includeCleanupEditorConfig.ts @@ -7,7 +7,10 @@ export interface IncludeCleanupPreferences { function getStringSetting(settings: any, key: string): string { const value: unknown = settings?.[key]; - return typeof value === 'string' && value.toLowerCase() !== 'unset' ? value : ''; + if (typeof value !== 'string' || value.toLowerCase() === 'unset') { + return ''; + } + return value; } export function getIncludeCleanupPreferences(settings: any): IncludeCleanupPreferences { @@ -17,4 +20,4 @@ export function getIncludeCleanupPreferences(settings: any): IncludeCleanupPrefe replacementFiles: getStringSetting(settings, 'cpp_include_cleanup_replacement_files'), requiredFiles: getStringSetting(settings, 'cpp_include_cleanup_required_files') }; -} \ No newline at end of file +} diff --git a/Extension/test/unit/includeCleanupEditorConfig.test.ts b/Extension/test/unit/includeCleanupEditorConfig.test.ts index 54d64ea68..427c35e62 100644 --- a/Extension/test/unit/includeCleanupEditorConfig.test.ts +++ b/Extension/test/unit/includeCleanupEditorConfig.test.ts @@ -17,7 +17,7 @@ describe('Include Cleanup editorconfig settings', () => { }); }); - it('ignores unset and non-string values', () => { + it('maps unset and non-string values to empty strings', () => { deepStrictEqual(getIncludeCleanupPreferences({ cpp_include_cleanup_alternate_files: 'unset', cpp_include_cleanup_excluded_files: true, @@ -29,4 +29,4 @@ describe('Include Cleanup editorconfig settings', () => { requiredFiles: '' }); }); -}); \ No newline at end of file +});