/*******************************************************************************
* Copyright (c) 2006, 2010 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Andrew Eidsness - fix and test for bug 278632
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.filesystem.provider.FileSystem;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.testplugin.Accessor;
import org.eclipse.cdt.ui.testplugin.DisplayHelper;
import org.eclipse.cdt.ui.testplugin.EditorTestHelper;
import org.eclipse.cdt.ui.testplugin.FileTool;
import org.eclipse.cdt.ui.testplugin.ResourceTestHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.ui.text.ICColorConstants;
import org.eclipse.cdt.ui.text.IColorManager;
import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
/**
* Basic CEditor tests.
*
* @since 4.0
*/
public class BasicCEditorTest extends BaseUITestCase {
final static class TestDocListener implements IDocumentListener {
public boolean fDocChanged;
public void documentAboutToBeChanged(DocumentEvent event) {
}
public void documentChanged(DocumentEvent event) {
fDocChanged= true;
}
}
public static class Bug278632FileSystem extends FileSystem {
public Bug278632FileSystem() {
getClass();
}
@Override
public IFileStore getStore(URI uri) {
try {
// For the test case, this just return the FS implementation
// used for the null filesystem.
// In a real application this would be a real implementation,
// however for the purposes
// of exposing the bug, any non-file:// scheme will do.
return EFS.getStore(new URI(
EFS.getNullFileSystem().getScheme(), uri
.getSchemeSpecificPart(), null));
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
} catch (CoreException e) {
e.printStackTrace();
return null;
}
}
}
private static CEditor fEditor;
private static SourceViewer fSourceViewer;
private ICProject fCProject;
private IProject fNonCProject;
private StyledText fTextWidget;
private Accessor fAccessor;
private IDocument fDocument;
private TestDocListener fDocListener= new TestDocListener();
public static Test suite() {
return new TestSuite(BasicCEditorTest.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown () throws Exception {
EditorTestHelper.closeEditor(fEditor);
if (fCProject != null)
CProjectHelper.delete(fCProject);
if (fNonCProject != null) {
ResourceHelper.delete(fNonCProject);
}
super.tearDown();
}
private void setUpEditor(IFile file) throws PartInitException {
IEditorPart editor= EditorTestHelper.openInEditor(file, true);
assertNotNull(editor);
assertTrue(editor instanceof CEditor);
fEditor= (CEditor) editor;
fTextWidget= fEditor.getViewer().getTextWidget();
assertNotNull(fTextWidget);
fAccessor= new Accessor(fTextWidget, StyledText.class);
fDocument= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
assertNotNull(fDocument);
}
private void setUpEditor(String file) throws PartInitException {
setUpEditor(ResourceTestHelper.findFile(file));
}
private void setUpEditor(File file) throws PartInitException, CModelException {
IEditorPart editor= EditorUtility.openInEditor(new ExternalTranslationUnit(fCProject, file.toURI(), CCorePlugin.CONTENT_TYPE_CXXSOURCE));
assertNotNull(editor);
assertTrue(editor instanceof CEditor);
fEditor= (CEditor) editor;
fTextWidget= fEditor.getViewer().getTextWidget();
assertNotNull(fTextWidget);
fAccessor= new Accessor(fTextWidget, StyledText.class);
fDocument= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
assertNotNull(fDocument);
}
private void setUpEditorUsingFileStore(File file) throws CoreException {
final IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IEditorPart editor= IDE.openEditorOnFileStore(activePage, EFS.getStore(URIUtil.toURI(file.getAbsolutePath())));
assertNotNull(editor);
assertTrue(editor instanceof CEditor);
fEditor= (CEditor) editor;
fTextWidget= fEditor.getViewer().getTextWidget();
assertNotNull(fTextWidget);
fAccessor= new Accessor(fTextWidget, StyledText.class);
fDocument= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
assertNotNull(fDocument);
}
public void testEditTranslationUnit() throws Exception {
final String file= "/ceditor/src/main.cpp";
fCProject= EditorTestHelper.createCProject("ceditor", "resources/ceditor", false, false);
IFile mainFile= ResourceTestHelper.findFile(file);
assertNotNull(mainFile);
setUpEditor(mainFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
String content= fDocument.get();
setCaret(0);
String newtext= "/* "+getName()+" */";
type(newtext);
type('\n');
String newContent= fDocument.get();
assertEquals("Edit failed", newtext, newContent.substring(0, newtext.length()));
// save
fEditor.doSave(new NullProgressMonitor());
assertFalse("Editor is still dirty", fEditor.isDirty());
// close and reopen
EditorTestHelper.closeEditor(fEditor);
setUpEditor(mainFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
content= fDocument.get();
assertEquals("Save failed", newContent, content);
// check reconciler
ITranslationUnit tUnit= (ITranslationUnit)fEditor.getInputCElement();
ICElement[] children= tUnit.getChildren();
assertEquals(2, children.length);
setCaret(content.length());
type('\n');
type("void func() {}\n");
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
children= tUnit.getChildren();
assertEquals(3, children.length);
}
//{Point.cpp}
//#include <math.h>
//class Point {
//public:
// Point(double xc, double yc) :
// x(xc), y(yc) {}
// double distance(const Point& other) const;
// int compareX(const Point& other) const;
// double x;
// double y;
//};
//double Point::distance(const Point& other) const {
// double dx = x - other.x;
// double dy = y - other.y;
// return sqrt(dx * dx + dy * dy);
//}
//int Point::compareX(const Point& other) const {
// if (x < other.x) {
// return -1;
// }
// else if (x > other.x) {
// return 1;
// }
// else {
// return 0;
// }
//}
//
public void testEditNewTranslationUnit() throws Exception {
fCProject= EditorTestHelper.createCProject("ceditor", "resources/ceditor", false, false);
IFile newFile= createFile(fCProject.getProject(), "Point.cpp", "");
assertNotNull(newFile);
setUpEditor(newFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
String content= fDocument.get();
setCaret(0);
String newText= "/* "+getName()+" */\n";
newText += readTaggedComment("Point.cpp");
String[] lines= newText.split("\\r\\n|\\r|\\n");
for (int i = 0; i < lines.length; i++) {
String line= lines[i].trim();
if (line.startsWith("}")) {
setCaret(fDocument.get().indexOf(line, getCaret())+line.length());
Thread.sleep(100);
} else {
if (i > 0) type('\n');
type(line);
Thread.sleep(50);
}
}
String newContent= fDocument.get();
String[] newLines= newContent.split("\\r\\n|\\r|\\n");
for (int i = 0; i < lines.length; i++) {
String line= lines[i];
assertEquals(line, newLines[i]);
}
// save
fEditor.doSave(new NullProgressMonitor());
assertFalse("Editor is still dirty", fEditor.isDirty());
// close and reopen
EditorTestHelper.closeEditor(fEditor);
setUpEditor(newFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
content= fDocument.get().trim();
assertEquals("Save failed", newContent, content);
// check reconciler
ITranslationUnit tUnit= (ITranslationUnit)fEditor.getInputCElement();
ICElement[] children= tUnit.getChildren();
assertEquals(4, children.length);
setCaret(content.length());
type('\n');
type("void func() {}\n");
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
children= tUnit.getChildren();
assertEquals(5, children.length);
}
public void testEditInNonCProject() throws Exception {
final String file= "/ceditor/src/main.cpp";
fNonCProject= EditorTestHelper.createNonCProject("ceditor", "resources/ceditor", false);
setUpEditor(file);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
String content= fDocument.get();
setCaret(0);
String newtext= "/* "+getName()+" */";
type(newtext);
type('\n');
String newContent= fDocument.get();
assertEquals("Edit failed", newtext, newContent.substring(0, newtext.length()));
// save
fEditor.doSave(new NullProgressMonitor());
assertFalse("Editor is still dirty", fEditor.isDirty());
// close and reopen
EditorTestHelper.closeEditor(fEditor);
setUpEditor(file);
content= fDocument.get();
assertEquals("Save failed", newContent, content);
}
public void testEditExternalTranslationUnit() throws Exception {
final String file= "/ceditor/src/main.cpp";
fCProject= EditorTestHelper.createCProject("ceditor", "resources/ceditor", false, false);
IFile mainFile= ResourceTestHelper.findFile(file);
assertNotNull(mainFile);
File tmpFile= File.createTempFile("tmp", ".cpp");
tmpFile.deleteOnExit();
FileTool.copy(mainFile.getLocation().toFile(), tmpFile);
setUpEditor(tmpFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
String content= fDocument.get();
setCaret(0);
String newtext= "/* "+getName()+" */";
type(newtext);
type('\n');
String newContent= fDocument.get();
assertEquals("Edit failed", newtext, newContent.substring(0, newtext.length()));
// save
fEditor.doSave(new NullProgressMonitor());
assertFalse("Editor is still dirty", fEditor.isDirty());
// close and reopen
EditorTestHelper.closeEditor(fEditor);
setUpEditor(tmpFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
content= fDocument.get();
assertEquals("Save failed", newContent, content);
// check reconciler
ITranslationUnit tUnit= (ITranslationUnit)fEditor.getInputCElement();
ICElement[] children= tUnit.getChildren();
assertEquals(2, children.length);
setCaret(content.length());
type('\n');
type("void func() {}\n");
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
children= tUnit.getChildren();
assertEquals(3, children.length);
tmpFile.delete();
}
public void testEditExternalTranslationUnitUsingFileStore() throws Exception {
final String file= "/ceditor/src/main.cpp";
fCProject= EditorTestHelper.createCProject("ceditor", "resources/ceditor", false, false);
IFile mainFile= ResourceTestHelper.findFile(file);
assertNotNull(mainFile);
File tmpFile= File.createTempFile("tmp", ".cpp");
tmpFile.deleteOnExit();
FileTool.copy(mainFile.getLocation().toFile(), tmpFile);
setUpEditorUsingFileStore(tmpFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
String content= fDocument.get();
setCaret(0);
String newtext= "/* "+getName()+" */";
type(newtext);
type('\n');
String newContent= fDocument.get();
assertEquals("Edit failed", newtext, newContent.substring(0, newtext.length()));
// save
fEditor.doSave(new NullProgressMonitor());
assertFalse("Editor is still dirty", fEditor.isDirty());
// close and reopen
EditorTestHelper.closeEditor(fEditor);
setUpEditor(tmpFile);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
content= fDocument.get();
assertEquals("Save failed", newContent, content);
// check reconciler
ITranslationUnit tUnit= (ITranslationUnit)fEditor.getInputCElement();
ICElement[] children= tUnit.getChildren();
assertEquals(2, children.length);
setCaret(content.length());
type('\n');
type("void func() {}\n");
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
children= tUnit.getChildren();
assertEquals(3, children.length);
tmpFile.delete();
}
public void testSyntaxHighlighting_Bug180433() throws Exception {
IColorManager colorMgr= CUIPlugin.getDefault().getTextTools().getColorManager();
colorMgr.unbindColor(ICColorConstants.PP_DIRECTIVE);
colorMgr.bindColor(ICColorConstants.PP_DIRECTIVE, new RGB(7,7,7));
final Color ppDirectiveColor= colorMgr.getColor(ICColorConstants.PP_DIRECTIVE);
final String file= "/ceditor/src/main.cpp";
fCProject= EditorTestHelper.createCProject("ceditor", "resources/ceditor", false, false);
setUpEditor(file);
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
String content= fDocument.get();
String include= "#include";
int includeIdx= content.indexOf(include);
StyleRange style= fTextWidget.getStyleRangeAtOffset(includeIdx);
assertSame(style.foreground, ppDirectiveColor);
}
public void testNonFileEFSResource_Bug278632() {
IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
assertNotNull(page);
IEditorRegistry reg = page.getWorkbenchWindow().getWorkbench()
.getEditorRegistry();
String editorID = reg.getDefaultEditor(".c").getId();
URI uri = null;
try {
uri = new URI("bug278632", "/folder/file", null);
} catch (URISyntaxException e) {
e.printStackTrace();
}
assertNotNull(uri);
IEditorPart part = null;
try {
part = IDE.openEditor(page, uri, editorID, true);
} catch (PartInitException e) {
e.printStackTrace();
}
assertNotNull(part);
assertTrue(part instanceof CEditor);
}
/**
* Type characters into the styled text.
*
* @param characters the characters to type
*/
private void type(CharSequence characters) {
for (int i= 0; i < characters.length(); i++)
type(characters.charAt(i), 0, 0);
}
/**
* Type a character into the styled text.
*
* @param character the character to type
*/
private void type(char character) {
type(character, 0, 0);
}
/**
* Type a character into the styled text.
*
* @param character the character to type
* @param keyCode the key code
* @param stateMask the state mask
*/
private void type(char character, int keyCode, int stateMask) {
fDocument.addDocumentListener(fDocListener);
fDocListener.fDocChanged= false;
Event event= new Event();
event.character= character;
event.keyCode= keyCode;
event.stateMask= stateMask;
fAccessor.invoke("handleKeyDown", new Object[] {event});
new DisplayHelper() {
@Override
protected boolean condition() {
return fDocListener.fDocChanged;
}
}.waitForCondition(EditorTestHelper.getActiveDisplay(), 50);
fDocument.removeDocumentListener(fDocListener);
}
private int getCaret() {
return ((ITextSelection) fEditor.getSelectionProvider().getSelection()).getOffset();
}
private void setCaret(int offset) {
fEditor.getSelectionProvider().setSelection(new TextSelection(offset, 0));
int newOffset= ((ITextSelection)fEditor.getSelectionProvider().getSelection()).getOffset();
assertEquals(offset, newOffset);
}
}