Strict null pass on some base ui files (#4832)

* more strict null checks in base browser code

* revert changes to radiobutton

* fix some more minor things, enable strict null check in pipelines

* formatting

* fix compile errors

* make null undefined

* more null to undefined
This commit is contained in:
Anthony Dresser
2019-04-03 16:18:33 -07:00
committed by GitHub
parent 80a8e1a4da
commit cef5bbb2be
25 changed files with 253 additions and 234 deletions

View File

@@ -41,5 +41,9 @@ steps:
condition: succeededOrFailed()
- script: |
yarn run tslint
yarn tslint
displayName: 'Run TSLint'
- script: |
yarn strict-null-check
displayName: 'Run Strict Null Check'

View File

@@ -26,5 +26,9 @@ steps:
condition: succeededOrFailed()
- script: |
yarn run tslint
yarn tslint
displayName: 'Run TSLint'
- script: |
yarn strict-null-check
displayName: 'Run Strict Null Check'

View File

@@ -98,7 +98,7 @@ export class DropdownList extends Dropdown {
* Render the selected label of the dropdown
*/
public renderLabel(): void {
if (this._options.labelRenderer) {
if (this._options.labelRenderer && this.label) {
this._options.labelRenderer(this.label);
}
}

View File

@@ -298,7 +298,7 @@ export class Dropdown extends Disposable {
this.$treeContainer.style('outline', `1px solid ${style.contextBorder || this._options.contextBorder}`);
}
private _inputValidator(value: string): IMessage {
private _inputValidator(value: string): IMessage | null {
if (this._dataSource.options && !this._dataSource.options.find(i => i.value === value)) {
if (this._options.strictSelection && this._options.errorMessage) {
return {
@@ -313,7 +313,7 @@ export class Dropdown extends Disposable {
}
}
return undefined;
return null;
}
public set enabled(val: boolean) {

View File

@@ -91,7 +91,7 @@ export class DropdownDataSource implements tree.IDataSource {
export class DropdownFilter extends TreeDefaults.DefaultFilter {
public filterString: string;
public isVisible(tree: tree.ITree, element: Resource): boolean {
public isVisible(tree: tree.ITree | undefined, element: Resource): boolean {
return element.value.toLowerCase().includes(this.filterString.toLowerCase());
}
}

View File

@@ -141,51 +141,54 @@ export class PanelComponent extends Disposable {
* Select a tab based on index (unrecommended)
* @param index index of tab in the html
*/
selectTab(index: number);
selectTab(index: number): void;
/**
* Select a tab based on the identifier that was passed into the tab
* @param identifier specified identifer of the tab
*/
selectTab(identifier: string);
selectTab(identifier: string): void;
/**
* Select a tab directly if you have access to the object
* @param tab tab to navigate to
*/
selectTab(tab: TabComponent);
selectTab(input: TabComponent | number | string) {
selectTab(tab: TabComponent): void;
selectTab(input: TabComponent | number | string): void {
if (this._tabs && this._tabs.length > 0) {
let tab: TabComponent;
let foundTab: TabComponent | undefined;
if (input instanceof TabComponent) {
tab = input;
foundTab = input;
} else if (types.isNumber(input)) {
tab = this._tabs.toArray()[input];
foundTab = this._tabs.toArray()[input];
} else if (types.isString(input)) {
tab = this._tabs.find(i => i.identifier === input);
foundTab = this._tabs.find(i => i.identifier === input);
}
// since we need to compare identifiers in this next step we are going to go through and make sure all tabs have one
this._tabs.forEach(i => {
if (!i.identifier) {
i.identifier = 'tabIndex_' + idPool++;
}
});
if (foundTab) {
const tab = foundTab;
// since we need to compare identifiers in this next step we are going to go through and make sure all tabs have one
this._tabs.forEach(i => {
if (!i.identifier) {
i.identifier = 'tabIndex_' + idPool++;
}
});
if (this._activeTab && tab === this._activeTab) {
this.onTabChange.emit(tab);
return;
if (this._activeTab && tab === this._activeTab) {
this.onTabChange.emit(tab);
return;
}
this._zone.run(() => {
if (this._activeTab) {
this._activeTab.active = false;
}
this._activeTab = tab;
this.setMostRecentlyUsed(tab);
this._activeTab.active = true;
this.onTabChange.emit(tab);
});
}
this._zone.run(() => {
if (this._activeTab) {
this._activeTab.active = false;
}
this._activeTab = tab;
this.setMostRecentlyUsed(tab);
this._activeTab.active = true;
this.onTabChange.emit(tab);
});
}
}

View File

@@ -47,7 +47,7 @@ export type PanelTabIdentifier = string;
export class TabbedPanel extends Disposable implements IThemable {
private _tabMap = new Map<PanelTabIdentifier, IInternalPanelTab>();
private _shownTab: PanelTabIdentifier;
private _shownTabId?: PanelTabIdentifier;
public readonly headersize = 35;
private header: HTMLElement;
private tabList: HTMLElement;
@@ -103,7 +103,7 @@ export class TabbedPanel extends Disposable implements IThemable {
internalTab.disposables = [];
this._tabMap.set(tab.identifier, internalTab);
this._createTab(internalTab);
if (!this._shownTab) {
if (!this._shownTabId) {
this.showTab(tab.identifier);
}
if (this._tabMap.size > 1 && !this._headerVisible) {
@@ -147,24 +147,23 @@ export class TabbedPanel extends Disposable implements IThemable {
}
public showTab(id: PanelTabIdentifier): void {
if (this._shownTab && this._shownTab === id) {
if (this._shownTabId === id || !this._tabMap.has(id)) {
return;
}
if (this._shownTab) {
DOM.removeClass(this._tabMap.get(this._shownTab).label, 'active');
DOM.removeClass(this._tabMap.get(this._shownTab).header, 'active');
this._tabMap.get(this._shownTab).header.setAttribute('aria-selected', 'false');
if (this._shownTabId) {
const shownTab = this._tabMap.get(this._shownTabId);
if (shownTab) {
DOM.removeClass(shownTab.label, 'active');
DOM.removeClass(shownTab.header, 'active');
shownTab.header.setAttribute('aria-selected', 'false');
shownTab.body.remove();
}
}
let prevTab = this._tabMap.get(this._shownTab);
if (prevTab) {
prevTab.body.remove();
}
this._shownTab = id;
this._shownTabId = id;
this.tabHistory.push(id);
let tab = this._tabMap.get(this._shownTab);
const tab = this._tabMap.get(this._shownTabId)!; // @anthonydresser we know this can't be undefined since we check further up if the map contains the id
if (!tab.body) {
tab.body = DOM.$('.tab-container');
tab.body.style.width = '100%';
@@ -183,7 +182,10 @@ export class TabbedPanel extends Disposable implements IThemable {
}
public removeTab(tab: PanelTabIdentifier) {
let actualTab = this._tabMap.get(tab);
const actualTab = this._tabMap.get(tab);
if (!actualTab) {
return;
}
if (actualTab.view && actualTab.view.remove) {
actualTab.view.remove();
}
@@ -195,12 +197,14 @@ export class TabbedPanel extends Disposable implements IThemable {
}
dispose(actualTab.disposables);
this._tabMap.delete(tab);
if (this._shownTab === tab) {
this._shownTab = undefined;
while (this._shownTab === undefined && this.tabHistory.length > 0) {
if (this._shownTabId === tab) {
this._shownTabId = undefined;
while (this._shownTabId === undefined && this.tabHistory.length > 0) {
let lastTab = this.tabHistory.shift();
if (this._tabMap.get(lastTab)) {
this.showTab(lastTab);
if (lastTab) {
if (this._tabMap.get(lastTab)) {
this.showTab(lastTab);
}
}
}
}
@@ -230,11 +234,13 @@ export class TabbedPanel extends Disposable implements IThemable {
}
private _layoutCurrentTab(dimension: DOM.Dimension): void {
if (this._shownTab) {
let tab = this._tabMap.get(this._shownTab);
tab.body.style.width = dimension.width + 'px';
tab.body.style.height = dimension.height + 'px';
tab.view.layout(dimension);
if (this._shownTabId) {
const tab = this._tabMap.get(this._shownTabId);
if (tab) {
tab.body.style.width = dimension.width + 'px';
tab.body.style.height = dimension.height + 'px';
tab.view.layout(dimension);
}
}
}

View File

@@ -21,7 +21,7 @@ export abstract class TabChild extends Disposable {
})
export class TabComponent implements OnDestroy {
private _child: TabChild;
@ContentChild(TemplateRef) templateRef;
@ContentChild(TemplateRef) templateRef: TemplateRef<any>;
@Input() public title: string;
@Input() public canClose: boolean;
@Input() public actions: Array<Action>;
@@ -32,8 +32,7 @@ export class TabComponent implements OnDestroy {
private rendered = false;
private destroyed: boolean = false;
@ContentChild(TabChild) private set child(tab: TabChild) {
@ContentChild(TabChild) public set child(tab: TabChild) {
this._child = tab;
if (this.active && this._child) {
this._child.layout();

View File

@@ -3,13 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as DOM from 'vs/base/browser/dom';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { Color } from 'vs/base/common/color';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { Event, Emitter } from 'vs/base/common/event';
import { Widget } from 'vs/base/browser/ui/widget';
import { withNullAsUndefined } from 'vs/base/common/types';
export interface IRadioButtonOptions {
label: string;
@@ -43,20 +39,24 @@ export class RadioButton extends Widget {
container.appendChild(this._label);
}
public set name(value: string) {
this.inputElement.setAttribute('name', value);
public set name(value: string | undefined) {
if (value) {
this.inputElement.setAttribute('name', value);
}
}
public get name(): string {
return this.inputElement.getAttribute('name');
public get name(): string | undefined {
return withNullAsUndefined(this.inputElement.getAttribute('name'));
}
public set value(value: string) {
this.inputElement.setAttribute('value', value);
public set value(value: string | undefined) {
if (value) {
this.inputElement.setAttribute('value', value);
}
}
public get value(): string {
return this.inputElement.getAttribute('value');
public get value(): string | undefined {
return withNullAsUndefined(this.inputElement.getAttribute('value'));
}
public set checked(val: boolean) {
@@ -83,4 +83,4 @@ export class RadioButton extends Widget {
this._label.innerText = val;
}
}
}

View File

@@ -30,7 +30,7 @@ export class ScrollableDirective extends AngularDisposable {
ngOnInit() {
this.scrolled = this._el.nativeElement as HTMLElement;
this.parent = this.scrolled.parentElement;
this.parent = this.scrolled.parentElement!;
const next = this.scrolled.nextSibling;
this.parent.removeChild(this.scrolled);

View File

@@ -31,8 +31,8 @@ export class HeightMap {
return !last ? 0 : last.top + last.height;
}
public onInsertItems(iterator: INextIterator<IViewItem>, afterItemId: string = null): number {
let viewItem: IViewItem;
public onInsertItems(iterator: INextIterator<IViewItem>, afterItemId: string | undefined = undefined): number | undefined {
let viewItem: IViewItem | undefined = undefined;
let i: number, j: number;
let totalSize: number;
let sizeDiff = 0;
@@ -89,10 +89,10 @@ export class HeightMap {
// Contiguous items
public onRemoveItems(iterator: INextIterator<string>): void {
let itemId: string;
let itemId: string | undefined = undefined;
let viewItem: IViewItem;
let startIndex: number = null;
let i: number;
let startIndex: number | undefined = undefined;
let i = 0;
let sizeDiff = 0;
while (itemId = iterator.next()) {
@@ -108,12 +108,12 @@ export class HeightMap {
delete this.indexes[itemId];
this.onRemoveItem(viewItem);
if (startIndex === null) {
if (startIndex === undefined) {
startIndex = i;
}
}
if (sizeDiff === 0) {
if (sizeDiff === 0 || startIndex === undefined) {
return;
}

View File

@@ -275,7 +275,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
// Add sash
if (this.options.enableResizing && this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) };
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: (sash: Sash) => this.getSashPosition(sash) } : { getVerticalSashLeft: (sash: Sash) => this.getSashPosition(sash) };
const sash = new Sash(this.sashContainer, layoutProvider, {
orientation,
orthogonalStartSash: this.orthogonalStartSash,
@@ -321,8 +321,8 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
// this isn't actually scrolling up or down
let scrollTop = this.lastRenderTop;
let viewHeight = this.lastRenderHeight;
this.lastRenderTop = undefined;
this.lastRenderHeight = undefined;
this.lastRenderTop = 0;
this.lastRenderHeight = 0;
this.render(scrollTop, viewHeight);
}
@@ -378,7 +378,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
// Add sash
if (this.options.enableResizing && this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) };
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: (sash: Sash) => this.getSashPosition(sash) } : { getVerticalSashLeft: (sash: Sash) => this.getSashPosition(sash) };
const sash = new Sash(this.sashContainer, layoutProvider, {
orientation,
orthogonalStartSash: this.orthogonalStartSash,
@@ -502,8 +502,8 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
const previousSize = Math.max(this.size, this.contentSize);
this.size = size;
this.contentSize = 0;
this.lastRenderHeight = undefined;
this.lastRenderTop = undefined;
this.lastRenderHeight = 0;
this.lastRenderTop = 0;
if (!this.proportions) {
this.resize(this.viewItems.length - 1, size - previousSize);
@@ -734,14 +734,14 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
return false;
}
let elementAfter: HTMLElement = null;
let elementAfter: HTMLElement | undefined = undefined;
let itemAfter = <IViewItem>this.itemAfter(item);
if (itemAfter && itemAfter.container) {
elementAfter = itemAfter.container;
}
if (elementAfter === null) {
if (elementAfter === undefined) {
this.viewContainer.appendChild(item.container);
} else {
try {

View File

@@ -11,7 +11,7 @@ import { Color } from 'vs/base/common/color';
import { IContextViewProvider, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import * as dom from 'vs/base/browser/dom';
import { RenderOptions, renderFormattedText, renderText } from 'vs/base/browser/htmlContentRenderer';
import { IMessage, MessageType, defaultOpts } from 'vs/base/browser/ui/inputbox/inputBox';
import { IMessage, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import aria = require('vs/base/browser/ui/aria/aria');
import nls = require('vs/nls');
@@ -22,40 +22,51 @@ export interface ISelectBoxStyles extends vsISelectBoxStyles {
disabledSelectForeground?: Color;
inputValidationInfoBorder?: Color;
inputValidationInfoBackground?: Color;
inputinputValidationInfoForeground?: Color;
inputValidationWarningBorder?: Color;
inputValidationWarningBackground?: Color;
inputValidationWarningForeground?: Color;
inputValidationErrorBorder?: Color;
inputValidationErrorBackground?: Color;
inputValidationErrorForeground?: Color;
}
export class SelectBox extends vsSelectBox {
private _optionsDictionary;
private _optionsDictionary: Map<string, number>;
private _dialogOptions: string[];
private _selectedOption: string;
private _selectBoxOptions: ISelectBoxOptions;
private enabledSelectBackground: Color;
private enabledSelectForeground: Color;
private enabledSelectBorder: Color;
private disabledSelectBackground: Color;
private disabledSelectForeground: Color;
private disabledSelectBorder: Color;
private _selectBoxOptions?: ISelectBoxOptions;
private enabledSelectBackground?: Color;
private enabledSelectForeground?: Color;
private enabledSelectBorder?: Color;
private disabledSelectBackground?: Color;
private disabledSelectForeground?: Color;
private disabledSelectBorder?: Color;
private contextViewProvider: IContextViewProvider;
private message: IMessage;
private inputValidationInfoBorder: Color;
private inputValidationInfoBackground: Color;
private inputValidationWarningBorder: Color;
private inputValidationWarningBackground: Color;
private inputValidationErrorBorder: Color;
private inputValidationErrorBackground: Color;
private message?: IMessage;
private inputValidationInfoBorder?: Color;
private inputValidationInfoBackground?: Color;
private inputValidationInfoForeground?: Color;
private inputValidationWarningBorder?: Color;
private inputValidationWarningBackground?: Color;
private inputValidationWarningForeground?: Color;
private inputValidationErrorBorder?: Color;
private inputValidationErrorBackground?: Color;
private inputValidationErrorForeground?: Color;
private element: HTMLElement;
constructor(options: string[], selectedOption: string, contextViewProvider: IContextViewProvider, container?: HTMLElement, selectBoxOptions?: ISelectBoxOptions) {
super(options.map(option => { return { text: option }; }), 0, contextViewProvider, undefined, selectBoxOptions);
this._optionsDictionary = new Array();
for (var i = 0; i < options.length; i++) {
this._optionsDictionary[options[i]] = i;
this._optionsDictionary = new Map<string, number>();
for (let i = 0; i < options.length; i++) {
this._optionsDictionary.set(options[i], i);
}
const option = this._optionsDictionary.get(selectedOption);
if (option) {
super.select(option);
}
super.select(this._optionsDictionary[selectedOption]);
this._selectedOption = selectedOption;
this._dialogOptions = options;
this._register(this.onDidSelect(newInput => {
@@ -66,8 +77,8 @@ export class SelectBox extends vsSelectBox {
this.enabledSelectForeground = this.selectForeground;
this.enabledSelectBorder = this.selectBorder;
this.disabledSelectBackground = Color.transparent;
this.disabledSelectForeground = null;
this.disabledSelectBorder = null;
this.disabledSelectForeground = undefined;
this.disabledSelectBorder = undefined;
this.contextViewProvider = contextViewProvider;
if (container) {
this.element = dom.append(container, $('.monaco-selectbox.idle'));
@@ -77,7 +88,7 @@ export class SelectBox extends vsSelectBox {
this.selectElement.setAttribute('role', 'combobox');
this._selectBoxOptions = selectBoxOptions;
var focusTracker = dom.trackFocus(this.selectElement);
let focusTracker = dom.trackFocus(this.selectElement);
this._register(focusTracker);
this._register(focusTracker.onDidBlur(() => this._hideMessage()));
this._register(focusTracker.onDidFocus(() => this._showMessage()));
@@ -92,16 +103,20 @@ export class SelectBox extends vsSelectBox {
this.disabledSelectForeground = styles.disabledSelectForeground;
this.inputValidationInfoBorder = styles.inputValidationInfoBorder;
this.inputValidationInfoBackground = styles.inputValidationInfoBackground;
this.inputValidationInfoForeground = styles.inputinputValidationInfoForeground;
this.inputValidationWarningBorder = styles.inputValidationWarningBorder;
this.inputValidationWarningBackground = styles.inputValidationWarningBackground;
this.inputValidationWarningForeground = styles.inputValidationWarningForeground;
this.inputValidationErrorBorder = styles.inputValidationErrorBorder;
this.inputValidationErrorBackground = styles.inputValidationErrorBackground;
this.inputValidationErrorForeground = styles.inputValidationErrorForeground;
this.applyStyles();
}
public selectWithOptionName(optionName: string): void {
if (this._optionsDictionary[optionName]) {
this.select(this._optionsDictionary[optionName]);
const option = this._optionsDictionary.get(optionName);
if (option) {
this.select(option);
} else {
this.select(0);
}
@@ -121,9 +136,9 @@ export class SelectBox extends vsSelectBox {
} else {
stringOptions = options as string[];
}
this._optionsDictionary = [];
for (var i = 0; i < stringOptions.length; i++) {
this._optionsDictionary[stringOptions[i]] = i;
this._optionsDictionary = new Map<string, number>();
for (let i = 0; i < stringOptions.length; i++) {
this._optionsDictionary.set(stringOptions[i], i);
}
this._dialogOptions = stringOptions;
super.setOptions(stringOptions.map(option => { return { text: option }; }), selected);
@@ -187,6 +202,7 @@ export class SelectBox extends vsSelectBox {
public _showMessage(): void {
if (this.message && this.contextViewProvider && this.element) {
const message = this.message;
let div: HTMLElement;
let layout = () => div.style.width = dom.getTotalWidth(this.selectElement) + 'px';
@@ -202,12 +218,12 @@ export class SelectBox extends vsSelectBox {
className: 'monaco-inputbox-message'
};
let spanElement: HTMLElement = (this.message.formatContent
? renderFormattedText(this.message.content, renderOptions)
: renderText(this.message.content, renderOptions)) as any;
dom.addClass(spanElement, this.classForType(this.message.type));
let spanElement: HTMLElement = (message.formatContent
? renderFormattedText(message.content, renderOptions)
: renderText(message.content, renderOptions)) as any;
dom.addClass(spanElement, this.classForType(message.type));
const styles = this.stylesForType(this.message.type);
const styles = this.stylesForType(message.type);
spanElement.style.backgroundColor = styles.background ? styles.background.toString() : null;
spanElement.style.border = styles.border ? `1px solid ${styles.border}` : null;
@@ -229,7 +245,7 @@ export class SelectBox extends vsSelectBox {
this._hideMessage();
this.applyStyles();
this.message = null;
this.message = undefined;
}
private _hideMessage(): void {
@@ -238,7 +254,7 @@ export class SelectBox extends vsSelectBox {
}
}
private classForType(type: MessageType): string {
private classForType(type: MessageType | undefined): string {
switch (type) {
case MessageType.INFO: return 'info';
case MessageType.WARNING: return 'warning';
@@ -246,11 +262,11 @@ export class SelectBox extends vsSelectBox {
}
}
private stylesForType(type: MessageType): { border: Color; background: Color } {
private stylesForType(type: MessageType | undefined): { border: Color | undefined; background: Color | undefined; foreground: Color | undefined } {
switch (type) {
case MessageType.INFO: return { border: this.inputValidationInfoBorder, background: this.inputValidationInfoBackground };
case MessageType.WARNING: return { border: this.inputValidationWarningBorder, background: this.inputValidationWarningBackground };
default: return { border: this.inputValidationErrorBorder, background: this.inputValidationErrorBackground };
case MessageType.INFO: return { border: this.inputValidationInfoBorder, background: this.inputValidationInfoBackground, foreground: this.inputValidationInfoForeground };
case MessageType.WARNING: return { border: this.inputValidationWarningBorder, background: this.inputValidationWarningBackground, foreground: this.inputValidationWarningForeground };
default: return { border: this.inputValidationErrorBorder, background: this.inputValidationErrorBackground, foreground: this.inputValidationErrorForeground };
}
}

View File

@@ -16,7 +16,7 @@ export interface IObservableCollection<T> {
}
class DataWindow<T> {
private _data: T[];
private _data: T[] | undefined;
private _length: number = 0;
private _offsetFromDataSource: number = -1;
@@ -30,9 +30,6 @@ class DataWindow<T> {
dispose() {
this._data = undefined;
this.loadFunction = undefined;
this.placeholderItemGenerator = undefined;
this.loadCompleteCallback = undefined;
this.cancellationToken.cancel();
}
@@ -157,7 +154,7 @@ export class VirtualizedCollection<T extends Slick.SlickData> implements IObserv
}
private getRangeFromCurrent(start: number, end: number): T[] {
let currentData = [];
const currentData: Array<T> = [];
for (let i = 0; i < end - start; i++) {
currentData.push(this.getDataFromCurrent(start + i));
}

View File

@@ -21,7 +21,7 @@ export interface ITableStyles extends IListStyles {
}
export interface ITableSorter<T> {
sort(args: Slick.OnSortEventArgs<T>);
(args: Slick.OnSortEventArgs<T>): void;
}
export interface ITableConfiguration<T> {

View File

@@ -6,7 +6,6 @@
import 'vs/css!./media/table';
import { TableDataView } from './tableDataView';
import { IDisposableDataProvider, ITableSorter, ITableMouseEvent, ITableConfiguration, ITableStyles } from 'sql/base/browser/ui/table/interfaces';
import { $ } from 'sql/base/browser/builder';
import { IThemable } from 'vs/platform/theme/common/styler';
import * as DOM from 'vs/base/browser/dom';
@@ -94,7 +93,7 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
if (configuration && configuration.sorter) {
this._sorter = configuration.sorter;
this._grid.onSort.subscribe((e, args) => {
this._sorter.sort(args);
this._sorter(args);
this._grid.invalidate();
this._grid.render();
});
@@ -121,7 +120,7 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
}
public dispose() {
$(this._container).dispose();
this._container.remove();
super.dispose();
}
@@ -146,9 +145,9 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
return this._grid;
}
setData(data: Array<T>);
setData(data: TableDataView<T>);
setData(data: Array<T> | TableDataView<T>) {
setData(data: Array<T>): void;
setData(data: TableDataView<T>): void;
setData(data: Array<T> | TableDataView<T>): void {
if (data instanceof TableDataView) {
this._data = data;
} else {

View File

@@ -16,22 +16,27 @@ export interface IFindPosition {
row: number;
}
function defaultSort<T>(args: Slick.OnSortEventArgs<T>, data: Array<T>): Array<T> {
let field = args.sortCol.field;
let sign = args.sortAsc ? 1 : -1;
let comparer: (a, b) => number;
function defaultSort<T extends { [key: string]: any }>(args: Slick.OnSortEventArgs<T>, data: Array<T>): Array<T> {
if (!args.sortCol || !args.sortCol.field) {
return data;
}
const field = args.sortCol.field;
const sign = args.sortAsc ? 1 : -1;
let comparer: (a: T, b: T) => number;
if (types.isString(data[0][field])) {
if (Number(data[0][field]) !== NaN) {
comparer = (a: number, b: number) => {
comparer = (a: T, b: T) => {
let anum = Number(a[field]);
let bnum = Number(b[field]);
return anum === bnum ? 0 : anum > bnum ? 1 : -1;
};
} else {
comparer = stringCompare;
comparer = (a: T, b: T) => {
return stringCompare(a[field], b[field]);
};
}
} else {
comparer = (a: number, b: number) => {
comparer = (a: T, b: T) => {
return a[field] === b[field] ? 0 : (a[field] > b[field] ? 1 : -1);
};
}
@@ -44,7 +49,7 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
//Used when filtering is enabled, _allData holds the complete set of data.
private _allData: Array<T>;
private _findArray: Array<IFindPosition>;
private _findObs: Observable<IFindPosition>;
private _findObs: Observable<IFindPosition> | undefined;
private _findIndex: number;
private _filterEnabled: boolean;
@@ -57,11 +62,14 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
private _onFilterStateChange = new Emitter<void>();
get onFilterStateChange(): Event<void> { return this._onFilterStateChange.event; }
private _filterFn: (data: Array<T>) => Array<T>;
private _sortFn: (args: Slick.OnSortEventArgs<T>, data: Array<T>) => Array<T>;
constructor(
data?: Array<T>,
private _findFn?: (val: T, exp: string) => Array<number>,
private _sortFn?: (args: Slick.OnSortEventArgs<T>, data: Array<T>) => Array<T>,
private _filterFn?: (data: Array<T>) => Array<T>
_sortFn?: (args: Slick.OnSortEventArgs<T>, data: Array<T>) => Array<T>,
_filterFn?: (data: Array<T>) => Array<T>
) {
if (data) {
this._data = data;
@@ -69,13 +77,9 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
this._data = new Array<T>();
}
if (!_sortFn) {
this._sortFn = defaultSort;
}
this._sortFn = _sortFn ? _sortFn : defaultSort;
if (!_filterFn) {
this._filterFn = (dataToFilter) => dataToFilter;
}
this._filterFn = _filterFn ? _filterFn : (dataToFilter) => dataToFilter;
this._filterEnabled = false;
}
@@ -119,9 +123,9 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
return this.filterEnabled ? this._allData.length : this._data.length;
}
push(items: Array<T>);
push(item: T);
push(input: T | Array<T>) {
push(items: Array<T>): void;
push(item: T): void;
push(input: T | Array<T>): void {
let inputArray = new Array();
if (Array.isArray(input)) {
inputArray.push(...input);
@@ -161,7 +165,7 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
this._findObs = Observable.create((observer: Observer<IFindPosition>) => {
for (let i = 0; i < this._data.length; i++) {
let item = this._data[i];
let result = this._findFn(item, exp);
let result = this._findFn!(item, exp);
if (result) {
result.forEach(pos => {
let index = { col: pos, row: i };
@@ -175,7 +179,7 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
}
}
});
return this._findObs.take(1).toPromise().then(() => {
return this._findObs!.take(1).toPromise().then(() => {
return this._findArray[this._findIndex];
});
} else {
@@ -234,9 +238,9 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
}
dispose() {
this._data = undefined;
this._allData = undefined;
this._findArray = undefined;
this._data = [];
this._allData = [];
this._findArray = [];
this._findObs = undefined;
}
}

View File

@@ -3,13 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!vs/base/browser/ui/actionbar/actionbar';
import { Builder, $ } from 'sql/base/browser/builder';
import { IAction, IActionRunner, ActionRunner } from 'vs/base/common/actions';
import { EventEmitter } from 'sql/base/common/eventEmitter';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import {

View File

@@ -80,12 +80,10 @@ export class ProfilerTableEditor extends BaseEditor implements IProfilerControll
parent.appendChild(this._overlay);
this._profilerTable = new Table(parent, {
sorter: {
sort: (args) => {
let input = this.input as ProfilerInput;
if (input && input.data) {
input.data.sort(args);
}
sorter: (args) => {
let input = this.input as ProfilerInput;
if (input && input.data) {
input.data.sort(args);
}
}
}, {

View File

@@ -70,10 +70,8 @@ export class TopOperationsView implements IPanelView {
this.table = new Table(this.container, {
columns: topOperationColumns,
dataProvider: this.dataView,
sorter: {
sort: (args) => {
this.dataView.sort(args);
}
sorter: (args) => {
this.dataView.sort(args);
}
});
this.disposables.push(this.table);

View File

@@ -0,0 +1,26 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"noEmit": true,
"strictNullChecks": true,
"moduleResolution": "classic"
},
"include": [
"./typings",
"./vs/**.*.ts",
"./sql/base/browser/ui/breadcrumb/*.ts",
"./sql/base/browser/ui/button/*.ts",
"./sql/base/browser/ui/checkbox/*.ts",
"./sql/base/browser/ui/dropdownList/*.ts",
"./sql/base/browser/ui/inputBox/*.ts",
"./sql/base/browser/ui/listBox/*.ts",
"./sql/base/browser/ui/panel/*.ts",
"./sql/base/browser/ui/radioButton/*.ts",
"./sql/base/browser/ui/scrollable/*.ts",
"./sql/base/browser/ui/selectBox/*.ts",
"./sql/base/browser/ui/table/*.ts",
],
"exclude": [
"node_modules/**"
]
}

View File

@@ -1,35 +0,0 @@
{
"extends": "./tsconfig.strictNullChecks.json",
"include": [
"./typings",
"./vs/base/browser/**/*.ts",
"./vs/base/common/**/*.ts",
"./vs/base/node/**/*.ts",
"./vs/editor/browser/**/*.ts",
"./vs/editor/common/**/*.ts",
"./vs/editor/contrib/codeAction/**/*.ts",
"./vs/editor/contrib/format/**/*.ts",
"./vs/editor/contrib/gotoError/**/*.ts",
"./vs/editor/contrib/inPlaceReplace/**/*.ts",
"./vs/editor/contrib/smartSelect/**/*.ts",
"./vs/editor/contrib/snippet/**/*.ts",
"./vs/editor/contrib/suggest/**/*.ts",
"./vs/editor/test/**/*.ts",
"./sql/base/common/**/*ts",
],
"files": [
// "./sql/base/browser/ui/breadcrumb/breadcrumb.component.ts", // pulls in angular which gives extrenous errors
// "./sql/base/browser/ui/breadcrumb/interfaces.ts", // pulls in angular which gives extrenous errors
"./sql/base/browser/ui/button/button.ts",
"./sql/base/browser/ui/checkbox/checkbox.ts",
// "./sql/base/browser/ui/checkbox/checkbox.component.ts", // pulls in angular which gives extrenous errors
// "./sql/base/browser/ui/dropdownList/dropdownList.ts", // skipping since vscode hasn't checked their dropdown yet
// "./sql/base/browser/ui/editableDropdown/actions.ts", // skipping since vscode hasn't checked their dropdown yet and it isn't in the right place anyways
// "./sql/base/browser/ui/editableDropdown/dropdown.ts", // skipping since vscode hasn't checked their dropdown yet and it isn't in the right place anyways
// "./sql/base/browser/ui/editableDropdown/dropdownTree.ts", // skipping since vscode hasn't checked their dropdown yet and it isn't in the right place anyways
// "./sql/base/browser/ui/editableDropdown/editableDropdown.component.ts", // skipping since vscode hasn't checked their dropdown yet and it isn't in the right place anyways
// "./sql/base/browser/ui/inputBox/inputBox.component.ts", // pulls in angular which gives extrenous errors
// "./sql/base/browser/ui/inputBox/inputBox.ts", // skipping since vscode hasn't checked their inputbox yet
// "./sql/base/browser/ui/listBox/listBox.ts",
]
}

View File

@@ -5469,7 +5469,7 @@ export interface IterableChanges<V> {
* original `Iterable` location, where as `currentIndex` refers to the transient location
* of the item, after applying the operations up to this point.
*/
forEachOperation(fn: (record: IterableChangeRecord<V>, previousIndex: number, currentIndex: number) => void): void;
forEachOperation(fn: (record: IterableChangeRecord<V>, previousIndex: number | null, currentIndex: number | null) => void): void;
/**
* Iterate over changes in the order of original `Iterable` showing where the original items
* have moved.

View File

@@ -74,9 +74,9 @@ export interface ISelectData {
export class SelectBox extends Widget implements ISelectBoxDelegate {
// {{SQL CARBON EDIT}}
protected selectElement: HTMLSelectElement;
protected selectBackground: Color;
protected selectForeground: Color;
protected selectBorder: Color;
protected selectBackground?: Color;
protected selectForeground?: Color;
protected selectBorder?: Color;
private styles: ISelectBoxStyles;
private selectBoxDelegate: ISelectBoxDelegate;
@@ -137,14 +137,15 @@ export class SelectBox extends Widget implements ISelectBoxDelegate {
public applyStyles(): void {
this.selectBoxDelegate.applyStyles();
}
// {{SQL CARBON EDIT}}
protected createOption(value: string, disabled?: boolean): HTMLOptionElement {
let option = document.createElement('option');
option.value = value;
option.text = value;
option.disabled = disabled;
option.disabled = disabled || false;
return option;
}
}
}

View File

@@ -20,6 +20,9 @@ import { ISelectBoxDelegate, ISelectOptionItem, ISelectBoxOptions, ISelectBoxSty
import { isMacintosh } from 'vs/base/common/platform';
import { renderMarkdown } from 'vs/base/browser/htmlContentRenderer';
// {{SQL CARBON EDIT}} import color
import { Color } from 'vs/base/common/color';
const $ = dom.$;
const SELECT_OPTION_ENTRY_TEMPLATE_ID = 'selectOption.entry.template';
@@ -372,23 +375,22 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate<I
// Style parent select
// {{SQL CARBON EDIT}}
let background = null;
let foreground = null;
let border = null;
let background: Color | undefined = undefined;
let foreground: Color | undefined = undefined;
let border: Color | undefined = undefined;
if (this.selectElement) {
if (this.selectElement.disabled) {
background = (<any>this.styles).disabledSelectBackground ? (<any>this.styles).disabledSelectBackground.toString() : null;
foreground = (<any>this.styles).disabledSelectForeground ? (<any>this.styles).disabledSelectForeground.toString() : null;
border = null;
background = (<any>this.styles).disabledSelectBackground;
foreground = (<any>this.styles).disabledSelectForeground;
} else {
background = this.styles.selectBackground ? this.styles.selectBackground.toString() : null;
foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : null;
border = this.styles.selectBorder ? this.styles.selectBorder.toString() : null;
background = this.styles.selectBackground;
foreground = this.styles.selectForeground;
border = this.styles.selectBorder;
}
this.selectElement.style.backgroundColor = background;
this.selectElement.style.color = foreground;
this.selectElement.style.borderColor = border;
this.selectElement.style.backgroundColor = background ? background.toString() : null;
this.selectElement.style.color = foreground ? foreground.toString() : null;
this.selectElement.style.borderColor = border ? border.toString() : null;
}
// Style drop down select list (non-native mode only)