소스 검색

Moved code hashing in service and restored restart

Johan Mabille 5 년 전
부모
커밋
37b28e921e
4개의 변경된 파일105개의 추가작업 그리고 50개의 파일을 삭제
  1. 5 28
      src/breakpoints/index.ts
  2. 13 6
      src/handlers/cell.ts
  3. 70 14
      src/service.ts
  4. 17 2
      src/tokens.ts

+ 5 - 28
src/breakpoints/index.ts

@@ -5,7 +5,6 @@ import { Toolbar, ToolbarButton } from '@jupyterlab/apputils';
 import { IDisposable } from '@phosphor/disposable';
 import { Signal } from '@phosphor/signaling';
 import { Panel, PanelLayout, Widget } from '@phosphor/widgets';
-import { murmur2 } from 'murmurhash-js';
 import { DebugProtocol } from 'vscode-debugprotocol';
 import { IDebugger } from '../tokens';
 import { Body } from './body';
@@ -48,7 +47,7 @@ export class Breakpoints extends Panel {
       new ToolbarButton({
         iconClassName: 'jp-CloseAllIcon',
         onClick: () => {
-          void this.service.updateBreakpoints([]);
+          void this.service.clearBreakpoints();
         },
         tooltip: 'Remove All Breakpoints'
       })
@@ -83,16 +82,6 @@ export namespace Breakpoints {
   }
 
   export class Model implements IDisposable {
-    setHashParameters(method: string, seed: number) {
-      if (method === 'Murmur2') {
-        this._hashMethod = (code: string) => {
-          return murmur2(code, seed).toString();
-        };
-      } else {
-        throw new Error('hash method not supported ' + method);
-      }
-    }
-
     get changed(): Signal<this, IBreakpoint[]> {
       return this._changed;
     }
@@ -122,17 +111,13 @@ export namespace Breakpoints {
       Signal.clearData(this);
     }
 
-    hash(code: string): string {
-      return this._hashMethod(code);
-    }
-
-    setBreakpoints(code: string, breakpoints: IBreakpoint[]) {
-      this._breakpoints.set(this.hash(code), breakpoints);
+    setBreakpoints(id: string, breakpoints: IBreakpoint[]) {
+      this._breakpoints.set(id, breakpoints);
       this.changed.emit(breakpoints);
     }
 
-    getBreakpoints(code: string): IBreakpoint[] {
-      return this._breakpoints.get(this.hash(code)) || [];
+    getBreakpoints(id: string): IBreakpoint[] {
+      return this._breakpoints.get(id) || [];
     }
 
     restoreBreakpoints(breakpoints: Map<string, IBreakpoint[]>) {
@@ -140,14 +125,6 @@ export namespace Breakpoints {
       this._restored.emit();
     }
 
-    /*private printMap() {
-      this._breakpoints.forEach((value, key, map) => {
-        console.log(key);
-        value.forEach((bp) => console.log(bp.line));
-      });
-    }*/
-
-    private _hashMethod: (code: string) => string;
     private _breakpoints = new Map<string, IBreakpoint[]>();
     private _changed = new Signal<this, IBreakpoint[]>(this);
     private _restored = new Signal<this, void>(this);

+ 13 - 6
src/handlers/cell.ts

@@ -175,8 +175,8 @@ export class CellManager implements IDisposable {
     }
 
     const isRemoveGutter = !!info.gutterMarkers;
-    let breakpoints: Breakpoints.IBreakpoint[] = this.breakpointsModel.getBreakpoints(
-      this._activeCell.model.value.text
+    let breakpoints: Breakpoints.IBreakpoint[] = this.getBreakpoints(
+      this._activeCell
     );
     if (isRemoveGutter) {
       breakpoints = breakpoints.filter(ele => ele.line !== info.line + 1);
@@ -190,15 +190,16 @@ export class CellManager implements IDisposable {
       );
     }
 
-    void this._debuggerService.updateBreakpoints(breakpoints);
+    void this._debuggerService.updateBreakpoints(
+      this._activeCell.model.value.text,
+      breakpoints
+    );
   };
 
   private addBreakpointsToEditor(cell: CodeCell) {
     this.clearGutter(cell);
     const editor = cell.editor as CodeMirrorEditor;
-    const breakpoints = this._debuggerModel.breakpointsModel.getBreakpoints(
-      cell.model.value.text
-    );
+    const breakpoints = this.getBreakpoints(cell);
     breakpoints.forEach(breakpoint => {
       editor.editor.setGutterMarker(
         breakpoint.line - 1,
@@ -208,6 +209,12 @@ export class CellManager implements IDisposable {
     });
   }
 
+  private getBreakpoints(cell: CodeCell): Breakpoints.IBreakpoint[] {
+    return this._debuggerModel.breakpointsModel.getBreakpoints(
+      this._debuggerService.getCellId(cell.model.value.text)
+    );
+  }
+
   private _previousCell: CodeCell;
   private _debuggerModel: Debugger.Model;
   private breakpointsModel: Breakpoints.Model;

+ 70 - 14
src/service.ts

@@ -5,6 +5,8 @@ import { IClientSession } from '@jupyterlab/apputils';
 
 import { ISignal, Signal } from '@phosphor/signaling';
 
+import { murmur2 } from 'murmurhash-js';
+
 import { DebugProtocol } from 'vscode-debugprotocol';
 
 import { Debugger } from './debugger';
@@ -140,6 +142,13 @@ export class DebugService implements IDebugger {
     Signal.clearData(this);
   }
 
+  /**
+   * Computes an id based on the given code.
+   */
+  getCellId(code: string): string {
+    return this._tmpFilePrefix + this._hashMethod(code) + this._tmpFileSuffix;
+  }
+
   /**
    * Whether the current debugger is started.
    */
@@ -175,12 +184,21 @@ export class DebugService implements IDebugger {
    * Precondition: isStarted() and stopped.
    */
   async restart(): Promise<void> {
-    // const breakpoints = this.model.breakpointsModel.breakpoints;
+    const breakpoints = this.model.breakpointsModel.breakpoints;
     await this.stop();
     this.clearModel();
     this._stoppedThreads.clear();
     await this.start();
-    // await this.updateBreakpoints(breakpoints);
+
+    // No need to dump the cells again, we can simply
+    // resend the breakpoints to the kernel and update
+    // the model.
+    breakpoints.forEach(async (bp, path, _) => {
+      const sourceBreakpoints = Private.toSourceBreakpoints(bp);
+      await this.setBreakpoints(sourceBreakpoints, path);
+    });
+
+    this.model.breakpointsModel.restoreBreakpoints(breakpoints);
   }
 
   /**
@@ -196,20 +214,18 @@ export class DebugService implements IDebugger {
 
     const reply = await this.session.restoreState();
 
-    this._model.breakpointsModel.setHashParameters(
-      reply.body.hashMethod,
-      reply.body.hashSeed
+    this.setHashParameters(reply.body.hashMethod, reply.body.hashSeed);
+    this.setTmpFileParameters(
+      reply.body.tmp_file_prefix,
+      reply.body.tmp_file_suffix
     );
 
     const breakpoints = reply.body.breakpoints;
     let bpMap = new Map<string, Breakpoints.IBreakpoint[]>();
     if (breakpoints.length !== 0) {
-      const prefix = reply.body.tmp_file_prefix;
-      const suffix = reply.body.tmp_file_suffix;
       breakpoints.forEach((bp: IDebugger.ISession.IDebugInfoBreakpoints) => {
-        let id = bp.source.replace(prefix, '').replace(suffix, '');
         bpMap.set(
-          id,
+          bp.source,
           bp.breakpoints.map(breakpoint => {
             return {
               ...breakpoint,
@@ -281,14 +297,18 @@ export class DebugService implements IDebugger {
 
   /**
    * Update all breakpoints at once.
+   * @param code - The code in the cell where the breakpoints are set.
+   * @param breakpoints - The list of breakpoints to set.
    */
-  async updateBreakpoints(breakpoints: Breakpoints.IBreakpoint[]) {
+  async updateBreakpoints(
+    code: string,
+    breakpoints: Breakpoints.IBreakpoint[]
+  ) {
     if (!this.session.isStarted) {
       return;
     }
     // Workaround: this should not be called before the session has started
     await this.ensureSessionReady();
-    const code = this._model.codeValue.text;
     const dumpedCell = await this.dumpCell(code);
     const sourceBreakpoints = Private.toSourceBreakpoints(breakpoints);
     const reply = await this.setBreakpoints(
@@ -298,8 +318,7 @@ export class DebugService implements IDebugger {
     let kernelBreakpoints = reply.body.breakpoints.map(breakpoint => {
       return {
         ...breakpoint,
-        active: true,
-        source: { path: this.session.client.name }
+        active: true
       };
     });
 
@@ -308,10 +327,28 @@ export class DebugService implements IDebugger {
       (breakpoint, i, arr) =>
         arr.findIndex(el => el.line === breakpoint.line) === i
     );
-    this._model.breakpointsModel.setBreakpoints(code, kernelBreakpoints);
+    this._model.breakpointsModel.setBreakpoints(
+      dumpedCell.sourcePath,
+      kernelBreakpoints
+    );
     await this.session.sendRequest('configurationDone', {});
   }
 
+  async clearBreakpoints() {
+    if (!this.session.isStarted) {
+      return;
+    }
+
+    this._model.breakpointsModel.breakpoints.forEach(
+      async (breakpoints, path, _) => {
+        await this.setBreakpoints([], path);
+      }
+    );
+
+    let bpMap = new Map<string, Breakpoints.IBreakpoint[]>();
+    this._model.breakpointsModel.restoreBreakpoints(bpMap);
+  }
+
   getAllFrames = async () => {
     const stackFrames = await this.getFrames(this.currentThread());
 
@@ -420,6 +457,21 @@ export class DebugService implements IDebugger {
     return 1;
   }
 
+  private setHashParameters(method: string, seed: number) {
+    if (method === 'Murmur2') {
+      this._hashMethod = (code: string) => {
+        return murmur2(code, seed).toString();
+      };
+    } else {
+      throw new Error('hash method not supported ' + method);
+    }
+  }
+
+  private setTmpFileParameters(prefix: string, suffix: string) {
+    this._tmpFilePrefix = prefix;
+    this._tmpFileSuffix = suffix;
+  }
+
   private _isDisposed: boolean = false;
   private _session: IDebugger.ISession;
   private _sessionChanged = new Signal<IDebugger, IDebugger.ISession>(this);
@@ -427,6 +479,10 @@ export class DebugService implements IDebugger {
   private _eventMessage = new Signal<IDebugger, IDebugger.ISession.Event>(this);
   private _model: Debugger.Model;
 
+  private _hashMethod: (code: string) => string;
+  private _tmpFilePrefix: string;
+  private _tmpFileSuffix: string;
+
   // TODO: remove frames from the service
   private frames: Frame[] = [];
 

+ 17 - 2
src/tokens.ts

@@ -56,6 +56,11 @@ export interface IDebugger extends IDisposable {
    */
   readonly eventMessage: ISignal<IDebugger, IDebugger.ISession.Event>;
 
+  /**
+   * Computes an id based on the given code.
+   */
+  getCellId(code: string): string;
+
   /**
    * Whether the current debugger is started.
    */
@@ -112,9 +117,19 @@ export interface IDebugger extends IDisposable {
   stepOut(): Promise<void>;
 
   /**
-   * Update all breakpoints at once.
+   * Update all breakpoints of a cell at once.
+   * @param code - The code in the cell where the breakpoints are set.
+   * @param breakpoints - The list of breakpoints to set.
+   */
+  updateBreakpoints(
+    code: string,
+    breakpoints: Breakpoints.IBreakpoint[]
+  ): Promise<void>;
+
+  /**
+   * Removes all the breakpoints from the current notebook or console
    */
-  updateBreakpoints(breakpoints: Breakpoints.IBreakpoint[]): Promise<void>;
+  clearBreakpoints(): Promise<void>;
 }
 
 /**