diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCodeSelector.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCodeSelector.java index fafdcb31a64..ec77e07170a 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCodeSelector.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/DOMCodeSelector.java @@ -60,7 +60,7 @@ public IJavaElement[] codeSelect(int offset, int length) throws JavaModelExcepti if (offset + length > this.unit.getSource().length()) { throw new JavaModelException(new IndexOutOfBoundsException(offset + length), IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS); } - org.eclipse.jdt.core.dom.CompilationUnit currentAST = this.unit.getOrBuildAST(this.owner); + org.eclipse.jdt.core.dom.CompilationUnit currentAST = this.unit.getOrBuildAST(this.owner, this.unit.getBuffer().getLength() < 50000 ? -1 : offset); if (currentAST == null) { return new IJavaElement[0]; } @@ -197,6 +197,10 @@ public IJavaElement[] codeSelect(int offset, int length) throws JavaModelExcepti return reorderedOverloadedMethods; } return new IJavaElement[] { importBinding.getJavaElement() }; + } else if (node instanceof MethodDeclaration decl && offset > decl.getName().getStartPosition()) { + // most likely inside and empty `()` + // case for TypeHierarchyCommandTest.testTypeHierarchy() + return null; } else if (findTypeDeclaration(node) == null) { IBinding binding = resolveBinding(node); if (binding != null && !binding.isRecovered()) { @@ -372,7 +376,7 @@ public IJavaElement[] codeSelect(int offset, int length) throws JavaModelExcepti return new IJavaElement[0]; } - static IBinding resolveBinding(ASTNode node) { + public static IBinding resolveBinding(ASTNode node) { if (node instanceof MethodDeclaration decl) { return decl.resolveBinding(); } @@ -450,7 +454,7 @@ static IBinding resolveBinding(ASTNode node) { } IMethod methodModel = ((IMethod)methodBinding.getJavaElement()); boolean allowExtraParam = true; - if ((methodModel.getFlags() & Flags.AccStatic) != 0) { + if (methodModel != null && (methodModel.getFlags() & Flags.AccStatic) != 0) { allowExtraParam = false; if (methodRef.getExpression() instanceof ClassInstanceCreation) { return null; @@ -463,15 +467,21 @@ static IBinding resolveBinding(ASTNode node) { while (type == null && cursor != null) { if (cursor.getParent() instanceof VariableDeclarationFragment declFragment) { type = declFragment.resolveBinding().getType(); - } - else if (cursor.getParent() instanceof MethodInvocation methodInvocation) { + } else if (cursor.getParent() instanceof MethodInvocation methodInvocation) { IMethodBinding methodInvocationBinding = methodInvocation.resolveMethodBinding(); - int index = methodInvocation.arguments().indexOf(cursor); - type = methodInvocationBinding.getParameterTypes()[index]; + if (methodInvocationBinding != null) { + int index = methodInvocation.arguments().indexOf(cursor); + type = methodInvocationBinding.getParameterTypes()[index]; + } else { + cursor = null; + } } else { cursor = cursor.getParent(); } } + if (type == null) { + return null; + } IMethodBinding boundMethod = type.getDeclaredMethods()[0]; @@ -562,6 +572,9 @@ private static boolean matchSignatures(IMethodBinding invocation, IMethodBinding } private IJavaElement[] findTypeInIndex(String packageName, String simpleName) throws JavaModelException { + if (simpleName == null) { + return new IJavaElement[0]; + } List indexMatch = new ArrayList<>(); TypeNameMatchRequestor requestor = new TypeNameMatchRequestor() { @Override diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java index b276422e750..e40405634f5 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java @@ -172,6 +172,10 @@ protected boolean buildStructure(OpenableElementInfo info, final IProgressMonito ASTNode dom = null; try { dom = astParser.createAST(pm); + if (computeProblems) { + // force resolution of bindings to load more problems + dom.getAST().resolveWellKnownType(Object.class.getName()); + } } catch (AbortCompilationUnit e) { var problem = e.problem; if (problem == null && e.exception instanceof IOException ioEx) { @@ -472,12 +476,14 @@ public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner workin } } -public org.eclipse.jdt.core.dom.CompilationUnit getOrBuildAST(WorkingCopyOwner workingCopyOwner) throws JavaModelException { +public org.eclipse.jdt.core.dom.CompilationUnit getOrBuildAST(WorkingCopyOwner workingCopyOwner, int focalPosition) throws JavaModelException { if (this.ast != null) { return this.ast; } Map options = getOptions(true); ASTParser parser = ASTParser.newParser(new AST(options).apiLevel()); // go through AST constructor to convert options to apiLevel + // but we should probably instead just use the latest Java version + // supported by the compiler parser.setWorkingCopyOwner(workingCopyOwner); parser.setSource(this); // greedily enable everything assuming the AST will be used extensively for edition @@ -485,7 +491,12 @@ public org.eclipse.jdt.core.dom.CompilationUnit getOrBuildAST(WorkingCopyOwner w parser.setStatementsRecovery(true); parser.setBindingsRecovery(true); parser.setCompilerOptions(options); + parser.setFocalPosition(focalPosition); if (parser.createAST(null) instanceof org.eclipse.jdt.core.dom.CompilationUnit newAST) { + if (focalPosition >= 0) { + // do not store + return newAST; + } this.ast = newAST; } return this.ast;