From de527bb7cdf6a0edffbd2aaede9221a600d753eb Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 6 Sep 2006 07:56:18 +0000 Subject: [PATCH] Additional test cases for Call Hierarchy --- .../eclipse/cdt/ui/tests/BaseTestCase.java | 7 + .../callhierarchy/BasicCallHierarchyTest.java | 332 ++++++++++++++++++ .../callhierarchy/CallHierarchyBaseTest.java | 9 +- .../callhierarchy/CallHierarchyTestSuite.java | 8 +- .../OpenCallHierarchyFromEditorTest.java | 111 ------ .../internal/ui/missingapi/CIndexQueries.java | 279 ++++++++------- 6 files changed, 509 insertions(+), 237 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCallHierarchyTest.java delete mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/OpenCallHierarchyFromEditorTest.java diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseTestCase.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseTestCase.java index 2e7fe330225..489de45f6ed 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseTestCase.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseTestCase.java @@ -29,7 +29,14 @@ import org.eclipse.core.runtime.Path; import org.eclipse.cdt.ui.testplugin.CTestPlugin; public class BaseTestCase extends TestCase { + public BaseTestCase() { + super(); + } + public BaseTestCase(String name) { + super(name); + } + /** * Reads a section in comments form the source of the given class. The section * is started with '// {tag}' and ends with the first line not started by '//' diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCallHierarchyTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCallHierarchyTest.java new file mode 100644 index 00000000000..789241753d6 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/BasicCallHierarchyTest.java @@ -0,0 +1,332 @@ +/******************************************************************************* + * Copyright (c) 2006 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.ui.tests.callhierarchy; + +import java.io.IOException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; + + +import org.eclipse.cdt.internal.ui.editor.CEditor; + + +public class BasicCallHierarchyTest extends CallHierarchyBaseTest { + + private static final int EVENT_QUEUE_MILLIS = 100; + + public BasicCallHierarchyTest(String name) { + super(name); + } + + public void testFunctionsC() throws Exception { + doTestFunctions("functions.c"); + } + + public void testFunctionsCpp() throws Exception { + doTestFunctions("functions.cpp"); + } + + // {testFunctions} + // void proto(); + // void func() { + // }; + // void main() { + // proto(); //ref + // func(); //ref + // }; + private void doTestFunctions(String filename) throws IOException, Exception, PartInitException { + String content = readTaggedComment("testFunctions"); + IFile file= createFile(getProject(), filename, content); + waitForIndexer(file, 1000); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + CEditor editor= (CEditor) IDE.openEditor(page, file); + + editor.selectAndReveal(content.indexOf("proto"), 5); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + Tree tree = getCHTree(page); + checkTreeNode(tree, 0, "proto()"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("func"), 2); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "func()"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("proto(); //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "proto()"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("func(); //ref"), 7); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "func()"); + checkTreeNode(tree, 0, 0, "main()"); + } + + public void testVariablesC() throws Exception { + doTestVariables("variables.c"); + } + + public void testVariablesCpp() throws Exception { + doTestVariables("variables.cpp"); + } + + // {testVariables} + // extern int extern_var; + // int global_var= 0; + // void main() { + // int i= extern_var; //ref + // i= global_var; //ref + // }; + private void doTestVariables(String filename) throws Exception { + String content = readTaggedComment("testVariables"); + IFile file= createFile(getProject(), filename, content); + waitForIndexer(file, 1000); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + CEditor editor= (CEditor) IDE.openEditor(page, file); + + editor.selectAndReveal(content.indexOf("extern_var"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + Tree tree = getCHTree(page); + checkTreeNode(tree, 0, "extern_var"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("global_var"), 2); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "global_var"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("extern_var; //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "extern_var"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("global_var; //ref"), 7); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "global_var"); + checkTreeNode(tree, 0, 0, "main()"); + } + + public void testEnumeratorC() throws Exception { + doTestEnumerator("enumerator.c", "testEnumerator"); + } + + public void testEnumeratorCpp() throws Exception { + doTestEnumerator("enumerator.cpp", "testEnumerator"); + } + + public void failing_testAnonymousEnumeratorC() throws Exception { + doTestEnumerator("enumerator.c", "testAnonymousEnumerator"); + } + + public void failing_testAnonymousEnumeratorCpp() throws Exception { + doTestEnumerator("enumerator.cpp", "testAnonymousEnumerator"); + } + + // {testEnumerator} + // enum Enum {enumerator=12}; + // void main() { + // int i= enumerator; //ref + // }; + + // {testAnonymousEnumerator} + // enum {enumerator}; + // void main() { + // int i= enumerator; //ref + // }; + private void doTestEnumerator(String filename, String contentTag) throws Exception { + String content = readTaggedComment(contentTag); + IFile file= createFile(getProject(), filename, content); + waitForIndexer(file, 1000); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + CEditor editor= (CEditor) IDE.openEditor(page, file); + + editor.selectAndReveal(content.indexOf("enumerator"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + Tree tree = getCHTree(page); + checkTreeNode(tree, 0, "enumerator"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("main"), 2); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "main()"); + + editor.selectAndReveal(content.indexOf("enumerator; //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "enumerator"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("main"), 2); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "main()"); + } + + public void testStructMembersC() throws Exception { + doTestStructMembers("struct_member.c"); + } + + public void testStructMembersCpp() throws Exception { + doTestStructMembers("struct_member.cpp"); + } + + // {testStructMembers} + // struct s1 { + // int mem1; + // }; + // typedef struct s2 { + // int mem2; + // } t2; + // typedef struct { + // int mem3; + // } t3; + // struct s4 { + // struct { + // int mem5; + // } mem4; + // }; + // + // void main() { + // struct s1 vs1; + // struct s2 vs2; + // struct s4 vs4; + // t2 vt2; + // t3 vt3; + // int i; + // i= vs1.mem1; //ref + // i= vs2.mem2; //ref + // i= vs4.mem4.mem5; //ref + // i= vt2.mem2; //ref + // i= vt3.mem3; //ref + // }; + private void doTestStructMembers(String filename) throws Exception { + String content = readTaggedComment("testStructMembers"); + IFile file= createFile(getProject(), filename, content); + waitForIndexer(file, 1000); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + CEditor editor= (CEditor) IDE.openEditor(page, file); + + editor.selectAndReveal(content.indexOf("mem1"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + Tree tree = getCHTree(page); + checkTreeNode(tree, 0, "s1::mem1"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem2"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "s2::mem2"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem3"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "(anon)::mem3"); + + editor.selectAndReveal(content.indexOf("mem4"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "s4::mem4"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem5"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "s4::(anon)::mem5"); + + editor.selectAndReveal(content.indexOf("mem1; //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "s1::mem1"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem2; //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "s2::mem2"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem4."), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "s4::mem4"); + checkTreeNode(tree, 0, 0, "main()"); + } + + public void failing_testAnonymousStructMembersC() throws Exception { + doTestAnonymousStructMembers("anon_struct_member.c"); + } + + public void failing_testAnonymousStructMembersCpp() throws Exception { + doTestAnonymousStructMembers("anon_struct_member.cpp"); + } + + private void doTestAnonymousStructMembers(String filename) throws Exception { + String content = readTaggedComment("testStructMembers"); + IFile file= createFile(getProject(), filename, content); + waitForIndexer(file, 1000); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + CEditor editor= (CEditor) IDE.openEditor(page, file); + + editor.selectAndReveal(content.indexOf("mem3"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + Tree tree = getCHTree(page); + checkTreeNode(tree, 0, "(anon)::mem3"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem5"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + checkTreeNode(tree, 0, "s4::(anon)::mem5"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem3; //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "(anon)::mem3"); + checkTreeNode(tree, 0, 0, "main()"); + + editor.selectAndReveal(content.indexOf("mem5; //ref"), 0); + openCallHierarchy(editor); + runEventQueue(EVENT_QUEUE_MILLIS); + tree = getCHTree(page); + checkTreeNode(tree, 0, "s4::(anon)::mem5"); + checkTreeNode(tree, 0, 0, "main()"); + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBaseTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBaseTest.java index 2f751cb0280..7e0d4ccf4ea 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBaseTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBaseTest.java @@ -39,10 +39,15 @@ public class CallHierarchyBaseTest extends BaseTestCase { private ICProject fCProject; private PDOM fPdom; + public CallHierarchyBaseTest(String name) { + super(name); + } + protected void setUp() throws CoreException { fCProject= CProjectHelper.createCProject("__chTest__", "bin"); CCorePlugin.getPDOMManager().setIndexerId(fCProject, "org.eclipse.cdt.core.fastIndexer"); fPdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(fCProject); + fPdom.clear(); } protected void tearDown() throws CoreException { @@ -100,7 +105,7 @@ public class CallHierarchyBaseTest extends BaseTestCase { root= tree.getItem(i0); } catch (IllegalArgumentException e) { - assertTrue("Tree node " + i0 + " does not exist!", false); + assertTrue("Tree node " + label + "{" + i0 + "} does not exist!", false); } assertEquals(label, root.getText()); } @@ -112,7 +117,7 @@ public class CallHierarchyBaseTest extends BaseTestCase { item= root.getItem(i1); } catch (IllegalArgumentException e) { - assertTrue("Tree node " + i0 + "," + i1 + " does not exist!", false); + assertTrue("Tree node " + label + "{" + i0 + "," + i1 + "} does not exist!", false); } assertEquals(label, item.getText()); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyTestSuite.java index 09b53258ccd..7a7fe212b11 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyTestSuite.java @@ -13,6 +13,8 @@ package org.eclipse.cdt.ui.tests.callhierarchy; import junit.framework.TestSuite; +import org.eclipse.cdt.core.tests.FailingTest; + public class CallHierarchyTestSuite extends TestSuite { public static TestSuite suite() { @@ -21,6 +23,10 @@ public class CallHierarchyTestSuite extends TestSuite { public CallHierarchyTestSuite() { super("Tests in package org.eclipse.cdt.ui.tests.callhierarchy"); - addTestSuite(OpenCallHierarchyFromEditorTest.class); + addTestSuite(BasicCallHierarchyTest.class); + addTest(new FailingTest(new BasicCallHierarchyTest("failing_testAnonymousEnumeratorC")));; + addTest(new FailingTest(new BasicCallHierarchyTest("failing_testAnonymousEnumeratorCpp")));; + addTest(new FailingTest(new BasicCallHierarchyTest("failing_testAnonymousStructMembersC")));; + addTest(new FailingTest(new BasicCallHierarchyTest("failing_testAnonymousStructMembersCpp")));; } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/OpenCallHierarchyFromEditorTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/OpenCallHierarchyFromEditorTest.java deleted file mode 100644 index 759e231f52d..00000000000 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/OpenCallHierarchyFromEditorTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006 Wind River Systems, Inc. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Markus Schorn - initial API and implementation - *******************************************************************************/ - -package org.eclipse.cdt.ui.tests.callhierarchy; - -import org.eclipse.core.resources.IFile; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.ide.IDE; - - -import org.eclipse.cdt.internal.ui.editor.CEditor; - - -public class OpenCallHierarchyFromEditorTest extends CallHierarchyBaseTest { - - // {testFunctions} - // void proto(); - // void func() { - // }; - // void main() { - // proto(); //ref - // func(); //ref - // }; - public void testFunctions() throws Exception { - String content = readTaggedComment("testFunctions"); - IFile file= createFile(getProject(), "functions.c", content); - waitForIndexer(file, 1000); - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - CEditor editor= (CEditor) IDE.openEditor(page, file); - - editor.selectAndReveal(content.indexOf("proto"), 5); - openCallHierarchy(editor); - runEventQueue(100); - Tree tree = getCHTree(page); - checkTreeNode(tree, 0, "proto()"); - checkTreeNode(tree, 0, 0, "main()"); - - editor.selectAndReveal(content.indexOf("func"), 2); - openCallHierarchy(editor); - runEventQueue(100); - checkTreeNode(tree, 0, "func()"); - checkTreeNode(tree, 0, 0, "main()"); - - editor.selectAndReveal(content.indexOf("proto(); //ref"), 0); - openCallHierarchy(editor); - runEventQueue(100); - tree = getCHTree(page); - checkTreeNode(tree, 0, "proto()"); - checkTreeNode(tree, 0, 0, "main()"); - - editor.selectAndReveal(content.indexOf("func(); //ref"), 7); - openCallHierarchy(editor); - runEventQueue(100); - tree = getCHTree(page); - checkTreeNode(tree, 0, "func()"); - checkTreeNode(tree, 0, 0, "main()"); - } - - // {testVariables} - // extern int extern_var; - // int global_var= 0; - // void main() { - // int i= extern_var; //ref - // i= global_var; //ref - // }; - public void testVariables() throws Exception { - String content = readTaggedComment("testVariables"); - IFile file= createFile(getProject(), "variables.c", content); - waitForIndexer(file, 1000); - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - CEditor editor= (CEditor) IDE.openEditor(page, file); - - editor.selectAndReveal(content.indexOf("extern_var"), 0); - openCallHierarchy(editor); - runEventQueue(100); - Tree tree = getCHTree(page); - checkTreeNode(tree, 0, "extern_var"); - checkTreeNode(tree, 0, 0, "main()"); - - editor.selectAndReveal(content.indexOf("global_var"), 2); - openCallHierarchy(editor); - runEventQueue(100); - checkTreeNode(tree, 0, "global_var"); - checkTreeNode(tree, 0, 0, "main()"); - - editor.selectAndReveal(content.indexOf("extern_var; //ref"), 0); - openCallHierarchy(editor); - runEventQueue(100); - tree = getCHTree(page); - checkTreeNode(tree, 0, "extern_var"); - checkTreeNode(tree, 0, 0, "main()"); - - editor.selectAndReveal(content.indexOf("global_var; //ref"), 7); - openCallHierarchy(editor); - runEventQueue(100); - tree = getCHTree(page); - checkTreeNode(tree, 0, "global_var"); - checkTreeNode(tree, 0, 0, "main()"); - } - -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/missingapi/CIndexQueries.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/missingapi/CIndexQueries.java index 2205223620b..f0cbc288116 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/missingapi/CIndexQueries.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/missingapi/CIndexQueries.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; @@ -26,6 +27,7 @@ import org.eclipse.jface.text.Region; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.IPositionConverter; +import org.eclipse.cdt.core.dom.IPDOM; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; @@ -53,7 +55,8 @@ import org.eclipse.cdt.internal.corext.util.CModelUtil; * @since 4.0 */ public class CIndexQueries { - private static final ICElement[] EMPTY_ELEMENTS = new ICElement[0]; + private static final int ASTTU_OPTIONS = ILanguage.AST_SKIP_ALL_HEADERS | ILanguage.AST_USE_INDEX; + private static final ICElement[] EMPTY_ELEMENTS = new ICElement[0]; private static final CIndexIncludeRelation[] EMPTY_INCLUDES = new CIndexIncludeRelation[0]; private static final CIndexQueries sInstance= new CIndexQueries(); @@ -192,53 +195,52 @@ public class CIndexQueries { * @since 4.0 */ public CalledByResult findCalledBy(ICProject[] scope, ICElement callee, IProgressMonitor pm) { - IASTName name= astNameForElement(callee); - CalledByResult result= new CalledByResult(); - if (name != null) { - // resolve the binding. - name.resolveBinding(); - + try { + findCalledBy(scope, callee, pm, result); + } + catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + catch (InterruptedException e) { + } + return result; + } + + private void findCalledBy(ICProject[] scope, ICElement callee, IProgressMonitor pm, CalledByResult result) + throws CoreException, InterruptedException { + if (! (callee instanceof ISourceReference)) { + return; + } + ISourceReference sf= (ISourceReference) callee; + ISourceRange range; + range = sf.getSourceRange(); + ITranslationUnit tu= sf.getTranslationUnit(); + IPDOM pdom= CCorePlugin.getPDOMManager().getPDOM(tu.getCProject()); + if (pdom != null) { + pdom.acquireReadLock(); + } + try { + ILanguage language = tu.getLanguage(); + IASTTranslationUnit ast= language.getASTTranslationUnit(tu, ASTTU_OPTIONS); + if (ast == null) { + return; + } + IASTName[] names = language.getSelectedNames(ast, range.getIdStartPos(), range.getIdLength()); + if (names == null || names.length == 0) { + return; + } + IASTName name= names[names.length-1]; for (int i = 0; i < scope.length; i++) { ICProject project = scope[i]; findCalledBy(name, project, result); } } - return result; - } - - private IASTName astNameForElement(ICElement elem) { - try { - if (elem instanceof ISourceReference) { - ISourceReference sf= (ISourceReference) elem; - ISourceRange range= sf.getSourceRange(); - ITranslationUnit tu= sf.getTranslationUnit(); - IASTTranslationUnit ast= astUnitForTU(tu); - if (ast != null) { - ILanguage language = tu.getLanguage(); - IASTName[] names = language.getSelectedNames(ast, range.getIdStartPos(), range.getIdLength()); - if (names.length > 0) { - return names[names.length-1]; - } - return null; - } + finally { + if (pdom != null) { + pdom.releaseReadLock(); } - } catch (CoreException e) { - CUIPlugin.getDefault().log(e); } - return null; - } - - private IASTTranslationUnit astUnitForTU(ITranslationUnit tu) { - try { - if (tu != null) { - ILanguage language = tu.getLanguage(); - return language.getASTTranslationUnit(tu, ILanguage.AST_SKIP_ALL_HEADERS | ILanguage.AST_USE_INDEX); - } - } catch (CoreException e) { - CUIPlugin.getDefault().log(e); - } - return null; } private void findCalledBy(IASTName name, ICProject project, CalledByResult result) { @@ -252,7 +254,7 @@ public class CIndexQueries { IASTName[] names= pdom.getReferences(binding); for (int i = 0; i < names.length; i++) { IASTName rname = names[i]; - ITranslationUnit tu= toTranslationUnit(project, rname); + ITranslationUnit tu= getTranslationUnit(project, rname); CIndexReference ref= new CIndexReference(tu, rname); ICElement elem = findCalledBy(ref); if (elem != null) { @@ -271,6 +273,20 @@ public class CIndexQueries { } } + private IBinding getPDOMBinding(PDOM pdom, IASTName name) { + IBinding binding= name.resolveBinding(); + IASTTranslationUnit tu= name.getTranslationUnit(); + ILanguage lang= tu.getLanguage(); + PDOMLinkage linkage; + try { + linkage = pdom.getLinkage(lang); + return linkage.adaptBinding(binding); + } catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + return null; + } + private ICElement findCalledBy(CIndexReference reference) { ITranslationUnit tu= reference.getTranslationUnit(); long timestamp= reference.getTimestamp(); @@ -306,41 +322,8 @@ public class CIndexQueries { return null; } - private ICElement findCElementForDeclaration(ICElement element, int offset, int length) { - int endoffset= offset+length; - if (element == null) { - return null; - } - try { - if (element instanceof IParent) { - ICElement[] children= ((IParent) element).getChildren(); - for (int i = 0; i < children.length; i++) { - ICElement child = children[i]; - if (child instanceof ISourceReference) { - ISourceRange sr= ((ISourceReference) child).getSourceRange(); - int offset2= sr.getIdStartPos(); - int endoffset2= offset2+sr.getIdLength(); - if (offset <= offset2 && endoffset2 <= endoffset) { - return child; - } - offset2= sr.getStartPos(); - endoffset2= offset2+sr.getLength(); - if (offset2 <= offset && endoffset <= endoffset2) { - ICElement result= findCElementForDeclaration(child, offset, length); - if (result != null) { - return result; - } - } - } - } - } - } catch (CModelException e) { - CUIPlugin.getDefault().log(e); - } - return null; - } - private ITranslationUnit toTranslationUnit(ICProject cproject, IASTName name) { + private ITranslationUnit getTranslationUnit(ICProject cproject, IASTName name) { IPath path= Path.fromOSString(name.getFileLocation().getFileName()); try { return CModelUtil.findTranslationUnitForLocation(path, cproject); @@ -361,32 +344,55 @@ public class CIndexQueries { */ public CallsToResult findCallsInRange(ICProject[] scope, ITranslationUnit tu, IRegion range, IProgressMonitor pm) { CallsToResult result= new CallsToResult(); - IASTTranslationUnit astTU= astUnitForTU(tu); - if (astTU != null) { - ReferenceVisitor refVisitor= new ReferenceVisitor(astTU.getFilePath(), range.getOffset(), range.getLength()); - astTU.accept(refVisitor); - - IASTName[] refs = refVisitor.getReferences(); - for (int i = 0; i < refs.length; i++) { - IASTName name = refs[i]; - ICElement[] defs = findAllDefinitions(scope, name); - if (defs.length == 0) { - ICElement elem = findAnyDeclaration(scope, name); - if (elem != null) { - defs = new ICElement[] { elem }; - } - } - if (defs != null && defs.length > 0) { - CIndexReference ref = new CIndexReference(tu, name); - result.add(defs, ref); - } - } + try { + findCallsInRange(scope, tu, range, pm, result); + } + catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + catch (InterruptedException e) { } return result; } + private void findCallsInRange(ICProject[] scope, ITranslationUnit tu, IRegion range, IProgressMonitor pm, CallsToResult result) + throws CoreException, InterruptedException { + IPDOM pdom= CCorePlugin.getPDOMManager().getPDOM(tu.getCProject()); + if (pdom != null) { + pdom.acquireReadLock(); + } + try { + ILanguage language = tu.getLanguage(); + IASTTranslationUnit astTU= language.getASTTranslationUnit(tu, ASTTU_OPTIONS); + if (astTU != null) { + ReferenceVisitor refVisitor= new ReferenceVisitor(astTU.getFilePath(), range.getOffset(), range.getLength()); + astTU.accept(refVisitor); + + IASTName[] refs = refVisitor.getReferences(); + for (int i = 0; i < refs.length; i++) { + IASTName name = refs[i]; + ICElement[] defs = findAllDefinitions(scope, name); + if (defs.length == 0) { + ICElement elem = findAnyDeclaration(scope, name); + if (elem != null) { + defs = new ICElement[] { elem }; + } + } + if (defs != null && defs.length > 0) { + CIndexReference ref = new CIndexReference(tu, name); + result.add(defs, ref); + } + } + } + } + finally { + if (pdom != null) { + pdom.releaseReadLock(); + } + } + } + public ICElement[] findAllDefinitions(ICProject[] projectsToSearch, IASTName name) { - name.resolveBinding(); ArrayList result= new ArrayList(); for (int i = 0; i < projectsToSearch.length; i++) { ICProject project = projectsToSearch[i]; @@ -407,7 +413,7 @@ public class CIndexQueries { try { IBinding binding= getPDOMBinding(pdom, name); if (binding != null) { - return allEnclosingElements(project, pdom.getDefinitions(binding)); + return getCElementsForNames(project, pdom.getDefinitions(binding)); } } finally { @@ -422,26 +428,13 @@ public class CIndexQueries { return EMPTY_ELEMENTS; } - private IBinding getPDOMBinding(PDOM pdom, IASTName name) { - IBinding binding= name.resolveBinding(); - IASTTranslationUnit tu= name.getTranslationUnit(); - ILanguage lang= tu.getLanguage(); - PDOMLinkage linkage; - try { - linkage = pdom.getLinkage(lang); - return linkage.adaptBinding(binding); - } catch (CoreException e) { - CUIPlugin.getDefault().log(e); - } - return null; - } - - private ICElement[] allEnclosingElements(ICProject project, IASTName[] defs) { + private ICElement[] getCElementsForNames(ICProject project, IASTName[] defs) { if (defs != null && defs.length > 0) { - ArrayList result= new ArrayList(defs.length); + HashSet result= new HashSet(defs.length); for (int i = 0; i < defs.length; i++) { IASTName defName = defs[i]; - ICElement elem= findCElementForDeclaration(project, defName); + assert !defName.isReference(); + ICElement elem= getCElementForName(project, defName); if (elem != null) { result.add(elem); } @@ -451,8 +444,9 @@ public class CIndexQueries { return EMPTY_ELEMENTS; } - private ICElement findCElementForDeclaration(ICProject project, IASTName declName) { - ITranslationUnit tu= toTranslationUnit(project, declName); + private ICElement getCElementForName(ICProject project, IASTName declName) { + assert !declName.isReference(); + ITranslationUnit tu= getTranslationUnit(project, declName); if (tu != null) { IRegion region= null; if (declName instanceof PDOMName) { @@ -470,11 +464,50 @@ public class CIndexQueries { IASTFileLocation loc= declName.getFileLocation(); region= new Region(loc.getNodeOffset(), loc.getNodeLength()); } - return findCElementForDeclaration(tu, region.getOffset(), region.getLength()); + return getCElementWithRangeOfID(tu, region.getOffset(), region.getLength()); } return null; } + private ICElement getCElementWithRangeOfID(ICElement element, int offset, int length) { + if (element == null) { + return null; + } + try { + if (element instanceof IParent) { + ICElement[] children= ((IParent) element).getChildren(); + for (int i = 0; i < children.length; i++) { + ICElement child = children[i]; + if (child instanceof ISourceReference) { + ISourceRange sr= ((ISourceReference) child).getSourceRange(); + if (surrounds(offset, length, sr.getIdStartPos(), sr.getIdLength())) { + return child; + } + int childOffset= sr.getStartPos(); + if (childOffset > offset) { + return null; + } + if (surrounds(childOffset, sr.getLength(), offset, length)) { + ICElement result= getCElementWithRangeOfID(child, offset, length); + if (result != null) { + return result; + } + } + } + } + } + } catch (CModelException e) { + CUIPlugin.getDefault().log(e); + } + return null; + } + + private boolean surrounds(int offset1, int length1, int offset2, int length2) { + int deltaOffset= offset2-offset1; + int deltaEndoffset= deltaOffset + length2 - length1; + return deltaOffset >= 0 && deltaEndoffset <= 0; + } + public ICElement findDefinition(ICProject[] projectsToSearch, IASTName name) { name.resolveBinding(); @@ -490,7 +523,7 @@ public class CIndexQueries { public ICElement findDefinition(ICProject project, IASTName name) { if (name.isDefinition()) { - return findCElementForDeclaration(project, name); + return getCElementForName(project, name); } PDOM pdom; @@ -501,7 +534,7 @@ public class CIndexQueries { try { IBinding binding= getPDOMBinding(pdom, name); if (binding != null) { - ICElement elem= firstEnclosingElement(project, pdom.getDefinitions(binding)); + ICElement elem= getFirstCElementForNames(project, pdom.getDefinitions(binding)); if (elem != null) { return elem; } @@ -519,11 +552,11 @@ public class CIndexQueries { return null; } - private ICElement firstEnclosingElement(ICProject project, IASTName[] defs) { + private ICElement getFirstCElementForNames(ICProject project, IASTName[] defs) { if (defs != null) { for (int i = 0; i < defs.length; i++) { IASTName defName = defs[i]; - ICElement elem= findCElementForDeclaration(project, defName); + ICElement elem= getCElementForName(project, defName); if (elem != null) { return elem; } @@ -554,11 +587,11 @@ public class CIndexQueries { try { IBinding binding= getPDOMBinding(pdom, name); if (binding != null) { - ICElement elem= firstEnclosingElement(project, pdom.getDefinitions(binding)); + ICElement elem= getFirstCElementForNames(project, pdom.getDefinitions(binding)); if (elem != null) { return elem; } - elem= firstEnclosingElement(project, pdom.getDeclarations(binding)); + elem= getFirstCElementForNames(project, pdom.getDeclarations(binding)); if (elem != null) { return elem; }