From 75560d52b852e3443ea8d4db540579e89157107f Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Sun, 31 May 2009 01:07:55 +0000 Subject: [PATCH] Bug 278337. --- .../cdt/core/dom/ast/IProblemBinding.java | 15 ++- .../core/dom/parser/ProblemBinding.java | 23 +++- .../internal/core/dom/parser/c/CVisitor.java | 20 +-- .../cpp/CPPASTFunctionCallExpression.java | 3 +- .../parser/cpp/semantics/CPPSemantics.java | 81 +++++++----- .../dom/parser/cpp/semantics/CPPVisitor.java | 6 +- .../dom/parser/cpp/semantics/LookupData.java | 45 +++---- .../selection/CPPSelectionTestsNoIndexer.java | 121 ++++++++++++------ .../actions/OpenDeclarationsAction.java | 67 ++++++---- 9 files changed, 240 insertions(+), 141 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IProblemBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IProblemBinding.java index bf6c9d0d1e8..eca5b6f2aae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IProblemBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IProblemBinding.java @@ -47,8 +47,19 @@ public interface IProblemBinding extends IBinding, IScope, IType { * returns the line number for this problem if known */ public int getLineNumber(); - - /* + + /** + * Returns bindings that were considered when resolving the node corresponding + * to this problem binding, but rejected for some reason. + * @return an array of candidate bindings. + * + * This method is experimental. Clients calling this method should expect + * possible changes. + * @since 5.1 experimental + */ + public IBinding[] getCandidateBindings(); + + /* * Parser Semantic Problems * All Semantic problems take a char[] as an argument */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java index 539a53ca79b..69f00477a64 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java @@ -40,16 +40,26 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I protected final int id; protected char[] arg; protected IASTNode node; - private String message = null; + private final String message = null; + private final IBinding[] candidateBindings; public ProblemBinding(IASTName name, int id) { - this(name, id, null); + this(name, id, null, null); } - + + public ProblemBinding(IASTName name, int id, IBinding[] candidateBindings) { + this(name, id, null, candidateBindings); + } + public ProblemBinding(IASTNode node, int id, char[] arg) { + this(node, id, arg, null); + } + + public ProblemBinding(IASTNode node, int id, char[] arg, IBinding[] candidateBindings) { this.id = id; this.arg = arg; this.node = node; + this.candidateBindings = candidateBindings; } public EScopeKind getKind() { @@ -59,7 +69,11 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I public IASTNode getASTNode() { return node; } - + + public IBinding[] getCandidateBindings() { + return candidateBindings != null ? candidateBindings : IBinding.EMPTY_BINDING_ARRAY; + } + protected static final String[] errorMessages; static { errorMessages = new String[IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS]; @@ -134,6 +148,7 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I return getASTNode(); } + @Override public Object clone() { // Don't clone problems diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index ace1ed4d200..66c7f625513 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -837,9 +837,10 @@ public class CVisitor extends ASTQueries { } else if (node instanceof IASTIdExpression) { IScope scope = getContainingScope(node); try { - IBinding binding = lookup(scope, ((IASTIdExpression)node).getName()); + IBinding binding = lookup(scope, ((IASTIdExpression) node).getName()); if (binding instanceof IType && !(binding instanceof IProblemBinding) ) { - return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray()); + return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, + binding.getNameCharArray(), new IBinding[] { binding }); } return binding; } catch (DOMException e) { @@ -848,20 +849,21 @@ public class CVisitor extends ASTQueries { } else if (node instanceof ICASTTypedefNameSpecifier) { IScope scope = getContainingScope(node); try { - IASTName name= ((ICASTTypedefNameSpecifier)node).getName(); + IASTName name= ((ICASTTypedefNameSpecifier) node).getName(); IBinding binding = lookup(scope, name); if (binding == null) return new ProblemBinding(node, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, name.toCharArray()); if (binding instanceof IType) return binding; - return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray()); + return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray(), + new IBinding[] { binding }); } catch (DOMException e) { return null; } } else if (node instanceof ICASTElaboratedTypeSpecifier) { IScope scope = getContainingScope(node); try { - return lookup(scope, ((ICASTElaboratedTypeSpecifier)node).getName()); + return lookup(scope, ((ICASTElaboratedTypeSpecifier) node).getName()); } catch (DOMException e) { return null; } @@ -885,10 +887,12 @@ public class CVisitor extends ASTQueries { } if (name != null) { IBinding binding = name.resolveBinding(); - if (binding instanceof IType) + if (binding instanceof IType) { return binding; - else if (binding != null) - return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray()); + } else if (binding != null) { + return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, + binding.getNameCharArray(), new IBinding[] { binding }); + } return null; } } else if (node instanceof ICASTFieldDesignator) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index da6718f0092..8748e404250 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -201,7 +201,8 @@ public class CPPASTFunctionCallExpression extends ASTNode implements if (owner instanceof ICPPClassType) { return (ICPPClassType) owner; } - return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE, binding.getName().toCharArray()); + return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE, + binding.getName().toCharArray()); } else if (binding instanceof IFunction) { t = ((IFunction) binding).getType(); } else if (binding instanceof IVariable) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index f96c01c235a..0c45f6087aa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -329,7 +329,8 @@ public class CPPSemantics { node= node.getParent(); } if (!ok) { - binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE); + binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE, + data.getFoundBindings()); } } } @@ -414,11 +415,13 @@ public class CPPSemantics { if (parent instanceof IASTTypeId && parent.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) { if (!(binding instanceof IType)) { // a type id needs to hold a type - binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE); + binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE, + data.getFoundBindings()); } // don't create a problem here } else { - binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE); + binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE, + data.getFoundBindings()); } } } else if (namePropertyInParent == IASTIdExpression.ID_NAME) { @@ -430,7 +433,8 @@ public class CPPSemantics { (binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration)) { // constructor or simple-type constructor } else { - binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE); + binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE, + data.getFoundBindings()); } } } @@ -449,10 +453,13 @@ public class CPPSemantics { } // If we're still null... if (binding == null) { - if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) - binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND); - else - binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND); + if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) { + binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND, + data.getFoundBindings()); + } else { + binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, + data.getFoundBindings()); + } } return binding; } @@ -1060,7 +1067,8 @@ public class CPPSemantics { Object temp = lookupInParents(data, classScope, overallScope, fileSet); if (!isEmpty) { inherited = mergePrefixResults(null, inCurrentScope, true); - inherited = mergePrefixResults((CharArrayObjectMap)inherited, (CharArrayObjectMap)temp, true); + inherited = mergePrefixResults((CharArrayObjectMap) inherited, + (CharArrayObjectMap) temp, true); } else { inherited= temp; } @@ -1071,7 +1079,8 @@ public class CPPSemantics { visitVirtualBaseClasses(data, cls); } } else { - data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, cls.getNameCharArray()); + data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, + cls.getNameCharArray(), data.getFoundBindings()); return null; } } @@ -1085,14 +1094,14 @@ public class CPPSemantics { for (int j = 0; j < r.length && r[j] != null; j++) { if (checkForAmbiguity(data, r[j], inherited)) { data.problem = new ProblemBinding(data.astName, - IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings()); return null; } } } else { if (checkForAmbiguity(data, result, inherited)) { data.problem = new ProblemBinding(data.astName, - IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings()); return null; } } @@ -1852,7 +1861,8 @@ public class CPPSemantics { type= temp; } } else { - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); } } } @@ -1866,7 +1876,8 @@ public class CPPSemantics { if (c < 0) { obj= temp; } else if (c == 0) { - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); } } } @@ -1874,8 +1885,11 @@ public class CPPSemantics { if (data.forUsingDeclaration()) { IBinding[] bindings = null; if (obj != null) { - if (fns.size() > 0) return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); - // if (type == null) return obj; + if (fns.size() > 0) { + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); + } +// if (type == null) return obj; bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, obj); bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type); } else { @@ -1898,8 +1912,10 @@ public class CPPSemantics { int numFns = fns.size(); if (numFns > 0) { - if (obj != null) - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + if (obj != null) { + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); + } return resolveFunction(data, fns.keyArray(IFunction.class), true); } @@ -2169,13 +2185,15 @@ public class CPPSemantics { return null; if (ambiguous || bestFnCost.hasAmbiguousUserDefinedConversion()) { - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); } return bestFnCost.getFunction(); } - private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, boolean allowUDC, LookupData data) throws DOMException { + private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, + boolean allowUDC, LookupData data) throws DOMException { final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType(); if (ftype == null) return null; @@ -2270,7 +2288,7 @@ public class CPPSemantics { ICPPASTConversionName astName= (ICPPASTConversionName) data.astName; IType t= CPPVisitor.createType(astName.getTypeId()); if (t == null) { - return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE); + return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings()); } if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { CPPTemplates.instantiateConversionTemplates(fns, t); @@ -2293,7 +2311,7 @@ public class CPPSemantics { } if (unknown != null) return unknown; - return new ProblemBinding(astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND); + return new ProblemBinding(astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.getFoundBindings()); } /** @@ -2337,8 +2355,10 @@ public class CPPSemantics { while (type != null) { type = getUltimateType(type, false); - if (type == null || !(type instanceof IFunctionType)) - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + if (type == null || !(type instanceof IFunctionType)) { + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); + } for (IBinding fn2 : fns) { IFunction fn = (IFunction) fn2; @@ -2356,13 +2376,9 @@ public class CPPSemantics { if (c < 0) { result= fn; } else if (c == 0) { - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); - } -// boolean fromIndex= isFromIndex(fn); -// if (isFromIndex(result) == fromIndex) -// return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); -// if (!fromIndex) -// result= fn; + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); + } } } } @@ -2374,7 +2390,8 @@ public class CPPSemantics { } } - return result != null ? result : new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP); + return result != null ? result : + new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings()); } private static Object getTargetType(LookupData data) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 4c4c0515e0a..93d56817d0a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -631,8 +631,8 @@ public class CPPVisitor extends ASTQueries { ASTInternal.addDeclaration(binding, name); return binding; } - } catch (DOMException e1) { - return e1.getProblem(); + } catch (DOMException e) { + return e.getProblem(); } return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION); } @@ -654,7 +654,7 @@ public class CPPVisitor extends ASTQueries { } else { IASTNode def = internal.getDefinition(); if (def instanceof IASTDeclarator) - def = ((IASTDeclarator)def).getName(); + def = ((IASTDeclarator) def).getName(); if (def != name) { return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 2f4289a3015..c93347889e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -18,30 +18,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; -import org.eclipse.cdt.core.dom.ast.DOMException; -import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; -import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; -import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarator; -import org.eclipse.cdt.core.dom.ast.IASTExpression; -import org.eclipse.cdt.core.dom.ast.IASTExpressionList; -import org.eclipse.cdt.core.dom.ast.IASTFieldReference; -import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; -import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; -import org.eclipse.cdt.core.dom.ast.IASTIdExpression; -import org.eclipse.cdt.core.dom.ast.IASTInitializer; -import org.eclipse.cdt.core.dom.ast.IASTName; -import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTTypeId; -import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; -import org.eclipse.cdt.core.dom.ast.IPointerType; -import org.eclipse.cdt.core.dom.ast.IScope; -import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.*; import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; @@ -66,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectSet; @@ -641,4 +619,23 @@ public class LookupData { public boolean hasArgumentTypes() { return functionArgTypes != null || functionArgs != null; } + + public IBinding[] getFoundBindings() { + if (foundItems instanceof Object[]) { + Object[] items = (Object[]) foundItems; + if (items.length != 0) { + IBinding[] bindings = new IBinding[items.length]; + int k = 0; + for (Object item : items) { + if (item instanceof IBinding) { + bindings[k++] = (IBinding) item; + } + } + if (k != 0) { + return ArrayUtil.trimAt(IBinding.class, bindings, k - 1); + } + } + } + return IBinding.EMPTY_BINDING_ARRAY; + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java index 5bd15070659..05a5a8e6f36 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java @@ -66,9 +66,11 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider; import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction; /** - * It is required to test the selection performance independent of the indexer to make sure that the DOM is functioning properly. + * It is required to test the selection performance independent of the indexer to make sure that the DOM + * is functioning properly. * - * Indexer bugs can drastically influence the correctness of these tests so the indexer has to be off when performing them. + * Indexer bugs can drastically influence the correctness of these tests so the indexer has to be off when + * performing them. * * @author dsteffle */ @@ -101,7 +103,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { File indexFile = new File(pathLoc.append(INDEX_FILE_ID + ".index").toOSString()); //$NON-NLS-1$ if (indexFile.exists()) indexFile.delete(); - } catch ( CoreException e ) { + } catch (CoreException e) { /*boo*/ } if (project == null) @@ -124,17 +126,17 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { public static Test suite() { TestSuite suite= suite(CPPSelectionTestsNoIndexer.class, "_"); - suite.addTest( new CPPSelectionTestsNoIndexer("cleanupProject") ); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsNoIndexer("cleanupProject")); //$NON-NLS-1$ return suite; } public void cleanupProject() throws Exception { closeAllEditors(); - try{ - project.delete( true, false, monitor ); - } catch( CoreException e ){ + try { + project.delete(true, false, monitor); + } catch (CoreException e) { try { - project.delete( true, false, monitor ); + project.delete(true, false, monitor); } catch (CoreException e1) {} } finally { @@ -151,35 +153,35 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { @Override protected void tearDown() throws Exception { - if( project == null || !project.exists() ) + if (project == null || !project.exists()) return; closeAllEditors(); - IResource [] members = project.members(); + IResource[] members = project.members(); for (IResource member : members) { - if( member.getName().equals( ".project" ) || member.getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ + if (member.getName().equals(".project") || member.getName().equals(".cproject")) //$NON-NLS-1$ //$NON-NLS-2$ continue; if (member.getName().equals(".settings")) continue; - try{ - member.delete( false, monitor ); - } catch( Throwable e ){ + try { + member.delete(false, monitor); + } catch (Throwable e) { /*boo*/ } } } - protected IFile importFile(String fileName, String contents ) throws Exception{ + protected IFile importFile(String fileName, String contents) throws Exception{ //Obtain file handle IFile file = project.getProject().getFile(fileName); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -199,19 +201,19 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { file.createLink(location, IResource.ALLOW_MISSING_LOCAL, null); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); return file; } - protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName ) throws Exception{ + protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName) throws Exception{ IFolder linkedFolder = project.getFolder(folderName); IPath folderLocation = new Path(project.getLocation().toOSString() + File.separator + folderName + "_this_is_linked"); //$NON-NLS-1$ IFolder actualFolder = project.getFolder(folderName + "_this_is_linked"); //$NON-NLS-1$ @@ -224,12 +226,12 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { IFile file = linkedFolder.getFile(fileName); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -263,7 +265,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { // the action above should highlight the declaration, so now retrieve it and use that selection to get the IASTName selected on the TU ISelection sel = ((AbstractTextEditor)part).getSelectionProvider().getSelection(); - final IASTName[] result= {null}; + final IASTName[] result= { null }; if (sel instanceof ITextSelection) { final ITextSelection textSel = (ITextSelection)sel; ITranslationUnit tu= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput()); @@ -280,7 +282,11 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { return null; } - + + private void assertContents(String code, int offset, String expected) { + assertEquals(expected, code.substring(offset, offset + expected.length())); + } + public void testBug93281() throws Exception { StringBuffer buffer = new StringBuffer(); buffer.append("class Point{ \n"); //$NON-NLS-1$ @@ -412,11 +418,11 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { public void testBug95224() throws Exception{ Writer writer = new StringWriter(); - writer.write( "class A{\n"); //$NON-NLS-1$ - writer.write( "A();\n"); //$NON-NLS-1$ - writer.write( "A(const A&); // open definition on A finds class A\n"); //$NON-NLS-1$ - writer.write( "~A(); // open definition on A finds nothing\n"); //$NON-NLS-1$ - writer.write( "};\n"); //$NON-NLS-1$ + writer.write("class A{\n"); //$NON-NLS-1$ + writer.write("A();\n"); //$NON-NLS-1$ + writer.write("A(const A&); // open definition on A finds class A\n"); //$NON-NLS-1$ + writer.write("~A(); // open definition on A finds nothing\n"); //$NON-NLS-1$ + writer.write("};\n"); //$NON-NLS-1$ String code = writer.toString(); IFile file = importFile("testBug95224.cpp", code); //$NON-NLS-1$ @@ -431,10 +437,10 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { public void testBasicTemplateInstance() throws Exception{ Writer writer = new StringWriter(); - writer.write( "namespace N{ \n"); //$NON-NLS-1$ - writer.write( " template < class T > class AAA { T _t; };\n"); //$NON-NLS-1$ - writer.write( "}; \n"); //$NON-NLS-1$ - writer.write( "N::AAA a; \n"); //$NON-NLS-1$ + writer.write("namespace N{ \n"); //$NON-NLS-1$ + writer.write(" template < class T > class AAA { T _t; };\n"); //$NON-NLS-1$ + writer.write("}; \n"); //$NON-NLS-1$ + writer.write("N::AAA a; \n"); //$NON-NLS-1$ String code = writer.toString(); IFile file = importFile("testBasicTemplateInstance.cpp", code); //$NON-NLS-1$ @@ -1048,4 +1054,41 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { assertEquals("myFunc", name.toString()); } } + + // struct A { + // void method(int p) {} + // }; + // + // void test(A* a) { + // a->method(); + // a.method(0); + // } + // void A::method(int a, int b) {} + // void B::method(int b) {} + public void testUnresolvedMethod_278337() throws Exception { + String code= getContentsForTest(1)[0].toString(); + IFile file = importFile("testBug278337.cpp", code); + IASTNode node= testF3(file, code.indexOf("method();")); + assertContents(code, node.getFileLocation().getNodeOffset(), "method(int p)"); + node= testF3(file, code.indexOf("method(0);")); + assertNull(node); + node= testF3(file, code.indexOf("method(int a, int b)")); + assertContents(code, node.getFileLocation().getNodeOffset(), "method(int p)"); + node= testF3(file, code.indexOf("method(int b)")); + // Should not navigate away since there is no good candidate. + assertContents(code, node.getFileLocation().getNodeOffset(), "method(int b)"); + } + + // class A { + // class B {}; + // }; + // + // B b; + public void testUnresolvedType() throws Exception { + String code= getContentsForTest(1)[0].toString(); + IFile file = importFile("testUndefinedType.cpp", code); + int offset= code.indexOf("B b;"); + IASTNode node= testF3(file, offset); + assertNull(node); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java index e0078d6cb52..879297b470a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsAction.java @@ -88,6 +88,9 @@ import org.eclipse.cdt.internal.ui.editor.CEditorMessages; import org.eclipse.cdt.internal.ui.text.CWordFinder; import org.eclipse.cdt.internal.ui.viewsupport.IndexUI; +/** + * Navigates to the definition of a name, or to the declaration if invoked on the definition. + */ public class OpenDeclarationsAction extends SelectionParseAction implements ASTRunnable { public static boolean sIsJUnitTest = false; @@ -185,38 +188,46 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR openInclude(((IASTPreprocessorIncludeStatement) parent)); return Status.OK_STATUS; } - IBinding binding = sourceName.resolveBinding(); NameKind kind = getNameKind(sourceName); - if (binding != null && !(binding instanceof IProblemBinding)) { - if (kind == NameKind.DEFINITION && binding instanceof IType) { - // Don't navigate away from a type definition. - // Select the name at the current location instead. - navigateToName(sourceName); - return Status.OK_STATUS; + IBinding b = sourceName.resolveBinding(); + IBinding[] bindings = new IBinding[] { b }; + if (b instanceof IProblemBinding) { + IBinding[] candidateBindings = ((IProblemBinding) b).getCandidateBindings(); + if (candidateBindings.length != 0) { + bindings = candidateBindings; } - IName[] declNames = findDeclNames(ast, kind, binding); - // Exclude the current location. - for (int i = 0; i < declNames.length; i++) { - if (isSameName(declNames[i], sourceName)) { - declNames[i] = null; - } else if (binding instanceof IParameter) { - if (!isInSameFunction(sourceName, declNames[i])) { - declNames[i] = null; - } - } else if (binding instanceof ICPPTemplateParameter) { - if (!isInSameTemplate(sourceName, declNames[i])) { + } else if (kind == NameKind.DEFINITION && b instanceof IType) { + // Don't navigate away from a type definition. + // Select the name at the current location instead. + navigateToName(sourceName); + return Status.OK_STATUS; + } + for (IBinding binding : bindings) { + if (binding != null && !(binding instanceof IProblemBinding)) { + IName[] declNames = findDeclNames(ast, kind, binding); + // Exclude the current location. + for (int i = 0; i < declNames.length; i++) { + if (isSameName(declNames[i], sourceName)) { declNames[i] = null; + } else if (binding instanceof IParameter) { + if (!isInSameFunction(sourceName, declNames[i])) { + declNames[i] = null; + } + } else if (binding instanceof ICPPTemplateParameter) { + if (!isInSameTemplate(sourceName, declNames[i])) { + declNames[i] = null; + } } } - } - declNames = (IName[]) ArrayUtil.removeNulls(IName.class, declNames); + declNames = (IName[]) ArrayUtil.removeNulls(IName.class, declNames); - if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, declNames)) { - found= true; - } else { - // Leave old method as fallback for local variables, parameters and - // everything else not covered by ICElementHandle. - found = navigateOneLocation(declNames); + if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, declNames)) { + found= true; + } else { + // Leave old method as fallback for local variables, parameters and + // everything else not covered by ICElementHandle. + found = navigateOneLocation(declNames); + } } } if (!found && !navigationFallBack(ast, sourceName, kind)) { @@ -372,10 +383,10 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR continue; } IName[] names = findNames(fIndex, ast, kind, binding); - // Exclude the current location. + // Exclude names of the same kind. for (int i = 0; i < names.length; i++) { if (getNameKind(names[i]) == kind) { - names[i] = null; // Don' navigate to a name of the same kind. + names[i] = null; } } names = (IName[]) ArrayUtil.removeNulls(IName.class, names);