Skip to content

fix(gradle): replace internal IElementType.getDebugName() with direct type equality#254

Merged
ruromero merged 3 commits into
redhat-developer:mainfrom
ruromero:TC-4167
Apr 20, 2026
Merged

fix(gradle): replace internal IElementType.getDebugName() with direct type equality#254
ruromero merged 3 commits into
redhat-developer:mainfrom
ruromero:TC-4167

Conversation

@ruromero

@ruromero ruromero commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replace IElementType.getDebugName() internal API call with direct == type identity comparison in GradleCAUpdateManifestIntentionAction
  • IElementType instances are singletons, so direct equality is both correct and idiomatic

Implements TC-4167

Test plan

  • ./gradlew compileJava passes
  • ./gradlew test — all existing tests pass
  • ./gradlew runPluginVerifier — no internal API warning for IElementType.getDebugName
  • Manual: open a build.gradle file, trigger update manifest intention action, confirm it works

🤖 Generated with Claude Code

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Add pyproject.toml support for Python dependency analysis with PEP 621 and Poetry formats

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add pyproject.toml support for Python dependency analysis
  - Parses PEP 621 [project.dependencies] and [project.optional-dependencies]
  - Parses Poetry [tool.poetry.dependencies] format with inline tables
  - Extracts PEP 508 package names, versions, extras, and environment markers
• Register PyprojectCAAnnotator and PyprojectCAInspection in plugin.xml
• Update package manager detection and API settings for pyproject.toml
• Fix Cargo.toml file validation with early return check
• Replace internal IElementType.getDebugName() with direct type equality
• Update documentation with pyproject.toml examples and ignore syntax
Diagram
flowchart LR
  A["pyproject.toml file"] -->|parsed by| B["PyprojectCAAnnotator"]
  B -->|extracts dependencies| C["PEP 621<br/>Poetry<br/>Optional deps"]
  C -->|creates| D["Dependency objects"]
  D -->|triggers| E["PyprojectCAInspection"]
  E -->|shows violations| F["PyprojectCAIntentionAction"]
  F -->|updates versions| A
  G["ApiService"] -->|applies Python settings| H["pyproject.toml analysis"]
Loading

Grey Divider

File Changes

1. src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/PyprojectCAAnnotator.java ✨ Enhancement +399/-0

New annotator for pyproject.toml dependency analysis

src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/PyprojectCAAnnotator.java


2. src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/PyprojectCAInspection.java ✨ Enhancement +39/-0

New inspection for pyproject.toml vulnerabilities

src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/PyprojectCAInspection.java


3. src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/PyprojectCAIntentionAction.java ✨ Enhancement +117/-0

New quick-fix for pyproject.toml version updates

src/main/java/org/jboss/tools/intellij/componentanalysis/pypi/PyprojectCAIntentionAction.java


View more (9)
4. src/main/java/org/jboss/tools/intellij/componentanalysis/CAAnnotator.java ✨ Enhancement +1/-1

Add pyproject.toml to package manager detection

src/main/java/org/jboss/tools/intellij/componentanalysis/CAAnnotator.java


5. src/main/java/org/jboss/tools/intellij/componentanalysis/SAIntentionAction.java ✨ Enhancement +2/-1

Add pyproject.toml to intention action availability

src/main/java/org/jboss/tools/intellij/componentanalysis/SAIntentionAction.java


6. src/main/java/org/jboss/tools/intellij/componentanalysis/cargo/CargoCAAnnotator.java 🐞 Bug fix +5/-1

Add file validation check for Cargo.toml

src/main/java/org/jboss/tools/intellij/componentanalysis/cargo/CargoCAAnnotator.java


7. src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java 🐞 Bug fix +1/-1

Replace getDebugName() with direct type equality

src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java


8. src/main/java/org/jboss/tools/intellij/exhort/ApiService.java ✨ Enhancement +3/-3

Apply Python settings for pyproject.toml analysis

src/main/java/org/jboss/tools/intellij/exhort/ApiService.java


