feat: add outline drag-and-drop method extraction prototype#319320
Open
robot-mazeee wants to merge 2 commits into
Open
feat: add outline drag-and-drop method extraction prototype#319320robot-mazeee wants to merge 2 commits into
robot-mazeee wants to merge 2 commits into
Conversation
Part of microsoft#299961. This prototypes structural refactoring from the Outline view. Supported drops are routed to an experimental outline-refactor extension. The implementation is split between a small Outline UI change and a language-specific refactoring engine. The Outline view detects supported drops and invokes outline.moveSymbol with symbol and drop metadata. The extension registers the command, validates the move, and applies a WorkspaceEdit. The JavaScript engine uses the TypeScript compiler API to analyze class methods, rewrite direct this.method(...) call sites, and convert the moved method to a standalone function. Supported today: - JavaScript class methods with simple identifier names. - Moves from a class to the surrounding source file. - Direct call sites of the form this.methodName(...). - this usages rewritten through an explicit receiver parameter. Unsupported cases are rejected conservatively, including constructors, getters, setters, class fields, static methods, private members, super, dynamic this[...] access, indirect references, cross-file moves, and moving methods into another class. Testing: - npm test in extensions/outline-refactor. - 9 semantic fixture tests passing. - git diff --check. - npm run compile completed successfully locally. Co-authored-by: Leonor Azevedo <leonor.a.e.azevedo@tecnico.ulisboa.pt>
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds experimental drag-and-drop refactoring from the Outline view by wiring tree DnD to a new outline.moveSymbol command, backed by a new outline-refactor extension that can extract JavaScript class methods into standalone functions.
Changes:
- Add custom Outline tree drag-and-drop handling, including custom drag preview + command invocation.
- Introduce
outline-refactorextension with move-symbol command + JS method extraction engine. - Add fixtures and a Mocha test suite validating supported/unsupported refactor cases.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/contrib/outline/browser/outlinePane.ts | Adds custom tree DnD logic and dispatches outline.moveSymbol on drop. |
| src/vs/workbench/contrib/outline/browser/outlinePane.css | Styles the custom drag image preview used during Outline DnD. |
| extensions/outline-refactor/tsconfig.json | Adds TypeScript build configuration for the new extension. |
| extensions/outline-refactor/test-fixtures/unsupported/super.input.js | Adds unsupported refactor fixture case (uses super). |
| extensions/outline-refactor/test-fixtures/unsupported/static-method.input.js | Adds unsupported refactor fixture case (static method). |
| extensions/outline-refactor/test-fixtures/unsupported/private-field.input.js | Adds unsupported refactor fixture case (private field). |
| extensions/outline-refactor/test-fixtures/unsupported/indirect-call.input.js | Adds unsupported refactor fixture case (indirect call). |
| extensions/outline-refactor/test-fixtures/unsupported/getter.input.js | Adds unsupported refactor fixture case (getter). |
| extensions/outline-refactor/test-fixtures/unsupported/dynamic-this.input.js | Adds unsupported refactor fixture case (dynamic this[...]). |
| extensions/outline-refactor/test-fixtures/supported/uses-this.input.js | Adds supported refactor fixture case (uses this). |
| extensions/outline-refactor/test-fixtures/supported/uses-this.expected.js | Adds expected output for uses-this supported fixture. |
| extensions/outline-refactor/test-fixtures/supported/simple-no-this.input.js | Adds supported refactor fixture case (no this). |
| extensions/outline-refactor/test-fixtures/supported/simple-no-this.expected.js | Adds expected output for simple-no-this supported fixture. |
| extensions/outline-refactor/test-fixtures/supported/multiple-args.input.js | Adds supported refactor fixture case (multiple args). |
| extensions/outline-refactor/test-fixtures/supported/multiple-args.expected.js | Adds expected output for multiple-args supported fixture. |
| extensions/outline-refactor/src/test/javascriptMethodExtractEngine.test.ts | Adds Mocha tests for the JS method extraction engine using fixtures. |
| extensions/outline-refactor/src/refactor/types.ts | Defines refactor request/engine types shared across the extension. |
| extensions/outline-refactor/src/refactor/textMoveEngine.ts | Implements a generic text-based “move symbol” edit builder. |
| extensions/outline-refactor/src/refactor/javascriptMethodExtractEngine.ts | Implements JS-specific analysis + extraction refactor and call-site rewriting. |
| extensions/outline-refactor/src/extension.ts | Registers the move-symbol command on activation. |
| extensions/outline-refactor/src/commands/moveSymbolCommand.ts | Implements outline.moveSymbol command and applies the resulting edit. |
| extensions/outline-refactor/package.nls.json | Adds localized strings for the extension display metadata and command title. |
| extensions/outline-refactor/package.json | Declares the new extension and contributes the outline.moveSymbol command. |
Avoid receiver parameter name collisions when extracting methods by choosing a non-conflicting receiver name and adding a fixture test for the obj-parameter case. Restore the patched module loader after semantic tests to avoid leaking the vscode stub across test files. Limit expensive outline drop-feedback traversal to after-drops on class symbols, reducing unnecessary work during drag-over events. Co-authored-by: Leonor Azevedo <leonor.a.e.azevedo@tecnico.ulisboa.pt>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add outline drag-and-drop method extraction prototype
Summary
Part of #299961.
This PR prototypes structural refactoring from the Outline view. It adds drag-and-drop handling for Outline symbols and routes supported moves to an experimental refactoring command.
The initial semantic implementation focuses on JavaScript class methods dragged outside their enclosing class. When the move can be statically validated, the method is transformed into a standalone function and direct call sites are updated.
Implementation approach
This prototype is implemented as a small experimental extension under
extensions/outline-refactor, with a focused change in the built-in Outline view to dispatch supported drag-and-drop operations to the extension command.The Outline view is responsible only for the interaction layer: detecting supported symbol drops, preserving existing Outline behavior for unsupported cases, and invoking the
outline.moveSymbolcommand with the source symbol, target symbol, parent symbols, document URI, and drop position.The extension contains the refactoring layer. It registers the
outline.moveSymbolcommand, validates whether the requested move is safe, and applies the resulting edit through aWorkspaceEdit. The current semantic implementation uses the TypeScript compiler API to analyze JavaScript class methods and rewrite supported method-extraction cases.This keeps the prototype split between:
The extension structure is intentionally designed so additional language engines could be added later without putting all semantic transformation logic directly into the Outline view.
What works
this.helper(x)thisusages inside the moved method when neededSupported cases
this.methodName(...)this, rewritten through an explicit receiver parameterExample:
becomes:
Unsupported cases
The prototype intentionally rejects cases that are not safely handled yet:
superusagethis[name]const fn = this.helperTesting
Automated semantic fixture tests:
Testing
Automated semantic fixture tests:
Current result:
Also checked:
The full repository compile was run with:
and completed successfully locally.
Notes
This is intended as a prototype of the interaction and semantic-refactoring flow. The implementation is intentionally conservative: if a move cannot be statically validated by the current analysis, it is rejected instead of applying a potentially unsafe edit.
Co-authored with @leonor-a-a-ist.