Query Editor Refactor (#5528)

* query editor changes

* query editor changes

* finish converting query editor

* fix merge issue

* remove unused code

* fix tests

* fix tests

* remove editor context key class

* edit tests to test input state
This commit is contained in:
Anthony Dresser
2019-05-23 11:43:59 -07:00
committed by GitHub
parent cf8f8907ee
commit 5e8a52bcc0
18 changed files with 537 additions and 1183 deletions

View File

@@ -10,9 +10,9 @@ import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionT
import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor'; import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IQueryModelService, IQueryEvent } from 'sql/platform/query/common/queryModel'; import { IQueryModelService } from 'sql/platform/query/common/queryModel';
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
@extHostNamedCustomer(SqlMainContext.MainThreadQueryEditor) @extHostNamedCustomer(SqlMainContext.MainThreadQueryEditor)
export class MainThreadQueryEditor implements MainThreadQueryEditorShape { export class MainThreadQueryEditor implements MainThreadQueryEditorShape {
@@ -23,9 +23,9 @@ export class MainThreadQueryEditor implements MainThreadQueryEditorShape {
constructor( constructor(
extHostContext: IExtHostContext, extHostContext: IExtHostContext,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@IQueryManagementService private _queryManagementService: IQueryManagementService,
@IQueryModelService private _queryModelService: IQueryModelService, @IQueryModelService private _queryModelService: IQueryModelService,
@IEditorService private _editorService: IEditorService @IEditorService private _editorService: IEditorService,
@IQueryManagementService private _queryManagementService: IQueryManagementService
) { ) {
if (extHostContext) { if (extHostContext) {
this._proxy = extHostContext.getProxy(SqlExtHostContext.ExtHostQueryEditor); this._proxy = extHostContext.getProxy(SqlExtHostContext.ExtHostQueryEditor);

View File

@@ -5,7 +5,6 @@
import { IInsightOptions, IInsight } from './interfaces'; import { IInsightOptions, IInsight } from './interfaces';
import { Graph } from './graphInsight'; import { Graph } from './graphInsight';
import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService'; import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import { IInsightsConfig } from 'sql/workbench/parts/dashboard/widgets/insights/interfaces'; import { IInsightsConfig } from 'sql/workbench/parts/dashboard/widgets/insights/interfaces';
import { resolveCurrentDirectory, getRootPath } from 'sql/platform/node/pathUtilities'; import { resolveCurrentDirectory, getRootPath } from 'sql/platform/node/pathUtilities';
@@ -20,6 +19,7 @@ import { URI } from 'vs/base/common/uri';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput';
export interface IChartActionContext { export interface IChartActionContext {
options: IInsightOptions; options: IInsightOptions;
@@ -87,10 +87,9 @@ export class CreateInsightAction extends Action {
} }
private getActiveUriString(): string { private getActiveUriString(): string {
let editor = this.editorService.activeControl; let editor = this.editorService.activeEditor;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryInput) {
let queryEditor: QueryEditor = editor; return editor.uri;
return queryEditor.uri;
} }
return undefined; return undefined;
} }
@@ -203,10 +202,9 @@ export class SaveImageAction extends Action {
} }
private getActiveUriString(): string { private getActiveUriString(): string {
let editor = this.editorService.activeControl; let editor = this.editorService.activeEditor;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryInput) {
let queryEditor: QueryEditor = editor; return editor.uri;
return queryEditor.uri;
} }
return undefined; return undefined;
} }

View File

@@ -205,12 +205,8 @@ export class ChartDataAction extends Action {
} }
public run(context: IGridActionContext): Promise<boolean> { public run(context: IGridActionContext): Promise<boolean> {
let activeEditor = this.editorService.activeControl; const activeEditor = this.editorService.activeControl as QueryEditor;
if (activeEditor instanceof QueryEditor) { activeEditor.chart({ batchId: context.batchId, resultId: context.resultId });
activeEditor.resultsEditor.chart({ batchId: context.batchId, resultId: context.resultId }); return Promise.resolve(true);
return Promise.resolve(true);
} else {
return Promise.resolve(false);
}
} }
} }

View File

@@ -7,7 +7,7 @@ import { Dimension } from 'vs/base/browser/dom';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { import {
IHorizontalSashLayoutProvider, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider,
ISashEvent, Orientation, Sash ISashEvent, Orientation, Sash
} from 'vs/base/browser/ui/sash/sash'; } from 'vs/base/browser/ui/sash/sash';
// There is no need to import the sash CSS - 'vs/base/browser/ui/sash/sash' already includes it // There is no need to import the sash CSS - 'vs/base/browser/ui/sash/sash' already includes it
@@ -40,121 +40,6 @@ export interface IFlexibleSash {
onPositionChange: Event<number>; onPositionChange: Event<number>;
} }
/**
* A simple Vertical Sash that computes the position of the sash when it is moved between the given dimension.
* Triggers onPositionChange event when the position is changed. Implements IFlexibleSash to enable classes to be
* agnostic of the fact that this sash is vertical.
*/
export class VerticalFlexibleSash extends Disposable implements IVerticalSashLayoutProvider, IFlexibleSash {
private sash: Sash;
private ratio: number;
private startPosition: number;
private position: number;
private dimension: Dimension;
private top: number;
private _onPositionChange: Emitter<number> = new Emitter<number>();
public get onPositionChange(): Event<number> { return this._onPositionChange.event; }
constructor(container: HTMLElement, private minWidth: number) {
super();
this.ratio = 0.5;
this.top = 0;
this.sash = new Sash(container, this);
this._register(this.sash.onDidStart(() => this.onSashDragStart()));
this._register(this.sash.onDidChange((e: ISashEvent) => this.onSashDrag(e)));
this._register(this.sash.onDidEnd(() => this.onSashDragEnd()));
this._register(this.sash.onDidReset(() => this.onSashReset()));
}
public getSplitPoint(): number {
return this.getVerticalSashLeft();
}
public layout(): void {
this.sash.layout();
}
public show(): void {
this.sash.show();
}
public hide(): void {
this.sash.hide();
}
public getVerticalSashTop(): number {
return this.top;
}
public getVerticalSashLeft(): number {
return this.position;
}
public getVerticalSashHeight(): number {
return this.dimension.height;
}
public setDimenesion(dimension: Dimension) {
this.dimension = dimension;
this.compute(this.ratio);
}
public setEdge(edge: number) {
this.top = edge;
}
private onSashDragStart(): void {
this.startPosition = this.position;
}
private onSashDrag(e: ISashEvent): void {
this.compute((this.startPosition + (e.currentX - e.startX)) / this.dimension.width);
}
private compute(ratio: number) {
this.computeSashPosition(ratio);
this.ratio = this.position / this.dimension.width;
this._onPositionChange.fire(this.position);
}
private onSashDragEnd(): void {
this.sash.layout();
}
private onSashReset(): void {
this.ratio = 0.5;
this._onPositionChange.fire(this.position);
this.sash.layout();
}
private computeSashPosition(sashRatio: number = this.ratio) {
let contentWidth = this.dimension.width;
let sashPosition = Math.floor((sashRatio || 0.5) * contentWidth);
let midPoint = Math.floor(0.5 * contentWidth);
if (contentWidth > this.minWidth * 2) {
if (sashPosition < this.minWidth) {
sashPosition = this.minWidth;
}
if (sashPosition > contentWidth - this.minWidth) {
sashPosition = contentWidth - this.minWidth;
}
} else {
sashPosition = midPoint;
}
if (this.position !== sashPosition) {
this.position = sashPosition;
this.sash.layout();
}
}
}
/** /**
* A simple Horizontal Sash that computes the position of the sash when it is moved between the given dimension. * A simple Horizontal Sash that computes the position of the sash when it is moved between the given dimension.
* Triggers onPositionChange event when the position is changed. Implements IFlexibleSash to enable classes to be * Triggers onPositionChange event when the position is changed. Implements IFlexibleSash to enable classes to be
@@ -269,4 +154,4 @@ export class HorizontalFlexibleSash extends Disposable implements IHorizontalSas
this.sash.layout(); this.sash.layout();
} }
} }
} }

View File

@@ -20,14 +20,15 @@ import * as ConnectionConstants from 'sql/platform/connection/common/constants';
import { EditDataEditor } from 'sql/workbench/parts/editData/browser/editDataEditor'; import { EditDataEditor } from 'sql/workbench/parts/editData/browser/editDataEditor';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput';
const singleQuote = '\''; const singleQuote = '\'';
function isConnected(editor: QueryEditor, connectionManagementService: IConnectionManagementService): boolean { function isConnected(editor: QueryEditor, connectionManagementService: IConnectionManagementService): boolean {
if (!editor || !editor.currentQueryInput) { if (!editor || !editor.input) {
return false; return false;
} }
return connectionManagementService.isConnected(editor.currentQueryInput.uri); return connectionManagementService.isConnected(editor.input.uri);
} }
function runActionOnActiveQueryEditor(editorService: IEditorService, action: (QueryEditor) => void): void { function runActionOnActiveQueryEditor(editorService: IEditorService, action: (QueryEditor) => void): void {
@@ -71,10 +72,9 @@ export class FocusOnCurrentQueryKeyboardAction extends Action {
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this._editorService.activeControl;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryEditor) {
let queryEditor: QueryEditor = editor; editor.focus();
queryEditor.focus();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -98,10 +98,9 @@ export class RunQueryKeyboardAction extends Action {
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this._editorService.activeControl;
if (editor && (editor instanceof QueryEditor || editor instanceof EditDataEditor)) { if (editor instanceof QueryEditor || editor instanceof EditDataEditor) {
let queryEditor: QueryEditor | EditDataEditor = editor; editor.runQuery();
queryEditor.runQuery();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -124,10 +123,9 @@ export class RunCurrentQueryKeyboardAction extends Action {
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this._editorService.activeControl;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryEditor) {
let queryEditor: QueryEditor = editor; editor.runCurrentQuery();
queryEditor.runCurrentQuery();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -147,10 +145,9 @@ export class RunCurrentQueryWithActualPlanKeyboardAction extends Action {
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this._editorService.activeControl;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryEditor) {
let queryEditor: QueryEditor = editor; editor.runCurrentQueryWithActualPlan();
queryEditor.runCurrentQueryWithActualPlan();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -174,10 +171,9 @@ export class CancelQueryKeyboardAction extends Action {
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this._editorService.activeControl;
if (editor && (editor instanceof QueryEditor || editor instanceof EditDataEditor)) { if (editor instanceof QueryEditor || editor instanceof EditDataEditor) {
let queryEditor: QueryEditor | EditDataEditor = editor; editor.cancelQuery();
queryEditor.cancelQuery();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -193,17 +189,17 @@ export class RefreshIntellisenseKeyboardAction extends Action {
constructor( constructor(
id: string, id: string,
label: string, label: string,
@IEditorService private _editorService: IEditorService @IConnectionManagementService private connectionManagementService: IConnectionManagementService,
@IEditorService private editorService: IEditorService
) { ) {
super(id, label); super(id, label);
this.enabled = true; this.enabled = true;
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this.editorService.activeEditor;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryInput) {
let queryEditor: QueryEditor = editor; this.connectionManagementService.rebuildIntelliSenseCache(editor.uri);
queryEditor.rebuildIntelliSenseCache();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -227,10 +223,9 @@ export class ToggleQueryResultsKeyboardAction extends Action {
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this._editorService.activeControl;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryEditor) {
let queryEditor: QueryEditor = editor; editor.toggleResultsEditorVisibility();
queryEditor.toggleResultsEditorVisibility();
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -243,18 +238,18 @@ export class RunQueryShortcutAction extends Action {
public static ID = 'runQueryShortcutAction'; public static ID = 'runQueryShortcutAction';
constructor( constructor(
@IEditorService private _editorService: IEditorService, @IEditorService private readonly editorService: IEditorService,
@IQueryModelService protected _queryModelService: IQueryModelService, @IQueryModelService protected readonly queryModelService: IQueryModelService,
@IQueryManagementService private _queryManagementService: IQueryManagementService, @IQueryManagementService private readonly queryManagementService: IQueryManagementService,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService,
@IConfigurationService private _workspaceConfigurationService: IConfigurationService @IConfigurationService private readonly configurationService: IConfigurationService
) { ) {
super(RunQueryShortcutAction.ID); super(RunQueryShortcutAction.ID);
} }
public run(index: number): Promise<void> { public run(index: number): Promise<void> {
let promise: Thenable<void> = Promise.resolve(null); let promise: Thenable<void> = Promise.resolve(null);
runActionOnActiveQueryEditor(this._editorService, (editor) => { runActionOnActiveQueryEditor(this.editorService, (editor) => {
promise = this.runQueryShortcut(editor, index); promise = this.runQueryShortcut(editor, index);
}); });
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -273,7 +268,7 @@ export class RunQueryShortcutAction extends Action {
throw new Error(nls.localize('queryShortcutNoEditor', 'Editor parameter is required for a shortcut to be executed')); throw new Error(nls.localize('queryShortcutNoEditor', 'Editor parameter is required for a shortcut to be executed'));
} }
if (isConnected(editor, this._connectionManagementService)) { if (isConnected(editor, this.connectionManagementService)) {
let shortcutText = this.getShortcutText(shortcutIndex); let shortcutText = this.getShortcutText(shortcutIndex);
if (!shortcutText.trim()) { if (!shortcutText.trim()) {
// no point going further // no point going further
@@ -285,7 +280,7 @@ export class RunQueryShortcutAction extends Action {
let parameterText: string = editor.getSelectionText(); let parameterText: string = editor.getSelectionText();
return this.escapeStringParamIfNeeded(editor, shortcutText, parameterText).then((escapedParam) => { return this.escapeStringParamIfNeeded(editor, shortcutText, parameterText).then((escapedParam) => {
let queryString = `${shortcutText} ${escapedParam}`; let queryString = `${shortcutText} ${escapedParam}`;
editor.currentQueryInput.runQueryString(queryString); editor.input.runQueryString(queryString);
}).then(success => null, err => { }).then(success => null, err => {
// swallow errors for now // swallow errors for now
return null; return null;
@@ -297,7 +292,7 @@ export class RunQueryShortcutAction extends Action {
private getShortcutText(shortcutIndex: number) { private getShortcutText(shortcutIndex: number) {
let shortcutSetting = Constants.shortcutStart + shortcutIndex; let shortcutSetting = Constants.shortcutStart + shortcutIndex;
let querySettings = WorkbenchUtils.getSqlConfigSection(this._workspaceConfigurationService, Constants.querySection); let querySettings = WorkbenchUtils.getSqlConfigSection(this.configurationService, Constants.querySection);
let shortcutText = querySettings[shortcutSetting]; let shortcutText = querySettings[shortcutSetting];
return shortcutText; return shortcutText;
} }
@@ -307,7 +302,7 @@ export class RunQueryShortcutAction extends Action {
if (this.canQueryProcMetadata(editor)) { if (this.canQueryProcMetadata(editor)) {
let dbName = this.getDatabaseName(editor); let dbName = this.getDatabaseName(editor);
let query = `exec dbo.sp_sproc_columns @procedure_name = N'${escapeSqlString(shortcutText, singleQuote)}', @procedure_owner = null, @procedure_qualifier = N'${escapeSqlString(dbName, singleQuote)}'`; let query = `exec dbo.sp_sproc_columns @procedure_name = N'${escapeSqlString(shortcutText, singleQuote)}', @procedure_owner = null, @procedure_qualifier = N'${escapeSqlString(dbName, singleQuote)}'`;
return this._queryManagementService.runQueryAndReturn(editor.uri, query) return this.queryManagementService.runQueryAndReturn(editor.input.uri, query)
.then(result => { .then(result => {
switch (this.isProcWithSingleArgument(result)) { switch (this.isProcWithSingleArgument(result)) {
case 1: case 1:
@@ -377,12 +372,12 @@ export class RunQueryShortcutAction extends Action {
} }
private canQueryProcMetadata(editor: QueryEditor): boolean { private canQueryProcMetadata(editor: QueryEditor): boolean {
let info = this._connectionManagementService.getConnectionInfo(editor.uri); let info = this.connectionManagementService.getConnectionInfo(editor.input.uri);
return (info && info.providerId === ConnectionConstants.mssqlProviderName); return (info && info.providerId === ConnectionConstants.mssqlProviderName);
} }
private getDatabaseName(editor: QueryEditor): string { private getDatabaseName(editor: QueryEditor): string {
let info = this._connectionManagementService.getConnectionInfo(editor.uri); let info = this.connectionManagementService.getConnectionInfo(editor.input.uri);
return info.connectionProfile.databaseName; return info.connectionProfile.databaseName;
} }
} }
@@ -398,39 +393,38 @@ export class ParseSyntaxAction extends Action {
constructor( constructor(
id: string, id: string,
label: string, label: string,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService,
@IQueryManagementService private _queryManagementService: IQueryManagementService, @IQueryManagementService private readonly queryManagementService: IQueryManagementService,
@IEditorService private _editorService: IEditorService, @IEditorService private readonly editorService: IEditorService,
@INotificationService private _notificationService: INotificationService @INotificationService private readonly notificationService: INotificationService
) { ) {
super(id, label); super(id, label);
this.enabled = true; this.enabled = true;
} }
public run(): Promise<void> { public run(): Promise<void> {
let editor = this._editorService.activeControl; const editor = this.editorService.activeControl;
if (editor && editor instanceof QueryEditor) { if (editor instanceof QueryEditor) {
let queryEditor: QueryEditor = editor; if (!editor.isSelectionEmpty()) {
if (!queryEditor.isSelectionEmpty()) { if (this.isConnected(editor)) {
if (this.isConnected(queryEditor)) { let text = editor.getSelectionText();
let text = queryEditor.getSelectionText();
if (text === '') { if (text === '') {
text = queryEditor.getAllText(); text = editor.getAllText();
} }
this._queryManagementService.parseSyntax(queryEditor.connectedUri, text).then(result => { this.queryManagementService.parseSyntax(editor.input.uri, text).then(result => {
if (result && result.parseable) { if (result && result.parseable) {
this._notificationService.notify({ this.notificationService.notify({
severity: Severity.Info, severity: Severity.Info,
message: nls.localize('queryActions.parseSyntaxSuccess', 'Commands completed successfully') message: nls.localize('queryActions.parseSyntaxSuccess', 'Commands completed successfully')
}); });
} else if (result && result.errors.length > 0) { } else if (result && result.errors.length > 0) {
let errorMessage = nls.localize('queryActions.parseSyntaxFailure', 'Command failed: '); let errorMessage = nls.localize('queryActions.parseSyntaxFailure', 'Command failed: ');
this._notificationService.error(`${errorMessage}${result.errors[0]}`); this.notificationService.error(`${errorMessage}${result.errors[0]}`);
} }
}); });
} else { } else {
this._notificationService.notify({ this.notificationService.notify({
severity: Severity.Error, severity: Severity.Error,
message: nls.localize('queryActions.notConnected', 'Please connect to a server') message: nls.localize('queryActions.notConnected', 'Please connect to a server')
}); });
@@ -447,9 +441,9 @@ export class ParseSyntaxAction extends Action {
* Public for testing only. * Public for testing only.
*/ */
private isConnected(editor: QueryEditor): boolean { private isConnected(editor: QueryEditor): boolean {
if (!editor || !editor.currentQueryInput) { if (!editor || !editor.input) {
return false; return false;
} }
return this._connectionManagementService.isConnected(editor.currentQueryInput.uri); return this.connectionManagementService.isConnected(editor.input.uri);
} }
} }

