/*******************************************************************************
* Copyright (c) 2008,2010 itemis AG (http://www.itemis.eu) 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
*
*******************************************************************************/
package org.eclipse.emf.mwe2.language.tests.parser;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.mwe2.language.mwe2.PlainString;
import org.eclipse.emf.mwe2.language.mwe2.PropertyReference;
import org.eclipse.emf.mwe2.language.mwe2.StringLiteral;
import org.eclipse.emf.mwe2.language.mwe2.StringPart;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.linking.impl.LinkingHelper;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.util.Strings;
import org.junit.Test;
public class StringLiteralTest extends AbstractParserTest {
@Override
protected ParserRule getRule() {
return getGrammarAccess().getStringLiteralRule();
}
@Test public void testEmptyLiteral() {
checkPlainString("", "");
}
@Test public void testKeywords() {
TreeIterator<EObject> iterator = EcoreUtil.getAllContents(getGrammarAccess().getGrammar(), false);
while(iterator.hasNext()) {
EObject next = iterator.next();
if (next instanceof TerminalRule
|| next == getGrammarAccess().getConstantValueRule()) {
iterator.prune();
} else if (next instanceof Keyword) {
String value = ((Keyword) next).getValue();
String expectation = value;
if ("'".equals(value) || "\"".equals(value) || "\\".equals(value) || "${".equals(value))
value = "\\" + value;
checkPlainString(value, expectation);
}
}
}
@Test public void testKeywordPrefixes() {
checkPlainString("$", "$");
checkPlainString("impo", "impo");
checkPlainString("/", "/");
}
@Test public void testComments() {
checkPlainString("// something\n", "// something\n");
checkPlainString("// something", "// something");
checkPlainString("/* something */", "/* something */");
checkPlainString("/* something", "/* something");
}
@Test public void testEscapedComments() {
parseWithErrors("\\// something", 1);
parseWithErrors("\\/* something", 1);
}
@Test public void testWS() {
checkPlainString(" \\n\\r\\t", " \n\r\t");
checkPlainString(" import ", " import ");
}
@Test public void testAnyChar() {
checkPlainString("*/", "*/");
checkPlainString("#", "#");
checkPlainString("/", "/");
}
@Test public void testComplex() {
checkPlainString(" import var id.id.* ", " import var id.id.* ");
checkPlainString(" \\${ something . .* } ", " ${ something . .* } ");
}
@Test public void testWsAfterRef() {
checkPlainOrRefString("${something} ", "ref:something", " ");
}
protected void checkPlainString(String input, String expectation) {
IParseResult result = parseSuccessfully(input);
StringLiteral literal = (StringLiteral) result.getRootASTElement();
if (Strings.isEmpty(expectation)) {
assertTrue(input, literal.getParts().isEmpty());
} else {
assertEquals(input, 1, literal.getParts().size());
PlainString plain = (PlainString) literal.getParts().get(0);
assertEquals(input, expectation, plain.getValue());
}
}
protected void checkPlainOrRefString(String input, String... expectation) {
IParseResult result = parseSuccessfully(input);
StringLiteral literal = (StringLiteral) result.getRootASTElement();
int i = 0;
LinkingHelper linkingHelper = get(LinkingHelper.class);
for(StringPart part: literal.getParts()) {
if (part instanceof PropertyReference) {
assertTrue(expectation[i].startsWith("ref:"));
String expected = expectation[i].substring(4);
ICompositeNode node = NodeModelUtils.getNode(part);
for(INode child: node.getChildren()) {
if (child.getGrammarElement() instanceof CrossReference) {
String nodeAsString = linkingHelper.getCrossRefNodeAsString(child, true);
assertEquals(expected, nodeAsString);
}
}
} else if (part instanceof PlainString) {
PlainString plain = (PlainString) part;
assertEquals(input, expectation[i], plain.getValue());
} else {
fail("Unexpected StringPart: " + part);
}
i++;
}
assertEquals(expectation.length, literal.getParts().size());
}
protected void checkReference(String input, String... expectedReferences) {
IParseResult result = parseSuccessfully(input);
StringLiteral literal = (StringLiteral) result.getRootASTElement();
int i = 0;
LinkingHelper linkingHelper = get(LinkingHelper.class);
for(StringPart part: literal.getParts()) {
if (part instanceof PropertyReference) {
ICompositeNode node = NodeModelUtils.getNode(part);
for(INode child: node.getChildren()) {
if (child.getGrammarElement() instanceof CrossReference) {
String nodeAsString = linkingHelper.getCrossRefNodeAsString(child, true);
assertEquals(expectedReferences[i], nodeAsString);
i++;
}
}
}
}
assertEquals(expectedReferences.length, i);
}
@Test public void testReference() {
checkReference("${something}", "something");
checkReference("${ something }", "something");
checkReference("${something. /* comment */ ^module}", "something.module");
checkReference("${something.\nsomething // comment \n}", "something.something");
}
@Test public void testReferences() {
checkReference("${something } ${ something.else}", "something", "something.else");
checkReference("${something}${else}", "something", "else");
}
@Test public void testIncompleteReference() {
parseWithErrors("${}", 1);
parseWithErrors("${", 1);
parseWithErrors("${something", 1);
parseWithErrors("${something.", 1);
}
@Test public void testMixed() {
checkReference("import${something}", "something");
checkReference("$${something}", "something");
checkReference(" ${something}}", "something");
checkReference("{${something}$", "something");
}
@Test public void testHttpInString() {
checkPlainString("http://www.xtext.org", "http://www.xtext.org");
}
@Test public void testDoubleQuoteInSingleQuotedString() {
IParseResult result = super.parseSuccessfully("'\"'");
StringLiteral literal = (StringLiteral) result.getRootASTElement();
assertEquals("'\"'", 1, literal.getParts().size());
PlainString plain = (PlainString) literal.getParts().get(0);
assertEquals("'\"'", "\"", plain.getValue());
}
@Test public void testSingleQuoteInDoubleQuotedString() {
IParseResult result = super.parseSuccessfully("\"'\"");
StringLiteral literal = (StringLiteral) result.getRootASTElement();
assertEquals("\"'\"", 1, literal.getParts().size());
PlainString plain = (PlainString) literal.getParts().get(0);
assertEquals("\"'\"", "'", plain.getValue());
}
@Override
protected IParseResult parseSuccessfully(String input) {
String quotedInput = '"' + input + '"';
super.parseSuccessfully(quotedInput);
quotedInput = "'" + input + "'";
return super.parseSuccessfully(quotedInput);
}
@Override
protected IParseResult parseWithErrors(String input, int errorCount) {
String quotedInput = '"' + input + '"';
super.parseWithErrors(quotedInput, errorCount);
quotedInput = "'" + input + "'";
return super.parseWithErrors(quotedInput, errorCount);
}
}