From d1db017310db80e2059dda83e04bd73da362bce6 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 23 May 2007 10:38:34 +0000 Subject: [PATCH] Fix for 188282, potential use of unlocked index. --- .../cdt/core/model/tests/ASTCacheTests.java | 130 ++++++++---- .../cdt/internal/core/model/ASTCache.java | 15 +- .../ui/callhierarchy/CallHierarchyUI.java | 2 +- .../cdt/internal/ui/editor/ASTProvider.java | 36 ---- .../ui/editor/CElementHyperlinkDetector.java | 54 +++-- .../actions/OpenDeclarationsAction.java | 192 +++++++++--------- .../cdt/internal/ui/viewsupport/IndexUI.java | 24 ++- 7 files changed, 247 insertions(+), 206 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/ASTCacheTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/ASTCacheTests.java index 67bb9fc452d..3c546708c52 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/ASTCacheTests.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/ASTCacheTests.java @@ -7,6 +7,7 @@ * * Contributors: * Anton Leherbauer (Wind River Systems) - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.model.tests; @@ -24,12 +25,15 @@ import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.internal.core.model.ASTCache; +import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; /** * Tests for the {@link ASTCache}. @@ -149,24 +153,44 @@ public class ASTCacheTests extends BaseTestCase { } private void checkSingleThreadAccess() throws Exception { - ASTCache cache= new ASTCache(); + final ASTCache cache= new ASTCache(); + final int[] counter= {0}; cache.setActiveElement(fTU1); - IASTTranslationUnit ast; - ast= cache.getAST(fTU1, fIndex, false, null); - assertNull(ast); + IStatus status= cache.runOnAST(fTU1, false, null, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException { + assertNull(ast); + counter[0]++; + return Status.OK_STATUS; + } + }); + assertEquals(1, counter[0]); + IProgressMonitor npm= new NullProgressMonitor(); npm.setCanceled(true); - ast= cache.getAST(fTU1, fIndex, true, npm); - assertNull(ast); + status= cache.runOnAST(fTU1, true, npm, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException { + assertNull(ast); + counter[0]++; + return Status.OK_STATUS; + } + }); + assertEquals(2, counter[0]); + npm.setCanceled(false); - ast= cache.getAST(fTU1, fIndex, true, npm); - assertNotNull(ast); + status= cache.runOnAST(fTU1, true, npm, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException { + assertNotNull(ast); + counter[0]++; + return Status.OK_STATUS; + } + }); + assertEquals(3, counter[0]); } private void checkAccessWithSequentialReconciler() throws Exception { - ASTCache cache= new ASTCache(); - MockReconciler reconciler1= new MockReconciler(fTU1, cache); - MockReconciler reconciler2= new MockReconciler(fTU2, cache); + final ASTCache cache= new ASTCache(); + final MockReconciler reconciler1= new MockReconciler(fTU1, cache); + final MockReconciler reconciler2= new MockReconciler(fTU2, cache); try { cache.setActiveElement(fTU1); assertFalse(cache.isReconciling(fTU1)); @@ -178,12 +202,15 @@ public class ASTCacheTests extends BaseTestCase { assertTrue(cache.isReconciling(fTU1)); } reconciler1.fStopped= true; - IASTTranslationUnit ast; - ast= cache.getAST(fTU1, fIndex, true, null); - assertNotNull(ast); - assertTrue(cache.isActiveElement(fTU1)); - assertFalse(cache.isReconciling(fTU1)); - assertSame(ast, reconciler1.fAST); + IStatus status= cache.runOnAST(fTU1, true, null, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException { + assertNotNull(ast); + assertTrue(cache.isActiveElement(fTU1)); + assertFalse(cache.isReconciling(fTU1)); + assertSame(ast, reconciler1.fAST); + return Status.OK_STATUS; + } + }); // change active element cache.setActiveElement(fTU2); @@ -196,11 +223,16 @@ public class ASTCacheTests extends BaseTestCase { assertTrue(cache.isReconciling(fTU2)); } reconciler2.fStopped= true; - ast= cache.getAST(fTU2, fIndex, true, null); - assertNotNull(ast); - assertTrue(cache.isActiveElement(fTU2)); - assertFalse(cache.isReconciling(fTU2)); - assertSame(ast, reconciler2.fAST); + + status= cache.runOnAST(fTU2, true, null, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException { + assertNotNull(ast); + assertTrue(cache.isActiveElement(fTU2)); + assertFalse(cache.isReconciling(fTU2)); + assertSame(ast, reconciler2.fAST); + return Status.OK_STATUS; + } + }); } finally { reconciler1.fStopped= true; reconciler1.join(1000); @@ -221,27 +253,42 @@ public class ASTCacheTests extends BaseTestCase { while (iterations < 10) { ++iterations; if (DEBUG) System.out.println("iteration="+iterations); - IASTTranslationUnit ast; cache.setActiveElement(fTU1); Thread.sleep(50); - ast = waitForAST(cache, fTU1); - assertNotNull(ast); - assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature()); + waitForAST(cache, fTU1, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) { + assertNotNull(ast); + assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature()); + return Status.OK_STATUS; + } + }); - ast = waitForAST(cache, fTU2); - assertNotNull(ast); - assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature()); + waitForAST(cache, fTU2, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) { + assertNotNull(ast); + assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature()); + return Status.OK_STATUS; + } + }); // change active element cache.setActiveElement(fTU2); Thread.sleep(50); - ast = waitForAST(cache, fTU2); - assertNotNull(ast); - assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature()); + waitForAST(cache, fTU2, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) { + assertNotNull(ast); + assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature()); + return Status.OK_STATUS; + } + }); - ast = waitForAST(cache, fTU1); - assertNotNull(ast); - assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature()); + waitForAST(cache, fTU1, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) { + assertNotNull(ast); + assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature()); + return Status.OK_STATUS; + } + }); } } finally { reconciler1.fStopped= true; @@ -251,13 +298,14 @@ public class ASTCacheTests extends BaseTestCase { } } - private IASTTranslationUnit waitForAST(ASTCache cache, ITranslationUnit tUnit) { + private void waitForAST(ASTCache cache, ITranslationUnit tUnit, ASTRunnable runnable) { if (DEBUG) System.out.println("waiting for "+tUnit.getElementName()); long start= System.currentTimeMillis(); - IASTTranslationUnit ast; - ast= cache.getAST(tUnit, fIndex, true, null); - if (DEBUG) System.out.println("wait time= " + (System.currentTimeMillis() - start)); - return ast; + try { + cache.runOnAST(tUnit, true, null, runnable); + } + finally { + if (DEBUG) System.out.println("wait time= " + (System.currentTimeMillis() - start)); + } } - } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java index 0d05da1e8f4..4368ffde41b 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java @@ -4,14 +4,16 @@ * 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: Anton Leherbauer (Wind River Systems) - initial API and - * implementation + * Contributors: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + * Markus Schorn (Wind River Systems) ******************************************************************************/ package org.eclipse.cdt.internal.core.model; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -51,7 +53,7 @@ public class ASTCache { * @param ast the translation unit AST, may be null * @return a status object */ - IStatus runOnAST(IASTTranslationUnit ast); + IStatus runOnAST(IASTTranslationUnit ast) throws CoreException; } private final int fParseMode; @@ -92,7 +94,7 @@ public class ASTCache { * @param progressMonitor the progress monitor or null * @return the AST or null if the AST is not available */ - public IASTTranslationUnit getAST(ITranslationUnit tUnit, IIndex index, boolean wait, IProgressMonitor progressMonitor) { + private IASTTranslationUnit getAST(ITranslationUnit tUnit, IIndex index, boolean wait, IProgressMonitor progressMonitor) { if (tUnit == null) return null; @@ -193,7 +195,7 @@ public class ASTCache { ASTRunnable astRunnable) { IIndex index; try { - index = CCorePlugin.getIndexManager().getIndex(tUnit.getCProject()); + index = CCorePlugin.getIndexManager().getIndex(tUnit.getCProject(), IIndexManager.ADD_DEPENDENCIES); index.acquireReadLock(); } catch (CoreException e) { return e.getStatus(); @@ -205,6 +207,9 @@ public class ASTCache { IASTTranslationUnit ast= getAST(tUnit, index, wait, monitor); return astRunnable.runOnAST(ast); } + catch (CoreException e) { + return e.getStatus(); + } finally { index.releaseReadLock(); } 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 60101a52e84..0c19442dcdd 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 @@ -154,7 +154,7 @@ public class CallHierarchyUI { index.acquireReadLock(); try { - IASTName name= IndexUI.getSelectedName(index, editorInput, sel); + IASTName name= IndexUI.getSelectedName(editorInput, sel); if (name != null) { IBinding binding= name.resolveBinding(); if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java index 0dd7c8fb29f..bad7442e8e8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java @@ -25,7 +25,6 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; -import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.CUIPlugin; @@ -280,30 +279,6 @@ public final class ASTProvider { fCache.aboutToBeReconciled((ITranslationUnit)cElement); } - /** - * Returns a shared translation unit AST for the given - * C element. - *

- * Clients are not allowed to modify the AST and must - * synchronize all access to its nodes. - *

- * - * @param cElement the C element - * @param index the index used to create the AST, needs to be read-locked. - * @param waitFlag {@link #WAIT_YES}, {@link #WAIT_NO} or {@link #WAIT_ACTIVE_ONLY} - * @param progressMonitor the progress monitor or null - * @return the AST or null if the AST is not available - */ - public IASTTranslationUnit getAST(ICElement cElement, IIndex index, WAIT_FLAG waitFlag, IProgressMonitor progressMonitor) { - if (cElement == null) - return null; - Assert.isTrue(cElement instanceof ITranslationUnit); - if (waitFlag == WAIT_ACTIVE_ONLY && !isActive((ITranslationUnit)cElement)) { - return null; - } - return fCache.getAST((ITranslationUnit)cElement, index, waitFlag != WAIT_NO, progressMonitor); - } - /** * Disposes this AST provider. */ @@ -334,16 +309,5 @@ public final class ASTProvider { } return fCache.runOnAST((ITranslationUnit)cElement, waitFlag != WAIT_NO, monitor, astRunnable); } - - /** - * @param cElement - * @param index - * @param monitor - * @return an AST or null, if no AST could be computed - */ - public IASTTranslationUnit createAST(ICElement cElement, IIndex index, IProgressMonitor monitor) { - Assert.isTrue(cElement instanceof ITranslationUnit); - return fCache.createAST((ITranslationUnit)cElement, index, monitor); - } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java index ddf22436eca..cb0d7d132a8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementHyperlinkDetector.java @@ -8,11 +8,14 @@ * Contributors: * QNX Software Systems - Initial API and implementation * IBM Corporation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.editor; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IAction; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; @@ -33,6 +36,8 @@ import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable; + import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction; public class CElementHyperlinkDetector implements IHyperlinkDetector { @@ -51,16 +56,16 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector { CEditor editor = (CEditor) fTextEditor; int offset = region.getOffset(); - IAction openAction= editor.getAction("OpenDeclarations"); //$NON-NLS-1$ + final IAction openAction= editor.getAction("OpenDeclarations"); //$NON-NLS-1$ if (openAction == null) return null; // reuse the logic from Open Decl that recognizes a word in the editor - ITextSelection selection = OpenDeclarationsAction.selectWord(offset, editor); + final ITextSelection selection = OpenDeclarationsAction.selectWord(offset, editor); if(selection == null) return null; - IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput()); + final IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput()); if (workingCopy == null) { return null; } @@ -79,29 +84,36 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector { return null; } + final IHyperlink[] result= {null}; try { - IASTTranslationUnit ast = - ASTProvider.getASTProvider().getAST(workingCopy, index, ASTProvider.WAIT_YES, null); - IASTName[] selectedNames = - workingCopy.getLanguage().getSelectedNames(ast, selection.getOffset(), selection.getLength()); - - IRegion linkRegion; - if(selectedNames.length > 0 && selectedNames[0] != null) { // found a name - linkRegion = new Region(selection.getOffset(), selection.getLength()); - } - else { // check if we are in an include statement - linkRegion = matchIncludeStatement(ast, selection); - } - - if(linkRegion != null) - return new IHyperlink[] { new CElementHyperlink(linkRegion, openAction) }; - - } catch(CoreException e) { + ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, null, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) { + try { + IASTName[] selectedNames = + workingCopy.getLanguage().getSelectedNames(ast, selection.getOffset(), selection.getLength()); + + IRegion linkRegion; + if(selectedNames.length > 0 && selectedNames[0] != null) { // found a name + linkRegion = new Region(selection.getOffset(), selection.getLength()); + } + else { // check if we are in an include statement + linkRegion = matchIncludeStatement(ast, selection); + } + + if(linkRegion != null) + result[0]= new CElementHyperlink(linkRegion, openAction); + } + catch (CoreException e) { + return e.getStatus(); + } + return Status.OK_STATUS; + } + }); } finally { index.releaseReadLock(); } - return null; + return result[0] == null ? null : result; } 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 88c7ba25bb8..a51903ffaf8 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 @@ -49,6 +49,8 @@ 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.core.model.ASTCache.ASTRunnable; + import org.eclipse.cdt.internal.ui.actions.OpenActionUtil; import org.eclipse.cdt.internal.ui.editor.ASTProvider; import org.eclipse.cdt.internal.ui.editor.CEditor; @@ -70,7 +72,10 @@ public class OpenDeclarationsAction extends SelectionParseAction { setDescription(CEditorMessages.getString("OpenDeclarations.description")); //$NON-NLS-1$ } - private class Runner extends Job { + private class Runner extends Job implements ASTRunnable { + private IWorkingCopy fWorkingCopy; + private IIndex fIndex; + Runner() { super(CEditorMessages.getString("OpenDeclarations.dialog.title")); //$NON-NLS-1$ } @@ -79,116 +84,115 @@ public class OpenDeclarationsAction extends SelectionParseAction { try { clearStatusLine(); - int selectionStart = selNode.getOffset(); - int selectionLength = selNode.getLength(); - - IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput()); - if (workingCopy == null) + fWorkingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput()); + if (fWorkingCopy == null) return Status.CANCEL_STATUS; - IIndex index = CCorePlugin.getIndexManager().getIndex(workingCopy.getCProject(), + fIndex= CCorePlugin.getIndexManager().getIndex(fWorkingCopy.getCProject(), IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT); try { - index.acquireReadLock(); + fIndex.acquireReadLock(); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } - try { - IASTTranslationUnit ast= - ASTProvider.getASTProvider().getAST( - workingCopy, index, ASTProvider.WAIT_YES, monitor); - IASTName[] selectedNames = workingCopy.getLanguage().getSelectedNames(ast, selectionStart, selectionLength); - - if (selectedNames.length > 0 && selectedNames[0] != null) { // just right, only one name selected - boolean found = false; - IASTName searchName = selectedNames[0]; - boolean isDefinition= searchName.isDefinition(); - IBinding binding = searchName.resolveBinding(); - if (binding != null && !(binding instanceof IProblemBinding)) { - IName[] declNames = findNames(index, ast, isDefinition, binding); - if (declNames.length == 0) { - // bug 86829, handle implicit methods. - if (binding instanceof ICPPMethod) { - ICPPMethod method= (ICPPMethod) binding; - if (method.isImplicit()) { - try { - IBinding clsBinding= method.getClassOwner(); - if (clsBinding != null && !(clsBinding instanceof IProblemBinding)) { - declNames= findNames(index, ast, false, clsBinding); - } - } catch (DOMException e) { - CCorePlugin.log(e); - } - } - } - } - 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) { - reportSymbolLookupFailure(new String(searchName.toCharArray())); - } - - } else { - // Check if we're in an include statement - IASTPreprocessorStatement[] preprocs = ast.getAllPreprocessorStatements(); - boolean foundInInclude = false; - 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 - foundInInclude = true; - String name = null; - if (incStmt.isResolved()) - name = incStmt.getPath(); - - if (name != null) { - final IPath path = new Path(name); - runInUIThread(new Runnable() { - public void run() { - try { - open(path, 0, 0); - } catch (CoreException e) { - CUIPlugin.getDefault().log(e); - } - } - }); - } else { - reportIncludeLookupFailure(new String(incStmt.getName().toCharArray())); - } - - break; - } - if (!foundInInclude) { - reportSelectionMatchFailure(); - } - } - } + return ASTProvider.getASTProvider().runOnAST(fWorkingCopy, ASTProvider.WAIT_YES, monitor, this); } finally { - index.releaseReadLock(); + fIndex.releaseReadLock(); } - - return Status.OK_STATUS; } catch (CoreException e) { return e.getStatus(); } } + public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException { + int selectionStart = selNode.getOffset(); + int selectionLength = selNode.getLength(); + + IASTName[] selectedNames = fWorkingCopy.getLanguage().getSelectedNames(ast, selectionStart, selectionLength); + + if (selectedNames.length > 0 && selectedNames[0] != null) { // just right, only one name selected + boolean found = false; + IASTName searchName = selectedNames[0]; + boolean isDefinition= searchName.isDefinition(); + IBinding binding = searchName.resolveBinding(); + if (binding != null && !(binding instanceof IProblemBinding)) { + IName[] declNames = findNames(fIndex, ast, isDefinition, binding); + if (declNames.length == 0) { + // bug 86829, handle implicit methods. + if (binding instanceof ICPPMethod) { + ICPPMethod method= (ICPPMethod) binding; + if (method.isImplicit()) { + try { + IBinding clsBinding= method.getClassOwner(); + if (clsBinding != null && !(clsBinding instanceof IProblemBinding)) { + declNames= findNames(fIndex, ast, false, clsBinding); + } + } catch (DOMException e) { + CCorePlugin.log(e); + } + } + } + } + if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, 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) { + reportSymbolLookupFailure(new String(searchName.toCharArray())); + } + + } else { + // Check if we're in an include statement + IASTPreprocessorStatement[] preprocs = ast.getAllPreprocessorStatements(); + boolean foundInInclude = false; + 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 + foundInInclude = true; + String name = null; + if (incStmt.isResolved()) + name = incStmt.getPath(); + + if (name != null) { + final IPath path = new Path(name); + runInUIThread(new Runnable() { + public void run() { + try { + open(path, 0, 0); + } catch (CoreException e) { + CUIPlugin.getDefault().log(e); + } + } + }); + } else { + reportIncludeLookupFailure(new String(incStmt.getName().toCharArray())); + } + + break; + } + if (!foundInInclude) { + reportSelectionMatchFailure(); + } + } + } + return Status.OK_STATUS; + } + private boolean navigateOneLocation(IName[] declNames) { for (int i = 0; i < declNames.length; i++) { IASTFileLocation fileloc = declNames[i].getFileLocation(); 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 e1320080cfb..a5130a1a3d1 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 @@ -17,8 +17,10 @@ import java.util.ArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Region; @@ -54,6 +56,7 @@ 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.core.model.ASTCache.ASTRunnable; import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory; import org.eclipse.cdt.internal.core.model.ext.ICElementHandle; @@ -238,18 +241,23 @@ public class IndexUI { return null; } - public static IASTName getSelectedName(IIndex index, IEditorInput editorInput, ITextSelection selection) throws CoreException { - int selectionStart = selection.getOffset(); - int selectionLength = selection.getLength(); + public static IASTName getSelectedName(IEditorInput editorInput, ITextSelection selection) throws CoreException { + final int selectionStart = selection.getOffset(); + final int selectionLength = selection.getLength(); IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editorInput); if (workingCopy == null) return null; - IASTTranslationUnit ast= ASTProvider.getASTProvider().getAST( - workingCopy, index, ASTProvider.WAIT_YES, new NullProgressMonitor()); - FindNameForSelectionVisitor finder= new FindNameForSelectionVisitor(ast.getFilePath(), selectionStart, selectionLength); - ast.accept(finder); - return finder.getSelectedName(); + final IASTName[] result= {null}; + ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, null, new ASTRunnable() { + public IStatus runOnAST(IASTTranslationUnit ast) { + FindNameForSelectionVisitor finder= new FindNameForSelectionVisitor(ast.getFilePath(), selectionStart, selectionLength); + ast.accept(finder); + result[0]= finder.getSelectedName(); + return Status.OK_STATUS; + } + }); + return result[0]; } }