string templates

This commit is contained in:
Dmitry Jemerov
2011-07-12 16:34:39 +02:00
parent bf7be08e3b
commit a09e06b3d4
4 changed files with 58 additions and 14 deletions
@@ -52,6 +52,7 @@ public class ExpressionCodegen extends JetVisitor {
private static final Type INTEGER_TYPE = Type.getType(Integer.class);
private static final Type ITERATOR_TYPE = Type.getType(Iterator.class);
private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
private static final Type STRING_TYPE = Type.getObjectType(CLASS_STRING);
private static final Type RANGE_TYPE = Type.getType(Range.class);
private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class);
@@ -490,21 +491,40 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitStringTemplateExpression(JetStringTemplateExpression expression) {
final StringBuilder builder = new StringBuilder();
StringBuilder constantValue = new StringBuilder("");
for (JetStringTemplateEntry entry : expression.getEntries()) {
entry.accept(new JetVisitor() {
@Override
public void visitStringTemplateEntry(JetStringTemplateEntry entry) {
throw new UnsupportedOperationException("Unsupported string template entry: " + entry); // TODO
}
@Override
public void visitLiteralStringTemplateEntry(JetLiteralStringTemplateEntry entry) {
builder.append(entry.getText());
}
});
if (entry instanceof JetLiteralStringTemplateEntry) {
constantValue.append(entry.getText());
}
else if (entry instanceof JetEscapeStringTemplateEntry) {
constantValue.append(((JetEscapeStringTemplateEntry) entry).getUnescapedValue());
}
else {
constantValue = null;
break;
}
}
if (constantValue != null) {
final Type type = expressionType(expression);
myStack.push(StackValue.constant(constantValue.toString(), type));
}
else {
generateStringBuilderConstructor();
for (JetStringTemplateEntry entry : expression.getEntries()) {
if (entry instanceof JetStringTemplateEntryWithExpression) {
invokeAppend(entry.getExpression());
}
else {
String text = entry instanceof JetEscapeStringTemplateEntry
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
: entry.getText();
v.aconst(text);
invokeAppendMethod(STRING_TYPE);
}
}
v.invokevirtual(CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
myStack.push(StackValue.onStack(expressionType(expression)));
}
myStack.push(StackValue.constant(builder.toString(), expressionType(expression)));
}
@Override
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
/**
@@ -15,4 +16,8 @@ public class JetEscapeStringTemplateEntry extends JetStringTemplateEntry {
public void accept(@NotNull JetVisitor visitor) {
visitor.visitEscapeStringTemplateEntry(this);
}
public String getUnescapedValue() {
return StringUtil.unescapeStringCharacters(getText());
}
}
@@ -451,4 +451,16 @@ public class NamespaceGenTest extends CodegenTestCase {
assertEquals("JetBrains", main.invoke(null, "JetBrains"));
assertNull(main.invoke(null, "IntelliJ"));
}
public void testEscapeSequence() throws Exception {
loadText("fun foo() = \"a\\nb\\$\"");
final Method main = generateFunction();
assertEquals("a\nb$", main.invoke(null));
}
public void testStringTemplate() throws Exception {
loadText("fun foo(a: String) = \"IntelliJ $a Rulezzz\"");
final Method main = generateFunction();
assertEquals("IntelliJ IDEA Rulezzz", main.invoke(null, "IDEA"));
}
}
@@ -66,7 +66,14 @@ public class PatternMatchingTest extends CodegenTestCase {
public void testTuplePattern() throws Exception {
loadText("fun foo(x: (Any, Any)) = when(x) { is (1,2) => \"one,two\"; else => \"something\" }");
Method foo = generateFunction();
assertEquals("one,two", foo.invoke(null, new Tuple2<Integer, Integer>(1, 2)));
final Object result;
try {
result = foo.invoke(null, new Tuple2<Integer, Integer>(1, 2));
} catch (Exception e) {
System.out.println(generateToText());
throw e;
}
assertEquals("one,two", result);
assertEquals("something", foo.invoke(null, new Tuple2<String, String>("not", "tuple")));
}