diff --git a/src/sql/workbench/common/customInputConverter.ts b/src/sql/workbench/common/customInputConverter.ts index 17bb8bd7d4..1ecfd5cd25 100644 --- a/src/sql/workbench/common/customInputConverter.ts +++ b/src/sql/workbench/common/customInputConverter.ts @@ -43,9 +43,7 @@ export function convertEditorInput(input: EditorInput, options: IQueryEditorOpti //QueryInput uri = getQueryEditorFileUri(input); if (uri) { - const queryResultsInput: QueryResultsInput = instantiationService.createInstance(QueryResultsInput, uri.toString()); - let queryInput: QueryInput = instantiationService.createInstance(QueryInput, '', input, queryResultsInput, undefined); - return queryInput; + return instantiationService.createInstance(QueryInput, '', input, undefined); } //QueryPlanInput diff --git a/src/sql/workbench/parts/commandLine/test/electron-browser/commandLine.test.ts b/src/sql/workbench/parts/commandLine/test/electron-browser/commandLine.test.ts index f185ab26c0..96351f2666 100644 --- a/src/sql/workbench/parts/commandLine/test/electron-browser/commandLine.test.ts +++ b/src/sql/workbench/parts/commandLine/test/electron-browser/commandLine.test.ts @@ -26,6 +26,9 @@ import { QueryInput, QueryEditorState } from 'sql/workbench/parts/query/common/q import { URI } from 'vs/base/common/uri'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { TestEditorInput } from 'vs/workbench/services/editor/test/browser/editorGroupsService.test'; +import { Schemas } from 'vs/base/common/network'; class TestParsedArgs implements ParsedArgs { [arg: string]: any; @@ -372,7 +375,9 @@ suite('commandLineService tests', () => { }).verifiable(TypeMoq.Times.once()); connectionManagementService.setup(c => c.getConnectionProfileById(TypeMoq.It.isAnyString())).returns(() => originalProfile); const configurationService = getConfigurationServiceMock(true); - const queryInput: TypeMoq.Mock = TypeMoq.Mock.ofType(QueryInput); + const instantiationService = new TestInstantiationService(); + const fileInput = new TestEditorInput(URI.from({ scheme: Schemas.untitled })); + const queryInput: TypeMoq.Mock = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Loose, undefined, fileInput, undefined, undefined, undefined, instantiationService); let uri = URI.file(args._[0]); const queryState = new QueryEditorState(); queryState.connected = true; diff --git a/src/sql/workbench/parts/query/browser/keyboardQueryActions.ts b/src/sql/workbench/parts/query/browser/keyboardQueryActions.ts index e3121afb8e..de3bbc8977 100644 --- a/src/sql/workbench/parts/query/browser/keyboardQueryActions.ts +++ b/src/sql/workbench/parts/query/browser/keyboardQueryActions.ts @@ -13,7 +13,6 @@ import * as azdata from 'azdata'; import { IQueryManagementService } from 'sql/platform/query/common/queryManagement'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor'; -import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils'; import * as Constants from 'sql/workbench/parts/query/common/constants'; import * as ConnectionConstants from 'sql/platform/connection/common/constants'; @@ -239,7 +238,6 @@ export class RunQueryShortcutAction extends Action { constructor( @IEditorService private readonly editorService: IEditorService, - @IQueryModelService protected readonly queryModelService: IQueryModelService, @IQueryManagementService private readonly queryManagementService: IQueryManagementService, @IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService, @IConfigurationService private readonly configurationService: IConfigurationService diff --git a/src/sql/workbench/parts/query/browser/queryActions.ts b/src/sql/workbench/parts/query/browser/queryActions.ts index 55b91b8164..e6260024d9 100644 --- a/src/sql/workbench/parts/query/browser/queryActions.ts +++ b/src/sql/workbench/parts/query/browser/queryActions.ts @@ -24,7 +24,6 @@ import { RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement'; import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor'; -import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox'; import { attachEditableDropdownStyler, attachSelectBoxStyler } from 'sql/platform/theme/common/styler'; import { Dropdown } from 'sql/base/parts/editableDropdown/browser/dropdown'; @@ -107,9 +106,7 @@ export class RunQueryAction extends QueryTaskbarAction { constructor( editor: QueryEditor, - @IQueryModelService protected readonly queryModelService: IQueryModelService, - @IConnectionManagementService connectionManagementService: IConnectionManagementService, - @IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService + @IConnectionManagementService connectionManagementService: IConnectionManagementService ) { super(connectionManagementService, editor, RunQueryAction.ID, RunQueryAction.EnabledClass); this.label = nls.localize('runQueryLabel', "Run"); @@ -178,8 +175,7 @@ export class CancelQueryAction extends QueryTaskbarAction { constructor( editor: QueryEditor, - @IQueryModelService private readonly queryModelService: IQueryModelService, - @IConnectionManagementService connectionManagementService: IConnectionManagementService + @IConnectionManagementService connectionManagementService: IConnectionManagementService, ) { super(connectionManagementService, editor, CancelQueryAction.ID, CancelQueryAction.EnabledClass); this.enabled = false; @@ -188,7 +184,7 @@ export class CancelQueryAction extends QueryTaskbarAction { public run(): Promise { if (this.isConnected(this.editor)) { - this.queryModelService.cancelQuery(this.editor.input.uri); + this.editor.input.runner.cancelQuery(); } return Promise.resolve(null); } diff --git a/src/sql/workbench/parts/query/browser/queryResultsView.ts b/src/sql/workbench/parts/query/browser/queryResultsView.ts index a2b7b2075f..e5c6ab9d4c 100644 --- a/src/sql/workbench/parts/query/browser/queryResultsView.ts +++ b/src/sql/workbench/parts/query/browser/queryResultsView.ts @@ -5,7 +5,6 @@ import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput'; import { TabbedPanel, IPanelTab, IPanelView } from 'sql/base/browser/ui/panel/panel'; -import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import QueryRunner from 'sql/platform/query/common/queryRunner'; import { MessagePanel } from 'sql/workbench/parts/query/browser/messagePanel'; import { GridPanel } from 'sql/workbench/parts/query/browser/gridPanel'; @@ -179,7 +178,6 @@ export class QueryResultsView extends Disposable { container: HTMLElement, @IThemeService themeService: IThemeService, @IInstantiationService private instantiationService: IInstantiationService, - @IQueryModelService private queryModelService: IQueryModelService ) { super(); this.resultsTab = this._register(new ResultsTab(instantiationService)); @@ -309,19 +307,7 @@ export class QueryResultsView extends Disposable { dynamicTab.captureState(this.input.state.dynamicModelViewTabsState); }); - let info = this.queryModelService._getQueryInfo(input.uri); - if (info) { - this.setQueryRunner(info.queryRunner); - } else { - let disposable = this.queryModelService.onRunQueryStart(c => { - if (c === input.uri) { - let info = this.queryModelService._getQueryInfo(input.uri); - this.setQueryRunner(info.queryRunner); - disposable.dispose(); - } - }); - this.runnerDisposables.push(disposable); - } + this.setQueryRunner(input.runner); } clearInput() { diff --git a/src/sql/workbench/parts/query/browser/statusBarItems.ts b/src/sql/workbench/parts/query/browser/statusBarItems.ts index 7e5ea34409..ca4dc27e41 100644 --- a/src/sql/workbench/parts/query/browser/statusBarItems.ts +++ b/src/sql/workbench/parts/query/browser/statusBarItems.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import { IntervalTimer } from 'vs/base/common/async'; import { IStatusbarService, StatusbarAlignment, IStatusbarEntryAccessor } from 'vs/platform/statusbar/common/statusbar'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; @@ -27,7 +26,6 @@ export class TimeElapsedStatusBarContributions extends Disposable implements IWo constructor( @IStatusbarService private readonly statusbarService: IStatusbarService, @IEditorService private readonly editorService: IEditorService, - @IQueryModelService private readonly queryModelService: IQueryModelService ) { super(); this.statusItem = this._register( @@ -57,30 +55,16 @@ export class TimeElapsedStatusBarContributions extends Disposable implements IWo this.hide(); const activeInput = this.editorService.activeEditor; if (activeInput && activeInput instanceof QueryInput && activeInput.uri) { - const uri = activeInput.uri; - const runner = this.queryModelService.getQueryRunner(uri); - if (runner) { - if (runner.hasCompleted || runner.isExecuting) { - this._displayValue(runner); - } - this.disposable.add(runner.onQueryStart(e => { - this._displayValue(runner); - })); - this.disposable.add(runner.onQueryEnd(e => { - this._displayValue(runner); - })); - } else { - this.disposable.add(this.queryModelService.onRunQueryStart(e => { - if (e === uri) { - this._displayValue(this.queryModelService.getQueryRunner(uri)); - } - })); - this.disposable.add(this.queryModelService.onRunQueryComplete(e => { - if (e === uri) { - this._displayValue(this.queryModelService.getQueryRunner(uri)); - } - })); + const runner = activeInput.runner; + if (runner.hasCompleted || runner.isExecuting) { + this._displayValue(runner); } + this.disposable.add(runner.onQueryStart(e => { + this._displayValue(runner); + })); + this.disposable.add(runner.onQueryEnd(e => { + this._displayValue(runner); + })); } } @@ -119,8 +103,7 @@ export class RowCountStatusBarContributions extends Disposable implements IWorkb constructor( @IStatusbarService private readonly statusbarService: IStatusbarService, - @IEditorService private readonly editorService: IEditorService, - @IQueryModelService private readonly queryModelService: IQueryModelService + @IEditorService private readonly editorService: IEditorService ) { super(); this.statusItem = this._register( @@ -150,29 +133,16 @@ export class RowCountStatusBarContributions extends Disposable implements IWorkb const activeInput = this.editorService.activeEditor; if (activeInput && activeInput instanceof QueryInput && activeInput.uri) { const uri = activeInput.uri; - const runner = this.queryModelService.getQueryRunner(uri); - if (runner) { - if (runner.hasCompleted || runner.isExecuting) { - this._displayValue(runner); - } - this.disposable.add(runner.onQueryStart(e => { - this._displayValue(runner); - })); - this.disposable.add(runner.onQueryEnd(e => { - this._displayValue(runner); - })); - } else { - this.disposable.add(this.queryModelService.onRunQueryStart(e => { - if (e === uri) { - this._displayValue(this.queryModelService.getQueryRunner(uri)); - } - })); - this.disposable.add(this.queryModelService.onRunQueryComplete(e => { - if (e === uri) { - this._displayValue(this.queryModelService.getQueryRunner(uri)); - } - })); + const runner = activeInput.runner; + if (runner.hasCompleted || runner.isExecuting) { + this._displayValue(runner); } + this.disposable.add(runner.onQueryStart(e => { + this._displayValue(runner); + })); + this.disposable.add(runner.onQueryEnd(e => { + this._displayValue(runner); + })); } } @@ -191,13 +161,11 @@ export class RowCountStatusBarContributions extends Disposable implements IWorkb export class QueryStatusStatusBarContributions extends Disposable implements IWorkbenchContribution { private static readonly ID = 'status.query.status'; - - private visisbleUri: string | undefined; + private runnerDisposables = new DisposableStore(); constructor( @IStatusbarService private readonly statusbarService: IStatusbarService, - @IEditorService private readonly editorService: IEditorService, - @IQueryModelService private readonly queryModelService: IQueryModelService + @IEditorService private readonly editorService: IEditorService ) { super(); this._register( @@ -209,22 +177,21 @@ export class QueryStatusStatusBarContributions extends Disposable implements IWo StatusbarAlignment.RIGHT, 100) ); - this._register(Event.filter(this.queryModelService.onRunQueryStart, uri => uri === this.visisbleUri)(this.update, this)); - this._register(Event.filter(this.queryModelService.onRunQueryComplete, uri => uri === this.visisbleUri)(this.update, this)); this._register(this.editorService.onDidActiveEditorChange(this.update, this)); this.update(); } private update() { this.hide(); - this.visisbleUri = undefined; + this.runnerDisposables.clear(); const activeInput = this.editorService.activeEditor; if (activeInput && activeInput instanceof QueryInput && activeInput.uri) { - this.visisbleUri = activeInput.uri; - const runner = this.queryModelService.getQueryRunner(this.visisbleUri); + const runner = activeInput.runner; if (runner && runner.isExecuting) { this.show(); } + this.runnerDisposables.add(runner.onQueryStart(() => this.show())); + this.runnerDisposables.add(runner.onQueryEnd(() => this.hide())); } } diff --git a/src/sql/workbench/parts/query/common/queryInput.ts b/src/sql/workbench/parts/query/common/queryInput.ts index 8367ae17a8..ee0f8239b7 100644 --- a/src/sql/workbench/parts/query/common/queryInput.ts +++ b/src/sql/workbench/parts/query/common/queryInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; @@ -13,11 +13,13 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IConnectionManagementService, IConnectableInput, INewConnectionParams, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement'; import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput'; -import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import { ISelectionData, ExecutionPlanOptions } from 'azdata'; import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel'; import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; +import { IQueryManagementService } from 'sql/platform/query/common/queryManagement'; +import QueryRunner from 'sql/platform/query/common/queryRunner'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; const MAX_SIZE = 13; @@ -110,63 +112,56 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec private _updateSelection: Emitter; + private _runner: QueryRunner; + public get runner(): QueryRunner { + return this._runner; + } + + private _results: QueryResultsInput; + constructor( private _description: string, private _sql: UntitledEditorInput, - private _results: QueryResultsInput, private _connectionProviderName: string, - @IConnectionManagementService private _connectionManagementService: IConnectionManagementService, - @IQueryModelService private _queryModelService: IQueryModelService, - @IConfigurationService private _configurationService: IConfigurationService + @IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService, + @IConfigurationService private readonly configurationService: IConfigurationService, + @IInstantiationService instantiationService: IInstantiationService ) { super(); this._updateSelection = new Emitter(); + this._runner = this._register(instantiationService.createInstance(QueryRunner, this.uri)); + this._results = this._register(instantiationService.createInstance(QueryResultsInput, this.uri, this.runner)); + this._register(this._sql); - this._register(this._results); // re-emit sql editor events through this editor if it exists if (this._sql) { this._register(this._sql.onDidChangeDirty(() => this._onDidChangeDirty.fire())); } - // Attach to event callbacks - if (this._queryModelService) { - // Register callbacks for the Actions - this._register( - this._queryModelService.onRunQueryStart(uri => { - if (this.uri === uri) { - this.onRunQuery(); - } - }) - ); + // Register callbacks for the Actions + this.runner.onQueryStart(() => this.onRunQuery()); - this._register( - this._queryModelService.onRunQueryComplete(uri => { - if (this.uri === uri) { - this.onQueryComplete(); - } - }) - ); - } + this.runner.onQueryEnd(() => this.onQueryComplete()); - if (this._connectionManagementService) { - this._register(this._connectionManagementService.onDisconnect(result => { + if (this.connectionManagementService) { + this._register(this.connectionManagementService.onDisconnect(result => { if (result.connectionUri === this.uri) { this.onDisconnect(); } })); if (this.uri) { if (this._connectionProviderName) { - this._connectionManagementService.doChangeLanguageFlavor(this.uri, 'sql', this._connectionProviderName); + this.connectionManagementService.doChangeLanguageFlavor(this.uri, 'sql', this._connectionProviderName); } else { - this._connectionManagementService.ensureDefaultLanguageFlavor(this.uri); + this.connectionManagementService.ensureDefaultLanguageFlavor(this.uri); } } } - if (this._configurationService) { - this._register(this._configurationService.onDidChangeConfiguration(e => { + if (this.configurationService) { + this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectedKeys.includes('sql.showConnectionInfoInTitle')) { this._onDidChangeLabel.fire(); } @@ -219,8 +214,8 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec } public getName(longForm?: boolean): string { - if (this._configurationService.getValue('sql.showConnectionInfoInTitle')) { - let profile = this._connectionManagementService.getConnectionProfile(this.uri); + if (this.configurationService.getValue('sql.showConnectionInfoInTitle')) { + let profile = this.connectionManagementService.getConnectionProfile(this.uri); let title = ''; if (this._description && this._description !== '') { title = this._description + ' '; @@ -253,17 +248,17 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec // State update funtions public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void { - this._queryModelService.runQuery(this.uri, selection, this, executePlanOptions); + this.runner.runQuery(selection, executePlanOptions); this.state.executing = true; } public runQueryStatement(selection: ISelectionData): void { - this._queryModelService.runQueryStatement(this.uri, selection, this); + this.runner.runQueryStatement(selection); this.state.executing = true; } public runQueryString(text: string): void { - this._queryModelService.runQueryString(this.uri, text, this); + this.runner.runQuery(text); this.state.executing = true; } @@ -286,7 +281,7 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec this.state.connected = true; this.state.connecting = false; - let isRunningQuery = this._queryModelService.isRunningQuery(this.uri); + let isRunningQuery = this.runner.isExecuting; if (!isRunningQuery && params && params.runQueryOnCompletion) { let selection: ISelectionData = params ? params.querySelection : undefined; if (params.runQueryOnCompletion === RunQueryOnConnectionMode.executeCurrentQuery) { @@ -317,8 +312,7 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec } public close(): void { - this._queryModelService.disposeQuery(this.uri); - this._connectionManagementService.disconnectEditor(this, true); + this.connectionManagementService.disconnectEditor(this, true); this._sql.close(); this._results.close(); @@ -329,6 +323,6 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec * Get the color that should be displayed */ public get tabColor(): string { - return this._connectionManagementService.getTabColorForUri(this.uri); + return this.connectionManagementService.getTabColorForUri(this.uri); } } diff --git a/src/sql/workbench/parts/query/common/queryResultsInput.ts b/src/sql/workbench/parts/query/common/queryResultsInput.ts index 83d47ab43b..a35d2acd69 100644 --- a/src/sql/workbench/parts/query/common/queryResultsInput.ts +++ b/src/sql/workbench/parts/query/common/queryResultsInput.ts @@ -13,6 +13,7 @@ import { QueryPlanState } from 'sql/workbench/parts/queryPlan/common/queryPlanSt import { MessagePanelState } from 'sql/workbench/parts/query/common/messagePanelState'; import { GridPanelState } from 'sql/workbench/parts/query/common/gridPanelState'; import { QueryModelViewState } from 'sql/workbench/parts/query/common/modelViewTab/modelViewState'; +import QueryRunner from 'sql/platform/query/common/queryRunner'; export class ResultsViewState { public gridPanelState: GridPanelState = new GridPanelState(); @@ -62,7 +63,11 @@ export class QueryResultsInput extends EditorInput { return this._state; } - constructor(private _uri: string) { + public get runner(): QueryRunner { + return this._runner; + } + + constructor(private _uri: string, private _runner: QueryRunner) { super(); this._visible = false; this._hasBootstrapped = false; diff --git a/src/sql/workbench/parts/query/test/browser/queryActions.test.ts b/src/sql/workbench/parts/query/test/browser/queryActions.test.ts index da6213401e..b076fbbc15 100644 --- a/src/sql/workbench/parts/query/test/browser/queryActions.test.ts +++ b/src/sql/workbench/parts/query/test/browser/queryActions.test.ts @@ -21,7 +21,6 @@ import { } from 'sql/workbench/parts/query/browser/queryActions'; import { QueryInput } from 'sql/workbench/parts/query/common/queryInput'; import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor'; -import { QueryModelService } from 'sql/platform/query/common/queryModelService'; import { ConnectionManagementService } from 'sql/platform/connection/common/connectionManagementService'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; @@ -31,6 +30,11 @@ import { TestStorageService, TestFileService } from 'vs/workbench/test/workbench import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; +import { TestEditorInput } from 'vs/workbench/services/editor/test/browser/editorGroupsService.test'; +import { URI } from 'vs/base/common/uri'; +import { Schemas } from 'vs/base/common/network'; let none: void; @@ -44,7 +48,9 @@ suite('SQL QueryAction Tests', () => { setup(() => { // Setup a reusable mock QueryInput - testQueryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict); + const instantiationService = new TestInstantiationService(); + const fileInput = new TestEditorInput(URI.from({ scheme: Schemas.untitled })); + testQueryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict, undefined, fileInput, undefined, undefined, undefined, instantiationService); testQueryInput.setup(x => x.uri).returns(() => testUri); testQueryInput.setup(x => x.runQuery(undefined)).callback(() => { calledRunQueryOnInput = true; }); @@ -69,7 +75,7 @@ suite('SQL QueryAction Tests', () => { test('setClass sets child CSS class correctly', (done) => { // If I create a RunQueryAction - let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined, undefined, undefined); + let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined); // "class should automatically get set to include the base class and the RunQueryAction class let className = RunQueryAction.EnabledClass; @@ -93,7 +99,7 @@ suite('SQL QueryAction Tests', () => { editor.setup(x => x.input).returns(() => testQueryInput.object); // If I create a QueryTaskbarAction and I pass a non-connected editor to _getConnectedQueryEditorUri - let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined, connectionManagementService.object, undefined); + let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, connectionManagementService.object); let connected: boolean = queryAction.isConnected(editor.object); // I should get an unconnected state @@ -129,14 +135,8 @@ suite('SQL QueryAction Tests', () => { connectionManagementService.callBase = true; connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected); - // ... Mock QueryModelService - let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose); - queryModelService.setup(x => x.runQuery(TypeMoq.It.isAny(), undefined, TypeMoq.It.isAny(), TypeMoq.It.isAny())).callback(() => { - calledRunQuery = true; - }); - // If I call run on RunQueryAction when I am not connected - let queryAction: RunQueryAction = new RunQueryAction(editor.object, queryModelService.object, connectionManagementService.object, undefined); + let queryAction: RunQueryAction = new RunQueryAction(editor.object, connectionManagementService.object); isConnected = false; calledRunQueryOnInput = false; queryAction.run(); @@ -170,8 +170,9 @@ suite('SQL QueryAction Tests', () => { let countCalledRunQuery: number = 0; // ... Mock "isSelectionEmpty" in QueryEditor - let queryInput: TypeMoq.Mock = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict); - queryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict); + const instantiationService = new TestInstantiationService(); + const fileInput = new TestEditorInput(URI.from({ scheme: Schemas.untitled })); + let queryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Strict, undefined, fileInput, undefined, undefined, undefined, instantiationService); queryInput.setup(x => x.uri).returns(() => testUri); queryInput.setup(x => x.runQuery(undefined)).callback(() => { countCalledRunQuery++; @@ -191,11 +192,8 @@ suite('SQL QueryAction Tests', () => { connectionManagementService.callBase = true; connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => true); - // ... Mock QueryModelService - let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose); - // If I call run on RunQueryAction when I have a non empty selection - let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, queryModelService.object, connectionManagementService.object, undefined); + let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, connectionManagementService.object); isSelectionEmpty = false; queryAction.run(); @@ -234,7 +232,9 @@ suite('SQL QueryAction Tests', () => { .returns(() => Promise.resolve(none)); // ... Mock "getSelection" in QueryEditor - let queryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Loose); + const instantiationService = new TestInstantiationService(); + const fileInput = new TestEditorInput(URI.from({ scheme: Schemas.untitled })); + let queryInput = TypeMoq.Mock.ofType(QueryInput, TypeMoq.MockBehavior.Loose, undefined, fileInput, undefined, undefined, undefined, instantiationService); queryInput.setup(x => x.uri).returns(() => testUri); queryInput.setup(x => x.runQuery(TypeMoq.It.isAny())).callback((selection: ISelectionData) => { runQuerySelection = selection; @@ -266,7 +266,7 @@ suite('SQL QueryAction Tests', () => { /// End Setup Test /// ////// If I call run on RunQueryAction while disconnected and with an undefined selection - let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, undefined, connectionManagementService.object, undefined); + let queryAction: RunQueryAction = new RunQueryAction(queryEditor.object, connectionManagementService.object); isConnected = false; selectionToReturnInGetSelection = undefined; queryAction.run(); @@ -317,38 +317,6 @@ suite('SQL QueryAction Tests', () => { assert.equal(runQuerySelection.endColumn, selectionToReturnInGetSelection.endColumn, 'endColumn should match'); }); - test('CancelQueryAction calls cancelQuery() only if URI is connected', (done) => { - // ... Create assert variables - let isConnected: boolean = undefined; - let calledCancelQuery: boolean = false; - - // ... Mock "isConnected" in ConnectionManagementService - let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}); - connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnected); - - // ... Mock QueryModelService - let queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose); - queryModelService.setup(x => x.cancelQuery(TypeMoq.It.isAny())).callback(() => { - calledCancelQuery = true; - }); - - // If I call run on CancelQueryAction when I am not connected - let queryAction: CancelQueryAction = new CancelQueryAction(editor.object, queryModelService.object, connectionManagementService.object); - isConnected = false; - queryAction.run(); - - // cancelQuery should not be run - assert.equal(calledCancelQuery, false, 'run should not call cancelQuery'); - - // If I call run on CancelQueryAction when I am connected - isConnected = true; - queryAction.run(); - - // cancelQuery should be run - assert.equal(calledCancelQuery, true, 'run should call cancelQuery'); - done(); - }); - // We want to call disconnectEditor regardless of connection to be able to cancel in-progress connections test('DisconnectDatabaseAction calls disconnectEditor regardless of URI being connected', (done) => { // ... Create assert variables diff --git a/src/sql/workbench/parts/query/test/browser/queryEditor.test.ts b/src/sql/workbench/parts/query/test/browser/queryEditor.test.ts index 9fbe720fdc..31ee319f93 100644 --- a/src/sql/workbench/parts/query/test/browser/queryEditor.test.ts +++ b/src/sql/workbench/parts/query/test/browser/queryEditor.test.ts @@ -10,7 +10,6 @@ import { Memento } from 'vs/workbench/common/memento'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput'; -import { QueryModelService } from 'sql/platform/query/common/queryModelService'; import { QueryInput } from 'sql/workbench/parts/query/common/queryInput'; import { INewConnectionParams, ConnectionType, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement'; import { ConnectionManagementService } from 'sql/platform/connection/common/connectionManagementService'; @@ -23,6 +22,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { TestStorageService } from 'vs/workbench/test/workbenchTestServices'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import QueryRunner from 'sql/platform/query/common/queryRunner'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; suite('SQL QueryEditor Tests', () => { let instantiationService: TypeMoq.Mock; @@ -54,7 +55,7 @@ suite('SQL QueryEditor Tests', () => { return new Promise((resolve) => resolve(mockEditor)); }); instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((input) => { - return new Promise((resolve) => resolve(new RunQueryAction(undefined, undefined, undefined, undefined))); + return new Promise((resolve) => resolve(new RunQueryAction(undefined, undefined))); }); // Setup hook to capture calls to create the listDatabase action instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((classDef, editor, action) => { @@ -64,7 +65,7 @@ suite('SQL QueryEditor Tests', () => { } } // Default - return new RunQueryAction(undefined, undefined, undefined, undefined); + return new RunQueryAction(undefined, undefined); }); // Mock EditorDescriptorService to give us a mock editor description @@ -247,7 +248,6 @@ suite('SQL QueryEditor Tests', () => { suite('Action Tests', () => { let queryActionInstantiationService: TypeMoq.Mock; let queryConnectionService: TypeMoq.Mock; - let queryModelService: TypeMoq.Mock; let queryInput: QueryInput; setup(() => { @@ -262,6 +262,7 @@ suite('SQL QueryEditor Tests', () => { // Mock InstantiationService to give us the actions queryActionInstantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose); + instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(QueryRunner), TypeMoq.It.isAnyString())).returns(() => new QueryRunner('', undefined, undefined, undefined, undefined, undefined)); queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny())).returns((input) => { return new Promise((resolve) => resolve(mockEditor)); @@ -269,7 +270,7 @@ suite('SQL QueryEditor Tests', () => { queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((input) => { // Default - return new RunQueryAction(undefined, undefined, undefined, undefined); + return new RunQueryAction(undefined, undefined); }); // Setup hook to capture calls to create the listDatabase action @@ -280,27 +281,24 @@ suite('SQL QueryEditor Tests', () => { return item; } // Default - return new RunQueryAction(undefined, undefined, undefined, undefined); + return new RunQueryAction(undefined, undefined); }); + const mockInstantiationService = new TestInstantiationService(); + let fileInput = new UntitledEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService.object, undefined, undefined); - queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose, undefined, undefined); - queryModelService.callBase = true; - queryModelService.setup(x => x.disposeQuery(TypeMoq.It.isAny())).returns(() => void 0); queryInput = new QueryInput( '', fileInput, undefined, - undefined, connectionManagementService.object, - queryModelService.object, - undefined + undefined, + mockInstantiationService ); }); test('Taskbar buttons are set correctly upon standard load', () => { queryConnectionService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false); - queryModelService.setup(x => x.isRunningQuery(TypeMoq.It.isAny())).returns(() => false); // If I use the created QueryEditor with no changes since creation // Buttons should be set as if disconnected assert.equal(queryInput.state.connected, false, 'query state should be not connected'); @@ -311,16 +309,14 @@ suite('SQL QueryEditor Tests', () => { test('Taskbar buttons are set correctly upon connect', () => { let params: INewConnectionParams = { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none }; queryInput.onConnectSuccess(params); - queryModelService.setup(x => x.isRunningQuery(TypeMoq.It.isAny())).returns(() => false); assert.equal(queryInput.state.connected, true, 'query state should be not connected'); assert.equal(queryInput.state.executing, false, 'query state should be not executing'); assert.equal(queryInput.state.connecting, false, 'query state should be not connecting'); }); test('Test that we attempt to dispose query when the queryInput is disposed', () => { - let queryResultsInput = new QueryResultsInput('testUri'); + let queryResultsInput = new QueryResultsInput('testUri', undefined); queryInput['_results'] = queryResultsInput; queryInput.close(); - queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once()); }); }); }); diff --git a/src/sql/workbench/services/queryEditor/browser/queryEditorService.ts b/src/sql/workbench/services/queryEditor/browser/queryEditorService.ts index f803bfb96f..dcbfa92f5c 100644 --- a/src/sql/workbench/services/queryEditor/browser/queryEditorService.ts +++ b/src/sql/workbench/services/queryEditor/browser/queryEditorService.ts @@ -12,7 +12,6 @@ import { QueryPlanInput } from 'sql/workbench/parts/queryPlan/common/queryPlanIn import { sqlModeId, untitledFilePrefix, getSupportedInputResource } from 'sql/workbench/common/customInputConverter'; import * as TaskUtilities from 'sql/workbench/browser/taskUtilities'; -import { IMode } from 'vs/editor/common/modes'; import { ITextModel } from 'vs/editor/common/model'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; @@ -91,10 +90,9 @@ export class QueryEditorService implements IQueryEditorService { } } - const queryResultsInput: QueryResultsInput = this._instantiationService.createInstance(QueryResultsInput, docUri.toString()); - let queryInput: QueryInput = this._instantiationService.createInstance(QueryInput, objectName, fileInput, queryResultsInput, connectionProviderName); + let input = this._instantiationService.createInstance(QueryInput, objectName, fileInput, connectionProviderName); - this._editorService.openEditor(queryInput, { pinned: true }) + this._editorService.openEditor(input, { pinned: true }) .then((editor) => { let params = editor.input; resolve(params); @@ -288,8 +286,7 @@ export class QueryEditorService implements IQueryEditorService { let newEditorInput: IEditorInput = undefined; if (changingToSql) { - const queryResultsInput: QueryResultsInput = QueryEditorService.instantiationService.createInstance(QueryResultsInput, uri.toString()); - let queryInput: QueryInput = QueryEditorService.instantiationService.createInstance(QueryInput, '', input, queryResultsInput, undefined); + let queryInput: QueryInput = QueryEditorService.instantiationService.createInstance(QueryInput, '', input, undefined); newEditorInput = queryInput; } else { let uriCopy: URI = URI.from({ scheme: uri.scheme, authority: uri.authority, path: uri.path, query: uri.query, fragment: uri.fragment }); diff --git a/src/sql/workbench/test/common/taskUtilities.test.ts b/src/sql/workbench/test/common/taskUtilities.test.ts index 1c55b404e8..73984bc912 100644 --- a/src/sql/workbench/test/common/taskUtilities.test.ts +++ b/src/sql/workbench/test/common/taskUtilities.test.ts @@ -14,6 +14,7 @@ import { URI } from 'vs/base/common/uri'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { QueryInput } from 'sql/workbench/parts/query/common/queryInput'; import { TestEditorService } from 'vs/workbench/test/workbenchTestServices'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; suite('TaskUtilities', function () { test('getCurrentGlobalConnection returns the selected OE server if a server or one of its children is selected', () => { @@ -76,7 +77,8 @@ suite('TaskUtilities', function () { // Mock the workbench service to return the active tab connection let tabConnectionUri = 'file://test_uri'; let editorInput = new UntitledEditorInput(URI.parse(tabConnectionUri), false, undefined, undefined, undefined, undefined, undefined, undefined); - let queryInput = new QueryInput(undefined, editorInput, undefined, undefined, undefined, undefined, undefined); + const instantiationService = new TestInstantiationService(); + let queryInput = new QueryInput(undefined, editorInput, undefined, undefined, undefined, instantiationService); mockConnectionManagementService.setup(x => x.getConnectionProfile(tabConnectionUri)).returns(() => tabProfile); // If I call getCurrentGlobalConnection, it should return the expected profile from the active tab