diff --git a/libraries/kotlin-jdbc/src/test/kotlin/test/kotlin/jdbc/experiment1/JdbcTemplateTest.kt b/libraries/kotlin-jdbc/src/test/kotlin/test/kotlin/jdbc/JdbcTemplateTest.kt similarity index 60% rename from libraries/kotlin-jdbc/src/test/kotlin/test/kotlin/jdbc/experiment1/JdbcTemplateTest.kt rename to libraries/kotlin-jdbc/src/test/kotlin/test/kotlin/jdbc/JdbcTemplateTest.kt index 48eb57ed8fb..0712aeb5e21 100644 --- a/libraries/kotlin-jdbc/src/test/kotlin/test/kotlin/jdbc/experiment1/JdbcTemplateTest.kt +++ b/libraries/kotlin-jdbc/src/test/kotlin/test/kotlin/jdbc/JdbcTemplateTest.kt @@ -1,6 +1,6 @@ package test.kotlin.jdbc.experiment1 -import kotlin.template.experiment1.* +import kotlin.template.* import kotlin.jdbc.* import kotlin.test.* import kotlin.util.* @@ -14,34 +14,50 @@ import java.sql.Connection import java.sql.PreparedStatement import java.sql.ResultSet -fun DataSource.update(fn: (PreparedStatementBuilder) -> Unit): Int { - return use{ it.update(fn) } +fun DataSource.update(template: StringTemplate): Int { + return use{ it.update(template) } } -fun DataSource.query(fn: (PreparedStatementBuilder) -> Unit, resultBlock: (ResultSet) -> T): T { - return use{ it.query(fn, resultBlock) } +fun DataSource.query(template: StringTemplate, resultBlock: (ResultSet) -> T): T { + return use{ it.query(template, resultBlock) } } -fun Connection.update(fn: (PreparedStatementBuilder) -> Unit): Int { - val preparedStatement = prepare(fn) +fun Connection.update(template: StringTemplate): Int { + val preparedStatement = prepare(template) return preparedStatement.update() } -fun Connection.query(fn: (PreparedStatementBuilder) -> Unit, resultBlock: (ResultSet) -> T): T { - val preparedStatement = prepare(fn) +fun Connection.query(template: StringTemplate, resultBlock: (ResultSet) -> T): T { + val preparedStatement = prepare(template) return preparedStatement.query(resultBlock) } -fun Connection.prepare(fn: (PreparedStatementBuilder) -> Unit): PreparedStatement { +fun Connection.prepare(template: StringTemplate): PreparedStatement { val builder = PreparedStatementBuilder(this) - fn(builder) + var constantText = true + template.forEach{ + if (constantText) { + if (it == null) { + throw IllegalStateException("No constant checks should be null"); + } else { + val text = it.toString() + if (text != null) { + builder.text(text) + } + } + } else { + builder.expression(it) + } + constantText = !constantText + } return builder.statement() } trait Binding { fun bind(statement: PreparedStatement): Unit } + class PreparedStatementBuilder(val connection: Connection) { val sql = StringBuilder() val tasks = arrayList() @@ -52,6 +68,16 @@ class PreparedStatementBuilder(val connection: Connection) { sql.append(value) } + fun expression(value: Any?): Unit { + if (value is String) { + expression(value) + } else if (value is Int) { + expression(value) + } else { + + } + } + fun expression(value: String): Unit { sql.append("?") tasks.add(object: Binding { @@ -98,21 +124,17 @@ class JdbcTemplateTest : TestCase() { // Mimicks the following code // dataSource.update("insert into foo (id, name) values ($id, $name)") - dataSource.update { - it.text("insert into foo (id, name) values (") - it.expression(id) - it.text(", ") - it.expression(name) - it.text(")") - } + // TODO will use a tuple soon + dataSource.update( + StringTemplate(array("insert into foo (id, name) values (", id, ", ", name, ")")) + ) // Mimicks - // datasource.query("select * from foo where id = $id") { it["name"] } + // datasource.query("select * from foo where id = $id") { it.map{ it["name"] } } - val names = dataSource.query({ - it.text("select * from foo where id = ") - it.expression(id) - }) { + val names = dataSource.query( + StringTemplate(array("select * from foo where id = ", id)) + ) { it.map{ it["name"] } } diff --git a/libraries/stdlib/src/kotlin/template/ReadMe.md b/libraries/stdlib/src/kotlin/template/ReadMe.md deleted file mode 100644 index 1eb8078a726..00000000000 --- a/libraries/stdlib/src/kotlin/template/ReadMe.md +++ /dev/null @@ -1,76 +0,0 @@ -## Warning experimental APIs - -This package contains a couple of alternative experimental implementations of string templates. - -These are not yet integrated into the language, but are here to compare implementation details, -suitability, code size, complexity and efficiency. - -### Aims - -* make it easy to generate various kinds of output such as text, text with internationalisation, HTML/XML, JSON, URL/URLs or make JDBC calls while reusing the same language templates with $ expressions - -### Issues - -* how many objects are created per call? -* how extensible & easy to reuse the concept of String Templates in other library features -* pass context into the template somehow; so that formatting options (Locales, nullText, JDBC Connection, converters or whatnot) can be customized -* avoid where possible lots of "if (value is SomeType)" runtime checks to determine what encoding strategy should be used - - -#### experiment1 - -Here we convert a string template into a function on some kind of builder object where we invoke the text() method for static text and expression() for dynamic expressions - -* [example](https://github.com/JetBrains/kotlin/blob/master/libraries/testlib/test/template/experiment1/HtmlTemplateTest.kt#L17) - -Pro: - -* simple and efficient code is generated - no arrays -* no arrays are created for static and expression arguments -* static dispatch of encoding functions; no runtime instanceof checks on each argument - -Cons: - -* function may create an inner object/class (though the compiler may get smart enough to inline some of those - or maybe generate a custom function for the whole thing with parameters?) -* we can only use this strategy if the template expression is passed to a function and we can detect the function parameter takes a fn: (T) -> Unit; and T has suitable text() and expression() methods. - (We can use extension methods to allow regular builder-like classes such as java.lang.StringBuilder to be used to minimise redundant object creation) - so the code generation is a bit more complex - -#### experiment2 - -Here we create a single StringTemplate object containing the constant text array and the values array. Then we use functions or extension functions as ways to do other things. - -* [example](https://github.com/JetBrains/kotlin/blob/master/libraries/testlib/test/template/experiment2/HtmlTemplateTest.kt#L13) - -Pros: - -* really simple -* no real compiler magic required where the type depends on the context - -Cons: - -* requires runtime [instanceof checks](https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/template/experiment2/Templates.kt#L66) on each expression value -* fair bit of object construction per call (2 arrays, a template object, then the string builder and lots of index lookup of arrays - - -#### experiment 3 - -The idea is we create a FooTemplate object with the static constant strings inside; so we can easily cache the immutable stuff on startup. Then we basically use pseudo code like - - val template = StringTemplate("some ", " static ", "text") - ... - val builder = template.builder() - builder.expression(foo) - builder.expression(bar) - val answer = builder.build() - -Then based on the context - e.g. an annotation or a method parameter type or something; we determine which kind of template to create (StringTemplate, HtmlTemplate, JdbcTemplate etc) - -Pros: - -* fairly simple - -Cons: - -* quite a few different types (FooTemplate and FooBuilder) -* no way to pass in parameters to the FooBuilder class; for example the JDBC connection, or the Locale / NumberFormats to use for numeric formatting etc -* requires runtime instanceof checks on each expression value & array access etc diff --git a/libraries/stdlib/src/kotlin/template/experiment2/Templates.kt b/libraries/stdlib/src/kotlin/template/Templates.kt similarity index 51% rename from libraries/stdlib/src/kotlin/template/experiment2/Templates.kt rename to libraries/stdlib/src/kotlin/template/Templates.kt index f95d58ae6ae..25c3d5f9a3f 100644 --- a/libraries/stdlib/src/kotlin/template/experiment2/Templates.kt +++ b/libraries/stdlib/src/kotlin/template/Templates.kt @@ -1,47 +1,57 @@ -package kotlin.template.experiment2 +package kotlin.template import kotlin.dom.* import org.w3c.dom.Node +import com.sun.org.apache.xalan.internal.xsltc.dom.UnionIterator +// TODO this class should move into the runtime +// in jet.StringTemplate +class StringTemplate(val values: Array) { -/** - * Creates a string template from some constant string expressions and some dynamic expressions. - */ -class StringTemplate(val constantText : Array, val expressions : Array) { - - /** - * Converts the given string template to a String - */ - fun toString(): String = toString(ToStringFormatter) - - fun toString(formatter : ValueFormatter): String { - val buffer = StringBuilder() - append(buffer, formatter) - return buffer.toString() ?: "" + fun toString(): String { + val out = StringBuilder() + forEach{ out.append(it) } + return out.toString() ?: "" } - fun append(buffer: Appendable, formatter: ValueFormatter): Unit { - val expressionSize = expressions.size - for (i in 0.upto(constantText.size - 1)) { - buffer.append(constantText[i]) - if (i < expressionSize) { - val value = expressions[i] - formatter.format(buffer, value) - } + /** + * Performs the given function on each value in the collection + */ + fun forEach(fn: (Any?) -> Unit): Unit { + for (v in values) { + fn(v) } } - - /** - * Converts the given template to HTML with an optional formatter - */ - fun toHtml(formatter: HtmlFormatter = HtmlFormatter()): String = toString(formatter) - - /** - * Appends the HTML representation of this template to the given appendable - */ - fun appendHtml(buffer: Appendable, formatter: HtmlFormatter = HtmlFormatter()): String = toString(formatter) } +fun StringTemplate.toString(formatter : ValueFormatter): String { + val buffer = StringBuilder() + append(buffer, formatter) + return buffer.toString() ?: "" +} + +fun StringTemplate.append(out: Appendable, formatter: ValueFormatter): Unit { + var constantText = true + this.forEach { + if (constantText) { + if (it == null) { + throw IllegalStateException("No constant checks should be null"); + } else { + val text = it.toString() + if (text != null) { + out.append(text) + } + } + } else { + formatter.format(out, it) + } + constantText = !constantText + } +} + + +fun StringTemplate.toHtml(formatter : HtmlFormatter = HtmlFormatter()): String = toString(formatter) + /** * Represents a formatter of values in a [[StringTemplate]] which understands how to escape * different types for different kinds of language diff --git a/libraries/stdlib/src/kotlin/template/experiment1/Templates.kt b/libraries/stdlib/src/kotlin/template/experiment1/Templates.kt deleted file mode 100644 index e28ac196edc..00000000000 --- a/libraries/stdlib/src/kotlin/template/experiment1/Templates.kt +++ /dev/null @@ -1,155 +0,0 @@ -package kotlin.template.experiment1 - -import org.w3c.dom.Node -import kotlin.dom.toXmlString - -import java.lang.Number -import java.text.DateFormat -import java.text.NumberFormat -import java.util.Date -import java.util.Locale - -fun StringBuilder.text(value : String) : Unit { - this.append(value) -} - -fun StringBuilder.expression(value : Any?) : Unit { - this.append(value) -} - -/** - * Converts a [[StringTemplate]] to a String - */ -// TODO tried toString() but compiler error kicks in -fun format(fn : (StringBuilder) -> Unit) : String { - val builder = StringBuilder() - fn(builder) - return builder.toString() ?: "" -} - - -abstract class TextBuilder(val output : Appendable) { - - /* - */ - /** - * Converts the given string template to a String - - fun toString(fn: (T) -> Unit): String = toString(ToStringFormatter, fn) - - fun toString(formatter : ValueFormatter, fn: (T) -> Unit): String { - fn(this) - return output.toString() ?: "" - } - */ - - fun text(value : String) : Unit { - output.append(value) - } -} - -open class I18nBuilder(output : Appendable, val formatter : I18nFormatter) : TextBuilder(output) { - - fun expression(value : Any?) : Unit { - escape(formatter.format(value)) - } - - fun expression(value : Number) : Unit { - escape(formatter.formatNumber(value)) - } - - fun expression(value : Date) : Unit { - escape(formatter.formatDate(value)) - } - - /** - * By default does no escaping but inherited classes may escape text - */ - open fun escape(text : String) : Unit { - output.append(text) - } -} - -open class HtmlBuilder(output : Appendable, formatter : I18nFormatter) : I18nBuilder(output, formatter) { - - /** - * Nodes are assumed to already be properly HTML/XML encoded so don't escape - */ - fun expression(value : Node) : Unit { - text(value.toXmlString()) - } - - /** - * Escapes text using HTML escaping of sensitive tokens - */ - override fun escape(text : String) : Unit { - for (c in text) { - if (c == '<') output.append("<") - else if (c == '>') output.append(">") - else if (c == '&') output.append("&") - else if (c == '"') output.append(""") - else output.append(c) - } - } -} - - -/** - * Represents a formatter of values in a [[StringTemplate]] which understands how to escape - * different types for different kinds of language - */ -trait ValueFormatter { - fun format(val value : Any?) : String -} - -open class ToStringFormatter : ValueFormatter { - - var nullText : String = "null" - - open fun toString() = "ToStringFormatter" - - override fun format(value : Any?): String { - return if (value == null) nullText else value.toString() - } -} - -open class I18nFormatter(val locale : Locale = Locale.getDefault().sure()): ToStringFormatter() { - - override fun toString() = "I18nFormatter" - - public var numberFormat : NumberFormat = NumberFormat.getInstance(locale).sure() - - public var dateFormat : DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale).sure() - - fun formatNumber(number : Number): String { - return numberFormat.format(number) ?: "" - } - - fun formatDate(date : Date): String { - return dateFormat.format(date) ?: "" - } - - /** - * Generates the internationalised text for this formatter - */ - fun toString(fn : (I18nBuilder) -> Unit) : String { - val buffer = StringBuilder() - val builder = I18nBuilder(buffer, this) - fn(builder) - return buffer.toString() ?: "" - } - - /** - * Generates the HTML for the given function - */ - fun toHtml(fn : (HtmlBuilder) -> Unit) : String { - val buffer = StringBuilder() - val html = HtmlBuilder(buffer, this) - fn(html) - return buffer.toString() ?: "" - } -} - - - - diff --git a/libraries/stdlib/src/kotlin/template/experiment3/HtmlTemplate.kt b/libraries/stdlib/src/kotlin/template/experiment3/HtmlTemplate.kt deleted file mode 100644 index 224322d962b..00000000000 --- a/libraries/stdlib/src/kotlin/template/experiment3/HtmlTemplate.kt +++ /dev/null @@ -1,64 +0,0 @@ -package kotlin.template.experiment3 - -import kotlin.dom.toXmlString -import org.w3c.dom.Node - - -/** - * Creates a string template from a string with $ expressions inside using HTML escaping of expressions. - */ -// TODO varargs on constructors seems to fail -//class HtmlTemplate(vararg val text: String) { -class HtmlTemplate(val constantText : Array) { - - /** - * Creates a builder of string expressions which use HTML encoding on expressions - */ - fun builder() : HtmlTemplateBuilder { - // TODO we should allow the caller to pass these in when we create the builder! - val options = HtmlTemplateOptions() - return HtmlTemplateBuilder(constantText, options) - } -} - -class HtmlTemplateOptions() { - var nullText : String = "" -} - -open class HtmlTemplateBuilder(constantText : Array, val options : HtmlTemplateOptions) : StringTemplateBuilder(constantText) { - - override fun expression(expression : Any) : Unit { - val text = if (expression != null) expression.toString() ?: "" else options.nullText - escape(text) - } - - /** - * Appends the DOM node, no HTML escaping is done as we assume its already escaped - */ - fun expression(node : Node) : Unit { - // no need to escape - unescape(node.toXmlString(false)) - } - - /** - * Appends the given text escaped properly - */ - fun escape(text : String): Unit { - appendNextConstant() - for (c in text) { - if (c == '<') buffer.append("<") - else if (c == '>') buffer.append(">") - else if (c == '&') buffer.append("&") - else if (c == '"') buffer.append(""") - else buffer.append(c) - } - } - - /** - * Appends the unescaped text - */ - fun unescape(text : String) { - appendNextConstant() - buffer.append(text) - } -} diff --git a/libraries/stdlib/src/kotlin/template/experiment3/StringTemplate.kt b/libraries/stdlib/src/kotlin/template/experiment3/StringTemplate.kt deleted file mode 100644 index d2df43952d0..00000000000 --- a/libraries/stdlib/src/kotlin/template/experiment3/StringTemplate.kt +++ /dev/null @@ -1,44 +0,0 @@ -package kotlin.template.experiment3 - -/** - * Creates a string template from a string with $ expressions inside. - */ -// TODO varargs on constructors seems to fail -//class StringTemplate(vararg val text: String) { -open class StringTemplate(val constantText : Array) { - - /** - * Creates a builder of string expressions - */ - open fun builder() : StringTemplateBuilder = StringTemplateBuilder(constantText) -} - -/** - * Used to build strings using expressions - */ -open class StringTemplateBuilder(val constantText : Array){ - protected val buffer: StringBuilder = StringBuilder() - var index : Int = 0 - - fun build() : String { - while (appendNextConstant()) {} - return buffer.toString() ?: "" - } - - open fun expression(expression : Any) { - appendNextConstant() - buffer.append(expression) - } - - /** - * Returns the next static text value from the template - */ - protected fun appendNextConstant(): Boolean { - if (index < constantText.size) { - buffer.append(constantText[index++]) - return true - } else { - return false - } - } -} \ No newline at end of file diff --git a/libraries/testlib/test/template/experiment2/HtmlTemplateTest.kt b/libraries/testlib/test/template/HtmlTemplateTest.kt similarity index 57% rename from libraries/testlib/test/template/experiment2/HtmlTemplateTest.kt rename to libraries/testlib/test/template/HtmlTemplateTest.kt index 458150fb321..8f13f58e93c 100644 --- a/libraries/testlib/test/template/experiment2/HtmlTemplateTest.kt +++ b/libraries/testlib/test/template/HtmlTemplateTest.kt @@ -1,6 +1,6 @@ -package test.template.experiment +package test.template -import kotlin.template.experiment2.* +import kotlin.template.* import kotlin.test.assertEquals import junit.framework.TestCase @@ -13,7 +13,10 @@ class HtmlTemplateTest : TestCase() { // Code generated by the following template expression: // // val actual = "

$foo

hey $bar

".toHtml() - val actual = StringTemplate(array("

", "

hey ", "

"), array(foo, bar)).toHtml() + + // TODO will use a tuple soon + //val actual = StringTemplate(Tuple3("

", foo, "

hey ", bar, "

")).toHtml() + val actual = StringTemplate(array("

", foo, "

hey ", bar, "

")).toHtml() assertEquals("

James

hey x > 1

", actual) } diff --git a/libraries/testlib/test/template/experiment2/StringTemplateTest.kt b/libraries/testlib/test/template/StringTemplateTest.kt similarity index 56% rename from libraries/testlib/test/template/experiment2/StringTemplateTest.kt rename to libraries/testlib/test/template/StringTemplateTest.kt index 48d7a7c2538..ab5e3e2790f 100644 --- a/libraries/testlib/test/template/experiment2/StringTemplateTest.kt +++ b/libraries/testlib/test/template/StringTemplateTest.kt @@ -1,6 +1,6 @@ -package test.template.experiment +package test.template -import kotlin.template.experiment2.* +import kotlin.template.* import kotlin.test.assertEquals import junit.framework.TestCase @@ -12,7 +12,10 @@ class StringTemplateTest : TestCase() { // Code generated by the following template expression: // // val actual = "hello $name!".toString() - val actual = StringTemplate(array("hello ", "!"), array(name)).toString() + + // TODO will use a tuple soon + //val actual = StringTemplate(Tuple3("hello ", name, "!"))).toString() + val actual = StringTemplate(array("hello ", name, "!")).toString() assertEquals("hello James!", actual) } diff --git a/libraries/testlib/test/template/experiment1/HtmlTemplateTest.kt b/libraries/testlib/test/template/experiment1/HtmlTemplateTest.kt deleted file mode 100644 index 6d99e311295..00000000000 --- a/libraries/testlib/test/template/experiment1/HtmlTemplateTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package template.experiment1 - -import kotlin.template.experiment1.* -import kotlin.test.assertEquals -import kotlin.dom.toXmlString - -import junit.framework.TestCase -import org.w3c.dom.Node - - -class HtmlTemplateTest : TestCase() { - fun testTemplate(): Unit { - val foo = "James" - val bar = "x > 1" - - val format = I18nFormatter() - // Code generated by the following template expression: - // - // val actual = format.toHtml("

$foo

hey $bar

") - val actual = format.toHtml{ - it.text("

") - it.expression(foo) - it.text("

hey ") - it.expression(bar) - it.text("

") - } - - assertEquals("

James

hey x > 1

", actual) - - println("Generated HTML: $actual") - } -} \ No newline at end of file diff --git a/libraries/testlib/test/template/experiment1/I18nTemplateTest.kt b/libraries/testlib/test/template/experiment1/I18nTemplateTest.kt deleted file mode 100644 index 9e7ba9a0d95..00000000000 --- a/libraries/testlib/test/template/experiment1/I18nTemplateTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -package template.experiment1 - -import kotlin.template.experiment1.* -import kotlin.test.assertEquals - -import junit.framework.TestCase -import java.util.Date -import java.util.Locale - -class I18nTemplateTest : TestCase() { - fun testDefaultLocale() : Unit { - format(I18nFormatter()) - } - - fun testFrance() : Unit { - format(I18nFormatter(Locale.FRANCE.sure())) - } - - fun testGermany() : Unit { - format(I18nFormatter(Locale.GERMANY.sure())) - } - - fun format(format: I18nFormatter): Unit { - val name = "James" - // TODO currently numbers cause: java.lang.ClassNotFoundException: jet.Number - //val price: Double = 1.99 - val now = Date() - - - // Code generated by the following template expression: - // - // val actual = format.toI18n("hello $name!") - val actual = format.toString{ - it.text("hello ") - it.expression(name) -/* - it.text(" price ") - it.expression(price) -*/ - it.text(" date ") - it.expression(now) - } - - println("Got text: $actual") - } -} diff --git a/libraries/testlib/test/template/experiment1/StringTemplateTest.kt b/libraries/testlib/test/template/experiment1/StringTemplateTest.kt deleted file mode 100644 index a02e2f7bb23..00000000000 --- a/libraries/testlib/test/template/experiment1/StringTemplateTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package template.experiment1 - -import kotlin.template.experiment1.* -import kotlin.test.assertEquals - -import junit.framework.TestCase - -class StringTemplateTest : TestCase() { - fun testTemplate() : Unit { - val name = "James" - - // Code generated by the following template expression: - // - // val actual = format("hello $name!") - val actual = format{ - it.text("hello ") - it.expression(name) - it.text("!") - } - - println("Got text: $actual") - assertEquals("hello James!", actual) - } -} diff --git a/libraries/testlib/test/template/experiment3/HtmlTemplateTest.kt b/libraries/testlib/test/template/experiment3/HtmlTemplateTest.kt deleted file mode 100644 index 2604eb44f88..00000000000 --- a/libraries/testlib/test/template/experiment3/HtmlTemplateTest.kt +++ /dev/null @@ -1,23 +0,0 @@ -package test.template - -import kotlin.template.experiment3.* -import kotlin.test.assertEquals - -import junit.framework.TestCase - -class HtmlTemplateTest : TestCase() { - fun testTemplate(): Unit { - val foo = "James" - val bar = "x > 1" - - // Code generated by the following template expression: - // - // val actual = [Html]"

$foo

hey $bar

" - val builder = HtmlTemplate(array("

", "

hey ", "

")).builder() - builder.expression(foo) - builder.expression(bar) - val actual = builder.build() - - assertEquals("

James

hey x > 1

", actual) - } -} \ No newline at end of file diff --git a/libraries/testlib/test/template/experiment3/StringTemplateTest.kt b/libraries/testlib/test/template/experiment3/StringTemplateTest.kt deleted file mode 100644 index fea979d128b..00000000000 --- a/libraries/testlib/test/template/experiment3/StringTemplateTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package test.template - -import kotlin.template.experiment3.* -import kotlin.test.assertEquals - -import junit.framework.TestCase - -class StringTemplateTest : TestCase() { - fun testTemplate(): Unit { - val name = "James" - - // Code generated by the following template expression: - // - // val actual = "hello $name!" - val builder = StringTemplate(array("hello ", "!")).builder() - builder.expression(name) - val actual = builder.build() - - assertEquals("hello James!", actual) - } -} \ No newline at end of file diff --git a/libraries/testlib/test/template/experiment4/Experiment4.kt b/libraries/testlib/test/template/experiment4/Experiment4.kt deleted file mode 100644 index 05db2fa0f2a..00000000000 --- a/libraries/testlib/test/template/experiment4/Experiment4.kt +++ /dev/null @@ -1,52 +0,0 @@ -package template.experiment4 - -import junit.framework.TestCase -import kotlin.test.assertEquals -import kotlin.test.todo - - -/** - * Creates a string template from some constant string expressions and some dynamic expressions. - */ -class StringTemplate(val constantText : Array, val fn : (T) -> Unit) { -} - -fun StringBuilder.text(value : String) : Unit { - this.append(value) -} - -fun StringBuilder.expression(value : Any?) : Unit { - this.append(value) -} - -/** - * Converts a [[StringTemplate]] to a String - */ -fun toString(template : StringTemplate) : String { - val builder = StringBuilder() - template.fn(builder) - return builder.toString() ?: "" -} - -class StringTemplateTest : TestCase() { - fun testTemplate() : Unit { - val name = "James" - - // Code generated by the following template expression: - // - // val actual = "hello $name!" - val template = StringTemplate(array("hello ", "!"), { (it : StringBuilder) -> - println("About to apply function!") - it.text("hello ") - it.expression(name) - it.text("!") - }) - println("Template has constants ${template.constantText.toList()} and function ${template.fn}") - - todo { - val actual = toString(template) - - assertEquals("hello James!", actual) - } - } -} \ No newline at end of file diff --git a/libraries/website/src/test/kotlin/org/jetbrains/kotlin/site/GenerateSiteTest.kt b/libraries/website/src/test/kotlin/org/jetbrains/kotlin/site/GenerateSiteTest.kt index 3e93ba2c33d..43c92de1827 100644 --- a/libraries/website/src/test/kotlin/org/jetbrains/kotlin/site/GenerateSiteTest.kt +++ b/libraries/website/src/test/kotlin/org/jetbrains/kotlin/site/GenerateSiteTest.kt @@ -32,7 +32,6 @@ class GenerateSiteTest : TestCase() { config.title = "Kotlin API ($version)" config.version = version config.ignorePackages.add("org.jetbrains.kotlin") - config.ignorePackages.add("kotlin.template.experiment") val compiler = KDocCompiler() compiler.exec(System.out, args)