Merge from vscode 81d7885dc2e9dc617e1522697a2966bc4025a45d (#5949)
* Merge from vscode 81d7885dc2e9dc617e1522697a2966bc4025a45d * Fix vs unit tests and hygiene issue * Fix strict null check issue
@@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { dispose, Disposable, toDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { dispose, Disposable, toDisposable, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { CheckboxActionViewItem } from 'vs/base/browser/ui/checkbox/checkbox';
|
||||
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
|
||||
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
|
||||
@@ -804,7 +804,7 @@ class KeybindingItemRenderer implements IListRenderer<IKeybindingItemEntry, Keyb
|
||||
const source = this.instantiationService.createInstance(SourceColumn, parent, this.keybindingsEditor);
|
||||
|
||||
const columns: Column[] = [actions, command, keybinding, when, source];
|
||||
const disposables: IDisposable[] = [...columns];
|
||||
const disposables = combinedDisposable(...columns);
|
||||
const elements = columns.map(({ element }) => element);
|
||||
|
||||
this.keybindingsEditor.layoutColumns(elements);
|
||||
@@ -814,7 +814,7 @@ class KeybindingItemRenderer implements IListRenderer<IKeybindingItemEntry, Keyb
|
||||
return {
|
||||
parent,
|
||||
columns,
|
||||
disposable: toDisposable(() => dispose(disposables))
|
||||
disposable: disposables
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,13 @@ import { parseTree, Node } from 'vs/base/common/json';
|
||||
import { ScanCodeBinding } from 'vs/base/common/scanCode';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { WindowsNativeResolvedKeybinding } from 'vs/workbench/services/keybinding/common/windowsKeyboardMapper';
|
||||
import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { themeColorFromId, ThemeColor, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { overviewRulerInfo, overviewRulerError } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { IModelDeltaDecoration, ITextModel, TrackedRangeStickiness, OverviewRulerLane } from 'vs/editor/common/model';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { KeybindingParser } from 'vs/base/common/keybindingParser';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
|
||||
|
||||
const NLS_LAUNCH_MESSAGE = nls.localize('defineKeybinding.start', "Define Keybinding");
|
||||
const NLS_KB_LAYOUT_ERROR_MESSAGE = nls.localize('defineKeybinding.kbLayoutErrorMessage', "You won't be able to produce this key combination under your current keyboard layout.");
|
||||
@@ -400,3 +402,8 @@ function isInterestingEditorModel(editor: ICodeEditor): boolean {
|
||||
|
||||
registerEditorContribution(DefineKeybindingController);
|
||||
registerEditorCommand(new DefineKeybindingCommand());
|
||||
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
collector.addRule(`.monaco-editor .inlineKeybindingInfo:before { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(Severity.Info, theme)}") -0.1em -0.2em no-repeat; }`);
|
||||
collector.addRule(`.monaco-editor .inlineKeybindingError:before { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(Severity.Error, theme)}") -0.1em -0.2em no-repeat; }`);
|
||||
});
|
||||
|
Before Width: | Height: | Size: 194 B After Width: | Height: | Size: 194 B |
|
Before Width: | Height: | Size: 194 B After Width: | Height: | Size: 194 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8 1c-3.865 0-7 3.135-7 7s3.135 7 7 7 7-3.135 7-7-3.135-7-7-7zm1 12h-2v-7h2v7zm0-8h-2v-2h2v2z" fill="#1BA1E2"/><path d="M7 6h2v7h-2v-7zm0-1h2v-2h-2v2z" fill="#fff"/></svg>
|
||||
|
Before Width: | Height: | Size: 243 B |
@@ -47,7 +47,6 @@
|
||||
display:inline-block;
|
||||
height:0.8em;
|
||||
width:1em;
|
||||
background: url(info.svg) 0px -0.1em no-repeat;
|
||||
background-size: 0.9em;
|
||||
}
|
||||
|
||||
@@ -57,7 +56,6 @@
|
||||
display:inline-block;
|
||||
height:0.8em;
|
||||
width:1em;
|
||||
background: url(status-error.svg) 0px -0.1em no-repeat;
|
||||
background-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -236,15 +236,6 @@
|
||||
background: url('edit_inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-editor .unsupportedWorkbenhSettingInfo:before {
|
||||
content:" ";
|
||||
display:inline-block;
|
||||
height:1em;
|
||||
width:1em;
|
||||
background: url(info.svg) 50% 50% no-repeat;
|
||||
background-size: 0.9em;
|
||||
}
|
||||
|
||||
.monaco-editor .dim-configuration {
|
||||
color: #b1b1b1;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8" cy="8" r="6" fill="#F6F6F6"/><path d="M8 3C5.238 3 3 5.238 3 8s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5zm3 7l-1 1-2-2-2 2-1-1 2-2.027L5 6l1-1 2 2 2-2 1 1-2 1.973L11 10z" fill="#E51400"/><path fill="#fff" d="M11 6l-1-1-2 2-2-2-1 1 2 1.973L5 10l1 1 2-2 2 2 1-1-2-2.027z"/></svg>
|
||||
|
Before Width: | Height: | Size: 403 B |
@@ -16,7 +16,6 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { WorkbenchStateContext, RemoteAuthorityContext } from 'vs/workbench/browser/contextkeys';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
@@ -30,10 +29,9 @@ import { ResourceContextKey } from 'vs/workbench/common/resources';
|
||||
import { KeybindingsEditor } from 'vs/workbench/contrib/preferences/browser/keybindingsEditor';
|
||||
import { ConfigureLanguageBasedSettingsAction, OpenDefaultKeybindingsFileAction, OpenFolderSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenGlobalSettingsAction, OpenRawDefaultSettingsAction, OpenSettings2Action, OpenSettingsJsonAction, OpenWorkspaceSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND, OPEN_FOLDER_SETTINGS_LABEL, OpenRemoteSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
|
||||
import { PreferencesEditor } from 'vs/workbench/contrib/preferences/browser/preferencesEditor';
|
||||
import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, IKeybindingsEditor, IPreferencesSearchService, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING, SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED, SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU, SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON, SETTINGS_COMMAND_OPEN_SETTINGS, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN } from 'vs/workbench/contrib/preferences/common/preferences';
|
||||
import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, IKeybindingsEditor, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING, SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED, SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU, SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON, SETTINGS_COMMAND_OPEN_SETTINGS, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN } from 'vs/workbench/contrib/preferences/common/preferences';
|
||||
import { PreferencesContribution } from 'vs/workbench/contrib/preferences/common/preferencesContribution';
|
||||
import { PreferencesSearchService } from 'vs/workbench/contrib/preferences/electron-browser/preferencesSearch';
|
||||
import { SettingsEditor2 } from 'vs/workbench/contrib/preferences/electron-browser/settingsEditor2';
|
||||
import { SettingsEditor2 } from 'vs/workbench/contrib/preferences/browser/settingsEditor2';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { DefaultPreferencesEditorInput, KeybindingsEditorInput, PreferencesEditorInput, SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput';
|
||||
@@ -42,8 +40,6 @@ import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
registerSingleton(IPreferencesSearchService, PreferencesSearchService, true);
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
PreferencesEditor,
|
||||
@@ -385,8 +381,8 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
|
||||
id: OpenGlobalKeybindingsAction.ID,
|
||||
title: OpenGlobalKeybindingsAction.LABEL,
|
||||
iconLocation: {
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor-inverse.svg`))
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor-inverse.svg`))
|
||||
}
|
||||
},
|
||||
when: ResourceContextKey.Resource.isEqualTo(URI.file(environmentService.appKeybindingsPath).toString()),
|
||||
@@ -401,11 +397,11 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
|
||||
id: commandId,
|
||||
title: OpenSettings2Action.LABEL,
|
||||
iconLocation: {
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor-inverse.svg`))
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor-inverse.svg`))
|
||||
}
|
||||
},
|
||||
when: ResourceContextKey.Resource.isEqualTo(URI.file(environmentService.appSettingsPath).toString()),
|
||||
when: ResourceContextKey.Resource.isEqualTo(environmentService.settingsResource.toString()),
|
||||
group: 'navigation',
|
||||
order: 1
|
||||
});
|
||||
@@ -442,8 +438,8 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
|
||||
id: commandId,
|
||||
title: OpenSettings2Action.LABEL,
|
||||
iconLocation: {
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor-inverse.svg`))
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor-inverse.svg`))
|
||||
}
|
||||
},
|
||||
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.workspaceSettingsResource!.toString()), WorkbenchStateContext.isEqualTo('workspace')),
|
||||
@@ -470,8 +466,8 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
|
||||
id: commandId,
|
||||
title: OpenSettings2Action.LABEL,
|
||||
iconLocation: {
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/preferences-editor-inverse.svg`))
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/preferences-editor-inverse.svg`))
|
||||
}
|
||||
},
|
||||
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.getFolderSettingsResource(folder.uri)!.toString())),
|
||||
@@ -537,8 +533,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
|
||||
id: OpenGlobalKeybindingsFileAction.ID,
|
||||
title: OpenGlobalKeybindingsFileAction.LABEL,
|
||||
iconLocation: {
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/edit-json.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/electron-browser/media/edit-json-inverse.svg`))
|
||||
light: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/edit-json.svg`)),
|
||||
dark: URI.parse(require.toUrl(`vs/workbench/contrib/preferences/browser/media/edit-json-inverse.svg`))
|
||||
}
|
||||
},
|
||||
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
|
||||
@@ -775,8 +771,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
|
||||
id: SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON,
|
||||
title: nls.localize('openSettingsJson', "Open Settings (JSON)"),
|
||||
iconLocation: {
|
||||
dark: URI.parse(require.toUrl('vs/workbench/contrib/preferences/electron-browser/media/edit-json-inverse.svg')),
|
||||
light: URI.parse(require.toUrl('vs/workbench/contrib/preferences/electron-browser/media/edit-json.svg'))
|
||||
dark: URI.parse(require.toUrl('vs/workbench/contrib/preferences/browser/media/edit-json-inverse.svg')),
|
||||
light: URI.parse(require.toUrl('vs/workbench/contrib/preferences/browser/media/edit-json.svg'))
|
||||
}
|
||||
},
|
||||
group: 'navigation',
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
@@ -164,7 +164,7 @@ export class OpenWorkspaceSettingsAction extends Action {
|
||||
static readonly ID = 'workbench.action.openWorkspaceSettings';
|
||||
static readonly LABEL = nls.localize('openWorkspaceSettings', "Open Workspace Settings");
|
||||
|
||||
private disposables: IDisposable[] = [];
|
||||
private readonly disposables = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -174,7 +174,7 @@ export class OpenWorkspaceSettingsAction extends Action {
|
||||
) {
|
||||
super(id, label);
|
||||
this.update();
|
||||
this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables);
|
||||
this.disposables.add(this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this));
|
||||
}
|
||||
|
||||
private update(): void {
|
||||
@@ -186,7 +186,7 @@ export class OpenWorkspaceSettingsAction extends Action {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
this.disposables.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import { ConfigurationTarget } from 'vs/platform/configuration/common/configurat
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -84,7 +84,7 @@ export class PreferencesEditor extends BaseEditor {
|
||||
|
||||
readonly minimumHeight = 260;
|
||||
|
||||
private _onDidCreateWidget = new Emitter<{ width: number; height: number; } | undefined>();
|
||||
private _onDidCreateWidget = this._register(new Emitter<{ width: number; height: number; } | undefined>());
|
||||
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined> = this._onDidCreateWidget.event;
|
||||
|
||||
constructor(
|
||||
@@ -94,7 +94,7 @@ export class PreferencesEditor extends BaseEditor {
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IProgressService private readonly progressService: IProgressService,
|
||||
@ILocalProgressService private readonly progressService: ILocalProgressService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
super(PreferencesEditor.ID, telemetryService, themeService, storageService);
|
||||
@@ -330,11 +330,6 @@ export class PreferencesEditor extends BaseEditor {
|
||||
this._lastReportedFilter = filter;
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._onDidCreateWidget.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsNavigator extends ArrayNavigator<ISetting> {
|
||||
@@ -774,10 +769,10 @@ class SideBySidePreferencesWidget extends Widget {
|
||||
|
||||
private settingsTargetsWidget: SettingsTargetsWidget;
|
||||
|
||||
private readonly _onFocus = new Emitter<void>();
|
||||
private readonly _onFocus = this._register(new Emitter<void>());
|
||||
readonly onFocus: Event<void> = this._onFocus.event;
|
||||
|
||||
private readonly _onDidSettingsTargetChange = new Emitter<SettingsTarget>();
|
||||
private readonly _onDidSettingsTargetChange = this._register(new Emitter<SettingsTarget>());
|
||||
readonly onDidSettingsTargetChange: Event<SettingsTarget> = this._onDidSettingsTargetChange.event;
|
||||
|
||||
private splitview: SplitView;
|
||||
|
||||
@@ -56,13 +56,13 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend
|
||||
private modelChangeDelayer: Delayer<void> = new Delayer<void>(200);
|
||||
private associatedPreferencesModel: IPreferencesEditorModel<ISetting>;
|
||||
|
||||
private readonly _onFocusPreference = new Emitter<ISetting>();
|
||||
private readonly _onFocusPreference = this._register(new Emitter<ISetting>());
|
||||
readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
|
||||
|
||||
private readonly _onClearFocusPreference = new Emitter<ISetting>();
|
||||
private readonly _onClearFocusPreference = this._register(new Emitter<ISetting>());
|
||||
readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
|
||||
|
||||
private readonly _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>();
|
||||
private readonly _onUpdatePreference = this._register(new Emitter<{ key: string, value: any, source: IIndexedSetting }>());
|
||||
readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event;
|
||||
|
||||
private filterResult: IFilterResult | undefined;
|
||||
@@ -233,13 +233,13 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
||||
private bracesHidingRenderer: BracesHidingRenderer;
|
||||
private filterResult: IFilterResult | undefined;
|
||||
|
||||
private readonly _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>();
|
||||
private readonly _onUpdatePreference = this._register(new Emitter<{ key: string, value: any, source: IIndexedSetting }>());
|
||||
readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event;
|
||||
|
||||
private readonly _onFocusPreference = new Emitter<ISetting>();
|
||||
private readonly _onFocusPreference = this._register(new Emitter<ISetting>());
|
||||
readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
|
||||
|
||||
private readonly _onClearFocusPreference = new Emitter<ISetting>();
|
||||
private readonly _onClearFocusPreference = this._register(new Emitter<ISetting>());
|
||||
readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
|
||||
|
||||
constructor(protected editor: ICodeEditor, readonly preferencesModel: DefaultSettingsEditorModel,
|
||||
@@ -436,13 +436,13 @@ class DefaultSettingsHeaderRenderer extends Disposable {
|
||||
|
||||
export class SettingsGroupTitleRenderer extends Disposable implements HiddenAreasProvider {
|
||||
|
||||
private readonly _onHiddenAreasChanged = new Emitter<void>();
|
||||
private readonly _onHiddenAreasChanged = this._register(new Emitter<void>());
|
||||
get onHiddenAreasChanged(): Event<void> { return this._onHiddenAreasChanged.event; }
|
||||
|
||||
private settingsGroups: ISettingsGroup[];
|
||||
private hiddenGroups: ISettingsGroup[] = [];
|
||||
private settingsGroupTitleWidgets: SettingsGroupTitleWidget[];
|
||||
private disposables: IDisposable[] = [];
|
||||
private renderDisposables: IDisposable[] = [];
|
||||
|
||||
constructor(private editor: ICodeEditor,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
@@ -474,8 +474,8 @@ export class SettingsGroupTitleRenderer extends Disposable implements HiddenArea
|
||||
const settingsGroupTitleWidget = this.instantiationService.createInstance(SettingsGroupTitleWidget, this.editor, group);
|
||||
settingsGroupTitleWidget.render();
|
||||
this.settingsGroupTitleWidgets.push(settingsGroupTitleWidget);
|
||||
this.disposables.push(settingsGroupTitleWidget);
|
||||
this.disposables.push(settingsGroupTitleWidget.onToggled(collapsed => this.onToggled(collapsed, settingsGroupTitleWidget.settingsGroup)));
|
||||
this.renderDisposables.push(settingsGroupTitleWidget);
|
||||
this.renderDisposables.push(settingsGroupTitleWidget.onToggled(collapsed => this.onToggled(collapsed, settingsGroupTitleWidget.settingsGroup)));
|
||||
}
|
||||
this.settingsGroupTitleWidgets.reverse();
|
||||
}
|
||||
@@ -515,7 +515,7 @@ export class SettingsGroupTitleRenderer extends Disposable implements HiddenArea
|
||||
|
||||
private disposeWidgets() {
|
||||
this.hiddenGroups = [];
|
||||
this.disposables = dispose(this.disposables);
|
||||
this.renderDisposables = dispose(this.renderDisposables);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ISettingsEditorModel, ISetting, ISettingsGroup, ISearchResult, IGroupFilter } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IMatch, or, matchesContiguousSubString, matchesPrefix, matchesCamelCase, matchesWords } from 'vs/base/common/filters';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IPreferencesSearchService, ISearchProvider } from 'vs/workbench/contrib/preferences/common/preferences';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
export interface IEndpointDetails {
|
||||
urlBase?: string;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
export class PreferencesSearchService extends Disposable implements IPreferencesSearchService {
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService protected readonly instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
getRemoteSearchProvider(filter: string, newExtensionsOnly = false): ISearchProvider | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getLocalSearchProvider(filter: string): LocalSearchProvider {
|
||||
return this.instantiationService.createInstance(LocalSearchProvider, filter);
|
||||
}
|
||||
}
|
||||
|
||||
export class LocalSearchProvider implements ISearchProvider {
|
||||
static readonly EXACT_MATCH_SCORE = 10000;
|
||||
static readonly START_SCORE = 1000;
|
||||
|
||||
constructor(private _filter: string) {
|
||||
// Remove " and : which are likely to be copypasted as part of a setting name.
|
||||
// Leave other special characters which the user might want to search for.
|
||||
this._filter = this._filter
|
||||
.replace(/[":]/g, ' ')
|
||||
.replace(/ /g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
searchModel(preferencesModel: ISettingsEditorModel, token?: CancellationToken): Promise<ISearchResult | null> {
|
||||
if (!this._filter) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let orderedScore = LocalSearchProvider.START_SCORE; // Sort is not stable
|
||||
const settingMatcher = (setting: ISetting) => {
|
||||
const matches = new SettingMatches(this._filter, setting, true, true, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches;
|
||||
const score = this._filter === setting.key ?
|
||||
LocalSearchProvider.EXACT_MATCH_SCORE :
|
||||
orderedScore--;
|
||||
|
||||
return matches && matches.length ?
|
||||
{
|
||||
matches,
|
||||
score
|
||||
} :
|
||||
null;
|
||||
};
|
||||
|
||||
const filterMatches = preferencesModel.filterSettings(this._filter, this.getGroupFilter(this._filter), settingMatcher);
|
||||
if (filterMatches[0] && filterMatches[0].score === LocalSearchProvider.EXACT_MATCH_SCORE) {
|
||||
return Promise.resolve({
|
||||
filterMatches: filterMatches.slice(0, 1),
|
||||
exactMatch: true
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve({
|
||||
filterMatches
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getGroupFilter(filter: string): IGroupFilter {
|
||||
const regex = strings.createRegExp(filter, false, { global: true });
|
||||
return (group: ISettingsGroup) => {
|
||||
return regex.test(group.title);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class SettingMatches {
|
||||
|
||||
private readonly descriptionMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
private readonly keyMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
private readonly valueMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
|
||||
readonly matches: IRange[];
|
||||
|
||||
constructor(searchString: string, setting: ISetting, private requireFullQueryMatch: boolean, private searchDescription: boolean, private valuesMatcher: (filter: string, setting: ISetting) => IRange[]) {
|
||||
this.matches = distinct(this._findMatchesInSetting(searchString, setting), (match) => `${match.startLineNumber}_${match.startColumn}_${match.endLineNumber}_${match.endColumn}_`);
|
||||
}
|
||||
|
||||
private _findMatchesInSetting(searchString: string, setting: ISetting): IRange[] {
|
||||
const result = this._doFindMatchesInSetting(searchString, setting);
|
||||
if (setting.overrides && setting.overrides.length) {
|
||||
for (const subSetting of setting.overrides) {
|
||||
const subSettingMatches = new SettingMatches(searchString, subSetting, this.requireFullQueryMatch, this.searchDescription, this.valuesMatcher);
|
||||
const words = searchString.split(' ');
|
||||
const descriptionRanges: IRange[] = this.getRangesForWords(words, this.descriptionMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const keyRanges: IRange[] = this.getRangesForWords(words, this.keyMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const subSettingKeyRanges: IRange[] = this.getRangesForWords(words, subSettingMatches.keyMatchingWords, [this.descriptionMatchingWords, this.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const subSettinValueRanges: IRange[] = this.getRangesForWords(words, subSettingMatches.valueMatchingWords, [this.descriptionMatchingWords, this.keyMatchingWords, subSettingMatches.keyMatchingWords]);
|
||||
result.push(...descriptionRanges, ...keyRanges, ...subSettingKeyRanges, ...subSettinValueRanges);
|
||||
result.push(...subSettingMatches.matches);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private _doFindMatchesInSetting(searchString: string, setting: ISetting): IRange[] {
|
||||
const registry: { [qualifiedKey: string]: IJSONSchema } = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
|
||||
const schema: IJSONSchema = registry[setting.key];
|
||||
|
||||
const words = searchString.split(' ');
|
||||
const settingKeyAsWords: string = setting.key.split('.').join(' ');
|
||||
|
||||
for (const word of words) {
|
||||
if (this.searchDescription) {
|
||||
for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) {
|
||||
const descriptionMatches = matchesWords(word, setting.description[lineIndex], true);
|
||||
if (descriptionMatches) {
|
||||
this.descriptionMatchingWords.set(word, descriptionMatches.map(match => this.toDescriptionRange(setting, match, lineIndex)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const keyMatches = or(matchesWords, matchesCamelCase)(word, settingKeyAsWords);
|
||||
if (keyMatches) {
|
||||
this.keyMatchingWords.set(word, keyMatches.map(match => this.toKeyRange(setting, match)));
|
||||
}
|
||||
|
||||
const valueMatches = typeof setting.value === 'string' ? matchesContiguousSubString(word, setting.value) : null;
|
||||
if (valueMatches) {
|
||||
this.valueMatchingWords.set(word, valueMatches.map(match => this.toValueRange(setting, match)));
|
||||
} else if (schema && schema.enum && schema.enum.some(enumValue => typeof enumValue === 'string' && !!matchesContiguousSubString(word, enumValue))) {
|
||||
this.valueMatchingWords.set(word, []);
|
||||
}
|
||||
}
|
||||
|
||||
const descriptionRanges: IRange[] = [];
|
||||
if (this.searchDescription) {
|
||||
for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) {
|
||||
const matches = or(matchesContiguousSubString)(searchString, setting.description[lineIndex] || '') || [];
|
||||
descriptionRanges.push(...matches.map(match => this.toDescriptionRange(setting, match, lineIndex)));
|
||||
}
|
||||
if (descriptionRanges.length === 0) {
|
||||
descriptionRanges.push(...this.getRangesForWords(words, this.descriptionMatchingWords, [this.keyMatchingWords, this.valueMatchingWords]));
|
||||
}
|
||||
}
|
||||
|
||||
const keyMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.key);
|
||||
const keyRanges: IRange[] = keyMatches ? keyMatches.map(match => this.toKeyRange(setting, match)) : this.getRangesForWords(words, this.keyMatchingWords, [this.descriptionMatchingWords, this.valueMatchingWords]);
|
||||
|
||||
let valueRanges: IRange[] = [];
|
||||
if (setting.value && typeof setting.value === 'string') {
|
||||
const valueMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.value);
|
||||
valueRanges = valueMatches ? valueMatches.map(match => this.toValueRange(setting, match)) : this.getRangesForWords(words, this.valueMatchingWords, [this.keyMatchingWords, this.descriptionMatchingWords]);
|
||||
} else {
|
||||
valueRanges = this.valuesMatcher ? this.valuesMatcher(searchString, setting) : [];
|
||||
}
|
||||
|
||||
return [...descriptionRanges, ...keyRanges, ...valueRanges];
|
||||
}
|
||||
|
||||
private getRangesForWords(words: string[], from: Map<string, IRange[]>, others: Map<string, IRange[]>[]): IRange[] {
|
||||
const result: IRange[] = [];
|
||||
for (const word of words) {
|
||||
const ranges = from.get(word);
|
||||
if (ranges) {
|
||||
result.push(...ranges);
|
||||
} else if (this.requireFullQueryMatch && others.every(o => !o.has(word))) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private toKeyRange(setting: ISetting, match: IMatch): IRange {
|
||||
return {
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn + match.start,
|
||||
endLineNumber: setting.keyRange.startLineNumber,
|
||||
endColumn: setting.keyRange.startColumn + match.end
|
||||
};
|
||||
}
|
||||
|
||||
private toDescriptionRange(setting: ISetting, match: IMatch, lineIndex: number): IRange {
|
||||
return {
|
||||
startLineNumber: setting.descriptionRanges[lineIndex].startLineNumber,
|
||||
startColumn: setting.descriptionRanges[lineIndex].startColumn + match.start,
|
||||
endLineNumber: setting.descriptionRanges[lineIndex].endLineNumber,
|
||||
endColumn: setting.descriptionRanges[lineIndex].startColumn + match.end
|
||||
};
|
||||
}
|
||||
|
||||
private toValueRange(setting: ISetting, match: IMatch): IRange {
|
||||
return {
|
||||
startLineNumber: setting.valueRange.startLineNumber,
|
||||
startColumn: setting.valueRange.startColumn + match.start + 1,
|
||||
endLineNumber: setting.valueRange.startLineNumber,
|
||||
endColumn: setting.valueRange.startColumn + match.end + 1
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -484,7 +484,7 @@ export class SettingsTargetsWidget extends Widget {
|
||||
|
||||
private _settingsTarget: SettingsTarget;
|
||||
|
||||
private readonly _onDidTargetChange = new Emitter<SettingsTarget>();
|
||||
private readonly _onDidTargetChange = this._register(new Emitter<SettingsTarget>());
|
||||
readonly onDidTargetChange: Event<SettingsTarget> = this._onDidTargetChange.event;
|
||||
|
||||
constructor(
|
||||
@@ -517,7 +517,7 @@ export class SettingsTargetsWidget extends Widget {
|
||||
const remoteAuthority = this.environmentService.configuration.remoteAuthority;
|
||||
const hostLabel = remoteAuthority && this.labelService.getHostLabel(REMOTE_HOST_SCHEME, remoteAuthority);
|
||||
const remoteSettingsLabel = localize('userSettingsRemote', "Remote") +
|
||||
(hostLabel ? ` (${hostLabel})` : '');
|
||||
(hostLabel ? ` [${hostLabel}]` : '');
|
||||
this.userRemoteSettings = new Action('userSettingsRemote', remoteSettingsLabel, '.settings-tab', true, () => this.updateTarget(ConfigurationTarget.USER_REMOTE));
|
||||
this.userRemoteSettings.tooltip = this.userRemoteSettings.label;
|
||||
|
||||
@@ -751,7 +751,7 @@ export class EditPreferenceWidget<T> extends Disposable {
|
||||
|
||||
private _editPreferenceDecoration: string[];
|
||||
|
||||
private readonly _onClick = new Emitter<IEditorMouseEvent>();
|
||||
private readonly _onClick = this._register(new Emitter<IEditorMouseEvent>());
|
||||
get onClick(): Event<IEditorMouseEvent> { return this._onClick.event; }
|
||||
|
||||
constructor(private editor: ICodeEditor
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { ITreeElement } from 'vs/base/browser/ui/tree/tree';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { Delayer, ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { Delayer, ThrottledDelayer, timeout } from 'vs/base/common/async';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as collections from 'vs/base/common/collections';
|
||||
import { getErrorMessage, isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
@@ -211,7 +211,7 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
setInput(input: SettingsEditor2Input, options: SettingsEditorOptions | null, token: CancellationToken): Promise<void> {
|
||||
this.inSettingsEditorContextKey.set(true);
|
||||
return super.setInput(input, options, token)
|
||||
.then(() => new Promise(process.nextTick)) // Force setInput to be async
|
||||
.then(() => timeout(0)) // Force setInput to be async
|
||||
.then(() => {
|
||||
return this.render(token);
|
||||
})
|
||||
@@ -251,10 +251,12 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
}
|
||||
}
|
||||
|
||||
setOptions(options: SettingsEditorOptions): void {
|
||||
setOptions(options: SettingsEditorOptions | null): void {
|
||||
super.setOptions(options);
|
||||
|
||||
this._setOptions(options);
|
||||
if (options) {
|
||||
this._setOptions(options);
|
||||
}
|
||||
}
|
||||
|
||||
private _setOptions(options: SettingsEditorOptions): void {
|
||||
@@ -565,7 +567,7 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
}
|
||||
|
||||
private createTOC(parent: HTMLElement): void {
|
||||
this.tocTreeModel = new TOCTreeModel(this.viewState);
|
||||
this.tocTreeModel = this.instantiationService.createInstance(TOCTreeModel, this.viewState);
|
||||
this.tocTreeContainer = DOM.append(parent, $('.settings-toc-container'));
|
||||
|
||||
this.tocTree = this._register(this.instantiationService.createInstance(TOCTree,
|
||||
@@ -25,7 +25,7 @@ import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ISpliceable } from 'vs/base/common/sequence';
|
||||
import { escapeRegExpCharacters, startsWith } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -45,6 +45,7 @@ import { ISettingsEditorViewState, settingKeyToDisplayFormat, SettingsTreeElemen
|
||||
import { ExcludeSettingWidget, IExcludeChangeEvent, IExcludeDataItem, settingsHeaderForeground, settingsNumberInputBackground, settingsNumberInputBorder, settingsNumberInputForeground, settingsSelectBackground, settingsSelectBorder, settingsSelectForeground, settingsSelectListBorder, settingsTextInputBackground, settingsTextInputBorder, settingsTextInputForeground } from 'vs/workbench/contrib/preferences/browser/settingsWidgets';
|
||||
import { SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU } from 'vs/workbench/contrib/preferences/common/preferences';
|
||||
import { ISetting, ISettingsGroup, SettingValueType } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -249,7 +250,7 @@ export interface ISettingOverrideClickEvent {
|
||||
targetKey: string;
|
||||
}
|
||||
|
||||
export abstract class AbstractSettingRenderer implements ITreeRenderer<SettingsTreeElement, never, any> {
|
||||
export abstract class AbstractSettingRenderer extends Disposable implements ITreeRenderer<SettingsTreeElement, never, any> {
|
||||
/** To override */
|
||||
abstract get templateId(): string;
|
||||
|
||||
@@ -261,19 +262,19 @@ export abstract class AbstractSettingRenderer implements ITreeRenderer<SettingsT
|
||||
static readonly SETTING_KEY_ATTR = 'data-key';
|
||||
static readonly SETTING_ID_ATTR = 'data-id';
|
||||
|
||||
private readonly _onDidClickOverrideElement = new Emitter<ISettingOverrideClickEvent>();
|
||||
private readonly _onDidClickOverrideElement = this._register(new Emitter<ISettingOverrideClickEvent>());
|
||||
readonly onDidClickOverrideElement: Event<ISettingOverrideClickEvent> = this._onDidClickOverrideElement.event;
|
||||
|
||||
protected readonly _onDidChangeSetting = new Emitter<ISettingChangeEvent>();
|
||||
protected readonly _onDidChangeSetting = this._register(new Emitter<ISettingChangeEvent>());
|
||||
readonly onDidChangeSetting: Event<ISettingChangeEvent> = this._onDidChangeSetting.event;
|
||||
|
||||
protected readonly _onDidOpenSettings = new Emitter<string>();
|
||||
protected readonly _onDidOpenSettings = this._register(new Emitter<string>());
|
||||
readonly onDidOpenSettings: Event<string> = this._onDidOpenSettings.event;
|
||||
|
||||
private readonly _onDidClickSettingLink = new Emitter<ISettingLinkClickEvent>();
|
||||
private readonly _onDidClickSettingLink = this._register(new Emitter<ISettingLinkClickEvent>());
|
||||
readonly onDidClickSettingLink: Event<ISettingLinkClickEvent> = this._onDidClickSettingLink.event;
|
||||
|
||||
private readonly _onDidFocusSetting = new Emitter<SettingsTreeSettingElement>();
|
||||
private readonly _onDidFocusSetting = this._register(new Emitter<SettingsTreeSettingElement>());
|
||||
readonly onDidFocusSetting: Event<SettingsTreeSettingElement> = this._onDidFocusSetting.event;
|
||||
|
||||
// Put common injections back here
|
||||
@@ -287,6 +288,7 @@ export abstract class AbstractSettingRenderer implements ITreeRenderer<SettingsT
|
||||
@IContextMenuService protected readonly _contextMenuService: IContextMenuService,
|
||||
@IKeybindingService protected readonly _keybindingService: IKeybindingService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
renderTemplate(container: HTMLElement): any {
|
||||
@@ -939,11 +941,11 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre
|
||||
|
||||
const deprecationWarningElement = DOM.append(container, $('.setting-item-deprecation-message'));
|
||||
|
||||
const toDispose: IDisposable[] = [];
|
||||
const toDispose = new DisposableStore();
|
||||
const checkbox = new Checkbox({ actionClassName: 'setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: undefined });
|
||||
controlElement.appendChild(checkbox.domNode);
|
||||
toDispose.push(checkbox);
|
||||
toDispose.push(checkbox.onChange(() => {
|
||||
toDispose.add(checkbox);
|
||||
toDispose.add(checkbox.onChange(() => {
|
||||
if (template.onChange) {
|
||||
template.onChange(checkbox.checked);
|
||||
}
|
||||
@@ -951,7 +953,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre
|
||||
|
||||
// Need to listen for mouse clicks on description and toggle checkbox - use target ID for safety
|
||||
// Also have to ignore embedded links - too buried to stop propagation
|
||||
toDispose.push(DOM.addDisposableListener(descriptionElement, DOM.EventType.MOUSE_DOWN, (e) => {
|
||||
toDispose.add(DOM.addDisposableListener(descriptionElement, DOM.EventType.MOUSE_DOWN, (e) => {
|
||||
const targetElement = <HTMLElement>e.target;
|
||||
const targetId = descriptionElement.getAttribute('checkbox_label_target_id');
|
||||
|
||||
@@ -968,10 +970,10 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre
|
||||
checkbox.domNode.classList.add(AbstractSettingRenderer.CONTROL_CLASS);
|
||||
const toolbarContainer = DOM.append(container, $('.setting-toolbar-container'));
|
||||
const toolbar = this.renderSettingToolbar(toolbarContainer);
|
||||
toDispose.push(toolbar);
|
||||
toDispose.add(toolbar);
|
||||
|
||||
const template: ISettingBoolItemTemplate = {
|
||||
toDispose,
|
||||
toDispose: [toDispose],
|
||||
|
||||
containerElement: container,
|
||||
categoryElement,
|
||||
@@ -987,16 +989,16 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre
|
||||
this.addSettingElementFocusHandler(template);
|
||||
|
||||
// Prevent clicks from being handled by list
|
||||
toDispose.push(DOM.addDisposableListener(controlElement, 'mousedown', (e: IMouseEvent) => e.stopPropagation()));
|
||||
toDispose.add(DOM.addDisposableListener(controlElement, 'mousedown', (e: IMouseEvent) => e.stopPropagation()));
|
||||
|
||||
toDispose.push(DOM.addStandardDisposableListener(controlElement, 'keydown', (e: StandardKeyboardEvent) => {
|
||||
toDispose.add(DOM.addStandardDisposableListener(controlElement, 'keydown', (e: StandardKeyboardEvent) => {
|
||||
if (e.keyCode === KeyCode.Escape) {
|
||||
e.browserEvent.stopPropagation();
|
||||
}
|
||||
}));
|
||||
|
||||
toDispose.push(DOM.addDisposableListener(titleElement, DOM.EventType.MOUSE_ENTER, e => container.classList.add('mouseover')));
|
||||
toDispose.push(DOM.addDisposableListener(titleElement, DOM.EventType.MOUSE_LEAVE, e => container.classList.remove('mouseover')));
|
||||
toDispose.add(DOM.addDisposableListener(titleElement, DOM.EventType.MOUSE_ENTER, e => container.classList.add('mouseover')));
|
||||
toDispose.add(DOM.addDisposableListener(titleElement, DOM.EventType.MOUSE_LEAVE, e => container.classList.remove('mouseover')));
|
||||
|
||||
return template;
|
||||
}
|
||||
@@ -1163,6 +1165,7 @@ function escapeInvisibleChars(enumValue: string): string {
|
||||
export class SettingsTreeFilter implements ITreeFilter<SettingsTreeElement> {
|
||||
constructor(
|
||||
private viewState: ISettingsEditorViewState,
|
||||
@IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService,
|
||||
) { }
|
||||
|
||||
filter(element: SettingsTreeElement, parentVisibility: TreeVisibility): TreeFilterResult<void> {
|
||||
@@ -1175,7 +1178,8 @@ export class SettingsTreeFilter implements ITreeFilter<SettingsTreeElement> {
|
||||
|
||||
// Non-user scope selected
|
||||
if (element instanceof SettingsTreeSettingElement && this.viewState.settingsTarget !== ConfigurationTarget.USER_LOCAL) {
|
||||
if (!element.matchesScope(this.viewState.settingsTarget)) {
|
||||
const isRemote = !!this.environmentService.configuration.remoteAuthority;
|
||||
if (!element.matchesScope(this.viewState.settingsTarget, isRemote)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1303,7 +1307,8 @@ export class SettingsTree extends ObjectTree<SettingsTreeElement> {
|
||||
container: HTMLElement,
|
||||
viewState: ISettingsEditorViewState,
|
||||
renderers: ITreeRenderer<any, void, any>[],
|
||||
@IThemeService themeService: IThemeService
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
const treeClass = 'settings-editor-tree';
|
||||
|
||||
@@ -1320,7 +1325,7 @@ export class SettingsTree extends ObjectTree<SettingsTreeElement> {
|
||||
}
|
||||
},
|
||||
styleController: new DefaultStyleController(DOM.createStyleSheet(container), treeClass),
|
||||
filter: new SettingsTreeFilter(viewState)
|
||||
filter: instantiationService.createInstance(SettingsTreeFilter, viewState)
|
||||
});
|
||||
|
||||
this.disposables = [];
|
||||
|
||||
@@ -14,6 +14,7 @@ import { SettingsTarget } from 'vs/workbench/contrib/preferences/browser/prefere
|
||||
import { ITOCEntry, knownAcronyms, knownTermMappings } from 'vs/workbench/contrib/preferences/browser/settingsLayout';
|
||||
import { MODIFIED_SETTING_TAG } from 'vs/workbench/contrib/preferences/common/preferences';
|
||||
import { IExtensionSetting, ISearchResult, ISetting, SettingValueType } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
export const ONLINE_SERVICES_SETTING_TAG = 'usesOnlineServices';
|
||||
|
||||
@@ -221,7 +222,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement {
|
||||
}
|
||||
}
|
||||
|
||||
matchesScope(scope: SettingsTarget): boolean {
|
||||
matchesScope(scope: SettingsTarget, isRemote: boolean): boolean {
|
||||
const configTarget = URI.isUri(scope) ? ConfigurationTarget.WORKSPACE_FOLDER : scope;
|
||||
|
||||
if (configTarget === ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
@@ -236,6 +237,10 @@ export class SettingsTreeSettingElement extends SettingsTreeElement {
|
||||
return this.setting.scope === ConfigurationScope.MACHINE || this.setting.scope === ConfigurationScope.WINDOW || this.setting.scope === ConfigurationScope.RESOURCE;
|
||||
}
|
||||
|
||||
if (configTarget === ConfigurationTarget.USER_LOCAL && isRemote) {
|
||||
return this.setting.scope !== ConfigurationScope.MACHINE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -479,7 +484,8 @@ export class SearchResultModel extends SettingsTreeModel {
|
||||
|
||||
constructor(
|
||||
viewState: ISettingsEditorViewState,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService,
|
||||
) {
|
||||
super(viewState, configurationService);
|
||||
this.update({ id: 'searchResultModel', label: '' });
|
||||
@@ -537,8 +543,9 @@ export class SearchResultModel extends SettingsTreeModel {
|
||||
});
|
||||
|
||||
// Save time, filter children in the search model instead of relying on the tree filter, which still requires heights to be calculated.
|
||||
const isRemote = !!this.environmentService.configuration.remoteAuthority;
|
||||
this.root.children = this.root.children
|
||||
.filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget) && child.matchesAnyExtension(this._viewState.extensionFilters));
|
||||
.filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters));
|
||||
|
||||
if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) {
|
||||
const newExtElement = new SettingsTreeNewExtensionsElement();
|
||||
|
||||
@@ -203,7 +203,7 @@ export class ExcludeSettingWidget extends Disposable {
|
||||
|
||||
private model = new ExcludeSettingListModel();
|
||||
|
||||
private readonly _onDidChangeExclude = new Emitter<IExcludeChangeEvent>();
|
||||
private readonly _onDidChangeExclude = this._register(new Emitter<IExcludeChangeEvent>());
|
||||
readonly onDidChangeExclude: Event<IExcludeChangeEvent> = this._onDidChangeExclude.event;
|
||||
|
||||
get domNode(): HTMLElement {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { SettingsTreeFilter } from 'vs/workbench/contrib/preferences/browser/set
|
||||
import { ISettingsEditorViewState, SearchResultModel, SettingsTreeElement, SettingsTreeGroupElement, SettingsTreeSettingElement } from 'vs/workbench/contrib/preferences/browser/settingsTreeModels';
|
||||
import { settingsHeaderForeground } from 'vs/workbench/contrib/preferences/browser/settingsWidgets';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -25,7 +26,10 @@ export class TOCTreeModel {
|
||||
private _currentSearchModel: SearchResultModel | null;
|
||||
private _settingsTreeRoot: SettingsTreeGroupElement;
|
||||
|
||||
constructor(private _viewState: ISettingsEditorViewState) {
|
||||
constructor(
|
||||
private _viewState: ISettingsEditorViewState,
|
||||
@IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
}
|
||||
|
||||
get settingsTreeRoot(): SettingsTreeGroupElement {
|
||||
@@ -81,7 +85,8 @@ export class TOCTreeModel {
|
||||
}
|
||||
|
||||
// Check everything that the SettingsFilter checks except whether it's filtered by a category
|
||||
return child.matchesScope(this._viewState.settingsTarget) && child.matchesAllTags(this._viewState.tagFilters) && child.matchesAnyExtension(this._viewState.extensionFilters);
|
||||
const isRemote = !!this.environmentService.configuration.remoteAuthority;
|
||||
return child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAllTags(this._viewState.tagFilters) && child.matchesAnyExtension(this._viewState.extensionFilters);
|
||||
}).length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { endsWith } from 'vs/base/common/strings';
|
||||
@@ -79,7 +79,7 @@ export class PreferencesContribution implements IWorkbenchContribution {
|
||||
}
|
||||
|
||||
// Global User Settings File
|
||||
if (isEqual(resource, URI.file(this.environmentService.appSettingsPath), !isLinux)) {
|
||||
if (isEqual(resource, this.environmentService.settingsResource, !isLinux)) {
|
||||
return { override: this.preferencesService.openGlobalSettings(true, options, group) };
|
||||
}
|
||||
|
||||
@@ -129,14 +129,14 @@ export class PreferencesContribution implements IWorkbenchContribution {
|
||||
const modelContent = JSON.stringify(schema);
|
||||
const languageSelection = this.modeService.create('jsonc');
|
||||
const model = this.modelService.createModel(modelContent, languageSelection, uri);
|
||||
const disposables: IDisposable[] = [];
|
||||
disposables.push(schemaRegistry.onDidChangeSchema(schemaUri => {
|
||||
const disposables = new DisposableStore();
|
||||
disposables.add(schemaRegistry.onDidChangeSchema(schemaUri => {
|
||||
if (schemaUri === uri.toString()) {
|
||||
schema = schemaRegistry.getSchemaContributions().schemas[uri.toString()];
|
||||
model.setValue(JSON.stringify(schema));
|
||||
}
|
||||
}));
|
||||
disposables.push(model.onWillDispose(() => dispose(disposables)));
|
||||
disposables.add(model.onWillDispose(() => disposables.dispose()));
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -4,18 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ISettingsEditorModel, ISetting, ISettingsGroup, IFilterMetadata, ISearchResult, IGroupFilter, ISettingMatcher, IScoredResults, ISettingMatch, IRemoteSetting, IExtensionSetting } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { distinct, top } from 'vs/base/common/arrays';
|
||||
import { top } from 'vs/base/common/arrays';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IMatch, or, matchesContiguousSubString, matchesPrefix, matchesCamelCase, matchesWords } from 'vs/base/common/filters';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IRequestService } from 'vs/platform/request/node/request';
|
||||
import { asJson } from 'vs/base/node/request';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionManagementService, ILocalExtension, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IPreferencesSearchService, ISearchProvider, IWorkbenchSettingsConfiguration } from 'vs/workbench/contrib/preferences/common/preferences';
|
||||
@@ -24,25 +18,26 @@ import { canceled } from 'vs/base/common/errors';
|
||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { nullRange } from 'vs/workbench/services/preferences/common/preferencesModels';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { PreferencesSearchService as LocalPreferencesSearchService, SettingMatches } from 'vs/workbench/contrib/preferences/browser/preferencesSearch';
|
||||
|
||||
export interface IEndpointDetails {
|
||||
urlBase?: string;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
export class PreferencesSearchService extends Disposable implements IPreferencesSearchService {
|
||||
export class PreferencesSearchService extends LocalPreferencesSearchService implements IPreferencesSearchService {
|
||||
_serviceBrand: any;
|
||||
|
||||
private _installedExtensions: Promise<ILocalExtension[]>;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
|
||||
) {
|
||||
super();
|
||||
super(instantiationService);
|
||||
|
||||
// This request goes to the shared process but results won't change during a window's lifetime, so cache the results.
|
||||
this._installedExtensions = this.extensionManagementService.getInstalled(ExtensionType.User).then(exts => {
|
||||
@@ -86,10 +81,6 @@ export class PreferencesSearchService extends Disposable implements IPreferences
|
||||
|
||||
return this.remoteSearchAllowed ? this.instantiationService.createInstance(RemoteSearchProvider, opts, this._installedExtensions) : undefined;
|
||||
}
|
||||
|
||||
getLocalSearchProvider(filter: string): LocalSearchProvider {
|
||||
return this.instantiationService.createInstance(LocalSearchProvider, filter);
|
||||
}
|
||||
}
|
||||
|
||||
export class LocalSearchProvider implements ISearchProvider {
|
||||
@@ -437,129 +428,4 @@ function remoteSettingToISetting(remoteSetting: IRemoteSetting): IExtensionSetti
|
||||
extensionName: remoteSetting.extensionName,
|
||||
extensionPublisher: remoteSetting.extensionPublisher
|
||||
};
|
||||
}
|
||||
|
||||
class SettingMatches {
|
||||
|
||||
private readonly descriptionMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
private readonly keyMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
private readonly valueMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
|
||||
readonly matches: IRange[];
|
||||
|
||||
constructor(searchString: string, setting: ISetting, private requireFullQueryMatch: boolean, private searchDescription: boolean, private valuesMatcher: (filter: string, setting: ISetting) => IRange[]) {
|
||||
this.matches = distinct(this._findMatchesInSetting(searchString, setting), (match) => `${match.startLineNumber}_${match.startColumn}_${match.endLineNumber}_${match.endColumn}_`);
|
||||
}
|
||||
|
||||
private _findMatchesInSetting(searchString: string, setting: ISetting): IRange[] {
|
||||
const result = this._doFindMatchesInSetting(searchString, setting);
|
||||
if (setting.overrides && setting.overrides.length) {
|
||||
for (const subSetting of setting.overrides) {
|
||||
const subSettingMatches = new SettingMatches(searchString, subSetting, this.requireFullQueryMatch, this.searchDescription, this.valuesMatcher);
|
||||
const words = searchString.split(' ');
|
||||
const descriptionRanges: IRange[] = this.getRangesForWords(words, this.descriptionMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const keyRanges: IRange[] = this.getRangesForWords(words, this.keyMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const subSettingKeyRanges: IRange[] = this.getRangesForWords(words, subSettingMatches.keyMatchingWords, [this.descriptionMatchingWords, this.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const subSettinValueRanges: IRange[] = this.getRangesForWords(words, subSettingMatches.valueMatchingWords, [this.descriptionMatchingWords, this.keyMatchingWords, subSettingMatches.keyMatchingWords]);
|
||||
result.push(...descriptionRanges, ...keyRanges, ...subSettingKeyRanges, ...subSettinValueRanges);
|
||||
result.push(...subSettingMatches.matches);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private _doFindMatchesInSetting(searchString: string, setting: ISetting): IRange[] {
|
||||
const registry: { [qualifiedKey: string]: IJSONSchema } = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
|
||||
const schema: IJSONSchema = registry[setting.key];
|
||||
|
||||
const words = searchString.split(' ');
|
||||
const settingKeyAsWords: string = setting.key.split('.').join(' ');
|
||||
|
||||
for (const word of words) {
|
||||
if (this.searchDescription) {
|
||||
for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) {
|
||||
const descriptionMatches = matchesWords(word, setting.description[lineIndex], true);
|
||||
if (descriptionMatches) {
|
||||
this.descriptionMatchingWords.set(word, descriptionMatches.map(match => this.toDescriptionRange(setting, match, lineIndex)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const keyMatches = or(matchesWords, matchesCamelCase)(word, settingKeyAsWords);
|
||||
if (keyMatches) {
|
||||
this.keyMatchingWords.set(word, keyMatches.map(match => this.toKeyRange(setting, match)));
|
||||
}
|
||||
|
||||
const valueMatches = typeof setting.value === 'string' ? matchesContiguousSubString(word, setting.value) : null;
|
||||
if (valueMatches) {
|
||||
this.valueMatchingWords.set(word, valueMatches.map(match => this.toValueRange(setting, match)));
|
||||
} else if (schema && schema.enum && schema.enum.some(enumValue => typeof enumValue === 'string' && !!matchesContiguousSubString(word, enumValue))) {
|
||||
this.valueMatchingWords.set(word, []);
|
||||
}
|
||||
}
|
||||
|
||||
const descriptionRanges: IRange[] = [];
|
||||
if (this.searchDescription) {
|
||||
for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) {
|
||||
const matches = or(matchesContiguousSubString)(searchString, setting.description[lineIndex] || '') || [];
|
||||
descriptionRanges.push(...matches.map(match => this.toDescriptionRange(setting, match, lineIndex)));
|
||||
}
|
||||
if (descriptionRanges.length === 0) {
|
||||
descriptionRanges.push(...this.getRangesForWords(words, this.descriptionMatchingWords, [this.keyMatchingWords, this.valueMatchingWords]));
|
||||
}
|
||||
}
|
||||
|
||||
const keyMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.key);
|
||||
const keyRanges: IRange[] = keyMatches ? keyMatches.map(match => this.toKeyRange(setting, match)) : this.getRangesForWords(words, this.keyMatchingWords, [this.descriptionMatchingWords, this.valueMatchingWords]);
|
||||
|
||||
let valueRanges: IRange[] = [];
|
||||
if (setting.value && typeof setting.value === 'string') {
|
||||
const valueMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.value);
|
||||
valueRanges = valueMatches ? valueMatches.map(match => this.toValueRange(setting, match)) : this.getRangesForWords(words, this.valueMatchingWords, [this.keyMatchingWords, this.descriptionMatchingWords]);
|
||||
} else {
|
||||
valueRanges = this.valuesMatcher ? this.valuesMatcher(searchString, setting) : [];
|
||||
}
|
||||
|
||||
return [...descriptionRanges, ...keyRanges, ...valueRanges];
|
||||
}
|
||||
|
||||
private getRangesForWords(words: string[], from: Map<string, IRange[]>, others: Map<string, IRange[]>[]): IRange[] {
|
||||
const result: IRange[] = [];
|
||||
for (const word of words) {
|
||||
const ranges = from.get(word);
|
||||
if (ranges) {
|
||||
result.push(...ranges);
|
||||
} else if (this.requireFullQueryMatch && others.every(o => !o.has(word))) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private toKeyRange(setting: ISetting, match: IMatch): IRange {
|
||||
return {
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn + match.start,
|
||||
endLineNumber: setting.keyRange.startLineNumber,
|
||||
endColumn: setting.keyRange.startColumn + match.end
|
||||
};
|
||||
}
|
||||
|
||||
private toDescriptionRange(setting: ISetting, match: IMatch, lineIndex: number): IRange {
|
||||
return {
|
||||
startLineNumber: setting.descriptionRanges[lineIndex].startLineNumber,
|
||||
startColumn: setting.descriptionRanges[lineIndex].startColumn + match.start,
|
||||
endLineNumber: setting.descriptionRanges[lineIndex].endLineNumber,
|
||||
endColumn: setting.descriptionRanges[lineIndex].startColumn + match.end
|
||||
};
|
||||
}
|
||||
|
||||
private toValueRange(setting: ISetting, match: IMatch): IRange {
|
||||
return {
|
||||
startLineNumber: setting.valueRange.startLineNumber,
|
||||
startColumn: setting.valueRange.startColumn + match.start + 1,
|
||||
endLineNumber: setting.valueRange.startLineNumber,
|
||||
endColumn: setting.valueRange.startColumn + match.end + 1
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||