Skip to content

Commit 4274904

Browse files
snjezamickaelistria
authored andcommitted
Incorrect hover and content assist with lombok
Signed-off-by: Snjezana Peco <[email protected]>
1 parent fc0a917 commit 4274904

File tree

5 files changed

+131
-49
lines changed

5 files changed

+131
-49
lines changed

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavacBindingResolver.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,9 @@
4949
import com.sun.tools.javac.api.JavacTaskImpl;
5050
import com.sun.tools.javac.api.JavacTrees;
5151
import com.sun.tools.javac.code.Attribute;
52+
import com.sun.tools.javac.code.Attribute.Compound;
5253
import com.sun.tools.javac.code.ClassFinder;
5354
import com.sun.tools.javac.code.Symbol;
54-
import com.sun.tools.javac.code.Symtab;
55-
import com.sun.tools.javac.code.TypeTag;
56-
import com.sun.tools.javac.code.Types;
57-
import com.sun.tools.javac.code.Attribute.Compound;
5855
import com.sun.tools.javac.code.Symbol.ClassSymbol;
5956
import com.sun.tools.javac.code.Symbol.CompletionFailure;
6057
import com.sun.tools.javac.code.Symbol.MethodSymbol;
@@ -64,6 +61,7 @@
6461
import com.sun.tools.javac.code.Symbol.TypeSymbol;
6562
import com.sun.tools.javac.code.Symbol.TypeVariableSymbol;
6663
import com.sun.tools.javac.code.Symbol.VarSymbol;
64+
import com.sun.tools.javac.code.Symtab;
6765
import com.sun.tools.javac.code.Type.ArrayType;
6866
import com.sun.tools.javac.code.Type.ClassType;
6967
import com.sun.tools.javac.code.Type.ErrorType;
@@ -75,9 +73,10 @@
7573
import com.sun.tools.javac.code.Type.ModuleType;
7674
import com.sun.tools.javac.code.Type.PackageType;
7775
import com.sun.tools.javac.code.Type.TypeVar;
76+
import com.sun.tools.javac.code.TypeTag;
77+
import com.sun.tools.javac.code.Types;
7878
import com.sun.tools.javac.comp.Modules;
7979
import com.sun.tools.javac.tree.JCTree;
80-
import com.sun.tools.javac.tree.TreeInfo;
8180
import com.sun.tools.javac.tree.JCTree.JCAnnotatedType;
8281
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
8382
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
@@ -103,6 +102,7 @@
103102
import com.sun.tools.javac.tree.JCTree.JCTypeUnion;
104103
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
105104
import com.sun.tools.javac.tree.JCTree.JCWildcard;
105+
import com.sun.tools.javac.tree.TreeInfo;
106106
import com.sun.tools.javac.util.Context;
107107
import com.sun.tools.javac.util.Names;
108108

@@ -1739,6 +1739,12 @@ Object resolveConstantExpressionValue(Expression expression) {
17391739
if (jcTree instanceof JCLiteral literal) {
17401740
return literal.getValue();
17411741
}
1742+
if (jcTree == null && expression.getParent() != null) {
1743+
jcTree = this.converter.domToJavac.get(expression.getParent());
1744+
if (jcTree == null) {
1745+
return null;
1746+
}
1747+
}
17421748
return TreeInfo.symbolFor(jcTree) instanceof VarSymbol varSymbol ? varSymbol.getConstantValue() : null;
17431749
}
17441750
@Override

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavacConverter.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.eclipse.jdt.core.dom.ModuleModifier.ModuleModifierKeyword;
3636
import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
3737
import org.eclipse.jdt.core.dom.PrimitiveType.Code;
38+
import org.eclipse.jdt.internal.codeassist.DOMCodeSelector;
3839
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
3940
import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
4041

@@ -140,6 +141,7 @@
140141
@SuppressWarnings("unchecked")
141142
class JavacConverter {
142143

144+
private static final String MISSING_IDENTIFIER = "$missing$";
143145
private static final String ERROR = "<error>";
144146
private static final String FAKE_IDENTIFIER = new String(RecoveryScanner.FAKE_IDENTIFIER);
145147
public final AST ast;
@@ -501,6 +503,8 @@ private void nameSettings(SimpleName name, JCMethodDecl javac, String selector,
501503
// handle constructor length using type name instead of selector.
502504
var length = isConstructor ? name.toString().length() : selector.length();
503505
name.setSourceRange(start, length);
506+
} else {
507+
name.setSourceRange(0, 0);
504508
}
505509
}
506510

@@ -510,6 +514,8 @@ private void nameSettings(SimpleName name, JCVariableDecl javac, String varName)
510514
var start = javac.getPreferredPosition();
511515
if (start > -1) {
512516
name.setSourceRange(start, varName.length());
517+
} else {
518+
name.setSourceRange(0, 0);
513519
}
514520
}
515521

