1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-31 12:55:40 +02:00

Bug 324232 - CElementHyperlinkDetector blocks UI thread waiting for an AST

This commit is contained in:
Sergey Prigogin 2010-09-11 18:25:29 +00:00
parent b24433c8de
commit 1d45ebec18
2 changed files with 28 additions and 9 deletions

View file

@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* IBM Corporation - initial API and implementation * IBM Corporation - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.ui.tests.text; package org.eclipse.cdt.ui.tests.text;
@ -15,17 +16,27 @@ import junit.framework.TestSuite;
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.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region; import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.ICContainer; import org.eclipse.cdt.core.model.ICContainer;
import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IWorkingCopyManager;
import org.eclipse.cdt.ui.testplugin.EditorTestHelper; import org.eclipse.cdt.ui.testplugin.EditorTestHelper;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.editor.CEditor; import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.CElementHyperlinkDetector; import org.eclipse.cdt.internal.ui.editor.CElementHyperlinkDetector;
@ -37,7 +48,6 @@ import org.eclipse.cdt.internal.ui.editor.CElementHyperlinkDetector;
* @author Mike Kucera * @author Mike Kucera
*/ */
public class HyperlinkTest extends TestCase { public class HyperlinkTest extends TestCase {
private static final String CPP_FILE_NAME = "hyperlink_test_cpp.cpp"; private static final String CPP_FILE_NAME = "hyperlink_test_cpp.cpp";
private static final String CPP_CODE = private static final String CPP_CODE =
"#include <stdio.h> \n" + "#include <stdio.h> \n" +
@ -76,7 +86,6 @@ public class HyperlinkTest extends TestCase {
private ICProject project; private ICProject project;
private CEditor editor; private CEditor editor;
public static TestSuite suite() { public static TestSuite suite() {
return new TestSuite(HyperlinkTest.class); return new TestSuite(HyperlinkTest.class);
} }
@ -85,12 +94,21 @@ public class HyperlinkTest extends TestCase {
super.setUp(); super.setUp();
project= CProjectHelper.createCCProject(super.getName(), "unused", IPDOMManager.ID_NO_INDEXER); project= CProjectHelper.createCCProject(super.getName(), "unused", IPDOMManager.ID_NO_INDEXER);
ICContainer cContainer= CProjectHelper.addCContainer(project, "src"); ICContainer cContainer= CProjectHelper.addCContainer(project, "src");
IFile file= EditorTestHelper.createFile((IContainer)cContainer.getResource(), fileName, code, new NullProgressMonitor()); IFile file= EditorTestHelper.createFile((IContainer) cContainer.getResource(), fileName, code, new NullProgressMonitor());
assertNotNull(file); assertNotNull(file);
assertTrue(file.exists()); assertTrue(file.exists());
editor = (CEditor)EditorTestHelper.openInEditor(file, true); editor = (CEditor) EditorTestHelper.openInEditor(file, true);
EditorTestHelper.joinReconciler(EditorTestHelper.getSourceViewer(editor), 10, 1000, 10); EditorTestHelper.joinReconciler(EditorTestHelper.getSourceViewer(editor), 10, 1000, 10);
// Since CElementHyperlinkDetector doesn't wait for an AST to be created,
// we trigger AST creation ahead of time.
IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager();
IWorkingCopy workingCopy = manager.getWorkingCopy(editor.getEditorInput());
IStatus status= ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_IF_OPEN, null, new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
return Status.OK_STATUS;
}
});
} }
@Override @Override
@ -119,8 +137,7 @@ public class HyperlinkTest extends TestCase {
IHyperlink[] links = getHyperlinks(mouseOffset); IHyperlink[] links = getHyperlinks(mouseOffset);
assertNull(links); assertNull(links);
} }
public void testHyperlinksCpp() throws Exception { public void testHyperlinksCpp() throws Exception {
// entire include highlighted // entire include highlighted
setUpEditor(CPP_FILE_NAME, CPP_CODE); setUpEditor(CPP_FILE_NAME, CPP_CODE);
@ -129,9 +146,9 @@ public class HyperlinkTest extends TestCase {
assertHyperlink(CPP_CODE.indexOf("<stdio.h>") + 2, 0, "#include <stdio.h>".length()); assertHyperlink(CPP_CODE.indexOf("<stdio.h>") + 2, 0, "#include <stdio.h>".length());
assertHyperlink(CPP_CODE.indexOf("<stdio.h>") + "<stdio.h".length(), 0, "#include <stdio.h>".length()); assertHyperlink(CPP_CODE.indexOf("<stdio.h>") + "<stdio.h".length(), 0, "#include <stdio.h>".length());
// hovering over the whitspace inside an include still results in a hyperlink // hovering over the whitespace inside an include still results in a hyperlink
assertHyperlink(CPP_CODE.indexOf("<stdio.h>") - 1, 0, "#include <stdio.h>".length()); assertHyperlink(CPP_CODE.indexOf("<stdio.h>") - 1, 0, "#include <stdio.h>".length());
// no hyperlinks in macro bodies // no hyperlinks in macro bodies
assertNotHyperlink(CPP_CODE.indexOf("#define") + 1); assertNotHyperlink(CPP_CODE.indexOf("#define") + 1);
assertHyperlink(CPP_CODE.indexOf("SOMEMACRO"), CPP_CODE.indexOf("SOMEMACRO"), "SOMEMACRO".length()); assertHyperlink(CPP_CODE.indexOf("SOMEMACRO"), CPP_CODE.indexOf("SOMEMACRO"), "SOMEMACRO".length());

View file

@ -73,7 +73,9 @@ public class CElementHyperlinkDetector extends AbstractHyperlinkDetector {
} }
final IHyperlink[] result= {null}; final IHyperlink[] result= {null};
IStatus status= ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_ACTIVE_ONLY, null, new ASTRunnable() { // Do not wait for AST if it's not available yet. Waiting for AST would block the UI thread
// for the duration of the parsing.
IStatus status= ASTProvider.getASTProvider().runOnAST(workingCopy, ASTProvider.WAIT_NO, null, new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) { public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
if (ast != null) { if (ast != null) {
final int offset= region.getOffset(); final int offset= region.getOffset();