Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
import static org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin.logInfo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.konveyor.tackle.core.internal.query.AnnotationQuery;
import io.konveyor.tackle.core.internal.symbol.CustomASTVisitor.QueryLocation;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
Expand All @@ -26,6 +25,9 @@
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;

import io.konveyor.tackle.core.internal.query.AnnotationQuery;
import io.konveyor.tackle.core.internal.symbol.CustomASTVisitor.QueryLocation;

public class AnnotationSymbolProvider implements SymbolProvider, WithQuery, WithAnnotationQuery {

private AnnotationQuery annotationQuery;
Expand Down Expand Up @@ -54,6 +56,34 @@ public List<SymbolInformation> get(SearchMatch match) throws CoreException {
unit = cls.getWorkingCopy(new WorkingCopyOwnerImpl(), null);
}
}
IType t = unit.getType(annotationElement.getElementName());
String fqdn = "";
if (!t.isResolved()) {
var elements = unit.codeSelect(match.getOffset(), match.getLength());
for (IJavaElement e: Arrays.asList(elements)) {
if (e instanceof IType) {
var newT = (IType) e;
if (newT.isResolved()) {
fqdn = newT.getFullyQualifiedName('.');
logInfo("FQDN from code select: " + fqdn);
}
}
}
} else {
fqdn = t.getFullyQualifiedName('.');
logInfo("resolved type: " + fqdn);
}
Copy link

@coderabbitai coderabbitai bot Oct 22, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Guard against null unit/handle existence; prefer codeSelect-first for FQDN

unit can still be null (no CU/class file), and unit.getType(simpleName) rarely resolves for annotations defined elsewhere. Also call sites on a non‑existent handle can mislead. Guard unit, use exists(), and favor codeSelect first.

-                    IType t = unit.getType(annotationElement.getElementName());
-                    String fqdn = "";
-                    if (!t.isResolved()) {
-                        var elements = unit.codeSelect(match.getOffset(), match.getLength());
-                        for (IJavaElement e: Arrays.asList(elements)) {
-                            if (e instanceof IType) {
-                                var newT = (IType) e;
-                                if (newT.isResolved()) {
-                                    fqdn = newT.getFullyQualifiedName('.');
-                                    logInfo("FQDN from code select: " + fqdn);
-                                }
-                            }
-                        }
-                    } else {
-                        fqdn = t.getFullyQualifiedName('.');
-                        logInfo("resolved type: " + fqdn);
-                    }
+                    String fqdn = "";
+                    IType t = null;
+                    if (unit != null) {
+                        // Prefer codeSelect: the annotation type is usually external to this CU.
+                        IJavaElement[] sel = unit.codeSelect(match.getOffset(), match.getLength());
+                        for (IJavaElement e : sel) {
+                            if (e.getElementType() == IJavaElement.TYPE) {
+                                IType newT = (IType) e;
+                                if (newT.isResolved()) {
+                                    fqdn = newT.getFullyQualifiedName('.');
+                                    logInfo("FQDN from code select: " + fqdn);
+                                    break;
+                                }
+                            }
+                        }
+                        // Fallback: try CU-local handle only if present and resolved.
+                        if (fqdn.isEmpty()) {
+                            t = unit.getType(annotationElement.getElementName());
+                            if (t != null && t.exists() && t.isResolved()) {
+                                fqdn = t.getFullyQualifiedName('.');
+                                logInfo("resolved type: " + fqdn);
+                            }
+                        }
+                    }
🤖 Prompt for AI Agents
In
java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/symbol/AnnotationSymbolProvider.java
around lines 59 to 75, guard against a null or non-existing ICompilationUnit
before calling methods on it, prefer using codeSelect first to resolve the
annotation FQDN (since unit.getType(simpleName) often fails for annotations
defined elsewhere), check unit.exists() and skip codeSelect/getType if the unit
is null or doesn't exist, iterate codeSelect results and return the first
resolved IType FQDN if present, and only if codeSelect yields nothing attempt
unit.getType(simpleName) with a null/exists check and use its
getFullyQualifiedName('.') as a fallback; add concise logs for each resolution
path and ensure no method is invoked on a null/non-existing unit.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@shawn-hurley this has a point, we should guard against nil just in case

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

if (query.matches(fqdn)) {
symbols.add(symbol);
return symbols;
}
if (fqdn.matches(query)) {
symbols.add(symbol);
return symbols;
}

logInfo("falling back to resolving via AST");

if (this.queryQualificationMatches(this.query.replaceAll("\\(([A-Za-z_][A-Za-z0-9_]*(\\|[A-Za-z_][A-Za-z0-9_]*)*)\\)", ".*"), annotationElement, unit, location)) {
ASTParser astParser = ASTParser.newParser(AST.getJLSLatest());
astParser.setSource(unit);
Expand Down Expand Up @@ -106,7 +136,6 @@ public List<SymbolInformation> get(SearchMatch match) throws CoreException {
symbols.add(symbol);
}
}

}
return symbols;
} catch (Exception e) {
Expand Down
Loading