mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
Fix for 188282, potential use of unlocked index.
This commit is contained in:
parent
dc82b160c3
commit
d1db017310
7 changed files with 247 additions and 206 deletions
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.model.tests;
|
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.BaseTestCase;
|
||||||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||||
import org.eclipse.cdt.internal.core.model.ASTCache;
|
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.IContainer;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
import org.eclipse.core.runtime.Path;
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the {@link ASTCache}.
|
* Tests for the {@link ASTCache}.
|
||||||
|
@ -149,24 +153,44 @@ public class ASTCacheTests extends BaseTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSingleThreadAccess() throws Exception {
|
private void checkSingleThreadAccess() throws Exception {
|
||||||
ASTCache cache= new ASTCache();
|
final ASTCache cache= new ASTCache();
|
||||||
|
final int[] counter= {0};
|
||||||
cache.setActiveElement(fTU1);
|
cache.setActiveElement(fTU1);
|
||||||
IASTTranslationUnit ast;
|
IStatus status= cache.runOnAST(fTU1, false, null, new ASTRunnable() {
|
||||||
ast= cache.getAST(fTU1, fIndex, false, null);
|
public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException {
|
||||||
assertNull(ast);
|
assertNull(ast);
|
||||||
|
counter[0]++;
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(1, counter[0]);
|
||||||
|
|
||||||
IProgressMonitor npm= new NullProgressMonitor();
|
IProgressMonitor npm= new NullProgressMonitor();
|
||||||
npm.setCanceled(true);
|
npm.setCanceled(true);
|
||||||
ast= cache.getAST(fTU1, fIndex, true, npm);
|
status= cache.runOnAST(fTU1, true, npm, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException {
|
||||||
assertNull(ast);
|
assertNull(ast);
|
||||||
|
counter[0]++;
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(2, counter[0]);
|
||||||
|
|
||||||
npm.setCanceled(false);
|
npm.setCanceled(false);
|
||||||
ast= cache.getAST(fTU1, fIndex, true, npm);
|
status= cache.runOnAST(fTU1, true, npm, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
|
counter[0]++;
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(3, counter[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAccessWithSequentialReconciler() throws Exception {
|
private void checkAccessWithSequentialReconciler() throws Exception {
|
||||||
ASTCache cache= new ASTCache();
|
final ASTCache cache= new ASTCache();
|
||||||
MockReconciler reconciler1= new MockReconciler(fTU1, cache);
|
final MockReconciler reconciler1= new MockReconciler(fTU1, cache);
|
||||||
MockReconciler reconciler2= new MockReconciler(fTU2, cache);
|
final MockReconciler reconciler2= new MockReconciler(fTU2, cache);
|
||||||
try {
|
try {
|
||||||
cache.setActiveElement(fTU1);
|
cache.setActiveElement(fTU1);
|
||||||
assertFalse(cache.isReconciling(fTU1));
|
assertFalse(cache.isReconciling(fTU1));
|
||||||
|
@ -178,12 +202,15 @@ public class ASTCacheTests extends BaseTestCase {
|
||||||
assertTrue(cache.isReconciling(fTU1));
|
assertTrue(cache.isReconciling(fTU1));
|
||||||
}
|
}
|
||||||
reconciler1.fStopped= true;
|
reconciler1.fStopped= true;
|
||||||
IASTTranslationUnit ast;
|
IStatus status= cache.runOnAST(fTU1, true, null, new ASTRunnable() {
|
||||||
ast= cache.getAST(fTU1, fIndex, true, null);
|
public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
assertTrue(cache.isActiveElement(fTU1));
|
assertTrue(cache.isActiveElement(fTU1));
|
||||||
assertFalse(cache.isReconciling(fTU1));
|
assertFalse(cache.isReconciling(fTU1));
|
||||||
assertSame(ast, reconciler1.fAST);
|
assertSame(ast, reconciler1.fAST);
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// change active element
|
// change active element
|
||||||
cache.setActiveElement(fTU2);
|
cache.setActiveElement(fTU2);
|
||||||
|
@ -196,11 +223,16 @@ public class ASTCacheTests extends BaseTestCase {
|
||||||
assertTrue(cache.isReconciling(fTU2));
|
assertTrue(cache.isReconciling(fTU2));
|
||||||
}
|
}
|
||||||
reconciler2.fStopped= true;
|
reconciler2.fStopped= true;
|
||||||
ast= cache.getAST(fTU2, fIndex, true, null);
|
|
||||||
|
status= cache.runOnAST(fTU2, true, null, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) throws CoreException {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
assertTrue(cache.isActiveElement(fTU2));
|
assertTrue(cache.isActiveElement(fTU2));
|
||||||
assertFalse(cache.isReconciling(fTU2));
|
assertFalse(cache.isReconciling(fTU2));
|
||||||
assertSame(ast, reconciler2.fAST);
|
assertSame(ast, reconciler2.fAST);
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
reconciler1.fStopped= true;
|
reconciler1.fStopped= true;
|
||||||
reconciler1.join(1000);
|
reconciler1.join(1000);
|
||||||
|
@ -221,27 +253,42 @@ public class ASTCacheTests extends BaseTestCase {
|
||||||
while (iterations < 10) {
|
while (iterations < 10) {
|
||||||
++iterations;
|
++iterations;
|
||||||
if (DEBUG) System.out.println("iteration="+iterations);
|
if (DEBUG) System.out.println("iteration="+iterations);
|
||||||
IASTTranslationUnit ast;
|
|
||||||
cache.setActiveElement(fTU1);
|
cache.setActiveElement(fTU1);
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
ast = waitForAST(cache, fTU1);
|
waitForAST(cache, fTU1, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature());
|
assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature());
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ast = waitForAST(cache, fTU2);
|
waitForAST(cache, fTU2, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature());
|
assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature());
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// change active element
|
// change active element
|
||||||
cache.setActiveElement(fTU2);
|
cache.setActiveElement(fTU2);
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
ast = waitForAST(cache, fTU2);
|
waitForAST(cache, fTU2, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature());
|
assertEquals("void foo2() {}", ast.getDeclarations()[0].getRawSignature());
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ast = waitForAST(cache, fTU1);
|
waitForAST(cache, fTU1, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) {
|
||||||
assertNotNull(ast);
|
assertNotNull(ast);
|
||||||
assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature());
|
assertEquals("void foo1() {}", ast.getDeclarations()[0].getRawSignature());
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
reconciler1.fStopped= true;
|
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());
|
if (DEBUG) System.out.println("waiting for "+tUnit.getElementName());
|
||||||
long start= System.currentTimeMillis();
|
long start= System.currentTimeMillis();
|
||||||
IASTTranslationUnit ast;
|
try {
|
||||||
ast= cache.getAST(tUnit, fIndex, true, null);
|
cache.runOnAST(tUnit, true, null, runnable);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
if (DEBUG) System.out.println("wait time= " + (System.currentTimeMillis() - start));
|
if (DEBUG) System.out.println("wait time= " + (System.currentTimeMillis() - start));
|
||||||
return ast;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,16 @@
|
||||||
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
|
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
|
||||||
* and is available at http://www.eclipse.org/legal/epl-v10.html
|
* and is available at http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors: Anton Leherbauer (Wind River Systems) - initial API and
|
* Contributors:
|
||||||
* implementation
|
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.model;
|
package org.eclipse.cdt.internal.core.model;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.index.IIndex;
|
import org.eclipse.cdt.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.core.index.IIndexManager;
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
@ -51,7 +53,7 @@ public class ASTCache {
|
||||||
* @param ast the translation unit AST, may be <code>null</code>
|
* @param ast the translation unit AST, may be <code>null</code>
|
||||||
* @return a status object
|
* @return a status object
|
||||||
*/
|
*/
|
||||||
IStatus runOnAST(IASTTranslationUnit ast);
|
IStatus runOnAST(IASTTranslationUnit ast) throws CoreException;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int fParseMode;
|
private final int fParseMode;
|
||||||
|
@ -92,7 +94,7 @@ public class ASTCache {
|
||||||
* @param progressMonitor the progress monitor or <code>null</code>
|
* @param progressMonitor the progress monitor or <code>null</code>
|
||||||
* @return the AST or <code>null</code> if the AST is not available
|
* @return the AST or <code>null</code> 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)
|
if (tUnit == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -193,7 +195,7 @@ public class ASTCache {
|
||||||
ASTRunnable astRunnable) {
|
ASTRunnable astRunnable) {
|
||||||
IIndex index;
|
IIndex index;
|
||||||
try {
|
try {
|
||||||
index = CCorePlugin.getIndexManager().getIndex(tUnit.getCProject());
|
index = CCorePlugin.getIndexManager().getIndex(tUnit.getCProject(), IIndexManager.ADD_DEPENDENCIES);
|
||||||
index.acquireReadLock();
|
index.acquireReadLock();
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
return e.getStatus();
|
return e.getStatus();
|
||||||
|
@ -205,6 +207,9 @@ public class ASTCache {
|
||||||
IASTTranslationUnit ast= getAST(tUnit, index, wait, monitor);
|
IASTTranslationUnit ast= getAST(tUnit, index, wait, monitor);
|
||||||
return astRunnable.runOnAST(ast);
|
return astRunnable.runOnAST(ast);
|
||||||
}
|
}
|
||||||
|
catch (CoreException e) {
|
||||||
|
return e.getStatus();
|
||||||
|
}
|
||||||
finally {
|
finally {
|
||||||
index.releaseReadLock();
|
index.releaseReadLock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ public class CallHierarchyUI {
|
||||||
|
|
||||||
index.acquireReadLock();
|
index.acquireReadLock();
|
||||||
try {
|
try {
|
||||||
IASTName name= IndexUI.getSelectedName(index, editorInput, sel);
|
IASTName name= IndexUI.getSelectedName(editorInput, sel);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
IBinding binding= name.resolveBinding();
|
IBinding binding= name.resolveBinding();
|
||||||
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
|
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.eclipse.ui.IWorkbenchWindow;
|
||||||
import org.eclipse.ui.PlatformUI;
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
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.ICElement;
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
@ -280,30 +279,6 @@ public final class ASTProvider {
|
||||||
fCache.aboutToBeReconciled((ITranslationUnit)cElement);
|
fCache.aboutToBeReconciled((ITranslationUnit)cElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a shared translation unit AST for the given
|
|
||||||
* C element.
|
|
||||||
* <p>
|
|
||||||
* Clients are not allowed to modify the AST and must
|
|
||||||
* synchronize all access to its nodes.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @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 <code>null</code>
|
|
||||||
* @return the AST or <code>null</code> 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.
|
* Disposes this AST provider.
|
||||||
*/
|
*/
|
||||||
|
@ -334,16 +309,5 @@ public final class ASTProvider {
|
||||||
}
|
}
|
||||||
return fCache.runOnAST((ITranslationUnit)cElement, waitFlag != WAIT_NO, monitor, astRunnable);
|
return fCache.runOnAST((ITranslationUnit)cElement, waitFlag != WAIT_NO, monitor, astRunnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cElement
|
|
||||||
* @param index
|
|
||||||
* @param monitor
|
|
||||||
* @return an AST or <code>null</code>, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* QNX Software Systems - Initial API and implementation
|
* QNX Software Systems - Initial API and implementation
|
||||||
* IBM Corporation
|
* IBM Corporation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
package org.eclipse.cdt.internal.ui.editor;
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
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.action.IAction;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.ITextSelection;
|
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.core.model.IWorkingCopy;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction;
|
import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction;
|
||||||
|
|
||||||
public class CElementHyperlinkDetector implements IHyperlinkDetector {
|
public class CElementHyperlinkDetector implements IHyperlinkDetector {
|
||||||
|
@ -51,16 +56,16 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector {
|
||||||
CEditor editor = (CEditor) fTextEditor;
|
CEditor editor = (CEditor) fTextEditor;
|
||||||
int offset = region.getOffset();
|
int offset = region.getOffset();
|
||||||
|
|
||||||
IAction openAction= editor.getAction("OpenDeclarations"); //$NON-NLS-1$
|
final IAction openAction= editor.getAction("OpenDeclarations"); //$NON-NLS-1$
|
||||||
if (openAction == null)
|
if (openAction == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// reuse the logic from Open Decl that recognizes a word in the editor
|
// 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)
|
if(selection == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
|
final IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
|
||||||
if (workingCopy == null) {
|
if (workingCopy == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +84,11 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final IHyperlink[] result= {null};
|
||||||
|
try {
|
||||||
|
ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, null, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) {
|
||||||
try {
|
try {
|
||||||
IASTTranslationUnit ast =
|
|
||||||
ASTProvider.getASTProvider().getAST(workingCopy, index, ASTProvider.WAIT_YES, null);
|
|
||||||
IASTName[] selectedNames =
|
IASTName[] selectedNames =
|
||||||
workingCopy.getLanguage().getSelectedNames(ast, selection.getOffset(), selection.getLength());
|
workingCopy.getLanguage().getSelectedNames(ast, selection.getOffset(), selection.getLength());
|
||||||
|
|
||||||
|
@ -94,14 +101,19 @@ public class CElementHyperlinkDetector implements IHyperlinkDetector {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(linkRegion != null)
|
if(linkRegion != null)
|
||||||
return new IHyperlink[] { new CElementHyperlink(linkRegion, openAction) };
|
result[0]= new CElementHyperlink(linkRegion, openAction);
|
||||||
|
}
|
||||||
} catch(CoreException e) {
|
catch (CoreException e) {
|
||||||
|
return e.getStatus();
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
index.releaseReadLock();
|
index.releaseReadLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return result[0] == null ? null : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ import org.eclipse.cdt.core.model.util.CElementBaseLabels;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
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.actions.OpenActionUtil;
|
||||||
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
|
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
|
||||||
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
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$
|
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() {
|
Runner() {
|
||||||
super(CEditorMessages.getString("OpenDeclarations.dialog.title")); //$NON-NLS-1$
|
super(CEditorMessages.getString("OpenDeclarations.dialog.title")); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
@ -79,28 +84,34 @@ public class OpenDeclarationsAction extends SelectionParseAction {
|
||||||
try {
|
try {
|
||||||
clearStatusLine();
|
clearStatusLine();
|
||||||
|
|
||||||
int selectionStart = selNode.getOffset();
|
fWorkingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
|
||||||
int selectionLength = selNode.getLength();
|
if (fWorkingCopy == null)
|
||||||
|
|
||||||
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
|
|
||||||
if (workingCopy == null)
|
|
||||||
return Status.CANCEL_STATUS;
|
return Status.CANCEL_STATUS;
|
||||||
|
|
||||||
IIndex index = CCorePlugin.getIndexManager().getIndex(workingCopy.getCProject(),
|
fIndex= CCorePlugin.getIndexManager().getIndex(fWorkingCopy.getCProject(),
|
||||||
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT);
|
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
index.acquireReadLock();
|
fIndex.acquireReadLock();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return Status.CANCEL_STATUS;
|
return Status.CANCEL_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IASTTranslationUnit ast=
|
return ASTProvider.getASTProvider().runOnAST(fWorkingCopy, ASTProvider.WAIT_YES, monitor, this);
|
||||||
ASTProvider.getASTProvider().getAST(
|
} finally {
|
||||||
workingCopy, index, ASTProvider.WAIT_YES, monitor);
|
fIndex.releaseReadLock();
|
||||||
IASTName[] selectedNames = workingCopy.getLanguage().getSelectedNames(ast, selectionStart, selectionLength);
|
}
|
||||||
|
} 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
|
if (selectedNames.length > 0 && selectedNames[0] != null) { // just right, only one name selected
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
@ -108,7 +119,7 @@ public class OpenDeclarationsAction extends SelectionParseAction {
|
||||||
boolean isDefinition= searchName.isDefinition();
|
boolean isDefinition= searchName.isDefinition();
|
||||||
IBinding binding = searchName.resolveBinding();
|
IBinding binding = searchName.resolveBinding();
|
||||||
if (binding != null && !(binding instanceof IProblemBinding)) {
|
if (binding != null && !(binding instanceof IProblemBinding)) {
|
||||||
IName[] declNames = findNames(index, ast, isDefinition, binding);
|
IName[] declNames = findNames(fIndex, ast, isDefinition, binding);
|
||||||
if (declNames.length == 0) {
|
if (declNames.length == 0) {
|
||||||
// bug 86829, handle implicit methods.
|
// bug 86829, handle implicit methods.
|
||||||
if (binding instanceof ICPPMethod) {
|
if (binding instanceof ICPPMethod) {
|
||||||
|
@ -117,7 +128,7 @@ public class OpenDeclarationsAction extends SelectionParseAction {
|
||||||
try {
|
try {
|
||||||
IBinding clsBinding= method.getClassOwner();
|
IBinding clsBinding= method.getClassOwner();
|
||||||
if (clsBinding != null && !(clsBinding instanceof IProblemBinding)) {
|
if (clsBinding != null && !(clsBinding instanceof IProblemBinding)) {
|
||||||
declNames= findNames(index, ast, false, clsBinding);
|
declNames= findNames(fIndex, ast, false, clsBinding);
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
|
@ -125,7 +136,7 @@ public class OpenDeclarationsAction extends SelectionParseAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (navigateViaCElements(workingCopy.getCProject(), index, declNames)) {
|
if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, declNames)) {
|
||||||
found= true;
|
found= true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -179,14 +190,7 @@ public class OpenDeclarationsAction extends SelectionParseAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
index.releaseReadLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
} catch (CoreException e) {
|
|
||||||
return e.getStatus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean navigateOneLocation(IName[] declNames) {
|
private boolean navigateOneLocation(IName[] declNames) {
|
||||||
|
|
|
@ -17,8 +17,10 @@ import java.util.ArrayList;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
import org.eclipse.core.runtime.Path;
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.ITextSelection;
|
import org.eclipse.jface.text.ITextSelection;
|
||||||
import org.eclipse.jface.text.Region;
|
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.core.model.IWorkingCopy;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
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.CElementHandleFactory;
|
||||||
import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
|
import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
|
||||||
|
|
||||||
|
@ -238,18 +241,23 @@ public class IndexUI {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IASTName getSelectedName(IIndex index, IEditorInput editorInput, ITextSelection selection) throws CoreException {
|
public static IASTName getSelectedName(IEditorInput editorInput, ITextSelection selection) throws CoreException {
|
||||||
int selectionStart = selection.getOffset();
|
final int selectionStart = selection.getOffset();
|
||||||
int selectionLength = selection.getLength();
|
final int selectionLength = selection.getLength();
|
||||||
|
|
||||||
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editorInput);
|
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editorInput);
|
||||||
if (workingCopy == null)
|
if (workingCopy == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
IASTTranslationUnit ast= ASTProvider.getASTProvider().getAST(
|
final IASTName[] result= {null};
|
||||||
workingCopy, index, ASTProvider.WAIT_YES, new NullProgressMonitor());
|
ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_YES, null, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(IASTTranslationUnit ast) {
|
||||||
FindNameForSelectionVisitor finder= new FindNameForSelectionVisitor(ast.getFilePath(), selectionStart, selectionLength);
|
FindNameForSelectionVisitor finder= new FindNameForSelectionVisitor(ast.getFilePath(), selectionStart, selectionLength);
|
||||||
ast.accept(finder);
|
ast.accept(finder);
|
||||||
return finder.getSelectedName();
|
result[0]= finder.getSelectedName();
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue