From b1441db5aaa26424472cf7b3bd04ccba7f1feef4 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 24 Jul 2009 12:37:33 +0000 Subject: Improves navigation of unknown bindings, bug 233822. --- .../dom/parser/cpp/semantics/CPPSemantics.java | 2 +- .../text/selection/CPPSelectionTestsNoIndexer.java | 15 ++++ .../ui/search/actions/OpenDeclarationsJob.java | 99 +++++++++++++++++----- 3 files changed, 96 insertions(+), 20 deletions(-) (limited to 'core') 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 24fc887d7e3..c7320e211da 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 @@ -464,7 +464,7 @@ public class CPPSemantics { return binding; } - private static LookupData createLookupData(IASTName name, boolean considerAssociatedScopes) { + public static LookupData createLookupData(IASTName name, boolean considerAssociatedScopes) { LookupData data = new LookupData(name); IASTNode parent = name.getParent(); 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 028bdae3437..19fd22dacf1 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 @@ -1125,4 +1125,19 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { IASTNode node= testF3(file, offset); assertContents(code, node.getFileLocation().getNodeOffset(), "func(T a, T b)"); } + + // template void func(T a){} + // template void func(T a, T b){} + // + // template void testFunc() { + // Tmp val; + // func(val, val); // F3 could know that 'func(T a)' cannot be a correct match. + // } + public void testDependentNameTwoChoices_281736() throws Exception { + String code= getContentsForTest(1)[0].toString(); + IFile file = importFile("testDependentNameTwoChoices_281736.cpp", code); + int offset= code.indexOf("func(val, val);"); + IASTNode node= testF3(file, offset); + assertContents(code, node.getFileLocation().getNodeOffset(), "func(T a, T b)"); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java index 3a82d4e79fc..ddc1cf5d583 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.internal.ui.search.actions; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -49,7 +50,9 @@ import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; @@ -70,7 +73,10 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData; import org.eclipse.cdt.internal.core.index.IIndexFragmentName; import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable; import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory; @@ -551,7 +557,7 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { List elems= new ArrayList(); // bug 252549, search for names in the AST first - Set bindings= new HashSet(); + Set primaryBindings= new HashSet(); Set ignoreIndexBindings= new HashSet(); ASTNameCollector nc= new ASTNameCollector(fSelectedText); ast.accept(nc); @@ -560,7 +566,7 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { try { IBinding b= astName.resolveBinding(); if (b != null && !(b instanceof IProblemBinding)) { - if (bindings.add(b)) { + if (primaryBindings.add(b)) { ignoreIndexBindings.add(fIndex.adaptBinding(b)); } } @@ -574,7 +580,7 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { final IIndexBinding[] idxBindings = fIndex.findBindings(name, false, filter, fMonitor); for (IIndexBinding idxBinding : idxBindings) { if (!ignoreIndexBindings.contains(idxBinding)) { - bindings.add(idxBinding); + primaryBindings.add(idxBinding); } } @@ -587,25 +593,26 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { } } - String[] sourceQualifiedName= sourceName != null ? - CPPVisitor.getQualifiedName(sourceName.resolveBinding()) : - new String[] { fSelectedText }; + Collection secondaryBindings= removeSecondaryBindings(primaryBindings, sourceName); // Convert bindings to CElements - for (IBinding binding : bindings) { - String[] qualifiedName = CPPVisitor.getQualifiedName(binding); - if (!Arrays.equals(qualifiedName, sourceQualifiedName)) { - continue; - } - IName[] names = findNames(fIndex, ast, kind, binding); - // Exclude names of the same kind. - for (int i = 0; i < names.length; i++) { - if (getNameKind(names[i]) == kind) { - names[i] = null; + Collection bs= primaryBindings; + for (int k=0; k<2; k++) { + for (IBinding binding : bs) { + IName[] names = findNames(fIndex, ast, kind, binding); + // Exclude names of the same kind. + for (int i = 0; i < names.length; i++) { + if (getNameKind(names[i]) == kind) { + names[i] = null; + } } + names = (IName[]) ArrayUtil.removeNulls(IName.class, names); + convertToCElements(project, fIndex, names, elems); } - names = (IName[]) ArrayUtil.removeNulls(IName.class, names); - convertToCElements(project, fIndex, names, elems); - } + // in case we did not find anything, consider the secondary bindings + if (!elems.isEmpty()) + break; + bs= secondaryBindings; + } if (navigateCElements(elems)) { return true; } @@ -619,4 +626,58 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { } return false; } + + private Collection removeSecondaryBindings(Set primaryBindings, IASTName sourceName) { + List result= new ArrayList(); + String[] sourceQualifiedName= null; + int funcArgCount= -1; + if (sourceName != null) { + sourceQualifiedName= CPPVisitor.getQualifiedName(sourceName.resolveBinding()); + if (sourceName.resolveBinding() instanceof ICPPUnknownBinding) { + LookupData data= CPPSemantics.createLookupData(sourceName, false); + if (data.functionCall()) { + funcArgCount= data.getFunctionArgumentCount(); + } + } + } + + for (Iterator iterator = primaryBindings.iterator(); iterator.hasNext();) { + IBinding binding = iterator.next(); + if (sourceQualifiedName != null) { + String[] qualifiedName = CPPVisitor.getQualifiedName(binding); + if (!Arrays.equals(qualifiedName, sourceQualifiedName)) { + iterator.remove(); + continue; + } + } + if (funcArgCount != -1) { + // for c++ we can check the number of parameters + if (binding instanceof ICPPFunction) { + ICPPFunction f= (ICPPFunction) binding; + try { + IParameter[] pars= f.getParameters(); + if (pars.length < funcArgCount) { + if (!f.takesVarArgs()) { + iterator.remove(); + result.add(binding); + continue; + } + } else if (pars.length > funcArgCount) { + IParameter p= pars[funcArgCount]; + if (!(p instanceof ICPPParameter) || !((ICPPParameter) p).hasDefaultValue()) { + iterator.remove(); + result.add(binding); + continue; + } + } + } catch (DOMException e) { + // ignore problem bindings + continue; + } + } + } + } + + return result; + } } \ No newline at end of file -- cgit v1.2.3