Strict nulls check contrib/queryplan (#11917)

* remove angular query pla neditor and replace with non-angular version; strict null check contrib/queryPlan

* fix compile
This commit is contained in:
Anthony Dresser
2020-08-21 23:04:36 -07:00
committed by GitHub
parent 91065ebc38
commit 3e515f2f59
9 changed files with 101 additions and 268 deletions

View File

@@ -300,8 +300,8 @@ export class QueryResultsView extends Disposable {
this.dynamicModelViewTabs.forEach(t => t.clear()); this.dynamicModelViewTabs.forEach(t => t.clear());
this.resultsTab.view.state = this.input.state.gridPanelState; this.resultsTab.view.state = this.input.state.gridPanelState;
this.qpTab.view.state = this.input.state.queryPlanState; this.qpTab.view.setState(this.input.state.queryPlanState);
this.topOperationsTab.view.state = this.input.state.topOperationsState; this.topOperationsTab.view.setState(this.input.state.topOperationsState);
this.chartTab.view.state = this.input.state.chartState; this.chartTab.view.state = this.input.state.chartState;
this.dynamicModelViewTabs.forEach((dynamicTab: QueryModelViewTab) => { this.dynamicModelViewTabs.forEach((dynamicTab: QueryModelViewTab) => {
dynamicTab.captureState(this.input.state.dynamicModelViewTabsState); dynamicTab.captureState(this.input.state.dynamicModelViewTabsState);

View File

@@ -4,12 +4,13 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
class RunTimeInformation { class RunTimeInformation {
runtimePerThreads: RuntimePerThread[]; constructor(public runtimePerThreads?: RuntimePerThread[]) { }
public get actualRows(): number { public get actualRows(): number {
let total = 0; let total = 0;
if (this.runtimePerThreads) { if (this.runtimePerThreads) {
this.runtimePerThreads.forEach(element => { this.runtimePerThreads.forEach(element => {
total += element.actualRow; total += element.actualRow ?? 0;
}); });
} }
@@ -20,26 +21,26 @@ class RunTimeInformation {
let total = 0; let total = 0;
if (this.runtimePerThreads) { if (this.runtimePerThreads) {
this.runtimePerThreads.forEach(element => { this.runtimePerThreads.forEach(element => {
total += element.actualExecutions; total += element.actualExecutions ?? 0;
}); });
} }
return total; return total;
} }
} }
class RuntimePerThread { interface RuntimePerThread {
threadId: number; threadId?: number;
actualRow: number; actualRow?: number;
actualExecutionMode: string; actualExecutionMode?: string;
actualExecutions: number; actualExecutions?: number;
} }
class IndexObject { class IndexObject {
database: string; public database?: string;
schema: string; public schema?: string;
table: string; public table?: string;
index: string; public index?: string;
indexKind: string; public indexKind?: string;
public get title() { public get title() {
let title: string = ''; let title: string = '';
@@ -54,22 +55,23 @@ class IndexObject {
} }
class PlanNode { class PlanNode {
root: PlanNode; private childrenNodes: PlanNode[] = [];
subtreeCost: number;
private childrenNodes: PlanNode[]; public root?: PlanNode;
parent: PlanNode; public subtreeCost?: number;
physicalOp: string; public parent?: PlanNode;
logicalOp: string; public physicalOp?: string;
id: number; public logicalOp?: string;
estimateRows: string; public id?: number;
estimateIo: string; public estimateRows?: string;
estimateCpu: string; public estimateIo?: string;
parallel: boolean; public estimateCpu?: string;
partitioned: boolean; public parallel?: boolean;
estimateRewinds: string; public partitioned?: boolean;
estimateRebinds: string; public estimateRewinds?: string;
runtimeInfo: RunTimeInformation; public estimateRebinds?: string;
indexObject: IndexObject; public runtimeInfo?: RunTimeInformation;
public indexObject?: IndexObject;
public addChildren(children: PlanNode[]): void { public addChildren(children: PlanNode[]): void {
if (children) { if (children) {
@@ -81,10 +83,10 @@ class PlanNode {
} }
public get totalSubTreeCost(): number { public get totalSubTreeCost(): number {
let total = this.subtreeCost; let total = this.subtreeCost ?? 0;
if (total === 0) { if (total === 0) {
this.children.forEach(element => { this.children.forEach(element => {
total += element.subtreeCost; total += element.subtreeCost ?? 0;
}); });
} }
return total; return total;
@@ -95,17 +97,17 @@ class PlanNode {
} }
public get cost(): number { public get cost(): number {
let total = this.subtreeCost; let total = this.subtreeCost ?? 0;
if (this.children && total !== 0) { if (this.children && total !== 0) {
this.children.forEach(element => { this.children.forEach(element => {
total -= element.subtreeCost; total -= element.subtreeCost ?? 0;
}); });
} }
return total; return total;
} }
public get relativeCost(): number { public get relativeCost(): number {
let overallCost = this.root.totalSubTreeCost; let overallCost = this.root?.totalSubTreeCost ?? 0;
return overallCost > 0 ? this.cost / overallCost : 0; return overallCost > 0 ? this.cost / overallCost : 0;
} }
@@ -125,7 +127,7 @@ class PlanNode {
public get title(): string { public get title(): string {
if (this.physicalOp === this.logicalOp) { if (this.physicalOp === this.logicalOp) {
return this.physicalOp; return this.physicalOp ?? '';
} else { } else {
return `${this.physicalOp}(${this.logicalOp})`; return `${this.physicalOp}(${this.logicalOp})`;
} }
@@ -141,10 +143,10 @@ class PlanNode {
} }
export class PlanXmlParser { export class PlanXmlParser {
parser: DOMParser = new DOMParser(); public parser: DOMParser = new DOMParser();
doc: Document; public doc?: Document;
planXml: string; public planXml?: string;
root: PlanNode; public root?: PlanNode;
constructor(planXml: string) { constructor(planXml: string) {
@@ -179,7 +181,9 @@ export class PlanXmlParser {
public get toTreeViewList(): PlanNode[] { public get toTreeViewList(): PlanNode[] {
let operations: PlanNode[] = []; let operations: PlanNode[] = [];
if (this.root) {
operations = this.addOperationsToList(operations, this.root.children); operations = this.addOperationsToList(operations, this.root.children);
}
return operations; return operations;
} }
@@ -192,7 +196,7 @@ export class PlanXmlParser {
return list; return list;
} }
private findChildren(element: Element, elementName: string, untilNode: string = undefined): Element[] { private findChildren(element: Element, elementName: string, untilNode: string | undefined = undefined): Element[] | undefined {
let elements: Element[] = []; let elements: Element[] = [];
if (element === undefined) { if (element === undefined) {
return undefined; return undefined;
@@ -251,10 +255,10 @@ export class PlanXmlParser {
private convertToPlanNode(element: Element): PlanNode { private convertToPlanNode(element: Element): PlanNode {
let planNode = new PlanNode(); let planNode = new PlanNode();
planNode.id = this.findAttribute(element.attributes, 'NodeId'); planNode.id = Number(this.findAttribute(element.attributes, 'NodeId'));
planNode.logicalOp = this.findAttribute(element.attributes, 'LogicalOp'); planNode.logicalOp = this.findAttribute(element.attributes, 'LogicalOp');
planNode.physicalOp = this.findAttribute(element.attributes, 'PhysicalOp'); planNode.physicalOp = this.findAttribute(element.attributes, 'PhysicalOp');
planNode.subtreeCost = +this.findAttribute(element.attributes, 'EstimatedTotalSubtreeCost'); planNode.subtreeCost = Number(this.findAttribute(element.attributes, 'EstimatedTotalSubtreeCost'));
planNode.estimateRows = this.findAttribute(element.attributes, 'EstimateRows'); planNode.estimateRows = this.findAttribute(element.attributes, 'EstimateRows');
planNode.estimateCpu = this.findAttribute(element.attributes, 'EstimateCPU'); planNode.estimateCpu = this.findAttribute(element.attributes, 'EstimateCPU');
planNode.estimateIo = this.findAttribute(element.attributes, 'EstimateIO'); planNode.estimateIo = this.findAttribute(element.attributes, 'EstimateIO');
@@ -266,12 +270,12 @@ export class PlanXmlParser {
} }
private convertToRuntimeInfo(element: Element): RuntimePerThread { private convertToRuntimeInfo(element: Element): RuntimePerThread {
let runtimeNode = new RuntimePerThread(); return {
runtimeNode.actualExecutionMode = this.findAttribute(element.attributes, 'ActualExecutionMode'); actualExecutionMode: this.findAttribute(element.attributes, 'ActualExecutionMode'),
runtimeNode.actualExecutions = +this.findAttribute(element.attributes, 'ActualExecutions'); actualExecutions: Number(this.findAttribute(element.attributes, 'ActualExecutions')),
runtimeNode.actualRow = +this.findAttribute(element.attributes, 'ActualRows'); actualRow: Number(this.findAttribute(element.attributes, 'ActualRows')),
runtimeNode.threadId = +this.findAttribute(element.attributes, 'Thread'); threadId: Number(this.findAttribute(element.attributes, 'Thread'))
return runtimeNode; };
} }
private convertToObject(element: Element): IndexObject { private convertToObject(element: Element): IndexObject {
@@ -284,12 +288,13 @@ export class PlanXmlParser {
return objectNode; return objectNode;
} }
private findAttribute(attributes: NamedNodeMap, attName: string): any { private findAttribute(attributes: NamedNodeMap, attName: string): string | undefined {
for (let index = 0; index < attributes.length; index++) { for (let index = 0; index < attributes.length; index++) {
let attribute = attributes[index]; let attribute = attributes[index];
if (attribute.name === attName) { if (attribute.name === attName) {
return attribute.value; return attribute.value;
} }
} }
return undefined;
} }
} }

View File

@@ -1,68 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/qp';
import { ElementRef, Component, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
import * as QP from 'html-query-plan';
import { IQueryPlanParams, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { registerThemingParticipant, ICssStyleCollector, IColorTheme } from 'vs/platform/theme/common/themeService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
export const QUERYPLAN_SELECTOR: string = 'queryplan-component';
@Component({
selector: QUERYPLAN_SELECTOR,
template: `
<div #container class="fullsize" style="overflow: scroll">
</div>
`
})
export class QueryPlanComponent implements OnDestroy, OnInit {
private _planXml: string;
private _disposables: Array<IDisposable> = [];
@ViewChild('container', { read: ElementRef }) _container: ElementRef;
constructor(
@Inject(IBootstrapParams) private _params: IQueryPlanParams
) { }
ngOnDestroy() {
dispose(this._disposables);
}
ngOnInit() {
if (this._params) {
this.planXml = this._params.planXml;
}
this._disposables.push(registerThemingParticipant(this._updateTheme));
}
public set planXml(val: string) {
this._planXml = val;
if (this._planXml) {
QP.showPlan(this._container.nativeElement, this._planXml, {
jsTooltips: false
});
}
}
private _updateTheme(theme: IColorTheme, collector: ICssStyleCollector) {
let backgroundColor = theme.getColor(colors.editorBackground);
let foregroundColor = theme.getColor(colors.editorForeground);
if (backgroundColor) {
collector.addRule(`div.qp-node, .qp-tt, .qp-root { background-color: ${backgroundColor} }`);
}
if (foregroundColor) {
collector.addRule(`.qp-root { color: ${foregroundColor} }`);
}
}
}

View File

@@ -1,51 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver, Type } from '@angular/core';
import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { QueryPlanComponent } from 'sql/workbench/contrib/queryPlan/browser/queryPlan.component';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
// Connection Dashboard main angular module
export const QueryPlanModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
@NgModule({
declarations: [
QueryPlanComponent
],
entryComponents: [QueryPlanComponent],
imports: [
CommonModule,
BrowserModule
],
providers: [
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: IBootstrapParams, useValue: params },
{ provide: ISelector, useValue: selector },
...providerIterator(instantiationService)
]
})
class ModuleClass {
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
@Inject(ISelector) private selector: string
) {
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(QueryPlanComponent);
(<any>factory).factory.selector = this.selector;
appRef.bootstrap(factory);
}
}
return ModuleClass;
};

View File

@@ -31,10 +31,10 @@ export class QueryPlanTab implements IPanelTab {
} }
export class QueryPlanView implements IPanelView { export class QueryPlanView implements IPanelView {
private qp: QueryPlan; private qp?: QueryPlan;
private xml: string; private xml?: string;
private container = document.createElement('div'); private container = document.createElement('div');
private _state: QueryPlanState; private _state?: QueryPlanState;
public render(container: HTMLElement): void { public render(container: HTMLElement): void {
container.appendChild(this.container); container.appendChild(this.container);
@@ -50,7 +50,6 @@ export class QueryPlanView implements IPanelView {
dispose() { dispose() {
this.container.remove(); this.container.remove();
this.qp = undefined; this.qp = undefined;
this.container = undefined;
} }
public layout(dimension: Dimension): void { public layout(dimension: Dimension): void {
@@ -79,38 +78,38 @@ export class QueryPlanView implements IPanelView {
} }
} }
public set state(val: QueryPlanState) { public setState(val: QueryPlanState) {
this._state = val; this._state = val;
if (this.state.xml) { if (this._state.xml) {
this.showPlan(this.state.xml); this.showPlan(this._state.xml);
} }
} }
public get state(): QueryPlanState { public get state(): QueryPlanState | undefined {
return this._state; return this._state;
} }
} }
export class QueryPlan { export class QueryPlan {
private _xml: string; private _xml?: string;
constructor(private container: HTMLElement) { constructor(private container: HTMLElement) {
} }
public set xml(xml: string) { public set xml(xml: string | undefined) {
this._xml = xml; this._xml = xml;
clearNode(this.container); clearNode(this.container);
if (this.xml) { if (this.xml) {
QP.showPlan(this.container, this._xml, { QP.showPlan(this.container, this.xml, {
jsTooltips: false jsTooltips: false
}); });
(<any>this.container.querySelectorAll('div.qp-tt')).forEach(toolTip => { this.container.querySelectorAll('div.qp-tt').forEach(toolTip => {
toolTip.classList.add('monaco-editor'); toolTip.classList.add('monaco-editor');
toolTip.classList.add('monaco-editor-hover'); toolTip.classList.add('monaco-editor-hover');
}); });
} }
} }
public get xml(): string { public get xml(): string | undefined {
return this._xml; return this._xml;
} }
} }

View File

@@ -8,23 +8,20 @@ import { EditorOptions } from 'vs/workbench/common/editor';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { QueryPlanInput } from 'sql/workbench/contrib/queryPlan/common/queryPlanInput'; import { QueryPlanInput } from 'sql/workbench/contrib/queryPlan/common/queryPlanInput';
import { QueryPlanModule } from 'sql/workbench/contrib/queryPlan/browser/queryPlan.module';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IQueryPlanParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { QUERYPLAN_SELECTOR } from 'sql/workbench/contrib/queryPlan/browser/queryPlan.component';
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';
import { QueryPlanView } from 'sql/workbench/contrib/queryPlan/browser/queryPlan';
export class QueryPlanEditor extends BaseEditor { export class QueryPlanEditor extends BaseEditor {
public static ID: string = 'workbench.editor.queryplan'; public static ID: string = 'workbench.editor.queryplan';
private view = this._register(new QueryPlanView());
constructor( constructor(
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService @IStorageService storageService: IStorageService
) { ) {
super(QueryPlanEditor.ID, telemetryService, themeService, storageService); super(QueryPlanEditor.ID, telemetryService, themeService, storageService);
@@ -45,12 +42,14 @@ export class QueryPlanEditor extends BaseEditor {
//(plus it's probable that we won't be using this control in the future anyways if development) //(plus it's probable that we won't be using this control in the future anyways if development)
//continues on the Query plan feature //continues on the Query plan feature
parent.style.background = '#fff'; parent.style.background = '#fff';
this.view.render(parent);
} }
/** /**
* Sets focus on this editor. Specifically, it sets the focus on the hosted text editor. * Sets focus on this editor. Specifically, it sets the focus on the hosted text editor.
*/ */
public focus(): void { public focus(): void {
this.view.focus();
} }
/** /**
@@ -58,6 +57,7 @@ export class QueryPlanEditor extends BaseEditor {
* To be called when the container of this editor changes size. * To be called when the container of this editor changes size.
*/ */
public layout(dimension: DOM.Dimension): void { public layout(dimension: DOM.Dimension): void {
this.view.layout(dimension);
} }
public async setInput(input: QueryPlanInput, options: EditorOptions): Promise<void> { public async setInput(input: QueryPlanInput, options: EditorOptions): Promise<void> {
@@ -65,49 +65,10 @@ export class QueryPlanEditor extends BaseEditor {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
await input.resolve(); await input.resolve();
if (!input.hasInitialized) {
this.bootstrapAngular(input);
}
this.revealElementWithTagName(input.uniqueSelector, this.getContainer());
return super.setInput(input, options, CancellationToken.None); await super.setInput(input, options, CancellationToken.None);
}
/** this.view.showPlan(input.planXml!);
* Reveal the child element with the given tagName and hide all other elements.
*/
private revealElementWithTagName(tagName: string, parent: HTMLElement): void {
let elementToReveal: HTMLElement;
for (let i = 0; i < parent.children.length; i++) {
let child: HTMLElement = <HTMLElement>parent.children[i];
if (child.tagName && child.tagName.toLowerCase() === tagName && !elementToReveal) {
elementToReveal = child;
} else {
child.style.display = 'none';
}
}
if (elementToReveal) {
elementToReveal.style.display = '';
}
}
/**
* Load the angular components and record for this input that we have done so
*/
private bootstrapAngular(input: QueryPlanInput): void {
// Get the bootstrap params and perform the bootstrap
let params: IQueryPlanParams = {
planXml: input.planXml
};
let uniqueSelector = this.instantiationService.invokeFunction(bootstrapAngular,
QueryPlanModule,
this.getContainer(),
QUERYPLAN_SELECTOR,
params);
input.setUniqueSelector(uniqueSelector);
} }
public dispose(): void { public dispose(): void {

View File

@@ -50,7 +50,7 @@ export class TopOperationsTab extends Disposable implements IPanelTab {
} }
export class TopOperationsView extends Disposable implements IPanelView { export class TopOperationsView extends Disposable implements IPanelView {
private _state: TopOperationsState; private _state?: TopOperationsState;
private table: Table<any>; private table: Table<any>;
private container = document.createElement('div'); private container = document.createElement('div');
private dataView = new TableDataView(); private dataView = new TableDataView();
@@ -86,19 +86,19 @@ export class TopOperationsView extends Disposable implements IPanelView {
} }
public showPlan(xml: string) { public showPlan(xml: string) {
this.state.xml = xml; this.state!.xml = xml;
this.dataView.clear(); this.dataView.clear();
let parser = new PlanXmlParser(xml); let parser = new PlanXmlParser(xml);
let operations = parser.topOperations; let operations = parser.topOperations;
let data = operations.map(i => { let data = operations.map(i => {
return { return {
operation: i.title, operation: i.title,
object: i.indexObject.title, object: i.indexObject?.title,
estCost: i.estimatedOperatorCost, estCost: i.estimatedOperatorCost,
estSubtreeCost: i.subtreeCost, estSubtreeCost: i.subtreeCost,
actualRows: i.runtimeInfo.actualRows, actualRows: i.runtimeInfo?.actualRows,
estRows: i.estimateRows, estRows: i.estimateRows,
actualExecutions: i.runtimeInfo.actualExecutions, actualExecutions: i.runtimeInfo?.actualExecutions,
estCPUCost: i.estimateCpu, estCPUCost: i.estimateCpu,
estIOCost: i.estimateIo, estIOCost: i.estimateIo,
parallel: i.parallel, parallel: i.parallel,
@@ -112,14 +112,14 @@ export class TopOperationsView extends Disposable implements IPanelView {
this.dataView.push(data); this.dataView.push(data);
} }
public set state(val: TopOperationsState) { public setState(val: TopOperationsState) {
this._state = val; this._state = val;
if (this.state.xml) { if (this._state.xml) {
this.showPlan(this.state.xml); this.showPlan(this._state.xml);
} }
} }
public get state(): TopOperationsState { public get state(): TopOperationsState | undefined {
return this._state; return this._state;
} }
} }

View File

@@ -4,24 +4,30 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { EditorInput, EditorModel, IEditorInput } from 'vs/workbench/common/editor'; import { EditorInput, EditorModel, IEditorInput } from 'vs/workbench/common/editor';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILanguageAssociation } from 'sql/workbench/services/languageAssociation/common/languageAssociation'; import { ILanguageAssociation } from 'sql/workbench/services/languageAssociation/common/languageAssociation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
export class QueryPlanConverter implements ILanguageAssociation { export class QueryPlanConverter implements ILanguageAssociation {
static readonly languages = ['sqlplan']; static readonly languages = ['sqlplan'];
constructor(@IInstantiationService private instantiationService: IInstantiationService) { } constructor(
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IEditorService private readonly editorService: IEditorService
) { }
convertInput(activeEditor: IEditorInput): QueryPlanInput { convertInput(activeEditor: IEditorInput): QueryPlanInput | undefined {
if (activeEditor.resource) {
return this.instantiationService.createInstance(QueryPlanInput, activeEditor.resource); return this.instantiationService.createInstance(QueryPlanInput, activeEditor.resource);
} }
return undefined;
}
createBase(activeEditor: QueryPlanInput): IEditorInput { createBase(activeEditor: QueryPlanInput): IEditorInput {
return undefined; return this.editorService.createEditorInput({ resource: activeEditor.resource });
} }
} }
@@ -30,8 +36,7 @@ export class QueryPlanInput extends EditorInput {
public static ID: string = 'workbench.editorinputs.queryplan'; public static ID: string = 'workbench.editorinputs.queryplan';
public static SCHEMA: string = 'queryplan'; public static SCHEMA: string = 'queryplan';
private _uniqueSelector: string; private _xml?: string;
private _xml: string;
constructor( constructor(
private _uri: URI, private _uri: URI,
@@ -40,10 +45,6 @@ export class QueryPlanInput extends EditorInput {
super(); super();
} }
public setUniqueSelector(uniqueSelector: string): void {
this._uniqueSelector = uniqueSelector;
}
public getTypeId(): string { public getTypeId(): string {
return UntitledTextEditorInput.ID; return UntitledTextEditorInput.ID;
} }
@@ -52,7 +53,7 @@ export class QueryPlanInput extends EditorInput {
return 'Query Plan'; return 'Query Plan';
} }
public get planXml(): string { public get planXml(): string | undefined {
return this._xml; return this._xml;
} }
@@ -64,24 +65,11 @@ export class QueryPlanInput extends EditorInput {
return false; return false;
} }
public getConnectionProfile(): IConnectionProfile { public async resolve(refresh?: boolean): Promise<EditorModel | null> {
//return this._connection.connectionProfile;
return undefined;
}
public async resolve(refresh?: boolean): Promise<EditorModel> {
if (!this._xml) { if (!this._xml) {
this._xml = (await this.fileService.readFile(this._uri)).value.toString(); this._xml = (await this.fileService.readFile(this._uri)).value.toString();
} }
return undefined; return null;
}
public get hasInitialized(): boolean {
return !!this._uniqueSelector;
}
public get uniqueSelector(): string {
return this._uniqueSelector;
} }
get resource(): URI | undefined { get resource(): URI | undefined {

View File

@@ -51,7 +51,6 @@
"./sql/workbench/contrib/profiler/**/*.ts", // 204 errors "./sql/workbench/contrib/profiler/**/*.ts", // 204 errors
"./sql/workbench/contrib/query/**/*.ts", // 3342 errors "./sql/workbench/contrib/query/**/*.ts", // 3342 errors
"./sql/workbench/contrib/queryHistory/**/*.ts", // 432 errors "./sql/workbench/contrib/queryHistory/**/*.ts", // 432 errors
"./sql/workbench/contrib/queryPlan/**/*.ts", // 52 errors
"./sql/workbench/contrib/restore/**/*.ts", // 142 errors "./sql/workbench/contrib/restore/**/*.ts", // 142 errors
"./sql/workbench/contrib/scripting/**/*.ts", // 280 errors "./sql/workbench/contrib/scripting/**/*.ts", // 280 errors
"./sql/workbench/contrib/tasks/**/*.ts", // 100 errors "./sql/workbench/contrib/tasks/**/*.ts", // 100 errors