diff --git a/src/vs/editor/contrib/documentSymbols/outlineTree.ts b/src/vs/editor/contrib/documentSymbols/outlineTree.ts index 970453bc12b53..b45f6f13e6c9f 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineTree.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineTree.ts @@ -7,7 +7,7 @@ import * as dom from 'vs/base/browser/dom'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IDataSource, ITreeNode, ITreeRenderer, ITreeSorter, ITreeFilter } from 'vs/base/browser/ui/tree/tree'; -import { values, forEach } from 'vs/base/common/collections'; +import { values } from 'vs/base/common/collections'; import { createMatches, FuzzyScore } from 'vs/base/common/filters'; import 'vs/css!./media/outlineTree'; import 'vs/css!./media/symbol-icons'; @@ -22,6 +22,8 @@ import { MarkerSeverity } from 'vs/platform/markers/common/markers'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { registerColor, listErrorForeground, listWarningForeground, foreground } from 'vs/platform/theme/common/colorRegistry'; import { IdleValue } from 'vs/base/common/async'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; +import { URI } from 'vs/base/common/uri'; export type OutlineItem = OutlineGroup | OutlineElement; @@ -278,27 +280,26 @@ export class OutlineFilter implements ITreeFilter { [SymbolKind.TypeParameter]: 'showTypeParameters', }); - private readonly _filteredTypes = new Set(); - constructor( private readonly _prefix: string, - @IConfigurationService private readonly _configService: IConfigurationService, - ) { - this.update(); - } - - update() { - this._filteredTypes.clear(); - forEach(OutlineFilter.configNameToKind, entry => { - const key = `${this._prefix}.${entry.key}`; - if (this._configService.getValue(key) === false) { - this._filteredTypes.add(entry.value); - } - }); - } + @ITextResourceConfigurationService private readonly _textResourceConfigService: ITextResourceConfigurationService, + ) { } filter(element: OutlineItem): boolean { - return !(element instanceof OutlineElement) || !this._filteredTypes.has(element.symbol.kind); + const outline = OutlineModel.get(element); + let uri: URI | undefined; + + if (outline) { + uri = outline.textModel.uri; + } + + if (!(element instanceof OutlineElement)) { + return true; + } + + const configName = OutlineFilter.kindToConfigName[element.symbol.kind]; + const configKey = `${this._prefix}.${configName}`; + return this._textResourceConfigService.getValue(uri, configKey); } } diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts index ac600063f1559..a62a5f543b09e 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts @@ -170,131 +170,157 @@ Registry.as(Extensions.Configuration).registerConfigurat 'breadcrumbs.showFiles': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.file', "When enabled breadcrumbs show `file`-symbols.") }, 'breadcrumbs.showModules': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.module', "When enabled breadcrumbs show `module`-symbols.") }, 'breadcrumbs.showNamespaces': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.namespace', "When enabled breadcrumbs show `namespace`-symbols.") }, 'breadcrumbs.showPackages': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.package', "When enabled breadcrumbs show `package`-symbols.") }, 'breadcrumbs.showClasses': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.class', "When enabled breadcrumbs show `class`-symbols.") }, 'breadcrumbs.showMethods': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.method', "When enabled breadcrumbs show `method`-symbols.") }, 'breadcrumbs.showProperties': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.property', "When enabled breadcrumbs show `property`-symbols.") }, 'breadcrumbs.showFields': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.field', "When enabled breadcrumbs show `field`-symbols.") }, 'breadcrumbs.showConstructors': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.constructor', "When enabled breadcrumbs show `constructor`-symbols.") }, 'breadcrumbs.showEnums': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.enum', "When enabled breadcrumbs show `enum`-symbols.") }, 'breadcrumbs.showInterfaces': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.interface', "When enabled breadcrumbs show `interface`-symbols.") }, 'breadcrumbs.showFunctions': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.function', "When enabled breadcrumbs show `function`-symbols.") }, 'breadcrumbs.showVariables': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.variable', "When enabled breadcrumbs show `variable`-symbols.") }, 'breadcrumbs.showConstants': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.constant', "When enabled breadcrumbs show `constant`-symbols.") }, 'breadcrumbs.showStrings': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.string', "When enabled breadcrumbs show `string`-symbols.") }, 'breadcrumbs.showNumbers': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.number', "When enabled breadcrumbs show `number`-symbols.") }, 'breadcrumbs.showBooleans': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.boolean', "When enabled breadcrumbs show `boolean`-symbols.") }, 'breadcrumbs.showArrays': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.array', "When enabled breadcrumbs show `array`-symbols.") }, 'breadcrumbs.showObjects': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.object', "When enabled breadcrumbs show `object`-symbols.") }, 'breadcrumbs.showKeys': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.key', "When enabled breadcrumbs show `key`-symbols.") }, 'breadcrumbs.showNull': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.null', "When enabled breadcrumbs show `null`-symbols.") }, 'breadcrumbs.showEnumMembers': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.enumMember', "When enabled breadcrumbs show `enumMember`-symbols.") }, 'breadcrumbs.showStructs': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.struct', "When enabled breadcrumbs show `struct`-symbols.") }, 'breadcrumbs.showEvents': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.event', "When enabled breadcrumbs show `event`-symbols.") }, 'breadcrumbs.showOperators': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.operator', "When enabled breadcrumbs show `operator`-symbols.") }, 'breadcrumbs.showTypeParameters': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.typeParameter', "When enabled breadcrumbs show `typeParameter`-symbols.") } } diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index ef154461212dd..dc488d207bdd7 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -47,6 +47,7 @@ import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; import { onDidChangeZoomLevel } from 'vs/base/browser/browser'; import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; class Item extends BreadcrumbsItem { @@ -168,6 +169,7 @@ export class BreadcrumbsControl { @IThemeService private readonly _themeService: IThemeService, @IQuickOpenService private readonly _quickOpenService: IQuickOpenService, @IConfigurationService private readonly _configurationService: IConfigurationService, + @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, @IFileService private readonly _fileService: IFileService, @ITelemetryService private readonly _telemetryService: ITelemetryService, @ILabelService private readonly _labelService: ILabelService, @@ -246,7 +248,12 @@ export class BreadcrumbsControl { const uri = input.getResource()!; const editor = this._getActiveCodeEditor(); - const model = new EditorBreadcrumbsModel(uri, editor, this._configurationService, this._workspaceService); + const model = new EditorBreadcrumbsModel( + uri, editor, + this._configurationService, + this._textResourceConfigurationService, + this._workspaceService + ); dom.toggleClass(this.domNode, 'relative-path', model.isRelative()); dom.toggleClass(this.domNode, 'backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\'); diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts index f05157c525722..565a8ebcb9e78 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts @@ -23,6 +23,8 @@ import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs import { FileKind } from 'vs/platform/files/common/files'; import { withNullAsUndefined } from 'vs/base/common/types'; import { OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; +import { ITextModel } from 'vs/editor/common/model'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; export class FileElement { constructor( @@ -53,9 +55,9 @@ export class EditorBreadcrumbsModel { private readonly _uri: URI, private readonly _editor: ICodeEditor | undefined, @IConfigurationService private readonly _configurationService: IConfigurationService, + @ITextResourceConfigurationService private readonly _textResourceConfigurationService: ITextResourceConfigurationService, @IWorkspaceContextService workspaceService: IWorkspaceContextService, ) { - this._cfgFilePath = BreadcrumbsConfig.FilePath.bindTo(_configurationService); this._cfgSymbolPath = BreadcrumbsConfig.SymbolPath.bindTo(_configurationService); @@ -142,6 +144,17 @@ export class EditorBreadcrumbsModel { this._disposables.add(this._configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('breadcrumbs')) { this._updateOutline(true); + return; + } + if (this._editor && this._editor.getModel()) { + const editorModel = this._editor.getModel() as ITextModel; + const languageName = editorModel.getLanguageIdentifier().language; + + // Checking for changes in the current language override config. + // We can't be more specific than this because the ConfigurationChangeEvent(e) only includes the first part of the root path + if (e.affectsConfiguration(`[${languageName}]`)) { + this._updateOutline(true); + } } })); @@ -250,7 +263,12 @@ export class EditorBreadcrumbsModel { private _isFiltered(element: TreeElement): boolean { if (element instanceof OutlineElement) { const key = `breadcrumbs.${OutlineFilter.kindToConfigName[element.symbol.kind]}`; - return !this._configurationService.getValue(key); + let uri: URI | undefined; + if (this._editor && this._editor.getModel()) { + const model = this._editor.getModel() as ITextModel; + uri = model.uri; + } + return !this._textResourceConfigurationService.getValue(uri, key); } return false; } diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 0affdee3013be..3746219701309 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -55,92 +55,110 @@ Registry.as(ConfigurationExtensions.Configuration).regis }, 'outline.showFiles': { type: 'boolean', + overridable: true, default: true, markdownDescription: localize('filteredTypes.file', "When enabled outline shows `file`-symbols.") }, 'outline.showModules': { type: 'boolean', + overridable: true, default: true, markdownDescription: localize('filteredTypes.module', "When enabled outline shows `module`-symbols.") }, 'outline.showNamespaces': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.namespace', "When enabled outline shows `namespace`-symbols.") }, 'outline.showPackages': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.package', "When enabled outline shows `package`-symbols.") }, 'outline.showClasses': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.class', "When enabled outline shows `class`-symbols.") }, 'outline.showMethods': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.method', "When enabled outline shows `method`-symbols.") }, 'outline.showProperties': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.property', "When enabled outline shows `property`-symbols.") }, 'outline.showFields': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.field', "When enabled outline shows `field`-symbols.") }, 'outline.showConstructors': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.constructor', "When enabled outline shows `constructor`-symbols.") }, 'outline.showEnums': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.enum', "When enabled outline shows `enum`-symbols.") }, 'outline.showInterfaces': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.interface', "When enabled outline shows `interface`-symbols.") }, 'outline.showFunctions': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.function', "When enabled outline shows `function`-symbols.") }, 'outline.showVariables': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.variable', "When enabled outline shows `variable`-symbols.") }, 'outline.showConstants': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.constant', "When enabled outline shows `constant`-symbols.") }, 'outline.showStrings': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.string', "When enabled outline shows `string`-symbols.") }, 'outline.showNumbers': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.number', "When enabled outline shows `number`-symbols.") }, 'outline.showBooleans': { type: 'boolean', + overridable: true, default: true, markdownDescription: localize('filteredTypes.boolean', "When enabled outline shows `boolean`-symbols.") }, 'outline.showArrays': { type: 'boolean', default: true, + overridable: true, markdownDescription: localize('filteredTypes.array', "When enabled outline shows `array`-symbols.") }, 'outline.showObjects': { diff --git a/src/vs/workbench/contrib/outline/browser/outlineNavigation.ts b/src/vs/workbench/contrib/outline/browser/outlineNavigation.ts index 9b6e7c96e1f32..c67f900e69e8b 100644 --- a/src/vs/workbench/contrib/outline/browser/outlineNavigation.ts +++ b/src/vs/workbench/contrib/outline/browser/outlineNavigation.ts @@ -17,9 +17,9 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { forEach } from 'vs/base/common/collections'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { OutlineFilter } from 'vs/editor/contrib/documentSymbols/outlineTree'; import { binarySearch } from 'vs/base/common/arrays'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; class FlatOutline { @@ -78,7 +78,7 @@ export class OutlineNavigation implements IEditorContribution { constructor( editor: ICodeEditor, - @IConfigurationService private readonly _configService: IConfigurationService, + @ITextResourceConfigurationService private readonly _textResourceConfigService: ITextResourceConfigurationService, ) { this._editor = editor; } @@ -104,7 +104,7 @@ export class OutlineNavigation implements IEditorContribution { this._cts = new EditorStateCancellationTokenSource(this._editor, CodeEditorStateFlag.Position | CodeEditorStateFlag.Value | CodeEditorStateFlag.Scroll); - const filter = new OutlineFilter('outline', this._configService); + const filter = new OutlineFilter('outline', this._textResourceConfigService); const outlineModel = await OutlineModel.create(textModel, this._cts.token); if (this._cts.token.isCancellationRequested) { diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 068c3471ed5bb..ec276fec9c032 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -372,8 +372,9 @@ export class OutlinePane extends ViewletPane { if (e.affectsConfiguration(OutlineConfigKeys.icons)) { this._tree.updateChildren(); } - if (e.affectsConfiguration('outline')) { - this._treeFilter.update(); + // This is a temporary solution to try and minimize refilters while + // ConfigurationChangeEvents only provide the first section of the config path. + if (e.affectedKeys.some(key => key.search(/(outline|\[\w+\])/))) { this._tree.refilter(); } })); diff --git a/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts b/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts index c26f9a10ecf79..01af728251902 100644 --- a/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts @@ -29,7 +29,7 @@ suite('Breadcrumb Model', function () { test('only uri, inside workspace', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, workspaceService); + let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, configService, workspaceService); let elements = model.getElements(); assert.equal(elements.length, 3); @@ -44,7 +44,7 @@ suite('Breadcrumb Model', function () { test('only uri, outside workspace', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/outside/file.ts'), undefined, configService, workspaceService); + let model = new EditorBreadcrumbsModel(URI.parse('foo:/outside/file.ts'), undefined, configService, configService, workspaceService); let elements = model.getElements(); assert.equal(elements.length, 2);