Skip to content

Commit

Permalink
Simplify type checking for objects
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew committed Nov 3, 2022
1 parent 5b2999e commit edddeff
Show file tree
Hide file tree
Showing 76 changed files with 325 additions and 269 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
import { SelectionService } from '@theia/core/lib/common/selection-service';
import { SelectionCommandHandler } from '@theia/core/lib/common/selection-command-handler';
import { ResourceFileEdit, ResourceTextEdit } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
import { Is } from '@theia/core/lib/common/is';

export interface BulkEditNodeSelection {
bulkEdit: ResourceFileEdit | ResourceTextEdit;
}
export namespace BulkEditNodeSelection {
export function is(arg: unknown): arg is BulkEditNodeSelection {
return !!arg && typeof arg === 'object' && ('bulkEdit' in arg);
return Is.object(arg) && 'bulkEdit' in arg;
}

export class CommandHandler extends SelectionCommandHandler<BulkEditNodeSelection> {
Expand Down
1 change: 1 addition & 0 deletions packages/core/shared/reflect-metadata/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from 'reflect-metadata';
1 change: 1 addition & 0 deletions packages/core/shared/reflect-metadata/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('reflect-metadata');
4 changes: 2 additions & 2 deletions packages/core/src/browser/frontend-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// *****************************************************************************

import { inject, injectable, named } from 'inversify';
import { ContributionProvider, CommandRegistry, MenuModelRegistry, isOSX, BackendStopwatch, LogLevel, Stopwatch } from '../common';
import { ContributionProvider, CommandRegistry, MenuModelRegistry, isOSX, BackendStopwatch, LogLevel, Stopwatch, Is } from '../common';
import { MaybePromise } from '../common/types';
import { KeybindingRegistry } from './keybinding';
import { Widget } from './widgets';
Expand Down Expand Up @@ -101,7 +101,7 @@ export interface OnWillStopAction<T = unknown> {

export namespace OnWillStopAction {
export function is(candidate: unknown): candidate is OnWillStopAction {
return typeof candidate === 'object' && !!candidate && 'action' in candidate && 'reason' in candidate;
return Is.object(candidate) && 'action' in candidate && 'reason' in candidate;
}
}

Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/browser/label-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable } from 'inversify';
import { Is } from '../common/is';

export interface LabelIcon {
name: string;
animation?: string;
}

export namespace LabelIcon {
export function is(val: object): val is LabelIcon {
return 'name' in val;
export function is(val: unknown): val is LabelIcon {
return Is.object<LabelIcon>(val) && Is.string(val.name);
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/browser/label-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as fileIcons from 'file-icons-js';
import URI from '../common/uri';
import { ContributionProvider } from '../common/contribution-provider';
import { Prioritizeable } from '../common/types';
import { Event, Emitter, Disposable, Path } from '../common';
import { Event, Emitter, Disposable, Path, Is } from '../common';
import { FrontendApplicationContribution } from './frontend-application';
import { EnvVariablesServer } from '../common/env-variables/env-variables-protocol';
import { ResourceLabelFormatter, ResourceLabelFormatting } from '../common/label-protocol';
Expand Down Expand Up @@ -99,7 +99,7 @@ export interface URIIconReference {
}
export namespace URIIconReference {
export function is(element: unknown): element is URIIconReference {
return !!element && typeof element === 'object' && 'kind' in element && (element as URIIconReference).kind === 'uriIconReference';
return Is.object(element) && element.kind === 'uriIconReference';
}
export function create(id: URIIconReference['id'], uri?: URI): URIIconReference {
return { kind: 'uriIconReference', id, uri };
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/browser/navigatable-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import URI from '../common/uri';
import { MaybeArray } from '../common/types';
import { Widget, BaseWidget } from './widgets';
import { Is } from '../common/is';

/**
* `Navigatable` provides an access to an URI of an underlying instance of `Resource`.
Expand All @@ -34,7 +35,7 @@ export interface Navigatable {

export namespace Navigatable {
export function is(arg: unknown): arg is Navigatable {
return !!arg && typeof arg === 'object' && 'getResourceUri' in arg && 'createMoveToUri' in arg;
return Is.object(arg) && 'getResourceUri' in arg && 'createMoveToUri' in arg;
}
}

Expand Down Expand Up @@ -71,12 +72,12 @@ export namespace NavigatableWidget {
}

export interface NavigatableWidgetOptions {
kind: 'navigatable',
uri: string,
counter?: number,
kind: 'navigatable';
uri: string;
counter?: number;
}
export namespace NavigatableWidgetOptions {
export function is(arg: unknown): arg is NavigatableWidgetOptions {
return !!arg && typeof arg === 'object' && 'kind' in arg && (arg as NavigatableWidgetOptions).kind === 'navigatable';
return Is.object(arg) && arg.kind === 'navigatable';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { inject, injectable, postConstruct } from 'inversify';
import { PreferenceSchema } from '../../common/preferences/preference-schema';
import { Disposable, DisposableCollection, Emitter, Event, MaybePromise } from '../../common';
import { Disposable, DisposableCollection, Emitter, Event, Is, MaybePromise } from '../../common';
import { PreferenceChangeEvent, PreferenceEventEmitter, PreferenceProxy, PreferenceProxyOptions, PreferenceRetrieval } from './preference-proxy';
import { PreferenceChange, PreferenceChangeImpl, PreferenceChanges, PreferenceScope, PreferenceService } from './preference-service';
import { JSONValue } from '@phosphor/coreutils';
Expand Down Expand Up @@ -103,7 +103,9 @@ export class InjectablePreferenceProxy<T extends Record<string, JSONValue>> impl
}

get(target: unknown, property: string, receiver: unknown): unknown {
if (typeof property !== 'string') { throw new Error(`Unexpected property: ${String(property)}`); }
if (typeof property !== 'string') {
throw new Error(`Unexpected property: ${String(property)}`);
}
const preferenceName = this.prefix + property;
if (this.schema && (this.isFlat || !property.includes('.')) && this.schema.properties[preferenceName]) {
const { overrideIdentifier } = this;
Expand Down Expand Up @@ -143,7 +145,7 @@ export class InjectablePreferenceProxy<T extends Record<string, JSONValue>> impl
} while (parentSegment && value === undefined);

let segment;
while (typeof value === 'object' && (segment = segments.pop())) {
while (Is.object(value) && (segment = segments.pop())) {
value = value[segment];
}
return segments.length ? undefined : value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import * as Ajv from 'ajv';
import { inject, injectable, interfaces, named, postConstruct } from 'inversify';
import { ContributionProvider, bindContributionProvider, Emitter, Event, Disposable } from '../../common';
import { ContributionProvider, bindContributionProvider, Emitter, Event, Disposable, Is } from '../../common';
import { PreferenceScope } from './preference-scope';
import { PreferenceProvider, PreferenceProviderDataChange } from './preference-provider';
import {
Expand Down Expand Up @@ -80,7 +80,7 @@ export interface FrontendApplicationPreferenceConfig extends FrontendApplication
}
export namespace FrontendApplicationPreferenceConfig {
export function is(config: FrontendApplicationConfig): config is FrontendApplicationPreferenceConfig {
return 'preferences' in config && typeof config['preferences'] === 'object';
return Is.object(config.preferences);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// *****************************************************************************

import { injectable } from 'inversify';
import { escapeRegExpCharacters } from '../../common';
import { escapeRegExpCharacters, Is } from '../../common';
import { PreferenceSchemaProperties } from '../../common/preferences/preference-schema';

export interface OverridePreferenceName {
Expand All @@ -24,7 +24,7 @@ export interface OverridePreferenceName {
}
export namespace OverridePreferenceName {
export function is(arg: unknown): arg is OverridePreferenceName {
return !!arg && typeof arg === 'object' && 'preferenceName' in arg && 'overrideIdentifier' in arg;
return Is.object(arg) && 'preferenceName' in arg && 'overrideIdentifier' in arg;
}
}

Expand Down
12 changes: 4 additions & 8 deletions packages/core/src/browser/preferences/preference-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import debounce = require('p-debounce');
import { injectable, inject } from 'inversify';
import { JSONExt, JSONValue } from '@phosphor/coreutils';
import URI from '../../common/uri';
import { Disposable, DisposableCollection, Emitter, Event } from '../../common';
import { Disposable, DisposableCollection, Emitter, Event, Is } from '../../common';
import { Deferred } from '../../common/promise-util';
import { PreferenceScope } from './preference-scope';
import { PreferenceLanguageOverrideService } from './preference-language-override-service';
Expand Down Expand Up @@ -253,16 +253,12 @@ export abstract class PreferenceProvider implements Disposable {

protected getParsedContent(jsonData: any): { [key: string]: any } {
const preferences: { [key: string]: any } = {};
if (typeof jsonData !== 'object') {
if (!Is.object(jsonData)) {
return preferences;
}
// eslint-disable-next-line guard-for-in
for (const preferenceName in jsonData) {
const preferenceValue = jsonData[preferenceName];
for (const [preferenceName, preferenceValue] of Object.entries(jsonData)) {
if (this.preferenceOverrideService.testOverrideValue(preferenceName, preferenceValue)) {
// eslint-disable-next-line guard-for-in
for (const overriddenPreferenceName in preferenceValue) {
const overriddenValue = preferenceValue[overriddenPreferenceName];
for (const [overriddenPreferenceName, overriddenValue] of Object.entries(preferenceValue)) {
preferences[`${preferenceName}.${overriddenPreferenceName}`] = overriddenValue;
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/browser/preferences/preference-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/* eslint-disable @typescript-eslint/no-explicit-any */

import { Disposable, Event, MaybePromise } from '../../common';
import { Disposable, Event, Is, MaybePromise } from '../../common';
import { PreferenceService } from './preference-service';
import { PreferenceSchema } from './preference-contribution';
import { PreferenceScope } from './preference-scope';
Expand Down Expand Up @@ -332,7 +332,7 @@ export function createPreferenceProxy<T>(preferences: PreferenceService, promise
} while (parentSegment && value === undefined);

let segment;
while (typeof value === 'object' && (segment = segments.pop())) {
while (Is.object(value) && (segment = segments.pop())) {
value = value[segment];
}
return segments.length ? undefined : value;
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/browser/saveable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Key } from './keyboard/keys';
import { AbstractDialog } from './dialogs';
import { waitForClosed } from './widgets';
import { nls } from '../common/nls';
import { Is } from '../common/is';

export interface Saveable {
readonly dirty: boolean;
Expand Down Expand Up @@ -60,10 +61,10 @@ export namespace Saveable {

export type Snapshot = { value: string } | { read(): string | null };
export function isSource(arg: unknown): arg is SaveableSource {
return typeof arg === 'object' && !!arg && is((arg as SaveableSource).saveable);
return Is.object<SaveableSource>(arg) && is(arg.saveable);
}
export function is(arg: unknown): arg is Saveable {
return typeof arg === 'object' && !!arg && 'dirty' in arg && 'onDirtyChanged' in arg;
return Is.object(arg) && 'dirty' in arg && 'onDirtyChanged' in arg;
}
export function get(arg: unknown): Saveable | undefined {
if (is(arg)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/browser/shell/application-shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from '@phosphor/widgets';
import { Message } from '@phosphor/messaging';
import { IDragEvent } from '@phosphor/dragdrop';
import { RecursivePartial, Event as CommonEvent, DisposableCollection, Disposable, environment } from '../../common';
import { RecursivePartial, Event as CommonEvent, DisposableCollection, Disposable, environment, Is } from '../../common';
import { animationFrame } from '../browser';
import { Saveable, SaveableWidget, SaveOptions, SaveableSource } from '../saveable';
import { StatusBarImpl, StatusBarEntry, StatusBarAlignment } from '../status-bar/status-bar';
Expand Down Expand Up @@ -2101,7 +2101,7 @@ export namespace ApplicationShell {

export namespace TrackableWidgetProvider {
export function is(widget: unknown): widget is TrackableWidgetProvider {
return !!widget && typeof widget === 'object' && 'getTrackableWidgets' in widget;
return Is.object(widget) && 'getTrackableWidgets' in widget;
}
}

Expand Down
16 changes: 6 additions & 10 deletions packages/core/src/browser/shell/shell-layout-restorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { ApplicationShell, applicationShellLayoutVersion, ApplicationShellLayout
import { CommonCommands } from '../common-frontend-contribution';
import { WindowService } from '../window/window-service';
import { StopReason } from '../../common/frontend-application-state';
import { Is } from '../../common/is';

/**
* A contract for widgets that want to store and restore their inner state, between sessions.
Expand All @@ -47,7 +48,7 @@ export interface StatefulWidget {

export namespace StatefulWidget {
export function is(arg: unknown): arg is StatefulWidget {
return !!arg && typeof arg === 'object' && typeof (arg as StatefulWidget).storeState === 'function' && typeof (arg as StatefulWidget).restoreState === 'function';
return Is.object<StatefulWidget>(arg) && Is.func(arg.storeState) && Is.func(arg.restoreState);
}
}

Expand Down Expand Up @@ -232,11 +233,7 @@ export class ShellLayoutRestorer implements CommandContribution {
const parseContext = new ShellLayoutRestorer.ParseContext();
const layout = this.parse<ApplicationShell.LayoutData>(layoutData, parseContext);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let layoutVersion: number | any;
try {
layoutVersion = 'version' in layout && Number(layout.version);
} catch { /* no-op */ }
const layoutVersion = Number(layout.version);
if (typeof layoutVersion !== 'number' || Number.isNaN(layoutVersion)) {
throw new Error('could not resolve a layout version');
}
Expand Down Expand Up @@ -282,9 +279,8 @@ export class ShellLayoutRestorer implements CommandContribution {
});
}
return widgets;
} else if (value && typeof value === 'object' && !Array.isArray(value)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const copy: any = {};
} else if (Is.object<Record<string, WidgetDescription>>(value) && !Array.isArray(value)) {
const copy: Record<string, unknown> = {};
for (const p in value) {
if (this.isWidgetProperty(p)) {
parseContext.push(async context => {
Expand All @@ -306,7 +302,7 @@ export class ShellLayoutRestorer implements CommandContribution {
// don't catch exceptions, if one migration fails all should fail.
const migrated = await migration.onWillInflateWidget(desc, context);
if (migrated) {
if (migrated.innerWidgetState && typeof migrated.innerWidgetState !== 'string') {
if (Is.object(migrated.innerWidgetState)) {
// in order to inflate nested widgets
migrated.innerWidgetState = JSON.stringify(migrated.innerWidgetState);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// *****************************************************************************

import * as React from 'react';
import { ArrayUtils, Event, MenuPath } from '../../../common';
import { ArrayUtils, Event, Is, MenuPath } from '../../../common';
import { Widget } from '../../widgets';

/** Items whose group is exactly 'navigation' will be rendered inline. */
Expand All @@ -27,13 +27,9 @@ export interface TabBarDelegator extends Widget {
}

export namespace TabBarDelegator {
export const is = (candidate?: Widget): candidate is TabBarDelegator => {
if (candidate) {
const asDelegator = candidate as TabBarDelegator;
return typeof asDelegator.getTabBarDelegate === 'function';
}
return false;
};
export function is(candidate?: Widget): candidate is TabBarDelegator {
return Is.object<TabBarDelegator>(candidate) && Is.func(candidate.getTabBarDelegate);
}
}

interface RegisteredToolbarItem {
Expand Down Expand Up @@ -172,14 +168,13 @@ export namespace TabBarToolbarItem {
};

export function is(arg: unknown): arg is TabBarToolbarItem {
return !!arg && typeof arg === 'object' && 'command' in arg && typeof (arg as TabBarToolbarItem).command === 'string';
return Is.object<TabBarToolbarItem>(arg) && Is.string(arg.command);
}

}

export namespace MenuToolbarItem {
export function getMenuPath(item: AnyToolbarItem): MenuPath | undefined {
const asDelegate = item as MenuToolbarItem;
return Array.isArray(asDelegate.menuPath) ? asDelegate.menuPath : undefined;
return Array.isArray(item.menuPath) ? item.menuPath : undefined;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class TabBarToolbar extends ReactWidget {
const classNames = [];
if (item.text) {
for (const labelPart of this.labelParser.parse(item.text)) {
if (typeof labelPart !== 'string' && LabelIcon.is(labelPart)) {
if (LabelIcon.is(labelPart)) {
const className = `fa fa-${labelPart.name}${labelPart.animation ? ' fa-' + labelPart.animation : ''}`;
classNames.push(...className.split(' '));
} else {
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/browser/source-tree/tree-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Emitter, Event } from '../../common/event';
import { MaybePromise } from '../../common/types';
import { Disposable, DisposableCollection } from '../../common/disposable';
import { TreeWidget } from '../tree';
import { Is } from '../../common/is';

export interface TreeElement {
/** default: parent id + position among siblings */
Expand All @@ -39,7 +40,7 @@ export interface CompositeTreeElement extends TreeElement {
}
export namespace CompositeTreeElement {
export function is(element: unknown): element is CompositeTreeElement {
return !!element && typeof element === 'object' && 'getElements' in element;
return Is.object(element) && 'getElements' in element;
}
export function hasElements(element: unknown): element is CompositeTreeElement {
return is(element) && element.hasElements !== false;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/browser/status-bar/status-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
const children: JSX.Element[] = [];

childStrings.forEach((val, key) => {
if (!(typeof val === 'string') && LabelIcon.is(val)) {
if (LabelIcon.is(val)) {
const animation = val.animation ? ` fa-${val.animation}` : '';
if (val.name.startsWith('codicon-')) {
children.push(<span key={key} className={`codicon ${val.name}${animation}`}></span>);
Expand Down
Loading

0 comments on commit edddeff

Please sign in to comment.