Browse Source

Fix compilation issues

Afshin T. Darian 4 years ago
parent
commit
092e00bb9c

+ 21 - 13
packages/debugger-extension/src/index.ts

@@ -79,7 +79,9 @@ const consoles: JupyterFrontEndPlugin<void> = {
     }
 
     consoleTracker.currentChanged.connect(async (_, consolePanel) => {
-      await updateHandlerAndCommands(consolePanel);
+      if (consolePanel) {
+        void updateHandlerAndCommands(consolePanel);
+      }
     });
   }
 };
@@ -114,6 +116,9 @@ const files: JupyterFrontEndPlugin<void> = {
       const sessions = app.serviceManager.sessions;
       try {
         const model = await sessions.findByPath(widget.context.path);
+        if (!model) {
+          return;
+        }
         let session = activeSessions[model.id];
         if (!session) {
           // Use `connectTo` only if the session does not exist.
@@ -354,9 +359,12 @@ const main: JupyterFrontEndPlugin<void> = {
 
     // hide the debugger sidebar if no kernel with support for debugging is available
     await kernelspecs.ready;
-    const specs = kernelspecs.specs.kernelspecs;
+    const specs = kernelspecs.specs?.kernelspecs;
+    if (!specs) {
+      return;
+    }
     const enabled = Object.keys(specs).some(
-      name => !!(specs[name].metadata?.['debugger'] ?? false)
+      name => !!(specs[name]?.metadata?.['debugger'] ?? false)
     );
     if (!enabled) {
       return;
@@ -446,9 +454,9 @@ const main: JupyterFrontEndPlugin<void> = {
         const filters = setting.get('variableFilters').composite as {
           [key: string]: string[];
         };
-        const list = filters[service.session?.connection?.kernel?.name];
-        if (list) {
-          sidebar.variables.filter = new Set<string>(list);
+        const kernel = service.session?.connection?.kernel?.name ?? '';
+        if (kernel && filters[kernel]) {
+          sidebar.variables.filter = new Set<string>(filters[kernel]);
         }
       };
 
@@ -500,9 +508,9 @@ const main: JupyterFrontEndPlugin<void> = {
         debuggerSources
           .find({
             focus: true,
-            kernel: service.session?.connection?.kernel?.name,
-            path: service.session?.connection?.path,
-            source: frame?.source.path ?? null
+            kernel: service.session?.connection?.kernel?.name ?? '',
+            path: service.session?.connection?.path ?? '',
+            source: frame?.source?.path ?? ''
           })
           .forEach(editor => {
             requestAnimationFrame(() => {
@@ -512,7 +520,7 @@ const main: JupyterFrontEndPlugin<void> = {
       };
 
       const onCurrentSourceOpened = (
-        _: IDebugger.Model.ISources,
+        _: IDebugger.Model.ISources | null,
         source: IDebugger.Source
       ): void => {
         if (!source) {
@@ -521,8 +529,8 @@ const main: JupyterFrontEndPlugin<void> = {
         const { content, mimeType, path } = source;
         const results = debuggerSources.find({
           focus: true,
-          kernel: service.session?.connection?.kernel.name,
-          path: service.session?.connection?.path,
+          kernel: service.session?.connection?.kernel?.name ?? '',
+          path: service.session?.connection?.path ?? '',
           source: path
         });
         if (results.length > 0) {
@@ -556,7 +564,7 @@ const main: JupyterFrontEndPlugin<void> = {
       model.callstack.currentFrameChanged.connect(onCurrentFrameChanged);
       model.sources.currentSourceOpened.connect(onCurrentSourceOpened);
       model.breakpoints.clicked.connect(async (_, breakpoint) => {
-        const path = breakpoint.source.path;
+        const path = breakpoint.source?.path;
         const source = await service.getSource({
           sourceReference: 0,
           path

+ 41 - 16
packages/debugger-extension/tsconfig.json

@@ -1,21 +1,46 @@
 {
+  "extends": "../../tsconfigbase",
   "compilerOptions": {
-    "allowSyntheticDefaultImports": true,
-    "composite": true,
-    "declaration": true,
-    "esModuleInterop": true,
-    "incremental": true,
-    "jsx": "react",
-    "module": "esnext",
-    "moduleResolution": "node",
-    "noEmitOnError": true,
-    "noImplicitAny": true,
-    "noUnusedLocals": true,
     "outDir": "lib",
-    "rootDir": "src",
-    "preserveWatchOutput": true,
-    "resolveJsonModule": true,
-    "target": "es2017"
+    "rootDir": "src"
   },
-  "include": ["src/**/*"]
+  "include": ["src/*"],
+  "references": [
+    {
+      "path": "../application"
+    },
+    {
+      "path": "../apputils"
+    },
+    {
+      "path": "../codeeditor"
+    },
+    {
+      "path": "../console"
+    },
+    {
+      "path": "../coreutils"
+    },
+    {
+      "path": "../debugger"
+    },
+    {
+      "path": "../docregistry"
+    },
+    {
+      "path": "../fileeditor"
+    },
+    {
+      "path": "../launcher"
+    },
+    {
+      "path": "../notebook"
+    },
+    {
+      "path": "../services"
+    },
+    {
+      "path": "../settingregistry"
+    }
+  ]
 }

+ 6 - 0
packages/debugger/src/config.ts

@@ -39,6 +39,9 @@ export class DebuggerConfig implements IDebugger.IConfig {
    */
   setHashParams(params: IDebugger.IConfig.HashParams): void {
     const { kernel, method, seed } = params;
+    if (!kernel) {
+      throw new TypeError(`Kernel name is not defined.`);
+    }
     switch (method) {
       case 'Murmur2':
         this._hashMethods.set(kernel, code => murmur2(code, seed).toString());
@@ -55,6 +58,9 @@ export class DebuggerConfig implements IDebugger.IConfig {
    */
   setTmpFileParams(params: IDebugger.IConfig.FileParams): void {
     const { kernel, prefix, suffix } = params;
+    if (!kernel) {
+      throw new TypeError(`Kernel name is not defined.`);
+    }
     this._fileParams.set(kernel, { kernel, prefix, suffix });
   }
 

+ 9 - 9
packages/debugger/src/handler.ts

@@ -90,7 +90,7 @@ export class DebuggerHandler {
    */
   async update(
     widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
-    connection: Session.ISessionConnection
+    connection: Session.ISessionConnection | null
   ): Promise<void> {
     if (!connection) {
       delete this._kernelChangedHandlers[widget.id];
@@ -164,14 +164,14 @@ export class DebuggerHandler {
    */
   private async _update(
     widget: DebuggerHandler.SessionWidget[DebuggerHandler.SessionType],
-    connection: Session.ISessionConnection
+    connection: Session.ISessionConnection | null
   ): Promise<void> {
-    if (!this._service.model) {
+    if (!this._service.model || !connection) {
       return;
     }
 
     const hasFocus = (): boolean => {
-      return this._shell.currentWidget && this._shell.currentWidget === widget;
+      return this._shell.currentWidget === widget;
     };
 
     const updateAttribute = (): void => {
@@ -263,13 +263,13 @@ export class DebuggerHandler {
 
       if (
         this._service.isStarted &&
-        this._previousConnection.id === connection.id
+        this._previousConnection?.id === connection?.id
       ) {
-        this._service.session.connection = connection;
+        this._service.session!.connection = connection;
         await this._service.stop();
         removeHandlers();
       } else {
-        this._service.session.connection = connection;
+        this._service.session!.connection = connection;
         this._previousConnection = connection;
         await this._service.restoreState(true);
         createHandler();
@@ -287,7 +287,7 @@ export class DebuggerHandler {
     if (!this._service.session) {
       this._service.session = new Debugger.Session({ connection });
     } else {
-      this._previousConnection = this._service.session.connection.kernel
+      this._previousConnection = this._service.session!.connection?.kernel
         ? this._service.session.connection
         : null;
       this._service.session.connection = connection;
@@ -314,7 +314,7 @@ export class DebuggerHandler {
   private _type: DebuggerHandler.SessionType;
   private _shell: JupyterFrontEnd.IShell;
   private _service: IDebugger;
-  private _previousConnection: Session.ISessionConnection;
+  private _previousConnection: Session.ISessionConnection | null;
   private _handlers: {
     [id: string]: DebuggerHandler.SessionHandler[DebuggerHandler.SessionType];
   } = {};

+ 4 - 2
packages/debugger/src/handlers/console.ts

@@ -33,7 +33,9 @@ export class ConsoleHandler implements IDisposable {
 
     const codeConsole = this._consolePanel.console;
 
-    this._addEditorHandler(codeConsole.promptCell);
+    if (codeConsole.promptCell) {
+      this._addEditorHandler(codeConsole.promptCell);
+    }
     codeConsole.promptCellCreated.connect((_: CodeConsole, cell: CodeCell) => {
       this._addEditorHandler(cell);
     });
@@ -87,7 +89,7 @@ export class ConsoleHandler implements IDisposable {
 
   private _consolePanel: ConsolePanel;
   private _debuggerService: IDebugger;
-  private _cellMap: IObservableMap<EditorHandler> = null;
+  private _cellMap: IObservableMap<EditorHandler>;
 }
 
 /**

+ 13 - 11
packages/debugger/src/handlers/editor.ts

@@ -37,8 +37,8 @@ export class EditorHandler implements IDisposable {
    * @param options The instantiation options for a EditorHandler.
    */
   constructor(options: EditorHandler.IOptions) {
-    this._id = options.debuggerService.session.connection.id;
-    this._path = options.path;
+    this._id = options.debuggerService.session?.connection?.id ?? '';
+    this._path = options.path ?? '';
     this._debuggerService = options.debuggerService;
     this._editor = options.editor;
 
@@ -133,7 +133,7 @@ export class EditorHandler implements IDisposable {
 
     const breakpoints = this._getBreakpointsFromEditor().map(lineInfo => {
       return Private.createBreakpoint(
-        this._debuggerService.session.connection.name,
+        this._debuggerService.session?.connection?.name || '',
         lineInfo.line + 1
       );
     });
@@ -153,7 +153,7 @@ export class EditorHandler implements IDisposable {
    */
   private _onGutterClick = (editor: Editor, lineNumber: number): void => {
     const info = editor.lineInfo(lineNumber);
-    if (!info || this._id !== this._debuggerService.session.connection.id) {
+    if (!info || this._id !== this._debuggerService.session?.connection?.id) {
       return;
     }
 
@@ -183,16 +183,18 @@ export class EditorHandler implements IDisposable {
   private _addBreakpointsToEditor(): void {
     const editor = this._editor as CodeMirrorEditor;
     const breakpoints = this._getBreakpoints();
-    if (this._id !== this._debuggerService.session.connection.id) {
+    if (this._id !== this._debuggerService.session?.connection?.id) {
       return;
     }
     EditorHandler.clearGutter(editor);
     breakpoints.forEach(breakpoint => {
-      editor.editor.setGutterMarker(
-        breakpoint.line - 1,
-        'breakpoints',
-        Private.createMarkerNode()
-      );
+      if (typeof breakpoint.line === 'number') {
+        editor.editor.setGutterMarker(
+          breakpoint.line - 1,
+          'breakpoints',
+          Private.createMarkerNode()
+        );
+      }
     });
   }
 
@@ -229,7 +231,7 @@ export class EditorHandler implements IDisposable {
   private _editorMonitor: ActivityMonitor<
     IObservableString,
     IObservableString.IChangedArgs
-  > = null;
+  >;
 }
 
 /**

+ 2 - 2
packages/debugger/src/handlers/notebook.ts

@@ -31,7 +31,7 @@ export class NotebookHandler implements IDisposable {
 
     const notebook = this._notebookPanel.content;
     notebook.activeCellChanged.connect(this._onActiveCellChanged, this);
-    notebook.model.cells.changed.connect(this._onCellsChanged, this);
+    notebook.model?.cells.changed.connect(this._onCellsChanged, this);
 
     this._onCellsChanged();
   }
@@ -100,7 +100,7 @@ export class NotebookHandler implements IDisposable {
 
   private _debuggerService: IDebugger;
   private _notebookPanel: NotebookPanel;
-  private _cellMap: IObservableMap<EditorHandler> = null;
+  private _cellMap: IObservableMap<EditorHandler>;
 }
 
 /**

+ 4 - 4
packages/debugger/src/panels/breakpoints/body.tsx

@@ -99,11 +99,11 @@ const BreakpointCellComponent = ({
     <>
       {breakpoints
         .sort((a, b) => {
-          return a.line - b.line;
+          return (a.line ?? 0) - (b.line ?? 0);
         })
         .map((breakpoint: IDebugger.IBreakpoint, index) => (
           <BreakpointComponent
-            key={breakpoint.source.path + index}
+            key={(breakpoint.source?.path ?? '') + index}
             breakpoint={breakpoint}
             model={model}
           />
@@ -135,11 +135,11 @@ const BreakpointComponent = ({
     <div
       className={'jp-DebuggerBreakpoint'}
       onClick={(): void => model.clicked.emit(breakpoint)}
-      title={breakpoint.source.path}
+      title={breakpoint.source?.path}
     >
       <span className={'jp-DebuggerBreakpoint-marker'}>●</span>
       <span className={'jp-DebuggerBreakpoint-source jp-left-truncated'}>
-        {moveToEndFirstCharIfSlash(breakpoint.source.path)}
+        {moveToEndFirstCharIfSlash(breakpoint.source?.path ?? '')}
       </span>
       <span className={'jp-DebuggerBreakpoint-line'}>{breakpoint.line}</span>
     </div>

+ 1 - 1
packages/debugger/src/panels/callstack/body.tsx

@@ -71,7 +71,7 @@ const FramesComponent = ({
           onClick={(): void => onSelected(ele)}
           className={selected?.id === ele.id ? 'selected' : ''}
         >
-          {ele.name} at {ele.source.name}:{ele.line}
+          {ele.name} at {ele.source?.name}:{ele.line}
         </li>
       ))}
     </ul>

+ 3 - 3
packages/debugger/src/panels/sources/body.ts

@@ -85,7 +85,7 @@ export class SourcesBody extends Widget {
    * @param frame The current frame.
    */
   private async _showSource(frame: IDebugger.IStackFrame): Promise<void> {
-    const path = frame.source.path;
+    const path = frame.source?.path;
     const source = await this._debuggerService.getSource({
       sourceReference: 0,
       path
@@ -102,7 +102,7 @@ export class SourcesBody extends Widget {
 
     const { content, mimeType } = source;
     const editorMimeType =
-      mimeType || this._mimeTypeService.getMimeTypeByFilePath(path);
+      mimeType || this._mimeTypeService.getMimeTypeByFilePath(path ?? '');
 
     this._editor.model.value.text = content;
     this._editor.model.mimeType = editorMimeType;
@@ -116,7 +116,7 @@ export class SourcesBody extends Widget {
     this._model.currentSource = {
       content,
       mimeType: editorMimeType,
-      path
+      path: path ?? ''
     };
 
     requestAnimationFrame(() => {

+ 2 - 2
packages/debugger/src/panels/sources/header.tsx

@@ -58,8 +58,8 @@ const SourcePathComponent = ({
   return (
     <UseSignal signal={model.currentSourceChanged} initialSender={model}>
       {(model): JSX.Element => (
-        <span onClick={(): void => model.open()}>
-          {model.currentSource?.path ?? ''}
+        <span onClick={(): void => model?.open()}>
+          {model?.currentSource?.path ?? ''}
         </span>
       )}
     </UseSignal>

+ 11 - 9
packages/debugger/src/panels/sources/model.ts

@@ -29,21 +29,21 @@ export class SourcesModel implements IDebugger.Model.ISources {
   /**
    * Signal emitted when a source should be open in the main area.
    */
-  get currentSourceOpened(): ISignal<SourcesModel, IDebugger.Source> {
+  get currentSourceOpened(): ISignal<SourcesModel, IDebugger.Source | null> {
     return this._currentSourceOpened;
   }
 
   /**
    * Signal emitted when the current source changes.
    */
-  get currentSourceChanged(): ISignal<SourcesModel, IDebugger.Source> {
+  get currentSourceChanged(): ISignal<SourcesModel, IDebugger.Source | null> {
     return this._currentSourceChanged;
   }
 
   /**
    * Return the current source.
    */
-  get currentSource(): IDebugger.Source {
+  get currentSource(): IDebugger.Source | null {
     return this._currentSource;
   }
 
@@ -65,12 +65,14 @@ export class SourcesModel implements IDebugger.Model.ISources {
   }
 
   private _currentSource: IDebugger.Source | null;
-  private _currentSourceOpened = new Signal<SourcesModel, IDebugger.Source>(
-    this
-  );
-  private _currentSourceChanged = new Signal<SourcesModel, IDebugger.Source>(
-    this
-  );
+  private _currentSourceOpened = new Signal<
+    SourcesModel,
+    IDebugger.Source | null
+  >(this);
+  private _currentSourceChanged = new Signal<
+    SourcesModel,
+    IDebugger.Source | null
+  >(this);
 }
 
 /**

+ 12 - 11
packages/debugger/src/panels/variables/grid.ts

@@ -270,11 +270,12 @@ class GridModel extends DataModel {
     });
     scopes.forEach(scope => {
       const filtered = scope.variables.filter(
-        variable => !this._filter.has(variable.evaluateName)
+        variable =>
+          variable.evaluateName && !this._filter.has(variable.evaluateName)
       );
       filtered.forEach((variable, index) => {
-        this._data.name[index] = variable.evaluateName;
-        this._data.type[index] = variable.type;
+        this._data.name[index] = variable.evaluateName!;
+        this._data.type[index] = variable.type || '';
         this._data.value[index] = variable.value;
         this._data.variablesReference[index] = variable.variablesReference;
       });
@@ -344,21 +345,21 @@ namespace Private {
   } {
     const palette = createPalette();
     document.body.appendChild(palette);
-    let node: HTMLDivElement;
+    let node: HTMLDivElement | null;
     node = palette.querySelector('.jp-mod-void');
-    const voidColor = getComputedStyle(node).color;
+    const voidColor = getComputedStyle(node!).color;
     node = palette.querySelector('.jp-mod-background');
-    const backgroundColor = getComputedStyle(node).color;
+    const backgroundColor = getComputedStyle(node!).color;
     node = palette.querySelector('.jp-mod-header-background');
-    const headerBackgroundColor = getComputedStyle(node).color;
+    const headerBackgroundColor = getComputedStyle(node!).color;
     node = palette.querySelector('.jp-mod-grid-line');
-    const gridLineColor = getComputedStyle(node).color;
+    const gridLineColor = getComputedStyle(node!).color;
     node = palette.querySelector('.jp-mod-header-grid-line');
-    const headerGridLineColor = getComputedStyle(node).color;
+    const headerGridLineColor = getComputedStyle(node!).color;
     node = palette.querySelector('.jp-mod-selection');
-    const selectionFillColor = getComputedStyle(node).color;
+    const selectionFillColor = getComputedStyle(node!).color;
     node = palette.querySelector('.jp-mod-text');
-    const textColor = getComputedStyle(node).color;
+    const textColor = getComputedStyle(node!).color;
     document.body.removeChild(palette);
     return {
       style: {

+ 1 - 1
packages/debugger/src/panels/variables/index.ts

@@ -112,7 +112,7 @@ export const convertType = (variable: IDebugger.IVariable): string | number => {
     case 'str':
       return value.slice(1, value.length - 1);
     default:
-      return type;
+      return type ?? '';
   }
 };
 

+ 6 - 3
packages/debugger/src/panels/variables/tree.tsx

@@ -14,6 +14,7 @@ import { IDebugger } from '../../tokens';
 import { convertType } from '.';
 
 import { VariablesModel } from './model';
+import { DebugProtocol } from 'vscode-debugprotocol';
 
 /**
  * The body for tree of variables.
@@ -104,7 +105,9 @@ const VariablesComponent = ({
   return (
     <ul>
       {variables
-        ?.filter(variable => !filter.has(variable.evaluateName))
+        ?.filter(
+          variable => !(filter || new Set()).has(variable.evaluateName || '')
+        )
         .map(variable => {
           const key = `${variable.evaluateName}-${variable.type}-${variable.value}`;
           return (
@@ -138,8 +141,8 @@ const VariableComponent = ({
   filter?: Set<string>;
 }): JSX.Element => {
   const [variable] = useState(data);
-  const [expanded, setExpanded] = useState(null);
-  const [variables, setVariables] = useState(null);
+  const [expanded, setExpanded] = useState<boolean>();
+  const [variables, setVariables] = useState<DebugProtocol.Variable[]>();
   const styleName = {
     color: 'var(--jp-mirror-editor-attribute-color)'
   };

+ 92 - 42
packages/debugger/src/service.ts

@@ -32,9 +32,9 @@ export class DebuggerService implements IDebugger, IDisposable {
     // TODO: also checks that the notebook or console
     // runs a kernel with debugging ability
     this._session = null;
-    this._specsManager = options.specsManager;
+    this._specsManager = options.specsManager ?? null;
     this._model = new Debugger.Model();
-    this._debuggerSources = options.debuggerSources;
+    this._debuggerSources = options.debuggerSources ?? null;
   }
 
   /**
@@ -68,7 +68,7 @@ export class DebuggerService implements IDebugger, IDisposable {
   /**
    * Returns the current debug session.
    */
-  get session(): IDebugger.ISession {
+  get session(): IDebugger.ISession | null {
     return this._session;
   }
 
@@ -77,7 +77,7 @@ export class DebuggerService implements IDebugger, IDisposable {
    *
    * @param session - the new debugger session.
    */
-  set session(session: IDebugger.ISession) {
+  set session(session: IDebugger.ISession | null) {
     if (this._session === session) {
       return;
     }
@@ -103,7 +103,7 @@ export class DebuggerService implements IDebugger, IDisposable {
   /**
    * Signal emitted upon session changed.
    */
-  get sessionChanged(): ISignal<IDebugger, IDebugger.ISession> {
+  get sessionChanged(): ISignal<IDebugger, IDebugger.ISession | null> {
     return this._sessionChanged;
   }
 
@@ -127,7 +127,7 @@ export class DebuggerService implements IDebugger, IDisposable {
     try {
       return this._config.getCodeId(
         code,
-        this.session?.connection?.kernel?.name
+        this.session?.connection?.kernel?.name ?? ''
       );
     } catch {
       return '';
@@ -156,11 +156,12 @@ export class DebuggerService implements IDebugger, IDisposable {
       return false;
     }
     const name = kernel.name;
-    if (!this._specsManager.specs.kernelspecs[name]) {
+    if (!this._specsManager.specs?.kernelspecs[name]) {
       return true;
     }
     return !!(
-      this._specsManager.specs.kernelspecs[name].metadata?.['debugger'] ?? false
+      this._specsManager.specs.kernelspecs[name]?.metadata?.['debugger'] ??
+      false
     );
   }
 
@@ -168,15 +169,13 @@ export class DebuggerService implements IDebugger, IDisposable {
    * Clear all the breakpoints for the current session.
    */
   async clearBreakpoints(): Promise<void> {
-    if (!this.session.isStarted) {
+    if (this.session?.isStarted !== true) {
       return;
     }
 
-    this._model.breakpoints.breakpoints.forEach(
-      async (breakpoints, path, _) => {
-        await this._setBreakpoints([], path);
-      }
-    );
+    this._model.breakpoints.breakpoints.forEach((_, path, map) => {
+      void this._setBreakpoints([], path);
+    });
 
     let bpMap = new Map<string, IDebugger.IBreakpoint[]>();
     this._model.breakpoints.restoreBreakpoints(bpMap);
@@ -187,6 +186,9 @@ export class DebuggerService implements IDebugger, IDisposable {
    */
   async continue(): Promise<void> {
     try {
+      if (!this.session) {
+        throw new Error('No active debugger session');
+      }
       await this.session.sendRequest('continue', {
         threadId: this._currentThread()
       });
@@ -202,11 +204,14 @@ export class DebuggerService implements IDebugger, IDisposable {
    * @param source The source object containing the path to the file.
    */
   async getSource(source: DebugProtocol.Source): Promise<IDebugger.Source> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     const reply = await this.session.sendRequest('source', {
       source,
-      sourceReference: source.sourceReference
+      sourceReference: source.sourceReference ?? 0
     });
-    return { ...reply.body, path: source.path };
+    return { ...reply.body, path: source.path ?? '' };
   }
 
   /**
@@ -214,6 +219,9 @@ export class DebuggerService implements IDebugger, IDisposable {
    */
   async next(): Promise<void> {
     try {
+      if (!this.session) {
+        throw new Error('No active debugger session');
+      }
       await this.session.sendRequest('next', {
         threadId: this._currentThread()
       });
@@ -230,6 +238,9 @@ export class DebuggerService implements IDebugger, IDisposable {
   async inspectVariable(
     variablesReference: number
   ): Promise<DebugProtocol.Variable[]> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     const reply = await this.session.sendRequest('variables', {
       variablesReference
     });
@@ -247,7 +258,9 @@ export class DebuggerService implements IDebugger, IDisposable {
     // Re-send the breakpoints to the kernel and update the model.
     for (const [source, points] of breakpoints) {
       await this._setBreakpoints(
-        points.map(({ line }) => ({ line })),
+        points
+          .filter(({ line }) => typeof line === 'number')
+          .map(({ line }) => ({ line: line! })),
         source
       );
     }
@@ -270,12 +283,12 @@ export class DebuggerService implements IDebugger, IDisposable {
     const stoppedThreads = new Set(reply.body.stoppedThreads);
 
     this._config.setHashParams({
-      kernel: this.session.connection.kernel.name,
+      kernel: this.session?.connection?.kernel?.name ?? '',
       method: body.hashMethod,
       seed: body.hashSeed
     });
     this._config.setTmpFileParams({
-      kernel: this.session.connection.kernel.name,
+      kernel: this.session?.connection?.kernel?.name ?? '',
       prefix: body.tmpFilePrefix,
       suffix: body.tmpFileSuffix
     });
@@ -287,7 +300,9 @@ export class DebuggerService implements IDebugger, IDisposable {
     }
 
     if (this.isStarted || autoStart) {
-      this._model.title = this.isStarted ? this.session?.connection?.name : '-';
+      this._model.title = this.isStarted
+        ? this.session?.connection?.name || '-'
+        : '-';
     }
 
     if (this._debuggerSources) {
@@ -310,6 +325,9 @@ export class DebuggerService implements IDebugger, IDisposable {
    * Precondition: !isStarted
    */
   start(): Promise<void> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     return this.session.start();
   }
 
@@ -318,6 +336,9 @@ export class DebuggerService implements IDebugger, IDisposable {
    */
   async stepIn(): Promise<void> {
     try {
+      if (!this.session) {
+        throw new Error('No active debugger session');
+      }
       await this.session.sendRequest('stepIn', {
         threadId: this._currentThread()
       });
@@ -331,6 +352,9 @@ export class DebuggerService implements IDebugger, IDisposable {
    */
   async stepOut(): Promise<void> {
     try {
+      if (!this.session) {
+        throw new Error('No active debugger session');
+      }
       await this.session.sendRequest('stepOut', {
         threadId: this._currentThread()
       });
@@ -344,6 +368,9 @@ export class DebuggerService implements IDebugger, IDisposable {
    * Precondition: isStarted
    */
   async stop(): Promise<void> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     await this.session.stop();
     if (this._model) {
       this._model.clear();
@@ -362,7 +389,7 @@ export class DebuggerService implements IDebugger, IDisposable {
     breakpoints: IDebugger.IBreakpoint[],
     path?: string
   ): Promise<void> {
-    if (!this.session.isStarted) {
+    if (!this.session?.isStarted) {
       return;
     }
 
@@ -371,7 +398,9 @@ export class DebuggerService implements IDebugger, IDisposable {
     }
 
     const state = await this.session.restoreState();
-    const localBreakpoints = breakpoints.map(({ line }) => ({ line }));
+    const localBreakpoints = breakpoints
+      .filter(({ line }) => typeof line === 'number')
+      .map(({ line }) => ({ line: line! }));
     const remoteBreakpoints = this._mapBreakpoints(state.body.breakpoints);
 
     // Set the local copy of breakpoints to reflect only editors that exist.
@@ -426,7 +455,7 @@ export class DebuggerService implements IDebugger, IDisposable {
     variables: DebugProtocol.Variable[]
   ): IDebugger.IScope[] {
     if (!variables || !scopes) {
-      return;
+      return [];
     }
     return scopes.map(scope => {
       return {
@@ -454,6 +483,9 @@ export class DebuggerService implements IDebugger, IDisposable {
   private async _dumpCell(
     code: string
   ): Promise<IDebugger.ISession.IDumpCellResponse> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     return this.session.sendRequest('dumpCell', { code });
   }
 
@@ -466,22 +498,23 @@ export class DebuggerService implements IDebugger, IDisposable {
   private _filterBreakpoints(
     breakpoints: Map<string, IDebugger.IBreakpoint[]>
   ): Map<string, IDebugger.IBreakpoint[]> {
+    if (!this._debuggerSources) {
+      return breakpoints;
+    }
     let bpMapForRestore = new Map<string, IDebugger.IBreakpoint[]>();
     for (const collection of breakpoints) {
       const [id, list] = collection;
       list.forEach(() => {
-        this._debuggerSources
-          .find({
-            focus: false,
-            kernel: this.session.connection.kernel.name,
-            path: this._session.connection.path,
-            source: id
-          })
-          .forEach(() => {
-            if (list.length > 0) {
-              bpMapForRestore.set(id, list);
-            }
-          });
+        this._debuggerSources!.find({
+          focus: false,
+          kernel: this.session?.connection?.kernel?.name ?? '',
+          path: this._session?.connection?.path ?? '',
+          source: id
+        }).forEach(() => {
+          if (list.length > 0) {
+            bpMapForRestore.set(id, list);
+          }
+        });
       });
     }
     return bpMapForRestore;
@@ -512,6 +545,9 @@ export class DebuggerService implements IDebugger, IDisposable {
   private async _getFrames(
     threadId: number
   ): Promise<DebugProtocol.StackFrame[]> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     const reply = await this.session.sendRequest('stackTrace', {
       threadId
     });
@@ -527,8 +563,11 @@ export class DebuggerService implements IDebugger, IDisposable {
   private async _getScopes(
     frame: DebugProtocol.StackFrame
   ): Promise<DebugProtocol.Scope[]> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     if (!frame) {
-      return;
+      return [];
     }
     const reply = await this.session.sendRequest('scopes', {
       frameId: frame.id
@@ -544,8 +583,11 @@ export class DebuggerService implements IDebugger, IDisposable {
   private async _getVariables(
     scope: DebugProtocol.Scope
   ): Promise<DebugProtocol.Variable[]> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     if (!scope) {
-      return;
+      return [];
     }
     const reply = await this.session.sendRequest('variables', {
       variablesReference: scope.variablesReference
@@ -610,6 +652,9 @@ export class DebuggerService implements IDebugger, IDisposable {
     _: VariablesModel,
     variable: DebugProtocol.Variable
   ): Promise<DebugProtocol.Variable[]> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     const reply = await this.session.sendRequest('variables', {
       variablesReference: variable.variablesReference
     });
@@ -640,6 +685,9 @@ export class DebuggerService implements IDebugger, IDisposable {
     breakpoints: DebugProtocol.SourceBreakpoint[],
     path: string
   ): Promise<DebugProtocol.SetBreakpointsResponse> {
+    if (!this.session) {
+      throw new Error('No active debugger session');
+    }
     return await this.session.sendRequest('setBreakpoints', {
       breakpoints: breakpoints,
       source: { path },
@@ -652,9 +700,11 @@ export class DebuggerService implements IDebugger, IDisposable {
   private _eventMessage = new Signal<IDebugger, IDebugger.ISession.Event>(this);
   private _isDisposed = false;
   private _model: IDebugger.Model.IService;
-  private _session: IDebugger.ISession;
-  private _sessionChanged = new Signal<IDebugger, IDebugger.ISession>(this);
-  private _specsManager: KernelSpec.IManager;
+  private _session: IDebugger.ISession | null;
+  private _sessionChanged = new Signal<IDebugger, IDebugger.ISession | null>(
+    this
+  );
+  private _specsManager: KernelSpec.IManager | null;
 }
 
 /**
@@ -673,11 +723,11 @@ export namespace DebuggerService {
     /**
      * The optional debugger sources instance.
      */
-    debuggerSources?: IDebugger.ISources;
+    debuggerSources?: IDebugger.ISources | null;
 
     /**
      * The optional kernel specs manager.
      */
-    specsManager?: KernelSpec.IManager;
+    specsManager?: KernelSpec.IManager | null;
   }
 }

+ 11 - 9
packages/debugger/src/session.ts

@@ -39,7 +39,7 @@ export class DebuggerSession implements IDebugger.ISession {
   /**
    * Returns the API session connection to connect to a debugger.
    */
-  get connection(): Session.ISessionConnection {
+  get connection(): Session.ISessionConnection | null {
     return this._connection;
   }
 
@@ -63,15 +63,17 @@ export class DebuggerSession implements IDebugger.ISession {
     this._connection.iopubMessage.connect(this._handleEvent, this);
 
     this._ready = new PromiseDelegate<void>();
-    const future = this.connection.kernel?.requestDebug({
+    const future = this.connection?.kernel?.requestDebug({
       type: 'request',
       seq: 0,
       command: 'debugInfo'
     });
-    future.onReply = (msg: KernelMessage.IDebugReplyMsg): void => {
-      this._ready.resolve();
-      future.dispose();
-    };
+    if (future) {
+      future.onReply = (msg: KernelMessage.IDebugReplyMsg): void => {
+        this._ready.resolve();
+        future.dispose();
+      };
+    }
   }
 
   /**
@@ -107,7 +109,7 @@ export class DebuggerSession implements IDebugger.ISession {
     await this.sendRequest('initialize', {
       clientID: 'jupyterlab',
       clientName: 'JupyterLab',
-      adapterID: this.connection.kernel?.name ?? '',
+      adapterID: this.connection?.kernel?.name ?? '',
       pathFormat: 'path',
       linesStartAt1: true,
       columnsStartAt1: true,
@@ -188,7 +190,7 @@ export class DebuggerSession implements IDebugger.ISession {
   private async _sendDebugMessage(
     msg: KernelMessage.IDebugRequestMsg['content']
   ): Promise<KernelMessage.IDebugReplyMsg> {
-    const kernel = this.connection.kernel;
+    const kernel = this.connection?.kernel;
     if (!kernel) {
       return Promise.reject(
         new Error('A kernel is required to send debug messages.')
@@ -205,7 +207,7 @@ export class DebuggerSession implements IDebugger.ISession {
 
   private _seq = 0;
   private _ready = new PromiseDelegate<void>();
-  private _connection: Session.ISessionConnection;
+  private _connection: Session.ISessionConnection | null;
   private _isDisposed = false;
   private _isStarted = false;
   private _disposed = new Signal<this, void>(this);

+ 1 - 1
packages/debugger/src/sidebar.ts

@@ -159,7 +159,7 @@ export namespace DebuggerSidebar {
     constructor() {
       super({ node: Private.createHeader() });
       this.title.changed.connect(_ => {
-        this.node.querySelector('h2').textContent = this.title.label;
+        this.node!.querySelector('h2')!.textContent = this.title.label;
       });
     }
   }

+ 12 - 10
packages/debugger/src/sources.ts

@@ -35,9 +35,9 @@ export class DebuggerSources implements IDebugger.ISources {
   constructor(options: DebuggerSources.IOptions) {
     this._config = options.config;
     this._shell = options.shell;
-    this._notebookTracker = options.notebookTracker;
-    this._consoleTracker = options.consoleTracker;
-    this._editorTracker = options.editorTracker;
+    this._notebookTracker = options.notebookTracker ?? null;
+    this._consoleTracker = options.consoleTracker ?? null;
+    this._editorTracker = options.editorTracker ?? null;
     this._readOnlyEditorTracker = new WidgetTracker<
       MainAreaWidget<CodeEditorWrapper>
     >({ namespace: '@jupyterlab/debugger' });
@@ -117,9 +117,11 @@ export class DebuggerSources implements IDebugger.ISources {
         }
         if (focus) {
           notebook.activeCellIndex = i;
-          const { node } = notebook.activeCell.inputArea;
-          const rect = node.getBoundingClientRect();
-          notebook.scrollToPosition(rect.bottom, 45);
+          if (notebook.activeCell) {
+            const node = notebook.activeCell.inputArea.node;
+            const rect = node.getBoundingClientRect();
+            notebook.scrollToPosition(rect.bottom, 45);
+          }
           this._shell.activateById(notebookPanel.id);
         }
         editors.push(cell.editor);
@@ -177,7 +179,7 @@ export class DebuggerSources implements IDebugger.ISources {
     params: IDebugger.ISources.FindParams
   ): CodeEditor.IEditor[] {
     if (!this._editorTracker) {
-      return;
+      return [];
     }
     const { focus, kernel, path, source } = params;
 
@@ -294,16 +296,16 @@ export namespace DebuggerSources {
     /**
      * An optional console tracker.
      */
-    consoleTracker?: IConsoleTracker;
+    consoleTracker?: IConsoleTracker | null;
 
     /**
      * An optional file editor tracker.
      */
-    editorTracker?: IEditorTracker;
+    editorTracker?: IEditorTracker | null;
 
     /**
      * An optional notebook tracker.
      */
-    notebookTracker?: INotebookTracker;
+    notebookTracker?: INotebookTracker | null;
   }
 }

+ 6 - 6
packages/debugger/src/tokens.ts

@@ -35,12 +35,12 @@ export interface IDebugger {
   /**
    * The current debugger session.
    */
-  session: IDebugger.ISession;
+  session: IDebugger.ISession | null;
 
   /**
    * Signal emitted upon session changed.
    */
-  readonly sessionChanged: ISignal<IDebugger, IDebugger.ISession>;
+  readonly sessionChanged: ISignal<IDebugger, IDebugger.ISession | null>;
 
   /**
    * Removes all the breakpoints from the current notebook or console
@@ -218,7 +218,7 @@ export namespace IDebugger {
     /**
      * The API session connection to connect to a debugger.
      */
-    connection: Session.ISessionConnection;
+    connection: Session.ISessionConnection | null;
 
     /**
      * Whether the debug session is started
@@ -670,14 +670,14 @@ export namespace IDebugger {
       /**
        * Return the current source.
        */
-      currentSource: IDebugger.Source;
+      currentSource: IDebugger.Source | null;
 
       /**
        * Signal emitted when the current source changes.
        */
       readonly currentSourceChanged: ISignal<
         IDebugger.Model.ISources,
-        IDebugger.Source
+        IDebugger.Source | null
       >;
 
       /**
@@ -685,7 +685,7 @@ export namespace IDebugger {
        */
       readonly currentSourceOpened: ISignal<
         IDebugger.Model.ISources,
-        IDebugger.Source
+        IDebugger.Source | null
       >;
 
       /**

+ 44 - 16
packages/debugger/tsconfig.json

@@ -1,21 +1,49 @@
 {
+  "extends": "../../tsconfigbase",
   "compilerOptions": {
-    "allowSyntheticDefaultImports": true,
-    "composite": true,
-    "declaration": true,
-    "esModuleInterop": true,
-    "incremental": true,
-    "jsx": "react",
-    "module": "esnext",
-    "moduleResolution": "node",
-    "noEmitOnError": true,
-    "noImplicitAny": true,
-    "noUnusedLocals": true,
     "outDir": "lib",
-    "rootDir": "src",
-    "preserveWatchOutput": true,
-    "resolveJsonModule": true,
-    "target": "es2017"
+    "rootDir": "src"
   },
-  "include": ["src/**/*"]
+  "include": ["src/**/*"],
+  "references": [
+    {
+      "path": "../application"
+    },
+    {
+      "path": "../apputils"
+    },
+    {
+      "path": "../codeeditor"
+    },
+    {
+      "path": "../console"
+    },
+    {
+      "path": "../coreutils"
+    },
+    {
+      "path": "../docregistry"
+    },
+    {
+      "path": "../fileeditor"
+    },
+    {
+      "path": "../launcher"
+    },
+    {
+      "path": "../notebook"
+    },
+    {
+      "path": "../observables"
+    },
+    {
+      "path": "../services"
+    },
+    {
+      "path": "../settingregistry"
+    },
+    {
+      "path": "../ui-components"
+    }
+  ]
 }

+ 6 - 0
packages/metapackage/tsconfig.json

@@ -60,6 +60,12 @@
     {
       "path": "../csvviewer-extension"
     },
+    {
+      "path": "../debugger"
+    },
+    {
+      "path": "../debugger-extension"
+    },
     {
       "path": "../docmanager"
     },