Browse Source

add service and debug sidebar when scopes is empty

Borys Palka 5 years ago
parent
commit
ffa78b9fdd
7 changed files with 184 additions and 115 deletions
  1. 21 21
      src/callstack/index.ts
  2. 21 0
      src/debugger.ts
  3. 5 2
      src/handlers/cell.ts
  4. 19 0
      src/index.ts
  5. 98 0
      src/service.ts
  6. 12 11
      src/variables/body/search.tsx
  7. 8 81
      src/variables/index.ts

+ 21 - 21
src/callstack/index.ts

@@ -11,7 +11,7 @@ export class Callstack extends Panel {
   constructor(options: Callstack.IOptions = {}) {
     super();
 
-    this.model = new Callstack.IModel(MOCK_FRAMES);
+    this.model = new Callstack.IModel([]);
     this.addClass('jp-DebuggerCallstack');
     this.title.label = 'Callstack';
 
@@ -116,23 +116,23 @@ export namespace Callstack {
   export interface IOptions extends Panel.IOptions {}
 }
 
-const MOCK_FRAMES: Callstack.IFrame[] = [
-  {
-    id: 0,
-    name: 'test',
-    source: {
-      name: 'untitled.py'
-    },
-    line: 6,
-    column: 1
-  },
-  {
-    id: 1,
-    name: '<module>',
-    source: {
-      name: 'untitled.py'
-    },
-    line: 7,
-    column: 1
-  }
-];
+// const MOCK_FRAMES: Callstack.IFrame[] = [
+//   {
+//     id: 0,
+//     name: 'test',
+//     source: {
+//       name: 'untitled.py'
+//     },
+//     line: 6,
+//     column: 1
+//   },
+//   {
+//     id: 1,
+//     name: '<module>',
+//     source: {
+//       name: 'untitled.py'
+//     },
+//     line: 7,
+//     column: 1
+//   }
+// ];

+ 21 - 0
src/debugger.ts

@@ -17,6 +17,12 @@ import { IDebugger } from './tokens';
 
 import { DebuggerSidebar } from './sidebar';
 
+import { IObservableString } from '@jupyterlab/observables';
+
+import { DebugService } from './service';
+
+import { DebugSession } from './session';
+
 export class Debugger extends BoxPanel {
   constructor(options: Debugger.IOptions) {
     super({ direction: 'left-to-right' });
@@ -104,9 +110,14 @@ export namespace Debugger {
         this._session.dispose();
       }
       this._session = session;
+      this._service.session = session as DebugSession;
       this._sessionChanged.emit(undefined);
     }
 
+    get service(): DebugService {
+      return this._service;
+    }
+
     get sessionChanged(): ISignal<this, void> {
       return this._sessionChanged;
     }
@@ -115,6 +126,14 @@ export namespace Debugger {
       return this._isDisposed;
     }
 
+    get codeValue() {
+      return this._codeValue;
+    }
+
+    set codeValue(observableString: IObservableString) {
+      this._codeValue = observableString;
+    }
+
     dispose(): void {
       this._isDisposed = true;
     }
@@ -127,12 +146,14 @@ export namespace Debugger {
       }
     }
 
+    private _codeValue: IObservableString;
     private _sidebar: DebuggerSidebar;
     private _isDisposed = false;
     private _mode: IDebugger.Mode;
     private _modeChanged = new Signal<this, IDebugger.Mode>(this);
     private _session: IDebugger.ISession | null;
     private _sessionChanged = new Signal<this, void>(this);
+    private _service = new DebugService(null, this);
   }
 
   export namespace Model {

+ 5 - 2
src/handlers/cell.ts

@@ -56,8 +56,11 @@ export class CellManager implements IDisposable {
   }
 
   set activeCell(cell: CodeCell) {
-    this._activeCell = cell;
-    this.onActiveCellChanged();
+    if (cell) {
+      this._activeCell = cell;
+      this._debuggerModel.codeValue = cell.model.value;
+      this.onActiveCellChanged();
+    }
   }
 
   get activeCell(): CodeCell {

+ 19 - 0
src/index.ts

@@ -221,6 +221,7 @@ const main: JupyterFrontEndPlugin<IDebugger> = {
       namespace: 'debugger'
     });
     const { commands, shell } = app;
+    const categoryLabel = 'Debugger';
     let widget: MainAreaWidget<Debugger>;
 
     const getModel = () => {
@@ -296,6 +297,20 @@ const main: JupyterFrontEndPlugin<IDebugger> = {
       }
     });
 
+    commands.addCommand(CommandIDs.debugNotebook, {
+      label: 'Launch',
+      isEnabled: () => {
+        const debuggerModel = getModel();
+        return (debuggerModel &&
+          debuggerModel.session !== null &&
+          debuggerModel.session.isStarted) as boolean;
+      },
+      execute: async () => {
+        const debuggerModel = getModel();
+        await debuggerModel.service.launch(debuggerModel.codeValue.text);
+      }
+    });
+
     commands.addCommand(CommandIDs.changeMode, {
       label: 'Change Mode',
       isEnabled: () => {
@@ -356,6 +371,10 @@ const main: JupyterFrontEndPlugin<IDebugger> = {
       palette.addItem({ command: CommandIDs.create, category: 'Debugger' });
       palette.addItem({ command: CommandIDs.start, category: 'Debugger' });
       palette.addItem({ command: CommandIDs.stop, category: 'Debugger' });
+      palette.addItem({
+        command: CommandIDs.debugNotebook,
+        category: categoryLabel
+      });
     }
 
     if (restorer) {

+ 98 - 0
src/service.ts

@@ -0,0 +1,98 @@
+import { DebugSession } from './session';
+import { IDebugger } from './tokens';
+import { DebugProtocol } from 'vscode-debugprotocol';
+import { Debugger } from './debugger';
+
+export class DebugService {
+  constructor(session: DebugSession | null, debuggerModel: Debugger.Model) {
+    this.session = session;
+    this.model = debuggerModel;
+  }
+
+  private _session: DebugSession;
+  // private _currentFrame: DebugProtocol.StackFrame;
+  private _debuggerModel: Debugger.Model;
+
+  set session(session: DebugSession) {
+    this._session = session;
+  }
+
+  get session() {
+    return this._session;
+  }
+
+  get model() {
+    return this._debuggerModel;
+  }
+
+  set model(model: Debugger.Model) {
+    this._debuggerModel = model;
+  }
+
+  // this will change for after execute cell
+  async launch(code: string): Promise<void> {
+    let threadId: number = 1;
+
+    this.session.eventMessage.connect(
+      (sender: DebugSession, event: IDebugger.ISession.Event) => {
+        const eventName = event.event;
+        if (eventName === 'thread') {
+          const msg = event as DebugProtocol.ThreadEvent;
+          threadId = msg.body.threadId;
+        }
+      }
+    );
+
+    const breakpoints: DebugProtocol.SourceBreakpoint[] = this.setBreakpoints();
+    const reply = await this.session
+      .sendRequest('dumpCell', {
+        code
+      })
+      .catch(error => error);
+
+    await this.session.sendRequest('setBreakpoints', {
+      breakpoints: breakpoints,
+      source: { path: reply.body.sourcePath },
+      sourceModified: false
+    });
+    await this.session.sendRequest('configurationDone', {});
+
+    this.session.client.kernel.requestExecute({ code });
+
+    const stackFrameReply = await this.getFrames(threadId);
+    const scopeReply = await this.getScopes(stackFrameReply);
+    const variablesReply = await this.getVariables(scopeReply);
+
+    console.log({ variablesReply, scopeReply, stackFrameReply });
+  }
+
+  getFrames = async (threadId: number) => {
+    const reply = await this.session.sendRequest('stackTrace', {
+      threadId
+    });
+    const stackFrames = reply.body.stackFrames;
+    return stackFrames;
+  };
+
+  getScopes = async (frame: DebugProtocol.StackFrame[]) => {
+    const reply = await this.session.sendRequest('scopes', {
+      frameId: frame[0].id
+    });
+    return reply.body.scopes;
+  };
+
+  getVariables = async (scopes: DebugProtocol.Scope[]) => {
+    const reply = await this.session.sendRequest('variables', {
+      variablesReference: scopes[0].variablesReference
+    });
+    return reply.body.variables;
+  };
+
+  setBreakpoints = (): DebugProtocol.SourceBreakpoint[] => {
+    return this.model.sidebar.breakpoints.model.breakpoints.map(breakpoint => {
+      return {
+        line: breakpoint.line
+      };
+    });
+  };
+}

+ 12 - 11
src/variables/body/search.tsx

@@ -97,12 +97,21 @@ const ScopeMenuComponent = ({ model }: { model: Variables.IModel }) => {
   const wrapperRef = useRef(null);
   const scopes = model.scopes;
 
+  const ListScopes = () =>
+    scopes.map(scope => (
+      <li key={scope.name} onClick={e => changeScope(scope)}>
+        {scope.name}
+      </li>
+    ));
+
   const onClickOutSide = () => {
     setToggle(false);
   };
 
   const toggle = (e: any) => {
-    setToggle(!toggleState);
+    if (!!scopes) {
+      setToggle(!toggleState);
+    }
   };
 
   useOutsideClick(wrapperRef, onClickOutSide);
@@ -116,19 +125,11 @@ const ScopeMenuComponent = ({ model }: { model: Variables.IModel }) => {
     setToggle(false);
   };
 
-  const List = (
-    <ul>
-      {scopes.map(scope => (
-        <li key={scope.name} onClick={e => changeScope(scope)}>
-          {scope.name}
-        </li>
-      ))}
-    </ul>
-  );
+  const List = <ul>{!!scopes ? ListScopes : null}</ul>;
 
   return (
     <div onClick={e => toggle(e)} ref={wrapperRef}>
-      <span className="label">{scope.name}</span>
+      <span className="label">{scope ? scope.name : '-'}</span>
       <span className="fa fa-caret-down"></span>
       {toggleState ? List : null}
     </div>

+ 8 - 81
src/variables/index.ts

@@ -13,7 +13,7 @@ export class Variables extends Panel {
   constructor(options: Variables.IOptions = {}) {
     super();
 
-    this.model = new Variables.IModel(MOCK_DATA_ROW.scopes);
+    this.model = new Variables.IModel();
     this.addClass('jp-DebuggerVariables');
     this.title.label = 'Variables';
 
@@ -54,9 +54,9 @@ export namespace Variables {
   export interface IModel {}
 
   export class IModel implements IModel {
-    constructor(model: IScope[]) {
+    constructor(model?: IScope[] | null) {
       this._state = model;
-      this._currentScope = this._state[0];
+      this._currentScope = !!this._state ? this._state[0] : null;
     }
 
     get currentScope(): IScope {
@@ -94,7 +94,9 @@ export namespace Variables {
         return;
       }
       this._filterState = value;
-      this._variablesChanged.emit(this._filterVariables());
+      if (!!this._currentScope) {
+        this._variablesChanged.emit(this._filterVariables());
+      }
     }
 
     get scopes(): IScope[] {
@@ -105,8 +107,9 @@ export namespace Variables {
       if (this._filterState) {
         return this._filterVariables();
       }
-      return this._currentScope.variables;
+      return !!this._currentScope ? this._currentScope.variables : [];
     }
+
     set variables(variables: IVariable[]) {
       this._currentScope.variables = variables;
     }
@@ -138,79 +141,3 @@ export namespace Variables {
 
   export interface IOptions extends Panel.IOptions {}
 }
-
-const MOCK_DATA_ROW = {
-  scopes: [
-    {
-      name: 'local',
-      variables: [
-        {
-          name: 'test 1',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def test1(): return 0'
-        },
-        {
-          name: 'Classtest',
-          value: 'class',
-          type: 'class',
-          variablesReference: 1,
-          description: 'def test2(): return 0'
-        },
-        {
-          name: 'test 3',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def test1(): return 0'
-        },
-        {
-          name: 'test 4',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def test2(): return 0'
-        },
-        {
-          name: 'test 5',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def test1(): return 0'
-        },
-        {
-          name: 'test 6',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def test2(): return 0'
-        }
-      ]
-    },
-    {
-      name: 'global',
-      variables: [
-        {
-          name: 'exampleGlobal',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def exampleGlobal(): return 0'
-        }
-      ] as Variables.IVariable[]
-    },
-    {
-      name: 'built-in',
-      variables: [
-        {
-          name: 'exmapleBuiltIn',
-          value: 'function()',
-          type: 'function',
-          variablesReference: 0,
-          description: 'def texmapleBuiltIn(): return 0'
-        }
-      ] as Variables.IVariable[]
-    }
-  ]
-};