package it.xsemantics.example.lambda.tests.ui;
import static it.xsemantics.example.lambda.tests.util.LambdaTestsUtil.getAbstraction;
import static it.xsemantics.example.lambda.tests.util.LambdaTestsUtil.getArrowType;
import static it.xsemantics.example.lambda.tests.util.LambdaTestsUtil.getTypeVariable;
import static it.xsemantics.example.lambda.tests.util.LambdaTestsUtil.rep;
import static org.eclipse.xtext.ui.junit.util.IResourcesSetupUtil.addNature;
import static org.eclipse.xtext.ui.junit.util.IResourcesSetupUtil.cleanWorkspace;
import static org.eclipse.xtext.ui.junit.util.IResourcesSetupUtil.createFile;
import static org.eclipse.xtext.ui.junit.util.IResourcesSetupUtil.waitForBuild;
import static org.eclipse.xtext.ui.junit.util.JavaProjectSetupUtil.addSourceFolder;
import static org.eclipse.xtext.ui.junit.util.JavaProjectSetupUtil.createJavaProject;
import it.xsemantics.example.lambda.LambdaUiInjectorProvider;
import it.xsemantics.example.lambda.lambda.Abstraction;
import it.xsemantics.example.lambda.lambda.ArrowType;
import it.xsemantics.example.lambda.lambda.Program;
import it.xsemantics.example.lambda.ui.typing.LambdaTermModifier;
import junit.framework.TestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.intro.IIntroManager;
import org.eclipse.ui.intro.IIntroPart;
import org.eclipse.xtext.junit4.InjectWith;
import org.eclipse.xtext.junit4.XtextRunner;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.XtextProjectHelper;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.editor.utils.EditorUtils;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.google.inject.Inject;
@RunWith(XtextRunner.class)
@InjectWith(LambdaUiInjectorProvider.class)
public class LambdaIntegrationTest extends TestCase {
@Inject
protected LambdaTermModifier lambdaTermModifier;
@BeforeClass
public static void closeWelcome() {
final IIntroManager introManager = PlatformUI.getWorkbench()
.getIntroManager();
IIntroPart part = introManager.getIntro();
introManager.closeIntro(part);
}
@Override
@After
public void tearDown() throws Exception {
super.tearDown();
saveAllEditors();
closeAllEditors();
cleanWorkspace();
}
@Test
public void testValidSimpleLambdaProgram() throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda", "lambda x. x");
waitForBuild();
assertNoErrorMarkers(file);
}
protected void assertNoErrorMarkers(IFile file) throws CoreException {
assertEquals(0, file.findMarkers(EValidator.MARKER, true,
IResource.DEPTH_INFINITE).length);
}
protected void assertErrorMarkers(IFile file, int numOfMarkers)
throws CoreException {
assertEquals(numOfMarkers, file.findMarkers(EValidator.MARKER, true,
IResource.DEPTH_INFINITE).length);
}
protected void assertContainsErrorMarkers(IFile file) throws CoreException {
assertTrue(file.findMarkers(EValidator.MARKER, true,
IResource.DEPTH_INFINITE).length > 0);
}
@Test
public void testGetActiveEditor() throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda", "lambda x. x");
waitForBuild();
IXtextDocument xtextDocument = openEditorAndGetDocument(file);
Program program = getLambdaProgramFromEditor(xtextDocument);
assertEquals("x", getAbstraction(program.getTerm()).getParam()
.getName());
}
@Test
public void testInferAndModifyAbstractionType() throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda", "lambda x. x");
waitForBuild();
IXtextDocument xtextDocument = modifyAbstractionWithInferredType(file);
assertNoErrorMarkers(file);
Abstraction abstraction = getAbstractionFromProgramEditor(xtextDocument);
assertEquals("a", getTypeVariable(abstraction.getParam().getType())
.getTypevarName());
}
@Test
public void testInferAndModifyComposeAbstractionType() throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda",
"lambda f . lambda g. lambda x. (f (g x))");
waitForBuild();
IXtextDocument xtextDocument = modifyAbstractionWithInferredType(file);
assertNoErrorMarkers(file);
Abstraction abstraction = getAbstractionFromProgramEditor(xtextDocument);
assertEquals("a -> b", rep(abstraction.getParam().getType()));
}
@Test
public void testInferAndModifyAbstractionWithExplicitType()
throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda",
"lambda x : int -> string. x");
waitForBuild();
IXtextDocument xtextDocument = modifyAbstractionWithInferredType(file);
assertNoErrorMarkers(file);
Abstraction abstraction = getAbstractionFromProgramEditor(xtextDocument);
assertEquals("a", rep(abstraction.getParam().getType()));
}
@Test
public void testInferAndModifyNotTypableAbstractionWithType()
throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda",
"lambda x : int -> string. x x");
waitForBuild();
IXtextDocument xtextDocument = modifyAbstractionWithInferredType(file);
assertContainsErrorMarkers(file);
Abstraction abstraction = getAbstractionFromProgramEditor(xtextDocument);
ArrowType arrowType = getArrowType(abstraction.getParam().getType());
// since the type cannot be inferred the original type is not changed
assertEquals("int -> string", rep(arrowType));
}
@Test
public void testInferAndModifyTerm() throws Exception {
createJavaProjectWithRootSrc("foo");
IFile file = createFile("foo/src/foo.lambda",
"lambda f . lambda g. lambda x. (f (g x))");
waitForBuild();
IXtextDocument xtextDocument = modifyTermWithInferredType(file);
assertNoErrorMarkers(file);
String newProgramText = xtextDocument.get();
assertEquals(
"lambda f : a -> b . lambda g : c -> a. lambda x : c. (f (g x))",
newProgramText);
}
@Test
public void testInferAndModifyWrongTerm() throws Exception {
createJavaProjectWithRootSrc("foo");
String originalProgramText = "lambda f . lambda g. lambda x. (f (f f))";
IFile file = createFile("foo/src/foo.lambda", originalProgramText);
waitForBuild();
IXtextDocument xtextDocument = modifyTermWithInferredType(file);
assertContainsErrorMarkers(file);
String newProgramText = xtextDocument.get();
assertEquals(originalProgramText, newProgramText);
}
protected Abstraction getAbstractionFromProgramEditor(
IXtextDocument xtextDocument) {
Program program = getLambdaProgramFromEditor(xtextDocument);
Abstraction abstraction = getAbstraction(program.getTerm());
return abstraction;
}
protected IXtextDocument modifyAbstractionWithInferredType(IFile file)
throws PartInitException {
IXtextDocument xtextDocument = openEditor(file).getDocument();
modifyAbstractionWithInferredType(xtextDocument);
waitForBuild();
return xtextDocument;
}
protected void modifyAbstractionWithInferredType(
IXtextDocument xtextDocument) {
lambdaTermModifier.modifyAbstractionWithInferredType(xtextDocument);
saveAllEditors();
}
protected IXtextDocument modifyTermWithInferredType(IFile file)
throws PartInitException {
IXtextDocument xtextDocument = openEditor(file).getDocument();
modifyTermWithInferredType(xtextDocument);
waitForBuild();
return xtextDocument;
}
protected void modifyTermWithInferredType(IXtextDocument xtextDocument) {
lambdaTermModifier.modifyTermWithInferredType(xtextDocument);
saveAllEditors();
}
protected void saveAllEditors() {
getWorkbenchPage().saveAllEditors(false);
}
protected void closeAllEditors() {
getWorkbenchPage().closeAllEditors(false);
}
protected Program getLambdaProgramFromEditor(IXtextDocument xtextDocument) {
Program program = xtextDocument
.readOnly(new IUnitOfWork<Program, XtextResource>() {
public Program exec(XtextResource resource) {
return (Program) resource.getContents().get(0);
}
});
return program;
}
protected IXtextDocument openEditorAndGetDocument(IFile file)
throws PartInitException {
XtextEditor activeXtextEditor = openEditor(file);
IXtextDocument xtextDocument = activeXtextEditor.getDocument();
return xtextDocument;
}
protected XtextEditor openEditor(IFile file) throws PartInitException {
IWorkbenchPage page = getWorkbenchPage();
IDE.openEditor(page, file);
XtextEditor activeXtextEditor = EditorUtils.getActiveXtextEditor();
return activeXtextEditor;
}
protected IWorkbenchPage getWorkbenchPage() {
IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
return page;
}
private IJavaProject createJavaProjectWithRootSrc(String string)
throws CoreException {
IJavaProject project = createJavaProject(string);
addNature(project.getProject(), XtextProjectHelper.NATURE_ID);
addSourceFolder(project, "src");
return project;
}
}