提交 b77192b4 编写于 作者: J Jackson Kearl

Fix #91121.

上级 50e742c4
...@@ -34,7 +34,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti ...@@ -34,7 +34,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { TreeResourceNavigator, WorkbenchObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService'; import { TreeResourceNavigator, WorkbenchObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService';
import { INotificationService } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';
import { IProgressService, IProgressStep, IProgress } from 'vs/platform/progress/common/progress'; import { IProgressService, IProgressStep, IProgress } from 'vs/platform/progress/common/progress';
import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, VIEW_ID, SearchSortOrder } from 'vs/workbench/services/search/common/search'; import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, VIEW_ID, SearchSortOrder, SearchCompletionExitCode } from 'vs/workbench/services/search/common/search';
import { ISearchHistoryService, ISearchHistoryValues } from 'vs/workbench/contrib/search/common/searchHistoryService'; import { ISearchHistoryService, ISearchHistoryValues } from 'vs/workbench/contrib/search/common/searchHistoryService';
import { diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, editorFindMatchHighlight, editorFindMatchHighlightBorder, listActiveSelectionForeground, foreground } from 'vs/platform/theme/common/colorRegistry'; import { diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, editorFindMatchHighlight, editorFindMatchHighlightBorder, listActiveSelectionForeground, foreground } from 'vs/platform/theme/common/colorRegistry';
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
...@@ -1348,7 +1348,7 @@ export class SearchView extends ViewPane { ...@@ -1348,7 +1348,7 @@ export class SearchView extends ViewPane {
this.inputPatternIncludes.onSearchSubmit(); this.inputPatternIncludes.onSearchSubmit();
}); });
this.viewModel.cancelSearch(); this.viewModel.cancelSearch(true);
this.currentSearchQ = this.currentSearchQ this.currentSearchQ = this.currentSearchQ
.then(() => this.doSearch(query, excludePatternText, includePatternText, triggeredOnType)) .then(() => this.doSearch(query, excludePatternText, includePatternText, triggeredOnType))
...@@ -1393,6 +1393,10 @@ export class SearchView extends ViewPane { ...@@ -1393,6 +1393,10 @@ export class SearchView extends ViewPane {
this.updateActions(); this.updateActions();
const hasResults = !this.viewModel.searchResult.isEmpty(); const hasResults = !this.viewModel.searchResult.isEmpty();
if (completed?.exit === SearchCompletionExitCode.NewSearchStarted) {
return;
}
if (completed && completed.limitHit) { if (completed && completed.limitHit) {
this.searchWidget.searchInput.showMessage({ this.searchWidget.searchInput.showMessage({
content: nls.localize('searchMaxResultsWarning', "The result set only contains a subset of all matches. Please be more specific in your search to narrow down the results."), content: nls.localize('searchMaxResultsWarning', "The result set only contains a subset of all matches. Please be more specific in your search to narrow down the results."),
......
...@@ -154,7 +154,6 @@ export class SearchWidget extends Widget { ...@@ -154,7 +154,6 @@ export class SearchWidget extends Widget {
private readonly _onDidToggleContext = new Emitter<void>(); private readonly _onDidToggleContext = new Emitter<void>();
readonly onDidToggleContext: Event<void> = this._onDidToggleContext.event; readonly onDidToggleContext: Event<void> = this._onDidToggleContext.event;
private temporarilySkipSearchOnChange = false;
private showContextCheckbox!: Checkbox; private showContextCheckbox!: Checkbox;
private contextLinesInput!: InputBox; private contextLinesInput!: InputBox;
...@@ -488,12 +487,10 @@ export class SearchWidget extends Widget { ...@@ -488,12 +487,10 @@ export class SearchWidget extends Widget {
this.setReplaceAllActionState(false); this.setReplaceAllActionState(false);
if (this.searchConfiguration.searchOnType) { if (this.searchConfiguration.searchOnType) {
if (!this.temporarilySkipSearchOnChange) { if (this.searchInput.getRegex()) {
this._onSearchCancel.fire({ focus: false }); try {
if (this.searchInput.getRegex()) { const regex = new RegExp(this.searchInput.getValue(), 'ug');
try { const matchienessHeuristic = `
const regex = new RegExp(this.searchInput.getValue(), 'ug');
const matchienessHeuristic = `
~!@#$%^&*()_+ ~!@#$%^&*()_+
\`1234567890-= \`1234567890-=
qwertyuiop[]\\ qwertyuiop[]\\
...@@ -503,18 +500,17 @@ export class SearchWidget extends Widget { ...@@ -503,18 +500,17 @@ export class SearchWidget extends Widget {
zxcvbnm,./ zxcvbnm,./
ZXCVBNM<>? `.match(regex)?.length ?? 0; ZXCVBNM<>? `.match(regex)?.length ?? 0;
const delayMultiplier = const delayMultiplier =
matchienessHeuristic < 50 ? 1 : matchienessHeuristic < 50 ? 1 :
matchienessHeuristic < 100 ? 5 : // expressions like `.` or `\w` matchienessHeuristic < 100 ? 5 : // expressions like `.` or `\w`
10; // only things matching empty string 10; // only things matching empty string
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod * delayMultiplier); this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod * delayMultiplier);
} catch { } catch {
// pass // pass
}
} else {
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod);
} }
} else {
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod);
} }
} }
} }
......
...@@ -20,7 +20,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; ...@@ -20,7 +20,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress'; import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
import { ReplacePattern } from 'vs/workbench/services/search/common/replace'; import { ReplacePattern } from 'vs/workbench/services/search/common/replace';
import { IFileMatch, IPatternInfo, ISearchComplete, ISearchProgressItem, ISearchConfigurationProperties, ISearchService, ITextQuery, ITextSearchPreviewOptions, ITextSearchMatch, ITextSearchStats, resultIsMatch, ISearchRange, OneLineRange, ITextSearchContext, ITextSearchResult, SearchSortOrder } from 'vs/workbench/services/search/common/search'; import { IFileMatch, IPatternInfo, ISearchComplete, ISearchProgressItem, ISearchConfigurationProperties, ISearchService, ITextQuery, ITextSearchPreviewOptions, ITextSearchMatch, ITextSearchStats, resultIsMatch, ISearchRange, OneLineRange, ITextSearchContext, ITextSearchResult, SearchSortOrder, SearchCompletionExitCode } from 'vs/workbench/services/search/common/search';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { overviewRulerFindMatchForeground, minimapFindMatch } from 'vs/platform/theme/common/colorRegistry'; import { overviewRulerFindMatchForeground, minimapFindMatch } from 'vs/platform/theme/common/colorRegistry';
import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { themeColorFromId } from 'vs/platform/theme/common/themeService';
...@@ -968,6 +968,7 @@ export class SearchModel extends Disposable { ...@@ -968,6 +968,7 @@ export class SearchModel extends Disposable {
readonly onReplaceTermChanged: Event<void> = this._onReplaceTermChanged.event; readonly onReplaceTermChanged: Event<void> = this._onReplaceTermChanged.event;
private currentCancelTokenSource: CancellationTokenSource | null = null; private currentCancelTokenSource: CancellationTokenSource | null = null;
private searchCancelledForNewSearch: boolean = false;
constructor( constructor(
@ISearchService private readonly searchService: ISearchService, @ISearchService private readonly searchService: ISearchService,
...@@ -1016,7 +1017,7 @@ export class SearchModel extends Disposable { ...@@ -1016,7 +1017,7 @@ export class SearchModel extends Disposable {
} }
search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> { search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> {
this.cancelSearch(); this.cancelSearch(true);
this._searchQuery = query; this._searchQuery = query;
...@@ -1114,7 +1115,12 @@ export class SearchModel extends Disposable { ...@@ -1114,7 +1115,12 @@ export class SearchModel extends Disposable {
private onSearchError(e: any, duration: number): void { private onSearchError(e: any, duration: number): void {
if (errors.isPromiseCanceledError(e)) { if (errors.isPromiseCanceledError(e)) {
this.onSearchCompleted(null, duration); this.onSearchCompleted(
this.searchCancelledForNewSearch
? { exit: SearchCompletionExitCode.NewSearchStarted, results: [] }
: null,
duration);
this.searchCancelledForNewSearch = false;
} }
} }
...@@ -1133,8 +1139,9 @@ export class SearchModel extends Disposable { ...@@ -1133,8 +1139,9 @@ export class SearchModel extends Disposable {
return this.configurationService.getValue<ISearchConfigurationProperties>('search'); return this.configurationService.getValue<ISearchConfigurationProperties>('search');
} }
cancelSearch(): boolean { cancelSearch(cancelledForNewSearch = false): boolean {
if (this.currentCancelTokenSource) { if (this.currentCancelTokenSource) {
this.searchCancelledForNewSearch = cancelledForNewSearch;
this.currentCancelTokenSource.cancel(); this.currentCancelTokenSource.cancel();
return true; return true;
} }
......
...@@ -77,6 +77,7 @@ export class SearchEditor extends BaseTextEditor { ...@@ -77,6 +77,7 @@ export class SearchEditor extends BaseTextEditor {
private searchHistoryDelayer: Delayer<void>; private searchHistoryDelayer: Delayer<void>;
private messageDisposables: IDisposable[] = []; private messageDisposables: IDisposable[] = [];
private container: HTMLElement; private container: HTMLElement;
private searchModel: SearchModel;
constructor( constructor(
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
...@@ -107,6 +108,8 @@ export class SearchEditor extends BaseTextEditor { ...@@ -107,6 +108,8 @@ export class SearchEditor extends BaseTextEditor {
this.inputFocusContextKey = InputBoxFocusedKey.bindTo(scopedContextKeyService); this.inputFocusContextKey = InputBoxFocusedKey.bindTo(scopedContextKeyService);
this.searchOperation = this._register(new LongRunningOperation(progressService)); this.searchOperation = this._register(new LongRunningOperation(progressService));
this.searchHistoryDelayer = new Delayer<void>(2000); this.searchHistoryDelayer = new Delayer<void>(2000);
this.searchModel = this._register(this.instantiationService.createInstance(SearchModel));
} }
createEditor(parent: HTMLElement) { createEditor(parent: HTMLElement) {
...@@ -326,6 +329,8 @@ export class SearchEditor extends BaseTextEditor { ...@@ -326,6 +329,8 @@ export class SearchEditor extends BaseTextEditor {
} }
private async doRunSearch() { private async doRunSearch() {
this.searchModel.cancelSearch(true);
const startInput = this.getInput(); const startInput = this.getInput();
this.searchHistoryDelayer.trigger(() => { this.searchHistoryDelayer.trigger(() => {
...@@ -372,30 +377,26 @@ export class SearchEditor extends BaseTextEditor { ...@@ -372,30 +377,26 @@ export class SearchEditor extends BaseTextEditor {
catch (err) { catch (err) {
return; return;
} }
const searchModel = this.instantiationService.createInstance(SearchModel);
this.searchOperation.start(500); this.searchOperation.start(500);
await searchModel.search(query).finally(() => this.searchOperation.stop()); await this.searchModel.search(query).finally(() => this.searchOperation.stop());
const input = this.getInput(); const input = this.getInput();
if (!input || if (!input ||
input !== startInput || input !== startInput ||
JSON.stringify(config) !== JSON.stringify(this.readConfigFromWidget())) { JSON.stringify(config) !== JSON.stringify(this.readConfigFromWidget())) {
searchModel.dispose();
return; return;
} }
const controller = ReferencesController.get(this.searchResultEditor); const controller = ReferencesController.get(this.searchResultEditor);
controller.closeWidget(false); controller.closeWidget(false);
const labelFormatter = (uri: URI): string => this.labelService.getUriLabel(uri, { relative: true }); const labelFormatter = (uri: URI): string => this.labelService.getUriLabel(uri, { relative: true });
const results = serializeSearchResultForEditor(searchModel.searchResult, config.includes, config.excludes, config.contextLines, labelFormatter, false); const results = serializeSearchResultForEditor(this.searchModel.searchResult, config.includes, config.excludes, config.contextLines, labelFormatter, false);
const { header, body } = await input.getModels(); const { header, body } = await input.getModels();
this.modelService.updateModel(body, results.text); this.modelService.updateModel(body, results.text);
header.setValue(serializeSearchConfiguration(config)); header.setValue(serializeSearchConfiguration(config));
input.setDirty(input.resource.scheme !== 'search-editor'); input.setDirty(input.resource.scheme !== 'search-editor');
input.setMatchRanges(results.matchRanges); input.setMatchRanges(results.matchRanges);
searchModel.dispose();
} }
layout(dimension: DOM.Dimension) { layout(dimension: DOM.Dimension) {
......
...@@ -198,6 +198,12 @@ export interface ISearchCompleteStats { ...@@ -198,6 +198,12 @@ export interface ISearchCompleteStats {
export interface ISearchComplete extends ISearchCompleteStats { export interface ISearchComplete extends ISearchCompleteStats {
results: IFileMatch[]; results: IFileMatch[];
exit?: SearchCompletionExitCode
}
export const enum SearchCompletionExitCode {
Normal,
NewSearchStarted
} }
export interface ITextSearchStats { export interface ITextSearchStats {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册