9. src/main/java/org/jboss/tools/intellij/stackanalysis/SaAction.java ✨ Enhancement +2/-1

Add pyproject.toml to supported manifest files

src/main/java/org/jboss/tools/intellij/stackanalysis/SaAction.java


10. src/main/java/org/jboss/tools/intellij/stackanalysis/SaUtils.java ✨ Enhancement +3/-2

Add pyproject.toml to package manager determination

src/main/java/org/jboss/tools/intellij/stackanalysis/SaUtils.java


11. src/main/resources/META-INF/plugin.xml ⚙️ Configuration changes +9/-0

Register pyproject.toml annotator and inspection

src/main/resources/META-INF/plugin.xml


12. README.md 📝 Documentation +21/-2

Document pyproject.toml support and ignore syntax

README.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Apr 20, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Gradle repositories lookup throws 🐞 Bug ☼ Reliability
Description
GradleCAUpdateManifestIntentionAction.getRepositoriesFromBuildGradle() uses findFirst().get(), so if
no REPOSITORIES leaf is produced it throws NoSuchElementException; isAvailable() calls it unguarded,
so simply querying intentions can crash for such build.gradle files.
Code

src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java[R47-50]

    private static @NotNull PsiElement getRepositoriesFromBuildGradle(PsiFile file) {
        PsiElement repositories = Arrays.stream(file.getChildren()).filter(psi -> psi instanceof LeafPsiElement)
-                .filter(psi -> ((LeafPsiElement) psi).getElementType().getDebugName().equals(BuildGradleTypes.REPOSITORIES.getDebugName())).findFirst().get();
+                .filter(psi -> ((LeafPsiElement) psi).getElementType() == BuildGradleTypes.REPOSITORIES).findFirst().get();
        return repositories;
Evidence
The intention’s repositories lookup is an unconditional Optional.get(), and isAvailable() invokes
it. The REPOSITORIES token is produced by a lexer regex; if the repositories block is absent or
doesn’t match the regex, the token won’t exist and the Optional will be empty, triggering
NoSuchElementException.

src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java[47-51]
src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java[57-63]
src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/build/buildGradle.flex[54-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`GradleCAUpdateManifestIntentionAction#getRepositoriesFromBuildGradle` calls `findFirst().get()` which can throw `NoSuchElementException` when the lexer/parser does not produce a `REPOSITORIES` token (e.g., the file has no repositories block or the block does not match the lexer regex). This also impacts `isAvailable()` because it calls `getRepositoriesFromBuildGradle(file)` unguarded.

### Issue Context
This intention is queried frequently by the IDE; throwing from `isAvailable()` degrades stability.

### Fix Focus Areas
- src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java[47-63]
- src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/build/buildGradle.flex[54-62]

### What to change
- Make `getRepositoriesFromBuildGradle` return `@Nullable PsiElement` or `Optional<PsiElement>`.
- In `isAvailable()`, return `false` when repositories cannot be found.
- In `updateManifest()`, either:
 - create/insert a new `repositories { ... }` block when missing, or
 - fail gracefully (no-op) with a clear user-facing message (avoid throwing).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. pyproject exclusion unavailable 🐞 Bug ⚙ Maintainability
Description
pyproject.toml is now treated as a supported manifest for analysis/actions, but the
manifest-exclusion intention is not available for pyproject.toml, so users can’t exclude it via the
same UI flow available for other supported manifests.
Code

src/main/java/org/jboss/tools/intellij/componentanalysis/SAIntentionAction.java[R49-53]

                || "requirements.txt".equals(file.getName())
                || "build.gradle".equals(file.getName())
                || "build.gradle.kts".equals(file.getName())
-                || "Cargo.toml".equals(file.getName());
+                || "Cargo.toml".equals(file.getName())
+                || "pyproject.toml".equals(file.getName());
Evidence
The PR adds pyproject.toml to supported-manifest checks and registers pyproject
inspections/annotators, but ExcludeManifestIntentionAction’s allowlist omits pyproject.toml,
preventing the exclusion intention from appearing on pyproject files.

src/main/java/org/jboss/tools/intellij/componentanalysis/SAIntentionAction.java[46-54]
src/main/resources/META-INF/plugin.xml[578-585]
src/main/java/org/jboss/tools/intellij/componentanalysis/ExcludeManifestIntentionAction.java[46-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`pyproject.toml` is now supported (inspection/annotator and other actions include it), but `ExcludeManifestIntentionAction#isAvailable` does not include `pyproject.toml`. This makes the exclusion intention inconsistent across supported manifest types.

### Issue Context
Users can exclude other manifests (pom.xml, package.json, requirements.txt, Cargo.toml, etc.) via the same intention action; pyproject.toml should behave similarly now that it is supported.

### Fix Focus Areas
- src/main/java/org/jboss/tools/intellij/componentanalysis/ExcludeManifestIntentionAction.java[46-54]
- src/main/java/org/jboss/tools/intellij/componentanalysis/SAIntentionAction.java[46-54]
- src/main/resources/META-INF/plugin.xml[578-585]

### What to change
- Extend the filename allowlist in `ExcludeManifestIntentionAction#isAvailable` to include `pyproject.toml`.
- (Optional) centralize supported-manifest names in a shared constant/helper to avoid future drift between actions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 47 to 50
private static @NotNull PsiElement getRepositoriesFromBuildGradle(PsiFile file) {
PsiElement repositories = Arrays.stream(file.getChildren()).filter(psi -> psi instanceof LeafPsiElement)
.filter(psi -> ((LeafPsiElement) psi).getElementType().getDebugName().equals(BuildGradleTypes.REPOSITORIES.getDebugName())).findFirst().get();
.filter(psi -> ((LeafPsiElement) psi).getElementType() == BuildGradleTypes.REPOSITORIES).findFirst().get();
return repositories;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Gradle repositories lookup throws 🐞 Bug ☼ Reliability

GradleCAUpdateManifestIntentionAction.getRepositoriesFromBuildGradle() uses findFirst().get(), so if
no REPOSITORIES leaf is produced it throws NoSuchElementException; isAvailable() calls it unguarded,
so simply querying intentions can crash for such build.gradle files.
Agent Prompt
### Issue description
`GradleCAUpdateManifestIntentionAction#getRepositoriesFromBuildGradle` calls `findFirst().get()` which can throw `NoSuchElementException` when the lexer/parser does not produce a `REPOSITORIES` token (e.g., the file has no repositories block or the block does not match the lexer regex). This also impacts `isAvailable()` because it calls `getRepositoriesFromBuildGradle(file)` unguarded.

### Issue Context
This intention is queried frequently by the IDE; throwing from `isAvailable()` degrades stability.

### Fix Focus Areas
- src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/GradleCAUpdateManifestIntentionAction.java[47-63]
- src/main/java/org/jboss/tools/intellij/componentanalysis/gradle/build/buildGradle.flex[54-62]

### What to change
- Make `getRepositoriesFromBuildGradle` return `@Nullable PsiElement` or `Optional<PsiElement>`.
- In `isAvailable()`, return `false` when repositories cannot be found.
- In `updateManifest()`, either:
  - create/insert a new `repositories { ... }` block when missing, or
  - fail gracefully (no-op) with a clear user-facing message (avoid throwing).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

… type equality

Use direct == comparison on IElementType singleton instances instead of
comparing debug name strings via the internal getDebugName() API.

Implements TC-4167

Assisted-by: Claude Code
Configure pluginVerification to treat INTERNAL_API_USAGES as a build
failure, preventing future internal API regressions from passing CI.

Implements TC-4167

Assisted-by: Claude Code
Return null instead of throwing NoSuchElementException when the
repositories block is not found, preventing IDE crashes when querying
intentions for build.gradle files without a repositories block.

Implements TC-4167

Assisted-by: Claude Code
@sonarqubecloud

Copy link
Copy Markdown

@ruromero
ruromero merged commit f740e17 into redhat-developer:main Apr 20, 2026
9 of 10 checks passed
@ruromero
ruromero deleted the TC-4167 branch April 20, 2026 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant