🍒 🐛 Try to fit annotations into on-demand imports for member che…#209
🍒 🐛 Try to fit annotations into on-demand imports for member che…#209jmle merged 1 commit intokonveyor:release-0.9from
Conversation
…cking (konveyor#208) * Try to fit annotations into on-demand imports for member checking Signed-off-by: Juan Manuel Leflet Estrada <jleflete@redhat.com> * Remove unneeded document Signed-off-by: Juan Manuel Leflet Estrada <jleflete@redhat.com> * Address automatic PR review comments Signed-off-by: Juan Manuel Leflet Estrada <jleflete@redhat.com> --------- Signed-off-by: Juan Manuel Leflet Estrada <jleflete@redhat.com>
📝 WalkthroughWalkthroughThe refactoring replaces single fully-qualified name resolution in annotation queries with a candidate-based approach. The implementation now iterates over multiple FQN candidates per annotation, adds support for nested annotations and varied member-value scenarios, and expands import-collection logic. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
If this is a cherry-pick, should we be release-0.9? |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java`:
- Around line 190-199: The getFQNCandidates(IAnnotation) method currently
returns no candidates when an annotation name is unqualified and not imported;
update getFQNCandidates to append implicit-scope fallback candidates by adding
the annotation name qualified with the annotation's enclosing package and with
"java.lang" (i.e., current package + "." + name and "java.lang." + name) before
returning; use tryToGetImports(annotation) and the annotation's owning
ICompilationUnit or type to determine the current package, and ensure these
fallbacks are only added when imports did not yield matches and the name
contains no dot (unqualified).
- Around line 51-55: In WithAnnotationQuery, the loop that iterates
getFQNCandidates(annotation) should not return doElementsMatch(...) directly
because a false result may hide later valid candidates; change the logic in the
block that calls getAnnotationQuery().matchesAnnotation(fqn) so that you call
doElementsMatch((Annotation) annotation) and if it returns true return true,
otherwise continue checking remaining fqn candidates and remaining annotations,
and only return false after all candidates/annotations are exhausted; apply the
same fix pattern to the other similar blocks (the ones around the occurrences
currently at lines 64-66 and 72-74) so each match only short-circuits on a true
result.
- Around line 203-206: The current filter uses endsWith(name) and can match
suffixes incorrectly; change the import matching in WithAnnotationQuery so it
only considers single-type imports (skip on-demand imports like "pkg.*") and
compares the simple name exactly: for each IImportDeclaration use its
getElementName(), ignore names that end with ".*", compute the simple name as
the substring after the last '.' (or the whole string if no dot) and require
simpleName.equals(name) before mapping to getElementName() and adding to
candidates.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java
...r-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java
Show resolved
Hide resolved
...r-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java
Show resolved
Hide resolved
...r-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java
Show resolved
Hide resolved
There was a problem hiding this comment.
super silly question but could I import xxx.yy.zzz.* that as ccc.AAA annotation and just reference it as (@ccc.AAA)?
If that makes no sense I get it, just wondering if that is a usecase that the java language supports that we have to handle.
There was a problem hiding this comment.
Sorry mate I don't understand, do you mean using something like an as keyword? That doesn't exist in Java, but you can import a.b.c.D; and then also use @a.b.c.D in the code (although it wouldn't make much sense)
shawn-hurley
left a comment
There was a problem hiding this comment.
Just wondering about an edge case, generally I think this is better behavior.
Is there any way to add a test for this in the integration tests?
Yep totally |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java (1)
190-220:⚠️ Potential issue | 🟠 MajorAdd implicit-scope FQN fallbacks for unqualified annotation names.
When an annotation is unqualified and imports don’t resolve it, this returns no candidates; valid annotations from the current package or
java.lang(e.g.,@Deprecated) are missed.Suggested fix
import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IImportDeclaration;// On-demand: one candidate per pkg.* for (IImportDeclaration imp : imports) { String elementName = imp.getElementName(); if (elementName != null && elementName.endsWith(".*")) { String prefix = elementName.substring(0, elementName.length() - 2); if (!prefix.isEmpty()) { candidates.add(prefix + "." + name); } } } + // Implicit scope fallback for unqualified names + if (candidates.isEmpty()) { + IJavaElement pkg = annotation.getAncestor(IJavaElement.PACKAGE_FRAGMENT); + if (pkg != null && pkg.getElementName() != null && !pkg.getElementName().isEmpty()) { + candidates.add(pkg.getElementName() + "." + name); + } + candidates.add("java.lang." + name); + } return candidates; }#!/bin/bash set -euo pipefail FILE="java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java" echo "Inspect getFQNCandidates for implicit fallback handling:" rg -n -C4 'getFQNCandidates|java\.lang|PACKAGE_FRAGMENT|getAncestor\(' "$FILE"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java` around lines 190 - 220, getFQNCandidates currently only considers explicit imports and on-demand imports, so unqualified annotation names from the current package or java.lang are missed; update getFQNCandidates (which receives IAnnotation and calls tryToGetImports) to, after processing imports and on-demand imports, add fallback candidates for the enclosing package and for java.lang by resolving the annotation's compilation unit or parent type to obtain its package (use the same ancestor lookup you use elsewhere) and then add package + "." + name and "java.lang." + name when not already present in candidates.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java`:
- Around line 52-53: The code is performing unsafe casts to the internal
org.eclipse.jdt.internal.core.Annotation; change the doElementsMatch(Annotation)
signature in WithAnnotationQuery to doElementsMatch(IAnnotation) (use
org.eclipse.jdt.core.IAnnotation), update all callers (where
getAnnotationQuery().matchesAnnotation(fqn) && doElementsMatch((Annotation)
annotation) and the other two similar sites) to pass the annotation variable as
an IAnnotation (remove casts) and replace any instanceof Annotation checks with
instanceof IAnnotation; update imports to use IAnnotation and adjust any
internal-Annotation-specific method calls to the public IAnnotation API so no
internal classes are referenced or cast.
---
Duplicate comments:
In
`@java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java`:
- Around line 190-220: getFQNCandidates currently only considers explicit
imports and on-demand imports, so unqualified annotation names from the current
package or java.lang are missed; update getFQNCandidates (which receives
IAnnotation and calls tryToGetImports) to, after processing imports and
on-demand imports, add fallback candidates for the enclosing package and for
java.lang by resolving the annotation's compilation unit or parent type to
obtain its package (use the same ancestor lookup you use elsewhere) and then add
package + "." + name and "java.lang." + name when not already present in
candidates.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fde627aa-6117-4891-b48a-27246232325e
📒 Files selected for processing (1)
java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java
| if (getAnnotationQuery().matchesAnnotation(fqn) && doElementsMatch((Annotation) annotation)) { | ||
| return true; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
FILE="java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java"
echo "=== File existence and size ==="
if [ -f "$FILE" ]; then
wc -l "$FILE"
echo "File exists"
else
echo "File not found"
exit 1
fi
echo
echo "=== Lines 50-75 (context around mentioned lines) ==="
sed -n '50,75p' "$FILE"
echo
echo "=== All imports ==="
head -50 "$FILE" | grep -E "^import"
echo
echo "=== Method signatures for doElementsMatch ==="
rg -n 'doElementsMatch' "$FILE" -B2 -A5Repository: konveyor/java-analyzer-bundle
Length of output: 4926
Remove unsafe casts to internal Annotation class; use IAnnotation interface instead.
Direct casts to the internal org.eclipse.jdt.internal.core.Annotation can throw ClassCastException when JDT returns an IAnnotation implementation that is not from the internal package. Lines 53, 62, and 70 all perform such casts; line 70 is particularly problematic as it checks instanceof IAnnotation but still unsafely casts to the internal Annotation class.
Update the doElementsMatch() method signature to accept IAnnotation and remove all unsafe casts:
Proposed changes
- private boolean doElementsMatch(Annotation annotation) throws JavaModelException {
+ private boolean doElementsMatch(IAnnotation annotation) throws JavaModelException {- return doElementsMatch((Annotation) annotation);
+ return doElementsMatch(annotation);- Annotation innerAnnotation = (Annotation) objs[i];
+ if (!(objs[i] instanceof IAnnotation)) {
+ continue;
+ }
+ IAnnotation innerAnnotation = (IAnnotation) objs[i];- Annotation innerAnnotation = (Annotation) member.getValue();
+ IAnnotation innerAnnotation = (IAnnotation) member.getValue();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/WithAnnotationQuery.java`
around lines 52 - 53, The code is performing unsafe casts to the internal
org.eclipse.jdt.internal.core.Annotation; change the doElementsMatch(Annotation)
signature in WithAnnotationQuery to doElementsMatch(IAnnotation) (use
org.eclipse.jdt.core.IAnnotation), update all callers (where
getAnnotationQuery().matchesAnnotation(fqn) && doElementsMatch((Annotation)
annotation) and the other two similar sites) to pass the annotation variable as
an IAnnotation (remove casts) and replace any instanceof Annotation checks with
instanceof IAnnotation; update imports to use IAnnotation and adjust any
internal-Annotation-specific method calls to the public IAnnotation API so no
internal classes are referenced or cast.
…cking (#208)
Summary by CodeRabbit