From 2bd73d2db8d2c56975153c291463f94c15364782 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Mon, 21 May 2007 13:40:24 +0000 Subject: [PATCH] Fix for 187792, handling ambiguities during 'Open Declaration' --- .../eclipse/cdt/core/model/CoreModelUtil.java | 2 +- .../core/model/ext/CElementHandleFactory.java | 8 ++ .../selection/BaseSelectionTestsIndexer.java | 5 + .../selection/CPPSelectionTestsNoIndexer.java | 5 + .../selection/CSelectionTestsNoIndexer.java | 5 + .../cdt/internal/corext/util/CModelUtil.java | 35 ------ .../ui/editor/CEditorMessages.properties | 3 + .../ui/includebrowser/IBConversions.java | 9 +- .../includebrowser/IBDropTargetListener.java | 7 +- .../actions/OpenDeclarationsAction.java | 112 ++++++++++++++---- .../cdt/internal/ui/viewsupport/IndexUI.java | 16 ++- 11 files changed, 139 insertions(+), 68 deletions(-) diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java index 4370d5cfdd5..f7d477cfd7d 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java @@ -610,7 +610,7 @@ public class CoreModelUtil { * Returns the translation unit for the file given or null. */ public static ITranslationUnit findTranslationUnit(IFile file) { - if (CoreModel.isTranslationUnit(file)) { + if (CoreModel.isTranslationUnit(file) && file.exists()) { ICProject cp= CoreModel.getDefault().getCModel().getCProject(file.getProject().getName()); if (cp != null) { ICElement tu; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandleFactory.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandleFactory.java index e4c5d8ce298..b787d040854 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandleFactory.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandleFactory.java @@ -19,10 +19,12 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IFunction; +import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.c.ICCompositeTypeScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -67,6 +69,9 @@ public class CElementHandleFactory { element= new FieldHandle(parentElement, (IField) binding); } else if (binding instanceof IVariable) { + if (binding instanceof IParameter) { + return null; + } element= new VariableHandle(parentElement, (IVariable) binding); } else if (binding instanceof IEnumeration) { @@ -125,6 +130,9 @@ public class CElementHandleFactory { ICompositeType type= ((ICCompositeTypeScope) scope).getCompositeType(); element= new StructureHandle(parentElement, type); } + else if (scope instanceof ICPPBlockScope) { + return null; + } else if (scope instanceof ICPPNamespaceScope) { element= new NamespaceHandle(parentElement, new String(scopeName.toCharArray())); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/BaseSelectionTestsIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/BaseSelectionTestsIndexer.java index b37adfd8ea2..e632b3bce65 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/BaseSelectionTestsIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/BaseSelectionTestsIndexer.java @@ -70,6 +70,11 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { super(name); } + protected void setUp() throws Exception { + super.setUp(); + OpenDeclarationsAction.sIsJUnitTest= true; + } + public void waitForIndex(int maxSec) throws Exception { assertTrue(CCorePlugin.getIndexManager().joinIndexer(maxSec*1000, new NullProgressMonitor())); } 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 7bd7c2e3871..116c34331f9 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 @@ -125,6 +125,11 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { } } + protected void setUp() throws Exception { + super.setUp(); + OpenDeclarationsAction.sIsJUnitTest= true; + } + protected void tearDown() throws Exception { if( project == null || !project.exists() ) return; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java index f49fbd7b43e..2348d32ab2c 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java @@ -106,6 +106,11 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { return suite; } + protected void setUp() throws Exception { + super.setUp(); + OpenDeclarationsAction.sIsJUnitTest= true; + } + public void cleanupProject() throws Exception { closeAllEditors(); CProjectHelper.delete(cPrj); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java index eff320bf37e..a0078a0ccf6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/CModelUtil.java @@ -11,21 +11,15 @@ *******************************************************************************/ package org.eclipse.cdt.internal.corext.util; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.IPath; -import org.eclipse.cdt.core.model.CModelException; -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ICContainer; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IWorkingCopy; -import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.ui.util.EditorUtility; @@ -120,33 +114,4 @@ public class CModelUtil { } return null; } - - /** - * Returns the translation unit for the file given or null. - */ - public static ITranslationUnit findTranslationUnit(IFile file) { - if (CoreModel.isTranslationUnit(file)) { - ICProject cp= CoreModel.getDefault().getCModel().getCProject(file.getProject().getName()); - if (cp != null) { - ICElement tu; - try { - tu = cp.findElement(file.getProjectRelativePath()); - if (tu instanceof ITranslationUnit) { - return (ITranslationUnit) tu; - } - } catch (CModelException e) { - CUIPlugin.getDefault().log(e); - } - } - } - return null; - } - - /** - * Returns the translation unit for the location given or null. - * @throws CModelException - */ - public static ITranslationUnit findTranslationUnitForLocation(IPath location, ICProject preferredProject) throws CModelException { - return CoreModelUtil.findTranslationUnitForLocation(location, preferredProject); - } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties index 5ea9e8f6986..ce1b1071504 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties @@ -9,6 +9,7 @@ # IBM Corporation - initial API and implementation # QNX Software System # Anton Leherbauer (Wind River Systems) +# Markus Schorn (Wind River Systems) ######################################### AddIncludeOnSelection.description=Add include statement on selection @@ -33,6 +34,8 @@ OpenHierarchy.tooltip=Show the type hierarchy of the selected element OpenDeclarations.description=Open an editor on the selected element's declaration OpenDeclarations.dialog.message=&Select or enter the element to open: +OpenDeclarationsAction.dialog.title=Open Declaration +OpenDeclarationsAction.selectMessage=Select one element from the list OpenDeclarations.dialog.title=Open Declaration OpenDeclarations.label=&Open Declaration OpenDeclarations.tooltip=Open an editor on the selected element's declaration diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBConversions.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBConversions.java index b140da6be46..094cebba950 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBConversions.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBConversions.java @@ -21,11 +21,10 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.editors.text.ILocationProvider; import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.cdt.internal.corext.util.CModelUtil; - public class IBConversions { public static IBNode selectionToNode(ISelection sel) { @@ -60,7 +59,7 @@ public class IBConversions { return (ITranslationUnit) object; } if (object instanceof IFile) { - return CModelUtil.findTranslationUnit((IFile) object); + return CoreModelUtil.findTranslationUnit((IFile) object); } if (object instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) object; @@ -70,7 +69,7 @@ public class IBConversions { } IFile file= (IFile) adaptable.getAdapter(IFile.class); if (file != null) { - return CModelUtil.findTranslationUnit(file); + return CoreModelUtil.findTranslationUnit(file); } ILocationProvider locProvider= (ILocationProvider) adaptable.getAdapter(ILocationProvider.class); @@ -78,7 +77,7 @@ public class IBConversions { IPath path= locProvider.getPath(locProvider); if (path != null) { try { - return CModelUtil.findTranslationUnitForLocation(path, null); + return CoreModelUtil.findTranslationUnitForLocation(path, null); } catch (CModelException e) { CUIPlugin.getDefault().log(e); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBDropTargetListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBDropTargetListener.java index 3f018a9b34c..966fe1ee115 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBDropTargetListener.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBDropTargetListener.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 @@ -30,10 +30,9 @@ import org.eclipse.swt.dnd.TransferData; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.part.ResourceTransfer; +import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.internal.corext.util.CModelUtil; - public class IBDropTargetListener implements DropTargetListener { private IBViewPart fIncludeBrowser; @@ -140,7 +139,7 @@ public class IBDropTargetListener implements DropTargetListener { for (int i = 0; i < files.length; i++) { IResource resource = files[i]; if (resource.getType() == IResource.FILE) { - ITranslationUnit tu= CModelUtil.findTranslationUnit((IFile) resource); + ITranslationUnit tu= CoreModelUtil.findTranslationUnit((IFile) resource); if (tu != null) { return tu; } 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 2dabaf23899..88c7ba25bb8 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 @@ -13,6 +13,8 @@ package org.eclipse.cdt.internal.ui.search.actions; +import java.util.ArrayList; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; @@ -37,15 +39,24 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexManager; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.model.util.CElementBaseLabels; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.actions.OpenActionUtil; import org.eclipse.cdt.internal.ui.editor.ASTProvider; import org.eclipse.cdt.internal.ui.editor.CEditor; import org.eclipse.cdt.internal.ui.editor.CEditorMessages; +import org.eclipse.cdt.internal.ui.viewsupport.IndexUI; public class OpenDeclarationsAction extends SelectionParseAction { + public static boolean sIsJUnitTest = false; public static final IASTName[] BLANK_NAME_ARRAY = new IASTName[0]; ITextSelection selNode; @@ -114,26 +125,13 @@ public class OpenDeclarationsAction extends SelectionParseAction { } } } - for (int i = 0; i < declNames.length; i++) { - IASTFileLocation fileloc = declNames[i].getFileLocation(); - if (fileloc != null) { - found = true; - - final IPath path = new Path(fileloc.getFileName()); - final int offset = fileloc.getNodeOffset(); - final int length = fileloc.getNodeLength(); - - runInUIThread(new Runnable() { - public void run() { - try { - open(path, offset, length); - } catch (CoreException e) { - CUIPlugin.getDefault().log(e); - } - } - }); - break; - } + if (navigateViaCElements(workingCopy.getCProject(), index, 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) { @@ -191,6 +189,80 @@ public class OpenDeclarationsAction extends SelectionParseAction { } } + private boolean navigateOneLocation(IName[] declNames) { + for (int i = 0; i < declNames.length; i++) { + IASTFileLocation fileloc = declNames[i].getFileLocation(); + if (fileloc != null) { + + final IPath path = new Path(fileloc.getFileName()); + final int offset = fileloc.getNodeOffset(); + final int length = fileloc.getNodeLength(); + + runInUIThread(new Runnable() { + public void run() { + try { + open(path, offset, length); + } catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + } + }); + return true; + } + } + return false; + } + + private boolean navigateViaCElements(ICProject project, IIndex index, IName[] declNames) { + final ArrayList elements= new ArrayList(); + for (int i = 0; i < declNames.length; i++) { + try { + ICElement elem = IndexUI.getCElementForName(project, index, declNames[i]); + if (elem instanceof ISourceReference) { + elements.add(elem); + } + } catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } catch (DOMException e) { + CUIPlugin.getDefault().log(e); + } + } + if (elements.isEmpty()) { + return false; + } + + runInUIThread(new Runnable() { + public void run() { + ISourceReference target= null; + if (elements.size() == 1) { + target= (ISourceReference) elements.get(0); + } + else { + if (sIsJUnitTest) { + throw new RuntimeException("ambiguous input"); //$NON-NLS-1$ + } + ICElement[] elemArray= (ICElement[]) elements.toArray(new ICElement[elements.size()]); + target = (ISourceReference) OpenActionUtil.selectCElement(elemArray, getSite().getShell(), + CEditorMessages.getString("OpenDeclarationsAction.dialog.title"), CEditorMessages.getString("OpenDeclarationsAction.selectMessage"), //$NON-NLS-1$ //$NON-NLS-2$ + CElementBaseLabels.ALL_DEFAULT | CElementBaseLabels.MF_POST_FILE_QUALIFIED, 0); + } + if (target != null) { + ITranslationUnit tu= target.getTranslationUnit(); + ISourceRange sourceRange; + try { + sourceRange = target.getSourceRange(); + if (tu != null && sourceRange != null) { + open(tu.getLocation(), sourceRange.getIdStartPos(), sourceRange.getIdLength()); + } + } catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + } + } + }); + return true; + } + private IName[] findNames(IIndex index, IASTTranslationUnit ast, boolean isDefinition, IBinding binding) throws CoreException { IName[] declNames= isDefinition ? diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java index 830f3e7fb3a..e1320080cfb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java @@ -45,6 +45,7 @@ import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ISourceRange; @@ -55,7 +56,6 @@ import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory; import org.eclipse.cdt.internal.core.model.ext.ICElementHandle; -import org.eclipse.cdt.internal.corext.util.CModelUtil; import org.eclipse.cdt.internal.ui.editor.ASTProvider; @@ -168,7 +168,17 @@ public class IndexUI { } return EMPTY_ELEMENTS; } - + + public static ICElementHandle getCElementForName(ICProject preferProject, IIndex index, IName declName) throws CoreException, DOMException { + if (declName instanceof IASTName) { + return getCElementForName(preferProject, index, (IASTName) declName); + } + else if (declName instanceof IIndexName) { + return getCElementForName(preferProject, index, (IIndexName) declName); + } + return null; + } + public static ICElementHandle getCElementForName(ICProject preferProject, IIndex index, IASTName declName) throws CoreException, DOMException { assert !declName.isReference(); IBinding binding= declName.resolveBinding(); @@ -192,7 +202,7 @@ public class IndexUI { private static ITranslationUnit getTranslationUnit(ICProject cproject, IName name) { IPath path= Path.fromOSString(name.getFileLocation().getFileName()); try { - return CModelUtil.findTranslationUnitForLocation(path, cproject); + return CoreModelUtil.findTranslationUnitForLocation(path, cproject); } catch (CModelException e) { CUIPlugin.getDefault().log(e); return null;