Skip to content

Commit 83dff6a

Browse files
authored
Fix hasCodeCells to update whenever code lens are generated. (microsoft#6226)
1 parent 514d381 commit 83dff6a

File tree

5 files changed

+49
-16
lines changed

5 files changed

+49
-16
lines changed

experiments.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

news/2 Fixes/5879.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix shift+enter to work in newly created files with cells.

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

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,44 @@
44
import { inject, injectable } from 'inversify';
55
import * as vscode from 'vscode';
66

7-
import { IDocumentManager } from '../../common/application/types';
7+
import { ICommandManager, IDocumentManager } from '../../common/application/types';
8+
import { ContextKey } from '../../common/contextKey';
89
import { IConfigurationService, IDataScienceSettings } from '../../common/types';
910
import { IServiceContainer } from '../../ioc/types';
11+
import { EditorContexts } from '../constants';
1012
import { ICodeWatcher, IDataScienceCodeLensProvider } from '../types';
1113

1214
@injectable()
1315
export class DataScienceCodeLensProvider implements IDataScienceCodeLensProvider {
1416
private activeCodeWatchers: ICodeWatcher[] = [];
1517
constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer,
1618
@inject(IDocumentManager) private documentManager: IDocumentManager,
17-
@inject(IConfigurationService) private configuration: IConfigurationService)
19+
@inject(IConfigurationService) private configuration: IConfigurationService,
20+
@inject(ICommandManager) private commandManager: ICommandManager
21+
)
1822
{
1923
}
2024

