The GitHub Actions job "Coverage" on grails-intellij-plugin.git/feature/custom-folders has failed. Run started by GitHub user amondel2 (triggered by amondel2).
Head commit for run: dd808bfbb0ed7ebda2f960428662b32c2d1827d6 / aaron <[email protected]> Add configurable custom folders to the Grails project view The Grails pane rendered grails-app's fixed set of directories and the test roots. This adds custom folders on top: paths (global defaults plus a per-project override) that appear as nodes under the application node, editable on a settings page and manageable from the tree with Add as Custom Folder, Remove Custom Folder and Configure Custom Folders. The shape that survived review, and why it is this shape: - Two node kinds behind one interface. A folder that resolves on disk is a GrailsPsiDirectoryNode subclass, so its value is the PsiDirectory. That is what makes the node traversable: an AbstractTreeNode<String> puts no PSI_ELEMENT or VIRTUAL_FILE in the data context, and ProjectViewNodeVisitor.getContent answers null for it, so the visitor returns SKIP_CHILDREN even when the node's own contains() returns true -- Reveal and Select Opened File dead-end and New, Copy Path, Find in Files, Open In and Delete do nothing. A path that resolves to nothing keeps a separate lightweight placeholder and is the only AbstractTreeNode<String> left in the feature; it stays visible so a typo is removable from the settings page rather than invisible. GrailsCustomFolder exposes getConfiguredPath()/getNodeWeight(), so GrailsNodeComparator and the three actions need a single instanceof. - One path base, the Grails application root, on both sides. Add used to store a path relative to Project.getBaseDir() while the provider resolved it against application.getRoot(), so in a multi-project build with the app in app/, adding app/docs stored "app/docs" and rendered a placeholder for app/app/docs. Both now go through findApplication(dir).getRoot(), and getBaseDir() no longer appears in plugin/src/main. A directory belonging to no Grails application is not offered at all, and a directory outside the application root has no path to store against that base. - No absolute paths. The provider resolves a relative path against the application root and nothing else, and apply() rejects an absolute path, an escaping "..", and a path resolving outside the root, naming the row it came from. Validation normalizes the row before checking it, so a stray leading space does not buy a path the trimmed form would be refused. A stored path that stops resolving becomes a placeholder rather than disappearing. External directories stay a tracked follow-up in IMPROVEMENT-PLAN.md 2.8. - The cap is a setting, not a constant, and it is applied only when the view is built. MAX_FOLDERS = 3 was applied when folders were saved, so lowering it would have deleted configuration. maxFolders is persisted global state (default 6, range 1-20), edited with a spinner; lowering it now changes what renders without touching what is stored. The four copies of the normalize/dedupe loop collapse into FolderPaths.dedupe and both MAX_FOLDERS constants are gone. - Refreshes go through a message bus. Pane refreshes used to be direct GrailsProjectViewPanes.refresh calls from the services, so editing the global defaults left every other open project stale and FoldersChangedListener had no subscriber at all. A GrailsCustomFoldersRefreshListener project activity subscribes to the project topic, the new application topic and VFS_CHANGES, and coalesces them through one flag held per project: one Apply costs one rebuild per open project, and a build that creates build/ turns its placeholder into a real folder. The flag is read off the project rather than captured per execute() because postStartupActivity also runs under unit-test mode, which would otherwise give two registrations and two rebuilds for one change. - The settings page lives at Languages & Frameworks > Grails, with no empty parent page, and the two text areas are scrollable one-line rows with a + button and a per-row remove. Any number of rows survives; the cap truncates only the preview and the rendered tree. Global defaults are validated on shape alone rather than against an application root, because each open project has its own root and a path that resolves in one need not resolve in another. Supporting changes: the three actions read PlatformCoreDataKeys.SELECTED_ITEMS rather than getCurrentProjectViewPane().getSelectedPath(), so no update() touches the Swing tree from its background thread; Add refuses a folder the Grails view already renders, project or global; GrailsApplicationManager starts its upward walk at the file itself when the file has no content root, so Gradle's excluded build/ and .gradle/ resolve to their application instead of to nothing; a failing view provider is logged as an error rather than a warning. Reveal is asserted through AbstractProjectViewPane.createVisitor, the visitor the pane actually uses, rather than on the node's own contains() -- which is what made the original test unable to fail, since the node under test returned true. README.md, IMPROVEMENT-PLAN.md 2.8 and the settings page state one rule; the claim that hidden directories are filtered was checked against the platform's default Ignored Files and Folders list and is false, so the docs were corrected rather than the claim restated. The feature is unreleased, so none of this reaches a user who was already running it. # Conflicts: # IMPROVEMENT-PLAN.md # README.md # plugin/src/main/java/org/apache/grails/intellij/plugin/actions/AddCustomFolderAction.java # plugin/src/main/java/org/apache/grails/intellij/plugin/actions/ConfigureCustomFoldersAction.java # plugin/src/main/java/org/apache/grails/intellij/plugin/actions/RemoveCustomFolderAction.java # plugin/src/main/java/org/apache/grails/intellij/plugin/config/FolderPaths.java # plugin/src/main/java/org/apache/grails/intellij/plugin/config/GrailsCustomFoldersAppService.java # plugin/src/main/java/org/apache/grails/intellij/plugin/config/GrailsCustomFoldersConfigurable.java # plugin/src/main/java/org/apache/grails/intellij/plugin/config/GrailsCustomFoldersProjectService.java # plugin/src/main/java/org/apache/grails/intellij/plugin/projectView/impl/GrailsCustomFoldersNodeProvider.java # plugin/src/main/java/org/apache/grails/intellij/plugin/projectView/impl/GrailsNodeComparator.java # plugin/src/main/java/org/apache/grails/intellij/plugin/projectView/nodes/GrailsApplicationNode.java # plugin/src/main/java/org/apache/grails/intellij/plugin/projectView/nodes/GrailsCustomFolderNode.java # plugin/src/main/resources/META-INF/plugin.xml # plugin/src/test/java/org/apache/grails/intellij/plugin/actions/CustomFoldersActionTest.java # plugin/src/test/java/org/apache/grails/intellij/plugin/config/GrailsCustomFoldersAppServiceTest.java # plugin/src/test/java/org/apache/grails/intellij/plugin/config/GrailsCustomFoldersConfigurableTest.java # plugin/src/test/java/org/apache/grails/intellij/plugin/config/GrailsCustomFoldersProjectServiceTest.java # plugin/src/test/java/org/apache/grails/intellij/plugin/projectView/GrailsCustomFoldersPaneTest.java # plugin/src/test/java/org/apache/grails/intellij/plugin/projectView/impl/GrailsCustomFoldersNodeProviderTest.java Report URL: https://github.com/apache/grails-intellij-plugin/actions/runs/38838760925 With regards, GitHub Actions via GitBox
