Implement recovery for incomplete expression before declaration

It's needed when declarations are parsed as a part of previous expression
(see tests)

Currently we apply this kind of recovery in a conservative way,
only when declaration starts at the next line, and while
the condition could be relaxed, there's no need to do this

 #KT-4948 Fixed
 #KT-7118 Fixed
This commit is contained in:
Denis Zharkov
2016-07-13 18:32:47 +03:00
parent 06a659e6e7
commit 4725dd3028
14 changed files with 623 additions and 30 deletions
@@ -12,18 +12,18 @@ fun test() {
val x1 =
if (1 == 1)
// TODO: Diagnostic content could be better
<!EXPECTED_TYPE_MISMATCH(\(\) -> Int)!>fun named4(): Int {return 1}<!>
else
<!EXPECTED_TYPE_MISMATCH!>fun named5() = 1<!>
<!SYNTAX!><!>fun named4(): Int {return 1}
<!SYNTAX!>else<!>
fun named5() = 1
val x2 =
if (1 == 1) {
<!EXPECTED_TYPE_MISMATCH!>fun named6(): Int {
fun named6(): Int {
return 1
}<!>
}
}
else
<!EXPECTED_TYPE_MISMATCH!>fun named7() = 1<!>
<!SYNTAX!><!>fun named7() = 1
val x3 = when (1) {
0 -> <!EXPECTED_TYPE_MISMATCH!>fun named8(): Int {return 1}<!>
@@ -0,0 +1,29 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
fun foo(x: Any) {
x.<!SYNTAX!><!>
val foo = 1
x.<!SYNTAX!><!>
fun bar() = 2
x.
<!ILLEGAL_SELECTOR!>fun String.() = 3<!>
var a = 24.<!SYNTAX!><!>
var b = 42.0
}
class A {
val z = "a".<!SYNTAX!><!>
val x = 4
val y = "b".<!SYNTAX!><!>
fun baz() = 5
val q = "c".
<!ILLEGAL_SELECTOR!>fun String.() = 6<!>
var a = 24.<!SYNTAX!><!>
var b = 42.0
}
@@ -0,0 +1,18 @@
package
public fun foo(/*0*/ x: kotlin.Any): kotlin.Unit
public final class A {
public constructor A()
public final var a: [ERROR : Type for 24.]
public final var b: kotlin.Double
public final val q: [ERROR : Type for "c".
fun String.() = 6]
public final val x: kotlin.Int = 4
public final val y: [ERROR : Type for "b".]
public final val z: [ERROR : Type for "a".]
public final fun baz(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,22 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
fun foo(x: Any?) {
x ?:<!SYNTAX!><!>
val foo = 1
x ?:<!SYNTAX!><!>
fun bar() = 2
val res: String.() -> Int = null ?:
fun String.() = 3
}
class A {
val z = null ?:<!SYNTAX!><!>
val x = 4
val y = null ?:<!SYNTAX!><!>
fun baz() = 5
val q = null ?:
fun String.() = 6
}
@@ -0,0 +1,15 @@
package
public fun foo(/*0*/ x: kotlin.Any?): kotlin.Unit
public final class A {
public constructor A()
public final val q: kotlin.String.() -> kotlin.Int
public final val x: kotlin.Int = 4
public final val y: [ERROR : Type for null ?:]
public final val z: [ERROR : Type for null ?:]
public final fun baz(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1,4 +1,4 @@
fun foo(s: String) {
s.
<!DECLARATION_IN_ILLEGAL_CONTEXT, ILLEGAL_SELECTOR!>val b = 42<!>
}
s.<!SYNTAX!><!>
val <!UNUSED_VARIABLE!>b<!> = 42
}
@@ -0,0 +1,27 @@
fun foo(x: Any) {
x.
val foo = 1
x.
fun bar() = 2
x.
fun String.() = 3
var a = 24.
var b = 42.0
}
class A {
val z = "a".
val x = 4
val y = "b".
fun baz() = 5
val q = "c".
fun String.() = 6
var a = 24.
var b = 42.0
}
@@ -0,0 +1,231 @@
JetFile: DeclarationAfterDotSelectorExpected.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
VALUE_PARAMETER
PsiElement(IDENTIFIER)('x')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Any')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n\n ')
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('bar')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiWhiteSpace('\n\n ')
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x')
PsiElement(DOT)('.')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('String')
PsiElement(DOT)('.')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
DOT_QUALIFIED_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('24')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
FLOAT_CONSTANT
PsiElement(FLOAT_CONSTANT)('42.0')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('z')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
DOT_QUALIFIED_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
LITERAL_STRING_TEMPLATE_ENTRY
PsiElement(REGULAR_STRING_PART)('a')
PsiElement(CLOSING_QUOTE)('"')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('4')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
DOT_QUALIFIED_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
LITERAL_STRING_TEMPLATE_ENTRY
PsiElement(REGULAR_STRING_PART)('b')
PsiElement(CLOSING_QUOTE)('"')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('baz')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('5')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('q')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
DOT_QUALIFIED_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
LITERAL_STRING_TEMPLATE_ENTRY
PsiElement(REGULAR_STRING_PART)('c')
PsiElement(CLOSING_QUOTE)('"')
PsiElement(DOT)('.')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('String')
PsiElement(DOT)('.')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('6')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
DOT_QUALIFIED_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('24')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
FLOAT_CONSTANT
PsiElement(FLOAT_CONSTANT)('42.0')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,21 @@
fun foo(x: Any?) {
x ?:
val foo = 1
x ?:
fun bar() = 2
x ?:
fun String.() = 3
}
class A {
val z = null ?:
val x = 4
val y = null ?:
fun baz() = 5
val q = null ?:
fun String.() = 6
}
@@ -0,0 +1,188 @@
JetFile: DeclarationAfterIncompleteElvis.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
VALUE_PARAMETER
PsiElement(IDENTIFIER)('x')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Any')
PsiElement(QUEST)('?')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('bar')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiWhiteSpace('\n\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('String')
PsiElement(DOT)('.')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('z')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
NULL
PsiElement(null)('null')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('4')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
NULL
PsiElement(null)('null')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('baz')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('5')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('q')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
NULL
PsiElement(null)('null')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('String')
PsiElement(DOT)('.')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('6')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')