Add setting to always show advanced settings (#283592)

* Initial plan

* Add workbench.settings.alwaysShowAdvancedSettings setting with insiders default

Co-authored-by: sandy081 <10746682+sandy081@users.noreply.github.com>

* Add configuration change handler to refresh view when alwaysShowAdvancedSettings changes

Co-authored-by: sandy081 <10746682+sandy081@users.noreply.github.com>

* polish

* polish

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sandy081 <10746682+sandy081@users.noreply.github.com>
Co-authored-by: Sandeep Somavarapu <sasomava@microsoft.com>
This commit is contained in:
Copilot
2025-12-15 16:45:07 +00:00
committed by GitHub
co-authored by sandy081 Sandeep Somavarapu
parent 9060979c6d
commit 473f563b6b
5 changed files with 52 additions and 6 deletions
@@ -7,6 +7,7 @@ import { isStandalone } from '../../base/browser/browser.js';
import { isLinux, isMacintosh, isNative, isWeb, isWindows } from '../../base/common/platform.js';
import { localize } from '../../nls.js';
import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationRegistry } from '../../platform/configuration/common/configurationRegistry.js';
import product from '../../platform/product/common/product.js';
import { Registry } from '../../platform/registry/common/platform.js';
import { ConfigurationKeyValuePairs, ConfigurationMigrationWorkbenchContribution, DynamicWindowConfiguration, DynamicWorkbenchSecurityConfiguration, Extensions, IConfigurationMigrationRegistry, problemsConfigurationNodeBase, windowConfigurationNodeBase, workbenchConfigurationNodeBase } from '../common/configuration.js';
import { WorkbenchPhase, registerWorkbenchContribution2 } from '../common/contributions.js';
@@ -533,6 +534,11 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
'description': localize('openDefaultKeybindings', "Controls whether opening keybinding settings also opens an editor showing all default keybindings."),
'default': false
},
'workbench.settings.alwaysShowAdvancedSettings': {
'type': 'boolean',
'description': localize('alwaysShowAdvancedSettings', "Controls whether advanced settings are always shown in the settings editor without requiring the `@tag:advanced` filter."),
'default': product.quality !== 'stable'
},
'workbench.sideBar.location': {
'type': 'string',
'enum': ['left', 'right'],
@@ -55,7 +55,7 @@ import { IChatEntitlementService } from '../../../services/chat/common/chatEntit
import { APPLICATION_SCOPES, IWorkbenchConfigurationService } from '../../../services/configuration/common/configuration.js';
import { IEditorGroup, IEditorGroupsService } from '../../../services/editor/common/editorGroupsService.js';
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
import { IOpenSettingsOptions, IPreferencesService, ISearchResult, ISetting, ISettingsEditorModel, ISettingsEditorOptions, ISettingsGroup, SettingMatchType, SettingValueType, validateSettingsEditorOptions } from '../../../services/preferences/common/preferences.js';
import { ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING, IOpenSettingsOptions, IPreferencesService, ISearchResult, ISetting, ISettingsEditorModel, ISettingsEditorOptions, ISettingsGroup, SettingMatchType, SettingValueType, validateSettingsEditorOptions } from '../../../services/preferences/common/preferences.js';
import { SettingsEditor2Input } from '../../../services/preferences/common/preferencesEditorInput.js';
import { nullRange, Settings2EditorModel } from '../../../services/preferences/common/preferencesModels.js';
import { IUserDataProfileService } from '../../../services/userDataProfile/common/userDataProfile.js';
@@ -299,6 +299,9 @@ export class SettingsEditor2 extends EditorPane {
|| e.affectedKeys.has(WorkbenchSettingsEditorSettings.EnableNaturalLanguageSearch)) {
this.updateAiSearchToggleVisibility();
}
if (e.affectsConfiguration(ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING)) {
this.onConfigUpdate(undefined, true, true);
}
if (e.source !== ConfigurationTarget.DEFAULT) {
this.onConfigUpdate(e.affectedKeys);
}
@@ -352,6 +355,9 @@ export class SettingsEditor2 extends EditorPane {
}
private canShowAdvancedSettings(): boolean {
if (this.configurationService.getValue<boolean>(ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING) ?? false) {
return true;
}
return this.viewState.tagFilters?.has(ADVANCED_SETTING_TAG) ?? false;
}
@@ -1420,7 +1426,7 @@ export class SettingsEditor2 extends EditorPane {
this.settingsOrderByTocIndex = this.createSettingsOrderByTocIndex(resolvedSettingsRoot);
}
private async onConfigUpdate(keys?: ReadonlySet<string>, forceRefresh = false, schemaChange = false): Promise<void> {
private async onConfigUpdate(keys?: ReadonlySet<string>, forceRefresh = false, triggerSearch = false): Promise<void> {
if (keys && this.settingsTreeModel) {
return this.updateElementsByKey(keys);
}
@@ -1576,7 +1582,7 @@ export class SettingsEditor2 extends EditorPane {
if (this.settingsTreeModel.value) {
this.refreshModels(resolvedSettingsRoot);
if (schemaChange && this.searchResultModel) {
if (triggerSearch && this.searchResultModel) {
// If an extension's settings were just loaded and a search is active, retrigger the search so it shows up
return await this.onSearchInputChanged(false);
}
@@ -67,6 +67,7 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
private readonly indicatorsContainerElement: HTMLElement;
private readonly previewIndicator: SettingIndicator;
private readonly advancedIndicator: SettingIndicator;
private readonly workspaceTrustIndicator: SettingIndicator;
private readonly scopeOverridesIndicator: SettingIndicator;
private readonly syncIgnoredIndicator: SettingIndicator;
@@ -91,7 +92,8 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
this.indicatorsContainerElement.style.display = 'inline';
this.previewIndicator = this.createPreviewIndicator();
this.isolatedIndicators = [this.previewIndicator];
this.advancedIndicator = this.createAdvancedIndicator();
this.isolatedIndicators = [this.previewIndicator, this.advancedIndicator];
this.workspaceTrustIndicator = this.createWorkspaceTrustIndicator();
this.scopeOverridesIndicator = this.createScopeOverridesIndicator();
@@ -225,6 +227,28 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
};
}
private createAdvancedIndicator(): SettingIndicator {
const disposables = new DisposableStore();
const advancedIndicator = $('span.setting-indicator.setting-item-preview');
const advancedLabel = disposables.add(new SimpleIconLabel(advancedIndicator));
advancedLabel.text = localize('advancedLabel', "Advanced");
const showHover = (focus: boolean) => {
return this.hoverService.showInstantHover({
...this.defaultHoverOptions,
content: ADVANCED_INDICATOR_DESCRIPTION,
target: advancedIndicator
}, focus);
};
this.addHoverDisposables(disposables, advancedIndicator, showHover);
return {
element: advancedIndicator,
label: advancedLabel,
disposables
};
}
private render() {
this.indicatorsContainerElement.innerText = '';
this.indicatorsContainerElement.style.display = 'none';
@@ -342,6 +366,12 @@ export class SettingsTreeIndicatorsLabel implements IDisposable {
this.render();
}
updateAdvancedIndicator(element: SettingsTreeSettingElement) {
const isAdvancedSetting = element.tags?.has('advanced');
this.advancedIndicator.element.style.display = isAdvancedSetting ? 'inline' : 'none';
this.render();
}
private getInlineScopeDisplayText(completeScope: string): string {
const [scope, language] = completeScope.split(':');
const localizedScope = scope === 'user' ?
@@ -575,12 +605,14 @@ function getAccessibleScopeDisplayMidSentenceText(completeScope: string, languag
export function getIndicatorsLabelAriaLabel(element: SettingsTreeSettingElement, configurationService: IWorkbenchConfigurationService, userDataProfilesService: IUserDataProfilesService, languageService: ILanguageService): string {
const ariaLabelSections: string[] = [];
// Add preview or experimental or advanced indicator text
// Add preview or experimental indicator text
if (element.tags?.has('preview')) {
ariaLabelSections.push(localize('previewLabel', "Preview"));
} else if (element.tags?.has('experimental')) {
ariaLabelSections.push(localize('experimentalLabel', "Experimental"));
} else if (element.tags?.has('advanced')) {
}
if (element.tags?.has('advanced')) {
ariaLabelSections.push(localize('advancedLabel', "Advanced"));
}
@@ -1041,6 +1041,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre
template.indicatorsLabel.updateSyncIgnored(element, this.ignoredSettings);
template.indicatorsLabel.updateDefaultOverrideIndicator(element);
template.indicatorsLabel.updatePreviewIndicator(element);
template.indicatorsLabel.updateAdvancedIndicator(element);
template.elementDisposables.add(this.onDidChangeIgnoredSettings(() => {
template.indicatorsLabel.updateSyncIgnored(element, this.ignoredSettings);
}));
@@ -348,5 +348,6 @@ export interface IDefineKeybindingEditorContribution extends IEditorContribution
export const FOLDER_SETTINGS_PATH = '.vscode/settings.json';
export const DEFAULT_SETTINGS_EDITOR_SETTING = 'workbench.settings.openDefaultSettings';
export const USE_SPLIT_JSON_SETTING = 'workbench.settings.useSplitJSON';
export const ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING = 'workbench.settings.alwaysShowAdvancedSettings';
export const SETTINGS_AUTHORITY = 'settings';