Skip to content

feat: DH-20578: Groovy remote file source#273

Draft
bmingles wants to merge 25 commits intomainfrom
DH-20578_groovy-remote-file-source
Draft

feat: DH-20578: Groovy remote file source#273
bmingles wants to merge 25 commits intomainfrom
DH-20578_groovy-remote-file-source

Conversation

@bmingles
Copy link
Collaborator

@bmingles bmingles commented Dec 16, 2025

@github-actions
Copy link

github-actions bot commented Dec 16, 2025

No docs changes detected for 94eb4ff

@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch from ac0c50b to e92d180 Compare December 23, 2025 23:01
@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch from d2eaefd to 093ca1f Compare January 5, 2026 21:40
@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch from 4d810c2 to 5eab919 Compare January 14, 2026 19:21
@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch from 7b8e4ea to 9778ba0 Compare February 20, 2026 18:29
@github-actions
Copy link

github-actions bot commented Feb 20, 2026

End-to-end Test Summary

Tests 📝Passed ✅Failed ❌Skipped ⏭️Pending ⏳Other ❓Flaky 🍂Duration ⏱️
330000017:21:23
A ctrf plugin

Failed Test Summary

No failed tests ✨

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

Unit Test Summary

Tests 📝Passed ✅Failed ❌Skipped ⏭️Pending ⏳Other ❓Flaky 🍂Duration ⏱️
72170912000000:00:00
A ctrf plugin

Failed Test Summary

NameStatusFailure Message
src/services/FilteredWorkspace.spec.ts: constructor > should create an instancefailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:350:33
src/services/FilteredWorkspace.spec.ts: getTopLevelMarkedFolders > should return an empty Set when workspace is emptyfailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:357:33
src/services/FilteredWorkspace.spec.ts: getTopLevelMarkedFolders > should return an empty Set when no folders are markedfailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:362:33
src/services/FilteredWorkspace.spec.ts: getTopLevelMarkedFolders > should return only top-level marked folder URIs: file:///path/to/ws1/sub1/afailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:372:35
src/services/FilteredWorkspace.spec.ts: getTopLevelMarkedFolders > should return only top-level marked folder URIs: file:///path/to/ws1/sub1failed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:372:35
src/services/FilteredWorkspace.spec.ts: mark / unmark > should mark a folder and its children: file:///path/to/ws1/sub1,file:///path/to/ws1/sub2failed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:390:49
src/services/FilteredWorkspace.spec.ts: mark / unmark > should mark a folder and its children: file:///path/to/ws1/sub1failed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:390:49
src/services/FilteredWorkspace.spec.ts: mark / unmark > should mark a folder and its children: file:///path/to/ws1/sub1/afailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:390:49
src/services/FilteredWorkspace.spec.ts: mark / unmark > should replace folder with conflicting module namefailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:401:47
src/services/FilteredWorkspace.spec.ts: unmarkFolder > should unmark a folder and its childrenfailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:436:47
src/services/FilteredWorkspace.spec.ts: unmarkConflictingTopLevelFolder > should unmark conflicting top-level marked foldersfailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:453:47
src/services/FilteredWorkspace.spec.ts: refresh > should refresh the workspace file URI mapfailed ❌ TypeError: watcher.onDidChange is not a function ❯ new FilteredWorkspace src/services/FilteredWorkspace.ts:81:15 ❯ initWorkspace src/services/FilteredWorkspace.spec.ts:294:27 ❯ src/services/FilteredWorkspace.spec.ts:488:47
A ctrf plugin

@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch 2 times, most recently from 331321e to 69164eb Compare March 3, 2026 16:45
@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch 2 times, most recently from 9465c03 to 22f7c02 Compare March 16, 2026 20:40
bmingles added 18 commits March 18, 2026 14:33
…rse Groovy import errors. Currently only Python errors are parsed in parseServerError(). Need to add new function that parses Groovy RuntimeExceptions with pattern 'Attempting to import a path that does not exist: import X;'. Example input: 'RuntimeException: Attempting to import a path that does not exist: import package3.subpackage1.MultiClassTest;'. Function should extract import path and return ParsedError object similar to Python version.

