This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts-intellij-plugin.git
The following commit(s) were added to refs/heads/main by this push:
new f6de54f fix: remediate private and deprecated API usages for
marketplace approval (#42)
f6de54f is described below
commit f6de54f2525c23c8cdc8ee38fd98ccc055972793
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Feb 23 15:07:43 2026 +0100
fix: remediate private and deprecated API usages for marketplace approval
(#42)
Replace internal and deprecated IntelliJ Platform APIs to pass
JetBrains Marketplace verification for plugin version 253.x.
Changes:
- Replace IconManager.loadRasterizedIcon() with IconLoader.getIcon()
- Replace WebFacet.getWebRoots(boolean) with getWebRoots()
- Replace AnActionButton with DumbAwareAction in toolbar
- Replace IdeFocusManager.doWhenFocusSettlesDown() with requestFocus()
- Replace ResourceRegistrar.addStdResource(Class) with ClassLoader version
- Replace FilenameIndex.getFilesByName() with getVirtualFilesByName()
- Replace deprecated URL(String) constructor with URI.create().toURL()
- Document GraphBuilder internal API usage (no public replacement)
- Document EXTEND_CLASS_NAMES deprecation (no replacement available)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <[email protected]>
---
.github/workflows/release.yml | 17 +-
CHANGELOG.md | 57 +-
CLAUDE.md | 68 ++-
src/main/gen/com/intellij/lang/ognl/OgnlIcons.java | 14 +-
.../java/com/intellij/struts2/Struts2Icons.java | 24 +-
.../intellij/struts2/Struts2ResourceProvider.java | 148 ++---
.../struts/impl/path/FileReferenceSetHelper.java | 126 ++--
.../struts2/facet/ui/FileSetConfigurationTab.java | 662 ++++++++++-----------
.../graph/fileEditor/Struts2GraphComponent.java | 197 +++---
.../graph/fileEditor/Struts2GraphFileEditor.java | 155 ++---
.../inspection/HardcodedActionUrlInspection.java | 486 ++++++++-------
.../contributor/ConstantValueClassConverter.java | 140 ++---
.../velocity/Struts2GlobalMacroProvider.java | 43 +-
13 files changed, 1099 insertions(+), 1038 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6f1219d..bcf79a9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -64,15 +64,19 @@ jobs:
run: |
PROPERTIES="$(./gradlew properties --console=plain -q)"
VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
+ CHANGELOG="$(./gradlew getChangelog --unreleased --no-header
--console=plain -q)"
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
+
+ echo "changelog<<EOF" >> $GITHUB_OUTPUT
+ echo "$CHANGELOG" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
# Update Unreleased section with the current release note
- name: Patch Changelog
if: ${{ steps.properties.outputs.changelog != '' }}
- env:
- CHANGELOG: ${{ steps.properties.outputs.changelog }}
run: |
- ./gradlew patchChangelog --release-note="$CHANGELOG"
+ ./gradlew patchChangelog
# Publish the plugin to JetBrains Marketplace
- name: Publish Plugin
@@ -94,6 +98,7 @@ jobs:
if: ${{ steps.properties.outputs.changelog != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ CHANGELOG: ${{ steps.properties.outputs.changelog }}
run: |
VERSION="${{ steps.properties.outputs.version }}"
BRANCH="changelog-update-$VERSION"
@@ -108,6 +113,10 @@ jobs:
gh pr create \
--title "Changelog update - \`$VERSION\`" \
- --body "Current pull request contains patched \`CHANGELOG.md\`
file for the \`$VERSION\` version." \
+ --body "Current pull request contains patched \`CHANGELOG.md\`
file for the \`$VERSION\` version.
+
+ ## Changes included in this release
+
+ $CHANGELOG" \
--label "$LABEL" \
--head $BRANCH
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9297e4e..76fdaa8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,19 @@
## [Unreleased]
+### Fixed
+
+- Fix private and deprecated API usages for JetBrains Marketplace approval:
+ - Replace `IconManager.loadRasterizedIcon()` with `IconLoader.getIcon()` in
icon classes
+ - Replace `WebFacet.getWebRoots(boolean)` with `getWebRoots()` (parameter
scheduled for removal)
+ - Replace `AnActionButton` with `DumbAwareAction` in toolbar decorator
+ - Replace `IdeFocusManager.doWhenFocusSettlesDown()` with direct
`requestFocus()`
+ - Replace `ResourceRegistrar.addStdResource(Class)` with ClassLoader-based
version
+ - Replace `FilenameIndex.getFilesByName()` with `getVirtualFilesByName()`
+ - Replace deprecated `URL(String)` constructor with `URI.create().toURL()`
+
+## [252.18978.1] - 2025-02-10
+
### Changed
- Update `platformVersion` to `2025.3`
@@ -20,27 +33,6 @@
- Fix `CreateFileAction` constructor signature change - use `Supplier<?
extends Icon>` instead of direct Icon
- Fix `BuildableRootsChangeRescanningInfo.addModule()` removal - simplified
file set change handling
- Remove deprecated `instrumentationTools()` call in build configuration
-
-### Temporarily Disabled Tests
-
-The following tests are temporarily disabled due to test infrastructure
changes in IntelliJ Platform 2025.3.
-These tests need investigation and fixes for test data path resolution,
highlighting comparison, and API behavior changes:
-
-- `OgnlLexerTest` - 4 tests (test data path resolution)
-- `StrutsCompletionTest.testCompletionVariantsPackageExtends` -
FreezableArrayList issue
-- `StrutsHighlightingSpringTest` - 5 tests (Spring integration)
-- `StrutsResultResolvingTest` - 2 tests (highlighting comparison)
-- `ActionLinkReferenceProviderTest` - 4 tests (JSP reference provider)
-- `ActionPropertyReferenceProviderTest` - 2 tests (highlighting comparison)
-- `ActionReferenceProviderTest.testActionHighlighting` - highlighting
comparison
-- `NamespaceReferenceProviderTest.testNamespaceHighlighting` - highlighting
comparison
-- `UITagsAttributesReferenceProviderTest` - 2 tests (highlighting comparison)
-- `ResultActionPropertyTest.testSimpleActionProperty` - highlighting comparison
-- `WebXmlConstantTest.testHighlighting` - highlighting comparison
-- `StrutsStructureViewTest` - 2 tests (structure view)
-
-### Previously Fixed
-
- Fix multiple internal API compatibility issues for IntelliJ Platform 2025.2:
- Replace `PlatformIcons` internal API with public
`AllIcons.Nodes.Parameter` in `OgnlReferenceExpressionBase`
- Replace `CharsetToolkit.getAvailableCharsets()` with standard Java
`Charset.availableCharsets()` in `StrutsCoreConstantContributor`
@@ -62,6 +54,24 @@ These tests need investigation and fixes for test data path
resolution, highligh
- [WW-5558](https://issues.apache.org/jira/browse/WW-5558) Support for new
Struts 7 packages
+### Temporarily Disabled Tests
+
+The following tests are temporarily disabled due to test infrastructure
changes in IntelliJ Platform 2025.3.
+These tests need investigation and fixes for test data path resolution,
highlighting comparison, and API behavior changes:
+
+- `OgnlLexerTest` - 4 tests (test data path resolution)
+- `StrutsCompletionTest.testCompletionVariantsPackageExtends` -
FreezableArrayList issue
+- `StrutsHighlightingSpringTest` - 5 tests (Spring integration)
+- `StrutsResultResolvingTest` - 2 tests (highlighting comparison)
+- `ActionLinkReferenceProviderTest` - 4 tests (JSP reference provider)
+- `ActionPropertyReferenceProviderTest` - 2 tests (highlighting comparison)
+- `ActionReferenceProviderTest.testActionHighlighting` - highlighting
comparison
+- `NamespaceReferenceProviderTest.testNamespaceHighlighting` - highlighting
comparison
+- `UITagsAttributesReferenceProviderTest` - 2 tests (highlighting comparison)
+- `ResultActionPropertyTest.testSimpleActionProperty` - highlighting comparison
+- `WebXmlConstantTest.testHighlighting` - highlighting comparison
+- `StrutsStructureViewTest` - 2 tests (structure view)
+
## [2.0.1] - 2024-08-09
### Changed
@@ -74,5 +84,6 @@ These tests need investigation and fixes for test data path
resolution, highligh
- Dependencies - upgrade `org.jetbrains.kotlinx.kover` to `0.8.3`
- Dependencies - upgrade `org.jetbrains.qodana` to `2024.1.9`
-[Unreleased]:
https://github.com/JetBrains/intellij-platform-plugin-template/compare/v2.0.1...HEAD
-[2.0.1]:
https://github.com/JetBrains/intellij-platform-plugin-template/compare/v2.0.0...v2.0.1
+[Unreleased]:
https://github.com/apache/struts-intellij-plugin/compare/v252.18978.1...HEAD
+[252.18978.1]:
https://github.com/apache/struts-intellij-plugin/compare/v2.0.1...v252.18978.1
+[2.0.1]: https://github.com/apache/struts-intellij-plugin/releases/tag/v2.0.1
\ No newline at end of file
diff --git a/CLAUDE.md b/CLAUDE.md
index 5b0707d..0752c42 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -5,6 +5,7 @@ This file provides guidance to Claude Code (claude.ai/code)
when working with co
## Development Commands
### Build and Test
+
```bash
./gradlew build # Build the plugin
./gradlew test -x rat # Run unit tests (excluding
Apache RAT license checks)
@@ -15,6 +16,7 @@ This file provides guidance to Claude Code (claude.ai/code)
when working with co
```
### Development and Debugging
+
```bash
./gradlew runIde # Run IntelliJ IDEA with the
plugin loaded
./gradlew runIdeForUiTests # Launch IDE with robot server on
port 8082
@@ -23,6 +25,7 @@ This file provides guidance to Claude Code (claude.ai/code)
when working with co
```
### Code Quality
+
```bash
./gradlew runInspections # Run Qodana inspections
(requires Docker)
./gradlew rat # Run Apache RAT license check
@@ -30,32 +33,38 @@ This file provides guidance to Claude Code (claude.ai/code)
when working with co
## Project Architecture
-This is an IntelliJ IDEA Ultimate plugin for Apache Struts 2 framework,
providing IDE support for struts.xml configuration, OGNL expressions,
validation files, and JSP tag libraries.
+This is an IntelliJ IDEA Ultimate plugin for Apache Struts 2 framework,
providing IDE support for struts.xml
+configuration, OGNL expressions, validation files, and JSP tag libraries.
### Package Structure
+
- `com.intellij.struts2` - Core Struts 2 plugin functionality
- `com.intellij.lang.ognl` - OGNL language support (lexer, parser,
highlighting, completion)
### Key Architectural Components
**DOM Model Layer** (`com.intellij.struts2.dom`)
+
- `struts/` - Struts XML configuration DOM (actions, results, interceptors,
packages)
- `validator/` - Validation XML DOM models
- `params/` - Parameter handling and type conversion
- DOM converters in `impl/` packages handle reference resolution
**Framework Integration** (`com.intellij.struts2.facet`)
+
- `StrutsFacet` / `StrutsFacetType` - Framework facet configuration
- `StrutsFrameworkDetector` - Auto-detection of Struts projects
- `StrutsFrameworkInitializer` - Modern `ProjectActivity`-based initialization
(replaces deprecated `StartupManager`)
- `FileSetConfigurationTab` - UI for configuring struts.xml file sets
**Reference Resolution** (`com.intellij.struts2.reference`)
+
- `StrutsReferenceContributor` - XML reference providers for struts.xml
- `jsp/` - JSP tag library references and action link resolution
- Reference contributors for various Struts tag libraries (jQuery, Bootstrap,
etc.)
**OGNL Language** (`com.intellij.lang.ognl`)
+
- `OgnlLanguage` / `OgnlFileType` - Language definition
- `lexer/` - JFlex-based lexer (`ognl.flex`)
- `parser/` - Grammar Kit parser (`OgnlParser.bnf`)
@@ -64,23 +73,32 @@ This is an IntelliJ IDEA Ultimate plugin for Apache Struts
2 framework, providin
- `completion/` - Code completion providers
**Extension Points** (defined in `plugin.xml`)
+
- `struts2.constantContributor` - Add custom Struts constants
- `struts2.resultContributor` - Custom result type path resolution
- `struts2.classContributor` - Extend class resolution (actions, interceptors)
- `struts2.paramNameCustomConverter` - Custom parameter name resolution
### Template Engine Integrations
+
Optional modules loaded via `<depends optional="true">`:
+
- `struts2-freemarker.xml` - FreeMarker template support
- `struts2-velocity.xml` - Velocity template support
- `struts2-spring.xml` - Spring integration
- `struts2-groovy.xml` - Groovy annotations support
### Test Organization
+
- `src/test/java` - Test classes following IntelliJ Platform test patterns
- `src/test/testData` - Test fixture files (XML, JSP, Java sources)
- Test base classes extend IntelliJ Platform's
`LightJavaCodeInsightFixtureTestCase` or similar
+### Generated Code
+
+- `src/main/gen/` - Generated parser/lexer code (included in source set
automatically)
+- Source grammars: `src/main/grammar/ognl.bnf` (Grammar Kit),
`_OgnlLexer.flex` (JFlex)
+
## IntelliJ Platform Version Mapping
| Branch | Platform Version | Build Range |
@@ -89,51 +107,59 @@ Optional modules loaded via `<depends optional="true">`:
| 243.x | 2024.3 | 243.* |
| 251.x | 2025.1 | 251.* |
| 252.x | 2025.2 | 252.* |
+| 253.x | 2025.3 | 253.* |
### Plugin Version Format
+
`{BRANCH}.{BUILD}.{FIX}` (e.g., `252.18970.1`)
- **BRANCH** - IntelliJ Platform branch (252 = 2025.2)
- **BUILD** - Automatically calculated in GitHub Actions as `18969 + git
rev-list --count HEAD`
- **FIX** - Patch version (typically `1` for new builds)
-The base value `18969` maintains historical continuity from when the plugin
was donated by JetBrains to Apache Software Foundation, ensuring version
numbers continue from the previous build sequence.
+The base value `18969` maintains historical continuity from when the plugin
was donated by JetBrains to Apache Software
+Foundation, ensuring version numbers continue from the previous build sequence.
## Platform Upgrade Checklist
When upgrading to a new IntelliJ Platform version:
1. **Update `gradle.properties`**:
- - `platformVersion` - Target platform (e.g., `2025.2`)
- - `pluginSinceBuild` / `pluginUntilBuild` - Build range (e.g., `251` to
`252.*`)
- - `pluginVersion` - Match branch prefix (e.g., `252.x.y`)
-
+ - `platformVersion` - Target platform (e.g., `2025.2`)
+ - `pluginSinceBuild` / `pluginUntilBuild` - Build range (e.g., `251` to
`252.*`)
+ - `pluginVersion` - Match branch prefix (e.g., `252.x.y`)
2. **Check API Compatibility**:
- - Review https://jb.gg/intellij-api-changes for breaking changes
- - Run `./gradlew runPluginVerifier` to detect issues
- - Common changes: deprecated UI icons, removed internal APIs, changed test
framework paths
-
+ - Review https://jb.gg/intellij-api-changes for breaking changes
+ - Run `./gradlew runPluginVerifier` to detect issues
+ - Common changes: deprecated UI icons, removed internal APIs, changed test
framework paths
3. **Update CI/Tooling** (if Java version changes):
- - `.github/workflows/build.yml` - Java version in setup
- - `qodana.yml` - Linter version and `projectJDK`
- - `build.gradle.kts` - `jvmToolchain()` version
-
+ - `.github/workflows/build.yml` - Java version in setup
+ - `qodana.yml` - Linter version and `projectJDK`
+ - `build.gradle.kts` - `jvmToolchain()` version
4. **Fix Test Path Issues**:
- - IntelliJ Platform test frameworks sometimes change path resolution
- - Override `getBasePath()` and `getTestDataPath()` if tests fail to find
fixtures
- - Use project-relative paths like `"src/test/testData/..."`
-
+ - IntelliJ Platform test frameworks sometimes change path resolution
+ - Override `getBasePath()` and `getTestDataPath()` if tests fail to find
fixtures
+ - Use project-relative paths like `"src/test/testData/..."`
5. **Update CHANGELOG.md** with dependency upgrades
## Known Platform Quirks
-**Test Data Path Resolution**: IntelliJ 2024.2+ changed how `LexerTestCase`
and `DomStubTest` resolve paths. If tests fail with "Cannot find source file",
override path methods to use project-relative paths.
+**Test Data Path Resolution**: IntelliJ 2024.2+ changed how `LexerTestCase`
and `DomStubTest` resolve paths. If tests
+fail with "Cannot find source file", override path methods to use
project-relative paths.
+
+**Internal API Usage**: Some platform icons and utilities are internal. The
plugin verifier will warn about these.
+Prefer public APIs:
-**Internal API Usage**: Some platform icons and utilities are internal. The
plugin verifier will warn about these. Prefer public APIs:
- Use `AllIcons.Nodes.*` instead of `PlatformIcons`
- Use `Charset.availableCharsets()` instead of
`CharsetToolkit.getAvailableCharsets()`
-**JSP Reference Providers**: The `javaee.web.customServletReferenceProvider`
extension point behavior changed in 2024.2. Action link references in JSP may
need alternative registration approaches.
+**JSP Reference Providers**: The `javaee.web.customServletReferenceProvider`
extension point behavior changed in 2024.2.
+Action link references in JSP may need alternative registration approaches.
+
+**Temporarily Disabled Tests**: Several tests are disabled pending 2025.3
compatibility fixes:
+OgnlLexerTest, StrutsCompletionTest, StrutsHighlightingSpringTest,
StrutsResultResolvingTest,
+ActionLinkReferenceProviderTest. See CHANGELOG.md for full list - these should
be re-enabled
+when infrastructure issues are resolved.
## Claude Guidance
diff --git a/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
b/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
index 449531f..1fc4f32 100644
--- a/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
+++ b/src/main/gen/com/intellij/lang/ognl/OgnlIcons.java
@@ -1,7 +1,7 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source
code is governed by the Apache 2.0 license.
package com.intellij.lang.ognl;
-import com.intellij.ui.IconManager;
+import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -11,8 +11,12 @@ import javax.swing.*;
* DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
*/
public final class OgnlIcons {
- private static @NotNull Icon load(@NotNull String path, int cacheKey, int
flags) {
- return IconManager.getInstance().loadRasterizedIcon(path,
OgnlIcons.class.getClassLoader(), cacheKey, flags);
- }
- /** 10x10 */ public static final @NotNull Icon Action_small =
load("icons/action_small.svg", -592871696, 0);
+ private static @NotNull Icon load(@NotNull String path) {
+ return IconLoader.getIcon(path, OgnlIcons.class.getClassLoader());
+ }
+
+ /**
+ * 10x10
+ */
+ public static final @NotNull Icon Action_small =
load("icons/action_small.svg");
}
diff --git a/src/main/java/com/intellij/struts2/Struts2Icons.java
b/src/main/java/com/intellij/struts2/Struts2Icons.java
index 7322e7c..e6bffd5 100644
--- a/src/main/java/com/intellij/struts2/Struts2Icons.java
+++ b/src/main/java/com/intellij/struts2/Struts2Icons.java
@@ -16,7 +16,7 @@
*/
package com.intellij.struts2;
-import com.intellij.ui.IconManager;
+import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -26,10 +26,20 @@ import javax.swing.*;
* DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
*/
public final class Struts2Icons {
- private static @NotNull Icon load(@NotNull String path, int cacheKey, int
flags) {
- return IconManager.getInstance().loadRasterizedIcon(path,
Struts2Icons.class.getClassLoader(), cacheKey, flags);
- }
- /** 16x16 */ public static final @NotNull Icon Action =
load("icons/action.svg", 1640284181, 0);
- /** 10x10 */ public static final @NotNull Icon Action_small =
load("icons/action_small.svg", -592871696, 0);
- /** 10x10 */ public static final @NotNull Icon Edit_small =
load("icons/edit_small.svg", 1635832574, 0);
+ private static @NotNull Icon load(@NotNull String path) {
+ return IconLoader.getIcon(path, Struts2Icons.class.getClassLoader());
+ }
+
+ /**
+ * 16x16
+ */
+ public static final @NotNull Icon Action = load("icons/action.svg");
+ /**
+ * 10x10
+ */
+ public static final @NotNull Icon Action_small =
load("icons/action_small.svg");
+ /**
+ * 10x10
+ */
+ public static final @NotNull Icon Edit_small =
load("icons/edit_small.svg");
}
diff --git a/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
b/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
index 82f399f..96f1d75 100644
--- a/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
+++ b/src/main/java/com/intellij/struts2/Struts2ResourceProvider.java
@@ -25,79 +25,79 @@ import org.jetbrains.annotations.NonNls;
* @author Dmitry Avdeev
*/
final class Struts2ResourceProvider implements StandardResourceProvider {
- @NonNls
- private static final String DTD_PATH = "/resources/dtds/";
-
- @Override
- public void registerResources(final ResourceRegistrar registrar) {
- addDTDResource(StrutsConstants.STRUTS_2_0_DTD_URI,
- StrutsConstants.STRUTS_2_0_DTD_ID,
- "struts-2.0.dtd", registrar);
-
- addDTDResource(StrutsConstants.STRUTS_2_1_DTD_URI,
- StrutsConstants.STRUTS_2_1_DTD_ID,
- "struts-2.1.dtd", registrar);
-
- addDTDResource(StrutsConstants.STRUTS_2_1_7_DTD_URI,
- StrutsConstants.STRUTS_2_1_7_DTD_ID,
- "struts-2.1.7.dtd", registrar);
-
- addDTDResource(StrutsConstants.STRUTS_2_3_DTD_URI,
- StrutsConstants.STRUTS_2_3_DTD_ID,
- "struts-2.3.dtd", registrar);
-
- addDTDResource(StrutsConstants.STRUTS_2_5_DTD_URI,
- StrutsConstants.STRUTS_2_5_DTD_ID,
- "struts-2.5.dtd", registrar);
-
- addDTDResource(StrutsConstants.STRUTS_6_0_DTD_URI,
- StrutsConstants.STRUTS_6_0_DTD_ID,
- "struts-6.0.dtd", registrar);
-
-
- addDTDResource(StrutsConstants.VALIDATOR_1_00_DTD_URI,
- StrutsConstants.VALIDATOR_1_00_DTD_ID,
- "xwork-validator-1.0.dtd", registrar);
- addDTDResource(StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_URI,
- StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_ID,
- "xwork-validator-struts-1.0.dtd", registrar);
-
- addDTDResource(StrutsConstants.VALIDATOR_1_02_DTD_URI,
- StrutsConstants.VALIDATOR_1_02_DTD_ID,
- "xwork-validator-1.0.2.dtd", registrar);
- addDTDResource(StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_URI,
- StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_ID,
- "xwork-validator-struts-1.0.2.dtd", registrar);
-
- addDTDResource(StrutsConstants.VALIDATOR_1_03_DTD_URI,
- StrutsConstants.VALIDATOR_1_03_DTD_ID,
- "xwork-validator-1.0.3.dtd", registrar);
-
- addDTDResource(StrutsConstants.VALIDATOR_CONFIG_DTD_URI,
- StrutsConstants.VALIDATOR_CONFIG_DTD_ID,
- "xwork-validator-config-1.0.dtd", registrar);
- addDTDResource(StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_URI,
- StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_ID,
- "xwork-validator-config-struts-1.0.dtd", registrar);
- addDTDResource(StrutsConstants.VALIDATOR_DEFINITION_DTD_URI,
- StrutsConstants.VALIDATOR_DEFINITION_DTD_ID,
- "xwork-validator-definition-1.0.dtd", registrar);
- }
-
- /**
- * Adds a DTD resource from local DTD resource path.
- *
- * @param uri Resource URI.
- * @param id Resource ID.
- * @param localFile DTD filename.
- * @param registrar Resource registrar.
- */
- private static void addDTDResource(@NonNls final String uri,
- @NonNls final String id,
- @NonNls final String localFile,
- final ResourceRegistrar registrar) {
- registrar.addStdResource(uri, DTD_PATH + localFile,
Struts2ResourceProvider.class);
- registrar.addStdResource(id, DTD_PATH + localFile,
Struts2ResourceProvider.class);
- }
+ @NonNls
+ private static final String DTD_PATH = "/resources/dtds/";
+
+ @Override
+ public void registerResources(final ResourceRegistrar registrar) {
+ addDTDResource(StrutsConstants.STRUTS_2_0_DTD_URI,
+ StrutsConstants.STRUTS_2_0_DTD_ID,
+ "struts-2.0.dtd", registrar);
+
+ addDTDResource(StrutsConstants.STRUTS_2_1_DTD_URI,
+ StrutsConstants.STRUTS_2_1_DTD_ID,
+ "struts-2.1.dtd", registrar);
+
+ addDTDResource(StrutsConstants.STRUTS_2_1_7_DTD_URI,
+ StrutsConstants.STRUTS_2_1_7_DTD_ID,
+ "struts-2.1.7.dtd", registrar);
+
+ addDTDResource(StrutsConstants.STRUTS_2_3_DTD_URI,
+ StrutsConstants.STRUTS_2_3_DTD_ID,
+ "struts-2.3.dtd", registrar);
+
+ addDTDResource(StrutsConstants.STRUTS_2_5_DTD_URI,
+ StrutsConstants.STRUTS_2_5_DTD_ID,
+ "struts-2.5.dtd", registrar);
+
+ addDTDResource(StrutsConstants.STRUTS_6_0_DTD_URI,
+ StrutsConstants.STRUTS_6_0_DTD_ID,
+ "struts-6.0.dtd", registrar);
+
+
+ addDTDResource(StrutsConstants.VALIDATOR_1_00_DTD_URI,
+ StrutsConstants.VALIDATOR_1_00_DTD_ID,
+ "xwork-validator-1.0.dtd", registrar);
+ addDTDResource(StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_URI,
+ StrutsConstants.VALIDATOR_1_00_STRUTS_DTD_ID,
+ "xwork-validator-struts-1.0.dtd", registrar);
+
+ addDTDResource(StrutsConstants.VALIDATOR_1_02_DTD_URI,
+ StrutsConstants.VALIDATOR_1_02_DTD_ID,
+ "xwork-validator-1.0.2.dtd", registrar);
+ addDTDResource(StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_URI,
+ StrutsConstants.VALIDATOR_1_02_STRUTS_DTD_ID,
+ "xwork-validator-struts-1.0.2.dtd", registrar);
+
+ addDTDResource(StrutsConstants.VALIDATOR_1_03_DTD_URI,
+ StrutsConstants.VALIDATOR_1_03_DTD_ID,
+ "xwork-validator-1.0.3.dtd", registrar);
+
+ addDTDResource(StrutsConstants.VALIDATOR_CONFIG_DTD_URI,
+ StrutsConstants.VALIDATOR_CONFIG_DTD_ID,
+ "xwork-validator-config-1.0.dtd", registrar);
+ addDTDResource(StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_URI,
+ StrutsConstants.VALIDATOR_CONFIG_STRUTS_DTD_ID,
+ "xwork-validator-config-struts-1.0.dtd", registrar);
+ addDTDResource(StrutsConstants.VALIDATOR_DEFINITION_DTD_URI,
+ StrutsConstants.VALIDATOR_DEFINITION_DTD_ID,
+ "xwork-validator-definition-1.0.dtd", registrar);
+ }
+
+ /**
+ * Adds a DTD resource from local DTD resource path.
+ *
+ * @param uri Resource URI.
+ * @param id Resource ID.
+ * @param localFile DTD filename.
+ * @param registrar Resource registrar.
+ */
+ private static void addDTDResource(@NonNls final String uri,
+ @NonNls final String id,
+ @NonNls final String localFile,
+ final ResourceRegistrar registrar) {
+ registrar.addStdResource(uri, DTD_PATH + localFile,
Struts2ResourceProvider.class.getClassLoader());
+ registrar.addStdResource(id, DTD_PATH + localFile,
Struts2ResourceProvider.class.getClassLoader());
+ }
}
\ No newline at end of file
diff --git
a/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
b/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
index 63ab97b..cb92169 100644
---
a/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
+++
b/src/main/java/com/intellij/struts2/dom/struts/impl/path/FileReferenceSetHelper.java
@@ -42,76 +42,76 @@ import java.util.Objects;
*/
public final class FileReferenceSetHelper {
- private FileReferenceSetHelper() {
- }
+ private FileReferenceSetHelper() {
+ }
- /**
- * Creates a new FileReferenceSet allowing references only to
(web-)directories and given FileType.
- *
- * @param psiElement Current element.
- * @param allowedFileType Allowed filetype for resolving.
- * @return Instance.
- */
- public static FileReferenceSet createRestrictedByFileType(final PsiElement
psiElement,
- @NotNull FileType
allowedFileType) {
- return new FileReferenceSet(psiElement) {
+ /**
+ * Creates a new FileReferenceSet allowing references only to
(web-)directories and given FileType.
+ *
+ * @param psiElement Current element.
+ * @param allowedFileType Allowed filetype for resolving.
+ * @return Instance.
+ */
+ public static FileReferenceSet createRestrictedByFileType(final PsiElement
psiElement,
+ @NotNull
FileType allowedFileType) {
+ return new FileReferenceSet(psiElement) {
- @Override
- protected boolean isSoft() {
- return true;
- }
+ @Override
+ protected boolean isSoft() {
+ return true;
+ }
- @Override
- protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
- return psiFileSystemItem -> {
- if (psiFileSystemItem instanceof PsiDirectory ||
- psiFileSystemItem instanceof WebDirectoryElement) {
- return true;
- }
+ @Override
+ protected Condition<PsiFileSystemItem>
getReferenceCompletionFilter() {
+ return psiFileSystemItem -> {
+ if (psiFileSystemItem instanceof PsiDirectory ||
+ psiFileSystemItem instanceof WebDirectoryElement) {
+ return true;
+ }
- final VirtualFile virtualFile = psiFileSystemItem.getVirtualFile();
- return virtualFile != null &&
FileTypeRegistry.getInstance().isFileOfType(virtualFile, allowedFileType);
+ final VirtualFile virtualFile =
psiFileSystemItem.getVirtualFile();
+ return virtualFile != null &&
FileTypeRegistry.getInstance().isFileOfType(virtualFile, allowedFileType);
+ };
+ }
};
- }
- };
- }
+ }
- /**
- * Adds all {@link WebDirectoryElement}s as well as web-directory with name
of given current namespace
- * (if not "root" namespace) as possible content roots.
- *
- * @param psiElement Current element.
- * @param namespace Current namespace.
- * @param webFacet Module.
- * @param set FRS to patch.
- */
- public static void addWebDirectoryAndCurrentNamespaceAsRoots(final
PsiElement psiElement,
- final String
namespace,
- final WebFacet
webFacet,
- final
FileReferenceSet set) {
- final WebDirectoryUtil directoryUtil =
WebDirectoryUtil.getWebDirectoryUtil(psiElement.getProject());
- set.addCustomization(
- FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION,
- file -> {
- final List<PsiFileSystemItem> basePathRoots = new ArrayList<>();
+ /**
+ * Adds all {@link WebDirectoryElement}s as well as web-directory with
name of given current namespace
+ * (if not "root" namespace) as possible content roots.
+ *
+ * @param psiElement Current element.
+ * @param namespace Current namespace.
+ * @param webFacet Module.
+ * @param set FRS to patch.
+ */
+ public static void addWebDirectoryAndCurrentNamespaceAsRoots(final
PsiElement psiElement,
+ final String
namespace,
+ final
WebFacet webFacet,
+ final
FileReferenceSet set) {
+ final WebDirectoryUtil directoryUtil =
WebDirectoryUtil.getWebDirectoryUtil(psiElement.getProject());
+ set.addCustomization(
+ FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION,
+ file -> {
+ final List<PsiFileSystemItem> basePathRoots = new
ArrayList<>();
- // 1. add all configured web root mappings
- final List<WebRoot> webRoots = webFacet.getWebRoots(true);
- for (final WebRoot webRoot : webRoots) {
- final String webRootPath = webRoot.getRelativePath();
- final WebDirectoryElement webRootBase =
- directoryUtil.findWebDirectoryElementByPath(webRootPath,
webFacet);
- ContainerUtil.addIfNotNull(basePathRoots, webRootBase);
- }
+ // 1. add all configured web root mappings
+ final List<WebRoot> webRoots = webFacet.getWebRoots();
+ for (final WebRoot webRoot : webRoots) {
+ final String webRootPath = webRoot.getRelativePath();
+ final WebDirectoryElement webRootBase =
+
directoryUtil.findWebDirectoryElementByPath(webRootPath, webFacet);
+ ContainerUtil.addIfNotNull(basePathRoots, webRootBase);
+ }
- // 2. add parent <package> "namespace" as result prefix directory
path if not ROOT
- if (!Objects.equals(namespace, StrutsPackage.DEFAULT_NAMESPACE)) {
- final WebDirectoryElement packageBase =
- directoryUtil.findWebDirectoryElementByPath(namespace,
webFacet);
- ContainerUtil.addIfNotNull(basePathRoots, packageBase);
- }
+ // 2. add parent <package> "namespace" as result prefix
directory path if not ROOT
+ if (!Objects.equals(namespace,
StrutsPackage.DEFAULT_NAMESPACE)) {
+ final WebDirectoryElement packageBase =
+
directoryUtil.findWebDirectoryElementByPath(namespace, webFacet);
+ ContainerUtil.addIfNotNull(basePathRoots, packageBase);
+ }
- return basePathRoots;
- });
- }
+ return basePathRoots;
+ });
+ }
}
\ No newline at end of file
diff --git
a/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
b/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
index 415e103..939ee02 100644
--- a/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
+++ b/src/main/java/com/intellij/struts2/facet/ui/FileSetConfigurationTab.java
@@ -26,6 +26,7 @@ import com.intellij.ide.projectView.PresentationData;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.ui.DialogWrapper;
@@ -68,378 +69,373 @@ import java.util.Set;
*/
public class FileSetConfigurationTab extends FacetEditorTab implements
Disposable {
- private final StructureTreeModel<SimpleTreeStructure> myModel;
- // GUI components -----------------------
- private JPanel myPanel;
-
- private final SimpleTree myTree;
- private final AnActionButton myRemoveButton;
- private final AnActionButton myEditButton;
- private JPanel myTreePanel;
-
- // GUI helpers
- private final SimpleNode myRootNode = new SimpleNode() {
- @Override
- public SimpleNode @NotNull [] getChildren() {
- final List<SimpleNode> nodes = new ArrayList<>(myBuffer.size());
- for (final StrutsFileSet entry : myBuffer) {
- if (!entry.isRemoved()) {
- final FileSetNode setNode = new FileSetNode(entry);
- nodes.add(setNode);
+ private final StructureTreeModel<SimpleTreeStructure> myModel;
+ // GUI components -----------------------
+ private JPanel myPanel;
+
+ private final SimpleTree myTree;
+ private final AnActionButton myRemoveButton;
+ private final AnActionButton myEditButton;
+ private JPanel myTreePanel;
+
+ // GUI helpers
+ private final SimpleNode myRootNode = new SimpleNode() {
+ @Override
+ public SimpleNode @NotNull [] getChildren() {
+ final List<SimpleNode> nodes = new ArrayList<>(myBuffer.size());
+ for (final StrutsFileSet entry : myBuffer) {
+ if (!entry.isRemoved()) {
+ final FileSetNode setNode = new FileSetNode(entry);
+ nodes.add(setNode);
+ }
+ }
+ return nodes.toArray(new SimpleNode[0]);
}
- }
- return nodes.toArray(new SimpleNode[0]);
- }
-
- @Override
- public boolean isAutoExpandNode() {
- return true;
- }
- };
- private final TreeExpander myTreeExpander;
+ @Override
+ public boolean isAutoExpandNode() {
+ return true;
+ }
+ };
- private final StrutsConfigsSearcher myConfigsSearcher;
+ private final TreeExpander myTreeExpander;
- // original config
- private final StrutsFacetConfiguration originalConfiguration;
- private final Module module;
+ private final StrutsConfigsSearcher myConfigsSearcher;
- // local config
- private final Set<StrutsFileSet> myBuffer = new LinkedHashSet<>();
- private boolean myModified;
+ // original config
+ private final StrutsFacetConfiguration originalConfiguration;
+ private final Module module;
- public FileSetConfigurationTab(@NotNull final StrutsFacetConfiguration
strutsFacetConfiguration,
- @NotNull final FacetEditorContext
facetEditorContext) {
- originalConfiguration = strutsFacetConfiguration;
- module = facetEditorContext.getModule();
- myConfigsSearcher = new StrutsConfigsSearcher(module);
+ // local config
+ private final Set<StrutsFileSet> myBuffer = new LinkedHashSet<>();
+ private boolean myModified;
- // init tree
- final SimpleTreeStructure structure = new SimpleTreeStructure() {
- @NotNull
- @Override
- public Object getRootElement() {
- return myRootNode;
- }
- };
+ public FileSetConfigurationTab(@NotNull final StrutsFacetConfiguration
strutsFacetConfiguration,
+ @NotNull final FacetEditorContext
facetEditorContext) {
+ originalConfiguration = strutsFacetConfiguration;
+ module = facetEditorContext.getModule();
+ myConfigsSearcher = new StrutsConfigsSearcher(module);
- myTree = new SimpleTree();
- myTree.setRootVisible(false);
- myTree.setShowsRootHandles(true); // show expand/collapse handles
-
myTree.getEmptyText().setText(StrutsBundle.message("facet.fileset.no.filesets.defined"),
SimpleTextAttributes.ERROR_ATTRIBUTES);
- myTreeExpander = new DefaultTreeExpander(myTree);
-
- myModel = new StructureTreeModel<>(structure, this);
- myTree.setModel(new AsyncTreeModel(myModel, this));
-
- final DumbService dumbService =
DumbService.getInstance(facetEditorContext.getProject());
- myTree.getSelectionModel().addTreeSelectionListener(new
TreeSelectionListener() {
- @Override
- public void valueChanged(final TreeSelectionEvent e) {
- final StrutsFileSet fileSet = getCurrentFileSet();
- myEditButton.setEnabled(fileSet != null && !dumbService.isDumb());
- myRemoveButton.setEnabled(fileSet != null);
- }
- });
-
- final CommonActionsManager actionManager =
CommonActionsManager.getInstance();
- myTreePanel.add(
- ToolbarDecorator.createDecorator(myTree)
- .setAddAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- final StrutsFileSet fileSet =
- new StrutsFileSet(StrutsFileSet.getUniqueId(myBuffer),
-
StrutsFileSet.getUniqueName(StrutsBundle.message("facet.fileset.my.fileset"),
myBuffer),
- originalConfiguration) {
- @Override
- public boolean isNew() {
- return true;
- }
- };
-
- final FileSetEditor editor = new FileSetEditor(myPanel,
- fileSet,
- facetEditorContext,
- myConfigsSearcher);
- editor.show();
- if (editor.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
- final StrutsFileSet editedFileSet = editor.getEditedFileSet();
- Disposer.register(strutsFacetConfiguration, editedFileSet);
- myBuffer.add(editedFileSet);
- myModified = true;
- myModel.invalidateAsync().thenRun(() ->
selectFileSet(editedFileSet));
+ // init tree
+ final SimpleTreeStructure structure = new SimpleTreeStructure() {
+ @NotNull
+ @Override
+ public Object getRootElement() {
+ return myRootNode;
}
- IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() ->
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true));
- }
- })
- .setRemoveAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- remove();
- myModified = true;
- myModel.invalidateAsync();
- IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() ->
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true));
- }
- })
- .setEditAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- final StrutsFileSet fileSet = getCurrentFileSet();
- if (fileSet != null) {
- final FileSetEditor editor = new FileSetEditor(myPanel,
- fileSet,
-
facetEditorContext,
-
myConfigsSearcher);
- editor.show();
- if (editor.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
- myModified = true;
- myBuffer.remove(fileSet);
- final StrutsFileSet edited = editor.getEditedFileSet();
- Disposer.register(strutsFacetConfiguration, edited);
- myBuffer.add(edited);
- edited.setAutodetected(false);
- myModel.invalidateAsync();
- selectFileSet(edited);
- }
- IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() ->
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true));
+ };
+
+ myTree = new SimpleTree();
+ myTree.setRootVisible(false);
+ myTree.setShowsRootHandles(true); // show expand/collapse handles
+
myTree.getEmptyText().setText(StrutsBundle.message("facet.fileset.no.filesets.defined"),
SimpleTextAttributes.ERROR_ATTRIBUTES);
+ myTreeExpander = new DefaultTreeExpander(myTree);
+
+ myModel = new StructureTreeModel<>(structure, this);
+ myTree.setModel(new AsyncTreeModel(myModel, this));
+
+ final DumbService dumbService =
DumbService.getInstance(facetEditorContext.getProject());
+ myTree.getSelectionModel().addTreeSelectionListener(new
TreeSelectionListener() {
+ @Override
+ public void valueChanged(final TreeSelectionEvent e) {
+ final StrutsFileSet fileSet = getCurrentFileSet();
+ myEditButton.setEnabled(fileSet != null &&
!dumbService.isDumb());
+ myRemoveButton.setEnabled(fileSet != null);
}
- }
- })
- .addExtraAction(actionManager.createExpandAllAction(myTreeExpander,
myTree))
- .addExtraAction(actionManager.createCollapseAllAction(myTreeExpander,
myTree))
- .addExtraAction(new
AnActionButton(StrutsBundle.messagePointer("action.AnActionButton.text.open.struts.2.plugin.documentation"),
- AllIcons.Actions.Help) {
- @Override
- public void actionPerformed(@NotNull AnActionEvent e) {
-
BrowserUtil.browse("https://confluence.jetbrains.com/pages/viewpage.action?pageId=35367");
- }
-
- @Override
- public @NotNull ActionUpdateThread getActionUpdateThread() {
- return ActionUpdateThread.EDT;
- }
- })
-
- .disableUpDownActions()
- .createPanel());
-
- myEditButton = ToolbarDecorator.findEditButton(myTreePanel);
- myRemoveButton = ToolbarDecorator.findRemoveButton(myTreePanel);
-
- // Note: makeDumbAware API may have changed in IntelliJ Platform 2025.2
- // Removing these calls as they caused compilation errors
- // Component dumb awareness should still work through DumbAware interface
- }
-
- @Nullable
- private StrutsFileSet getCurrentFileSet() {
- final FileSetNode currentFileSetNode = getCurrentFileSetNode();
- return currentFileSetNode == null ? null : currentFileSetNode.mySet;
- }
-
- @Nullable
- private FileSetNode getCurrentFileSetNode() {
- final SimpleNode selectedNode = myTree.getSelectedNode();
- if (selectedNode == null) {
- return null;
+ });
+
+ final CommonActionsManager actionManager =
CommonActionsManager.getInstance();
+ myTreePanel.add(
+ ToolbarDecorator.createDecorator(myTree)
+ .setAddAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ final StrutsFileSet fileSet =
+ new
StrutsFileSet(StrutsFileSet.getUniqueId(myBuffer),
+
StrutsFileSet.getUniqueName(StrutsBundle.message("facet.fileset.my.fileset"),
myBuffer),
+ originalConfiguration) {
+ @Override
+ public boolean isNew() {
+ return true;
+ }
+ };
+
+ final FileSetEditor editor = new
FileSetEditor(myPanel,
+ fileSet,
+ facetEditorContext,
+ myConfigsSearcher);
+ editor.show();
+ if (editor.getExitCode() ==
DialogWrapper.OK_EXIT_CODE) {
+ final StrutsFileSet editedFileSet =
editor.getEditedFileSet();
+
Disposer.register(strutsFacetConfiguration, editedFileSet);
+ myBuffer.add(editedFileSet);
+ myModified = true;
+ myModel.invalidateAsync().thenRun(() ->
selectFileSet(editedFileSet));
+ }
+
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true);
+ }
+ })
+ .setRemoveAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ remove();
+ myModified = true;
+ myModel.invalidateAsync();
+
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true);
+ }
+ })
+ .setEditAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ final StrutsFileSet fileSet =
getCurrentFileSet();
+ if (fileSet != null) {
+ final FileSetEditor editor = new
FileSetEditor(myPanel,
+ fileSet,
+ facetEditorContext,
+ myConfigsSearcher);
+ editor.show();
+ if (editor.getExitCode() ==
DialogWrapper.OK_EXIT_CODE) {
+ myModified = true;
+ myBuffer.remove(fileSet);
+ final StrutsFileSet edited =
editor.getEditedFileSet();
+
Disposer.register(strutsFacetConfiguration, edited);
+ myBuffer.add(edited);
+ edited.setAutodetected(false);
+ myModel.invalidateAsync();
+ selectFileSet(edited);
+ }
+
IdeFocusManager.getGlobalInstance().requestFocus(myTree, true);
+ }
+ }
+ })
+
.addExtraAction(actionManager.createExpandAllAction(myTreeExpander, myTree))
+
.addExtraAction(actionManager.createCollapseAllAction(myTreeExpander, myTree))
+ .addExtraAction(new
DumbAwareAction(StrutsBundle.messagePointer("action.AnActionButton.text.open.struts.2.plugin.documentation"),
+ AllIcons.Actions.Help) {
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent
e) {
+
BrowserUtil.browse("https://confluence.jetbrains.com/pages/viewpage.action?pageId=35367");
+ }
+
+ @Override
+ public @NotNull ActionUpdateThread
getActionUpdateThread() {
+ return ActionUpdateThread.EDT;
+ }
+ })
+
+ .disableUpDownActions()
+ .createPanel());
+
+ myEditButton = ToolbarDecorator.findEditButton(myTreePanel);
+ myRemoveButton = ToolbarDecorator.findRemoveButton(myTreePanel);
+
+ // Note: makeDumbAware API may have changed in IntelliJ Platform 2025.2
+ // Removing these calls as they caused compilation errors
+ // Component dumb awareness should still work through DumbAware
interface
}
- if (selectedNode instanceof FileSetNode) {
- return (FileSetNode)selectedNode;
+
+ @Nullable
+ private StrutsFileSet getCurrentFileSet() {
+ final FileSetNode currentFileSetNode = getCurrentFileSetNode();
+ return currentFileSetNode == null ? null : currentFileSetNode.mySet;
}
- else if (selectedNode.getParent() instanceof FileSetNode) {
- return (FileSetNode)selectedNode.getParent();
+
+ @Nullable
+ private FileSetNode getCurrentFileSetNode() {
+ final SimpleNode selectedNode = myTree.getSelectedNode();
+ if (selectedNode == null) {
+ return null;
+ }
+ if (selectedNode instanceof FileSetNode) {
+ return (FileSetNode) selectedNode;
+ } else if (selectedNode.getParent() instanceof FileSetNode) {
+ return (FileSetNode) selectedNode.getParent();
+ } else {
+ final SimpleNode parent = selectedNode.getParent();
+ if (parent != null && parent.getParent() instanceof FileSetNode) {
+ return (FileSetNode) selectedNode.getParent().getParent();
+ }
+ }
+ return null;
}
- else {
- final SimpleNode parent = selectedNode.getParent();
- if (parent != null && parent.getParent() instanceof FileSetNode) {
- return (FileSetNode)selectedNode.getParent().getParent();
- }
+
+ private void selectFileSet(final StrutsFileSet fileSet) {
+ SimpleNode simpleNode = ContainerUtil.find(myRootNode.getChildren(),
node -> ((FileSetNode) node).mySet == fileSet);
+ assert simpleNode != null;
+ myModel.select(simpleNode, myTree, path -> {
+ });
}
- return null;
- }
-
- private void selectFileSet(final StrutsFileSet fileSet) {
- SimpleNode simpleNode = ContainerUtil.find(myRootNode.getChildren(), node
-> ((FileSetNode)node).mySet == fileSet);
- assert simpleNode != null;
- myModel.select(simpleNode, myTree, path -> {});
- }
-
- private void remove() {
- final SimpleNode[] nodes = myTree.getSelectedNodesIfUniform();
- for (final SimpleNode node : nodes) {
-
- if (node instanceof FileSetNode) {
- final StrutsFileSet fileSet = ((FileSetNode)node).mySet;
- if (fileSet.getFiles().isEmpty()) {
- myBuffer.remove(fileSet);
- return;
- }
- final int result = Messages.showYesNoDialog(myPanel,
-
StrutsBundle.message("facet.fileset.remove.fileset.question",
-
fileSet.getName()),
-
StrutsBundle.message("facet.fileset.remove.fileset.title"),
-
Messages.getQuestionIcon());
- if (result == Messages.YES) {
- if (fileSet.isAutodetected()) {
- fileSet.setRemoved(true);
- myBuffer.add(fileSet);
- }
- else {
- myBuffer.remove(fileSet);
- }
+ private void remove() {
+ final SimpleNode[] nodes = myTree.getSelectedNodesIfUniform();
+ for (final SimpleNode node : nodes) {
+
+ if (node instanceof FileSetNode) {
+ final StrutsFileSet fileSet = ((FileSetNode) node).mySet;
+ if (fileSet.getFiles().isEmpty()) {
+ myBuffer.remove(fileSet);
+ return;
+ }
+
+ final int result = Messages.showYesNoDialog(myPanel,
+
StrutsBundle.message("facet.fileset.remove.fileset.question",
+ fileSet.getName()),
+
StrutsBundle.message("facet.fileset.remove.fileset.title"),
+ Messages.getQuestionIcon());
+ if (result == Messages.YES) {
+ if (fileSet.isAutodetected()) {
+ fileSet.setRemoved(true);
+ myBuffer.add(fileSet);
+ } else {
+ myBuffer.remove(fileSet);
+ }
+ }
+ } else if (node instanceof ConfigFileNode) {
+ final VirtualFilePointer filePointer = ((ConfigFileNode)
node).myFilePointer;
+ final StrutsFileSet fileSet = ((FileSetNode)
node.getParent()).mySet;
+ fileSet.removeFile(filePointer);
+ }
}
- }
- else if (node instanceof ConfigFileNode) {
- final VirtualFilePointer filePointer =
((ConfigFileNode)node).myFilePointer;
- final StrutsFileSet fileSet = ((FileSetNode)node.getParent()).mySet;
- fileSet.removeFile(filePointer);
- }
}
- }
-
- @Override
- @Nls
- public String getDisplayName() {
- return StrutsBundle.message("facet.fileset.title");
- }
-
- @Override
- @NotNull
- public JComponent createComponent() {
- return myPanel;
- }
-
- @Override
- public boolean isModified() {
- return myModified;
- }
-
- @Override
- public void apply() {
- final Set<StrutsFileSet> fileSets = originalConfiguration.getFileSets();
- fileSets.clear();
- for (final StrutsFileSet fileSet : myBuffer) {
- if (!fileSet.isAutodetected() || fileSet.isRemoved()) {
- fileSets.add(fileSet);
- }
+
+ @Override
+ @Nls
+ public String getDisplayName() {
+ return StrutsBundle.message("facet.fileset.title");
}
- originalConfiguration.setModified();
- myModified = false;
- }
-
- @Override
- public void reset() {
- myBuffer.clear();
- final Set<StrutsFileSet> sets =
StrutsManager.getInstance(module.getProject()).getAllConfigFileSets(module);
- /*new StrutsFileSet(fileSet)*/
- myBuffer.addAll(sets);
-
- myModel.invalidateAsync();
- myTree.setSelectionRow(0);
- }
-
- @Override
- public void disposeUIResources() {
- Disposer.dispose(this);
- }
-
- @Override
- public void dispose() {
- }
-
- private class FileSetNode extends SimpleNode {
-
- protected final StrutsFileSet mySet;
-
- FileSetNode(final StrutsFileSet fileSet) {
- super(myRootNode);
- mySet = fileSet;
-
- final PresentationData presentationData = getPresentation();
- final String name = mySet.getName(); //NON-NLS
-
- if (fileSet.getFiles().isEmpty()) {
- presentationData.addText(name, getErrorAttributes());
-
presentationData.setTooltip(StrutsBundle.message("facet.fileset.no.files.attached"));
- }
- else {
- presentationData.addText(name, getPlainAttributes());
-
presentationData.setLocationString(Integer.toString(fileSet.getFiles().size()));
- }
+
+ @Override
+ @NotNull
+ public JComponent createComponent() {
+ return myPanel;
}
@Override
- public SimpleNode @NotNull [] getChildren() {
- final List<SimpleNode> nodes = new ArrayList<>();
+ public boolean isModified() {
+ return myModified;
+ }
- for (final VirtualFilePointer file : mySet.getFiles()) {
- nodes.add(new ConfigFileNode(file, this));
- }
- return nodes.toArray(new SimpleNode[0]);
+ @Override
+ public void apply() {
+ final Set<StrutsFileSet> fileSets =
originalConfiguration.getFileSets();
+ fileSets.clear();
+ for (final StrutsFileSet fileSet : myBuffer) {
+ if (!fileSet.isAutodetected() || fileSet.isRemoved()) {
+ fileSets.add(fileSet);
+ }
+ }
+ originalConfiguration.setModified();
+ myModified = false;
}
@Override
- public boolean isAutoExpandNode() {
- return true;
+ public void reset() {
+ myBuffer.clear();
+ final Set<StrutsFileSet> sets =
StrutsManager.getInstance(module.getProject()).getAllConfigFileSets(module);
+ /*new StrutsFileSet(fileSet)*/
+ myBuffer.addAll(sets);
+
+ myModel.invalidateAsync();
+ myTree.setSelectionRow(0);
}
@Override
- public Object @NotNull [] getEqualityObjects() {
- return new Object[]{mySet, mySet.getName(), mySet.getFiles()};
+ public void disposeUIResources() {
+ Disposer.dispose(this);
}
- }
+ @Override
+ public void dispose() {
+ }
- private static final class ConfigFileNode extends SimpleNode {
+ private class FileSetNode extends SimpleNode {
- private final VirtualFilePointer myFilePointer;
+ protected final StrutsFileSet mySet;
- ConfigFileNode(final VirtualFilePointer name, final SimpleNode parent) {
- super(parent);
- myFilePointer = name;
- getTemplatePresentation().setIcon(StrutsIcons.STRUTS_CONFIG_FILE);
- }
+ FileSetNode(final StrutsFileSet fileSet) {
+ super(myRootNode);
+ mySet = fileSet;
- @Override
- public boolean isAlwaysLeaf() {
- return true;
- }
+ final PresentationData presentationData = getPresentation();
+ final String name = mySet.getName(); //NON-NLS
- @Override
- protected void doUpdate(@NotNull PresentationData presentation) {
- final VirtualFile file = myFilePointer.getFile();
- if (file != null) {
- renderFile(presentation, file, getPlainAttributes(), null);
- }
- else {
- renderFile(presentation, null, getErrorAttributes(),
StrutsBundle.message("facet.fileset.file.not.found"));
- }
+ if (fileSet.getFiles().isEmpty()) {
+ presentationData.addText(name, getErrorAttributes());
+
presentationData.setTooltip(StrutsBundle.message("facet.fileset.no.files.attached"));
+ } else {
+ presentationData.addText(name, getPlainAttributes());
+
presentationData.setLocationString(Integer.toString(fileSet.getFiles().size()));
+ }
+ }
+
+ @Override
+ public SimpleNode @NotNull [] getChildren() {
+ final List<SimpleNode> nodes = new ArrayList<>();
+
+ for (final VirtualFilePointer file : mySet.getFiles()) {
+ nodes.add(new ConfigFileNode(file, this));
+ }
+ return nodes.toArray(new SimpleNode[0]);
+ }
+
+ @Override
+ public boolean isAutoExpandNode() {
+ return true;
+ }
+
+ @Override
+ public Object @NotNull [] getEqualityObjects() {
+ return new Object[]{mySet, mySet.getName(), mySet.getFiles()};
+ }
}
- private void renderFile(@NotNull PresentationData presentation,
- final VirtualFile file,
- final SimpleTextAttributes textAttributes,
- @NlsContexts.Tooltip @Nullable final String
toolTip) {
- presentation.setTooltip(toolTip);
- presentation.clearText();
- presentation.addText(myFilePointer.getFileName(), textAttributes);
//NON-NLS
-
- if (file != null) {
- presentation.setLocationString(file.getPath());
- }
+
+ private static final class ConfigFileNode extends SimpleNode {
+
+ private final VirtualFilePointer myFilePointer;
+
+ ConfigFileNode(final VirtualFilePointer name, final SimpleNode parent)
{
+ super(parent);
+ myFilePointer = name;
+ getTemplatePresentation().setIcon(StrutsIcons.STRUTS_CONFIG_FILE);
+ }
+
+ @Override
+ public boolean isAlwaysLeaf() {
+ return true;
+ }
+
+ @Override
+ protected void doUpdate(@NotNull PresentationData presentation) {
+ final VirtualFile file = myFilePointer.getFile();
+ if (file != null) {
+ renderFile(presentation, file, getPlainAttributes(), null);
+ } else {
+ renderFile(presentation, null, getErrorAttributes(),
StrutsBundle.message("facet.fileset.file.not.found"));
+ }
+ }
+
+ private void renderFile(@NotNull PresentationData presentation,
+ final VirtualFile file,
+ final SimpleTextAttributes textAttributes,
+ @NlsContexts.Tooltip @Nullable final String
toolTip) {
+ presentation.setTooltip(toolTip);
+ presentation.clearText();
+ presentation.addText(myFilePointer.getFileName(), textAttributes);
//NON-NLS
+
+ if (file != null) {
+ presentation.setLocationString(file.getPath());
+ }
+ }
+
+ @Override
+ public SimpleNode @NotNull [] getChildren() {
+ return NO_CHILDREN;
+ }
}
@Override
- public SimpleNode @NotNull [] getChildren() {
- return NO_CHILDREN;
+ public String getHelpTopic() {
+ return "reference.settings.project.structure.facets.struts2.facet";
}
- }
-
- @Override
- public String getHelpTopic() {
- return "reference.settings.project.structure.facets.struts2.facet";
- }
}
diff --git
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
index 6f84ea4..85a666d 100644
---
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
+++
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphComponent.java
@@ -52,110 +52,113 @@ import java.util.Objects;
* @author Yann Cébron
*/
public class Struts2GraphComponent extends JPanel implements DataProvider,
Disposable {
- @NonNls
- private static final String STRUTS2_DESIGNER_COMPONENT =
"STRUTS2_DESIGNER_COMPONENT";
-
- private final GraphBuilder<BasicStrutsNode, BasicStrutsEdge> myBuilder;
-
- public Struts2GraphComponent(final XmlFile xmlFile) {
- final ProgressIndicator progress =
ProgressManager.getInstance().getProgressIndicator();
-
- progress.setText("Initializing...");
- final Project project = xmlFile.getProject();
- final Graph2D graph = GraphManager.getGraphManager().createGraph2D();
- final Graph2DView view =
GraphManager.getGraphManager().createGraph2DView();
-
- progress.setText("Building model...");
- final StrutsDataModel myDataModel = new StrutsDataModel(xmlFile);
- final StrutsPresentationModel presentationModel = new
StrutsPresentationModel(graph);
+ @NonNls
+ private static final String STRUTS2_DESIGNER_COMPONENT =
"STRUTS2_DESIGNER_COMPONENT";
+
+ private final GraphBuilder<BasicStrutsNode, BasicStrutsEdge> myBuilder;
+
+ public Struts2GraphComponent(final XmlFile xmlFile) {
+ final ProgressIndicator progress =
ProgressManager.getInstance().getProgressIndicator();
+
+ progress.setText("Initializing...");
+ final Project project = xmlFile.getProject();
+ final Graph2D graph = GraphManager.getGraphManager().createGraph2D();
+ final Graph2DView view =
GraphManager.getGraphManager().createGraph2DView();
+
+ progress.setText("Building model...");
+ final StrutsDataModel myDataModel = new StrutsDataModel(xmlFile);
+ final StrutsPresentationModel presentationModel = new
StrutsPresentationModel(graph);
+
+ progress.setText("Setup graph...");
+ myBuilder =
GraphBuilderFactory.getInstance(project).createGraphBuilder(graph,
+ view,
+ myDataModel,
+ presentationModel);
+ Disposer.register(this, myBuilder);
+
+ JComponent graphComponent = myBuilder.getView().getJComponent();
+ setLayout(new BorderLayout());
+
+ ActionToolbar toolbar =
ActionManager.getInstance().createActionToolbar(
+ ActionPlaces.TOOLBAR,
AbstractGraphAction.getCommonToolbarActions(), true);
+ toolbar.setTargetComponent(graphComponent);
+
+ add(toolbar.getComponent(), BorderLayout.NORTH);
+ add(graphComponent, BorderLayout.CENTER);
+
+ // TODO: GraphBuilder.initialize() is @Internal API with no public
replacement.
+ // Consider migrating to Diagram API when available.
+ myBuilder.initialize();
+
+
DomManager.getDomManager(myBuilder.getProject()).addDomEventListener(new
DomEventListener() {
+ @Override
+ public void eventOccured(@NotNull final DomEvent event) {
+ if (isShowing()) {
+ // TODO: GraphBuilder.queueUpdate() is deprecated with no
public replacement.
+ myBuilder.queueUpdate();
+ }
+ }
+ }, this);
+ }
- progress.setText("Setup graph...");
- myBuilder =
GraphBuilderFactory.getInstance(project).createGraphBuilder(graph,
-
view,
-
myDataModel,
-
presentationModel);
- Disposer.register(this, myBuilder);
+ public List<DomElement> getSelectedDomElements() {
+ final var selected = new ArrayList<DomElement>();
+
GraphSelectionService.getInstance().forEachSelectedNode(myBuilder.getGraph(),
node -> {
+ final var nodeObject = myBuilder.getNodeObject(node);
+ if (nodeObject != null) {
+ ContainerUtil.addIfNotNull(selected,
nodeObject.getIdentifyingElement());
+ }
+ });
+ return selected;
+ }
- JComponent graphComponent = myBuilder.getView().getJComponent();
- setLayout(new BorderLayout());
+ public void setSelectedDomElement(final DomElement domElement) {
+ // TODO
+ //if (domElement == null) return;
+ //
+ //final SeamPagesDomElement pageflowDomElement =
domElement.getParentOfType(SeamPagesDomElement.class, false);
+ //if (pageflowDomElement == null) return;
+ //
+ //final Node selectedNode = myBuilder.getNode(pageflowDomElement);
+ //
+ //if (selectedNode != null) {
+ // final Graph2D graph = myBuilder.getGraph();
+ //
+ // for (Node n : graph.getNodeArray()) {
+ // final boolean selected = n.equals(selectedNode);
+ // graph.setSelected(n, selected);
+ // if (selected) {
+ // final YRectangle yRectangle = graph.getRectangle(n);
+ // if (!myBuilder.getView().getVisibleRect().contains(
+ // new Rectangle((int)yRectangle.getX(),
(int)yRectangle.getY(), (int)yRectangle.getWidth(),
(int)yRectangle.getHeight()))) {
+ // myBuilder.getView().setCenter(graph.getX(n), graph.getY(n));
+ // }
+ // }
+ // }
+ //}
+ //myBuilder.getView().updateView();
+ }
- ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(
- ActionPlaces.TOOLBAR, AbstractGraphAction.getCommonToolbarActions(),
true);
- toolbar.setTargetComponent(graphComponent);
+ public GraphBuilder getBuilder() {
+ return myBuilder;
+ }
- add(toolbar.getComponent(), BorderLayout.NORTH);
- add(graphComponent, BorderLayout.CENTER);
+ public Overview getOverview() {
+ return
GraphManager.getGraphManager().createOverview(myBuilder.getView());
+ }
- myBuilder.initialize();
+ @Override
+ public void dispose() {
+ }
- DomManager.getDomManager(myBuilder.getProject()).addDomEventListener(new
DomEventListener() {
- @Override
- public void eventOccured(@NotNull final DomEvent event) {
- if (isShowing()) {
- myBuilder.queueUpdate();
+ @Override
+ @Nullable
+ public Object getData(@NotNull @NonNls final String dataId) {
+ if (Objects.equals(dataId, STRUTS2_DESIGNER_COMPONENT)) {
+ return this;
}
- }
- }, this);
- }
-
- public List<DomElement> getSelectedDomElements() {
- final var selected = new ArrayList<DomElement>();
-
GraphSelectionService.getInstance().forEachSelectedNode(myBuilder.getGraph(),
node -> {
- final var nodeObject = myBuilder.getNodeObject(node);
- if (nodeObject != null) {
- ContainerUtil.addIfNotNull(selected,
nodeObject.getIdentifyingElement());
- }
- });
- return selected;
- }
-
- public void setSelectedDomElement(final DomElement domElement) {
- // TODO
- //if (domElement == null) return;
- //
- //final SeamPagesDomElement pageflowDomElement =
domElement.getParentOfType(SeamPagesDomElement.class, false);
- //if (pageflowDomElement == null) return;
- //
- //final Node selectedNode = myBuilder.getNode(pageflowDomElement);
- //
- //if (selectedNode != null) {
- // final Graph2D graph = myBuilder.getGraph();
- //
- // for (Node n : graph.getNodeArray()) {
- // final boolean selected = n.equals(selectedNode);
- // graph.setSelected(n, selected);
- // if (selected) {
- // final YRectangle yRectangle = graph.getRectangle(n);
- // if (!myBuilder.getView().getVisibleRect().contains(
- // new Rectangle((int)yRectangle.getX(), (int)yRectangle.getY(),
(int)yRectangle.getWidth(), (int)yRectangle.getHeight()))) {
- // myBuilder.getView().setCenter(graph.getX(n), graph.getY(n));
- // }
- // }
- // }
- //}
- //myBuilder.getView().updateView();
- }
-
- public GraphBuilder getBuilder() {
- return myBuilder;
- }
-
- public Overview getOverview() {
- return GraphManager.getGraphManager().createOverview(myBuilder.getView());
- }
-
- @Override
- public void dispose() {
- }
-
- @Override
- @Nullable
- public Object getData(@NotNull @NonNls final String dataId) {
- if (Objects.equals(dataId, STRUTS2_DESIGNER_COMPONENT)) {
- return this;
- }
- return null;
- }
+ return null;
+ }
}
\ No newline at end of file
diff --git
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
index 1438362..bc720b5 100644
---
a/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
+++
b/src/main/java/com/intellij/struts2/graph/fileEditor/Struts2GraphFileEditor.java
@@ -38,86 +38,87 @@ import java.util.List;
*/
public class Struts2GraphFileEditor extends PerspectiveFileEditor {
- private Struts2GraphComponent myComponent;
- private final XmlFile myXmlFile;
-
- private final @NotNull NotNullLazyValue<StructureViewBuilder>
myStructureViewBuilder =
- NotNullLazyValue.atomicLazy(() ->
GraphStructureViewBuilderSetup.setupFor(getStruts2GraphComponent().getBuilder(),
null));
-
- public Struts2GraphFileEditor(final Project project, final VirtualFile file)
{
- super(project, file);
-
- final PsiFile psiFile = getPsiFile();
- assert psiFile instanceof XmlFile;
-
- myXmlFile = (XmlFile)psiFile;
- }
-
- @Override
- @Nullable
- protected DomElement getSelectedDomElement() {
- final List<DomElement> selectedDomElements =
getStruts2GraphComponent().getSelectedDomElements();
-
- return selectedDomElements.size() > 0 ? selectedDomElements.get(0) : null;
- }
-
- @Override
- protected void setSelectedDomElement(final DomElement domElement) {
- getStruts2GraphComponent().setSelectedDomElement(domElement);
- }
-
- @Override
- @NotNull
- protected JComponent createCustomComponent() {
- return getStruts2GraphComponent();
- }
-
- @Override
- @Nullable
- public JComponent getPreferredFocusedComponent() {
- return getStruts2GraphComponent().getBuilder().getView().getJComponent();
- }
-
- @Override
- public void commit() {
- }
-
- @Override
- public void reset() {
- getStruts2GraphComponent().getBuilder().queueUpdate();
- }
-
- @Override
- @NotNull
- public String getName() {
- return "Graph";
- }
-
- @Override
- public StructureViewBuilder getStructureViewBuilder() {
- return myStructureViewBuilder.getValue();
- }
-
- private Struts2GraphComponent getStruts2GraphComponent() {
- if (myComponent == null) {
- myComponent = createGraphComponent();
- Disposer.register(this, myComponent);
+ private Struts2GraphComponent myComponent;
+ private final XmlFile myXmlFile;
+
+ private final @NotNull NotNullLazyValue<StructureViewBuilder>
myStructureViewBuilder =
+ NotNullLazyValue.atomicLazy(() ->
GraphStructureViewBuilderSetup.setupFor(getStruts2GraphComponent().getBuilder(),
null));
+
+ public Struts2GraphFileEditor(final Project project, final VirtualFile
file) {
+ super(project, file);
+
+ final PsiFile psiFile = getPsiFile();
+ assert psiFile instanceof XmlFile;
+
+ myXmlFile = (XmlFile) psiFile;
+ }
+
+ @Override
+ @Nullable
+ protected DomElement getSelectedDomElement() {
+ final List<DomElement> selectedDomElements =
getStruts2GraphComponent().getSelectedDomElements();
+
+ return selectedDomElements.size() > 0 ? selectedDomElements.get(0) :
null;
+ }
+
+ @Override
+ protected void setSelectedDomElement(final DomElement domElement) {
+ getStruts2GraphComponent().setSelectedDomElement(domElement);
+ }
+
+ @Override
+ @NotNull
+ protected JComponent createCustomComponent() {
+ return getStruts2GraphComponent();
+ }
+
+ @Override
+ @Nullable
+ public JComponent getPreferredFocusedComponent() {
+ return
getStruts2GraphComponent().getBuilder().getView().getJComponent();
+ }
+
+ @Override
+ public void commit() {
+ }
+
+ @Override
+ public void reset() {
+ // TODO: GraphBuilder.queueUpdate() is deprecated with no public
replacement.
+ getStruts2GraphComponent().getBuilder().queueUpdate();
+ }
+
+ @Override
+ @NotNull
+ public String getName() {
+ return "Graph";
+ }
+
+ @Override
+ public StructureViewBuilder getStructureViewBuilder() {
+ return myStructureViewBuilder.getValue();
+ }
+
+ private Struts2GraphComponent getStruts2GraphComponent() {
+ if (myComponent == null) {
+ myComponent = createGraphComponent();
+ Disposer.register(this, myComponent);
+ }
+ return myComponent;
}
- return myComponent;
- }
- /**
- * Creates graph component while showing modal wait dialog.
- *
- * @return new instance.
- */
- private Struts2GraphComponent createGraphComponent() {
- final Struts2GraphComponent[] graphComponent = {null};
- ProgressManager.getInstance().runProcessWithProgressSynchronously(
- (Runnable)() -> graphComponent[0] = ReadAction.compute(() -> new
Struts2GraphComponent(myXmlFile)), "Generating Graph", false,
myXmlFile.getProject());
+ /**
+ * Creates graph component while showing modal wait dialog.
+ *
+ * @return new instance.
+ */
+ private Struts2GraphComponent createGraphComponent() {
+ final Struts2GraphComponent[] graphComponent = {null};
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(
+ (Runnable) () -> graphComponent[0] = ReadAction.compute(() ->
new Struts2GraphComponent(myXmlFile)), "Generating Graph", false,
myXmlFile.getProject());
- return graphComponent[0];
- }
+ return graphComponent[0];
+ }
}
\ No newline at end of file
diff --git
a/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
b/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
index 0ed336e..7af9d1a 100644
---
a/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
+++
b/src/main/java/com/intellij/struts2/jsp/inspection/HardcodedActionUrlInspection.java
@@ -41,6 +41,7 @@ import com.intellij.xml.XmlNamespaceHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.net.URI;
import java.net.URL;
import java.util.Collections;
@@ -50,290 +51,285 @@ import java.util.Collections;
*/
public class HardcodedActionUrlInspection extends
XmlSuppressableInspectionTool {
- @NotNull
- @Override
- public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder,
boolean isOnTheFly) {
- final boolean isJspFileWithStrutsSupport =
- JspPsiUtil.getJspFile(holder.getFile()) != null &&
- StrutsFacet.getInstance(holder.getFile()) != null;
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder
holder, boolean isOnTheFly) {
+ final boolean isJspFileWithStrutsSupport =
+ JspPsiUtil.getJspFile(holder.getFile()) != null &&
+ StrutsFacet.getInstance(holder.getFile()) != null;
+
+ @Nullable final String actionExtension;
+ if (isJspFileWithStrutsSupport) {
+ actionExtension =
ContainerUtil.getFirstItem(StrutsConstantHelper.getActionExtensions(holder.getFile()));
+ } else {
+ actionExtension = null;
+ }
+
+ return new XmlElementVisitor() {
+
+ @Override
+ public void visitXmlAttributeValue(@NotNull XmlAttributeValue
value) {
+ if (!isJspFileWithStrutsSupport ||
+ actionExtension == null) {
+ return;
+ }
+
+ XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class);
+ if (tag == null) return;
+
+ URL parsedURL = parseURL(value, actionExtension);
+ if (parsedURL == null) return;
- @Nullable final String actionExtension;
- if (isJspFileWithStrutsSupport) {
- actionExtension =
ContainerUtil.getFirstItem(StrutsConstantHelper.getActionExtensions(holder.getFile()));
+ if (buildTag("", parsedURL, "", false, actionExtension) ==
null) return;
+
+ TextRange range = ElementManipulators.getValueTextRange(value);
+ holder.registerProblem(value, range, "Use Struts <url> tag
instead of hardcoded URL", new WrapWithSUrl(actionExtension));
+ }
+ };
}
- else {
- actionExtension = null;
+
+ @Override
+ public String @NotNull [] getGroupPath() {
+ return new
String[]{StrutsBundle.message("inspections.group.path.name"),
getGroupDisplayName()};
}
- return new XmlElementVisitor() {
- @Override
- public void visitXmlAttributeValue(@NotNull XmlAttributeValue value) {
- if (!isJspFileWithStrutsSupport ||
- actionExtension == null) {
- return;
- }
+ private static final class WrapWithSUrl implements LocalQuickFix {
- XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class);
- if (tag == null) return;
+ private final String myActionExtension;
- URL parsedURL = parseURL(value, actionExtension);
- if (parsedURL == null) return;
+ private WrapWithSUrl(String actionExtension) {
+ myActionExtension = actionExtension;
+ }
- if (buildTag("", parsedURL, "", false, actionExtension) == null)
return;
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Wrap with Struts <url> tag";
+ }
- TextRange range = ElementManipulators.getValueTextRange(value);
- holder.registerProblem(value, range, "Use Struts <url> tag instead of
hardcoded URL", new WrapWithSUrl(actionExtension));
- }
- };
- }
+ @Override
+ public void applyFix(@NotNull Project project, @NotNull
ProblemDescriptor descriptor) {
+ PsiElement element = descriptor.getPsiElement();
+ if (element instanceof XmlAttributeValue value) {
+ XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class,
false);
- @Override
- public String @NotNull [] getGroupPath() {
- return new String[]{StrutsBundle.message("inspections.group.path.name"),
getGroupDisplayName()};
- }
+ final boolean inline = tag instanceof HtmlTag;
+ final URL url = parseURL(value, myActionExtension);
+ if (url == null) {
+ return;
+ }
- private static final class WrapWithSUrl implements LocalQuickFix {
+ final JspFile jspFile = JspPsiUtil.getJspFile(value);
+ assert jspFile != null;
+
+ XmlTag rootTag = jspFile.getRootTag();
+ String prefix =
rootTag.getPrefixByNamespace(StrutsConstants.TAGLIB_STRUTS_UI_URI);
+
+ if (StringUtil.isEmpty(prefix)) {
+ prefix = "s"; // Use default Struts prefix
+
+ // Insert taglib declaration after existing taglibs or
comments
+ Document document =
PsiDocumentManager.getInstance(project).getDocument(jspFile);
+ if (document != null) {
+ String text = document.getText();
+ int insertionPoint = 0;
+
+ // Look for last existing taglib declaration
+ int lastTaglibEnd = -1;
+ int searchPos = 0;
+ while (true) {
+ int taglibStart = text.indexOf("<%@ taglib",
searchPos);
+ if (taglibStart == -1) break;
+
+ int taglibEnd = text.indexOf("%>", taglibStart);
+ if (taglibEnd != -1) {
+ lastTaglibEnd = taglibEnd + 2;
+ searchPos = lastTaglibEnd;
+ } else {
+ break;
+ }
+ }
+
+ if (lastTaglibEnd != -1) {
+ // Insert after last existing taglib
+ insertionPoint = lastTaglibEnd;
+ // Skip to end of line
+ while (insertionPoint < text.length() &&
text.charAt(insertionPoint) != '\n') {
+ insertionPoint++;
+ }
+ if (insertionPoint < text.length())
insertionPoint++; // Skip the newline
+ } else {
+ // No existing taglibs, insert after comment block
+ int commentEnd = text.indexOf("-->");
+ if (commentEnd != -1) {
+ insertionPoint = commentEnd + 3;
+ // Skip whitespace/newlines after comment
+ while (insertionPoint < text.length() &&
Character.isWhitespace(text.charAt(insertionPoint))) {
+ insertionPoint++;
+ }
+ }
+ }
+
+ String taglibDeclaration = "<%@ taglib prefix=\"" +
prefix + "\" uri=\"" + StrutsConstants.TAGLIB_STRUTS_UI_URI + "\" %>\n";
+ document.insertString(insertionPoint,
taglibDeclaration);
+
PsiDocumentManager.getInstance(project).commitDocument(document);
+ }
+
+ wrapValue(prefix, value, url, inline);
+ } else {
+ wrapValue(prefix, value, url, inline);
+ }
+ }
+ }
- private final String myActionExtension;
+ private void wrapValue(String prefix, XmlAttributeValue value, URL
url, boolean inline) {
+ final JspFile jspFile = JspPsiUtil.getJspFile(value);
+ assert jspFile != null;
- private WrapWithSUrl(String actionExtension) {
- myActionExtension = actionExtension;
- }
+ Project project = jspFile.getProject();
+ TextRange range = value.getValueTextRange();
+ Document document =
PsiDocumentManager.getInstance(project).getDocument(jspFile);
+ assert document != null;
+
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
- @NotNull
- @Override
- public String getFamilyName() {
- return "Wrap with Struts <url> tag";
- }
+ int start = range.getStartOffset();
+ int lineStart =
document.getLineStartOffset(document.getLineNumber(start));
+ String linePrefix =
document.getCharsSequence().subSequence(lineStart, start).toString();
+ linePrefix = linePrefix.substring(0, linePrefix.length() -
linePrefix.trim().length());
- @Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor
descriptor) {
- PsiElement element = descriptor.getPsiElement();
- if (element instanceof XmlAttributeValue value) {
- XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class, false);
+ String indent = linePrefix;
+ while (indent.length() < start - lineStart) indent += " ";
- final boolean inline = tag instanceof HtmlTag;
+ Pair<String, String> tag_var = buildTag(prefix, url, indent,
inline, myActionExtension);
+ String tag = tag_var.getFirst();
+ String var = tag_var.getSecond();
- final URL url = parseURL(value, myActionExtension);
- if (url == null) {
- return;
- }
+ int end = range.getEndOffset();
- final JspFile jspFile = JspPsiUtil.getJspFile(value);
- assert jspFile != null;
-
- XmlTag rootTag = jspFile.getRootTag();
- String prefix =
rootTag.getPrefixByNamespace(StrutsConstants.TAGLIB_STRUTS_UI_URI);
-
- if (StringUtil.isEmpty(prefix)) {
- prefix = "s"; // Use default Struts prefix
-
- // Insert taglib declaration after existing taglibs or comments
- Document document =
PsiDocumentManager.getInstance(project).getDocument(jspFile);
- if (document != null) {
- String text = document.getText();
- int insertionPoint = 0;
-
- // Look for last existing taglib declaration
- int lastTaglibEnd = -1;
- int searchPos = 0;
- while (true) {
- int taglibStart = text.indexOf("<%@ taglib", searchPos);
- if (taglibStart == -1) break;
-
- int taglibEnd = text.indexOf("%>", taglibStart);
- if (taglibEnd != -1) {
- lastTaglibEnd = taglibEnd + 2;
- searchPos = lastTaglibEnd;
- } else {
- break;
- }
- }
-
- if (lastTaglibEnd != -1) {
- // Insert after last existing taglib
- insertionPoint = lastTaglibEnd;
- // Skip to end of line
- while (insertionPoint < text.length() &&
text.charAt(insertionPoint) != '\n') {
- insertionPoint++;
- }
- if (insertionPoint < text.length()) insertionPoint++; // Skip
the newline
+ int formattingStart;
+ int formattingEnd;
+
+ if (inline) {
+ document.replaceString(start, end, tag);
+ formattingStart = start;
+ formattingEnd = start + tag.length();
} else {
- // No existing taglibs, insert after comment block
- int commentEnd = text.indexOf("-->");
- if (commentEnd != -1) {
- insertionPoint = commentEnd + 3;
- // Skip whitespace/newlines after comment
- while (insertionPoint < text.length() &&
Character.isWhitespace(text.charAt(insertionPoint))) {
- insertionPoint++;
- }
- }
+ document.replaceString(start, end, "${" + var + "}");
+ XmlTag containingTag = PsiTreeUtil.getParentOfType(value,
XmlTag.class, false);
+ assert containingTag != null;
+ int startOffset =
containingTag.getTextRange().getStartOffset();
+ document.insertString(startOffset, "\n");
+ document.insertString(startOffset, tag);
+
+ formattingStart = startOffset;
+ formattingEnd = startOffset + tag.length() + 2;
}
-
- String taglibDeclaration = "<%@ taglib prefix=\"" + prefix + "\"
uri=\"" + StrutsConstants.TAGLIB_STRUTS_UI_URI + "\" %>\n";
- document.insertString(insertionPoint, taglibDeclaration);
+
PsiDocumentManager.getInstance(project).commitDocument(document);
- }
-
- wrapValue(prefix, value, url, inline);
- }
- else {
- wrapValue(prefix, value, url, inline);
- }
- }
- }
- private void wrapValue(String prefix, XmlAttributeValue value, URL url,
boolean inline) {
- final JspFile jspFile = JspPsiUtil.getJspFile(value);
- assert jspFile != null;
-
- Project project = jspFile.getProject();
- TextRange range = value.getValueTextRange();
- Document document =
PsiDocumentManager.getInstance(project).getDocument(jspFile);
- assert document != null;
-
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
-
- int start = range.getStartOffset();
- int lineStart =
document.getLineStartOffset(document.getLineNumber(start));
- String linePrefix = document.getCharsSequence().subSequence(lineStart,
start).toString();
- linePrefix = linePrefix.substring(0, linePrefix.length() -
linePrefix.trim().length());
-
- String indent = linePrefix;
- while (indent.length() < start - lineStart) indent += " ";
-
- Pair<String, String> tag_var = buildTag(prefix, url, indent, inline,
myActionExtension);
- String tag = tag_var.getFirst();
- String var = tag_var.getSecond();
-
- int end = range.getEndOffset();
-
- int formattingStart;
- int formattingEnd;
-
- if (inline) {
- document.replaceString(start, end, tag);
- formattingStart = start;
- formattingEnd = start + tag.length();
- }
- else {
- document.replaceString(start, end, "${" + var + "}");
- XmlTag containingTag = PsiTreeUtil.getParentOfType(value,
XmlTag.class, false);
- assert containingTag != null;
- int startOffset = containingTag.getTextRange().getStartOffset();
- document.insertString(startOffset, "\n");
- document.insertString(startOffset, tag);
-
- formattingStart = startOffset;
- formattingEnd = startOffset + tag.length() + 2;
- }
-
- PsiDocumentManager.getInstance(project).commitDocument(document);
-
- CodeStyleManager.getInstance(project).reformatText(jspFile,
formattingStart, formattingEnd);
+ CodeStyleManager.getInstance(project).reformatText(jspFile,
formattingStart, formattingEnd);
+ }
}
- }
- private static Pair<String, String> buildTag(String prefix, URL url, String
indent, boolean inline, String actionExtension) {
- String path = url.getPath();
- int slash = path.lastIndexOf('/');
- String namespace = slash > 0 ? path.substring(0, slash) : null;
- String action = slash != -1 ? path.substring(slash + 1) : path;
+ private static Pair<String, String> buildTag(String prefix, URL url,
String indent, boolean inline, String actionExtension) {
+ String path = url.getPath();
+ int slash = path.lastIndexOf('/');
+ String namespace = slash > 0 ? path.substring(0, slash) : null;
+ String action = slash != -1 ? path.substring(slash + 1) : path;
- action = StringUtil.trimEnd(action, actionExtension);
+ action = StringUtil.trimEnd(action, actionExtension);
- int exclamationIdx = action.indexOf('!');
- String method = null;
- if (exclamationIdx > 0) {
- method = action.substring(exclamationIdx + 1);
- action = action.substring(0, exclamationIdx);
- }
+ int exclamationIdx = action.indexOf('!');
+ String method = null;
+ if (exclamationIdx > 0) {
+ method = action.substring(exclamationIdx + 1);
+ action = action.substring(0, exclamationIdx);
+ }
- StringBuilder sb = new StringBuilder();
- sb.append('<').append(prefix).append(":url");
+ StringBuilder sb = new StringBuilder();
+ sb.append('<').append(prefix).append(":url");
- String var;
- if (inline) {
- var = null;
- }
- else {
- var = action + "_url";
- sb.append(" var=\"").append(var).append("\"");
- }
+ String var;
+ if (inline) {
+ var = null;
+ } else {
+ var = action + "_url";
+ sb.append(" var=\"").append(var).append("\"");
+ }
- if (namespace != null) {
- sb.append(" namespace=\"").append(namespace).append("\"");
- }
+ if (namespace != null) {
+ sb.append(" namespace=\"").append(namespace).append("\"");
+ }
- sb.append(" action=\"").append(action).append("\"");
- if (method != null) {
- sb.append(" method=\"").append(method).append("\"");
- }
+ sb.append(" action=\"").append(action).append("\"");
+ if (method != null) {
+ sb.append(" method=\"").append(method).append("\"");
+ }
- String query = url.getQuery();
- if (StringUtil.isEmpty(query)) {
- sb.append("/>");
- }
- else {
- sb.append(">");
-
- for (String escapedArg : StringUtil.split(query, "&")) {
- for (String arg : StringUtil.split(escapedArg, "&")) {
- int eq = arg.indexOf('=');
- String name = eq > 0 ? arg.substring(0, eq) : arg;
- String value = eq > 0 ? arg.substring(eq + 1) : "";
-
- if (name.contains("[") || name.contains("$")) return null; // This
will not work if arg name is actually an expression
-
- sb.append("\n").append(indent).append(" <")
- .append(prefix)
- .append(":param name=\"")
- .append(name).append("\">")
- .append(value)
- .append("</")
- .append(prefix)
- .append(":param>");
+ String query = url.getQuery();
+ if (StringUtil.isEmpty(query)) {
+ sb.append("/>");
+ } else {
+ sb.append(">");
+
+ for (String escapedArg : StringUtil.split(query, "&")) {
+ for (String arg : StringUtil.split(escapedArg, "&")) {
+ int eq = arg.indexOf('=');
+ String name = eq > 0 ? arg.substring(0, eq) : arg;
+ String value = eq > 0 ? arg.substring(eq + 1) : "";
+
+ if (name.contains("[") || name.contains("$"))
+ return null; // This will not work if arg name is
actually an expression
+
+ sb.append("\n").append(indent).append(" <")
+ .append(prefix)
+ .append(":param name=\"")
+ .append(name).append("\">")
+ .append(value)
+ .append("</")
+ .append(prefix)
+ .append(":param>");
+ }
+ }
+ sb.append('\n').append(indent);
+ sb.append("</").append(prefix).append(":url>");
}
- }
- sb.append('\n').append(indent);
- sb.append("</").append(prefix).append(":url>");
+
+ return Pair.create(sb.toString(), var);
}
- return Pair.create(sb.toString(), var);
- }
+ @Nullable
+ private static URL parseURL(XmlAttributeValue value, String
actionExtension) {
+ String rawUrl = value.getValue();
+ if (rawUrl.startsWith("http://") ||
+ rawUrl.startsWith("https://")) {
+ return null;
+ }
- @Nullable
- private static URL parseURL(XmlAttributeValue value, String actionExtension)
{
- String rawUrl = value.getValue();
- if (rawUrl.startsWith("http://") ||
- rawUrl.startsWith("https://")) {
- return null;
- }
+ URL parsedURL;
+ try {
+ parsedURL = URI.create("http://" + rawUrl).toURL();
+ } catch (Exception e) {
+ return null;
+ }
- URL parsedURL;
- try {
- parsedURL = new URL("http://" + rawUrl);
- }
- catch (Exception e) {
- return null;
- }
+ String host = parsedURL.getHost();
+ if (!StringUtil.isEmpty(host) &&
+ !(host.startsWith("${") && host.endsWith("}"))) {
+ return null;
+ }
- String host = parsedURL.getHost();
- if (!StringUtil.isEmpty(host) &&
- !(host.startsWith("${") && host.endsWith("}"))) {
- return null;
- }
+ String path = parsedURL.getPath();
+ if (!path.endsWith(actionExtension)) {
+ return null;
+ }
- String path = parsedURL.getPath();
- if (!path.endsWith(actionExtension)) {
- return null;
- }
+ if (path.contains("${")) {
+ return null; // Dynamic action paths cannot be converted.
+ }
- if (path.contains("${")) {
- return null; // Dynamic action paths cannot be converted.
+ return parsedURL;
}
-
- return parsedURL;
- }
}
diff --git
a/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
b/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
index 8ab013d..16b6aee 100644
---
a/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
+++
b/src/main/java/com/intellij/struts2/model/constant/contributor/ConstantValueClassConverter.java
@@ -40,81 +40,83 @@ import java.util.Set;
*/
class ConstantValueClassConverter extends ResolvingConverter<PsiClass>
implements CustomReferenceConverter {
- private final JavaClassReferenceProvider javaClassReferenceProvider = new
JavaClassReferenceProvider();
-
- private final Map<String, String> shortCutToPsiClassMap;
- private final boolean hasShortCuts;
-
- ConstantValueClassConverter(@NonNls @NotNull String baseClass,
- final Map<String, String> shortCutToPsiClassMap)
{
- this.shortCutToPsiClassMap = shortCutToPsiClassMap;
- this.hasShortCuts = !shortCutToPsiClassMap.isEmpty();
-
- javaClassReferenceProvider.setSoft(true);
- javaClassReferenceProvider.setAllowEmpty(false);
- javaClassReferenceProvider.setOption(JavaClassReferenceProvider.CONCRETE,
Boolean.TRUE);
-
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.NOT_INTERFACE,
Boolean.TRUE);
-
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.EXTEND_CLASS_NAMES,
new String[]{baseClass});
- }
-
- @NotNull
- @Override
- public Collection<? extends PsiClass> getVariants(ConvertContext context) {
- return Collections.emptyList();
- }
-
- @Override
- public PsiClass fromString(@Nullable @NonNls final String s, final
ConvertContext convertContext) {
- if (s == null) {
- return null;
+ private final JavaClassReferenceProvider javaClassReferenceProvider = new
JavaClassReferenceProvider();
+
+ private final Map<String, String> shortCutToPsiClassMap;
+ private final boolean hasShortCuts;
+
+ ConstantValueClassConverter(@NonNls @NotNull String baseClass,
+ final Map<String, String>
shortCutToPsiClassMap) {
+ this.shortCutToPsiClassMap = shortCutToPsiClassMap;
+ this.hasShortCuts = !shortCutToPsiClassMap.isEmpty();
+
+ javaClassReferenceProvider.setSoft(true);
+ javaClassReferenceProvider.setAllowEmpty(false);
+
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.CONCRETE,
Boolean.TRUE);
+
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.NOT_INTERFACE,
Boolean.TRUE);
+ // TODO: EXTEND_CLASS_NAMES is deprecated but no replacement is
documented.
+ //noinspection deprecation
+
javaClassReferenceProvider.setOption(JavaClassReferenceProvider.EXTEND_CLASS_NAMES,
new String[]{baseClass});
}
- // 1. via shortcut
- if (hasShortCuts) {
- final String shortCutClassName = shortCutToPsiClassMap.get(s);
+ @NotNull
+ @Override
+ public Collection<? extends PsiClass> getVariants(ConvertContext context) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public PsiClass fromString(@Nullable @NonNls final String s, final
ConvertContext convertContext) {
+ if (s == null) {
+ return null;
+ }
+
+ // 1. via shortcut
+ if (hasShortCuts) {
+ final String shortCutClassName = shortCutToPsiClassMap.get(s);
+
+ if (StringUtil.isNotEmpty(shortCutClassName)) {
+ return DomJavaUtil.findClass(shortCutClassName,
convertContext.getInvocationElement());
+ }
+ }
+
+ // 2. first non-null result from extension point contributor
(currently only Spring)
+ for (final ConstantValueConverterClassContributor
converterClassContributor :
+
ConstantValueConverterClassContributor.EP_NAME.getExtensionList()) {
+ final PsiClass contributorClass =
converterClassContributor.fromString(s, convertContext);
+ if (contributorClass != null) {
+ return contributorClass;
+ }
+ }
+
+ // 3. via JAVA-class
+ final PsiClass psiClass = DomJavaUtil.findClass(s,
convertContext.getInvocationElement());
+ if (psiClass == null) {
+ return null;
+ }
+ return !psiClass.isInterface() &&
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) ? psiClass : null;
+ }
+
+ @Override
+ public String toString(@Nullable PsiClass aClass, ConvertContext context) {
+ return aClass == null ? null : aClass.getName();
+ }
- if (StringUtil.isNotEmpty(shortCutClassName)) {
- return DomJavaUtil.findClass(shortCutClassName,
convertContext.getInvocationElement());
- }
+ @Override
+ @NotNull
+ public Set<String> getAdditionalVariants(@NotNull final ConvertContext
context) {
+ return shortCutToPsiClassMap.keySet();
}
- // 2. first non-null result from extension point contributor (currently
only Spring)
- for (final ConstantValueConverterClassContributor
converterClassContributor :
- ConstantValueConverterClassContributor.EP_NAME.getExtensionList()) {
- final PsiClass contributorClass =
converterClassContributor.fromString(s, convertContext);
- if (contributorClass != null) {
- return contributorClass;
- }
+ @Override
+ public PsiReference @NotNull [] createReferences(GenericDomValue value,
PsiElement element, ConvertContext context) {
+ final PsiReference[] references =
javaClassReferenceProvider.getReferencesByElement(element);
+ //noinspection unchecked
+ return ArrayUtil.append(references, new
GenericDomValueReference(value), PsiReference.ARRAY_FACTORY);
}
- // 3. via JAVA-class
- final PsiClass psiClass = DomJavaUtil.findClass(s,
convertContext.getInvocationElement());
- if (psiClass == null) {
- return null;
+ @Override
+ public String getErrorMessage(@Nullable final String s, final
ConvertContext context) {
+ return CodeInsightBundle.message("error.cannot.resolve.class", s);
}
- return !psiClass.isInterface() &&
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) ? psiClass : null;
- }
-
- @Override
- public String toString(@Nullable PsiClass aClass, ConvertContext context) {
- return aClass == null ? null : aClass.getName();
- }
-
- @Override
- @NotNull
- public Set<String> getAdditionalVariants(@NotNull final ConvertContext
context) {
- return shortCutToPsiClassMap.keySet();
- }
-
- @Override
- public PsiReference @NotNull [] createReferences(GenericDomValue value,
PsiElement element, ConvertContext context) {
- final PsiReference[] references =
javaClassReferenceProvider.getReferencesByElement(element);
- //noinspection unchecked
- return ArrayUtil.append(references, new GenericDomValueReference(value),
PsiReference.ARRAY_FACTORY);
- }
-
- @Override
- public String getErrorMessage(@Nullable final String s, final ConvertContext
context) {
- return CodeInsightBundle.message("error.cannot.resolve.class", s);
- }
}
diff --git
a/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
b/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
index 8b9c5eb..0491431 100644
---
a/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
+++
b/src/main/java/com/intellij/struts2/velocity/Struts2GlobalMacroProvider.java
@@ -16,7 +16,9 @@ package com.intellij.struts2.velocity;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.velocity.VtlGlobalMacroProvider;
@@ -34,27 +36,28 @@ import java.util.Collections;
* @author Yann Cébron
*/
final class Struts2GlobalMacroProvider extends VtlGlobalMacroProvider {
- @NonNls
- private static final String STRUTS_MACROS_FILENAME = "struts.vm";
+ @NonNls
+ private static final String STRUTS_MACROS_FILENAME = "struts.vm";
- @NotNull
- @Override
- public Collection<VtlMacro> getGlobalMacros(@NotNull final VtlFile vtlFile) {
- final Module module = ModuleUtilCore.findModuleForPsiElement(vtlFile);
- if (module == null) {
- return Collections.emptySet();
- }
+ @NotNull
+ @Override
+ public Collection<VtlMacro> getGlobalMacros(@NotNull final VtlFile
vtlFile) {
+ final Module module = ModuleUtilCore.findModuleForPsiElement(vtlFile);
+ if (module == null) {
+ return Collections.emptySet();
+ }
- final PsiFile[] filesByName =
FilenameIndex.getFilesByName(vtlFile.getProject(),
-
STRUTS_MACROS_FILENAME,
-
GlobalSearchScope.moduleRuntimeScope(module, false));
- if (filesByName.length == 1) {
- final PsiFile psiFile = filesByName[0];
- if (psiFile instanceof VtlFile) {
- return ((VtlFile) psiFile).getDefinedMacros();
- }
- }
+ final Collection<VirtualFile> virtualFiles =
FilenameIndex.getVirtualFilesByName(
+ STRUTS_MACROS_FILENAME,
+ GlobalSearchScope.moduleRuntimeScope(module, false));
+ if (virtualFiles.size() == 1) {
+ final VirtualFile virtualFile = virtualFiles.iterator().next();
+ final PsiFile psiFile =
PsiManager.getInstance(vtlFile.getProject()).findFile(virtualFile);
+ if (psiFile instanceof VtlFile) {
+ return ((VtlFile) psiFile).getDefinedMacros();
+ }
+ }
- return Collections.emptySet();
- }
+ return Collections.emptySet();
+ }
}
\ No newline at end of file