mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 01:00:29 -04:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
@@ -12,7 +12,7 @@ import { ITreeContextMenuEvent, ITreeElement } from 'vs/base/browser/ui/tree/tre
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Iterator } from 'vs/base/common/iterator';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -23,7 +23,7 @@ import 'vs/css!./media/searchview';
|
||||
import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import * as nls from 'vs/nls';
|
||||
import { fillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -33,8 +33,8 @@ import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/file
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TreeResourceNavigator2, WorkbenchObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, SearchErrorCode, VIEW_ID } from 'vs/workbench/services/search/common/search';
|
||||
import { IProgressService, IProgressStep, IProgress } from 'vs/platform/progress/common/progress';
|
||||
import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, SearchErrorCode, VIEW_ID, VIEWLET_ID } 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 } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
@@ -59,11 +59,17 @@ import { relativePath } from 'vs/base/common/resources';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { Memento } from 'vs/workbench/common/memento';
|
||||
import { Memento, MementoObject } from 'vs/workbench/common/memento';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
enum SearchUIState {
|
||||
Idle,
|
||||
Searching,
|
||||
SlowSearch
|
||||
}
|
||||
|
||||
export class SearchView extends ViewletPanel {
|
||||
|
||||
private static readonly MAX_TEXT_RESULTS = 10000;
|
||||
@@ -92,8 +98,7 @@ export class SearchView extends ViewletPanel {
|
||||
private matchFocused: IContextKey<boolean>;
|
||||
private hasSearchResultsKey: IContextKey<boolean>;
|
||||
|
||||
private searchSubmitted: boolean;
|
||||
private searching: boolean;
|
||||
private state: SearchUIState;
|
||||
|
||||
private actions: Array<CollapseDeepestExpandedLevelAction | ClearSearchResultsAction> = [];
|
||||
private cancelAction: CancelSearchAction;
|
||||
@@ -102,8 +107,8 @@ export class SearchView extends ViewletPanel {
|
||||
|
||||
private tree: WorkbenchObjectTree<RenderableMatch>;
|
||||
private treeLabels: ResourceLabels;
|
||||
private viewletState: object;
|
||||
private globalMemento: object;
|
||||
private viewletState: MementoObject;
|
||||
private globalMemento: MementoObject;
|
||||
private messagesElement: HTMLElement;
|
||||
private messageDisposables: IDisposable[] = [];
|
||||
private searchWidgetsContainerElement: HTMLElement;
|
||||
@@ -117,7 +122,6 @@ export class SearchView extends ViewletPanel {
|
||||
|
||||
private currentSelectedFileMatch: FileMatch | undefined;
|
||||
|
||||
private readonly selectCurrentMatchEmitter: Emitter<string | undefined>;
|
||||
private delayedRefresh: Delayer<void>;
|
||||
private changedWhileHidden: boolean;
|
||||
|
||||
@@ -165,6 +169,7 @@ export class SearchView extends ViewletPanel {
|
||||
this.matchFocused = Constants.MatchFocusKey.bindTo(this.contextKeyService);
|
||||
this.hasSearchResultsKey = Constants.HasSearchResults.bindTo(this.contextKeyService);
|
||||
|
||||
this.viewModel = this._register(this.searchWorkbenchService.searchModel);
|
||||
this.queryBuilder = this.instantiationService.createInstance(QueryBuilder);
|
||||
this.memento = new Memento(this.id, storageService);
|
||||
this.viewletState = this.memento.getMemento(StorageScope.WORKSPACE);
|
||||
@@ -175,10 +180,6 @@ export class SearchView extends ViewletPanel {
|
||||
this._register(this.contextService.onDidChangeWorkbenchState(() => this.onDidChangeWorkbenchState()));
|
||||
this._register(this.searchHistoryService.onDidClearHistory(() => this.clearHistory()));
|
||||
|
||||
this.selectCurrentMatchEmitter = this._register(new Emitter<string>());
|
||||
this._register(Event.debounce(this.selectCurrentMatchEmitter.event, (l, e) => e, 100, /*leading=*/true)
|
||||
(() => this.selectCurrentMatch()));
|
||||
|
||||
this.delayedRefresh = this._register(new Delayer<void>(250));
|
||||
|
||||
this.actions = [
|
||||
@@ -204,7 +205,6 @@ export class SearchView extends ViewletPanel {
|
||||
}
|
||||
|
||||
renderBody(parent: HTMLElement): void {
|
||||
this.viewModel = this._register(this.searchWorkbenchService.searchModel);
|
||||
this.container = dom.append(parent, dom.$('.search-view'));
|
||||
|
||||
this.searchWidgetsContainerElement = dom.append(this.container, $('.search-widgets-container'));
|
||||
@@ -320,14 +320,6 @@ export class SearchView extends ViewletPanel {
|
||||
if (this.viewModel) {
|
||||
this.viewModel.searchResult.toggleHighlights(visible);
|
||||
}
|
||||
|
||||
// Open focused element from results in case the editor area is otherwise empty
|
||||
if (visible && !this.editorService.activeEditor) {
|
||||
const focus = this.tree.getFocus();
|
||||
if (focus) {
|
||||
this.onFocus(focus, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get searchAndReplaceWidget(): SearchWidget {
|
||||
@@ -348,9 +340,11 @@ export class SearchView extends ViewletPanel {
|
||||
protected updateActions(): void {
|
||||
for (const action of this.actions) {
|
||||
action.update();
|
||||
this.refreshAction.update();
|
||||
this.cancelAction.update();
|
||||
}
|
||||
|
||||
this.refreshAction.update();
|
||||
this.cancelAction.update();
|
||||
|
||||
super.updateActions();
|
||||
}
|
||||
|
||||
@@ -517,13 +511,19 @@ export class SearchView extends ViewletPanel {
|
||||
return;
|
||||
}
|
||||
|
||||
const progressRunner = this.progressService.show(100);
|
||||
|
||||
const occurrences = this.viewModel.searchResult.count();
|
||||
const fileCount = this.viewModel.searchResult.fileCount();
|
||||
const replaceValue = this.searchWidget.getReplaceValue() || '';
|
||||
const afterReplaceAllMessage = this.buildAfterReplaceAllMessage(occurrences, fileCount, replaceValue);
|
||||
|
||||
let progressComplete: () => void;
|
||||
let progressReporter: IProgress<IProgressStep>;
|
||||
this.progressService.withProgress({ location: VIEWLET_ID, delay: 100, total: occurrences }, p => {
|
||||
progressReporter = p;
|
||||
|
||||
return new Promise(resolve => progressComplete = resolve);
|
||||
});
|
||||
|
||||
const confirmation: IConfirmation = {
|
||||
title: nls.localize('replaceAll.confirmation.title', "Replace All"),
|
||||
message: this.buildReplaceAllConfirmationMessage(occurrences, fileCount, replaceValue),
|
||||
@@ -534,12 +534,12 @@ export class SearchView extends ViewletPanel {
|
||||
this.dialogService.confirm(confirmation).then(res => {
|
||||
if (res.confirmed) {
|
||||
this.searchWidget.setReplaceAllActionState(false);
|
||||
this.viewModel.searchResult.replaceAll(progressRunner).then(() => {
|
||||
progressRunner.done();
|
||||
this.viewModel.searchResult.replaceAll(progressReporter).then(() => {
|
||||
progressComplete();
|
||||
const messageEl = this.clearMessage();
|
||||
dom.append(messageEl, $('p', undefined, afterReplaceAllMessage));
|
||||
}, (error) => {
|
||||
progressRunner.done();
|
||||
progressComplete();
|
||||
errors.isPromiseCanceledError(error);
|
||||
this.notificationService.error(error);
|
||||
});
|
||||
@@ -693,23 +693,17 @@ export class SearchView extends ViewletPanel {
|
||||
e.browserEvent.preventDefault();
|
||||
e.browserEvent.stopPropagation();
|
||||
|
||||
const actions: IAction[] = [];
|
||||
const actionsDisposable = createAndFillInContextMenuActions(this.contextMenu, { shouldForwardArgs: true }, actions, this.contextMenuService);
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => {
|
||||
const actions: IAction[] = [];
|
||||
fillInContextMenuActions(this.contextMenu, { shouldForwardArgs: true }, actions, this.contextMenuService);
|
||||
return actions;
|
||||
},
|
||||
getActionsContext: () => e.element
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => e.element,
|
||||
onHide: () => dispose(actionsDisposable)
|
||||
});
|
||||
}
|
||||
|
||||
selectCurrentMatch(): void {
|
||||
const focused = this.tree.getFocus()[0];
|
||||
const fakeKeyboardEvent = getSelectionKeyboardEvent(undefined, false);
|
||||
this.tree.setSelection([focused], fakeKeyboardEvent);
|
||||
}
|
||||
|
||||
selectNextMatch(): void {
|
||||
const [selected] = this.tree.getSelection();
|
||||
|
||||
@@ -743,7 +737,6 @@ export class SearchView extends ViewletPanel {
|
||||
if (next) {
|
||||
this.tree.setFocus([next], getSelectionKeyboardEvent(undefined, false));
|
||||
this.tree.reveal(next);
|
||||
this.selectCurrentMatchEmitter.fire(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +776,6 @@ export class SearchView extends ViewletPanel {
|
||||
if (prev) {
|
||||
this.tree.setFocus([prev], getSelectionKeyboardEvent(undefined, false));
|
||||
this.tree.reveal(prev);
|
||||
this.selectCurrentMatchEmitter.fire(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -922,12 +914,8 @@ export class SearchView extends ViewletPanel {
|
||||
return this.tree;
|
||||
}
|
||||
|
||||
isSearchSubmitted(): boolean {
|
||||
return this.searchSubmitted;
|
||||
}
|
||||
|
||||
isSearching(): boolean {
|
||||
return this.searching;
|
||||
isSlowSearch(): boolean {
|
||||
return this.state === SearchUIState.SlowSearch;
|
||||
}
|
||||
|
||||
allSearchFieldsClear(): boolean {
|
||||
@@ -1193,7 +1181,7 @@ export class SearchView extends ViewletPanel {
|
||||
|
||||
const options: ITextQueryBuilderOptions = {
|
||||
_reason: 'searchView',
|
||||
extraFileResources: getOutOfWorkspaceEditorResources(this.editorService, this.contextService),
|
||||
extraFileResources: this.instantiationService.invokeFunction(getOutOfWorkspaceEditorResources),
|
||||
maxResults: SearchView.MAX_TEXT_RESULTS,
|
||||
disregardIgnoreFiles: !useExcludesAndIgnoreFiles || undefined,
|
||||
disregardExcludeSettings: !useExcludesAndIgnoreFiles || undefined,
|
||||
@@ -1265,22 +1253,26 @@ export class SearchView extends ViewletPanel {
|
||||
}
|
||||
|
||||
private doSearch(query: ITextQuery, options: ITextQueryBuilderOptions, excludePatternText: string, includePatternText: string): Thenable<void> {
|
||||
const progressRunner = this.progressService.show(/*infinite=*/true);
|
||||
let progressComplete: () => void;
|
||||
this.progressService.withProgress({ location: VIEWLET_ID }, _progress => {
|
||||
return new Promise(resolve => progressComplete = resolve);
|
||||
});
|
||||
|
||||
this.searchWidget.searchInput.clearMessage();
|
||||
this.searching = true;
|
||||
setTimeout(() => {
|
||||
if (this.searching) {
|
||||
this.updateActions();
|
||||
}
|
||||
}, 2000);
|
||||
this.state = SearchUIState.Searching;
|
||||
this.showEmptyStage();
|
||||
|
||||
const slowTimer = setTimeout(() => {
|
||||
this.state = SearchUIState.SlowSearch;
|
||||
this.updateActions();
|
||||
}, 2000);
|
||||
|
||||
const onComplete = (completed?: ISearchComplete) => {
|
||||
this.searching = false;
|
||||
clearTimeout(slowTimer);
|
||||
this.state = SearchUIState.Idle;
|
||||
|
||||
// Complete up to 100% as needed
|
||||
progressRunner.done();
|
||||
progressComplete();
|
||||
|
||||
// Do final render, then expand if just 1 file with less than 50 matches
|
||||
this.onSearchResultsChanged();
|
||||
@@ -1295,7 +1287,6 @@ export class SearchView extends ViewletPanel {
|
||||
|
||||
this.viewModel.replaceString = this.searchWidget.getReplaceValue();
|
||||
|
||||
this.searchSubmitted = true;
|
||||
this.updateActions();
|
||||
const hasResults = !this.viewModel.searchResult.isEmpty();
|
||||
|
||||
@@ -1370,12 +1361,13 @@ export class SearchView extends ViewletPanel {
|
||||
};
|
||||
|
||||
const onError = (e: any) => {
|
||||
clearTimeout(slowTimer);
|
||||
this.state = SearchUIState.Idle;
|
||||
if (errors.isPromiseCanceledError(e)) {
|
||||
return onComplete(undefined);
|
||||
} else {
|
||||
this.searching = false;
|
||||
this.updateActions();
|
||||
progressRunner.done();
|
||||
progressComplete();
|
||||
this.searchWidget.searchInput.showMessage({ content: e.message, type: MessageType.ERROR });
|
||||
this.viewModel.searchResult.clear();
|
||||
|
||||
@@ -1393,7 +1385,7 @@ export class SearchView extends ViewletPanel {
|
||||
|
||||
// Handle UI updates in an interval to show frequent progress and results
|
||||
const uiRefreshHandle: any = setInterval(() => {
|
||||
if (!this.searching) {
|
||||
if (this.state === SearchUIState.Idle) {
|
||||
window.clearInterval(uiRefreshHandle);
|
||||
return;
|
||||
}
|
||||
@@ -1507,7 +1499,7 @@ export class SearchView extends ViewletPanel {
|
||||
this.searchWithoutFolderMessageElement = this.clearMessage();
|
||||
|
||||
const textEl = dom.append(this.searchWithoutFolderMessageElement,
|
||||
$('p', undefined, nls.localize('searchWithoutFolder', "You have not yet opened a folder. Only open files are currently searched - ")));
|
||||
$('p', undefined, nls.localize('searchWithoutFolder', "You have not opened or specified a folder. Only open files are currently searched - ")));
|
||||
|
||||
const openFolderLink = dom.append(textEl,
|
||||
$('a.pointer.prominent', { tabindex: 0 }, nls.localize('openFolder', "Open Folder")));
|
||||
@@ -1527,9 +1519,7 @@ export class SearchView extends ViewletPanel {
|
||||
}
|
||||
|
||||
private showEmptyStage(): void {
|
||||
|
||||
// disable 'result'-actions
|
||||
this.searchSubmitted = false;
|
||||
this.updateActions();
|
||||
|
||||
// clean up ui
|
||||
@@ -1539,12 +1529,7 @@ export class SearchView extends ViewletPanel {
|
||||
this.currentSelectedFileMatch = undefined;
|
||||
}
|
||||
|
||||
private onFocus(lineMatch: any, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<any> {
|
||||
if (!(lineMatch instanceof Match)) {
|
||||
this.viewModel.searchResult.rangeHighlightDecorations.removeHighlightRange();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
private onFocus(lineMatch: Match, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): Promise<any> {
|
||||
const useReplacePreview = this.configurationService.getValue<ISearchConfiguration>().search.useReplacePreview;
|
||||
return (useReplacePreview && this.viewModel.isReplaceActive() && !!this.viewModel.replaceString) ?
|
||||
this.replaceService.openReplacePreview(lineMatch, preserveFocus, sideBySide, pinned) :
|
||||
@@ -1634,7 +1619,7 @@ export class SearchView extends ViewletPanel {
|
||||
|
||||
getActions(): IAction[] {
|
||||
return [
|
||||
this.searching ?
|
||||
this.state === SearchUIState.SlowSearch ?
|
||||
this.cancelAction :
|
||||
this.refreshAction,
|
||||
...this.actions
|
||||
@@ -1695,21 +1680,9 @@ export class SearchView extends ViewletPanel {
|
||||
super.saveState();
|
||||
}
|
||||
|
||||
private _toDispose: IDisposable[] = [];
|
||||
protected _register<T extends IDisposable>(t: T): T {
|
||||
if (this.isDisposed) {
|
||||
console.warn('Registering disposable on object that has already been disposed.');
|
||||
t.dispose();
|
||||
} else {
|
||||
this._toDispose.push(t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.isDisposed = true;
|
||||
this.saveState();
|
||||
this._toDispose = dispose(this._toDispose);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user