From e655142a3a003fb0ce07d83d35b5dc35af9e1918 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 10 May 2007 14:23:59 +0000 Subject: [PATCH] Test-cases and follow-up for 183941, call hierarchy opened with declaration. --- .../eclipse/cdt/ui/tests/BaseUITestCase.java | 91 +++++++++++- .../callhierarchy/CallHierarchyBaseTest.java | 58 ++++---- .../callhierarchy/CallHierarchyBugs.java | 135 ++++++++++++++++++ .../callhierarchy/CallHierarchyTestSuite.java | 3 +- .../IncludeBrowserBaseTest.java | 10 +- .../typehierarchy/TypeHierarchyBaseTest.java | 10 +- .../ui/callhierarchy/CallHierarchyUI.java | 33 +++-- 7 files changed, 287 insertions(+), 53 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseUITestCase.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseUITestCase.java index 72fa12acb7e..c53162254ed 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseUITestCase.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/BaseUITestCase.java @@ -12,19 +12,28 @@ package org.eclipse.cdt.ui.tests; import java.io.IOException; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.NotEnabledException; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.commands.common.NotDefinedException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; @@ -94,16 +103,38 @@ public class BaseUITestCase extends BaseTestCase { } protected void runEventQueue(int time) { - long endTime= System.currentTimeMillis()+time; - do { + final long endTime= System.currentTimeMillis()+time; + while(true) { while (Display.getCurrent().readAndDispatch()); + long diff= endTime-System.currentTimeMillis(); + if (diff <= 0) { + break; + } try { - Thread.sleep(20); + Thread.sleep(Math.min(20, diff)); } catch (InterruptedException e) { return; } } - while(System.currentTimeMillis() < endTime); + } + + protected void expandTreeItem(Tree tree, int idx) { + expandTreeItem(tree, new int[] {idx}); + } + + protected void expandTreeItem(Tree tree, int idx1, int idx2) { + expandTreeItem(tree, new int[] {idx1, idx2}); + } + + protected void expandTreeItem(Tree tree, int[] idxs) { + TreeItem item= tree.getItem(idxs[0]); + assertNotNull(item); + expandTreeItem(item); + for (int i=1; i < idxs.length; i++) { + item= item.getItem(idxs[i]); + assertNotNull(item); + expandTreeItem(item); + } } protected void expandTreeItem(TreeItem item) { @@ -114,6 +145,28 @@ public class BaseUITestCase extends BaseTestCase { runEventQueue(0); } + protected void selectTreeItem(Tree tree, int idx) { + selectTreeItem(tree, new int[] {idx}); + } + + protected void selectTreeItem(Tree tree, int idx1, int idx2) { + selectTreeItem(tree, new int[] {idx1, idx2}); + } + + protected void selectTreeItem(Tree tree, int[] idxs) { + TreeItem item= tree.getItem(idxs[0]); + assertNotNull(item); + for (int i=1; i < idxs.length; i++) { + item= item.getItem(idxs[i]); + assertNotNull(item); + } + tree.setSelection(item); + Event event = new Event(); + event.item = item; + item.getParent().notifyListeners(SWT.Selection, event); + runEventQueue(0); + } + protected void closeEditor(IEditorPart editor) { IWorkbenchPartSite site; IWorkbenchPage page; @@ -132,4 +185,34 @@ public class BaseUITestCase extends BaseTestCase { } } } + + protected IViewPart activateView(String id) throws PartInitException { + IViewPart view= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(id); + assertNotNull(view); + runEventQueue(0); + return view; + } + + protected void executeCommand(IViewPart viewPart, String commandID) throws ExecutionException, NotDefinedException, NotEnabledException, NotHandledException { + IHandlerService hs= (IHandlerService)viewPart.getSite().getService(IHandlerService.class); + assertNotNull(hs); + hs.executeCommand(commandID, null); + } + + protected Control getFocusControl(Class clazz, int wait) { + return getFocusControl(clazz, null, wait); + } + + protected Control getFocusControl(Class clazz, Control differentTo, int wait) { + for (int i = 0; i <= wait/10; i++) { + Control fc= Display.getCurrent().getFocusControl(); + if (clazz.isInstance(fc) && fc != differentTo) { + return fc; + } + runEventQueue(10); + } + fail(); + return null; + } + } 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 b49f105c325..161cf205c9b 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 @@ -48,6 +48,7 @@ public class CallHierarchyBaseTest extends BaseUITestCase { protected void setUp() throws Exception { super.setUp(); + CallHierarchyUI.setIsJUnitTest(true); String prjName= "chTest"+sProjectCounter++; fCProject= CProjectHelper.createCCProject(prjName, "bin", IPDOMManager.ID_FAST_INDEXER); CCorePlugin.getIndexManager().joinIndexer(INDEXER_WAIT_TIME, NPM); @@ -73,7 +74,6 @@ public class CallHierarchyBaseTest extends BaseUITestCase { } protected void openCallHierarchy(CEditor editor) { - CallHierarchyUI.setIsJUnitTest(true); CallHierarchyUI.open(editor, (ITextSelection) editor.getSelectionProvider().getSelection()); } @@ -109,45 +109,47 @@ public class CallHierarchyBaseTest extends BaseUITestCase { protected TreeItem checkTreeNode(Tree tree, int i0, String label) { TreeItem root= null; - try { - for (int i=0; i<800; i++) { + for (int i=0; i<200; i++) { + try { root= tree.getItem(i0); - try { - if (label.equals(root.getText())) { - return root; - } - } catch (SWTException e) { - // in case widget was disposed, item may be replaced + if (label.equals(root.getText())) { + return root; } - runEventQueue(10); + } + catch (SWTException e) { + // in case widget was disposed, item may be replaced } + catch (IllegalArgumentException e) { + // item does not yet exist. + } + runEventQueue(10); } - catch (IllegalArgumentException e) { - fail("Tree node " + label + "{" + i0 + "} does not exist!"); - } + assertNotNull("Tree node " + label + "{" + i0 + "} does not exist!", root); assertEquals(label, root.getText()); return root; } protected TreeItem checkTreeNode(Tree tree, int i0, int i1, String label) { TreeItem item= null; - try { - TreeItem root= tree.getItem(i0); - for (int i=0; i<40; i++) { + TreeItem root= tree.getItem(i0); + for (int i=0; i<200; i++) { + try { item= root.getItem(i1); - try { - if (!"...".equals(item.getText())) { - break; - } - } catch (SWTException e) { - // in case widget was disposed, item may be replaced + if (!"...".equals(item.getText())) { + break; } - runEventQueue(50); + } catch (SWTException e) { + // in case widget was disposed, item may be replaced } + catch (IllegalArgumentException e) { + if (label == null) { + return null; + } + } + runEventQueue(10); } - catch (IllegalArgumentException e) { - fail("Tree node " + label + "{" + i0 + "," + i1 + "} does not exist!"); - } + assertNotNull("Tree node " + label + "{" + i0 + "," + i1 + "} does not exist!", item); + assertNotNull("Unexpected tree node " + item.getText(), label); assertEquals(label, item.getText()); return item; } @@ -155,7 +157,7 @@ public class CallHierarchyBaseTest extends BaseUITestCase { protected TreeItem checkTreeNode(TreeItem root, int i1, String label) { TreeItem item= null; try { - for (int i=0; i<40; i++) { + for (int i=0; i<200; i++) { item= root.getItem(i1); try { if (!"...".equals(item.getText())) { @@ -164,7 +166,7 @@ public class CallHierarchyBaseTest extends BaseUITestCase { } catch (SWTException e) { // in case widget was disposed, item may be replaced } - runEventQueue(50); + runEventQueue(10); } } catch (IllegalArgumentException e) { diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java new file mode 100644 index 00000000000..76fb90e907c --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyBugs.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2007 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 junit.framework.Test; + +import org.eclipse.core.resources.IFile; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IViewPart; +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.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.callhierarchy.CHViewPart; +import org.eclipse.cdt.internal.ui.editor.ICEditorActionDefinitionIds; + + +public class CallHierarchyBugs extends CallHierarchyBaseTest { + + public CallHierarchyBugs(String name) { + super(name); + } + + public static Test suite() { + return suite(CallHierarchyBugs.class); + } + + + // class SomeClass { + // public: + // void method(); + // int field; + // }; + + // #include "SomeClass.h" + // void SomeClass::method() { + // field= 1; + // } + public void testCallHierarchyFromOutlineView_183941() throws Exception { + StringBuffer[] contents = getContentsForTest(2); + IFile file1= createFile(getProject(), "SomeClass.h", contents[0].toString()); + IFile file2= createFile(getProject(), "SomeClass.cpp", contents[1].toString()); + waitForIndexer(fIndex, file2, CallHierarchyBaseTest.INDEXER_WAIT_TIME); + + openEditor(file1); + IViewPart outline = activateView(IPageLayout.ID_OUTLINE); + Tree outlineTree= (Tree) getFocusControl(Tree.class, 8000); + checkTreeNode(outlineTree, 0, "SomeClass"); + expandTreeItem(outlineTree, 0); + checkTreeNode(outlineTree, 0, 0, "method() : void"); + selectTreeItem(outlineTree, 0, 0); + executeCommand(outline, ICEditorActionDefinitionIds.OPEN_CALL_HIERARCHY); + + CHViewPart ch= (CHViewPart) activateView(CUIPlugin.ID_CALL_HIERARCHY); + Tree chTree= (Tree) getFocusControl(Tree.class, 8000); + checkTreeNode(chTree, 0, "SomeClass::method()"); + checkTreeNode(chTree, 0, 1, null); + + ch.onSetShowReferencedBy(false); + checkTreeNode(chTree, 0, "SomeClass::method()"); + checkTreeNode(chTree, 0, 0, "SomeClass::field"); + } + + // class SomeClass { + // public: + // void ambiguous_impl(); + // int ref1; + // int ref2; + // }; + // + // void SomeClass::ambiguous_impl() { + // ref1= 1; + // } + + // #include "SomeClass.h" + // void SomeClass::ambiguous_impl() { + // ref2= 0; + // } + public void testCallHierarchyFromOutlineViewAmbiguous_183941() throws Exception { + StringBuffer[] contents = getContentsForTest(2); + IFile file1= createFile(getProject(), "SomeClass.h", contents[0].toString()); + IFile file2= createFile(getProject(), "SomeClass.cpp", contents[1].toString()); + waitForIndexer(fIndex, file2, CallHierarchyBaseTest.INDEXER_WAIT_TIME); + + IViewPart outline= activateView(IPageLayout.ID_OUTLINE); + Control avoid= getFocusControl(Control.class, 8000); + openEditor(file1); + outline= activateView(IPageLayout.ID_OUTLINE); + Tree outlineTree= (Tree) getFocusControl(Tree.class, avoid, 8000); + checkTreeNode(outlineTree, 1, "SomeClass::ambiguous_impl() : void"); + selectTreeItem(outlineTree, 1); // select the definition + executeCommand(outline, ICEditorActionDefinitionIds.OPEN_CALL_HIERARCHY); + + CHViewPart ch= (CHViewPart) activateView(CUIPlugin.ID_CALL_HIERARCHY); + ch.onSetShowReferencedBy(false); + Tree chTree= (Tree) getFocusControl(Tree.class, 8000); + checkTreeNode(chTree, 0, "SomeClass::ambiguous_impl()"); + checkTreeNode(chTree, 0, 0, "SomeClass::ref1"); + + openEditor(file2); + outline= activateView(IPageLayout.ID_OUTLINE); + outlineTree= (Tree) getFocusControl(Tree.class, outlineTree, 8000); + + checkTreeNode(outlineTree, 1, "SomeClass::ambiguous_impl() : void"); + selectTreeItem(outlineTree, 1); // select the definition + executeCommand(outline, ICEditorActionDefinitionIds.OPEN_CALL_HIERARCHY); + + ch= (CHViewPart) activateView(CUIPlugin.ID_CALL_HIERARCHY); + ch.onSetShowReferencedBy(false); + chTree= (Tree) getFocusControl(Tree.class, 8000); + checkTreeNode(chTree, 0, "SomeClass::ambiguous_impl()"); + checkTreeNode(chTree, 0, 0, "SomeClass::ref2"); + } + + private void openEditor(IFile file) throws PartInitException { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IDE.openEditor(page, file); + getFocusControl(StyledText.class, 8000); + } +} 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 d82aa62c4c2..a0e678be4a6 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2007 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 @@ -26,5 +26,6 @@ public class CallHierarchyTestSuite extends TestSuite { addTest(InitializersInCallHierarchyTest.suite()); addTest(CppCallHierarchyTest.suite()); addTest(CallHierarchyAcrossProjectsTest.suite()); + addTest(CallHierarchyBugs.suite()); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/IncludeBrowserBaseTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/IncludeBrowserBaseTest.java index f713fbaf0a4..ad10fce5a1f 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/IncludeBrowserBaseTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/IncludeBrowserBaseTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2007 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 @@ -99,12 +99,12 @@ public class IncludeBrowserBaseTest extends BaseUITestCase { protected void checkTreeNode(Tree tree, int i0, String label) { TreeItem root= null; try { - for (int i=0; i<20; i++) { + for (int i=0; i<200; i++) { root= tree.getItem(i0); if (!"...".equals(root.getText())) { break; } - runEventQueue(50); + runEventQueue(10); } } catch (IllegalArgumentException e) { @@ -117,11 +117,11 @@ public class IncludeBrowserBaseTest extends BaseUITestCase { try { TreeItem root= tree.getItem(i0); TreeItem item= root.getItem(i1); - for (int i=0; i<40; i++) { + for (int i=0; i<200; i++) { if (!"...".equals(item.getText())) { break; } - runEventQueue(50); + runEventQueue(10); } assertEquals(label, item.getText()); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/typehierarchy/TypeHierarchyBaseTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/typehierarchy/TypeHierarchyBaseTest.java index 05ff4333bee..12570d5bc80 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/typehierarchy/TypeHierarchyBaseTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/typehierarchy/TypeHierarchyBaseTest.java @@ -155,7 +155,7 @@ public class TypeHierarchyBaseTest extends BaseUITestCase { protected TreeItem checkTreeNode(Tree tree, int i0, String label) { TreeItem root= null; try { - for (int i=0; i<100; i++) { + for (int i=0; i<200; i++) { root= tree.getItem(i0); try { if (!"...".equals(root.getText())) { @@ -178,7 +178,7 @@ public class TypeHierarchyBaseTest extends BaseUITestCase { TreeItem item= null; try { TreeItem root= tree.getItem(i0); - for (int i=0; i<40; i++) { + for (int i=0; i<200; i++) { item= root.getItem(i1); try { if (!"...".equals(item.getText())) { @@ -187,7 +187,7 @@ public class TypeHierarchyBaseTest extends BaseUITestCase { } catch (SWTException e) { // in case widget was disposed, item may be replaced } - runEventQueue(50); + runEventQueue(10); } } catch (IllegalArgumentException e) { @@ -200,7 +200,7 @@ public class TypeHierarchyBaseTest extends BaseUITestCase { protected TreeItem checkTreeNode(TreeItem root, int i1, String label) { TreeItem item= null; try { - for (int i=0; i<40; i++) { + for (int i=0; i<200; i++) { item= root.getItem(i1); try { if ("".equals(item.getText())) { @@ -215,7 +215,7 @@ public class TypeHierarchyBaseTest extends BaseUITestCase { } catch (SWTException e) { // in case widget was disposed, item may be replaced } - runEventQueue(50); + runEventQueue(10); } } catch (IllegalArgumentException e) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java index d92417e7a77..60101a52e84 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java @@ -204,18 +204,20 @@ public class CallHierarchyUI { index.acquireReadLock(); try { - IBinding binding= IndexUI.elementToBinding(index, input); - if (binding != null) { - ICElement[] result= IndexUI.findAllDefinitions(index, binding); - if (result.length > 0) { - return result; - } - IIndexName name= IndexUI.elementToName(index, input); - if (name != null) { - ICElementHandle handle= IndexUI.getCElementForName(tu, index, name); - return new ICElement[] {handle}; + if (needToFindDefinition(input)) { + IBinding binding= IndexUI.elementToBinding(index, input); + if (binding != null) { + ICElement[] result= IndexUI.findAllDefinitions(index, binding); + if (result.length > 0) { + return result; + } } } + IIndexName name= IndexUI.elementToName(index, input); + if (name != null) { + ICElementHandle handle= IndexUI.getCElementForName(tu, index, name); + return new ICElement[] {handle}; + } } finally { if (index != null) { @@ -236,6 +238,17 @@ public class CallHierarchyUI { return new ICElement[] {input}; } + private static boolean needToFindDefinition(ICElement elem) { + switch (elem.getElementType()) { + case ICElement.C_FUNCTION_DECLARATION: + case ICElement.C_METHOD_DECLARATION: + case ICElement.C_TEMPLATE_FUNCTION_DECLARATION: + case ICElement.C_TEMPLATE_METHOD_DECLARATION: + return true; + } + return false; + } + public static boolean isRelevantForCallHierarchy(IBinding binding) { if (binding instanceof ICExternalBinding || binding instanceof IEnumerator ||