Add strict compiling for profiler service (#11898)

* add strict compiling for profiler

* fix up strict

* add contrib
This commit is contained in:
Anthony Dresser
2020-08-21 12:52:24 -07:00
committed by GitHub
parent 31323d6efb
commit 1b02fb6906
11 changed files with 248 additions and 163 deletions

View File

@@ -27,19 +27,19 @@ export interface IProfilerSession {
/**
* Called by the service when more rows are available to render
*/
onMoreRows(events: azdata.ProfilerSessionEvents);
onMoreRows(events: azdata.ProfilerSessionEvents): void;
/**
* Called by the service when the session is closed unexpectedly
*/
onSessionStopped(events: azdata.ProfilerSessionStoppedParams);
onSessionStopped(events: azdata.ProfilerSessionStoppedParams): void;
/**
* Called by the service when a new profiler session is created by the dialog
*/
onProfilerSessionCreated(events: azdata.ProfilerSessionCreatedParams);
onProfilerSessionCreated(events: azdata.ProfilerSessionCreatedParams): void;
/**
* Called by the service when the session state is changed
*/
onSessionStateChanged(newState: INewProfilerState);
onSessionStateChanged(newState: INewProfilerState): void;
}
/**
@@ -83,7 +83,7 @@ export interface IProfilerService {
/**
* Gets a list of running XEvent sessions on the Profiler Session's target
*/
getXEventSessions(sessionId: ProfilerSessionID): Thenable<string[]>;
getXEventSessions(sessionId: ProfilerSessionID): Promise<string[] | undefined>;
/**
* The method called by the service provider for when more rows are available to render
*/
@@ -95,7 +95,7 @@ export interface IProfilerService {
/**
* Called by the service when a new profiler session is created by the dialog
*/
onProfilerSessionCreated(events: azdata.ProfilerSessionCreatedParams);
onProfilerSessionCreated(events: azdata.ProfilerSessionCreatedParams): void;
/**
* Gets a list of the view templates that are specified in the settings
* @param provider An optional string to limit the view templates to a specific provider

View File

@@ -33,11 +33,8 @@ class EventItem {
constructor(
private _name: string,
private _parent: SessionItem,
private _columns?: Array<ColumnItem>,
private _columns: Array<ColumnItem> = new Array<ColumnItem>(),
) {
if (!_columns) {
this._columns = new Array<ColumnItem>();
}
}
public hasChildren(): boolean {
@@ -74,7 +71,7 @@ class EventItem {
}
class ColumnItem {
public selected: boolean;
public selected?: boolean;
public readonly indeterminate = false;
constructor(
private _name: string,
@@ -131,19 +128,15 @@ class SessionItem {
constructor(
private _name: string,
private _sort: 'event' | 'column',
private _events?: Array<EventItem>
private _events: Array<EventItem> = new Array<EventItem>()
) {
if (!_events) {
this._events = new Array<EventItem>();
} else {
_events.forEach(e => {
e.getChildren().forEach(c => {
if (!this._sortedColumnItems.some(i => i.id === c.id)) {
this._sortedColumnItems.push(new ColumnSortedColumnItem(c.id, this));
}
});
this._events.forEach(e => {
e.getChildren().forEach(c => {
if (!this._sortedColumnItems.some(i => i.id === c.id)) {
this._sortedColumnItems.push(new ColumnSortedColumnItem(c.id, this));
}
});
}
});
}
public get id(): string {
@@ -152,9 +145,9 @@ class SessionItem {
public hasChildren(): boolean {
if (this._sort === 'event') {
return this._events && this._events.length > 0;
return !!this._events && this._events.length > 0;
} else {
return this._events && this._events.some(i => i.hasChildren());
return !!this._events && this._events.some(i => i.hasChildren());
}
}
@@ -202,10 +195,8 @@ class TreeRenderer implements IRenderer {
return 'event';
} else if (element instanceof ColumnItem) {
return 'column';
} else if (element instanceof ColumnSortedColumnItem) {
return 'columnSorted';
} else {
return undefined;
return 'columnSorted';
}
}
@@ -253,12 +244,8 @@ class TreeDataSource implements IDataSource {
return element.parent.id + element.id;
} else if (element instanceof ColumnItem) {
return element.parent.parent.id + element.parent.id + element.id;
} else if (element instanceof SessionItem) {
return element.id;
} else if (element instanceof ColumnSortedColumnItem) {
return element.id;
} else {
return undefined;
return element.id;
}
}
@@ -268,7 +255,7 @@ class TreeDataSource implements IDataSource {
} else if (element instanceof EventItem) {
return element.hasChildren();
} else {
return undefined;
return false;
}
}
@@ -278,7 +265,7 @@ class TreeDataSource implements IDataSource {
} else if (element instanceof SessionItem) {
return Promise.resolve(element.getChildren());
} else {
return Promise.resolve(null);
return Promise.resolve([]);
}
}
@@ -301,14 +288,14 @@ class TreeDataSource implements IDataSource {
export class ProfilerColumnEditorDialog extends Modal {
private _selectBox: SelectBox;
private _selectBox?: SelectBox;
private readonly _options = [
{ text: nls.localize('eventSort', "Sort by event") },
{ text: nls.localize('nameColumn', "Sort by column") }
];
private _tree: Tree;
private _element: SessionItem;
private _treeContainer: HTMLElement;
private _tree?: Tree;
private _element?: SessionItem;
private _treeContainer?: HTMLElement;
constructor(
@ILayoutService layoutService: ILayoutService,
@@ -335,22 +322,22 @@ export class ProfilerColumnEditorDialog extends Modal {
this._selectBox = new SelectBox(this._options, 0, this._contextViewService);
this._selectBox.render(body);
this._register(this._selectBox.onDidSelect(e => {
this._element.changeSort(e.index === 0 ? 'event' : 'column');
this._tree.refresh(this._element, true);
this._element!.changeSort(e.index === 0 ? 'event' : 'column');
this._tree!.refresh(this._element!, true);
}));
this._treeContainer = DOM.append(body, DOM.$('.profiler-column-tree'));
const renderer = new TreeRenderer();
this._tree = new Tree(this._treeContainer, { dataSource: new TreeDataSource(), renderer });
this._register(renderer.onSelectedChange(e => this._tree.refresh(e, true)));
this._register(renderer.onSelectedChange(e => this._tree!.refresh(e, true)));
this._register(attachListStyler(this._tree, this._themeService));
}
public open(input: ProfilerInput): void {
public open(_input?: ProfilerInput): void {
super.show();
this._updateList();
}
protected onAccept(e: StandardKeyboardEvent): void {
protected onAccept(e?: StandardKeyboardEvent): void {
this._updateInput();
super.onAccept(e);
}
@@ -408,7 +395,9 @@ export class ProfilerColumnEditorDialog extends Modal {
}
protected layout(height?: number): void {
this._tree.layout(DOM.getContentHeight(this._treeContainer));
if (this._tree) {
this._tree.layout(DOM.getContentHeight(this._treeContainer!));
}
}
}

View File

@@ -68,7 +68,7 @@ function matches(item: any, clauses: ProfilerFilterClause[]): boolean {
match = actualValue !== undefined && actualValue !== null && actualValue !== '';
break;
case ProfilerFilterClauseOperator.Contains:
match = actualValueString && actualValueString.indexOf(expectedValueString) > -1;
match = !!actualValueString && actualValueString.indexOf(expectedValueString) > -1;
break;
case ProfilerFilterClauseOperator.NotContains:
match = !actualValueString || !(actualValueString.indexOf(expectedValueString) > -1);

View File

@@ -63,13 +63,13 @@ const Operators = [Equals, NotEquals, LessThan, LessThanOrEquals, GreaterThan, G
export class ProfilerFilterDialog extends Modal {
private _clauseBuilder: HTMLElement;
private _okButton: Button;
private _cancelButton: Button;
private _applyButton: Button;
private _loadFilterButton: Button;
private _saveFilterButton: Button;
private _input: ProfilerInput;
private _clauseBuilder?: HTMLElement;
private _okButton?: Button;
private _cancelButton?: Button;
private _applyButton?: Button;
private _loadFilterButton?: Button;
private _saveFilterButton?: Button;
private _input?: ProfilerInput;
private _clauseRows: ClauseRowUI[] = [];
@@ -80,7 +80,7 @@ export class ProfilerFilterDialog extends Modal {
@IAdsTelemetryService telemetryService: IAdsTelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@ILogService logService: ILogService,
@IContextViewService private contextViewService: IContextViewService,
@IContextViewService private readonly contextViewService: IContextViewService,
@IProfilerService private profilerService: IProfilerService,
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService
) {
@@ -91,7 +91,7 @@ export class ProfilerFilterDialog extends Modal {
this._input = input;
this.render();
this.show();
this._okButton.focus();
this._okButton!.focus();
}
public dispose(): void {
@@ -125,7 +125,7 @@ export class ProfilerFilterDialog extends Modal {
DOM.append(headerRow, DOM.$('td')).innerText = ValueText;
DOM.append(headerRow, DOM.$('td')).innerText = '';
this._input.filter.clauses.forEach(clause => {
this._input!.filter.clauses.forEach(clause => {
this.addClauseRow(true, clause.field, this.convertToOperatorString(clause.operator), clause.value);
});
@@ -182,7 +182,7 @@ export class ProfilerFilterDialog extends Modal {
}
private filterSession(): void {
this._input.filterSession(this.getFilter());
this._input!.filterSession(this.getFilter());
}
private saveFilter(): void {
@@ -222,19 +222,19 @@ export class ProfilerFilterDialog extends Modal {
}
private addClauseRow(setInitialValue: boolean, field?: string, operator?: string, value?: string): void {
const columns = this._input.columns.map(column => column.name);
const columns = this._input!.columns.map(column => column.name);
if (field && !find(columns, x => x === field)) {
return;
}
const row = DOM.append(this._clauseBuilder, DOM.$('tr'));
const row = DOM.append(this._clauseBuilder!, DOM.$('tr'));
const clauseId = generateUuid();
const fieldDropDown = this.createSelectBox(DOM.append(row, DOM.$('td')), columns, columns[0], FieldText);
const operatorDropDown = this.createSelectBox(DOM.append(row, DOM.$('td')), Operators, Operators[0], OperatorText);
const valueText = new InputBox(DOM.append(row, DOM.$('td')), undefined, {});
const valueText = new InputBox(DOM.append(row, DOM.$('td')), this.contextViewService, {});
this._register(attachInputBoxStyler(valueText, this._themeService));
const removeCell = DOM.append(row, DOM.$('td'));
@@ -259,7 +259,7 @@ export class ProfilerFilterDialog extends Modal {
if (setInitialValue) {
fieldDropDown.selectWithOptionName(field);
operatorDropDown.selectWithOptionName(operator);
valueText.value = value;
valueText.value = value ?? '';
}
this._clauseRows.push({

View File

@@ -29,11 +29,19 @@ class TwoWayMap<T, K> {
this.reverseMap = new Map<K, T>();
}
get(input: T): K {
has(input: T): boolean {
return this.forwardMap.has(input);
}
reverseHas(input: K): boolean {
return this.reverseMap.has(input);
}
get(input: T): K | undefined {
return this.forwardMap.get(input);
}
reverseGet(input: K): T {
reverseGet(input: K): T | undefined {
return this.reverseMap.get(input);
}
@@ -51,7 +59,7 @@ export class ProfilerService implements IProfilerService {
private _idMap = new TwoWayMap<ProfilerSessionID, string>();
private _sessionMap = new Map<ProfilerSessionID, IProfilerSession>();
private _connectionMap = new Map<ProfilerSessionID, IConnectionProfile>();
private _editColumnDialog: ProfilerColumnEditorDialog;
private _editColumnDialog?: ProfilerColumnEditorDialog;
private _memento: any;
private _context: Memento;
@@ -91,67 +99,100 @@ export class ProfilerService implements IProfilerService {
}
public onMoreRows(params: azdata.ProfilerSessionEvents): void {
this._sessionMap.get(this._idMap.reverseGet(params.sessionId)).onMoreRows(params);
if (this._idMap.reverseHas(params.sessionId)) {
this._sessionMap.get(this._idMap.reverseGet(params.sessionId)!)!.onMoreRows(params);
}
}
public onSessionStopped(params: azdata.ProfilerSessionStoppedParams): void {
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)).onSessionStopped(params);
if (this._idMap.reverseHas(params.ownerUri)) {
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)!)!.onSessionStopped(params);
}
}
public onProfilerSessionCreated(params: azdata.ProfilerSessionCreatedParams): void {
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)).onProfilerSessionCreated(params);
this.updateMemento(params.ownerUri, { previousSessionName: params.sessionName });
if (this._idMap.reverseHas(params.ownerUri)) {
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)!)!.onProfilerSessionCreated(params);
this.updateMemento(params.ownerUri, { previousSessionName: params.sessionName });
}
}
public connectSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)));
public async connectSession(id: ProfilerSessionID): Promise<boolean> {
if (this._idMap.has(id)) {
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)!));
}
return false;
}
public disconnectSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.disconnectSession(this._idMap.get(id)));
public async disconnectSession(id: ProfilerSessionID): Promise<boolean> {
if (this._idMap.has(id)) {
return this._runAction(id, provider => provider.disconnectSession(this._idMap.get(id)!));
}
return false;
}
public createSession(id: string, createStatement: string, template: azdata.ProfilerSessionTemplate): Thenable<boolean> {
return this._runAction(id, provider => provider.createSession(this._idMap.get(id), createStatement, template)).then(() => {
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
return true;
}, (reason) => {
this._notificationService.error(reason.message);
});
public async createSession(id: string, createStatement: string, template: azdata.ProfilerSessionTemplate): Promise<boolean> {
if (this._idMap.has(id)) {
try {
await this._runAction(id, provider => provider.createSession(this._idMap.get(id)!, createStatement, template));
this._sessionMap.get(this._idMap.reverseGet(id)!)!.onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
return true;
} catch (reason) {
this._notificationService.error(reason.message);
return false;
}
}
return false;
}
public startSession(id: ProfilerSessionID, sessionName: string): Thenable<boolean> {
this.updateMemento(id, { previousSessionName: sessionName });
return this._runAction(id, provider => provider.startSession(this._idMap.get(id), sessionName)).then(() => {
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
return true;
}, (reason) => {
this._notificationService.error(reason.message);
});
public async startSession(id: ProfilerSessionID, sessionName: string): Promise<boolean> {
if (this._idMap.has(id)) {
this.updateMemento(id, { previousSessionName: sessionName });
try {
await this._runAction(id, provider => provider.startSession(this._idMap.get(id)!, sessionName));
this._sessionMap.get(this._idMap.reverseGet(id)!)!.onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
return true;
} catch (reason) {
this._notificationService.error(reason.message);
return false;
}
}
return false;
}
public pauseSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.pauseSession(this._idMap.get(id)));
public async pauseSession(id: ProfilerSessionID): Promise<boolean> {
if (this._idMap.has(id)) {
return this._runAction(id, provider => provider.pauseSession(this._idMap.get(id)!));
} else {
return false;
}
}
public stopSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.stopSession(this._idMap.get(id))).then(() => {
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
return true;
}, (reason) => {
// The error won't be actionable to the user, so only log it to console.
// In case of error, the state of the UI is not usable, makes more sense to
// set it to stopped so that user can restart it or pick a different session
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
});
public async stopSession(id: ProfilerSessionID): Promise<boolean> {
if (this._idMap.has(id)) {
try {
await this._runAction(id, provider => provider.stopSession(this._idMap.get(id)!));
this._sessionMap.get(this._idMap.reverseGet(id)!)!.onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
return true;
} catch (e) {
this._sessionMap.get(this._idMap.reverseGet(id)!)!.onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
return false;
}
} else {
return false;
}
}
public getXEventSessions(id: ProfilerSessionID): Thenable<string[]> {
return this._runAction(id, provider => provider.getXEventSessions(this._idMap.get(id))).then((r) => {
return r;
}, (reason) => {
this._notificationService.error(reason.message);
});
public async getXEventSessions(id: ProfilerSessionID): Promise<string[] | undefined> {
if (this._idMap.get(id)) {
return this._runAction(id, provider => provider.getXEventSessions(this._idMap.get(id)!)).then((r) => {
return r;
}, (reason) => {
this._notificationService.error(reason.message);
return undefined;
});
}
return undefined;
}
private _runAction<T>(id: ProfilerSessionID, action: (handler: azdata.ProfilerProvider) => Thenable<T>): Thenable<T> {
@@ -192,9 +233,9 @@ export class ProfilerService implements IProfilerService {
return undefined;
}
private getMementoKey(ownerUri: string): string {
private getMementoKey(ownerUri: string): string | undefined {
let mementoKey = undefined;
let connectionProfile: IConnectionProfile = this._connectionMap.get(ownerUri);
let connectionProfile = this._connectionMap.get(ownerUri);
if (connectionProfile) {
mementoKey = connectionProfile.serverName;
}
@@ -219,7 +260,7 @@ export class ProfilerService implements IProfilerService {
}
this._editColumnDialog.open(input);
return Promise.resolve(null);
return Promise.resolve();
}
public launchCreateSessionDialog(input: ProfilerInput): Thenable<void> {