From 8f4e999a64678bb7d363090c3e105ebde2a37ab6 Mon Sep 17 00:00:00 2001 From: aamunger Date: Tue, 20 Sep 2022 14:47:11 -0700 Subject: [PATCH 1/3] Add code folding regions for # %% cells within python files --- news/1 Enhancements/1527.md | 1 + .../pythonCellFoldingProvider.ts | 38 +++++++++++++++++++ .../editor-integration/types.ts | 15 +++++++- .../serviceRegistry.node.ts | 5 ++- src/standalone/activation/globalActivation.ts | 13 ++++++- src/test/datascience/datascience.unit.test.ts | 1 + 6 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 news/1 Enhancements/1527.md create mode 100644 src/interactive-window/editor-integration/pythonCellFoldingProvider.ts diff --git a/news/1 Enhancements/1527.md b/news/1 Enhancements/1527.md new file mode 100644 index 00000000000..46bf0c0b232 --- /dev/null +++ b/news/1 Enhancements/1527.md @@ -0,0 +1 @@ +Add code folding regions for `# %%` cells within python files. diff --git a/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts b/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts new file mode 100644 index 00000000000..b8d7ce4c39f --- /dev/null +++ b/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { inject, injectable } from 'inversify'; +import { + TextDocument, + FoldingContext, + CancellationToken, + ProviderResult, + FoldingRange, + FoldingRangeKind +} from 'vscode'; +import { IDataScienceCodeLensProvider, IPythonCellFoldingProvider } from './types'; + +@injectable() +export class PythonCellFoldingProvider implements IPythonCellFoldingProvider { + constructor( + @inject(IDataScienceCodeLensProvider) private dataScienceCodeLensProvider: IDataScienceCodeLensProvider + ) {} + + provideFoldingRanges( + document: TextDocument, + _context: FoldingContext, + token: CancellationToken + ): ProviderResult { + const codeWatcher = this.dataScienceCodeLensProvider.getCodeWatcher(document); + if (codeWatcher) { + const codeLenses = codeWatcher.getCodeLenses(); + if (token.isCancellationRequested) { + return undefined; + } + return codeLenses.map((codeLens) => { + return new FoldingRange(codeLens.range.start.line, codeLens.range.end.line, FoldingRangeKind.Region); + }); + } + return undefined; + } +} diff --git a/src/interactive-window/editor-integration/types.ts b/src/interactive-window/editor-integration/types.ts index 3d09daa5ebc..83b9e171c7c 100644 --- a/src/interactive-window/editor-integration/types.ts +++ b/src/interactive-window/editor-integration/types.ts @@ -3,7 +3,17 @@ 'use strict'; -import { Event, CodeLens, CodeLensProvider, Uri, TextEditor, Range, TextDocument, NotebookDocument } from 'vscode'; +import { + Event, + CodeLens, + CodeLensProvider, + Uri, + TextEditor, + Range, + TextDocument, + NotebookDocument, + FoldingRangeProvider +} from 'vscode'; import { ICellRange, IDisposable } from '../../platform/common/types'; // Wraps the vscode CodeLensProvider base class @@ -12,6 +22,9 @@ export interface IDataScienceCodeLensProvider extends CodeLensProvider { getCodeWatcher(document: TextDocument): ICodeWatcher | undefined; } +export const IPythonCellFoldingProvider = Symbol('IPythonCellFoldingProvider'); +export interface IPythonCellFoldingProvider extends FoldingRangeProvider {} + // Wraps the Code Watcher API export const ICodeWatcher = Symbol('ICodeWatcher'); export interface ICodeWatcher extends IDisposable { diff --git a/src/interactive-window/serviceRegistry.node.ts b/src/interactive-window/serviceRegistry.node.ts index 0f4ce80a9df..dbd0def67bc 100644 --- a/src/interactive-window/serviceRegistry.node.ts +++ b/src/interactive-window/serviceRegistry.node.ts @@ -21,7 +21,8 @@ import { ICodeLensFactory, IDataScienceCodeLensProvider, IGeneratedCodeStorageFactory, - ICodeGeneratorFactory + ICodeGeneratorFactory, + IPythonCellFoldingProvider } from './editor-integration/types'; import { GeneratedCodeStorageManager } from './generatedCodeStoreManager'; import { InteractiveWindowTracebackFormatter } from './outputs/tracebackFormatter'; @@ -30,6 +31,7 @@ import { InteractiveWindowDebugger } from './debugger/interactiveWindowDebugger. import { InteractiveWindowDebuggingManager } from './debugger/jupyter/debuggingManager'; import { BANNER_NAME_INTERACTIVE_SHIFTENTER, InteractiveShiftEnterBanner } from './shiftEnterBanner'; import { InteractiveWindowDebuggingStartupCodeProvider } from './debugger/startupCodeProvider'; +import { PythonCellFoldingProvider } from './editor-integration/pythonCellFoldingProvider'; export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(IInteractiveWindowProvider, InteractiveWindowProvider); @@ -41,6 +43,7 @@ export function registerTypes(serviceManager: IServiceManager) { IDataScienceCodeLensProvider, DataScienceCodeLensProvider ); + serviceManager.addSingleton(IPythonCellFoldingProvider, PythonCellFoldingProvider); serviceManager.addSingleton(IExtensionSingleActivationService, Decorator); serviceManager.addSingleton( IExtensionSyncActivationService, diff --git a/src/standalone/activation/globalActivation.ts b/src/standalone/activation/globalActivation.ts index ec9df0f3c03..7b3160d8911 100644 --- a/src/standalone/activation/globalActivation.ts +++ b/src/standalone/activation/globalActivation.ts @@ -20,7 +20,10 @@ import { debounceAsync, swallowExceptions } from '../../platform/common/utils/de import { noop } from '../../platform/common/utils/misc'; import { EditorContexts } from '../../platform/common/constants'; import { IExtensionSingleActivationService } from '../../platform/activation/types'; -import { IDataScienceCodeLensProvider } from '../../interactive-window/editor-integration/types'; +import { + IDataScienceCodeLensProvider, + IPythonCellFoldingProvider +} from '../../interactive-window/editor-integration/types'; import { IRawNotebookSupportedService } from '../../kernels/raw/types'; import { hasCells } from '../../interactive-window/editor-integration/cellFactory'; import { sendTelemetryEvent } from '../../telemetry'; @@ -41,6 +44,9 @@ export class GlobalActivation implements IExtensionSingleActivationService { @inject(IDataScienceCodeLensProvider) @optional() private dataScienceCodeLensProvider: IDataScienceCodeLensProvider | undefined, + @optional() + @inject(IPythonCellFoldingProvider) + private pythonCellFoldingProvider: IPythonCellFoldingProvider | undefined, @inject(IConfigurationService) private configuration: IConfigurationService, @inject(IDocumentManager) private documentManager: IDocumentManager, @inject(IWorkspaceService) private workspace: IWorkspaceService, @@ -61,6 +67,11 @@ export class GlobalActivation implements IExtensionSingleActivationService { vscode.languages.registerCodeLensProvider([PYTHON_FILE_ANY_SCHEME], this.dataScienceCodeLensProvider) ); } + if (this.pythonCellFoldingProvider) { + this.extensionContext.subscriptions.push( + vscode.languages.registerFoldingRangeProvider([PYTHON_FILE_ANY_SCHEME], this.pythonCellFoldingProvider) + ); + } // Set our initial settings and sign up for changes this.onSettingsChanged(); diff --git a/src/test/datascience/datascience.unit.test.ts b/src/test/datascience/datascience.unit.test.ts index 6d8a8cfb639..2118d165510 100644 --- a/src/test/datascience/datascience.unit.test.ts +++ b/src/test/datascience/datascience.unit.test.ts @@ -49,6 +49,7 @@ suite('DataScience Tests', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any { subscriptions: [] } as any, instance(dataScienceCodeLensProvider), + undefined, instance(configService), instance(docManager), instance(workspaceService), From e26efc39250bdf15f7d709699a828d55a9600bcb Mon Sep 17 00:00:00 2001 From: aamunger Date: Wed, 21 Sep 2022 09:42:39 -0700 Subject: [PATCH 2/3] moved provider activation to be self-contained --- .../pythonCellFoldingProvider.ts | 14 +++++++++++--- .../editor-integration/types.ts | 15 +-------------- src/interactive-window/serviceRegistry.node.ts | 8 +++++--- src/standalone/activation/globalActivation.ts | 13 +------------ src/test/datascience/datascience.unit.test.ts | 1 - 5 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts b/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts index b8d7ce4c39f..44f56771a24 100644 --- a/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts +++ b/src/interactive-window/editor-integration/pythonCellFoldingProvider.ts @@ -8,16 +8,24 @@ import { CancellationToken, ProviderResult, FoldingRange, - FoldingRangeKind + FoldingRangeKind, + FoldingRangeProvider, + languages } from 'vscode'; -import { IDataScienceCodeLensProvider, IPythonCellFoldingProvider } from './types'; +import { IExtensionSyncActivationService } from '../../platform/activation/types'; +import { PYTHON_FILE_ANY_SCHEME } from '../../platform/common/constants'; +import { IDataScienceCodeLensProvider } from './types'; @injectable() -export class PythonCellFoldingProvider implements IPythonCellFoldingProvider { +export class PythonCellFoldingProvider implements IExtensionSyncActivationService, FoldingRangeProvider { constructor( @inject(IDataScienceCodeLensProvider) private dataScienceCodeLensProvider: IDataScienceCodeLensProvider ) {} + public activate() { + languages.registerFoldingRangeProvider([PYTHON_FILE_ANY_SCHEME], this); + } + provideFoldingRanges( document: TextDocument, _context: FoldingContext, diff --git a/src/interactive-window/editor-integration/types.ts b/src/interactive-window/editor-integration/types.ts index 83b9e171c7c..3d09daa5ebc 100644 --- a/src/interactive-window/editor-integration/types.ts +++ b/src/interactive-window/editor-integration/types.ts @@ -3,17 +3,7 @@ 'use strict'; -import { - Event, - CodeLens, - CodeLensProvider, - Uri, - TextEditor, - Range, - TextDocument, - NotebookDocument, - FoldingRangeProvider -} from 'vscode'; +import { Event, CodeLens, CodeLensProvider, Uri, TextEditor, Range, TextDocument, NotebookDocument } from 'vscode'; import { ICellRange, IDisposable } from '../../platform/common/types'; // Wraps the vscode CodeLensProvider base class @@ -22,9 +12,6 @@ export interface IDataScienceCodeLensProvider extends CodeLensProvider { getCodeWatcher(document: TextDocument): ICodeWatcher | undefined; } -export const IPythonCellFoldingProvider = Symbol('IPythonCellFoldingProvider'); -export interface IPythonCellFoldingProvider extends FoldingRangeProvider {} - // Wraps the Code Watcher API export const ICodeWatcher = Symbol('ICodeWatcher'); export interface ICodeWatcher extends IDisposable { diff --git a/src/interactive-window/serviceRegistry.node.ts b/src/interactive-window/serviceRegistry.node.ts index dbd0def67bc..1fd3ee77210 100644 --- a/src/interactive-window/serviceRegistry.node.ts +++ b/src/interactive-window/serviceRegistry.node.ts @@ -21,8 +21,7 @@ import { ICodeLensFactory, IDataScienceCodeLensProvider, IGeneratedCodeStorageFactory, - ICodeGeneratorFactory, - IPythonCellFoldingProvider + ICodeGeneratorFactory } from './editor-integration/types'; import { GeneratedCodeStorageManager } from './generatedCodeStoreManager'; import { InteractiveWindowTracebackFormatter } from './outputs/tracebackFormatter'; @@ -43,7 +42,10 @@ export function registerTypes(serviceManager: IServiceManager) { IDataScienceCodeLensProvider, DataScienceCodeLensProvider ); - serviceManager.addSingleton(IPythonCellFoldingProvider, PythonCellFoldingProvider); + serviceManager.addSingleton( + IExtensionSyncActivationService, + PythonCellFoldingProvider + ); serviceManager.addSingleton(IExtensionSingleActivationService, Decorator); serviceManager.addSingleton( IExtensionSyncActivationService, diff --git a/src/standalone/activation/globalActivation.ts b/src/standalone/activation/globalActivation.ts index 7b3160d8911..ec9df0f3c03 100644 --- a/src/standalone/activation/globalActivation.ts +++ b/src/standalone/activation/globalActivation.ts @@ -20,10 +20,7 @@ import { debounceAsync, swallowExceptions } from '../../platform/common/utils/de import { noop } from '../../platform/common/utils/misc'; import { EditorContexts } from '../../platform/common/constants'; import { IExtensionSingleActivationService } from '../../platform/activation/types'; -import { - IDataScienceCodeLensProvider, - IPythonCellFoldingProvider -} from '../../interactive-window/editor-integration/types'; +import { IDataScienceCodeLensProvider } from '../../interactive-window/editor-integration/types'; import { IRawNotebookSupportedService } from '../../kernels/raw/types'; import { hasCells } from '../../interactive-window/editor-integration/cellFactory'; import { sendTelemetryEvent } from '../../telemetry'; @@ -44,9 +41,6 @@ export class GlobalActivation implements IExtensionSingleActivationService { @inject(IDataScienceCodeLensProvider) @optional() private dataScienceCodeLensProvider: IDataScienceCodeLensProvider | undefined, - @optional() - @inject(IPythonCellFoldingProvider) - private pythonCellFoldingProvider: IPythonCellFoldingProvider | undefined, @inject(IConfigurationService) private configuration: IConfigurationService, @inject(IDocumentManager) private documentManager: IDocumentManager, @inject(IWorkspaceService) private workspace: IWorkspaceService, @@ -67,11 +61,6 @@ export class GlobalActivation implements IExtensionSingleActivationService { vscode.languages.registerCodeLensProvider([PYTHON_FILE_ANY_SCHEME], this.dataScienceCodeLensProvider) ); } - if (this.pythonCellFoldingProvider) { - this.extensionContext.subscriptions.push( - vscode.languages.registerFoldingRangeProvider([PYTHON_FILE_ANY_SCHEME], this.pythonCellFoldingProvider) - ); - } // Set our initial settings and sign up for changes this.onSettingsChanged(); diff --git a/src/test/datascience/datascience.unit.test.ts b/src/test/datascience/datascience.unit.test.ts index 2118d165510..6d8a8cfb639 100644 --- a/src/test/datascience/datascience.unit.test.ts +++ b/src/test/datascience/datascience.unit.test.ts @@ -49,7 +49,6 @@ suite('DataScience Tests', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any { subscriptions: [] } as any, instance(dataScienceCodeLensProvider), - undefined, instance(configService), instance(docManager), instance(workspaceService), From a5777cf537f5048641db056091d2660bfeef362c Mon Sep 17 00:00:00 2001 From: aamunger Date: Wed, 21 Sep 2022 09:50:02 -0700 Subject: [PATCH 3/3] added cell folding provider to web --- src/interactive-window/serviceRegistry.web.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/interactive-window/serviceRegistry.web.ts b/src/interactive-window/serviceRegistry.web.ts index 587ef87bb92..62bfed0ef12 100644 --- a/src/interactive-window/serviceRegistry.web.ts +++ b/src/interactive-window/serviceRegistry.web.ts @@ -26,6 +26,7 @@ import { GeneratedCodeStorageManager } from './generatedCodeStoreManager'; import { InteractiveWindowTracebackFormatter } from './outputs/tracebackFormatter'; import { InteractiveWindowDebuggingManager } from './debugger/jupyter/debuggingManager'; import { InteractiveWindowDebuggingStartupCodeProvider } from './debugger/startupCodeProvider'; +import { PythonCellFoldingProvider } from './editor-integration/pythonCellFoldingProvider'; export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(IInteractiveWindowProvider, InteractiveWindowProvider); @@ -36,6 +37,10 @@ export function registerTypes(serviceManager: IServiceManager) { IDataScienceCodeLensProvider, DataScienceCodeLensProvider ); + serviceManager.addSingleton( + IExtensionSyncActivationService, + PythonCellFoldingProvider + ); serviceManager.addSingleton(IExtensionSingleActivationService, Decorator); serviceManager.addSingleton( IExtensionSyncActivationService,