From 6784a0bd27f8982b3bd539585f997206dbf6f7c1 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 6 Mar 2019 10:15:31 -0800 Subject: [PATCH] Strict null check settings files --- src/tsconfig.strictNullChecks.json | 2 + .../preferences/browser/settingsTree.ts | 55 ++++----- .../preferences/browser/settingsTreeModels.ts | 24 ++-- .../contrib/preferences/browser/tocTree.ts | 10 +- .../electron-browser/settingsEditor2.ts | 109 +++++++++++------- 5 files changed, 115 insertions(+), 85 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 47698340041..6ac1d410616 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -32,6 +32,8 @@ "./vs/workbench/services/timer/**/*.ts", "./vs/workbench/contrib/webview/**/*.ts", "./vs/workbench/contrib/debug/common/**/*.ts", + "./vs/workbench/contrib/preferences/common/**/*.ts", + "./vs/workbench/contrib/preferences/**/settings*.ts", ], "files": [ "./vs/monaco.d.ts", diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 8f1fabdf359..8211f695bbc 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -112,7 +112,7 @@ function _resolveSettingsTree(tocData: ITOCEntry, allSettings: Set): I } if (!children && !settings) { - return null; + throw new Error(`TOC node has no child groups or settings: ${tocData.id}`); } return { @@ -439,7 +439,7 @@ export abstract class AbstractSettingRenderer implements ITreeRenderer this._onDidChangeSetting.fire({ key: element.setting.key, value, type: template.context.valueType }); + const onChange = value => this._onDidChangeSetting.fire({ key: element.setting.key, value, type: template.context!.valueType }); template.deprecationWarningElement.innerText = element.setting.deprecationMessage || ''; this.renderValue(element, template, onChange); @@ -488,7 +488,7 @@ export abstract class AbstractSettingRenderer implements ITreeRenderertemplate.controlElement.firstElementChild) { itemElement.setAttribute('role', 'combobox'); label += modifiedText; } @@ -587,7 +587,7 @@ export class SettingNewExtensionsRenderer implements ITreeRenderer { if (template.context) { @@ -621,9 +621,9 @@ export class SettingComplexRenderer extends AbstractSettingRenderer implements I renderTemplate(container: HTMLElement): ISettingComplexItemTemplate { const common = this.renderCommonTemplate(null, container, 'complex'); - const openSettingsButton = new Button(common.controlElement, { title: true, buttonBackground: null, buttonHoverBackground: null }); + const openSettingsButton = new Button(common.controlElement, { title: true, buttonBackground: undefined, buttonHoverBackground: undefined }); common.toDispose.push(openSettingsButton); - common.toDispose.push(openSettingsButton.onDidClick(() => template.onChange(null))); + common.toDispose.push(openSettingsButton.onDidClick(() => template.onChange!())); openSettingsButton.label = localize('editInSettingsJson', "Edit in settings.json"); openSettingsButton.element.classList.add('edit-in-settings-button'); @@ -770,7 +770,7 @@ export class SettingTextRenderer extends AbstractSettingRenderer implements ITre protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingTextItemTemplate, onChange: (value: string) => void): void { const label = this.setElementAriaLabels(dataElement, SETTINGS_TEXT_TEMPLATE_ID, template); - template.onChange = null; + template.onChange = undefined; template.inputBox.value = dataElement.value; template.onChange = value => { renderValidations(dataElement, template, false, label); onChange(value); }; @@ -784,7 +784,7 @@ export class SettingEnumRenderer extends AbstractSettingRenderer implements ITre renderTemplate(container: HTMLElement): ISettingEnumItemTemplate { const common = this.renderCommonTemplate(null, container, 'enum'); - const selectBox = new SelectBox([], undefined, this._contextViewService, undefined, { useCustomDrawn: true }); + const selectBox = new SelectBox([], 0, this._contextViewService, undefined, { useCustomDrawn: true }); common.toDispose.push(selectBox); common.toDispose.push(attachSelectBoxStyler(selectBox, this._themeService, { @@ -827,7 +827,7 @@ export class SettingEnumRenderer extends AbstractSettingRenderer implements ITre const enumDescriptions = dataElement.setting.enumDescriptions; const enumDescriptionsAreMarkdown = dataElement.setting.enumDescriptionsAreMarkdown; - const displayOptions = dataElement.setting.enum + const displayOptions = dataElement.setting.enum! .map(String) .map(escapeInvisibleChars) .map((data, index) => { @@ -842,10 +842,10 @@ export class SettingEnumRenderer extends AbstractSettingRenderer implements ITre const label = this.setElementAriaLabels(dataElement, SETTINGS_ENUM_TEMPLATE_ID, template); template.selectBox.setAriaLabel(label); - const idx = dataElement.setting.enum.indexOf(dataElement.value); - template.onChange = null; + const idx = dataElement.setting.enum!.indexOf(dataElement.value); + template.onChange = undefined; template.selectBox.select(idx); - template.onChange = idx => onChange(dataElement.setting.enum[idx]); + template.onChange = idx => onChange(dataElement.setting.enum![idx]); template.enumDescriptionElement.innerHTML = ''; } @@ -889,7 +889,7 @@ export class SettingNumberRenderer extends AbstractSettingRenderer implements IT super.renderSettingElement(element, index, templateData); } - protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingNumberItemTemplate, onChange: (value: number) => void): void { + protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingNumberItemTemplate, onChange: (value: number | null) => void): void { const numParseFn = (dataElement.valueType === 'integer' || dataElement.valueType === 'nullable-integer') ? parseInt : parseFloat; @@ -898,9 +898,12 @@ export class SettingNumberRenderer extends AbstractSettingRenderer implements IT const label = this.setElementAriaLabels(dataElement, SETTINGS_NUMBER_TEMPLATE_ID, template); - template.onChange = null; + template.onChange = undefined; template.inputBox.value = dataElement.value; - template.onChange = value => { renderValidations(dataElement, template, false, label); onChange(nullNumParseFn(value)); }; + template.onChange = value => { + renderValidations(dataElement, template, false, label); + onChange(nullNumParseFn(value)); + }; renderValidations(dataElement, template, true, label); } @@ -930,7 +933,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre const deprecationWarningElement = DOM.append(container, $('.setting-item-deprecation-message')); const toDispose: IDisposable[] = []; - const checkbox = new Checkbox({ actionClassName: 'setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: null }); + const checkbox = new Checkbox({ actionClassName: 'setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: undefined }); controlElement.appendChild(checkbox.domNode); toDispose.push(checkbox); toDispose.push(checkbox.onChange(() => { @@ -949,7 +952,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre // Toggle target checkbox if (targetElement.tagName.toLowerCase() !== 'a' && targetId === template.checkbox.domNode.id) { template.checkbox.checked = template.checkbox.checked ? false : true; - template.onChange(checkbox.checked); + template.onChange!(checkbox.checked); } DOM.EventHelper.stop(e); })); @@ -993,7 +996,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre } protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingBoolItemTemplate, onChange: (value: boolean) => void): void { - template.onChange = null; + template.onChange = undefined; template.checkbox.checked = dataElement.value; template.onChange = onChange; @@ -1067,17 +1070,17 @@ export class SettingTreeRenderers { } showContextMenu(element: SettingsTreeSettingElement, settingDOMElement: HTMLElement): void { - const toolbarElement: HTMLElement = settingDOMElement.querySelector('.toolbar-toggle-more'); + const toolbarElement = settingDOMElement.querySelector('.toolbar-toggle-more'); if (toolbarElement) { this._contextMenuService.showContextMenu({ getActions: () => this.settingActions, - getAnchor: () => toolbarElement, + getAnchor: () => toolbarElement, getActionsContext: () => element }); } } - getSettingDOMElementForDOMElement(domElement: HTMLElement): HTMLElement { + getSettingDOMElementForDOMElement(domElement: HTMLElement): HTMLElement | null { const parent = DOM.findParentWithClass(domElement, AbstractSettingRenderer.CONTENTS_CLASS); if (parent) { return parent; @@ -1090,12 +1093,12 @@ export class SettingTreeRenderers { return treeContainer.querySelectorAll(`[${AbstractSettingRenderer.SETTING_KEY_ATTR}="${key}"]`); } - getKeyForDOMElementInSetting(element: HTMLElement): string { + getKeyForDOMElementInSetting(element: HTMLElement): string | null { const settingElement = this.getSettingDOMElementForDOMElement(element); return settingElement && settingElement.getAttribute(AbstractSettingRenderer.SETTING_KEY_ATTR); } - getIdForDOMElementInSetting(element: HTMLElement): string { + getIdForDOMElementInSetting(element: HTMLElement): string | null { const settingElement = this.getSettingDOMElementForDOMElement(element); return settingElement && settingElement.getAttribute(AbstractSettingRenderer.SETTING_ID_ATTR); } @@ -1108,11 +1111,11 @@ function renderValidations(dataElement: SettingsTreeSettingElement, template: IS DOM.addClass(template.containerElement, 'invalid-input'); template.validationErrorMessageElement.innerText = errMsg; const validationError = localize('validationError', "Validation Error."); - template.inputBox.inputElement.parentElement.setAttribute('aria-label', [originalAriaLabel, validationError, errMsg].join(' ')); + template.inputBox.inputElement.parentElement!.setAttribute('aria-label', [originalAriaLabel, validationError, errMsg].join(' ')); if (!calledOnStartup) { ariaAlert(validationError + ' ' + errMsg); } return; } else { - template.inputBox.inputElement.parentElement.setAttribute('aria-label', originalAriaLabel); + template.inputBox.inputElement.parentElement!.setAttribute('aria-label', originalAriaLabel); } } DOM.removeClass(template.containerElement, 'invalid-input'); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 879d9a9e49f..4e7f56b60d8 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -24,7 +24,7 @@ export interface ISettingsEditorViewState { export abstract class SettingsTreeElement { id: string; - parent: SettingsTreeGroupElement; + parent?: SettingsTreeGroupElement; /** * Index assigned in display order, used for paging. @@ -130,7 +130,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } private initLabel(): void { - const displayKeyFormat = settingKeyToDisplayFormat(this.setting.key, this.parent.id); + const displayKeyFormat = settingKeyToDisplayFormat(this.setting.key, this.parent!.id); this._displayLabel = displayKeyFormat.label; this._displayCategory = displayKeyFormat.category; } @@ -161,7 +161,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { } if (this.setting.tags) { - this.setting.tags.forEach(tag => this.tags.add(tag)); + this.setting.tags.forEach(tag => this.tags!.add(tag)); } } @@ -207,7 +207,7 @@ export class SettingsTreeSettingElement extends SettingsTreeElement { if (this.tags) { let hasFilteredTag = true; tagFilters.forEach(tag => { - hasFilteredTag = hasFilteredTag && this.tags.has(tag); + hasFilteredTag = hasFilteredTag && this.tags!.has(tag); }); return hasFilteredTag; } else { @@ -261,12 +261,12 @@ export class SettingsTreeModel { } } - getElementById(id: string): SettingsTreeElement { - return this._treeElementsById.get(id); + getElementById(id: string): SettingsTreeElement | null { + return this._treeElementsById.get(id) || null; } - getElementsByName(name: string): SettingsTreeSettingElement[] { - return this._treeElementsBySettingName.get(name); + getElementsByName(name: string): SettingsTreeSettingElement[] | null { + return this._treeElementsBySettingName.get(name) || null; } updateElementsByName(name: string): void { @@ -274,7 +274,7 @@ export class SettingsTreeModel { return; } - this._treeElementsBySettingName.get(name).forEach(element => { + this._treeElementsBySettingName.get(name)!.forEach(element => { const inspectResult = inspectSetting(element.setting.key, this._viewState.settingsTarget, this._configurationService); element.update(inspectResult); }); @@ -428,7 +428,7 @@ export const enum SearchResultIdx { export class SearchResultModel extends SettingsTreeModel { private rawSearchResults: ISearchResult[]; - private cachedUniqueSearchResults: ISearchResult[]; + private cachedUniqueSearchResults: ISearchResult[] | undefined; private newExtensionSearchResults: ISearchResult; readonly id = 'searchResultModel'; @@ -473,8 +473,8 @@ export class SearchResultModel extends SettingsTreeModel { return this.rawSearchResults; } - setResult(order: SearchResultIdx, result: ISearchResult): void { - this.cachedUniqueSearchResults = null; + setResult(order: SearchResultIdx, result: ISearchResult | null): void { + this.cachedUniqueSearchResults = undefined; this.rawSearchResults = this.rawSearchResults || []; if (!result) { delete this.rawSearchResults[order]; diff --git a/src/vs/workbench/contrib/preferences/browser/tocTree.ts b/src/vs/workbench/contrib/preferences/browser/tocTree.ts index 273471fdcfa..d3fdbdcc6f5 100644 --- a/src/vs/workbench/contrib/preferences/browser/tocTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/tocTree.ts @@ -22,7 +22,7 @@ const $ = DOM.$; export class TOCTreeModel { - private _currentSearchModel: SearchResultModel; + private _currentSearchModel: SearchResultModel | null; private _settingsTreeRoot: SettingsTreeGroupElement; constructor(private _viewState: ISettingsEditorViewState) { @@ -37,7 +37,11 @@ export class TOCTreeModel { this.update(); } - set currentSearchModel(model: SearchResultModel) { + get currentSearchModel(): SearchResultModel | null { + return this._currentSearchModel; + } + + set currentSearchModel(model: SearchResultModel | null) { this._currentSearchModel = model; this.update(); } @@ -61,7 +65,7 @@ export class TOCTreeModel { const childCount = group.children .filter(child => child instanceof SettingsTreeGroupElement) - .reduce((acc, cur) => acc + (cur).count, 0); + .reduce((acc, cur) => acc + (cur).count!, 0); group.count = childCount + this.getGroupCount(group); } diff --git a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts index efdfdce5654..8dccdbea88c 100644 --- a/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/electron-browser/settingsEditor2.ts @@ -107,14 +107,14 @@ export class SettingsEditor2 extends BaseEditor { private delayedFilterLogging: Delayer; private localSearchDelayer: Delayer; private remoteSearchThrottle: ThrottledDelayer; - private searchInProgress: CancellationTokenSource; + private searchInProgress: CancellationTokenSource | null; private settingFastUpdateDelayer: Delayer; private settingSlowUpdateDelayer: Delayer; - private pendingSettingUpdate: { key: string, value: any }; + private pendingSettingUpdate: { key: string, value: any } | null; private readonly viewState: ISettingsEditorViewState; - private _searchResultModel: SearchResultModel; + private _searchResultModel: SearchResultModel | null; private tocRowFocused: IContextKey; private inSettingsEditorContextKey: IContextKey; @@ -128,7 +128,7 @@ export class SettingsEditor2 extends BaseEditor { private editorMemento: IEditorMemento; - private tocFocusedElement: SettingsTreeGroupElement; + private tocFocusedElement: SettingsTreeGroupElement | null; private settingsTreeScrollTop = 0; constructor( @@ -180,18 +180,19 @@ export class SettingsEditor2 extends BaseEditor { return this.searchResultModel || this.settingsTreeModel; } - private get searchResultModel(): SearchResultModel { + private get searchResultModel(): SearchResultModel | null { return this._searchResultModel; } - private set searchResultModel(value: SearchResultModel) { + private set searchResultModel(value: SearchResultModel | null) { this._searchResultModel = value; DOM.toggleClass(this.rootElement, 'search-mode', !!this._searchResultModel); } - private get currentSettingsContextMenuKeyBindingLabel() { - return this.keybindingService.lookupKeybinding(SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU).getAriaLabel(); + private get currentSettingsContextMenuKeyBindingLabel(): string { + const keybinding = this.keybindingService.lookupKeybinding(SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU); + return (keybinding && keybinding.getAriaLabel()) || ''; } createEditor(parent: HTMLElement): void { @@ -233,7 +234,7 @@ export class SettingsEditor2 extends BaseEditor { } private restoreCachedState(): void { - const cachedState = this.editorMemento.loadEditorState(this.group, this.input); + const cachedState = this.group && this.input && this.editorMemento.loadEditorState(this.group, this.input); if (cachedState && typeof cachedState.target === 'object') { cachedState.target = URI.revive(cachedState.target); } @@ -268,7 +269,10 @@ export class SettingsEditor2 extends BaseEditor { clearInput(): void { this.inSettingsEditorContextKey.set(false); - this.editorMemento.clearEditorState(this.input, this.group); + if (this.input) { + this.editorMemento.clearEditorState(this.input, this.group); + } + super.clearInput(); } @@ -315,7 +319,12 @@ export class SettingsEditor2 extends BaseEditor { } showContextMenu(): void { - const settingDOMElement = this.settingRenderers.getSettingDOMElementForDOMElement(this.getActiveElementInSettingsTree()); + const activeElement = this.getActiveElementInSettingsTree(); + if (!activeElement) { + return; + } + + const settingDOMElement = this.settingRenderers.getSettingDOMElementForDOMElement(activeElement); if (!settingDOMElement) { return; } @@ -383,9 +392,10 @@ export class SettingsEditor2 extends BaseEditor { this._register(attachStylerCallback(this.themeService, { badgeBackground, contrastBorder, badgeForeground }, colors => { const background = colors.badgeBackground ? colors.badgeBackground.toString() : null; const border = colors.contrastBorder ? colors.contrastBorder.toString() : null; + const foreground = colors.badgeForeground ? colors.badgeForeground.toString() : null; this.countElement.style.backgroundColor = background; - this.countElement.style.color = colors.badgeForeground.toString(); + this.countElement.style.color = foreground; this.countElement.style.borderWidth = border ? '1px' : null; this.countElement.style.borderStyle = border ? 'solid' : null; @@ -412,6 +422,10 @@ export class SettingsEditor2 extends BaseEditor { const elements = this.currentSettingsModel.getElementsByName(evt.targetKey); if (elements && elements[0]) { let sourceTop = this.settingsTree.getRelativeTop(evt.source); + if (typeof sourceTop !== 'number') { + return; + } + if (sourceTop < 0) { // e.g. clicked a searched element, now the search has been cleared sourceTop = 0.5; @@ -435,12 +449,12 @@ export class SettingsEditor2 extends BaseEditor { } } - switchToSettingsFile(): Promise { + switchToSettingsFile(): Promise { const query = parseQuery(this.searchWidget.getValue()); return this.openSettingsFile(query.query); } - private openSettingsFile(query?: string): Promise { + private openSettingsFile(query?: string): Promise { const currentSettingsTarget = this.settingsTargetsWidget.settingsTarget; const options: ISettingsEditorOptions = { query }; @@ -550,7 +564,7 @@ export class SettingsEditor2 extends BaseEditor { this.viewState)); this._register(this.tocTree.onDidChangeFocus(e => { - const element: SettingsTreeGroupElement = e.elements[0]; + const element: SettingsTreeGroupElement | null = e.elements[0]; if (this.tocFocusedElement === element) { return; } @@ -559,7 +573,7 @@ export class SettingsEditor2 extends BaseEditor { this.tocTree.setSelection(element ? [element] : []); if (this.searchResultModel) { if (this.viewState.filterToCategory !== element) { - this.viewState.filterToCategory = element; + this.viewState.filterToCategory = element || undefined; this.renderTree(); this.settingsTree.scrollTop = 0; } @@ -672,6 +686,10 @@ export class SettingsEditor2 extends BaseEditor { this.tocTree.reveal(element); const elementTop = this.tocTree.getRelativeTop(element); + if (typeof elementTop !== 'number') { + return; + } + this.tocTree.collapseAll(); ancestors.forEach(e => this.tocTree.expand(e)); @@ -738,17 +756,17 @@ export class SettingsEditor2 extends BaseEditor { }); } - private reportModifiedSetting(props: { key: string, query: string, searchResults: ISearchResult[], rawResults: ISearchResult[], showConfiguredOnly: boolean, isReset: boolean, settingsTarget: SettingsTarget }): void { + private reportModifiedSetting(props: { key: string, query: string, searchResults: ISearchResult[] | null, rawResults: ISearchResult[] | null, showConfiguredOnly: boolean, isReset: boolean, settingsTarget: SettingsTarget }): void { this.pendingSettingUpdate = null; - const remoteResult = props.searchResults && props.searchResults[SearchResultIdx.Remote]; - const localResult = props.searchResults && props.searchResults[SearchResultIdx.Local]; - - let groupId = undefined; - let nlpIndex = undefined; - let displayIndex = undefined; + let groupId: string | undefined = undefined; + let nlpIndex: number | undefined = undefined; + let displayIndex: number | undefined = undefined; if (props.searchResults) { - const localIndex = arrays.firstIndex(localResult.filterMatches, m => m.setting.key === props.key); + const remoteResult = props.searchResults[SearchResultIdx.Remote]; + const localResult = props.searchResults[SearchResultIdx.Local]; + + const localIndex = arrays.firstIndex(localResult!.filterMatches, m => m.setting.key === props.key); groupId = localIndex >= 0 ? 'local' : 'remote'; @@ -860,9 +878,9 @@ export class SettingsEditor2 extends BaseEditor { } const commonlyUsed = resolveSettingsTree(commonlyUsedData, dividedGroups.core); - resolvedSettingsRoot.children.unshift(commonlyUsed.tree); + resolvedSettingsRoot.children!.unshift(commonlyUsed.tree); - resolvedSettingsRoot.children.push(resolveExtensionsSettings(dividedGroups.extension || [])); + resolvedSettingsRoot.children!.push(resolveExtensionsSettings(dividedGroups.extension || [])); if (this.searchResultModel) { this.searchResultModel.updateChildren(); @@ -872,7 +890,7 @@ export class SettingsEditor2 extends BaseEditor { this.settingsTreeModel.update(resolvedSettingsRoot); // Make sure that all extensions' settings are included in search results - const cachedState = this.editorMemento.loadEditorState(this.group, this.input); + const cachedState = this.group && this.input && this.editorMemento.loadEditorState(this.group, this.input); if (cachedState && cachedState.searchQuery) { this.triggerSearch(cachedState.searchQuery); } else { @@ -895,7 +913,7 @@ export class SettingsEditor2 extends BaseEditor { private updateElementsByKey(keys: string[]): Promise { if (keys.length) { if (this.searchResultModel) { - keys.forEach(key => this.searchResultModel.updateElementsByName(key)); + keys.forEach(key => this.searchResultModel!.updateElementsByName(key)); } if (this.settingsTreeModel) { @@ -923,7 +941,8 @@ export class SettingsEditor2 extends BaseEditor { } // If a setting control is currently focused, schedule a refresh for later - const focusedSetting = this.settingRenderers.getSettingDOMElementForDOMElement(this.getActiveElementInSettingsTree()); + const activeElement = this.getActiveElementInSettingsTree(); + const focusedSetting = activeElement && this.settingRenderers.getSettingDOMElementForDOMElement(activeElement); if (focusedSetting && !force) { // If a single setting is being refreshed, it's ok to refresh now if that is not the focused setting if (key) { @@ -978,7 +997,7 @@ export class SettingsEditor2 extends BaseEditor { const isModified = dataElements && dataElements[0] && dataElements[0].isConfigured; // all elements are either configured or not const elements = this.settingRenderers.getDOMElementsForSettingKey(this.settingsTree.getHTMLElement(), key); if (elements && elements[0]) { - DOM.toggleClass(elements[0], 'is-configured', isModified); + DOM.toggleClass(elements[0], 'is-configured', !!isModified); } } @@ -987,12 +1006,12 @@ export class SettingsEditor2 extends BaseEditor { this.delayedFilterLogging.cancel(); this.triggerSearch(query.replace(/›/g, ' ')).then(() => { if (query && this.searchResultModel) { - this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(query, this.searchResultModel.getUniqueResults())); + this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(query, this.searchResultModel!.getUniqueResults())); } }); } - private parseSettingFromJSON(query: string): string { + private parseSettingFromJSON(query: string): string | null { const match = query.match(/"([a-zA-Z.]+)": /); return match && match[1]; } @@ -1002,7 +1021,7 @@ export class SettingsEditor2 extends BaseEditor { if (query) { const parsedQuery = parseQuery(query); query = parsedQuery.query; - parsedQuery.tags.forEach(tag => this.viewState.tagFilters.add(tag)); + parsedQuery.tags.forEach(tag => this.viewState.tagFilters!.add(tag)); } if (query && query !== '@') { @@ -1023,7 +1042,7 @@ export class SettingsEditor2 extends BaseEditor { this.searchInProgress = null; } - this.viewState.filterToCategory = null; + this.viewState.filterToCategory = undefined; this.tocTreeModel.currentSearchModel = this.searchResultModel; this.onSearchModeToggled(); @@ -1043,7 +1062,7 @@ export class SettingsEditor2 extends BaseEditor { this.refreshTOCTree(); } - return Promise.resolve(null); + return Promise.resolve(); } /** @@ -1121,18 +1140,18 @@ export class SettingsEditor2 extends BaseEditor { if (result && !result.exactMatch) { this.remoteSearchThrottle.trigger(() => { return searchInProgress && !searchInProgress.token.isCancellationRequested ? - this.remoteSearchPreferences(query, this.searchInProgress.token) : - Promise.resolve(null); + this.remoteSearchPreferences(query, this.searchInProgress!.token) : + Promise.resolve(); }); } }); } else { - return Promise.resolve(null); + return Promise.resolve(); } }); } - private localFilterPreferences(query: string, token?: CancellationToken): Promise { + private localFilterPreferences(query: string, token?: CancellationToken): Promise { const localSearchProvider = this.preferencesSearchService.getLocalSearchProvider(query); return this.filterOrSearchPreferences(query, SearchResultIdx.Local, localSearchProvider, token); } @@ -1147,7 +1166,7 @@ export class SettingsEditor2 extends BaseEditor { ]).then(() => { }); } - private filterOrSearchPreferences(query: string, type: SearchResultIdx, searchProvider: ISearchProvider, token?: CancellationToken): Promise { + private filterOrSearchPreferences(query: string, type: SearchResultIdx, searchProvider?: ISearchProvider, token?: CancellationToken): Promise { return this._filterOrSearchPreferencesModel(query, this.defaultSettingsEditorModel, searchProvider, token).then(result => { if (token && token.isCancellationRequested) { // Handle cancellation like this because cancellation is lost inside the search provider due to async/await @@ -1165,7 +1184,7 @@ export class SettingsEditor2 extends BaseEditor { } this.tocTree.setSelection([]); - this.viewState.filterToCategory = null; + this.viewState.filterToCategory = undefined; this.tocTree.expandAll(); return this.renderTree(undefined, true).then(() => result); @@ -1193,7 +1212,7 @@ export class SettingsEditor2 extends BaseEditor { } } - private _filterOrSearchPreferencesModel(filter: string, model: ISettingsEditorModel, provider: ISearchProvider, token?: CancellationToken): Promise { + private _filterOrSearchPreferencesModel(filter: string, model: ISettingsEditorModel, provider?: ISearchProvider, token?: CancellationToken): Promise { const searchP = provider ? provider.searchModel(model, token) : Promise.resolve(null); return searchP .then(null, err => { @@ -1212,7 +1231,7 @@ export class SettingsEditor2 extends BaseEditor { this.telemetryService.publicLog('settingsEditor.searchError', { message, filter }); this.logService.info('Setting search error: ' + message); } - return null; + return Promise.resolve(null); } }); } @@ -1232,7 +1251,9 @@ export class SettingsEditor2 extends BaseEditor { if (this.isVisible()) { const searchQuery = this.searchWidget.getValue().trim(); const target = this.settingsTargetsWidget.settingsTarget as SettingsTarget; - this.editorMemento.saveEditorState(this.group, this.input, { searchQuery, target }); + if (this.group && this.input) { + this.editorMemento.saveEditorState(this.group, this.input, { searchQuery, target }); + } } super.saveState(); -- GitLab