From 8e855d931c2af0dcc6e4af20ba79d3f64906903e Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Mon, 20 Jul 2009 09:48:58 +0000 Subject: [PATCH] Further disambiguation of bindings from index, bug 268704. --- .../internal/index/tests/IndexBugsTests.java | 37 +++++++++- .../parser/cpp/semantics/CPPSemantics.java | 70 ++++++++++++++++--- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 8bfe8fb40b9..ac9f1e5c402 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -1866,8 +1866,7 @@ public class IndexBugsTests extends BaseTestCase { IName[] decls= ast.getDeclarations(var); assertEquals(2, decls.length); int check= 0; - for (int i = 0; i < decls.length; i++) { - IName name = decls[i]; + for (IName name : decls) { assert name instanceof IIndexName; IIndexName iName= (IIndexName) name; if (iName.getFileLocation().getFileName().endsWith("a.h")) { @@ -1976,6 +1975,40 @@ public class IndexBugsTests extends BaseTestCase { } } + // // a.h + // int xx; + + // #include "a.h" + // int yy= xx; + + // // b.h + // int xx(); + + // #include "b.h" + // void test() { + // xx(); + // } + public void testDisambiguationByReachability_268704_3() throws Exception { + String[] testData = getContentsForTest(4); + TestSourceReader.createFile(fCProject.getProject(), "a.h", testData[0]); + IFile a = TestSourceReader.createFile(fCProject.getProject(), "a.cpp", testData[1]); + TestSourceReader.createFile(fCProject.getProject(), "b.h", testData[2]); + IFile b = TestSourceReader.createFile(fCProject.getProject(), "b.cpp", testData[3]); + final IIndexManager indexManager = CCorePlugin.getIndexManager(); + indexManager.reindex(fCProject); + waitForIndexer(); + IIndex index= indexManager.getIndex(fCProject); + index.acquireReadLock(); + try { + BindingAssertionHelper aHelper = new BindingAssertionHelper(a, testData[1], index); + IVariable b1 = aHelper.assertNonProblem("xx;", 2, IVariable.class); + BindingAssertionHelper bHelper = new BindingAssertionHelper(b, testData[3], index); + IFunction f = bHelper.assertNonProblem("xx();", 2, IFunction.class); + } finally { + index.releaseReadLock(); + } + } + // // header.h // template // struct A { 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 e8aa96a2aba..370f6c8c4eb 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 @@ -1928,17 +1928,24 @@ public class CPPSemantics { } } if (data.forUsingDeclaration()) { - IBinding[] bindings = null; + int cmp= -1; if (obj != null) { + cmp= 1; if (fns.size() > 0) { - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, - data.getFoundBindings()); + IFunction[] fnArray= fns.keyArray(IFunction.class); + cmp= compareByRelevance(data, obj, fnArray); + if (cmp == 0) { + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); + } } -// if (type == null) return obj; + } + + IBinding[] bindings = null; + if (cmp > 0) { bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, obj); bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type); } else { -// if (fns == null) return type; bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type); bindings = (IBinding[]) ArrayUtil.addAll(IBinding.class, bindings, fns.keyArray()); } @@ -1955,13 +1962,18 @@ public class CPPSemantics { return null; } - int numFns = fns.size(); - if (numFns > 0) { + if (fns.size() > 0) { + final IFunction[] fnArray = fns.keyArray(IFunction.class); if (obj != null) { - return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, - data.getFoundBindings()); + int cmp= compareByRelevance(data, obj, fnArray); + if (cmp == 0) { + return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + data.getFoundBindings()); + } + if (cmp > 0) + return obj; } - return resolveFunction(data, fns.keyArray(IFunction.class), true); + return resolveFunction(data, fnArray, true); } if (obj != null) { @@ -2000,6 +2012,44 @@ public class CPPSemantics { return 0; } + /** + * Compares a binding with a list of function candidates for relevance in the context of an AST. AST bindings are + * considered more relevant than index ones since the index may be out of date, + * built for a different configuration, etc. Index bindings reachable through includes + * are more relevant than unreachable ones. + * @return 1 if binding obj is more relevant than the function candidates; 0 if + * the they have the same relevance; -1 if obj is less relevant than + * the function candidates. + */ + static int compareByRelevance(LookupData data, IBinding obj, IFunction[] fns) { + if (isFromIndex(obj)) { + for (int i = 0; i < fns.length; i++) { + if (!isFromIndex(fns[i])) { + return -1; // function from ast + } + } + // everything is from the index + if (!isReachableFromAst(data.tu, obj)) { + return -1; // obj not reachable + } + + for (IFunction fn : fns) { + if (isReachableFromAst(data.tu, fn)) { + return 0; // obj reachable, 1 function reachable + } + } + return 1; // no function is reachable + } + + // obj is not from the index + for (int i = 0; i < fns.length; i++) { + if (!isFromIndex(fns[i])) { + return 0; // obj and function from ast + } + } + return 1; // only obj is from ast. + } + private static boolean isFromIndex(IBinding binding) { if (binding instanceof IIndexBinding) { return true;