提交 85e2b3b6 编写于 作者: S Sandeep Somavarapu

#75079 Move preferences to browser

上级 a85b5f0f
......@@ -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,8 +397,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: ResourceContextKey.Resource.isEqualTo(environmentService.settingsResource.toString()),
......@@ -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',
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. 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
};
}
}
\ No newline at end of file
......@@ -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
};
}
}
}
\ No newline at end of file
......@@ -191,8 +191,11 @@ import 'vs/workbench/contrib/telemetry/browser/telemetry.contribution';
import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
// Preferences
import 'vs/workbench/contrib/preferences/electron-browser/preferences.contribution';
import 'vs/workbench/contrib/preferences/browser/preferences.contribution';
import 'vs/workbench/contrib/preferences/browser/keybindingsEditorContribution';
import { IPreferencesSearchService } from 'vs/workbench/contrib/preferences/common/preferences';
import { PreferencesSearchService } from 'vs/workbench/contrib/preferences/electron-browser/preferencesSearch';
registerSingleton(IPreferencesSearchService, PreferencesSearchService, true);
// Logs
import 'vs/workbench/contrib/logs/common/logs.contribution';
......
......@@ -194,8 +194,11 @@ import 'vs/workbench/contrib/telemetry/browser/telemetry.contribution';
// import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
// Preferences
// import 'vs/workbench/contrib/preferences/electron-browser/preferences.contribution';
import 'vs/workbench/contrib/preferences/browser/preferences.contribution';
import 'vs/workbench/contrib/preferences/browser/keybindingsEditorContribution';
import { IPreferencesSearchService } from 'vs/workbench/contrib/preferences/common/preferences';
import { PreferencesSearchService } from 'vs/workbench/contrib/preferences/browser/preferencesSearch';
registerSingleton(IPreferencesSearchService, PreferencesSearchService, true);
// Logs
import 'vs/workbench/contrib/logs/common/logs.contribution';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册