@@ -607,6 +613,11 @@ private AbstractTypeDeclaration convertClassDecl(JCClassDecl javacClassDecl, AST
607613
int namePosition = this.rawText.indexOf(simpName.getIdentifier(), searchNameFrom);
608614
if (namePosition >= 0) {
609615
simpName.setSourceRange(namePosition, simpName.getIdentifier().length());
616+
} else if (!MISSING_IDENTIFIER.equals(simpName.getFullyQualifiedName())) {
617+
// lombok case
618+
if (DOMCodeSelector.isGenerated(res)) {
619+
simpName.setSourceRange(0, 0);
620+
}
610621
}
611622
}
612623
res.modifiers().addAll(convert(javacClassDecl.mods, res));
@@ -2865,9 +2876,13 @@ Type convertToType(JCTree javac) {
28652876
simpleName.delete();
28662877
return qualifierType;
28672878
} else {
2868-
// lombok case
2869-
// or empty (eg `test.`)
2870-
simpleName.setSourceRange(qualifierType.getStartPosition(), 0);
2879+
if (MISSING_IDENTIFIER.equals(simpleName.getFullyQualifiedName())) {
2880+
// empty (eg `test.`)
2881+
simpleName.setSourceRange(qualifierType.getStartPosition(), 0);
2882+
} else {
2883+
// lombok case
2884+
simpleName.setSourceRange(0, 0);
2885+
}
28712886
}
28722887
if(qualifierType instanceof SimpleType simpleType && simpleType.annotations().isEmpty()) {
28732888
simpleType.delete();
@@ -2876,13 +2891,18 @@ Type convertToType(JCTree javac) {
28762891
QualifiedName name = this.ast.newQualifiedName(simpleType.getName(), simpleName);
28772892
commonSettings(name, javac);
28782893
int length = simpleType.getName().getLength() + 1 + simpleName.getLength();
2879-
if (name.getStartPosition() >= 0) {
2894+
if (simpleNameStart > 0 && name.getStartPosition() >= 0) {
28802895
name.setSourceRange(name.getStartPosition(), Math.max(0, length));
2896+
} else if (!MISSING_IDENTIFIER.equals(simpleName.getFullyQualifiedName())) {
2897+
// lombok case
2898+
name.setSourceRange(0, 0);
28812899
}
28822900
SimpleType res = this.ast.newSimpleType(name);
28832901
commonSettings(res, javac);
2884-
if (name.getStartPosition() >= 0) {
2902+
if (simpleNameStart > 0 && name.getStartPosition() >= 0) {
28852903
res.setSourceRange(name.getStartPosition(), Math.max(0, length));
2904+
} else if (!MISSING_IDENTIFIER.equals(simpleName.getFullyQualifiedName())) {
2905+
res.setSourceRange(0, 0);
28862906
}
28872907
return res;
28882908
} else {
@@ -3397,8 +3417,10 @@ public boolean visit(QualifiedName node) {
33973417

33983418
@Override
33993419
public void endVisit(QualifiedName node) {
3400-
if (node.getName().getStartPosition() >= 0) {
3420+
if (node.getName().getStartPosition() >= 0 && (node.getName().getStartPosition() + node.getName().getLength() - node.getQualifier().getStartPosition()) >= 0) {
34013421
node.setSourceRange(node.getQualifier().getStartPosition(), node.getName().getStartPosition() + node.getName().getLength() - node.getQualifier().getStartPosition());
3422+
} else if (!MISSING_IDENTIFIER.equals(node.getName().getIdentifier())) {
3423+
node.setSourceRange(0, 0);
34023424
}
34033425
}
34043426

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavadocConverter.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import com.sun.source.util.TreePath;
3030
import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
3131
import com.sun.tools.javac.tree.DCTree;
32-
import com.sun.tools.javac.tree.JCTree;
33-
import com.sun.tools.javac.tree.TreeScanner;
3432
import com.sun.tools.javac.tree.DCTree.DCAuthor;
3533
import com.sun.tools.javac.tree.DCTree.DCBlockTag;
3634
import com.sun.tools.javac.tree.DCTree.DCComment;
@@ -58,7 +56,9 @@
5856
import com.sun.tools.javac.tree.DCTree.DCUses;
5957
import com.sun.tools.javac.tree.DCTree.DCValue;
6058
import com.sun.tools.javac.tree.DCTree.DCVersion;
59+
import com.sun.tools.javac.tree.JCTree;
6160
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
61+
import com.sun.tools.javac.tree.TreeScanner;
6262
import com.sun.tools.javac.util.Convert;
6363
import com.sun.tools.javac.util.JCDiagnostic;
6464

@@ -635,10 +635,23 @@ private Stream<? extends IDocElement> convertElement(DCTree javac) {
635635
}
636636
return regions.stream();
637637
} else {
638-
TextElement element = this.ast.newTextElement();
639-
commonSettings(element, javac);
640-
element.setText(rawText.getContent());
641-
return Stream.of(element);
638+
String content = rawText.getContent();
639+
char last = content.charAt(content.length()-1);
640+
if (last != 26 /* EOF */) {
641+
// https://github.com/eclipse-jdtls/eclipse-jdt-core-incubator/issues/1185
642+
// Possible error converting Javadoc
643+
TextElement element = this.ast.newTextElement();
644+
commonSettings(element, javac);
645+
element.setText(rawText.getContent());
646+
return Stream.of(element);
647+
} else {
648+
content = rawText.getContent().substring(0, content.length() - 1);
649+
int currentStart = this.docComment.getSourcePosition(rawText.getStartPosition());
650+
TextElement element = this.ast.newTextElement();
651+
element.setSourceRange(currentStart, content.length());
652+
element.setText(content);
653+
return Stream.of(element);
654+
}
642655
}
643656
} else if (javac instanceof DCIdentifier identifier) {
644657
Name res = this.ast.newName(identifier.getName().toString());

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/codeassist/DOMCompletionContext.java

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -72,37 +72,53 @@ class DOMCompletionContext extends CompletionContext {
7272
this.textContent = textContent;
7373
this.offset = offset;
7474
int adjustedOffset = this.offset;
75-
if (adjustedOffset > 0 && Character.isJavaIdentifierPart(textContent.charAt(adjustedOffset - 1))) {
76-
// workaround for cases where right node is empty and reported (wrongly) as starting at same offset
77-
adjustedOffset--;
78-
}
79-
ASTNode currentNode = NodeFinder.perform(domUnit, adjustedOffset, 0);
80-
// Use the raw text to walk back the offset to the first non-whitespace spot
81-
adjustedOffset = this.offset;
82-
if (adjustedOffset >= textContent.length()) {
83-
adjustedOffset = textContent.length() - 1;
84-
}
85-
if (adjustedOffset > 0 && Character.isJavaIdentifierPart(textContent.charAt(adjustedOffset - 1))) {
86-
// workaround for cases where right node is empty and reported (wrongly) as starting at same offset
87-
adjustedOffset--;
88-
}
89-
if (adjustedOffset + 1 >= textContent.length()
90-
|| !Character.isJavaIdentifierStart(textContent.charAt(adjustedOffset))) {
91-
while (adjustedOffset > 0 && Character.isWhitespace(textContent.charAt(adjustedOffset - 1)) ) {
75+
boolean isGenerated = DOMCodeSelector.isGenerated(domUnit);
76+
if (!isGenerated) {
77+
if (adjustedOffset > 0 && Character.isJavaIdentifierPart(textContent.charAt(adjustedOffset - 1))) {
78+
// workaround for cases where right node is empty and reported (wrongly) as starting at same offset
9279
adjustedOffset--;
9380
}
81+
ASTNode currentNode = NodeFinder.perform(domUnit, adjustedOffset, 0);
82+
// Use the raw text to walk back the offset to the first non-whitespace spot
83+
adjustedOffset = this.offset;
84+
if (adjustedOffset >= textContent.length()) {
85+
adjustedOffset = textContent.length() - 1;
86+
}
87+
if (adjustedOffset > 0 && Character.isJavaIdentifierPart(textContent.charAt(adjustedOffset - 1))) {
88+
// workaround for cases where right node is empty and reported (wrongly) as starting at same offset
89+
adjustedOffset--;
90+
}
91+
if (adjustedOffset + 1 >= textContent.length()
92+
|| !Character.isJavaIdentifierStart(textContent.charAt(adjustedOffset))) {
93+
while (adjustedOffset > 0 && Character.isWhitespace(textContent.charAt(adjustedOffset - 1)) ) {
94+
adjustedOffset--;
95+
}
96+
}
97+
ASTNode previousNodeBeforeWhitespaces = NodeFinder.perform(domUnit, adjustedOffset, 0);
98+
adjustedOffset = this.offset;
99+
if (adjustedOffset < textContent.length() - 1 && Character.isWhitespace(textContent.charAt(adjustedOffset)) ) {
100+
adjustedOffset++;
101+
}
102+
ASTNode nextNodeAfterWhitespaces = NodeFinder.perform(domUnit, adjustedOffset, 0);
103+
this.node = (nextNodeAfterWhitespaces.getLength() == 0 && nextNodeAfterWhitespaces.getParent() == currentNode)
104+
? nextNodeAfterWhitespaces
105+
: (previousNodeBeforeWhitespaces instanceof SimpleName || previousNodeBeforeWhitespaces instanceof StringLiteral || previousNodeBeforeWhitespaces instanceof CharacterLiteral || previousNodeBeforeWhitespaces instanceof NumberLiteral)
106+
? currentNode
107+
: previousNodeBeforeWhitespaces;
108+
} else {
109+
if (adjustedOffset + 1 <= textContent.length()
110+
|| !Character.isJavaIdentifierStart(textContent.charAt(adjustedOffset))) {
111+
while (adjustedOffset > 0 && Character.isJavaIdentifierStart(textContent.charAt(adjustedOffset - 1))) {
112+
adjustedOffset--;
113+
}
114+
}
115+
int length = 0;
116+
while (adjustedOffset + length <= textContent.length()
117+
&& Character.isJavaIdentifierStart(textContent.charAt(adjustedOffset + length))) {
118+
length++;
119+
}
120+
this.node = NodeFinder.perform(domUnit, adjustedOffset, length);
94121
}
95-
ASTNode previousNodeBeforeWhitespaces = NodeFinder.perform(domUnit, adjustedOffset, 0);
96-
adjustedOffset = this.offset;
97-
if (adjustedOffset < textContent.length() - 1 && Character.isWhitespace(textContent.charAt(adjustedOffset)) ) {
98-
adjustedOffset++;
99-
}
100-
ASTNode nextNodeAfterWhitespaces = NodeFinder.perform(domUnit, adjustedOffset, 0);
101-
this.node = (nextNodeAfterWhitespaces.getLength() == 0 && nextNodeAfterWhitespaces.getParent() == currentNode)
102-
? nextNodeAfterWhitespaces
103-
: (previousNodeBeforeWhitespaces instanceof SimpleName || previousNodeBeforeWhitespaces instanceof StringLiteral || previousNodeBeforeWhitespaces instanceof CharacterLiteral || previousNodeBeforeWhitespaces instanceof NumberLiteral)
104-
? currentNode
105-
: previousNodeBeforeWhitespaces;
106122
this.expectedTypes = new ExpectedTypes(assistOptions, this.node, offset);
107123
this.token = tokenBefore(this.textContent).toCharArray();
108124
this.bindingsAcquirer = bindings::all;

org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCodeSelector.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,7 @@ public IJavaElement[] codeSelect(int offset, int length) throws JavaModelExcepti
113113
} while (changed);
114114
}
115115
String trimmedText = rawText.trim();
116-
NodeFinder finder = new NodeFinder(currentAST, offset, length);
117-
final ASTNode node = finder.getCoveredNode() != null && finder.getCoveredNode().getStartPosition() > offset && finder.getCoveringNode().getStartPosition() + finder.getCoveringNode().getLength() > offset + length ?
118-
finder.getCoveredNode() :
119-
finder.getCoveringNode();
116+
final ASTNode node = NodeFinder.perform(currentAST, offset, length);
120117
if (node instanceof TagElement tagElement && TagElement.TAG_INHERITDOC.equals(tagElement.getTagName())) {
121118
ASTNode javadocNode = node;
122119
while (javadocNode != null && !(javadocNode instanceof Javadoc)) {
@@ -300,8 +297,10 @@ public IJavaElement[] codeSelect(int offset, int length) throws JavaModelExcepti
300297
int finalLength = length;
301298
do {
302299
newChildFound = false;
300+
boolean isGeneratedByLombok = isGenerated(currentAST);
303301
if (currentElement instanceof IParent parentElement) {
304302
Optional<IJavaElement> candidate = Stream.of(parentElement.getChildren())
303+
.filter(e -> (!isGeneratedByLombok || e.getElementName().equals(trimmedText)))
305304
.filter(ISourceReference.class::isInstance)
306305
.map(ISourceReference.class::cast)
307306
.filter(sourceRef -> {
@@ -621,4 +620,30 @@ private String findWord(int offset) throws JavaModelException {
621620
while (end < source.length() && Character.isJavaIdentifierPart(source.charAt(end))) end++;
622621
return source.substring(start, end);
623622
}
623+
624+
/**
625+
* Checks if the node is generated
626+
*
627+
* @param node the AST node
628+
* @return true if the node is generated.
629+
*/
630+
public static boolean isGenerated(ASTNode node) {
631+
if (node != null) {
632+
boolean[] isGenerated = {false};
633+
node.accept(new ASTVisitor() {
634+
635+
@Override
636+
public void endVisit(MarkerAnnotation markerAnnotation) {
637+
if (!isGenerated[0]) {
638+
// check lombok only for now
639+
isGenerated[0] = "lombok.Generated".equals(markerAnnotation.getTypeName().getFullyQualifiedName()); //$NON-NLS-1$
640+
super.endVisit(markerAnnotation);
641+
}
642+
}
643+
644+
});
645+
return isGenerated[0];
646+
}
647+
return false;
648+
}
624649
}

0 commit comments

Comments
 (0)