Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strict nulls for everything except logconsole #7657

Merged
merged 16 commits into from Dec 23, 2019
20 changes: 15 additions & 5 deletions packages/apputils/src/vdom.ts
Expand Up @@ -95,8 +95,15 @@ export abstract class ReactWidget extends Widget {
* An abstract ReactWidget with a model.
*/
export abstract class VDomRenderer<
T extends VDomRenderer.IModel | null
T extends VDomRenderer.IModel | null = null
> extends ReactWidget {
/**
* Create a new VDomRenderer
*/
constructor(model: T extends null ? void : T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit changes the VDomRenderer to take the model as a constructor arg, in order to make it non-nullable. This was an easy fit here, but might give less flexibility for 3rd party renderers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason not to have it in the constructor was because setting the model calls override-able methods, which would not call overrridden versions of those methods in the subclass.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No test failures 😉

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to revert this behavior then? Or perhaps have the constructor call a protected setter method (or something similar)?

super();
this.model = ((model ?? null) as unknown) as T;
}
/**
* A signal emitted when the model changes.
*/
Expand All @@ -107,7 +114,7 @@ export abstract class VDomRenderer<
/**
* Set the model and fire changed signals.
*/
set model(newValue: T | null) {
set model(newValue: T) {
if (this._model === newValue) {
return;
}
Expand All @@ -126,19 +133,22 @@ export abstract class VDomRenderer<
/**
* Get the current model.
*/
get model(): T | null {
get model(): T {
return this._model;
}

/**
* Dispose this widget.
*/
dispose() {
this._model = null;
if (this.isDisposed) {
return;
}
this._model = null!;
super.dispose();
}

private _model: T | null;
private _model: T;
private _modelChanged = new Signal<this, void>(this);
}

Expand Down
3 changes: 1 addition & 2 deletions packages/codemirror/src/syntaxstatus.tsx
Expand Up @@ -64,8 +64,7 @@ export class EditorSyntaxStatus extends VDomRenderer<EditorSyntaxStatus.Model> {
* Construct a new VDomRenderer for the status item.
*/
constructor(opts: EditorSyntaxStatus.IOptions) {
super();
this.model = new EditorSyntaxStatus.Model();
super(new EditorSyntaxStatus.Model());
this._commands = opts.commands;
this.addClass(interactiveItem);
this.title.caption = 'Change text editor syntax highlighting';
Expand Down
6 changes: 1 addition & 5 deletions packages/docmanager/src/pathstatus.tsx
Expand Up @@ -56,9 +56,7 @@ export class PathStatus extends VDomRenderer<PathStatus.Model> {
* Construct a new PathStatus status item.
*/
constructor(opts: PathStatus.IOptions) {
super();
this._docManager = opts.docManager;
this.model = new PathStatus.Model(this._docManager);
super(new PathStatus.Model(opts.docManager));
this.node.title = this.model.path;
}

Expand All @@ -73,8 +71,6 @@ export class PathStatus extends VDomRenderer<PathStatus.Model> {
/>
);
}

private _docManager: IDocumentManager;
}

/**
Expand Down
6 changes: 1 addition & 5 deletions packages/docmanager/src/savingstatus.tsx
Expand Up @@ -55,9 +55,7 @@ export class SavingStatus extends VDomRenderer<SavingStatus.Model> {
* Create a new SavingStatus item.
*/
constructor(opts: SavingStatus.IOptions) {
super();
this._docManager = opts.docManager;
this.model = new SavingStatus.Model(this._docManager);
super(new SavingStatus.Model(opts.docManager));
}

/**
Expand All @@ -70,8 +68,6 @@ export class SavingStatus extends VDomRenderer<SavingStatus.Model> {
return <SavingStatusComponent fileStatus={this.model.status} />;
}
}

private _docManager: IDocumentManager;
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/extensionmanager/src/widget.tsx
Expand Up @@ -429,8 +429,7 @@ export namespace CollapsibleSection {
*/
export class ExtensionView extends VDomRenderer<ListModel> {
constructor(serviceManager: ServiceManager) {
super();
this.model = new ListModel(serviceManager);
super(new ListModel(serviceManager));
this.addClass('jp-extensionmanager-view');
}

Expand Down
10 changes: 5 additions & 5 deletions packages/filebrowser/src/uploadstatus.tsx
Expand Up @@ -65,13 +65,13 @@ export class FileUploadStatus extends VDomRenderer<FileUploadStatus.Model> {
* Construct a new FileUpload status item.
*/
constructor(opts: FileUploadStatus.IOptions) {
super();
super(
new FileUploadStatus.Model(
opts.tracker.currentWidget && opts.tracker.currentWidget.model
)
);
this._tracker = opts.tracker;
this._tracker.currentChanged.connect(this._onBrowserChange);

this.model = new FileUploadStatus.Model(
this._tracker.currentWidget && this._tracker.currentWidget.model
);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/fileeditor/src/tabspacestatus.tsx
Expand Up @@ -67,9 +67,8 @@ export class TabSpaceStatus extends VDomRenderer<TabSpaceStatus.Model> {
* Create a new tab/space status item.
*/
constructor(options: TabSpaceStatus.IOptions) {
super();
super(new TabSpaceStatus.Model());
this._menu = options.menu;
this.model = new TabSpaceStatus.Model();
this.addClass(interactiveItem);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/launcher-extension/src/index.ts
Expand Up @@ -59,7 +59,7 @@ function activate(
const callback = (item: Widget) => {
labShell.add(item, 'main', { ref: id });
};
const launcher = new Launcher({ cwd, callback, commands });
const launcher = new Launcher({ model, cwd, callback, commands });

launcher.model = model;
launcher.title.label = 'Launcher';
Expand Down
7 changes: 6 additions & 1 deletion packages/launcher/src/index.tsx
Expand Up @@ -120,7 +120,7 @@ export class Launcher extends VDomRenderer<LauncherModel> {
* Construct a new launcher widget.
*/
constructor(options: ILauncher.IOptions) {
super();
super(options.model);
this._cwd = options.cwd;
this._callback = options.callback;
this._commands = options.commands;
Expand Down Expand Up @@ -267,6 +267,11 @@ export namespace ILauncher {
* The options used to create a Launcher.
*/
export interface IOptions {
/**
* The model of the launcher.
*/
model: LauncherModel;

/**
* The cwd of the launcher.
*/
Expand Down
3 changes: 1 addition & 2 deletions packages/logconsole-extension/src/status.tsx
Expand Up @@ -81,9 +81,8 @@ export class LogConsoleStatus extends VDomRenderer<LogConsoleStatus.Model> {
* @param options - The status widget initialization options.
*/
constructor(options: LogConsoleStatus.IOptions) {
super();
super(new LogConsoleStatus.Model(options.loggerRegistry));
this._handleClick = options.handleClick;
this.model = new LogConsoleStatus.Model(options.loggerRegistry);
this.addClass(interactiveItem);
this.addClass('jp-LogConsoleStatusItem');
}
Expand Down
3 changes: 1 addition & 2 deletions packages/notebook/src/modestatus.tsx
Expand Up @@ -44,8 +44,7 @@ export class CommandEditStatus extends VDomRenderer<CommandEditStatus.Model> {
* Construct a new CommandEdit status item.
*/
constructor() {
super();
this.model = new CommandEditStatus.Model();
super(new CommandEditStatus.Model());
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/notebook/src/truststatus.tsx
Expand Up @@ -93,8 +93,7 @@ export class NotebookTrustStatus extends VDomRenderer<
* Construct a new status item.
*/
constructor() {
super();
this.model = new NotebookTrustStatus.Model();
super(new NotebookTrustStatus.Model());
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/statusbar/src/defaults/kernelStatus.tsx
Expand Up @@ -67,9 +67,8 @@ export class KernelStatus extends VDomRenderer<KernelStatus.Model> {
* Construct the kernel status widget.
*/
constructor(opts: KernelStatus.IOptions) {
super();
super(new KernelStatus.Model());
this._handleClick = opts.onClick;
this.model = new KernelStatus.Model();
this.addClass(interactiveItem);
}

Expand Down
3 changes: 1 addition & 2 deletions packages/statusbar/src/defaults/lineCol.tsx
Expand Up @@ -225,8 +225,7 @@ export class LineCol extends VDomRenderer<LineCol.Model> {
* Construct a new LineCol status item.
*/
constructor() {
super();
this.model = new LineCol.Model();
super(new LineCol.Model());
this.addClass(interactiveItem);
}

Expand Down
3 changes: 1 addition & 2 deletions packages/statusbar/src/defaults/memoryUsage.tsx
Expand Up @@ -21,8 +21,7 @@ export class MemoryUsage extends VDomRenderer<MemoryUsage.Model> {
* Construct a new memory usage status item.
*/
constructor() {
super();
this.model = new MemoryUsage.Model({ refreshRate: 5000 });
super(new MemoryUsage.Model({ refreshRate: 5000 }));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/statusbar/src/defaults/runningSessions.tsx
Expand Up @@ -85,7 +85,7 @@ export class RunningSessions extends VDomRenderer<RunningSessions.Model> {
* Create a new RunningSessions widget.
*/
constructor(opts: RunningSessions.IOptions) {
super();
super(new RunningSessions.Model());
this._serviceManager = opts.serviceManager;
this._handleClick = opts.onClick;

Expand All @@ -98,7 +98,6 @@ export class RunningSessions extends VDomRenderer<RunningSessions.Model> {
this
);

this.model = new RunningSessions.Model();
this.addClass(interactiveItem);
}

Expand Down
10 changes: 5 additions & 5 deletions tests/test-apputils/src/vdom.spec.ts
Expand Up @@ -30,7 +30,7 @@ class TestWidget extends VDomRenderer<TestModel> {
}
}

class TestWidgetNoModel extends VDomRenderer<null> {
class TestWidgetNoModel extends VDomRenderer {
protected render(): React.ReactElement<any> {
return React.createElement('span', null, 'No model!');
}
Expand Down Expand Up @@ -72,21 +72,21 @@ describe('@jupyterlab/apputils', () => {
describe('VDomRenderer', () => {
describe('#constructor()', () => {
it('should create a TestWidget', () => {
const widget = new TestWidget();
const widget = new TestWidget(new TestModel());
expect(widget).to.be.an.instanceof(TestWidget);
});

it('should be properly disposed', () => {
const widget = new TestWidget();
const widget = new TestWidget(new TestModel());
widget.dispose();
expect(widget.isDisposed).to.equal(true);
});
});

describe('#modelChanged()', () => {
it('should fire the stateChanged signal on a change', () => {
const widget = new TestWidget();
const model = new TestModel();
const widget = new TestWidget(new TestModel());
let changed = false;
widget.modelChanged.connect(() => {
changed = true;
Expand All @@ -98,7 +98,7 @@ describe('@jupyterlab/apputils', () => {

describe('#render()', () => {
it('should render the contents after a model change', async () => {
const widget = new TestWidget();
const widget = new TestWidget(new TestModel());
const model = new TestModel();
widget.model = model;
model.value = 'foo';
Expand Down