2125
// CodeLensProvider interface
2226
// Some implementation based on DonJayamanne's jupyter extension work
23-
public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken):
24-
vscode.CodeLens[] {
27+
public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.CodeLens[] {
28+
// Get the list of code lens for this document.
29+
const result = this.getCodeLens(document);
30+
31+
// Update the hasCodeCells context at the same time we are asked for codelens as VS code will
32+
// ask whenever a change occurs.
33+
const editorContext = new ContextKey(EditorContexts.HasCodeCells, this.commandManager);
34+
editorContext.set(result && result.length > 0).catch();
35+
36+
return result;
37+
}
38+
39+
// IDataScienceCodeLensProvider interface
40+
public getCodeWatcher(document: vscode.TextDocument): ICodeWatcher | undefined {
41+
return this.matchWatcher(document.fileName, document.version, this.configuration.getSettings().datascience);
42+
}
43+
44+
private getCodeLens(document: vscode.TextDocument): vscode.CodeLens[] {
2545
// Don't provide any code lenses if we have not enabled data science
2646
const settings = this.configuration.getSettings();
2747
if (!settings.datascience.enabled || !settings.datascience.enableCellCodeLens) {
@@ -46,11 +66,6 @@ export class DataScienceCodeLensProvider implements IDataScienceCodeLensProvider
4666
return newCodeWatcher.getCodeLenses();
4767
}
4868

49-
// IDataScienceCodeLensProvider interface
50-
public getCodeWatcher(document: vscode.TextDocument): ICodeWatcher | undefined {
51-
return this.matchWatcher(document.fileName, document.version, this.configuration.getSettings().datascience);
52-
}
53-
5469
private matchWatcher(fileName: string, version: number, settings: IDataScienceSettings) : ICodeWatcher | undefined {
5570
const index = this.activeCodeWatchers.findIndex(item => item.getFileName() === fileName);
5671
if (index >= 0) {

src/test/datascience/editor-integration/codelensprovider.unit.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,38 @@
44
import * as TypeMoq from 'typemoq';
55
import { CancellationTokenSource, TextDocument } from 'vscode';
66

7-
import { IDocumentManager } from '../../../client/common/application/types';
7+
import { ICommandManager, IDocumentManager } from '../../../client/common/application/types';
88
import { IConfigurationService, IDataScienceSettings, IPythonSettings } from '../../../client/common/types';
99
import { DataScienceCodeLensProvider } from '../../../client/datascience/editor-integration/codelensprovider';
1010
import { ICodeWatcher, IDataScienceCodeLensProvider } from '../../../client/datascience/types';
1111
import { IServiceContainer } from '../../../client/ioc/types';
1212

13+
// tslint:disable-next-line: max-func-body-length
1314
suite('DataScienceCodeLensProvider Unit Tests', () => {
1415
let serviceContainer: TypeMoq.IMock<IServiceContainer>;
1516
let configurationService: TypeMoq.IMock<IConfigurationService>;
1617
let codeLensProvider: IDataScienceCodeLensProvider;
1718
let dataScienceSettings: TypeMoq.IMock<IDataScienceSettings>;
1819
let pythonSettings: TypeMoq.IMock<IPythonSettings>;
1920
let documentManager: TypeMoq.IMock<IDocumentManager>;
21+
let commandManager: TypeMoq.IMock<ICommandManager>;
2022
let tokenSource : CancellationTokenSource;
2123

2224
setup(() => {
2325
tokenSource = new CancellationTokenSource();
2426
serviceContainer = TypeMoq.Mock.ofType<IServiceContainer>();
2527
configurationService = TypeMoq.Mock.ofType<IConfigurationService>();
2628
documentManager = TypeMoq.Mock.ofType<IDocumentManager>();
29+
commandManager = TypeMoq.Mock.ofType<ICommandManager>();
2730

2831
pythonSettings = TypeMoq.Mock.ofType<IPythonSettings>();
2932
dataScienceSettings = TypeMoq.Mock.ofType<IDataScienceSettings>();
3033
dataScienceSettings.setup(d => d.enabled).returns(() => true);
3134
pythonSettings.setup(p => p.datascience).returns(() => dataScienceSettings.object);
3235
configurationService.setup(c => c.getSettings(TypeMoq.It.isAny())).returns(() => pythonSettings.object);
36+
commandManager.setup(c => c.executeCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve());
3337

34-
codeLensProvider = new DataScienceCodeLensProvider(serviceContainer.object, documentManager.object, configurationService.object);
38+
codeLensProvider = new DataScienceCodeLensProvider(serviceContainer.object, documentManager.object, configurationService.object, commandManager.object);
3539
});
3640

3741
test('Initialize Code Lenses one document', () => {
@@ -49,7 +53,7 @@ suite('DataScienceCodeLensProvider Unit Tests', () => {
4953

5054
targetCodeWatcher.verifyAll();
5155
serviceContainer.verifyAll();
52-
});
56+
});
5357

5458
test('Initialize Code Lenses same doc called', () => {
5559
// Create our document

src/test/datascience/editor-integration/codewatcher.unit.test.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import { expect } from 'chai';
77
import * as TypeMoq from 'typemoq';
88
import { CancellationTokenSource, CodeLens, Range, Selection, TextEditor } from 'vscode';
99

10-
import { IApplicationShell, IDocumentManager } from '../../../client/common/application/types';
10+
import { IApplicationShell, ICommandManager, IDocumentManager } from '../../../client/common/application/types';
1111
import { PythonSettings } from '../../../client/common/configSettings';
1212
import { IFileSystem } from '../../../client/common/platform/types';
1313
import { IConfigurationService, ILogger } from '../../../client/common/types';
14-
import { Commands } from '../../../client/datascience/constants';
14+
import { Commands, EditorContexts } from '../../../client/datascience/constants';
1515
import { DataScienceCodeLensProvider } from '../../../client/datascience/editor-integration/codelensprovider';
1616
import { CodeWatcher } from '../../../client/datascience/editor-integration/codewatcher';
1717
import { ICodeWatcher, IHistory, IHistoryProvider } from '../../../client/datascience/types';
@@ -29,12 +29,14 @@ suite('DataScience Code Watcher Unit Tests', () => {
2929
let historyProvider: TypeMoq.IMock<IHistoryProvider>;
3030
let activeHistory: TypeMoq.IMock<IHistory>;
3131
let documentManager: TypeMoq.IMock<IDocumentManager>;
32+
let commandManager: TypeMoq.IMock<ICommandManager>;
3233
let textEditor: TypeMoq.IMock<TextEditor>;
3334
let fileSystem: TypeMoq.IMock<IFileSystem>;
3435
let configService: TypeMoq.IMock<IConfigurationService>;
3536
let serviceContainer : TypeMoq.IMock<IServiceContainer>;
3637
let helper: TypeMoq.IMock<ICodeExecutionHelper>;
3738
let tokenSource : CancellationTokenSource;
39+
const contexts : Map<string, boolean> = new Map<string, boolean>();
3840
const pythonSettings = new class extends PythonSettings {
3941
public fireChangeEvent() {
4042
this.changed.fire();
@@ -52,6 +54,7 @@ suite('DataScience Code Watcher Unit Tests', () => {
5254
fileSystem = TypeMoq.Mock.ofType<IFileSystem>();
5355
configService = TypeMoq.Mock.ofType<IConfigurationService>();
5456
helper = TypeMoq.Mock.ofType<ICodeExecutionHelper>();
57+
commandManager = TypeMoq.Mock.ofType<ICommandManager>();
5558

5659
// Setup default settings
5760
pythonSettings.datascience = {
@@ -94,6 +97,13 @@ suite('DataScience Code Watcher Unit Tests', () => {
9497
// Setup config service
9598
configService.setup(c => c.getSettings()).returns(() => pythonSettings);
9699

100+
commandManager.setup(c => c.executeCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((c, n, v) => {
101+
if (c === 'setContext') {
102+
contexts.set(n, v);
103+
}
104+
return Promise.resolve();
105+
});
106+
97107
codeWatcher = new CodeWatcher(appShell.object, logger.object, historyProvider.object, fileSystem.object, configService.object, documentManager.object, helper.object);
98108
});
99109

@@ -657,20 +667,24 @@ testing2`; // Command tests override getText, so just need the ranges here
657667
const inputText = '#%% foobar';
658668
const document = createDocument(inputText, fileName, version, TypeMoq.Times.atLeastOnce());
659669
documentManager.setup(d => d.textDocuments).returns(() => [document.object]);
660-
const codeLensProvider = new DataScienceCodeLensProvider(serviceContainer.object, documentManager.object, configService.object);
670+
const codeLensProvider = new DataScienceCodeLensProvider(serviceContainer.object, documentManager.object, configService.object, commandManager.object);
661671

662672
let result = codeLensProvider.provideCodeLenses(document.object, tokenSource.token);
663673
expect(result, 'result not okay').to.be.ok;
664674
let codeLens = result as CodeLens[];
665675
expect(codeLens.length).to.equal(2, 'Code lens wrong length');
666676

677+
expect(contexts.get(EditorContexts.HasCodeCells)).to.be.equal(true, 'Code cells context not set');
678+
667679
// Change settings
668680
pythonSettings.datascience.codeRegularExpression = '#%%%.*dude';
669681
result = codeLensProvider.provideCodeLenses(document.object, tokenSource.token);
670682
expect(result, 'result not okay').to.be.ok;
671683
codeLens = result as CodeLens[];
672684
expect(codeLens.length).to.equal(0, 'Code lens wrong length');
673685

686+
expect(contexts.get(EditorContexts.HasCodeCells)).to.be.equal(false, 'Code cells context not set');
687+
674688
// Change settings to empty
675689
pythonSettings.datascience.codeRegularExpression = '';
676690
result = codeLensProvider.provideCodeLenses(document.object, tokenSource.token);

0 commit comments

Comments
 (0)