提交 08d62853 编写于 作者: N Nikolay Krasko

Assign trailing and preceding whitespaces to lambda block until the last comment in parser

上级 02613856
......@@ -17,13 +17,13 @@
package org.jetbrains.kotlin.parsing
import com.intellij.lang.WhitespacesAndCommentsBinder
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.lexer.KtTokens
import com.intellij.openapi.util.text.StringUtil
object PrecedingCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
override fun getEdgePosition(
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
// 1. bind doc comment
......@@ -53,8 +53,8 @@ object PrecedingCommentsBinder : WhitespacesAndCommentsBinder {
}
object PrecedingDocCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
override fun getEdgePosition(
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
for (idx in tokens.indices.reversed()) {
......@@ -67,8 +67,8 @@ object PrecedingDocCommentsBinder : WhitespacesAndCommentsBinder {
// Binds comments on the same line
object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
override fun getEdgePosition(
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
var result = 0
......@@ -87,8 +87,30 @@ object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
}
}
private class AllCommentsBinder(val isTrailing: Boolean) : WhitespacesAndCommentsBinder {
override fun getEdgePosition(
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
val size = tokens.size
// Skip comment if needed. Expect that there can't be several consecutive comments
val endToken = tokens[if (isTrailing) size - 1 else 0]
val shift = if (endToken == KtTokens.WHITE_SPACE) 1 else 0
return if (isTrailing) size - shift else shift
}
}
@JvmField
val PRECEDING_ALL_COMMENTS_BINDER: WhitespacesAndCommentsBinder = AllCommentsBinder(false)
@JvmField
val TRAILING_ALL_COMMENTS_BINDER: WhitespacesAndCommentsBinder = AllCommentsBinder(true)
object DoNotBindAnything : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
override fun getEdgePosition(
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
return 0
}
}
\ No newline at end of file
......@@ -1091,7 +1091,9 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
else {
PsiBuilder.Marker body = mark();
parseStatements();
body.done(BLOCK);
body.setCustomEdgeTokenBinders(CommentBindersKt.PRECEDING_ALL_COMMENTS_BINDER, CommentBindersKt.TRAILING_ALL_COMMENTS_BINDER);
expect(RBRACE, "Expecting '}'");
literal.done(FUNCTION_LITERAL);
......
......@@ -305,30 +305,30 @@ sink:
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark(if (state) state = true println(state))
2 <START> INIT: in: {some=D} out: {some=D}
3 mark(if (state) state = true println(state) // OK)
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6)
L5 [else branch]:
read (Unit)
L6 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5>
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?} out: {some=I?} USE: in: {} out: {}
<SINK> INIT: in: {some=I?} out: {some=I?} USE: in: {} out: {}
=====================
== exec ==
fun <T> exec(f: () -> T): T = f()
......@@ -391,30 +391,30 @@ sink:
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark(if (state) state = true println(state))
2 <START> INIT: in: {some=D} out: {some=D}
3 mark(if (state) state = true println(state) // must be initialized)
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) INIT: in: {some=D} out: {some=D, state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6) INIT: in: {some=D, state=I} out: {some=D, state=I}
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) INIT: in: {some=D} out: {some=D, state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6) INIT: in: {some=D, state=I} out: {some=D, state=I}
L5 [else branch]:
read (Unit) INIT: in: {some=D} out: {some=D}
read (Unit) INIT: in: {some=D} out: {some=D}
L6 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5> INIT: in: {some=D, state=I} out: {some=D, state=I}
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
merge(if (state) state = true|!<v4>) -> <v5> INIT: in: {some=D, state=I} out: {some=D, state=I}
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {} out: {}
<SINK> INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {} out: {}
=====================
== Demo5 ==
class Demo5 {
......
......@@ -164,16 +164,16 @@ true <v3>: Boolean
println(state) // OK
}
---------------------
<v0>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
if (state) state = true println(state) <v8>: * COPY
<v0>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
if (state) state = true println(state) // OK <v8>: * COPY
=====================
== exec ==
fun <T> exec(f: () -> T): T = f()
......@@ -206,16 +206,16 @@ true <v2>: B
println(state) // must be initialized
}
---------------------
<v0>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
if (state) state = true println(state) <v8>: * COPY
<v0>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
if (state) state = true println(state) // must be initialized <v8>: * COPY
=====================
== Demo5 ==
class Demo5 {
......
......@@ -58,15 +58,15 @@ sink:
---------------------
L3:
3 <START>
4 mark(return nonLocal)
4 mark(return nonLocal //unreachable)
r(nonLocal) -> <v0>
ret(*|<v0>) L1 NEXT:[<END>]
ret(*|<v0>) L1 NEXT:[<END>]
L4:
3 <END> NEXT:[<SINK>] PREV:[]
3 <END> NEXT:[<SINK>] PREV:[]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
== doSomething ==
fun doSomething() {}
......
......@@ -26,9 +26,9 @@ return "NON_LOCAL_FAILED $localResult"
return nonLocal //unreachable
}
---------------------
nonLocal <v0>: String NEW: r(nonLocal) -> <v0>
return nonLocal !<v1>: *
return nonLocal !<v1>: * COPY
nonLocal <v0>: String NEW: r(nonLocal) -> <v0>
return nonLocal !<v1>: *
return nonLocal //unreachable !<v1>: * COPY
=====================
== doSomething ==
fun doSomething() {}
......
val la1 = {
// start
// start 1
foo()
// middle
foo()
// end
}
val la2 = {
/**/
}
val la3 = {
/** */
}
val la4 = {
/** Should be under block */
/** Should be under property */
val some = 1
}
val la5 = {
/** */
/** */
}
val la6 = /*1*/ {/*2*/ a /*3*/ -> /*4*/
}
val la7 = {/**/}
fun foo() {}
JetFile: CommentsBindingInLambda.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la1')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BLOCK
PsiComment(EOL_COMMENT)('// start')
PsiWhiteSpace('\n ')
PsiComment(EOL_COMMENT)('// start 1')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
PsiComment(EOL_COMMENT)('// middle')
PsiWhiteSpace('\n\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
PsiComment(EOL_COMMENT)('// end')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la2')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BLOCK
PsiComment(BLOCK_COMMENT)('/**/')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la3')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BLOCK
KDoc
PsiElement(KDOC_START)('/**')
KDOC_SECTION
PsiElement(KDOC_TEXT)(' ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la4')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BLOCK
KDoc
PsiElement(KDOC_START)('/**')
KDOC_SECTION
PsiElement(KDOC_TEXT)(' Should be under block ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n\n ')
PROPERTY
KDoc
PsiElement(KDOC_START)('/**')
KDOC_SECTION
PsiElement(KDOC_TEXT)(' Should be under property ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('some')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la5')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BLOCK
KDoc
PsiElement(KDOC_START)('/**')
KDOC_SECTION
PsiElement(KDOC_TEXT)(' ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
KDoc
PsiElement(KDOC_START)('/**')
KDOC_SECTION
PsiElement(KDOC_TEXT)(' ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la6')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
PsiComment(BLOCK_COMMENT)('/*1*/')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiComment(BLOCK_COMMENT)('/*2*/')
PsiWhiteSpace(' ')
VALUE_PARAMETER_LIST
VALUE_PARAMETER
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PsiComment(BLOCK_COMMENT)('/*3*/')
PsiWhiteSpace(' ')
PsiElement(ARROW)('->')
PsiWhiteSpace(' ')
BLOCK
PsiComment(BLOCK_COMMENT)('/*4*/')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('la7')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
BLOCK
PsiComment(BLOCK_COMMENT)('/**/')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
\ No newline at end of file
fun test() {
if (true) {/*start-end*/}
if (true) {
/*start-end*/
}
if (true) {
/*start*/
/*end*/
}
if (true) {
/*start*/
/** doc */
val a = 12
/*end*/
}
}
\ No newline at end of file
JetFile: CommentsBindingInStatementBlock.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
IF
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
THEN
BLOCK
PsiElement(LBRACE)('{')
PsiComment(BLOCK_COMMENT)('/*start-end*/')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
IF
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
THEN
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiComment(BLOCK_COMMENT)('/*start-end*/')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
IF
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
THEN
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiComment(BLOCK_COMMENT)('/*start*/')
PsiWhiteSpace('\n ')
PsiComment(BLOCK_COMMENT)('/*end*/')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
IF
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
THEN
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiComment(BLOCK_COMMENT)('/*start*/')
PsiWhiteSpace('\n\n ')
PROPERTY
KDoc
PsiElement(KDOC_START)('/**')
KDOC_SECTION
PsiElement(KDOC_TEXT)(' doc ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('12')
PsiWhiteSpace('\n\n ')
PsiComment(BLOCK_COMMENT)('/*end*/')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
\ No newline at end of file
fun test() {
// start
foo()
// middle
foo()
// end
}
fun foo() {}
JetFile: LineCommentsInBlock.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiComment(EOL_COMMENT)('// start')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
PsiComment(EOL_COMMENT)('// middle')
PsiWhiteSpace('\n\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
PsiComment(EOL_COMMENT)('// end')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
\ No newline at end of file
......@@ -61,9 +61,9 @@ JetFile: lambda.kt
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// parsed as array access')
PsiWhiteSpace('\n ')
BLOCK
PsiComment(EOL_COMMENT)('// parsed as array access')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('print')
......
......@@ -33,9 +33,9 @@ JetFile: recovery.kt
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// should be no space after c')
PsiWhiteSpace('\n ')
BLOCK
PsiComment(EOL_COMMENT)('// should be no space after c')
PsiWhiteSpace('\n ')
RETURN
PsiElement(return)('return')
PsiWhiteSpace(' ')
......@@ -61,9 +61,9 @@ JetFile: recovery.kt
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// no label identifier')
PsiWhiteSpace('\n ')
BLOCK
PsiComment(EOL_COMMENT)('// no label identifier')
PsiWhiteSpace('\n ')
RETURN
PsiElement(return)('return')
PsiWhiteSpace(' ')
......@@ -94,9 +94,9 @@ JetFile: recovery.kt
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// should be no space after loop2')
PsiWhiteSpace('\n ')
BLOCK
PsiComment(EOL_COMMENT)('// should be no space after loop2')
PsiWhiteSpace('\n ')
RETURN
PsiElement(return)('return')
PsiErrorElement:Label must be named
......
......@@ -127,6 +127,18 @@ public class ParsingTestGenerated extends AbstractParsingTest {
doParsingTest(fileName);
}
@TestMetadata("CommentsBindingInLambda.kt")
public void testCommentsBindingInLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/CommentsBindingInLambda.kt");
doParsingTest(fileName);
}
@TestMetadata("CommentsBindingInStatementBlock.kt")
public void testCommentsBindingInStatementBlock() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/CommentsBindingInStatementBlock.kt");
doParsingTest(fileName);
}
@TestMetadata("Constructors.kt")
public void testConstructors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/Constructors.kt");
......@@ -541,6 +553,12 @@ public class ParsingTestGenerated extends AbstractParsingTest {
doParsingTest(fileName);
}
@TestMetadata("LineCommentsInBlock.kt")
public void testLineCommentsInBlock() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/LineCommentsInBlock.kt");
doParsingTest(fileName);
}
@TestMetadata("LocalDeclarations.kt")
public void testLocalDeclarations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/LocalDeclarations.kt");
......
......@@ -4,7 +4,8 @@
fun foo(list: List<String>) {
// string should be non-empty
// save it into result
val result: String? = list.firstOrNull { // search for first non-empty string in the list
val result: String? = list.firstOrNull {
// search for first non-empty string in the list
it.length > 0
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册