Added parseGroovyServerError function to errorUtils.ts that parses Groovy RuntimeException import errors, returning ParsedError with type, value, and importPath fields. Added 3 unit tests covering successful parse, unrecognized format, and empty string cases. (#DH-20578)
…nsionController. Currently only _pythonDiagnostics exists at line 230. Add _groovyDiagnostics property, initialize it in initializeDiagnostics() method (line 474) with vscode.languages.createDiagnosticCollection('groovy'), add listener to clear diagnostics on save for .groovy files, and pass to DhcService and MCP controller constructors.

Added _groovyDiagnostics property to ExtensionController, initialized with createDiagnosticCollection('groovy') in initializeDiagnostics(), added save listener to clear groovy diagnostics for .groovy files, passed to DhcService.factory and McpController constructor. Also updated DhcService.factory signature and McpController constructor to accept the new parameter. (#DH-20578)
…stics. Currently constructor accepts diagnosticsCollection parameter for Python (line 60). Add groovyDiagnosticsCollection parameter. In runCode() method around line 541, add else-if branch for languageId === 'groovy' that calls parseGroovyServerError() and creates diagnostics similar to Python error handling (lines 542-577). Store diagnostics in groovyDiagnosticsCollection.

Added parseGroovyServerError import to DhcService.ts, cleared groovy diagnostics at start of runCode(), and added else-if branch for languageId === 'groovy' that calls parseGroovyServerError() and stores vscode.Diagnostic objects in groovyDiagnosticsCollection (#DH-20578)
…unCodeUtils.ts. Pattern match errors for 'Attempting to import a path that does not exist: import X;', extract import path (e.g. package3.subpackage1.MultiClassTest), get top-level package (package3), and verify subpackage path exists. For import 'package3.subpackage1.MultiClassTest', must find folder named 'package3' that contains subfolder 'subpackage1'. Use groovyWorkspace.getChildNodes() and iterateNodeTree() to search. Return {hint, foundMatchingFolderUris} where foundMatchingFolderUris contains only folders with verified subpackage paths. Check hasGroovyRemoteFileSourcePlugin(connection) first. Also create hasGroovyRemoteFileSourcePlugin() helper function.

Created createGroovyImportErrorHint() in runCodeUtils.ts that parses Groovy import errors (regex matching 'Attempting to import a path that does not exist: import X;'), extracts top-level package and verifies subpackage folder structure using groovyWorkspace.getChildNodes() and iterateNodeTree(). Added hasGroovyRemoteFileSourcePlugin() helper and exported both functions. Added hasGroovyRemoteFileSourcePlugin() method to DhcService and IDhcService interface. Added comprehensive unit tests covering all scenarios (no errors, plugin not installed, subpackage verification, multiple roots). All 31 tests pass. (#DH-20578)
…oovyDiagnostics and groovyWorkspace parameters. Currently only pythonDiagnostics and pythonWorkspace are passed (line 51-52). Add groovyDiagnostics (vscode.DiagnosticCollection) and groovyWorkspace (FilteredWorkspace<GroovyPackageName>) parameters. Pass both to createRunCodeFromUriTool() factory function.

Updated McpServer constructor to accept groovyDiagnostics and groovyWorkspace parameters. Updated McpController constructor to add _groovyWorkspace parameter. Updated createRunCodeFromUriTool signature to accept both groovy params. Updated ExtensionController to assert and pass _groovyWorkspace to McpController. (#DH-20578)
… import errors. Currently has TODO comment at line 130 about DH-21363. Add groovyDiagnostics and groovyWorkspace to tool parameters. In error handling (line 124+), add else-if for languageId === 'groovy' that calls getDiagnosticsErrors(groovyDiagnostics), formats errors, and calls createGroovyImportErrorHint(groovyErrors, executedConnection, groovyWorkspace). Remove TODO comment. Pattern should match Python error handling at lines 132-147.

Added createGroovyImportErrorHint import and else-if block for languageId === 'groovy' in runCodeFromUri.ts. The groovy branch calls getDiagnosticsErrors(groovyDiagnostics), formats errors, and calls createGroovyImportErrorHint with correct parameters. Removed the TODO comment about DH-21363. (#DH-20578)
…detection. Add tests in errorUtils.spec.ts for parseGroovyServerError with multiple error patterns. Add tests in runCodeUtils.spec.ts for createGroovyImportErrorHint covering: no errors, plugin not installed, plugin installed with matching folders, plugin installed without matches, complex package paths (e.g. package3.subpackage1.MultiClassTest). Add tests in runCodeFromUri.spec.ts for MCP tool with Groovy errors. Mock groovyDiagnostics and groovyWorkspace appropriately.

Added comprehensive Groovy error tests: (1) 4 new parseGroovyServerError patterns in errorUtils.spec.ts (simple import, deep nested, extra text after semicolon, different prefix); (2) Updated runCodeFromUri.spec.ts with groovyDiagnostics/groovyWorkspace mocks, added createGroovyImportErrorHint to mock, updated all 4 createRunCodeFromUriTool calls to include new params, and added groovy code execution describe block with 5 test cases (success, error with hint, error without hint, ConnectionNotFoundError, general exception). All 55 tests pass. (#DH-20578)
@bmingles bmingles force-pushed the DH-20578_groovy-remote-file-source branch from 22f7c02 to 94eb4ff Compare March 18, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant