From c5c0fc6d242e5e5b1edda8846960c329bf25af72 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Sat, 16 May 2009 06:27:13 +0000 Subject: [PATCH] Open Declaration improvements. Bug 232587. --- .../selection/BaseSelectionTestsIndexer.java | 41 +++-- .../selection/CPPSelectionTestsNoIndexer.java | 18 +- .../selection/CSelectionTestsAnyIndexer.java | 4 - .../selection/CSelectionTestsNoIndexer.java | 57 ++++--- .../actions/OpenDeclarationsAction.java | 156 +++++++++++++----- 5 files changed, 173 insertions(+), 103 deletions(-) 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 acace37dfda..35e2d3a604b 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 @@ -80,7 +80,6 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { protected void setUp() throws Exception { super.setUp(); OpenDeclarationsAction.sIsJUnitTest= true; - OpenDeclarationsAction.sAllowFallback= false; IWorkbenchPage page= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewReference[] refs= page.getViewReferences(); for (int i = 0; i < refs.length; i++) { @@ -90,7 +89,7 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { } public void waitForIndex(int maxSec) throws Exception { - assertTrue(CCorePlugin.getIndexManager().joinIndexer(maxSec*1000, new NullProgressMonitor())); + assertTrue(CCorePlugin.getIndexManager().joinIndexer(maxSec * 1000, new NullProgressMonitor())); } protected String getMessage(IStatus status) { @@ -106,16 +105,16 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { return message.toString(); } - protected IFile importFile(String fileName, String contents ) throws Exception{ + protected IFile importFile(String fileName, String contents) throws Exception{ //Obtain file handle IFile file = fCProject.getProject().getFile(fileName); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -137,24 +136,24 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { file.createLink(location, IResource.ALLOW_MISSING_LOCAL, null); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) { + if (file.exists()) { long timestamp= file.getLocalTimeStamp(); - file.setContents( stream, false, false, monitor ); + file.setContents(stream, false, false, monitor); if (file.getLocalTimeStamp() == timestamp) { file.setLocalTimeStamp(timestamp+1000); } - } - else - file.create( stream, false, monitor ); + } else { + file.create(stream, false, monitor); + } fileManager.addFile(file); return file; } - protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName ) throws Exception{ + protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName) throws Exception{ IProject project= fCProject.getProject(); IFolder linkedFolder = project.getFolder(folderName); IPath folderLocation = new Path(project.getLocation().toOSString() + File.separator + folderName + "_this_is_linked"); //$NON-NLS-1$ @@ -168,12 +167,12 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { IFile file = linkedFolder.getFile(fileName); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -184,18 +183,16 @@ public class BaseSelectionTestsIndexer extends BaseUITestCase { IFolder folder = fCProject.getProject().getFolder(folderName); //Create file input stream - if( !folder.exists() ) - folder.create( false, false, monitor ); + if (!folder.exists()) + folder.create(false, false, monitor); return folder; } - protected String getEditorID() { return "org.eclipse.cdt.ui.editor.CEditor"; } - protected IASTNode testF3(IFile file, int offset) throws ParserException, CoreException { return testF3(file, offset, 0); } 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 98ebdebad37..6adaf580ef7 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 @@ -110,15 +110,15 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { //Create file manager fileManager = new FileManager(); } - public CPPSelectionTestsNoIndexer() - { + + public CPPSelectionTestsNoIndexer() { super(); } + /** * @param name */ - public CPPSelectionTestsNoIndexer(String name) - { + public CPPSelectionTestsNoIndexer(String name) { super(name); } @@ -147,7 +147,6 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { super.setUp(); initProject(); OpenDeclarationsAction.sIsJUnitTest= true; - OpenDeclarationsAction.sAllowFallback= false; } @Override @@ -326,7 +325,6 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { assertEquals(((IASTName)node).toString(), "operator ="); //$NON-NLS-1$ assertEquals(((ASTNode)node).getOffset(), 121); assertEquals(((ASTNode)node).getLength(), 9); - } public void testBasicDefinition() throws Exception { @@ -993,7 +991,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { String appendCode= contents[1].toString(); String[] filenames= {"testBug195822.c", "testBug195822.cpp"}; - for (int i=0; i<2; i++) { + for (int i= 0; i < 2; i++) { IFile file = importFile(filenames[i], code); int od1 = code.indexOf("functionPointer"); int or1 = code.indexOf("functionPointer", od1+1); @@ -1023,7 +1021,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { public void testEmptyMacro_Bug198649() throws Exception { String code= getContentsForTest(1)[0].toString(); String[] filenames= {"testBug198649.c", "testBug198649.cpp"}; - for (int i=0; i<2; i++) { + for (int i= 0; i < 2; i++) { IFile file = importFile(filenames[i], code); int od1 = code.indexOf("EMPTY"); int or1 = code.indexOf("EMPTY", od1+1); @@ -1040,8 +1038,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { public void testFallBackForStaticFuncs_Bug252549() throws Exception { String code= getContentsForTest(1)[0].toString(); String[] filenames= {"testBug252549.c", "testBug252549.cpp"}; - for (int i=0; i<2; i++) { - OpenDeclarationsAction.sAllowFallback= true; + for (int i= 0; i < 2; i++) { IFile file = importFile(filenames[i], code); int offset= code.indexOf("myFunc(x)"); IASTNode decl= testF3(file, offset); @@ -1051,5 +1048,4 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { assertEquals("myFunc", name.toString()); } } - } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsAnyIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsAnyIndexer.java index d6acb3f96d2..d7ca6b64963 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsAnyIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsAnyIndexer.java @@ -32,8 +32,6 @@ import org.eclipse.cdt.ui.testplugin.CTestPlugin; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction; - public abstract class CSelectionTestsAnyIndexer extends BaseSelectionTestsIndexer { private static final int MAX_WAIT_TIME = 8000; @@ -506,8 +504,6 @@ public abstract class CSelectionTestsAnyIndexer extends BaseSelectionTestsIndexe // #define DR_ACCESS_FNS(DR) public void testNavigationInMacroDefinition_Bug102643() throws Exception { - OpenDeclarationsAction.sAllowFallback= true; - StringBuffer[] buffers= getContents(2); String hcode= buffers[0].toString(); String scode= buffers[1].toString(); 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 bf6e4d69b80..4d1f3dddea8 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 @@ -89,7 +89,7 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { try { cPrj = CProjectHelper.createCProject("CSelectionTestsNoIndexerProject", "bin", IPDOMManager.ID_NO_INDEXER); //$NON-NLS-1$ //$NON-NLS-2$ project = cPrj.getProject(); - } catch ( CoreException e ) { + } catch (CoreException e) { /*boo*/ } if (project == null) @@ -111,8 +111,8 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { } public static Test suite() { - TestSuite suite = new TestSuite( CSelectionTestsNoIndexer.class ); - suite.addTest( new CSelectionTestsNoIndexer("cleanupProject") ); //$NON-NLS-1$ + TestSuite suite = new TestSuite(CSelectionTestsNoIndexer.class); + suite.addTest(new CSelectionTestsNoIndexer("cleanupProject")); //$NON-NLS-1$ return suite; } @@ -120,7 +120,6 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { protected void setUp() throws Exception { super.setUp(); OpenDeclarationsAction.sIsJUnitTest= true; - OpenDeclarationsAction.sAllowFallback= false; initProject(); } @@ -137,35 +136,35 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { @Override protected void tearDown() throws Exception { - if( project == null || !project.exists() ) + if (project == null || !project.exists()) return; closeAllEditors(); IResource [] members = project.members(); for (IResource member : members) { - if( member.getName().equals( ".project" ) || member.getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ + if (member.getName().equals(".project") || member.getName().equals(".cproject")) //$NON-NLS-1$ //$NON-NLS-2$ continue; if (member.getName().equals(".settings")) continue; - try{ - member.delete( true, monitor ); - } catch( Throwable e ){ + try { + member.delete(true, monitor); + } catch (Throwable e) { /*boo*/ } } } - protected IFile importFile(String fileName, String contents ) throws Exception{ + protected IFile importFile(String fileName, String contents) throws Exception{ //Obtain file handle IFile file = project.getProject().getFile(fileName); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -185,19 +184,19 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { file.createLink(location, IResource.ALLOW_MISSING_LOCAL, null); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); return file; } - protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName ) throws Exception{ + protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName) throws Exception{ IFolder linkedFolder = project.getFolder(folderName); IPath folderLocation = new Path(project.getLocation().toOSString() + File.separator + folderName + "_this_is_linked"); //$NON-NLS-1$ IFolder actualFolder = project.getFolder(folderName + "_this_is_linked"); //$NON-NLS-1$ @@ -210,12 +209,12 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { IFile file = linkedFolder.getFile(fileName); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -238,12 +237,12 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { file.createLink(location, IResource.ALLOW_MISSING_LOCAL, null); - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); + if (file.exists()) + file.setContents(stream, false, false, monitor); else - file.create( stream, false, monitor ); + file.create(stream, false, monitor); fileManager.addFile(file); @@ -254,8 +253,8 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { IFolder folder = project.getProject().getFolder(folderName); //Create file input stream - if( !folder.exists() ) - folder.create( false, false, monitor ); + if (!folder.exists()) + folder.create(false, false, monitor); return folder; } 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 b14953775d1..0bc737070eb 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 @@ -10,6 +10,7 @@ * Markus Schorn (Wind River Systems) * Ed Swartz (Nokia) * Mike Kucera (IBM) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search.actions; @@ -39,6 +40,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.ASTNameCollector; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner; @@ -48,9 +50,12 @@ import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IProblemBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; 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; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; @@ -69,6 +74,7 @@ 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.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable; import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory; import org.eclipse.cdt.internal.core.model.ext.ICElementHandle; @@ -82,7 +88,6 @@ import org.eclipse.cdt.internal.ui.viewsupport.IndexUI; public class OpenDeclarationsAction extends SelectionParseAction implements ASTRunnable { public static boolean sIsJUnitTest = false; - public static boolean sAllowFallback= true; private static final int KIND_OTHER = 0; private static final int KIND_USING_DECL = 1; @@ -163,7 +168,7 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR if (implicits.length > 0) { List allNames = new ArrayList(); for (IASTImplicitName name : implicits) { - if (((ASTNode)name).getOffset() == ((ASTNode) implicit).getOffset()) { + if (((ASTNode) name).getOffset() == ((ASTNode) implicit).getOffset()) { IBinding binding = name.resolveBinding(); // guaranteed to resolve IName[] declNames = findDeclNames(ast, KIND_OTHER, binding); allNames.addAll(Arrays.asList(declNames)); @@ -181,25 +186,41 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR return Status.OK_STATUS; } IBinding binding = searchName.resolveBinding(); + int isKind= KIND_OTHER; + if (searchName.isDefinition()) { + if (binding instanceof ICPPUsingDeclaration) { + isKind= KIND_USING_DECL; + } else { + isKind= KIND_DEFINITION; + } + } if (binding != null && !(binding instanceof IProblemBinding)) { - int isKind= KIND_OTHER; - if (searchName.isDefinition()) { - if (binding instanceof ICPPUsingDeclaration) { - isKind= KIND_USING_DECL; - } else { - isKind= KIND_DEFINITION; + IName[] declNames = findDeclNames(ast, isKind, binding); + // Exclude the current location. + for (int i = 0; i < declNames.length; i++) { + if (isSameName(declNames[i], searchName)) { + declNames[i] = null; + } else if (binding instanceof IParameter) { + if (!isInSameFunction(searchName, declNames[i])) { + declNames[i] = null; + } + } else if (binding instanceof ICPPTemplateParameter) { + if (!isInSameTemplate(searchName, declNames[i])) { + declNames[i] = null; + } } } - IName[] declNames = findDeclNames(ast, isKind, binding); + declNames = (IName[]) ArrayUtil.removeNulls(IName.class, declNames); + if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, declNames)) { found= true; } else { - // leave old method as fallback for local variables, parameters and + // Leave old method as fallback for local variables, parameters and // everything else not covered by ICElementHandle. found = navigateOneLocation(declNames); } } - if (!found && !navigationFallBack(ast)) { + if (!found && !navigationFallBack(ast, searchName, isKind)) { reportSymbolLookupFailure(new String(searchName.toCharArray())); } return Status.OK_STATUS; @@ -208,15 +229,42 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR // no enclosing name, check if we're in an include statement IASTNode node= nodeSelector.findEnclosingNode(selectionStart, selectionLength); if (node instanceof IASTPreprocessorIncludeStatement) { - openInclude(((IASTPreprocessorIncludeStatement) node)); + openInclude((IASTPreprocessorIncludeStatement) node); return Status.OK_STATUS; } - if (!navigationFallBack(ast)) { + if (!navigationFallBack(ast, null, KIND_OTHER)) { reportSelectionMatchFailure(); } return Status.OK_STATUS; } + private boolean isInSameFunction(IASTName name1, IName name2) { + IASTDeclaration decl1 = getEnclosingDeclaration(name1); + IASTDeclaration decl2 = name2 instanceof IASTName ? getEnclosingDeclaration((IASTName) name2) : null; + return decl1 != null && decl1.equals(decl2) || decl1 == null && decl2 == null; + } + + private IASTDeclaration getEnclosingDeclaration(IASTNode node) { + while (node != null && !(node instanceof IASTDeclaration)) { + node= node.getParent(); + } + return (IASTDeclaration) node; + } + + private boolean isInSameTemplate(IASTName name1, IName name2) { + IASTDeclaration decl1 = getEnclosingTemplateDeclaration(name1); + IASTDeclaration decl2 = name2 instanceof IASTName ? + getEnclosingTemplateDeclaration((IASTName) name2) : null; + return decl1 != null && decl1.equals(decl2) || decl1 == null && decl2 == null; + } + + private IASTDeclaration getEnclosingTemplateDeclaration(IASTNode node) { + while (node != null && !(node instanceof ICPPASTTemplateDeclaration)) { + node= node.getParent(); + } + return (IASTDeclaration) node; + } + private IName[] findDeclNames(IASTTranslationUnit ast, int isKind, IBinding binding) throws CoreException { IName[] declNames = findNames(fIndex, ast, isKind, binding); if (declNames.length == 0) { @@ -244,9 +292,9 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR return declNames; } - private boolean navigationFallBack(IASTTranslationUnit ast) { + private boolean navigationFallBack(IASTTranslationUnit ast, IASTName sourceName, int isKind) { // bug 102643, as a fall-back we look up the selected word in the index - if (sAllowFallback && fSelectedText != null && fSelectedText.length() > 0) { + if (fSelectedText != null && fSelectedText.length() > 0) { try { final ICProject project = fWorkingCopy.getCProject(); final char[] name = fSelectedText.toCharArray(); @@ -288,13 +336,33 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR elems.add(elem); } } - - // convert bindings to CElements + + String[] sourceQualifiedName= sourceName != null ? + CPPVisitor.getQualifiedName(sourceName.resolveBinding()) : + new String[] { fSelectedText }; + // Convert bindings to CElements for (IBinding binding : bindings) { - final IName[] names = findNames(fIndex, ast, KIND_OTHER, binding); + String[] qualifiedName = CPPVisitor.getQualifiedName(binding); + if (!Arrays.equals(qualifiedName, sourceQualifiedName)) { + continue; + } + IName[] names = findNames(fIndex, ast, isKind, binding); + // Exclude the current location. + for (int i = 0; i < names.length; i++) { + if (sourceName != null && isSameName(names[i], sourceName)) { + names[i] = null; + } + } + names = (IName[]) ArrayUtil.removeNulls(IName.class, names); convertToCElements(project, fIndex, names, elems); } - return navigateCElements(elems); + if (navigateCElements(elems)) { + return true; + } + if (sourceName != null && sourceName.isDeclaration()) { + // Select the name at the current location as the last resort. + return navigateToName(sourceName); + } } catch (CoreException e) { CUIPlugin.log(e); } @@ -302,6 +370,14 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR return false; } + private boolean isSameName(IName n1, IName n2) { + IASTFileLocation loc1 = n1.getFileLocation(); + IASTFileLocation loc2 = n2.getFileLocation(); + return loc1.getFileName().equals(loc2.getFileName()) && + loc1.getNodeOffset() == loc2.getNodeOffset() && + loc1.getNodeLength() == loc2.getNodeLength(); + } + private void openInclude(IASTPreprocessorIncludeStatement incStmt) { String name = null; if (incStmt.isResolved()) @@ -323,30 +399,36 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR } } - private boolean navigateOneLocation(IName[] declNames) { - for (IName declName : declNames) { - IASTFileLocation fileloc = declName.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.log(e); - } - } - }); + private boolean navigateOneLocation(IName[] names) { + for (IName name : names) { + if (navigateToName(name)) { return true; } } return false; } + private boolean navigateToName(IName name) { + IASTFileLocation fileloc = name.getFileLocation(); + if (fileloc == null) { + return false; + } + 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.log(e); + } + } + }); + return true; + } + private boolean navigateViaCElements(ICProject project, IIndex index, IName[] declNames) { final ArrayList elements= new ArrayList(); convertToCElements(project, index, declNames, elements);