diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 2ccace9af81..61a384889fd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -468,8 +468,9 @@ public class JetExpressionParsing extends AbstractJetParsing { */ protected boolean parseCallWithClosure() { boolean success = false; - while (!myBuilder.newlineBeforeCurrentToken() - && (at(LBRACE) +// while (!myBuilder.newlineBeforeCurrentToken() +// && (at(LBRACE) + while ((at(LBRACE) || atSet(LABELS) && lookahead(1) == LBRACE)) { if (!at(LBRACE)) { assert _atSet(LABELS); diff --git a/compiler/testData/diagnostics/tests/Builders.jet b/compiler/testData/diagnostics/tests/Builders.jet index 762d4d2fbf9..5d2f38686de 100644 --- a/compiler/testData/diagnostics/tests/Builders.jet +++ b/compiler/testData/diagnostics/tests/Builders.jet @@ -1,122 +1,157 @@ // FILE: a.kt // +JDK +/** + * This is an example of a Type-Safe Groovy-style Builder + * + * Builders are good for declaratively describing data in your code. + * In this example we show how to describe an HTML page in Kotlin. + * + * See this page for details: + * http://confluence.jetbrains.net/display/Kotlin/Type-safe+Groovy-style+builders + */ package html + import java.util.* - abstract class Factory { - abstract fun create() : T - } - - abstract class Element - - class TextElement(val text : String) : Element - - abstract class Tag(val name : String) : Element { - val children = ArrayList() - val attributes = HashMap() - - protected fun initTag(init : T.() -> Unit) : T - where class object T : Factory{ - val tag = T.create() - tag.init() - children.add(tag) - return tag - } - } - - abstract class TagWithText(name : String) : Tag(name) { - fun String.plus() { - children.add(TextElement(this)) - } - } - - class HTML() : TagWithText("html") { - class object : Factory { - override fun create() = HTML() - } - - fun head(init : Head.() -> Unit) = initTag(init) - - fun body(init : Body.() -> Unit) = initTag(init) - } - - class Head() : TagWithText("head") { - class object : Factory { - override fun create() = Head() - } - - fun title(init : Title.() -> Unit) = initTag(init) - } - - class Title() : TagWithText("title") - - abstract class BodyTag(name : String) : TagWithText(name) { - } - - class Body() : BodyTag("body") { - class object : Factory<Body> { - override fun create() = Body() - } - - fun b(init : B.() -> Unit) = initTag<B>(init) - fun p(init : P.() -> Unit) = initTag<P>(init) - fun h1(init : H1.() -> Unit) = initTag<H1>(init) - fun a(href : String, init : A.() -> Unit) { - val a = initTag<A>(init) - a.href = href - } - } - - class B() : BodyTag("b") - class P() : BodyTag("p") - class H1() : BodyTag("h1") - class A() : BodyTag("a") { - var href : String - get() = attributes["href"] - set(value) { attributes["href"] = value } - } - - fun Map<String, String>.set(key : String, value : String) = this.put(key, value) - - fun html(init : HTML.() -> Unit) : HTML { - val html = HTML() - html.init() - return html - } - -// FILE: b.kt - -package foo - -import html.* - -fun result(args : Array<String>) = - html { - head { - title {+"XML encoding with Groovy"} - } - body { - h1 {+"XML encoding with Groovy"} - p {+"this format can be used as an alternative markup to XML"} - - // an element with attributes and text content - a(href = "http://groovy.codehaus.org") {+"Groovy"} - - // mixed content - p { - +"This is some" - b {+"mixed"} - +"text. For more see the" - a(href = "http://groovy.codehaus.org") {+"Groovy"} - +"project" +fun main(args : Array<String>) { + val result = + html { + head { + title {+"XML encoding with Kotlin"} } - p {+"some text"} + body { + h1 {+"XML encoding with Kotlin"} + p {+"this format can be used as an alternative markup to XML"} - // content generated by - p { - for (arg in args) - +arg + // an element with attributes and text content + a(href = "http://jetbrains.com/kotlin") {+"Kotlin"} + + // mixed content + p { + +"This is some" + b {+"mixed"} + +"text. For more see the" + a(href = "http://jetbrains.com/kotlin") {+"Kotlin"} + +"project" + } + p {+"some text"} + + // content generated from command-line arguments + p { + +"Command line arguments were:" + ul { + for (arg in args) + li {+arg} + } + } } } + println(result) +} + +trait Element { + fun render(builder : StringBuilder, indent : String) + + fun toString() : String? { + val builder = StringBuilder() + render(builder, "") + return builder.toString() } +} + +class TextElement(val text : String) : Element { + override fun render(builder : StringBuilder, indent : String) { + builder.append("$indent$text\n") + } +} + +abstract class Tag(val name : String) : Element { + val children = ArrayList<Element>() + val attributes = HashMap<String, String>() + + protected fun initTag<T : Element>(tag : T, init : T.() -> Unit) : T { + tag.init() + children.add(tag) + return tag + } + + override fun render(builder : StringBuilder, indent : String) { + builder.append("$indent<$name${renderAttributes()}>\n") + for (c in children) { + c.render(builder, indent + " ") + } + builder.append("$indent</$name>\n") + } + + private fun renderAttributes() : String? { + val builder = StringBuilder() + for (a in attributes.keySet()) { + builder.append(" $a=\"${attributes[a]}\"") + } + return builder.toString() + } +} + +abstract class TagWithText(name : String) : Tag(name) { + fun String.plus() { + children.add(TextElement(this)) + } +} + +class HTML() : TagWithText("html") { + fun head(init : Head.() -> Unit) = initTag(Head(), init) + + fun body(init : Body.() -> Unit) = initTag(Body(), init) +} + +class Head() : TagWithText("head") { + fun title(init : Title.() -> Unit) = initTag(Title(), init) +} + +class Title() : TagWithText("title") + +abstract class BodyTag(name : String) : TagWithText(name) { + fun b(init : B.() -> Unit) = initTag(B(), init) + fun p(init : P.() -> Unit) = initTag(P(), init) + fun h1(init : H1.() -> Unit) = initTag(H1(), init) + fun ul(init : UL.() -> Unit) = initTag(UL(), init) + fun a(href : String, init : A.() -> Unit) { + val a = initTag(A(), init) + a.href = href + } +} + +class Body() : BodyTag("body") +class UL() : BodyTag("ul") { + fun li(init : LI.() -> Unit) = initTag(LI(), init) +} + +class B() : BodyTag("b") +class LI() : BodyTag("li") +class P() : BodyTag("p") +class H1() : BodyTag("h1") +class A() : BodyTag("a") { + public var href : String + get() = attributes["href"] + set(value) { + attributes["href"] = value + } +} + +fun html(init : HTML.() -> Unit) : HTML { + val html = HTML() + html.init() + return html +} + +// An excerpt from the Standard Library +fun <K, V> Map<K, V>.set(key : K, value : V) = this.put(key, value) + +fun println(message : Any?) { + System.out?.println(message) +} + +fun print(message : Any?) { + System.out?.print(message) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.jet b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.jet index 32fc8be4b84..b190d98be31 100644 --- a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.jet +++ b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.jet @@ -53,7 +53,7 @@ fun f() : Int.() -> Unit = {} fun main1() { 1.{Int.() -> 1}(); - {1}() + {1}(); {(x : Int) -> x}(1) 1.{Int.(x : Int) -> x}(1) @l{1}() @@ -71,11 +71,11 @@ fun main1() { } fun test() { - {(x : Int) -> 1}<!NO_VALUE_FOR_PARAMETER!>()<!> + {(x : Int) -> 1}<!NO_VALUE_FOR_PARAMETER!>()<!>; <!MISSING_RECEIVER!>{Int.() -> 1}<!>() <!TYPE_MISMATCH!>"sd"<!>.{Int.() -> 1}() val i : Int? = null - i<!UNSAFE_CALL!>.<!>{Int.() -> 1}() + i<!UNSAFE_CALL!>.<!>{Int.() -> 1}(); {}<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>() 1<!UNNECESSARY_SAFE_CALL!>?.<!>{Int.() -> 1}() 1.<!NO_RECEIVER_ADMITTED!>{}<!>() diff --git a/compiler/testData/diagnostics/tests/regressions/kt306.jet b/compiler/testData/diagnostics/tests/regressions/kt306.jet index b78f2902f9d..cb4a4f182f5 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt306.jet +++ b/compiler/testData/diagnostics/tests/regressions/kt306.jet @@ -2,7 +2,7 @@ fun test() { {Foo.() -> - bar() + bar(); {Barr.() -> this.bar() bar() diff --git a/compiler/testData/psi/FunctionCalls.jet b/compiler/testData/psi/FunctionCalls.jet index 42161ea63ae..b3815710d1a 100644 --- a/compiler/testData/psi/FunctionCalls.jet +++ b/compiler/testData/psi/FunctionCalls.jet @@ -4,7 +4,7 @@ fun foo() { f<foo> (a) f {s} - f + f; {s} f { s @@ -12,14 +12,14 @@ fun foo() { f(a) { s } - f(a) + f(a); { s } f<a>(a) { s } - f<a>(a) + f<a>(a); { s } diff --git a/compiler/testData/psi/FunctionCalls.txt b/compiler/testData/psi/FunctionCalls.txt index 226682524cb..b008b1afe86 100644 --- a/compiler/testData/psi/FunctionCalls.txt +++ b/compiler/testData/psi/FunctionCalls.txt @@ -72,6 +72,7 @@ JetFile: FunctionCalls.jet PsiWhiteSpace('\n ') REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('f') + PsiElement(SEMICOLON)(';') PsiWhiteSpace('\n ') FUNCTION_LITERAL_EXPRESSION FUNCTION_LITERAL @@ -124,6 +125,7 @@ JetFile: FunctionCalls.jet REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RPAR)(')') + PsiElement(SEMICOLON)(';') PsiWhiteSpace('\n ') FUNCTION_LITERAL_EXPRESSION FUNCTION_LITERAL @@ -180,6 +182,7 @@ JetFile: FunctionCalls.jet REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RPAR)(')') + PsiElement(SEMICOLON)(';') PsiWhiteSpace('\n ') FUNCTION_LITERAL_EXPRESSION FUNCTION_LITERAL