From a09e06b3d4fc0c098295c7992a1e95118813889e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 12 Jul 2011 16:34:39 +0200 Subject: [PATCH] string templates --- .../jet/codegen/ExpressionCodegen.java | 46 +++++++++++++------ .../psi/JetEscapeStringTemplateEntry.java | 5 ++ .../jet/codegen/NamespaceGenTest.java | 12 +++++ .../jet/codegen/PatternMatchingTest.java | 9 +++- 4 files changed, 58 insertions(+), 14 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index c0c2cfec643..9eac2586d1c 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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 diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java index 006810c6a28..aedd7c26d93 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java @@ -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()); + } } diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index d2afec870a4..3df1dafb268 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -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")); + } } diff --git a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java index 6bc4d686f52..1e5ac174c0d 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java @@ -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(1, 2))); + final Object result; + try { + result = foo.invoke(null, new Tuple2(1, 2)); + } catch (Exception e) { + System.out.println(generateToText()); + throw e; + } + assertEquals("one,two", result); assertEquals("something", foo.invoke(null, new Tuple2("not", "tuple"))); }