View File

@@ -37,8 +37,8 @@ export abstract class QueryTaskbarAction extends Action {
private _classes: string[]; private _classes: string[];
constructor( constructor(
protected _connectionManagementService: IConnectionManagementService, protected readonly connectionManagementService: IConnectionManagementService,
protected editor: QueryEditor, protected readonly editor: QueryEditor,
id: string, id: string,
enabledClass: string enabledClass: string
) { ) {
@@ -75,10 +75,10 @@ export abstract class QueryTaskbarAction extends Action {
* Public for testing only. * Public for testing only.
*/ */
public isConnected(editor: QueryEditor): boolean { public isConnected(editor: QueryEditor): boolean {
if (!editor || !editor.currentQueryInput) { if (!editor || !editor.input) {
return false; return false;
} }
return this._connectionManagementService.isConnected(editor.currentQueryInput.uri); return this.connectionManagementService.isConnected(editor.input.uri);
} }
/** /**
@@ -87,12 +87,12 @@ export abstract class QueryTaskbarAction extends Action {
*/ */
protected connectEditor(editor: QueryEditor, runQueryOnCompletion?: RunQueryOnConnectionMode, selection?: ISelectionData): void { protected connectEditor(editor: QueryEditor, runQueryOnCompletion?: RunQueryOnConnectionMode, selection?: ISelectionData): void {
let params: INewConnectionParams = { let params: INewConnectionParams = {
input: editor.currentQueryInput, input: editor.input,
connectionType: ConnectionType.editor, connectionType: ConnectionType.editor,
runQueryOnCompletion: runQueryOnCompletion ? runQueryOnCompletion : RunQueryOnConnectionMode.none, runQueryOnCompletion: runQueryOnCompletion ? runQueryOnCompletion : RunQueryOnConnectionMode.none,
querySelection: selection querySelection: selection
}; };
this._connectionManagementService.showConnectionDialog(params); this.connectionManagementService.showConnectionDialog(params);
} }
} }
@@ -106,7 +106,7 @@ export class RunQueryAction extends QueryTaskbarAction {
constructor( constructor(
editor: QueryEditor, editor: QueryEditor,
@IQueryModelService protected _queryModelService: IQueryModelService, @IQueryModelService protected readonly queryModelService: IQueryModelService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService @IConnectionManagementService connectionManagementService: IConnectionManagementService
) { ) {
super(connectionManagementService, editor, RunQueryAction.ID, RunQueryAction.EnabledClass); super(connectionManagementService, editor, RunQueryAction.ID, RunQueryAction.EnabledClass);
@@ -151,11 +151,11 @@ export class RunQueryAction extends QueryTaskbarAction {
// otherwise, either run the statement or the script depending on parameter // otherwise, either run the statement or the script depending on parameter
let selection: ISelectionData = editor.getSelection(false); let selection: ISelectionData = editor.getSelection(false);
if (runCurrentStatement && selection && this.isCursorPosition(selection)) { if (runCurrentStatement && selection && this.isCursorPosition(selection)) {
editor.currentQueryInput.runQueryStatement(selection); editor.input.runQueryStatement(selection);
} else { } else {
// get the selection again this time with trimming // get the selection again this time with trimming
selection = editor.getSelection(); selection = editor.getSelection();
editor.currentQueryInput.runQuery(selection); editor.input.runQuery(selection);
} }
} }
} }
@@ -176,7 +176,7 @@ export class CancelQueryAction extends QueryTaskbarAction {
constructor( constructor(
editor: QueryEditor, editor: QueryEditor,
@IQueryModelService private _queryModelService: IQueryModelService, @IQueryModelService private readonly queryModelService: IQueryModelService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService @IConnectionManagementService connectionManagementService: IConnectionManagementService
) { ) {
super(connectionManagementService, editor, CancelQueryAction.ID, CancelQueryAction.EnabledClass); super(connectionManagementService, editor, CancelQueryAction.ID, CancelQueryAction.EnabledClass);
@@ -186,7 +186,7 @@ export class CancelQueryAction extends QueryTaskbarAction {
public run(): Promise<void> { public run(): Promise<void> {
if (this.isConnected(this.editor)) { if (this.isConnected(this.editor)) {
this._queryModelService.cancelQuery(this.editor.currentQueryInput.uri); this.queryModelService.cancelQuery(this.editor.input.uri);
} }
return Promise.resolve(null); return Promise.resolve(null);
} }
@@ -202,7 +202,6 @@ export class EstimatedQueryPlanAction extends QueryTaskbarAction {
constructor( constructor(
editor: QueryEditor, editor: QueryEditor,
@IQueryModelService private _queryModelService: IQueryModelService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService @IConnectionManagementService connectionManagementService: IConnectionManagementService
) { ) {
super(connectionManagementService, editor, EstimatedQueryPlanAction.ID, EstimatedQueryPlanAction.EnabledClass); super(connectionManagementService, editor, EstimatedQueryPlanAction.ID, EstimatedQueryPlanAction.EnabledClass);
@@ -229,7 +228,7 @@ export class EstimatedQueryPlanAction extends QueryTaskbarAction {
} }
if (this.isConnected(editor)) { if (this.isConnected(editor)) {
editor.currentQueryInput.runQuery(editor.getSelection(), { editor.input.runQuery(editor.getSelection(), {
displayEstimatedQueryPlan: true displayEstimatedQueryPlan: true
}); });
} }
@@ -242,7 +241,6 @@ export class ActualQueryPlanAction extends QueryTaskbarAction {
constructor( constructor(
editor: QueryEditor, editor: QueryEditor,
@IQueryModelService private _queryModelService: IQueryModelService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService @IConnectionManagementService connectionManagementService: IConnectionManagementService
) { ) {
super(connectionManagementService, editor, ActualQueryPlanAction.ID, ActualQueryPlanAction.EnabledClass); super(connectionManagementService, editor, ActualQueryPlanAction.ID, ActualQueryPlanAction.EnabledClass);
@@ -273,7 +271,7 @@ export class ActualQueryPlanAction extends QueryTaskbarAction {
if (!selection) { if (!selection) {
selection = editor.getAllSelection(); selection = editor.getAllSelection();
} }
editor.currentQueryInput.runQuery(selection, { editor.input.runQuery(selection, {
displayActualQueryPlan: true displayActualQueryPlan: true
}); });
} }
@@ -299,7 +297,7 @@ export class DisconnectDatabaseAction extends QueryTaskbarAction {
public run(): Promise<void> { public run(): Promise<void> {
// Call disconnectEditor regardless of the connection state and let the ConnectionManagementService // Call disconnectEditor regardless of the connection state and let the ConnectionManagementService
// determine if we need to disconnect, cancel an in-progress conneciton, or do nothing // determine if we need to disconnect, cancel an in-progress conneciton, or do nothing
this._connectionManagementService.disconnectEditor(this.editor.currentQueryInput); this.connectionManagementService.disconnectEditor(this.editor.input);
return Promise.resolve(null); return Promise.resolve(null);
} }
} }
@@ -350,22 +348,14 @@ export class ToggleConnectDatabaseAction extends QueryTaskbarAction {
public static DisconnectClass = 'disconnect'; public static DisconnectClass = 'disconnect';
public static ID = 'toggleConnectDatabaseAction'; public static ID = 'toggleConnectDatabaseAction';
private _connected: boolean; private _connectLabel = nls.localize('connectDatabaseLabel', 'Connect');
private _connectLabel: string; private _disconnectLabel = nls.localize('disconnectDatabaseLabel', 'Disconnect');
private _disconnectLabel: string;
constructor( constructor(
editor: QueryEditor, editor: QueryEditor,
isConnected: boolean, private _connected: boolean,
@IConnectionManagementService connectionManagementService: IConnectionManagementService @IConnectionManagementService connectionManagementService: IConnectionManagementService
) { ) {
let enabledClass: string; super(connectionManagementService, editor, ToggleConnectDatabaseAction.ID, undefined);
super(connectionManagementService, editor, ToggleConnectDatabaseAction.ID, enabledClass);
this._connectLabel = nls.localize('connectDatabaseLabel', 'Connect');
this._disconnectLabel = nls.localize('disconnectDatabaseLabel', 'Disconnect');
this.connected = isConnected;
} }
public get connected(): boolean { public get connected(): boolean {
@@ -393,7 +383,7 @@ export class ToggleConnectDatabaseAction extends QueryTaskbarAction {
if (this.connected) { if (this.connected) {
// Call disconnectEditor regardless of the connection state and let the ConnectionManagementService // Call disconnectEditor regardless of the connection state and let the ConnectionManagementService
// determine if we need to disconnect, cancel an in-progress connection, or do nothing // determine if we need to disconnect, cancel an in-progress connection, or do nothing
this._connectionManagementService.disconnectEditor(this.editor.currentQueryInput); this.connectionManagementService.disconnectEditor(this.editor.input);
} else { } else {
this.connectEditor(this.editor); this.connectEditor(this.editor);
} }
@@ -444,14 +434,14 @@ export class ListDatabasesActionItem implements IActionViewItem {
// CONSTRUCTOR ///////////////////////////////////////////////////////// // CONSTRUCTOR /////////////////////////////////////////////////////////
constructor( constructor(
private _editor: QueryEditor, private _editor: QueryEditor,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@INotificationService private _notificationService: INotificationService,
@IContextViewService contextViewProvider: IContextViewService, @IContextViewService contextViewProvider: IContextViewService,
@IConfigurationService private readonly _configurationService: IConfigurationService @IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService,
@INotificationService private readonly notificationService: INotificationService,
@IConfigurationService private readonly configurationService: IConfigurationService
) { ) {
this._toDispose = []; this._toDispose = [];
this._databaseListDropdown = $('.databaseListDropdown'); this._databaseListDropdown = $('.databaseListDropdown');
this._isInAccessibilityMode = this._configurationService.getValue('editor.accessibilitySupport') === 'on'; this._isInAccessibilityMode = this.configurationService.getValue('editor.accessibilitySupport') === 'on';
if (this._isInAccessibilityMode) { if (this._isInAccessibilityMode) {
this._databaseSelectBox = new SelectBox([this._selectDatabaseString], this._selectDatabaseString, contextViewProvider, undefined, { ariaLabel: this._selectDatabaseString }); this._databaseSelectBox = new SelectBox([this._selectDatabaseString], this._selectDatabaseString, contextViewProvider, undefined, { ariaLabel: this._selectDatabaseString });
@@ -467,12 +457,11 @@ export class ListDatabasesActionItem implements IActionViewItem {
actionLabel: nls.localize('listDatabases.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown') actionLabel: nls.localize('listDatabases.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
}); });
this._dropdown.onValueChange(s => this.databaseSelected(s)); this._dropdown.onValueChange(s => this.databaseSelected(s));
this._toDispose.push(this._dropdown.onFocus(() => { self.onDropdownFocus(); })); this._toDispose.push(this._dropdown.onFocus(() => this.onDropdownFocus()));
} }
// Register event handlers // Register event handlers
let self = this; this._toDispose.push(this.connectionManagementService.onConnectionChanged(params => this.onConnectionChanged(params)));
this._toDispose.push(this._connectionManagementService.onConnectionChanged(params => { self.onConnectionChanged(params); }));
} }
// PUBLIC METHODS ////////////////////////////////////////////////////// // PUBLIC METHODS //////////////////////////////////////////////////////
@@ -546,22 +535,22 @@ export class ListDatabasesActionItem implements IActionViewItem {
// PRIVATE HELPERS ///////////////////////////////////////////////////// // PRIVATE HELPERS /////////////////////////////////////////////////////
private databaseSelected(dbName: string): void { private databaseSelected(dbName: string): void {
let uri = this._editor.connectedUri; let uri = this._editor.input.uri;
if (!uri) { if (!uri) {
return; return;
} }
let profile = this._connectionManagementService.getConnectionProfile(uri); let profile = this.connectionManagementService.getConnectionProfile(uri);
if (!profile) { if (!profile) {
return; return;
} }
this._connectionManagementService.changeDatabase(this._editor.uri, dbName) this.connectionManagementService.changeDatabase(this._editor.input.uri, dbName)
.then( .then(
result => { result => {
if (!result) { if (!result) {
this.resetDatabaseName(); this.resetDatabaseName();
this._notificationService.notify({ this.notificationService.notify({
severity: Severity.Error, severity: Severity.Error,
message: nls.localize('changeDatabase.failed', "Failed to change database") message: nls.localize('changeDatabase.failed', "Failed to change database")
}); });
@@ -569,7 +558,7 @@ export class ListDatabasesActionItem implements IActionViewItem {
}, },
error => { error => {
this.resetDatabaseName(); this.resetDatabaseName();
this._notificationService.notify({ this.notificationService.notify({
severity: Severity.Error, severity: Severity.Error,
message: nls.localize('changeDatabase.failedWithError', "Failed to change database {0}", error) message: nls.localize('changeDatabase.failedWithError', "Failed to change database {0}", error)
}); });
@@ -577,9 +566,9 @@ export class ListDatabasesActionItem implements IActionViewItem {
} }
private getCurrentDatabaseName() { private getCurrentDatabaseName() {
let uri = this._editor.connectedUri; let uri = this._editor.input.uri;
if (uri) { if (uri) {
let profile = this._connectionManagementService.getConnectionProfile(uri); let profile = this.connectionManagementService.getConnectionProfile(uri);
if (profile) { if (profile) {
return profile.databaseName; return profile.databaseName;
} }
@@ -600,7 +589,7 @@ export class ListDatabasesActionItem implements IActionViewItem {
return; return;
} }
let uri = this._editor.connectedUri; let uri = this._editor.input.uri;
if (uri !== connParams.connectionUri) { if (uri !== connParams.connectionUri) {
return; return;
} }
@@ -609,14 +598,12 @@ export class ListDatabasesActionItem implements IActionViewItem {
} }
private onDropdownFocus(): void { private onDropdownFocus(): void {
let self = this; let uri = this._editor.input.uri;
let uri = self._editor.connectedUri;
if (!uri) { if (!uri) {
return; return;
} }
self._connectionManagementService.listDatabases(uri) this.connectionManagementService.listDatabases(uri)
.then(result => { .then(result => {
if (result && result.databaseNames) { if (result && result.databaseNames) {
this._dropdown.values = result.databaseNames; this._dropdown.values = result.databaseNames;
@@ -630,12 +617,11 @@ export class ListDatabasesActionItem implements IActionViewItem {
if (this._isInAccessibilityMode) { if (this._isInAccessibilityMode) {
this._databaseSelectBox.enable(); this._databaseSelectBox.enable();
let self = this; let uri = this._editor.input.uri;
let uri = self._editor.connectedUri;
if (!uri) { if (!uri) {
return; return;
} }
self._connectionManagementService.listDatabases(uri) this.connectionManagementService.listDatabases(uri)
.then(result => { .then(result => {
if (result && result.databaseNames) { if (result && result.databaseNames) {
this._databaseSelectBox.setOptions(result.databaseNames); this._databaseSelectBox.setOptions(result.databaseNames);

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@ import * as types from 'vs/base/common/types';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput'; import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput';
import { IQueryModelService } from 'sql/platform/query/common/queryModel';
import { QueryResultsView } from 'sql/workbench/parts/query/browser/queryResultsView'; import { QueryResultsView } from 'sql/workbench/parts/query/browser/queryResultsView';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage'; import { IStorageService } from 'vs/platform/storage/common/storage';
@@ -95,7 +94,6 @@ export class QueryResultsEditor extends BaseEditor {
constructor( constructor(
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@IQueryModelService private _queryModelService: IQueryModelService,
@IConfigurationService private _configurationService: IConfigurationService, @IConfigurationService private _configurationService: IConfigurationService,
@IInstantiationService private _instantiationService: IInstantiationService, @IInstantiationService private _instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService @IStorageService storageService: IStorageService

View File

@@ -8,19 +8,21 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import { EditorInput, EditorModel, ConfirmResult, EncodingMode, IEncodingSupport } from 'vs/workbench/common/editor'; import { EditorInput, ConfirmResult, EncodingMode, IEncodingSupport } from 'vs/workbench/common/editor';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IEditorViewState } from 'vs/editor/common/editorCommon';
import { IConnectionManagementService, IConnectableInput, INewConnectionParams, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement'; import { IConnectionManagementService, IConnectableInput, INewConnectionParams, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement';
import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput'; import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput';
import { IQueryModelService } from 'sql/platform/query/common/queryModel'; import { IQueryModelService } from 'sql/platform/query/common/queryModel';
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
import { ISelectionData, ExecutionPlanOptions } from 'azdata'; import { ISelectionData, ExecutionPlanOptions } from 'azdata';
import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel';
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
const MAX_SIZE = 13; const MAX_SIZE = 13;
type PublicPart<T> = { [K in keyof T]: T[K] };
function trimTitle(title: string): string { function trimTitle(title: string): string {
const length = title.length; const length = title.length;
const diff = length - MAX_SIZE; const diff = length - MAX_SIZE;
@@ -33,30 +35,81 @@ function trimTitle(title: string): string {
} }
} }
export interface IQueryEditorStateChange {
connectedChange?: boolean;
resultsVisibleChange?: boolean;
executingChange?: boolean;
connectingChange?: boolean;
}
export class QueryEditorState {
private _connected = false;
private _resultsVisible = false;
private _executing = false;
private _connecting = false;
private _onChange = new Emitter<IQueryEditorStateChange>();
public onChange = this._onChange.event;
public set connected(val: boolean) {
if (val !== this._connected) {
this._connected = val;
this._onChange.fire({ connectedChange: true });
}
}
public get connected(): boolean {
return this._connected;
}
public set connecting(val: boolean) {
if (val !== this._connecting) {
this._connecting = val;
this._onChange.fire({ connectingChange: true });
}
}
public get connecting(): boolean {
return this._connecting;
}
public set resultsVisible(val: boolean) {
if (val !== this._resultsVisible) {
this._resultsVisible = val;
this._onChange.fire({ resultsVisibleChange: true });
}
}
public get resultsVisible(): boolean {
return this._resultsVisible;
}
public set executing(val: boolean) {
if (val !== this._executing) {
this._executing = val;
this._onChange.fire({ executingChange: true });
}
}
public get executing(): boolean {
return this._executing;
}
}
/** /**
* Input for the QueryEditor. This input is simply a wrapper around a QueryResultsInput for the QueryResultsEditor * Input for the QueryEditor. This input is simply a wrapper around a QueryResultsInput for the QueryResultsEditor
* and a UntitledEditorInput for the SQL File Editor. * and a UntitledEditorInput for the SQL File Editor.
*/ */
export class QueryInput extends EditorInput implements IEncodingSupport, IConnectableInput, IDisposable { export class QueryInput extends EditorInput implements IEncodingSupport, IConnectableInput, PublicPart<UntitledEditorInput>, IDisposable {
public static ID: string = 'workbench.editorinputs.queryInput'; public static ID: string = 'workbench.editorinputs.queryInput';
public static SCHEMA: string = 'sql'; public static SCHEMA: string = 'sql';
private _runQueryEnabled: boolean; private _state = new QueryEditorState();
private _cancelQueryEnabled: boolean; public get state(): QueryEditorState { return this._state; }
private _connectEnabled: boolean;
private _disconnectEnabled: boolean;
private _changeConnectionEnabled: boolean;
private _listDatabasesConnected: boolean;
private _updateTaskbar: Emitter<void>;
private _showQueryResultsEditor: Emitter<void>;
private _updateSelection: Emitter<ISelectionData>; private _updateSelection: Emitter<ISelectionData>;
private _currentEventCallbacks: IDisposable[];
public savedViewState: IEditorViewState;
constructor( constructor(
private _description: string, private _description: string,
private _sql: UntitledEditorInput, private _sql: UntitledEditorInput,
@@ -64,16 +117,12 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
private _connectionProviderName: string, private _connectionProviderName: string,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@IQueryModelService private _queryModelService: IQueryModelService, @IQueryModelService private _queryModelService: IQueryModelService,
@IQueryEditorService private _queryEditorService: IQueryEditorService,
@IConfigurationService private _configurationService: IConfigurationService @IConfigurationService private _configurationService: IConfigurationService
) { ) {
super(); super();
this._updateTaskbar = new Emitter<void>();
this._showQueryResultsEditor = new Emitter<void>();
this._updateSelection = new Emitter<ISelectionData>(); this._updateSelection = new Emitter<ISelectionData>();
this._toDispose = []; this._toDispose = [];
this._currentEventCallbacks = [];
// re-emit sql editor events through this editor if it exists // re-emit sql editor events through this editor if it exists
if (this._sql) { if (this._sql) {
this._toDispose.push(this._sql.onDidChangeDirty(() => this._onDidChangeDirty.fire())); this._toDispose.push(this._sql.onDidChangeDirty(() => this._onDidChangeDirty.fire()));
@@ -130,17 +179,6 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
public get uri(): string { return this.getResource().toString(); } public get uri(): string { return this.getResource().toString(); }
public get sql(): UntitledEditorInput { return this._sql; } public get sql(): UntitledEditorInput { return this._sql; }
public get results(): QueryResultsInput { return this._results; } public get results(): QueryResultsInput { return this._results; }
public get updateTaskbarEvent(): Event<void> { return this._updateTaskbar.event; }
public get showQueryResultsEditorEvent(): Event<void> { return this._showQueryResultsEditor.event; }
public get updateSelectionEvent(): Event<ISelectionData> { return this._updateSelection.event; }
public get runQueryEnabled(): boolean { return this._runQueryEnabled; }
public get cancelQueryEnabled(): boolean { return this._cancelQueryEnabled; }
public get connectEnabled(): boolean { return this._connectEnabled; }
public get disconnectEnabled(): boolean { return this._disconnectEnabled; }
public get changeConnectionEnabled(): boolean { return this._changeConnectionEnabled; }
public get listDatabasesConnected(): boolean { return this._listDatabasesConnected; }
public getQueryResultsInputResource(): string { return this._results.uri; }
public showQueryResultsEditor(): void { this._showQueryResultsEditor.fire(); }
public updateSelection(selection: ISelectionData): void { this._updateSelection.fire(selection); } public updateSelection(selection: ISelectionData): void { this._updateSelection.fire(selection); }
public getTypeId(): string { return QueryInput.ID; } public getTypeId(): string { return QueryInput.ID; }
// Description is shown beside the tab name in the combobox of open editors // Description is shown beside the tab name in the combobox of open editors
@@ -163,7 +201,7 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
// Forwarding resource functions to the inline sql file editor // Forwarding resource functions to the inline sql file editor
public get onDidModelChangeContent(): Event<void> { return this._sql.onDidModelChangeContent; } public get onDidModelChangeContent(): Event<void> { return this._sql.onDidModelChangeContent; }
public get onDidModelChangeEncoding(): Event<void> { return this._sql.onDidModelChangeEncoding; } public get onDidModelChangeEncoding(): Event<void> { return this._sql.onDidModelChangeEncoding; }
public resolve(refresh?: boolean): Promise<EditorModel> { return this._sql.resolve(); } public resolve(): Promise<UntitledEditorModel & IResolvedTextEditorModel> { return this._sql.resolve(); }
public save(): Promise<boolean> { return this._sql.save(); } public save(): Promise<boolean> { return this._sql.save(); }
public isDirty(): boolean { return this._sql.isDirty(); } public isDirty(): boolean { return this._sql.isDirty(); }
public confirmSave(): Promise<ConfirmResult> { return this._sql.confirmSave(); } public confirmSave(): Promise<ConfirmResult> { return this._sql.confirmSave(); }
@@ -207,43 +245,37 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
// State update funtions // State update funtions
public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void { public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void {
this._queryModelService.runQuery(this.uri, selection, this, executePlanOptions); this._queryModelService.runQuery(this.uri, selection, this, executePlanOptions);
this.showQueryResultsEditor(); this.state.executing = true;
} }
public runQueryStatement(selection: ISelectionData): void { public runQueryStatement(selection: ISelectionData): void {
this._queryModelService.runQueryStatement(this.uri, selection, this); this._queryModelService.runQueryStatement(this.uri, selection, this);
this.showQueryResultsEditor(); this.state.executing = true;
} }
public runQueryString(text: string): void { public runQueryString(text: string): void {
this._queryModelService.runQueryString(this.uri, text, this); this._queryModelService.runQueryString(this.uri, text, this);
this.showQueryResultsEditor(); this.state.executing = true;
} }
public onConnectStart(): void { public onConnectStart(): void {
this._runQueryEnabled = false; this.state.connecting = true;
this._cancelQueryEnabled = false; this.state.connected = false;
this._connectEnabled = false;
this._disconnectEnabled = true;
this._changeConnectionEnabled = false;
this._listDatabasesConnected = false;
this._updateTaskbar.fire();
} }
public onConnectReject(): void { public onConnectReject(): void {
this.onDisconnect(); this.state.connecting = false;
this._updateTaskbar.fire(); this.state.connected = false;
} }
public onConnectCanceled(): void { public onConnectCanceled(): void {
this.state.connecting = false;
this.state.connected = false;
} }
public onConnectSuccess(params?: INewConnectionParams): void { public onConnectSuccess(params?: INewConnectionParams): void {
this._runQueryEnabled = true; this.state.connected = true;
this._connectEnabled = false; this.state.connecting = false;
this._disconnectEnabled = true;
this._changeConnectionEnabled = true;
this._listDatabasesConnected = true;
let isRunningQuery = this._queryModelService.isRunningQuery(this.uri); let isRunningQuery = this._queryModelService.isRunningQuery(this.uri);
if (!isRunningQuery && params && params.runQueryOnCompletion) { if (!isRunningQuery && params && params.runQueryOnCompletion) {
@@ -258,30 +290,19 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
this.runQuery(selection, { displayActualQueryPlan: true }); this.runQuery(selection, { displayActualQueryPlan: true });
} }
} }
this._updateTaskbar.fire();
this._onDidChangeLabel.fire();
} }
public onDisconnect(): void { public onDisconnect(): void {
this._runQueryEnabled = true; this.state.connected = false;
this._cancelQueryEnabled = false;
this._connectEnabled = true;
this._disconnectEnabled = false;
this._changeConnectionEnabled = false;
this._listDatabasesConnected = false;
this._updateTaskbar.fire();
} }
public onRunQuery(): void { public onRunQuery(): void {
this._runQueryEnabled = false; this.state.executing = true;
this._cancelQueryEnabled = true; this.state.resultsVisible = true;
this._updateTaskbar.fire();
} }
public onQueryComplete(): void { public onQueryComplete(): void {
this._runQueryEnabled = true; this.state.executing = false;
this._cancelQueryEnabled = false;
this._updateTaskbar.fire();
} }
// Clean up functions // Clean up functions
@@ -289,7 +310,6 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
this._sql.dispose(); this._sql.dispose();
this._results.dispose(); this._results.dispose();
this._toDispose = dispose(this._toDispose); this._toDispose = dispose(this._toDispose);
this._currentEventCallbacks = dispose(this._currentEventCallbacks);
super.dispose(); super.dispose();
} }
@@ -301,18 +321,6 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
this._results.close(); this._results.close();
} }
/**
* Unsubscribe all events in _currentEventCallbacks and set the new callbacks
* to be unsubscribed the next time this method is called.
*
* This method is used to ensure that all callbacks point to the current QueryEditor
* in the case that this QueryInput is moved between different QueryEditors.
*/
public setEventCallbacks(callbacks: IDisposable[]): void {
this._currentEventCallbacks = dispose(this._currentEventCallbacks);
this._currentEventCallbacks = callbacks;
}
/** /**
* Get the color that should be displayed * Get the color that should be displayed
*/ */

View File

@@ -142,7 +142,7 @@ export class CommandLineService implements ICommandLineProcessing {
let activeEditor = this._editorService.editors.filter(v => v.getResource().toString() === uriString).pop(); let activeEditor = this._editorService.editors.filter(v => v.getResource().toString() === uriString).pop();
if (activeEditor) { if (activeEditor) {
let queryInput = activeEditor as QueryInput; let queryInput = activeEditor as QueryInput;
if (queryInput && queryInput.connectEnabled) { if (queryInput && queryInput.state.connected) {
let options: IConnectionCompletionOptions = { let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: queryInput }, params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: queryInput },
saveTheConnection: false, saveTheConnection: false,

View File

@@ -23,7 +23,7 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { assertThrowsAsync } from 'sqltest/utils/testUtils'; import { assertThrowsAsync } from 'sqltest/utils/testUtils';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestEditorService, TestLogService } from 'vs/workbench/test/workbenchTestServices'; import { TestEditorService, TestLogService } from 'vs/workbench/test/workbenchTestServices';
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput'; import { QueryInput, QueryEditorState } from 'sql/workbench/parts/query/common/queryInput';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
@@ -374,7 +374,9 @@ suite('commandLineService tests', () => {
const configurationService = getConfigurationServiceMock(true); const configurationService = getConfigurationServiceMock(true);
const queryInput: TypeMoq.Mock<QueryInput> = TypeMoq.Mock.ofType<QueryInput>(QueryInput); const queryInput: TypeMoq.Mock<QueryInput> = TypeMoq.Mock.ofType<QueryInput>(QueryInput);
let uri = URI.file(args._[0]); let uri = URI.file(args._[0]);
queryInput.setup(q => q.connectEnabled).returns(() => 1 === 1).verifiable(TypeMoq.Times.once()); const queryState = new QueryEditorState();
queryState.connected = true;
queryInput.setup(q => q.state).returns(() => queryState);
queryInput.setup(q => q.getResource()).returns(() => uri).verifiable(TypeMoq.Times.once()); queryInput.setup(q => q.getResource()).returns(() => uri).verifiable(TypeMoq.Times.once());
const editorService: TypeMoq.Mock<IEditorService> = TypeMoq.Mock.ofType<IEditorService>(TestEditorService, TypeMoq.MockBehavior.Strict); const editorService: TypeMoq.Mock<IEditorService> = TypeMoq.Mock.ofType<IEditorService>(TestEditorService, TypeMoq.MockBehavior.Strict);
editorService.setup(e => e.editors).returns(() => [queryInput.object]); editorService.setup(e => e.editors).returns(() => [queryInput.object]);

View File

@@ -30,7 +30,8 @@ import { ConfigurationService } from 'vs/platform/configuration/node/configurati
import * as TypeMoq from 'typemoq'; import * as TypeMoq from 'typemoq';
import * as assert from 'assert'; import * as assert from 'assert';
import { TestStorageService, TestLayoutService } from 'vs/workbench/test/workbenchTestServices'; import { TestStorageService, TestContextService } from 'vs/workbench/test/workbenchTestServices';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
let none: void; let none: void;
@@ -48,12 +49,12 @@ suite('SQL QueryAction Tests', () => {
testQueryInput.setup(x => x.uri).returns(() => testUri); testQueryInput.setup(x => x.uri).returns(() => testUri);
testQueryInput.setup(x => x.runQuery(undefined)).callback(() => { calledRunQueryOnInput = true; }); testQueryInput.setup(x => x.runQuery(undefined)).callback(() => { calledRunQueryOnInput = true; });
const contextkeyservice = new MockContextKeyService();
// Setup a reusable mock QueryEditor // Setup a reusable mock QueryEditor
editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(), undefined, undefined, undefined, undefined, editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(), new TestStorageService(), contextkeyservice, undefined, undefined,
undefined, undefined, undefined, new TestStorageService()); undefined);
editor.setup(x => x.connectedUri).returns(() => testUri); editor.setup(x => x.input).returns(() => testQueryInput.object);
editor.setup(x => x.currentQueryInput).returns(() => testQueryInput.object);
editor.setup(x => x.uri).returns(() => testUri);
editor.setup(x => x.getSelection()).returns(() => undefined); editor.setup(x => x.getSelection()).returns(() => undefined);
editor.setup(x => x.getSelection(false)).returns(() => undefined); editor.setup(x => x.getSelection(false)).returns(() => undefined);
@@ -85,10 +86,12 @@ suite('SQL QueryAction Tests', () => {
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, new TestStorageService()); let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, {}, new TestStorageService());
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnectedReturnValue); connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAnyString())).returns(() => isConnectedReturnValue);
// ... Create an editor const contextkeyservice = new MockContextKeyService();
let editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Loose, undefined, new TestThemeService(), undefined, undefined, undefined, undefined,
undefined, undefined, undefined, new TestStorageService()); // Setup a reusable mock QueryEditor
editor.setup(x => x.currentQueryInput).returns(() => testQueryInput.object); editor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(), new TestStorageService(), contextkeyservice, undefined, undefined,
undefined);
editor.setup(x => x.input).returns(() => testQueryInput.object);
// If I create a QueryTaskbarAction and I pass a non-connected editor to _getConnectedQueryEditorUri // If I create a QueryTaskbarAction and I pass a non-connected editor to _getConnectedQueryEditorUri
let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined, connectionManagementService.object); let queryAction: QueryTaskbarAction = new RunQueryAction(undefined, undefined, connectionManagementService.object);
@@ -148,7 +151,7 @@ suite('SQL QueryAction Tests', () => {
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor'); assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, RunQueryOnConnectionMode.executeQuery, 'runQueryOnCompletion should be true`'); assert.equal(connectionParams.runQueryOnCompletion, RunQueryOnConnectionMode.executeQuery, 'runQueryOnCompletion should be true`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI'); assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.currentQueryInput, 'Editor should be set to the mock editor'); assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
// If I call run on RunQueryAction when I am connected // If I call run on RunQueryAction when I am connected
isConnected = true; isConnected = true;
@@ -174,9 +177,12 @@ suite('SQL QueryAction Tests', () => {
queryInput.setup(x => x.runQuery(undefined)).callback(() => { queryInput.setup(x => x.runQuery(undefined)).callback(() => {
countCalledRunQuery++; countCalledRunQuery++;
}); });
let queryEditor: TypeMoq.Mock<QueryEditor> = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(), undefined, const contextkeyservice = new MockContextKeyService();
undefined, undefined, undefined, undefined, undefined, undefined, new TestStorageService());
queryEditor.setup(x => x.currentQueryInput).returns(() => queryInput.object); // Setup a reusable mock QueryEditor
let queryEditor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(), new TestStorageService(), contextkeyservice, undefined, undefined,
undefined);
queryEditor.setup(x => x.input).returns(() => queryInput.object);
queryEditor.setup(x => x.getSelection()).returns(() => undefined); queryEditor.setup(x => x.getSelection()).returns(() => undefined);
queryEditor.setup(x => x.getSelection(false)).returns(() => undefined); queryEditor.setup(x => x.getSelection(false)).returns(() => undefined);
queryEditor.setup(x => x.isSelectionEmpty()).returns(() => isSelectionEmpty); queryEditor.setup(x => x.isSelectionEmpty()).returns(() => isSelectionEmpty);
@@ -206,7 +212,7 @@ suite('SQL QueryAction Tests', () => {
done(); done();
}); });
test('ISelectionData is properly passed when queries are run', (done) => { test('ISelectionData is properly passed when queries are run', () => {
/// Setup Test /// /// Setup Test ///
@@ -239,14 +245,19 @@ suite('SQL QueryAction Tests', () => {
runQuerySelection = selection; runQuerySelection = selection;
countCalledRunQuery++; countCalledRunQuery++;
}); });
const contextkeyservice = new MockContextKeyService();
// ... Mock "getSelection" in QueryEditor // Setup a reusable mock QueryEditor
let queryEditor: TypeMoq.Mock<QueryEditor> = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Loose, undefined, new TestThemeService(), undefined, let queryEditor = TypeMoq.Mock.ofType(QueryEditor, TypeMoq.MockBehavior.Strict, undefined, new TestThemeService(), new TestStorageService(), contextkeyservice, undefined, undefined,
undefined, undefined, undefined, undefined, undefined, undefined, new TestStorageService()); undefined);
queryEditor.setup(x => x.currentQueryInput).returns(() => queryInput.object); queryEditor.setup(x => x.input).returns(() => queryInput.object);
queryEditor.setup(x => x.isSelectionEmpty()).returns(() => false);
queryEditor.setup(x => x.getSelection()).returns(() => { queryEditor.setup(x => x.getSelection()).returns(() => {
return selectionToReturnInGetSelection; return selectionToReturnInGetSelection;
}); });
queryEditor.setup(x => x.getSelection(TypeMoq.It.isAny())).returns(() => {
return selectionToReturnInGetSelection;
});
// ... Mock "isConnected" in ConnectionManagementService // ... Mock "isConnected" in ConnectionManagementService
let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, connectionDialogService.object); let connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, {}, connectionDialogService.object);
@@ -305,8 +316,6 @@ suite('SQL QueryAction Tests', () => {
assert.equal(runQuerySelection.startColumn, selectionToReturnInGetSelection.startColumn, 'startColumn should match'); assert.equal(runQuerySelection.startColumn, selectionToReturnInGetSelection.startColumn, 'startColumn should match');
assert.equal(runQuerySelection.endLine, selectionToReturnInGetSelection.endLine, 'endLine should match'); assert.equal(runQuerySelection.endLine, selectionToReturnInGetSelection.endLine, 'endLine should match');
assert.equal(runQuerySelection.endColumn, selectionToReturnInGetSelection.endColumn, 'endColumn should match'); assert.equal(runQuerySelection.endColumn, selectionToReturnInGetSelection.endColumn, 'endColumn should match');
done();
}); });
test('CancelQueryAction calls cancelQuery() only if URI is connected', (done) => { test('CancelQueryAction calls cancelQuery() only if URI is connected', (done) => {
@@ -401,7 +410,7 @@ suite('SQL QueryAction Tests', () => {
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor'); assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`'); assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI'); assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.currentQueryInput, 'Editor should be set to the mock editor'); assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
// If I call run on ConnectDatabaseAction when I am connected // If I call run on ConnectDatabaseAction when I am connected
isConnected = true; isConnected = true;
@@ -412,7 +421,7 @@ suite('SQL QueryAction Tests', () => {
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor'); assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`'); assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI'); assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.currentQueryInput, 'Editor should be set to the mock editor'); assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
done(); done();
}); });
@@ -447,7 +456,7 @@ suite('SQL QueryAction Tests', () => {
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor'); assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`'); assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI'); assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.currentQueryInput, 'Editor should be set to the mock editor'); assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
// Then if I call run on ChangeConnectionAction when I am connected // Then if I call run on ChangeConnectionAction when I am connected
isConnected = true; isConnected = true;
queryAction.run(); queryAction.run();
@@ -457,7 +466,7 @@ suite('SQL QueryAction Tests', () => {
assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor'); assert.equal(connectionParams.connectionType, ConnectionType.editor, 'connectionType should be queryEditor');
assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`'); assert.equal(connectionParams.runQueryOnCompletion, false, 'runQueryOnCompletion should be false`');
assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI'); assert.equal(connectionParams.input.uri, testUri, 'URI should be set to the test URI');
assert.equal(connectionParams.input, editor.object.currentQueryInput, 'Editor should be set to the mock editor'); assert.equal(connectionParams.input, editor.object.input, 'Editor should be set to the mock editor');
done(); done();
}); });
@@ -476,7 +485,7 @@ suite('SQL QueryAction Tests', () => {
}); });
// If I query without having initialized anything, state should be clear // If I query without having initialized anything, state should be clear
listItem = new ListDatabasesActionItem(editor.object, connectionManagementService.object, undefined, undefined, configurationService.object); listItem = new ListDatabasesActionItem(editor.object, undefined, connectionManagementService.object, undefined, configurationService.object);
assert.equal(listItem.isEnabled(), false, 'do not expect dropdown enabled unless connected'); assert.equal(listItem.isEnabled(), false, 'do not expect dropdown enabled unless connected');
assert.equal(listItem.currentDatabaseName, undefined, 'do not expect dropdown to have entries unless connected'); assert.equal(listItem.currentDatabaseName, undefined, 'do not expect dropdown to have entries unless connected');
@@ -511,7 +520,7 @@ suite('SQL QueryAction Tests', () => {
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName }); cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
// ... Create a database dropdown that has been connected // ... Create a database dropdown that has been connected
let listItem = new ListDatabasesActionItem(editor.object, cms.object, null, null, configurationService.object); let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, undefined, configurationService.object);
listItem.onConnected(); listItem.onConnected();
// If: I raise a connection changed event // If: I raise a connection changed event
@@ -535,7 +544,7 @@ suite('SQL QueryAction Tests', () => {
cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName }); cms.setup(x => x.getConnectionProfile(TypeMoq.It.isAny())).returns(() => <IConnectionProfile>{ databaseName: databaseName });
// ... Create a database dropdown that has been connected // ... Create a database dropdown that has been connected
let listItem = new ListDatabasesActionItem(editor.object, cms.object, null, null, configurationService.object); let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, undefined, configurationService.object);
listItem.onConnected(); listItem.onConnected();
// If: I raise a connection changed event for the 'wrong' URI // If: I raise a connection changed event for the 'wrong' URI
@@ -562,14 +571,14 @@ suite('SQL QueryAction Tests', () => {
cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event); cms.setup(x => x.onConnectionChanged).returns(() => dbChangedEmitter.event);
// ... Create a database dropdown // ... Create a database dropdown
let listItem = new ListDatabasesActionItem(editor.object, cms.object, null, null, configurationService.object); let listItem = new ListDatabasesActionItem(editor.object, undefined, cms.object, undefined, configurationService.object);
// If: I raise a connection changed event // If: I raise a connection changed event
let eventParams = <IConnectionParams>{ let eventParams = <IConnectionParams>{
connectionProfile: { connectionProfile: {
databaseName: 'foobarbaz' databaseName: 'foobarbaz'
}, },
connectionUri: editor.object.uri connectionUri: editor.object.input.uri
}; };
dbChangedEmitter.fire(eventParams); dbChangedEmitter.fire(eventParams);

View File

@@ -6,12 +6,10 @@
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEditorDescriptor } from 'vs/workbench/browser/editor'; import { IEditorDescriptor } from 'vs/workbench/browser/editor';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import * as DOM from 'vs/base/browser/dom';
import { Memento } from 'vs/workbench/common/memento'; import { Memento } from 'vs/workbench/common/memento';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput'; import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResultsInput';
import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor';
import { QueryModelService } from 'sql/platform/query/common/queryModelService'; import { QueryModelService } from 'sql/platform/query/common/queryModelService';
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput'; import { QueryInput } from 'sql/workbench/parts/query/common/queryInput';
import { INewConnectionParams, ConnectionType, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement'; import { INewConnectionParams, ConnectionType, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement';
@@ -19,8 +17,6 @@ import { ConnectionManagementService } from 'sql/platform/connection/common/conn
import { RunQueryAction, ListDatabasesActionItem } from 'sql/workbench/parts/query/browser/queryActions'; import { RunQueryAction, ListDatabasesActionItem } from 'sql/workbench/parts/query/browser/queryActions';
import { EditorDescriptorService } from 'sql/workbench/services/queryEditor/common/editorDescriptorService'; import { EditorDescriptorService } from 'sql/workbench/services/queryEditor/common/editorDescriptorService';
import { TestThemeService } from 'sqltest/stubs/themeTestService';
import * as TypeMoq from 'typemoq'; import * as TypeMoq from 'typemoq';
import * as assert from 'assert'; import * as assert from 'assert';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -30,7 +26,6 @@ import { TestStorageService } from 'vs/workbench/test/workbenchTestServices';
suite('SQL QueryEditor Tests', () => { suite('SQL QueryEditor Tests', () => {
let instantiationService: TypeMoq.Mock<InstantiationService>; let instantiationService: TypeMoq.Mock<InstantiationService>;
let themeService: TestThemeService = new TestThemeService();
let editorDescriptorService: TypeMoq.Mock<EditorDescriptorService>; let editorDescriptorService: TypeMoq.Mock<EditorDescriptorService>;
let connectionManagementService: TypeMoq.Mock<ConnectionManagementService>; let connectionManagementService: TypeMoq.Mock<ConnectionManagementService>;
let configurationService: TypeMoq.Mock<ConfigurationService>; let configurationService: TypeMoq.Mock<ConfigurationService>;
@@ -38,20 +33,6 @@ suite('SQL QueryEditor Tests', () => {
let mockEditor: any; let mockEditor: any;
let getQueryEditor = function (): QueryEditor {
return new QueryEditor(
undefined,
themeService,
instantiationService.object,
undefined,
undefined,
editorDescriptorService.object,
undefined,
undefined,
configurationService.object,
new TestStorageService());
};
setup(() => { setup(() => {
// Create object to mock the Editor classes // Create object to mock the Editor classes
// QueryResultsEditor fails at runtime due to the way we are importing Angualar, // QueryResultsEditor fails at runtime due to the way we are importing Angualar,
@@ -79,7 +60,7 @@ suite('SQL QueryEditor Tests', () => {
instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((classDef, editor, action) => { instantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((classDef, editor, action) => {
if (classDef.ID) { if (classDef.ID) {
if (classDef.ID === 'listDatabaseQueryActionItem') { if (classDef.ID === 'listDatabaseQueryActionItem') {
return new ListDatabasesActionItem(editor, connectionManagementService.object, undefined, undefined, configurationService.object); return new ListDatabasesActionItem(editor, undefined, connectionManagementService.object, undefined, configurationService.object);
} }
} }
// Default // Default
@@ -114,26 +95,6 @@ suite('SQL QueryEditor Tests', () => {
connectionManagementService.setup(x => x.ensureDefaultLanguageFlavor(TypeMoq.It.isAnyString())).returns(() => void 0); connectionManagementService.setup(x => x.ensureDefaultLanguageFlavor(TypeMoq.It.isAnyString())).returns(() => void 0);
}); });
test('createEditor creates only the taskbar', (done) => {
// If I call createEditor
let editor: QueryEditor = getQueryEditor();
editor.createEditor(DOM.$('queryEditorParent'));
// The taskbar should be created
assert.equal(!!editor.taskbar, true);
assert.equal(!!editor.taskbarContainer, true);
// But Nothing else should be created
assert.equal(!!editor.getContainer(), false);
assert.equal(!!editor.sqlEditor, false);
assert.equal(!!editor.sqlEditorContainer, false);
assert.equal(!!editor.resultsEditor, false);
assert.equal(!!editor.resultsEditorContainer, false);
assert.equal(!!editor.sash, false);
assert.equal(!!editor._isResultsEditorVisible(), false);
done();
});
/* /*
test('setInput creates SQL components', (done) => { test('setInput creates SQL components', (done) => {
let assertInput = function () { let assertInput = function () {
@@ -315,7 +276,7 @@ suite('SQL QueryEditor Tests', () => {
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())) queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.returns((definition, editor, action, selectBox) => { .returns((definition, editor, action, selectBox) => {
if (definition.ID === 'listDatabaseQueryActionItem') { if (definition.ID === 'listDatabaseQueryActionItem') {
let item = new ListDatabasesActionItem(editor, queryConnectionService.object, undefined, undefined, configurationService.object); let item = new ListDatabasesActionItem(editor, undefined, queryConnectionService.object, undefined, configurationService.object);
return item; return item;
} }
// Default // Default
@@ -333,43 +294,33 @@ suite('SQL QueryEditor Tests', () => {
undefined, undefined,
connectionManagementService.object, connectionManagementService.object,
queryModelService.object, queryModelService.object,
undefined,
undefined undefined
); );
}); });
test('Taskbar buttons are set correctly upon standard load', (done) => { test('Taskbar buttons are set correctly upon standard load', () => {
queryConnectionService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false); queryConnectionService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false);
queryModelService.setup(x => x.isRunningQuery(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 // If I use the created QueryEditor with no changes since creation
// Buttons should be set as if disconnected // Buttons should be set as if disconnected
assert.equal(queryInput.runQueryEnabled, true, 'runQueryAction button should be enabled'); assert.equal(queryInput.state.connected, false, 'query state should be not connected');
assert.equal(queryInput.cancelQueryEnabled, false, 'cancelQueryAction button should not be enabled'); assert.equal(queryInput.state.executing, false, 'query state should be not executing');
assert.equal(queryInput.connectEnabled, true, 'connectDatabaseAction button should be enabled'); assert.equal(queryInput.state.connecting, false, 'query state should be not connecting');
assert.equal(queryInput.disconnectEnabled, false, 'disconnectDatabaseAction button should not be enabled');
assert.equal(queryInput.changeConnectionEnabled, false, 'changeConnectionAction button should not be enabled');
assert.equal(queryInput.listDatabasesConnected, false);
done();
}); });
test('Taskbar buttons are set correctly upon connect', (done) => { test('Taskbar buttons are set correctly upon connect', () => {
let params: INewConnectionParams = { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none }; let params: INewConnectionParams = { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none };
queryInput.onConnectSuccess(params); queryInput.onConnectSuccess(params);
queryModelService.setup(x => x.isRunningQuery(TypeMoq.It.isAny())).returns(() => false); queryModelService.setup(x => x.isRunningQuery(TypeMoq.It.isAny())).returns(() => false);
assert.equal(queryInput.runQueryEnabled, true, 'runQueryAction button should be enabled'); assert.equal(queryInput.state.connected, true, 'query state should be not connected');
assert.equal(queryInput.cancelQueryEnabled, false, 'cancelQueryAction button should not be enabled'); assert.equal(queryInput.state.executing, false, 'query state should be not executing');
assert.equal(queryInput.connectEnabled, false, 'connectDatabaseAction button should not be enabled'); assert.equal(queryInput.state.connecting, false, 'query state should be not connecting');
assert.equal(queryInput.disconnectEnabled, true, 'disconnectDatabaseAction button should be enabled');
assert.equal(queryInput.changeConnectionEnabled, true, 'changeConnectionAction button should be enabled');
assert.equal(queryInput.listDatabasesConnected, true);
done();
}); });
test('Test that we attempt to dispose query when the queryInput is disposed', (done) => { test('Test that we attempt to dispose query when the queryInput is disposed', () => {
let queryResultsInput = new QueryResultsInput('testUri', configurationService.object); let queryResultsInput = new QueryResultsInput('testUri', configurationService.object);
queryInput['_results'] = queryResultsInput; queryInput['_results'] = queryResultsInput;
queryInput.close(); queryInput.close();
queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once()); queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
done();
}); });
}); });
}); });

View File

@@ -76,7 +76,7 @@ suite('TaskUtilities', function () {
// Mock the workbench service to return the active tab connection // Mock the workbench service to return the active tab connection
let tabConnectionUri = 'file://test_uri'; let tabConnectionUri = 'file://test_uri';
let editorInput = new UntitledEditorInput(URI.parse(tabConnectionUri), false, undefined, undefined, undefined, undefined, undefined, undefined); 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, undefined); let queryInput = new QueryInput(undefined, editorInput, undefined, undefined, undefined, undefined, undefined);
mockConnectionManagementService.setup(x => x.getConnectionProfile(tabConnectionUri)).returns(() => tabProfile); mockConnectionManagementService.setup(x => x.getConnectionProfile(tabConnectionUri)).returns(() => tabProfile);
// If I call getCurrentGlobalConnection, it should return the expected profile from the active tab // If I call getCurrentGlobalConnection, it should return the expected profile from the active tab

View File

@@ -160,10 +160,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs
} }
// {{SQL CARBON EDIT}} const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom';
// turn-off custom menus to avoid bug calculating size of SQL editor
// const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom';
const useCustomTitleStyle = false;
if (useCustomTitleStyle) { if (useCustomTitleStyle) {
options.titleBarStyle = 'hidden'; options.titleBarStyle = 'hidden';
this.hiddenTitleBarStyle = true; this.hiddenTitleBarStyle = true;

View File

@@ -300,16 +300,13 @@ export function getTitleBarStyle(configurationService: IConfigurationService, en
return 'native'; // simple fullscreen does not work well with custom title style (https://github.com/Microsoft/vscode/issues/63291) return 'native'; // simple fullscreen does not work well with custom title style (https://github.com/Microsoft/vscode/issues/63291)
} }
// {{SQL CARBON EDIT}} - Always use native toolbar const style = configuration.titleBarStyle;
// const style = configuration.titleBarStyle; if (style === 'native' || style === 'custom') {
// if (style === 'native' || style === 'custom') { return style;
// return style; }
// }
} }
// {{SQL CARBON EDIT}} - Always use native toolbar return isLinux ? 'native' : 'custom'; // default to custom on all macOS and Windows
return 'native';
// return isLinux ? 'native' : 'custom'; // default to custom on all macOS and Windows
} }
export const enum OpenContext { export const enum OpenContext {

View File

@@ -219,7 +219,6 @@ export class MenubarControl extends Disposable {
// TODO@sbatten remove after feb19 // TODO@sbatten remove after feb19
private notifyExistingLinuxUser(): void { private notifyExistingLinuxUser(): void {
/*// {{SQL CARBON EDIT}} - Disable the custom titlebar recommendation
if (!isLinux) { if (!isLinux) {
return; return;
} }
@@ -246,7 +245,6 @@ export class MenubarControl extends Disposable {
} }
} }
]); ]);
*/
} }
private notifyUserOfCustomMenubarAccessibility(): void { private notifyUserOfCustomMenubarAccessibility(): void {

View File

@@ -55,12 +55,11 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
private onConfigurationChange(config: IConfiguration, notify: boolean): void { private onConfigurationChange(config: IConfiguration, notify: boolean): void {
let changed = false; let changed = false;
// {{SQL CARBON EDIT}}
// Titlebar style // Titlebar style
// if (config.window && config.window.titleBarStyle !== this.titleBarStyle && (config.window.titleBarStyle === 'native' || config.window.titleBarStyle === 'custom')) { if (config.window && config.window.titleBarStyle !== this.titleBarStyle && (config.window.titleBarStyle === 'native' || config.window.titleBarStyle === 'custom')) {
// this.titleBarStyle = 'native'; //config.window.titleBarStyle; this.titleBarStyle = config.window.titleBarStyle;
// changed = true; changed = true;
// } }
// macOS: Native tabs // macOS: Native tabs
if (isMacintosh && config.window && typeof config.window.nativeTabs === 'boolean' && config.window.nativeTabs !== this.nativeTabs) { if (isMacintosh && config.window && typeof config.window.nativeTabs === 'boolean' && config.window.nativeTabs !== this.nativeTabs) {