diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavacBindingResolver.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavacBindingResolver.java index 02f15a79907..58cb0605fa3 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavacBindingResolver.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/core/dom/JavacBindingResolver.java @@ -47,8 +47,11 @@ import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.code.Attribute; -import com.sun.tools.javac.code.Attribute.Compound; import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.code.Attribute.Compound; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.ModuleSymbol; @@ -57,7 +60,6 @@ import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.TypeVariableSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; -import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.Type.ErrorType; @@ -69,9 +71,8 @@ import com.sun.tools.javac.code.Type.ModuleType; import com.sun.tools.javac.code.Type.PackageType; import com.sun.tools.javac.code.Type.TypeVar; -import com.sun.tools.javac.code.TypeTag; -import com.sun.tools.javac.code.Types; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; @@ -95,7 +96,6 @@ import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWildcard; -import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Context; /** @@ -378,7 +378,12 @@ public IBinding getBinding(final Symbol owner, final com.sun.tools.javac.code.Ty } else if (owner instanceof TypeSymbol typeSymbol) { return getTypeBinding(isTypeOfType(type) ? type : typeSymbol.type); } else if (owner instanceof final MethodSymbol other) { - return getMethodBinding(type instanceof com.sun.tools.javac.code.Type.MethodType methodType ? methodType : owner.type.asMethodType(), other, null, false); + var methodType = type instanceof com.sun.tools.javac.code.Type.MethodType aMethodType ? aMethodType : + owner.type != null ? owner.type.asMethodType() : + null; + if (methodType != null) { + return getMethodBinding(methodType, other, null, false); + } } else if (owner instanceof final VarSymbol other) { return getVariableBinding(other); } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCompletionContext.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCompletionContext.java index dac038163b1..5e08b2c2b65 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCompletionContext.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCompletionContext.java @@ -68,7 +68,7 @@ class DOMCompletionContext extends CompletionContext { : previousNodeBeforeWhitespaces; // use previous node this.expectedTypes = new ExpectedTypes(assistOptions, this.node, offset); this.token = tokenBefore(cuBuffer).toCharArray(); - this.enclosingElement = computeEnclosingElement(modelUnit); + this.enclosingElement = computeEnclosingElement(domUnit, modelUnit); this.bindingsAcquirer = bindings::stream; this.isJustAfterStringLiteral = this.node instanceof StringLiteral && this.node.getLength() > 1 && this.offset >= node.getStartPosition() + node.getLength() && cuBuffer.getChar(this.offset - 1) == '"'; } @@ -84,16 +84,51 @@ private String tokenBefore(IBuffer cuBuffer) { return builder.toString(); } - private IJavaElement computeEnclosingElement(ICompilationUnit modelUnit) { + private IJavaElement computeEnclosingElement(CompilationUnit domUnit, ICompilationUnit modelUnit) { + IJavaElement enclosingElement = modelUnit; try { - if (modelUnit == null) - return null; - IJavaElement enclosingElement = modelUnit.getElementAt(this.offset); - return enclosingElement == null ? modelUnit : enclosingElement; + enclosingElement = modelUnit.getElementAt(this.offset); } catch (JavaModelException e) { ILog.get().error(e.getMessage(), e); - return null; } + if (enclosingElement == null) { + return modelUnit; + } + // then refine to get "resolved" element from the matching binding + // pitfall: currently resolve O(depth(node)) bindings while we can + // most likely find a O(1) solution + ASTNode node = NodeFinder.perform(domUnit, this.offset, 0); + while (node != null) { + IBinding binding = resolveBindingForContext(node); + if (binding != null) { + IJavaElement bindingBasedJavaElement = binding.getJavaElement(); + if (enclosingElement.equals(bindingBasedJavaElement)) { + return bindingBasedJavaElement; + } + } + node = node.getParent(); + } + return enclosingElement; + } + + private IBinding resolveBindingForContext(ASTNode node) { + var res = DOMCodeSelector.resolveBinding(node); + if (res != null) { + return res; + } + // Some declaration types are intentionally skipped by + // DOMCodeSelector.resolveBinding() as they're not + // expected by `codeSelect` add them here + if (node instanceof TypeDeclaration typeDecl) { + return typeDecl.resolveBinding(); + } + if (node instanceof MethodDeclaration methodDecl) { + return methodDecl.resolveBinding(); + } + if (node instanceof VariableDeclaration varDecl) { + return varDecl.resolveBinding(); + } + return null; } @Override