Skip to content

Commit 324824a

Browse files
authored
Fix a bunch of debugger issues (#10572)
* Fix notebook taking ownership of hash provider * Fix last line removal and startup of interactive window during debugging * Add news entries
1 parent 6500b2a commit 324824a

File tree

11 files changed

+71
-45
lines changed

11 files changed

+71
-45
lines changed

news/2 Fixes/10206.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix interactive window debugging after running cells in a notebook.

news/2 Fixes/10395.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix interactive window debugging when debugging the first cell to be run.

news/2 Fixes/10396.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix interactive window debugging for extra lines in a function.

src/client/datascience/editor-integration/cellhashprovider.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ export class CellHashProvider implements ICellHashProvider, IInteractiveWindowLi
136136
return lines;
137137
}
138138

139+
// tslint:disable-next-line: cyclomatic-complexity
139140
public async addCellHash(cell: ICell, expectedCount: number): Promise<void> {
140141
// Find the text document that matches. We need more information than
141142
// the add code gives us
@@ -163,14 +164,25 @@ export class CellHashProvider implements ICellHashProvider, IInteractiveWindowLi
163164
const endOffset = doc.offsetAt(endLine.rangeIncludingLineBreak.end);
164165

165166
// Jupyter also removes blank lines at the end. Make sure only one
166-
let lastLine = stripped[stripped.length - 1];
167-
while (lastLine !== undefined && (lastLine.length === 0 || lastLine === '\n')) {
168-
stripped.splice(stripped.length - 1, 1);
169-
lastLine = stripped[stripped.length - 1];
167+
let lastLinePos = stripped.length - 1;
168+
let nextToLastLinePos = stripped.length - 2;
169+
while (nextToLastLinePos > 0) {
170+
const lastLine = stripped[lastLinePos];
171+
const nextToLastLine = stripped[nextToLastLinePos];
172+
if (
173+
(lastLine.length === 0 || lastLine === '\n') &&
174+
(nextToLastLine.length === 0 || nextToLastLine === '\n')
175+
) {
176+
stripped.splice(lastLinePos, 1);
177+
lastLinePos -= 1;
178+
nextToLastLinePos -= 1;
179+
} else {
180+
break;
181+
}
170182
}
171183
// Make sure the last line with actual content ends with a linefeed
172-
if (!lastLine.endsWith('\n') && lastLine.length > 0) {
173-
stripped[stripped.length - 1] = `${lastLine}\n`;
184+
if (!stripped[lastLinePos].endsWith('\n') && stripped[lastLinePos].length > 0) {
185+
stripped[lastLinePos] = `${stripped[lastLinePos]}\n`;
174186
}
175187

176188
// Compute the runtime line and adjust our cell/stripped source for debugging

src/client/datascience/interactive-common/interactiveBase.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,11 +1159,11 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
11591159
// Create a new notebook if we need to.
11601160
if (!this._notebook) {
11611161
// While waiting make the notebook look busy
1162-
await this.postMessage(InteractiveWindowMessages.UpdateKernel, {
1162+
this.postMessage(InteractiveWindowMessages.UpdateKernel, {
11631163
jupyterServerStatus: ServerStatus.Busy,
11641164
localizedUri: this.getServerUri(server),
11651165
displayName: ''
1166-
});
1166+
}).ignoreErrors();
11671167

11681168
this._notebook = await this.createNotebook(server);
11691169

src/client/datascience/interactive-window/interactiveWindow.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,7 @@ export class InteractiveWindow extends InteractiveBase implements IInteractiveWi
181181
}
182182

183183
public async addCode(code: string, file: string, line: number): Promise<boolean> {
184-
if (this.lastFile && !this.fileSystem.arePathsSame(file, this.lastFile)) {
185-
sendTelemetryEvent(Telemetry.NewFileForInteractiveWindow);
186-
}
187-
// Save the last file we ran with.
188-
this.lastFile = file;
189-
190-
// Make sure our web panel opens.
191-
await this.show();
192-
193-
// Tell the webpanel about the new directory.
194-
this.updateCwd(path.dirname(file));
195-
196-
// Call the internal method.
197-
return this.submitCode(code, file, line);
184+
return this.addOrDebugCode(code, file, line, false);
198185
}
199186

200187
public exportCells() {
@@ -252,7 +239,7 @@ export class InteractiveWindow extends InteractiveBase implements IInteractiveWi
252239

253240
// Call the internal method if we were able to save
254241
if (saved) {
255-
return this.submitCode(code, file, line, undefined, undefined, true);
242+
return this.addOrDebugCode(code, file, line, true);
256243
}
257244

258245
return false;
@@ -365,6 +352,23 @@ export class InteractiveWindow extends InteractiveBase implements IInteractiveWi
365352
return super.ensureServerAndNotebook();
366353
}
367354

355+
private async addOrDebugCode(code: string, file: string, line: number, debug: boolean): Promise<boolean> {
356+
if (this.lastFile && !this.fileSystem.arePathsSame(file, this.lastFile)) {
357+
sendTelemetryEvent(Telemetry.NewFileForInteractiveWindow);
358+
}
359+
// Save the last file we ran with.
360+
this.lastFile = file;
361+
362+
// Make sure our web panel opens.
363+
await this.show();
364+
365+
// Tell the webpanel about the new directory.
366+
this.updateCwd(path.dirname(file));
367+
368+
// Call the internal method.
369+
return this.submitCode(code, file, line, undefined, undefined, debug);
370+
}
371+
368372
@captureTelemetry(Telemetry.ExportNotebook, undefined, false)
369373
// tslint:disable-next-line: no-any no-empty
370374
private async export(cells: ICell[]) {

src/client/datascience/jupyter/jupyterNotebook.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ export class JupyterNotebookBase implements INotebook {
154154
private _identity: Uri;
155155
private _disposed: boolean = false;
156156
private _workingDirectory: string | undefined;
157-
private _loggers: INotebookExecutionLogger[] = [];
158157
private onStatusChangedEvent: EventEmitter<ServerStatus> | undefined;
159158
public get onKernelChanged(): Event<IJupyterKernelSpec | LiveKernelModel> {
160159
return this.kernelChanged.event;
@@ -170,7 +169,7 @@ export class JupyterNotebookBase implements INotebook {
170169
private disposableRegistry: IDisposableRegistry,
171170
private owner: INotebookServer,
172171
private launchInfo: INotebookServerLaunchInfo,
173-
loggers: INotebookExecutionLogger[],
172+
private loggers: INotebookExecutionLogger[],
174173
resource: Resource,
175174
identity: Uri,
176175
private getDisposedError: () => Error,
@@ -188,7 +187,6 @@ export class JupyterNotebookBase implements INotebook {
188187
this.sessionStatusChanged = this.session.onSessionStatusChanged(statusChangeHandler);
189188
this._identity = identity;
190189
this._resource = resource;
191-
this._loggers = [...loggers];
192190
// Save our interpreter and don't change it. Later on when kernel changes
193191
// are possible, recompute it.
194192
}
@@ -617,7 +615,7 @@ export class JupyterNotebookBase implements INotebook {
617615
}
618616

619617
public getLoggers(): INotebookExecutionLogger[] {
620-
return this._loggers;
618+
return this.loggers;
621619
}
622620

623621
private async initializeMatplotlib(cancelToken?: CancellationToken): Promise<void> {
@@ -1051,11 +1049,11 @@ export class JupyterNotebookBase implements INotebook {
10511049
}
10521050

10531051
private async logPreCode(cell: ICell, silent: boolean): Promise<void> {
1054-
await Promise.all(this._loggers.map(l => l.preExecute(cell, silent)));
1052+
await Promise.all(this.loggers.map(l => l.preExecute(cell, silent)));
10551053
}
10561054

10571055
private async logPostCode(cell: ICell, silent: boolean): Promise<void> {
1058-
await Promise.all(this._loggers.map(l => l.postExecute(cloneDeep(cell), silent)));
1056+
await Promise.all(this.loggers.map(l => l.postExecute(cloneDeep(cell), silent)));
10591057
}
10601058

10611059
private addToCellData = (

src/client/datascience/jupyter/jupyterServer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ import {
1818
import { createDeferred, Deferred } from '../../common/utils/async';
1919
import * as localize from '../../common/utils/localize';
2020
import { noop } from '../../common/utils/misc';
21+
import { IServiceContainer } from '../../ioc/types';
2122
import {
2223
IConnection,
2324
IJupyterSession,
2425
IJupyterSessionManager,
2526
IJupyterSessionManagerFactory,
2627
INotebook,
27-
INotebookExecutionLogger,
2828
INotebookServer,
2929
INotebookServerLaunchInfo
3030
} from '../types';
@@ -48,7 +48,7 @@ export class JupyterServerBase implements INotebookServer {
4848
private disposableRegistry: IDisposableRegistry,
4949
protected readonly configService: IConfigurationService,
5050
private sessionManagerFactory: IJupyterSessionManagerFactory,
51-
private loggers: INotebookExecutionLogger[],
51+
private serviceContainer: IServiceContainer,
5252
private jupyterOutputChannel: IOutputChannel
5353
) {
5454
this.asyncRegistry.push(this);
@@ -115,7 +115,7 @@ export class JupyterServerBase implements INotebookServer {
115115
savedSession,
116116
this.disposableRegistry,
117117
this.configService,
118-
this.loggers,
118+
this.serviceContainer,
119119
notebookMetadata,
120120
cancelToken
121121
).then(r => {
@@ -223,7 +223,7 @@ export class JupyterServerBase implements INotebookServer {
223223
_savedSession: IJupyterSession | undefined,
224224
_disposableRegistry: IDisposableRegistry,
225225
_configService: IConfigurationService,
226-
_loggers: INotebookExecutionLogger[],
226+
_serviceContainer: IServiceContainer,
227227
_notebookMetadata?: nbformat.INotebookMetadata,
228228
_cancelToken?: CancellationToken
229229
): Promise<INotebook> {

src/client/datascience/jupyter/jupyterServerWrapper.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33
'use strict';
44
import { nbformat } from '@jupyterlab/coreutils';
5-
import { inject, injectable, multiInject, named, optional } from 'inversify';
5+
import { inject, injectable, named } from 'inversify';
66
import * as uuid from 'uuid/v4';
77
import { Uri } from 'vscode';
88
import { CancellationToken } from 'vscode-jsonrpc';
@@ -18,13 +18,13 @@ import {
1818
Resource
1919
} from '../../common/types';
2020
import { IInterpreterService } from '../../interpreter/contracts';
21+
import { IServiceContainer } from '../../ioc/types';
2122
import { JUPYTER_OUTPUT_CHANNEL } from '../constants';
2223
import {
2324
IConnection,
2425
IDataScience,
2526
IJupyterSessionManagerFactory,
2627
INotebook,
27-
INotebookExecutionLogger,
2828
INotebookServer,
2929
INotebookServerLaunchInfo
3030
} from '../types';
@@ -46,7 +46,7 @@ type JupyterServerClassType = {
4646
configService: IConfigurationService,
4747
sessionManager: IJupyterSessionManagerFactory,
4848
workspaceService: IWorkspaceService,
49-
loggers: INotebookExecutionLogger[],
49+
serviceContainer: IServiceContainer,
5050
appShell: IApplicationShell,
5151
fs: IFileSystem,
5252
kernelSelector: KernelSelector,
@@ -73,12 +73,12 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
7373
@inject(IConfigurationService) configService: IConfigurationService,
7474
@inject(IJupyterSessionManagerFactory) sessionManager: IJupyterSessionManagerFactory,
7575
@inject(IWorkspaceService) workspaceService: IWorkspaceService,
76-
@multiInject(INotebookExecutionLogger) @optional() loggers: INotebookExecutionLogger[] | undefined,
7776
@inject(IApplicationShell) appShell: IApplicationShell,
7877
@inject(IFileSystem) fs: IFileSystem,
7978
@inject(IInterpreterService) interpreterService: IInterpreterService,
8079
@inject(KernelSelector) kernelSelector: KernelSelector,
81-
@inject(IOutputChannel) @named(JUPYTER_OUTPUT_CHANNEL) jupyterOutput: IOutputChannel
80+
@inject(IOutputChannel) @named(JUPYTER_OUTPUT_CHANNEL) jupyterOutput: IOutputChannel,
81+
@inject(IServiceContainer) serviceContainer: IServiceContainer
8282
) {
8383
// The server factory will create the appropriate HostJupyterServer or GuestJupyterServer based on
8484
// the liveshare state.
@@ -93,7 +93,7 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole
9393
configService,
9494
sessionManager,
9595
workspaceService,
96-
loggers ? loggers : [],
96+
serviceContainer,
9797
appShell,
9898
fs,
9999
kernelSelector,

src/client/datascience/jupyter/liveshare/guestJupyterServer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import { ILiveShareApi, IWorkspaceService } from '../../../common/application/ty
99
import { IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry, Resource } from '../../../common/types';
1010
import { createDeferred, Deferred } from '../../../common/utils/async';
1111
import * as localize from '../../../common/utils/localize';
12+
import { IServiceContainer } from '../../../ioc/types';
1213
import { LiveShare, LiveShareCommands } from '../../constants';
1314
import {
1415
IConnection,
1516
IDataScience,
1617
IJupyterSessionManagerFactory,
1718
INotebook,
18-
INotebookExecutionLogger,
1919
INotebookServer,
2020
INotebookServerLaunchInfo
2121
} from '../../types';
@@ -39,7 +39,7 @@ export class GuestJupyterServer
3939
private configService: IConfigurationService,
4040
_sessionManager: IJupyterSessionManagerFactory,
4141
_workspaceService: IWorkspaceService,
42-
_loggers: INotebookExecutionLogger[]
42+
_serviceContainer: IServiceContainer
4343
) {
4444
super(liveShare);
4545
}

src/client/datascience/jupyter/liveshare/hostJupyterServer.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
} from '../../../common/types';
2323
import * as localize from '../../../common/utils/localize';
2424
import { IInterpreterService } from '../../../interpreter/contracts';
25+
import { IServiceContainer } from '../../../ioc/types';
2526
import { Identifiers, LiveShare, LiveShareCommands, RegExpValues } from '../../constants';
2627
import {
2728
IDataScience,
@@ -55,14 +56,22 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
5556
configService: IConfigurationService,
5657
sessionManager: IJupyterSessionManagerFactory,
5758
private workspaceService: IWorkspaceService,
58-
loggers: INotebookExecutionLogger[],
59+
serviceContainer: IServiceContainer,
5960
private appService: IApplicationShell,
6061
private fs: IFileSystem,
6162
private readonly kernelSelector: KernelSelector,
6263
private readonly interpreterService: IInterpreterService,
6364
outputChannel: IOutputChannel
6465
) {
65-
super(liveShare, asyncRegistry, disposableRegistry, configService, sessionManager, loggers, outputChannel);
66+
super(
67+
liveShare,
68+
asyncRegistry,
69+
disposableRegistry,
70+
configService,
71+
sessionManager,
72+
serviceContainer,
73+
outputChannel
74+
);
6675
}
6776

6877
public async dispose(): Promise<void> {
@@ -163,7 +172,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
163172
possibleSession: IJupyterSession | undefined,
164173
disposableRegistry: IDisposableRegistry,
165174
configService: IConfigurationService,
166-
loggers: INotebookExecutionLogger[],
175+
serviceContainer: IServiceContainer,
167176
notebookMetadata?: nbformat.INotebookMetadata,
168177
cancelToken?: CancellationToken
169178
): Promise<INotebook> {
@@ -208,7 +217,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas
208217
disposableRegistry,
209218
this,
210219
info,
211-
loggers,
220+
serviceContainer.getAll<INotebookExecutionLogger>(INotebookExecutionLogger),
212221
resource,
213222
identity,
214223
this.getDisposedError.bind(this),

0 commit comments

Comments
 (0)