package com.sap.furcas.runtime.parser.incremental; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.Iterator; import org.antlr.runtime.Lexer; import org.antlr.runtime.Token; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.junit.Test; import com.sap.furcas.metamodel.FURCAS.textblocks.AbstractToken; import com.sap.furcas.metamodel.FURCAS.textblocks.Bostoken; import com.sap.furcas.metamodel.FURCAS.textblocks.Eostoken; import com.sap.furcas.metamodel.FURCAS.textblocks.LexedToken; import com.sap.furcas.metamodel.FURCAS.textblocks.TextBlock; import com.sap.furcas.metamodel.FURCAS.textblocks.Version; import com.sap.furcas.parser.tcs.TCSParserFactory; import com.sap.furcas.parser.tcs.stable.TCSLexer; import com.sap.furcas.runtime.common.exceptions.ParserInstantiationException; import com.sap.furcas.runtime.parser.ParserFactory; import com.sap.furcas.runtime.parser.PartitionAssignmentHandler; import com.sap.furcas.runtime.parser.impl.ObservableInjectingParser; import com.sap.furcas.runtime.parser.impl.ParserScope; import com.sap.furcas.runtime.parser.testbase.MockPartitionAssignmentHandler; import com.sap.furcas.runtime.parser.textblocks.observer.ParserTextBlocksHandler; import com.sap.furcas.runtime.parser.textblocks.observer.TextBlockProxy; import com.sap.furcas.runtime.tcs.TcsUtil; import com.sap.furcas.runtime.textblocks.TbNavigationUtil; import com.sap.furcas.runtime.textblocks.model.TextBlocksModel; import com.sap.furcas.runtime.textblocks.modifcation.TbVersionUtil; import com.sap.furcas.runtime.textblocks.testbase.FixtureProvidingTextBlockTest; import com.sap.furcas.test.testutils.ResourceTestHelper; import com.sap.ide.cts.parser.errorhandling.SemanticParserException; import com.sap.ide.cts.parser.incremental.IncrementalParserFacade; import com.sap.ide.cts.parser.incremental.LexerAdapter; import com.sap.ide.cts.parser.incremental.TextBlockReuseStrategyImpl; import com.sap.ide.cts.parser.incremental.antlr.ANTLRIncrementalLexerAdapter; import com.sap.ide.cts.parser.incremental.antlr.ANTLRIncrementalTokenStream; import com.sap.ide.cts.parser.incremental.antlr.ANTLRLexerAdapter; public class TestLexerParserInteraction extends FixtureProvidingTextBlockTest { @Test public void testTokenRelocationWithParser() throws ParserInstantiationException, SemanticParserException { ResourceSet resourceSet = ResourceTestHelper.createResourceSet(); Resource transientParsingResource = ResourceTestHelper.createTransientResource(resourceSet); ParserFactory<? extends ObservableInjectingParser, ? extends Lexer> parserFactory = new TCSParserFactory(); resourceSet.getResource(parserFactory.getSyntaxResourceURI(), true); IncrementalParserFacade ipf = new IncrementalParserFacade(parserFactory, resourceSet, new MockPartitionAssignmentHandler( transientParsingResource)); TextBlock root = modelFactory.createTextBlock(); transientParsingResource.getContents().add(root); root.setVersion(Version.REFERENCE); root.setCachedString(""); LexedToken t = modelFactory.createLexedToken(); t.setValue(""); t.setOffset(0); t.setOffsetRelative(true); t.setVersion(Version.REFERENCE); Bostoken bostoken = modelFactory.createBostoken(); bostoken.setOffsetRelative(true); root.getSubNodes().add(bostoken); root.getSubNodes().add(t); Eostoken eostoken = modelFactory.createEostoken(); eostoken.setOffset(1); eostoken.setOffsetRelative(true); root.getSubNodes().add(eostoken); TextBlocksModel model = new TextBlocksModel(root); model.replace(0, 0, "syntax test{template ->bla:;}"); ipf.parseIncrementally(root); bostoken = TbVersionUtil.getOtherVersion(bostoken, Version.CURRENT); root = TbVersionUtil.getOtherVersion(root, Version.CURRENT); if (ipf.getErrors().size() > 0) { fail(ipf.getErrors().get(0).getMessage()); } assertEquals(0, ipf.getErrors().size()); assertEquals(7, root.getTokens().size()); assertEquals(1, root.getSubBlocks().size()); TextBlock syntaxTb = root.getSubBlocks().get(0); assertEquals(6, syntaxTb.getTokens().size()); // TODO check rest of expected structure: /* * tb - tok syntax - tok " " - tok test - tok { - tb - tok template - * tok " " - tok bla - tok ; - tok ; - tok } */ } @Test public void testTokenRelocationWithStub() { ResourceSet resourceSet = ResourceTestHelper.createResourceSet(); Resource transientParsingResource = ResourceTestHelper.createTransientResource(resourceSet); TCSLexer antlrLexer = new TCSLexer(null, null); LexerAdapter lexerAdapter = new ANTLRLexerAdapter(antlrLexer, new TextBlockReuseStrategyImpl(antlrLexer, null)); ANTLRIncrementalLexerAdapter lexer = new ANTLRIncrementalLexerAdapter(lexerAdapter, null); ANTLRIncrementalTokenStream input = new ANTLRIncrementalTokenStream(lexer); ParserScope parserScope = new ParserScope(resourceSet, new TCSParserFactory()); PartitionAssignmentHandler partitioningHandler = new MockPartitionAssignmentHandler(transientParsingResource); ParserTextBlocksHandler tbh = new ParserTextBlocksHandler(input, parserScope, partitioningHandler); TextBlock root = modelFactory.createTextBlock(); transientParsingResource.getContents().add(root); root.setVersion(Version.REFERENCE); root.setCachedString(""); LexedToken t = modelFactory.createLexedToken(); t.setValue(""); t.setOffsetRelative(true); t.setVersion(Version.REFERENCE); Bostoken bostoken = modelFactory.createBostoken(); bostoken.setOffsetRelative(true); root.getSubNodes().add(bostoken); root.getSubNodes().add(t); Eostoken eostoken = modelFactory.createEostoken(); eostoken.setOffset(1); eostoken.setOffsetRelative(true); root.getSubNodes().add(eostoken); TextBlocksModel model = new TextBlocksModel(root); model.replace(0, 0, "syntax test{template bla:;}"); lexer.setSource(bostoken); lexer.lex(root); bostoken = TbVersionUtil.getOtherVersion(bostoken, Version.CURRENT); lexer.setCurrentTokenForParser(bostoken); root = TbVersionUtil.getOtherVersion(root, Version.CURRENT); tbh.setRootBlock(root); // make sur the fillBuffer() method is caled before modeifications are // made to the textblock model input.getTokens(); String templateURI = EcoreUtil.getURI(TcsUtil.getMainClassTemplate(parserScope.getSyntax())).toString(); // simulate main parse rule tbh.notifyEnterRule(templateURI); // simulate consumption of "syntax" token AbstractToken nextToken = TbNavigationUtil.nextToken(bostoken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of "<space>" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of "test" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of "{" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // descend into sub parse rule for template tbh.notifyEnterRule(templateURI); // simulate consumption of "template" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of "<space>" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of "bla" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of ":" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // simulate consumption of ";" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // exit template rule tbh.notifyExitRule(); // simulate consumption of "}" token nextToken = TbNavigationUtil.nextToken(nextToken); tbh.notifyTokenConsume(getInverseToken(input, nextToken)); // exit main rule tbh.notifyExitRule(); assertEquals(6, tbh.getCurrentTbProxy().getSubNodes().size()); TextBlockProxy syntaxTb = (TextBlockProxy) tbh.getCurrentTbProxy().getSubNodes().get(4); assertEquals(5, syntaxTb.getSubNodes().size()); // The following structure is being expected /* * rootTb EOS tb - tok syntax - tok { - tb - tok template - tok bla - * tok : - tok ; - tok } BOS */ } private Token getInverseToken(ANTLRIncrementalTokenStream input, AbstractToken nextToken) { if (nextToken == null) { throw new IllegalArgumentException("nextToken has to be other than null"); } for (Iterator<?> it = input.getTokens().iterator(); it.hasNext();) { Token tok = (Token) it.next(); if (input.getTokenModelElementForParserToken(tok) == nextToken) { return tok; } } return null; } }