From 16d620eaa5b3a4f4bfd5954e3391190a9760a516 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 6 Mar 2008 08:23:15 +0000 Subject: [PATCH] Navigation from macro definition body, bug 102643. --- .../index/tests/EmptyIndexFragment.java | 6 ++ .../cdt/internal/core/index/CIndex.java | 31 +++++- .../internal/core/index/IIndexFragment.java | 7 +- .../eclipse/cdt/internal/core/pdom/PDOM.java | 26 +++++ .../cdt/internal/core/pdom/PDOMProxy.java | 8 ++ .../selection/CSelectionTestsAnyIndexer.java | 26 ++++- .../actions/OpenDeclarationsAction.java | 99 +++++++++++++++---- .../cdt/internal/ui/viewsupport/IndexUI.java | 23 ++++- 8 files changed, 198 insertions(+), 28 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java index d7a9ac2480b..67fefc9799b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java @@ -54,6 +54,12 @@ public class EmptyIndexFragment implements IIndexFragment { return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; } + public IIndexFragmentBinding[] findBindings(char[] name, + boolean filescope, IndexFilter filter, IProgressMonitor monitor) + throws CoreException { + return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + public IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java index f9784997b44..121c2b8b8b6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java @@ -146,7 +146,7 @@ public class CIndex implements IIndex { } } // bug 192352, files can reside in multiple fragments, remove duplicates - if (fragCount > 1) { + if (fragCount > 1 || (flags & IIndex.SEARCH_ACCROSS_LANGUAGE_BOUNDARIES) != 0) { HashMap fileMap= new HashMap(); for (Iterator iterator = result.iterator(); iterator.hasNext();) { final IIndexFragmentName name = iterator.next(); @@ -395,7 +395,7 @@ public class CIndex implements IIndex { } public IIndexBinding[] findBindings(char[] name, IndexFilter filter, IProgressMonitor monitor) throws CoreException { - return findBindings(new char[][]{name}, filter, monitor); + return findBindings(name, true, filter, monitor); } /* @@ -499,6 +499,33 @@ public class CIndex implements IIndex { } } + public IIndexBinding[] findBindings(char[] name, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException { + if(SPECIALCASE_SINGLES && fFragments.length==1) { + return fFragments[0].findBindings(name, filescope, filter, monitor); + } else { + List result = new ArrayList(); + ILinkage[] linkages = Linkage.getAllLinkages(); + for(int j=0; j < linkages.length; j++) { + if(filter.acceptLinkage(linkages[j])) { + IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fPrimaryFragmentCount][]; + for (int i = 0; i < fPrimaryFragmentCount; i++) { + try { + IBinding[] part = fFragments[i].findBindings(name, filescope, retargetFilter(linkages[j], filter), monitor); + fragmentBindings[i] = new IIndexFragmentBinding[part.length]; + System.arraycopy(part, 0, fragmentBindings[i], 0, part.length); + } catch (CoreException e) { + CCorePlugin.log(e); + fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + } + ICompositesFactory factory = getCompositesFactory(linkages[j].getLinkageID()); + result.add(factory.getCompositeBindings(fragmentBindings)); + } + } + return flatten(result); + } + } + public IIndexMacro[] findMacros(char[] name, IndexFilter filter, IProgressMonitor monitor) throws CoreException { return findMacros(name, false, true, filter, monitor); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index e09760934ea..8cf38880770 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -10,7 +10,6 @@ * Bryan Wilkinson (QNX) * Andrew Ferguson (Symbian) *******************************************************************************/ - package org.eclipse.cdt.internal.core.index; import java.util.regex.Pattern; @@ -178,6 +177,12 @@ public interface IIndexFragment { */ long getLastWriteAccess(); + /** + * Returns all bindings with the given name, accepted by the given filter + * @param monitor to report progress, may be null + */ + IIndexFragmentBinding[] findBindings(char[] name, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException; + /** * Returns all bindings with the given prefix, accepted by the given filter * @param monitor to report progress, may be null diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index e35b0797f71..bd8c67663c0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -794,6 +794,32 @@ public class PDOM extends PlatformObject implements IPDOM { return result.toArray(new IIndexFragmentBinding[result.size()]); } + public IIndexFragmentBinding[] findBindings(char[] name, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException { + ArrayList result= new ArrayList(); + for (Iterator iter= fLinkageIDCache.values().iterator(); iter.hasNext();) { + PDOMLinkage linkage= iter.next(); + if (filter.acceptLinkage(linkage)) { + PDOMBinding[] bindings; + BindingCollector visitor = new BindingCollector(linkage, name, filter, false, true); + visitor.setMonitor(monitor); + try { + linkage.accept(visitor); + if (!filescope) { + linkage.getNestedBindingsIndex().accept(visitor); + } + } + catch (OperationCanceledException e) { + } + bindings= visitor.getBindings(); + + for (int j = 0; j < bindings.length; j++) { + result.add(bindings[j]); + } + } + } + return result.toArray(new IIndexFragmentBinding[result.size()]); + } + public IIndexMacro[] findMacros(char[] prefix, boolean isPrefix, boolean isCaseSensitive, IndexFilter filter, IProgressMonitor monitor) throws CoreException { ArrayList result= new ArrayList(); MacroCollector visitor = new MacroCollector(this, prefix, isPrefix, isCaseSensitive); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java index 3c33b386b54..387c9274d2c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java @@ -85,6 +85,14 @@ public class PDOMProxy implements IPDOM { return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; } + public synchronized IIndexFragmentBinding[] findBindings(char[] name, boolean filescope, + IndexFilter filter, IProgressMonitor monitor) throws CoreException { + if (fDelegate != null) + return fDelegate.findBindings(name, filescope, filter, monitor); + + return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY; + } + public synchronized IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException { if (fDelegate != null) 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 b5bfaa23dc1..8fef004739a 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 @@ -451,14 +451,14 @@ public abstract class CSelectionTestsAnyIndexer extends BaseSelectionTestsIndexe assertNode("MY_PAR", offset0, decl); } - // #define MY_MACRO 0xDEADBEEF - // #define MY_PAR( aRef ); + // #define MY_MACRO 0xDEADBEEF + // #define MY_PAR( aRef ) aRef // #include "macrodef.h" // int basictest(void){ // int tester = MY_PAR(MY_MACRO); // } - public void _testMacroNavigation_Bug208300() throws Exception { + public void testMacroNavigation_Bug208300() throws Exception { StringBuffer[] buffers= getContents(2); String hcode= buffers[0].toString(); String scode= buffers[1].toString(); @@ -498,4 +498,24 @@ public abstract class CSelectionTestsAnyIndexer extends BaseSelectionTestsIndexe IEditorInput input = part.getEditorInput(); assertEquals("aheader.h", ((FileEditorInput)input).getFile().getName()); } + + // #define DR_NUM_DIMENSIONS(DR) VEC_length (tree, DR_ACCESS_FNS (DR)) + + // #define DR_ACCESS_FNS(DR) + public void testNavigationInMacroDefinition_Bug102643() throws Exception { + StringBuffer[] buffers= getContents(2); + String hcode= buffers[0].toString(); + String scode= buffers[1].toString(); + IFile hfile = importFile("aheader.h", hcode); + IFile file = importFile("source.cpp", scode); + TestSourceReader.waitUntilFileIsIndexed(index, file, MAX_WAIT_TIME); + IASTNode decl; + int offset0, offset1; + + offset1 = hcode.indexOf("DR_ACC"); + testF3(hfile, offset1); + IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + IEditorInput input = part.getEditorInput(); + assertEquals("source.cpp", ((FileEditorInput)input).getFile().getName()); + } } 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 e67edb3b70f..00ae274329f 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 @@ -25,6 +25,8 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Region; @@ -36,8 +38,8 @@ import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; -import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; @@ -45,8 +47,11 @@ 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.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexMacro; import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ILanguage; @@ -66,6 +71,7 @@ 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.text.CWordFinder; import org.eclipse.cdt.internal.ui.viewsupport.IndexUI; public class OpenDeclarationsAction extends SelectionParseAction implements ASTRunnable { @@ -92,8 +98,10 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR ITextSelection fTextSelection; + private String fSelectedText; private IWorkingCopy fWorkingCopy; private IIndex fIndex; + private IProgressMonitor fMonitor; /** * Creates a new action with the given editor @@ -109,6 +117,7 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR protected IStatus performNavigation(IProgressMonitor monitor) throws CoreException { clearStatusLine(); + fMonitor= monitor; fWorkingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput()); if (fWorkingCopy == null) return Status.CANCEL_STATUS; @@ -136,7 +145,8 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR int selectionStart = fTextSelection.getOffset(); int selectionLength = fTextSelection.getLength(); - IASTName searchName= ast.getNodeSelector(null).findEnclosingName(selectionStart, selectionLength); + final IASTNodeSelector nodeSelector = ast.getNodeSelector(null); + IASTName searchName= nodeSelector.findEnclosingName(selectionStart, selectionLength); if (searchName != null) { // just right, only one name selected boolean found= false; final IASTNode parent = searchName.getParent(); @@ -186,32 +196,54 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR found = navigateOneLocation(declNames); } } - if (!found) { + if (!found && !navigationFallBack(ast)) { reportSymbolLookupFailure(new String(searchName.toCharArray())); } return Status.OK_STATUS; } // Check if we're in an include statement - IASTPreprocessorStatement[] preprocs = ast.getAllPreprocessorStatements(); - for (int i = 0; i < preprocs.length; ++i) { - if (!(preprocs[i] instanceof IASTPreprocessorIncludeStatement)) - continue; - IASTPreprocessorIncludeStatement incStmt = (IASTPreprocessorIncludeStatement)preprocs[i]; - IASTFileLocation loc = preprocs[i].getFileLocation(); - if (loc != null - && loc.getFileName().equals(ast.getFilePath()) - && loc.getNodeOffset() < selectionStart - && loc.getNodeOffset() + loc.getNodeLength() > selectionStart) { - // Got it - openInclude(incStmt); + if (searchName == null) { + IASTNode node= nodeSelector.findEnclosingNode(selectionStart, selectionLength); + if (node instanceof IASTPreprocessorIncludeStatement) { + openInclude(((IASTPreprocessorIncludeStatement) node)); return Status.OK_STATUS; } } - reportSelectionMatchFailure(); + if (!navigationFallBack(ast)) { + reportSelectionMatchFailure(); + } return Status.OK_STATUS; } + private boolean navigationFallBack(IASTTranslationUnit ast) { + // bug 102643, as a fall-back we look up the selected word in the index + if (fSelectedText != null && fSelectedText.length() > 0) { + try { + final ICProject project = fWorkingCopy.getCProject(); + final char[] name = fSelectedText.toCharArray(); + List elems= new ArrayList(); + final IndexFilter filter = IndexFilter.getDeclaredBindingFilter(ast.getLinkage().getLinkageID(), false); + IIndexMacro[] macros= fIndex.findMacros(name, filter, fMonitor); + for (IIndexMacro macro : macros) { + ICElement elem= IndexUI.getCElementForMacro(project, fIndex, macro); + if (elem != null) { + elems.add(elem); + } + } + IIndexBinding[] bindings = fIndex.findBindings(name, filter, fMonitor); + for (IBinding binding : bindings) { + final IName[] names = findNames(fIndex, ast, KIND_OTHER, binding); + convertToCElements(project, fIndex, names, elems); + } + return navigateCElements(elems); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + return false; + } + private void openInclude(IASTPreprocessorIncludeStatement incStmt) { String name = null; if (incStmt.isResolved()) @@ -259,6 +291,12 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR private boolean navigateViaCElements(ICProject project, IIndex index, IName[] declNames) { final ArrayList elements= new ArrayList(); + convertToCElements(project, index, declNames, elements); + return navigateCElements(elements); + } + + + private void convertToCElements(ICProject project, IIndex index, IName[] declNames, List elements) { for (int i = 0; i < declNames.length; i++) { try { ICElement elem = getCElementForName(project, index, declNames[i]); @@ -269,6 +307,9 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR CUIPlugin.getDefault().log(e); } } + } + + private boolean navigateCElements(final List elements) { if (elements.isEmpty()) { return false; } @@ -378,7 +419,7 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR @Override public void run() { - fTextSelection = getSelectedStringFromEditor(); + computeSelectedWord(); if (fTextSelection != null) { new WrapperJob().schedule(); } @@ -398,10 +439,32 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR * @since 4.0 */ public void runSync() throws CoreException { - fTextSelection = getSelectedStringFromEditor(); + computeSelectedWord(); if (fTextSelection != null) { performNavigation(new NullProgressMonitor()); } } + + + private void computeSelectedWord() { + fTextSelection = getSelectedStringFromEditor(); + fSelectedText= null; + if (fTextSelection != null) { + if (fTextSelection.getLength() > 0) { + fSelectedText= fTextSelection.getText(); + } + else { + IDocument document= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); + IRegion reg= CWordFinder.findWord(document, fTextSelection.getOffset()); + if (reg != null && reg.getLength() > 0) { + try { + fSelectedText= document.get(reg.getOffset(), reg.getLength()); + } catch (BadLocationException e) { + CCorePlugin.log(e); + } + } + } + } + } } 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 15783e619bb..2c5185f48ee 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2008 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 @@ -55,6 +55,7 @@ import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexInclude; +import org.eclipse.cdt.core.index.IIndexMacro; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexLocationFactory; @@ -265,7 +266,7 @@ public class IndexUI { if (binding != null) { IIndexName[] defs= index.findNames(binding, IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACCROSS_LANGUAGE_BOUNDARIES); - ArrayList result= new ArrayList(); + ArrayList result= new ArrayList(); for (int i = 0; i < defs.length; i++) { IIndexName in = defs[i]; ICElementHandle definition= getCElementForName((ICProject) null, index, in); @@ -274,7 +275,7 @@ public class IndexUI { } } - return (ICElementHandle[]) result.toArray(new ICElementHandle[result.size()]); + return result.toArray(new ICElementHandle[result.size()]); } return EMPTY_ELEMENTS; } @@ -309,7 +310,10 @@ public class IndexUI { } public static ITranslationUnit getTranslationUnit(ICProject cproject, IName name) { - final IASTFileLocation fileLocation = name.getFileLocation(); + return getTranslationUnit(cproject, name.getFileLocation()); + } + + private static ITranslationUnit getTranslationUnit(ICProject cproject, final IASTFileLocation fileLocation) { if (fileLocation != null) { IPath path= Path.fromOSString(fileLocation.getFileName()); try { @@ -338,6 +342,17 @@ public class IndexUI { return CElementHandleFactory.create(tu, index.findBinding(declName), declName.isDefinition(), region, timestamp); } + public static ICElementHandle getCElementForMacro(ICProject preferProject, IIndex index, IIndexMacro macro) + throws CoreException { + ITranslationUnit tu= getTranslationUnit(preferProject, macro.getFileLocation()); + if (tu != null) { + IRegion region= new Region(macro.getNodeOffset(), macro.getNodeLength()); + long timestamp= macro.getFile().getTimestamp(); + return CElementHandleFactory.create(tu, macro, region, timestamp); + } + return null; + } + public static ICElementHandle findAnyDeclaration(IIndex index, ICProject preferProject, IBinding binding) throws CoreException { if (binding != null) {