package com.sap.furcas.prettyprinter.scenario;
import static com.sap.furcas.prettyprinter.testutils.PrettyPrintAssertionUtil.assertEqualsByLines;
import static com.sap.furcas.prettyprinter.testutils.PrettyPrintTestHelper.prettyPrintTextBlock;
import static com.sap.furcas.prettyprinter.testutils.PrettyPrintTestHelper.readFile;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.Set;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import com.sap.furcas.metamodel.FURCAS.TCS.ClassTemplate;
import com.sap.furcas.metamodel.FURCAS.TCS.ConcreteSyntax;
import com.sap.furcas.metamodel.FURCAS.TCS.SpaceKind;
import com.sap.furcas.metamodel.FURCAS.TCS.Symbol;
import com.sap.furcas.metamodel.FURCAS.TCS.TCSFactory;
import com.sap.furcas.metamodel.FURCAS.textblocks.AbstractToken;
import com.sap.furcas.metamodel.FURCAS.textblocks.TextBlock;
import com.sap.furcas.parser.tcs.TCSParserFactory;
import com.sap.furcas.parser.tcs.TCSSyntaxDefinition;
import com.sap.furcas.parsergenerator.GrammarGenerationSourceConfiguration;
import com.sap.furcas.parsergenerator.TCSParserGenerator;
import com.sap.furcas.parsergenerator.TCSParserGeneratorFactory;
import com.sap.furcas.prettyprinter.testutils.PrettyPrintAssertionUtil;
import com.sap.furcas.prettyprinter.testutils.PrettyPrintTestHelper;
import com.sap.furcas.runtime.parser.incremental.testbase.TcsTestHelper;
import com.sap.furcas.runtime.parser.testbase.FailOnErrorErrorHandler;
import com.sap.furcas.runtime.textblocks.model.TextBlocksModel;
import com.sap.furcas.runtime.textblocks.testutils.EMFTextBlocksModelElementFactory;
import com.sap.furcas.runtime.textblocks.testutils.TestSourceTextBlockCreator;
import com.sap.furcas.runtime.textblocks.testutils.TextBlocksModelElementFactory;
import com.sap.furcas.test.testutils.ResourceTestHelper;
import com.sap.furcas.utils.projects.FileReadHelper;
import com.sap.ide.cts.parser.incremental.IncrementalParserFacade;
public class TestPrettyPrintTCS {
private final TCSFactory modelFactory = TCSFactory.eINSTANCE;
private static ConcreteSyntax syntax;
@Rule
public final TemporaryFolder tmpFolder = new TemporaryFolder();
private static Set<URI> referenceScope;
@BeforeClass
public static void init() {
referenceScope = ResourceTestHelper.createFURCASReferenceScope();
referenceScope.addAll(ResourceTestHelper.createEcoreReferenceScope());
ResourceSet resourceSet = ResourceTestHelper.createResourceSet();
TCSParserFactory factory = new TCSParserFactory();
syntax = (ConcreteSyntax) resourceSet.getEObject(URI.createURI(factory.getSyntaxUUID()), /*load*/true);
}
@Test
public void testSyntaxOnly() throws Exception {
ConcreteSyntax concreteSyntax = modelFactory.createConcreteSyntax();
concreteSyntax.setName("SimpleSyntax");
TextBlock output = prettyPrintTextBlock(concreteSyntax, syntax, new TCSParserFactory());
PrettyPrintAssertionUtil.assertEqualsByLines(output, readFile("fixtureData/TCS_SyntaxOnly.out"));
}
@Test
public void testSyntaxWithMainClassTemplateMetaReference() throws Exception {
ConcreteSyntax concreteSyntax = modelFactory.createConcreteSyntax();
concreteSyntax.setName("SyntaxWithMainClassTemplateMetaReference");
ClassTemplate template = modelFactory.createClassTemplate();
template.setIsMain(true);
EAttribute attr = (EAttribute) concreteSyntax.eClass().getEStructuralFeature("name");
template.setMetaReference(attr.getEType());
concreteSyntax.getTemplates().add(template);
TextBlock output = prettyPrintTextBlock(concreteSyntax, syntax, new TCSParserFactory());
assertEqualsByLines(output, readFile("fixtureData/TCS_SyntaxWithMainClassTemplateMetaReference.out"));
}
@Test
public void testSyntaxWithSymbols() throws Exception {
ConcreteSyntax concreteSyntax = modelFactory.createConcreteSyntax();
concreteSyntax.setName("SyntaxWithSymbols");
Symbol sym = modelFactory.createSymbol();
sym.setName("lsquare");
sym.setValue("[");
sym.getSpaces().add(SpaceKind.LEFT_SPACE);
sym.getSpaces().add(SpaceKind.RIGHT_NONE);
concreteSyntax.getSymbols().add(sym);
sym = modelFactory.createSymbol();
sym.setName("rsquare");
sym.setValue("]");
concreteSyntax.getSymbols().add(sym);
sym = modelFactory.createSymbol();
sym.setName("dlsquare");
sym.setValue("[[");
sym.getSpaces().add(SpaceKind.LEFT_NONE);
sym.getSpaces().add(SpaceKind.RIGHT_NONE);
concreteSyntax.getSymbols().add(sym);
sym = modelFactory.createSymbol();
sym.setName("drsquare");
sym.setValue("]]");
sym.getSpaces().add(SpaceKind.RIGHT_SPACE);
concreteSyntax.getSymbols().add(sym);
TextBlock output = PrettyPrintTestHelper.prettyPrintTextBlock(concreteSyntax, syntax, new TCSParserFactory());
assertEqualsByLines(output, readFile("fixtureData/TCS_SyntaxWithSymbols.out"));
}
/**
* Print the TCS model and then check if it can be parsed again.
*
* No much validation on the pretty printed result is performed, as we cannot
* compare it to the source TCS.tcs due to missing comments and extended keywords.
*
* Reparsing asserts that all constructs used in the TCS can be printed correctly.
* Common errors are that a name is quoted when it shouldn't be or that it is missing
* entirely because the feature is not supported by the pretty printer.
* With this test we can detect such errors.
*/
@Test
public void testPrettyPrintTCS() throws Exception {
String reprintedTCS = PrettyPrintTestHelper.prettyPrintString(syntax, syntax, referenceScope);
assertTrue(reprintedTCS.startsWith("syntax TCS"));
assertTrue(reprintedTCS.endsWith("}"));
// write to file
File tmpFile = tmpFolder.newFile("reprinted.tcs");
FileWriter out = new FileWriter(tmpFile);
out.write(reprintedTCS);
out.close();
// parse the tmpFile
TCSParserGenerator generator = TCSParserGeneratorFactory.INSTANCE.createTCSParserGenerator();
Set<URI> refScope = ResourceTestHelper.createFURCASReferenceScope();
refScope.addAll(ResourceTestHelper.createEcoreReferenceScope());
ConcreteSyntax reparsedSyntax = generator.parseSyntax(new GrammarGenerationSourceConfiguration(ResourceTestHelper.createResourceSet(),
refScope), tmpFile, new FailOnErrorErrorHandler()).getSyntax();
assertNotNull(reparsedSyntax);
// reprint the new syntax model yet another time.
// Obviously both pretty print results should be equal.
TextBlock reprintedTCS2 = PrettyPrintTestHelper.prettyPrintTextBlock(reparsedSyntax, syntax, new TCSParserFactory());
assertEqualsByLines(reprintedTCS2, reprintedTCS);
}
/**
* Print the TCS model and then check if it can be parsed again.
* Use a pre-existing TextBlock to re-use comments and formatting.
*/
@Test
public void testPrettyPrintWithReuse() throws Exception {
IncrementalParserFacade incrementalParserFacade = TcsTestHelper.createTCSIncrementalParserFacade();
TextBlocksModelElementFactory factory = new EMFTextBlocksModelElementFactory();
AbstractToken tcsTcsContent = factory.createToken("");
TextBlock root = TestSourceTextBlockCreator.initialiseTextBlocksWithContentToken(factory, tcsTcsContent);
FileInputStream in = new FileInputStream(TCSSyntaxDefinition.TCS_TCS);
String referenceContent = FileReadHelper.readInput(in);
TextBlocksModel tbModel = new TextBlocksModel(root);
tbModel.replace(0, 0, referenceContent);
root = incrementalParserFacade.parseIncrementally(root);
// Incremental reprint.
TextBlock reprinted = PrettyPrintTestHelper.prettyPrintTextBlock(IncrementalParserFacade.getParsingResult(root),
root, new TCSParserFactory());
// FIXME: Workaround for missing formatting re-use between primitive-typed lists.
String reprintedContent = reprinted.getCachedString().replace("createAs =FURCAS::TCS::Keyword", "createAs = FURCAS::TCS::Keyword");
// Unfortunately the TCS Syntax definition is not "determinstic". There are certain things
// that the pretty printer cannot know solely from the syntax definition. We have to fix those.
reprintedContent = reprintedContent.replace("FURCAS:: TCS::", "TCS::");
reprintedContent = reprintedContent.replace("\n \n \n keywords {\r\n\r\n}", "");
assertEqualsByLines(reprintedContent, referenceContent);
}
}