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

Fix #91121.

上级 50e742c4
......@@ -34,7 +34,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { TreeResourceNavigator, WorkbenchObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService';
import { INotificationService } from 'vs/platform/notification/common/notification';
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 { 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';
......@@ -1348,7 +1348,7 @@ export class SearchView extends ViewPane {
this.inputPatternIncludes.onSearchSubmit();
});
this.viewModel.cancelSearch();
this.viewModel.cancelSearch(true);
this.currentSearchQ = this.currentSearchQ
.then(() => this.doSearch(query, excludePatternText, includePatternText, triggeredOnType))
......@@ -1393,6 +1393,10 @@ export class SearchView extends ViewPane {
this.updateActions();
const hasResults = !this.viewModel.searchResult.isEmpty();
if (completed?.exit === SearchCompletionExitCode.NewSearchStarted) {
return;
}
if (completed && completed.limitHit) {
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."),
......
......@@ -154,7 +154,6 @@ export class SearchWidget extends Widget {
private readonly _onDidToggleContext = new Emitter<void>();
readonly onDidToggleContext: Event<void> = this._onDidToggleContext.event;
private temporarilySkipSearchOnChange = false;
private showContextCheckbox!: Checkbox;
private contextLinesInput!: InputBox;
......@@ -488,12 +487,10 @@ export class SearchWidget extends Widget {
this.setReplaceAllActionState(false);
if (this.searchConfiguration.searchOnType) {
if (!this.temporarilySkipSearchOnChange) {
this._onSearchCancel.fire({ focus: false });
if (this.searchInput.getRegex()) {
try {
const regex = new RegExp(this.searchInput.getValue(), 'ug');
const matchienessHeuristic = `
if (this.searchInput.getRegex()) {
try {
const regex = new RegExp(this.searchInput.getValue(), 'ug');
const matchienessHeuristic = `
~!@#$%^&*()_+
\`1234567890-=
qwertyuiop[]\\
......@@ -503,18 +500,17 @@ export class SearchWidget extends Widget {
zxcvbnm,./
ZXCVBNM<>? `.match(regex)?.length ?? 0;
const delayMultiplier =
matchienessHeuristic < 50 ? 1 :
matchienessHeuristic < 100 ? 5 : // expressions like `.` or `\w`
10; // only things matching empty string
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod * delayMultiplier);
} catch {
// pass
}
} else {
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod);
const delayMultiplier =
matchienessHeuristic < 50 ? 1 :
matchienessHeuristic < 100 ? 5 : // expressions like `.` or `\w`
10; // only things matching empty string
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod * delayMultiplier);
} catch {
// pass
}
} else {
this.submitSearch(true, this.searchConfiguration.searchOnTypeDebouncePeriod);
}
}
}
......
......@@ -20,7 +20,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
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 { overviewRulerFindMatchForeground, minimapFindMatch } from 'vs/platform/theme/common/colorRegistry';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
......@@ -968,6 +968,7 @@ export class SearchModel extends Disposable {
readonly onReplaceTermChanged: Event<void> = this._onReplaceTermChanged.event;
private currentCancelTokenSource: CancellationTokenSource | null = null;
private searchCancelledForNewSearch: boolean = false;
constructor(
@ISearchService private readonly searchService: ISearchService,
......@@ -1016,7 +1017,7 @@ export class SearchModel extends Disposable {
}
search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> {
this.cancelSearch();
this.cancelSearch(true);
this._searchQuery = query;
......@@ -1114,7 +1115,12 @@ export class SearchModel extends Disposable {
private onSearchError(e: any, duration: number): void {
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 {
return this.configurationService.getValue<ISearchConfigurationProperties>('search');
}
cancelSearch(): boolean {
cancelSearch(cancelledForNewSearch = false): boolean {
if (this.currentCancelTokenSource) {
this.searchCancelledForNewSearch = cancelledForNewSearch;
this.currentCancelTokenSource.cancel();
return true;
}
......
......@@ -77,6 +77,7 @@ export class SearchEditor extends BaseTextEditor {
private searchHistoryDelayer: Delayer<void>;
private messageDisposables: IDisposable[] = [];
private container: HTMLElement;
private searchModel: SearchModel;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
......@@ -107,6 +108,8 @@ export class SearchEditor extends BaseTextEditor {
this.inputFocusContextKey = InputBoxFocusedKey.bindTo(scopedContextKeyService);
this.searchOperation = this._register(new LongRunningOperation(progressService));
this.searchHistoryDelayer = new Delayer<void>(2000);
this.searchModel = this._register(this.instantiationService.createInstance(SearchModel));
}
createEditor(parent: HTMLElement) {
......@@ -326,6 +329,8 @@ export class SearchEditor extends BaseTextEditor {
}
private async doRunSearch() {
this.searchModel.cancelSearch(true);
const startInput = this.getInput();
this.searchHistoryDelayer.trigger(() => {
......@@ -372,30 +377,26 @@ export class SearchEditor extends BaseTextEditor {
catch (err) {
return;
}
const searchModel = this.instantiationService.createInstance(SearchModel);
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();
if (!input ||
input !== startInput ||
JSON.stringify(config) !== JSON.stringify(this.readConfigFromWidget())) {
searchModel.dispose();
return;
}
const controller = ReferencesController.get(this.searchResultEditor);
controller.closeWidget(false);
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();
this.modelService.updateModel(body, results.text);
header.setValue(serializeSearchConfiguration(config));
input.setDirty(input.resource.scheme !== 'search-editor');
input.setMatchRanges(results.matchRanges);
searchModel.dispose();
}
layout(dimension: DOM.Dimension) {
......
......@@ -198,6 +198,12 @@ export interface ISearchCompleteStats {
export interface ISearchComplete extends ISearchCompleteStats {
results: IFileMatch[];
exit?: SearchCompletionExitCode
}
export const enum SearchCompletionExitCode {
Normal,
NewSearchStarted
}
export interface ITextSearchStats {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册