You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@grails.apache.org by GitBox <gi...@apache.org> on 2026/10/20 21:21:23 UTC
[GH] (grails-intellij-plugin/feature/custom-folders): Workflow run "Licensing - RAT Report" failed!
The GitHub Actions job "Licensing - RAT Report" 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 <am...@gmail.com>
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/38838760765
With regards,
GitHub Actions via GitBox