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:
@@ -21,6 +21,7 @@ import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.KtNodeType;
|
||||
import org.jetbrains.kotlin.KtNodeTypes;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
@@ -42,6 +43,9 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
|
||||
private static final ImmutableMap<String, KtToken> KEYWORD_TEXTS = tokenSetToMap(KEYWORDS);
|
||||
|
||||
private static final IElementType[] LOCAL_DECLARATION_FIRST =
|
||||
new IElementType[] {CLASS_KEYWORD, INTERFACE_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, TYPE_ALIAS_KEYWORD};
|
||||
|
||||
private static ImmutableMap<String, KtToken> tokenSetToMap(TokenSet tokens) {
|
||||
ImmutableMap.Builder<String, KtToken> builder = ImmutableMap.builder();
|
||||
for (IElementType token : tokens.getTypes()) {
|
||||
@@ -298,8 +302,6 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* see the precedence table
|
||||
*/
|
||||
private void parseBinaryExpression(Precedence precedence) {
|
||||
// System.out.println(precedence.name() + " at " + myBuilder.getTokenText());
|
||||
|
||||
PsiBuilder.Marker expression = mark();
|
||||
|
||||
precedence.parseHigherPrecedence(this);
|
||||
@@ -331,10 +333,8 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* operation? prefixExpression
|
||||
*/
|
||||
private void parsePrefixExpression() {
|
||||
// System.out.println("pre at " + myBuilder.getTokenText());
|
||||
|
||||
if (at(AT)) {
|
||||
if (!parseLocalDeclaration()) {
|
||||
if (!parseLocalDeclaration(/* rollbackIfDefinitelyNotExpression = */ false)) {
|
||||
PsiBuilder.Marker expression = mark();
|
||||
myKotlinParsing.parseAnnotations(DEFAULT);
|
||||
parsePrefixExpression();
|
||||
@@ -454,7 +454,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
expression = mark();
|
||||
}
|
||||
|
||||
parseCallExpression();
|
||||
parseSelectorCallExpression();
|
||||
|
||||
if (firstExpressionParsed) {
|
||||
expression.done(expressionType);
|
||||
@@ -515,7 +515,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
/*
|
||||
* atomicExpression typeParameters? valueParameters? functionLiteral*
|
||||
*/
|
||||
private void parseCallExpression() {
|
||||
private void parseSelectorCallExpression() {
|
||||
PsiBuilder.Marker mark = mark();
|
||||
parseAtomicExpression();
|
||||
if (!myBuilder.newlineBeforeCurrentToken() && parseCallSuffix()) {
|
||||
@@ -624,8 +624,6 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* ;
|
||||
*/
|
||||
private boolean parseAtomicExpression() {
|
||||
// System.out.println("atom at " + myBuilder.getTokenText());
|
||||
|
||||
boolean ok = true;
|
||||
|
||||
if (at(LPAR)) {
|
||||
@@ -670,9 +668,9 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
else if (at(DO_KEYWORD)) {
|
||||
parseDoWhile();
|
||||
}
|
||||
else if (atSet(CLASS_KEYWORD, INTERFACE_KEYWORD, FUN_KEYWORD, VAL_KEYWORD,
|
||||
VAR_KEYWORD, TYPE_ALIAS_KEYWORD)) {
|
||||
parseLocalDeclaration();
|
||||
else if (atSet(LOCAL_DECLARATION_FIRST) &&
|
||||
parseLocalDeclaration(/* rollbackIfDefinitelyNotExpression = */ myBuilder.newlineBeforeCurrentToken())) {
|
||||
// declaration was parsed, do nothing
|
||||
}
|
||||
else if (at(IDENTIFIER)) {
|
||||
parseSimpleNameExpression();
|
||||
@@ -1018,12 +1016,12 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
/*
|
||||
* modifiers declarationRest
|
||||
*/
|
||||
private boolean parseLocalDeclaration() {
|
||||
private boolean parseLocalDeclaration(boolean rollbackIfDefinitelyNotExpression) {
|
||||
PsiBuilder.Marker decl = mark();
|
||||
KotlinParsing.ModifierDetector detector = new KotlinParsing.ModifierDetector();
|
||||
myKotlinParsing.parseModifierList(detector, DEFAULT, TokenSet.EMPTY);
|
||||
|
||||
IElementType declType = parseLocalDeclarationRest(detector.isEnumDetected());
|
||||
IElementType declType = parseLocalDeclarationRest(detector.isEnumDetected(), rollbackIfDefinitelyNotExpression);
|
||||
|
||||
if (declType != null) {
|
||||
// we do not attach preceding comments (non-doc) to local variables because they are likely commenting a few statements below
|
||||
@@ -1220,7 +1218,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* ;
|
||||
*/
|
||||
private void parseStatement(boolean isScriptTopLevel) {
|
||||
if (!parseLocalDeclaration()) {
|
||||
if (!parseLocalDeclaration(/* rollbackIfDefinitelyNotExpression = */false)) {
|
||||
if (!atSet(EXPRESSION_FIRST)) {
|
||||
errorAndAdvance("Expecting a statement");
|
||||
}
|
||||
@@ -1245,9 +1243,17 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* : object
|
||||
* ;
|
||||
*/
|
||||
private IElementType parseLocalDeclarationRest(boolean isEnum) {
|
||||
@Nullable
|
||||
private IElementType parseLocalDeclarationRest(boolean isEnum, boolean failIfDefinitelyNotExpression) {
|
||||
IElementType keywordToken = tt();
|
||||
IElementType declType = null;
|
||||
|
||||
if (failIfDefinitelyNotExpression) {
|
||||
if (keywordToken != FUN_KEYWORD) return null;
|
||||
|
||||
return myKotlinParsing.parseFunction(/* failIfIdentifierExists = */ true);
|
||||
}
|
||||
|
||||
if (keywordToken == CLASS_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
||||
declType = myKotlinParsing.parseClass(isEnum);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.lang.WhitespacesBinders;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
@@ -1444,6 +1445,11 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
return accessorKind;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
IElementType parseFunction() {
|
||||
return parseFunction(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* function
|
||||
* : modifiers "fun" typeParameters?
|
||||
@@ -1454,7 +1460,8 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
* functionBody?
|
||||
* ;
|
||||
*/
|
||||
IElementType parseFunction() {
|
||||
@Contract("false -> !null")
|
||||
IElementType parseFunction(boolean failIfIdentifierExists) {
|
||||
assert _at(FUN_KEYWORD);
|
||||
|
||||
advance(); // FUN_KEYWORD
|
||||
@@ -1476,6 +1483,11 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
TokenSet functionNameFollow = TokenSet.create(LT, LPAR, RPAR, COLON, EQ);
|
||||
boolean receiverFound = parseReceiverType("function", functionNameFollow);
|
||||
|
||||
if (at(IDENTIFIER) && failIfIdentifierExists) {
|
||||
myBuilder.restoreJoiningComplexTokensState();
|
||||
return null;
|
||||
}
|
||||
|
||||
// function as expression has no name
|
||||
parseFunctionOrPropertyName(receiverFound, "function", functionNameFollow, /*nameRequired = */ false);
|
||||
|
||||
@@ -1598,15 +1610,15 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
/*
|
||||
* IDENTIFIER
|
||||
*/
|
||||
private void parseFunctionOrPropertyName(boolean receiverFound, String title, TokenSet nameFollow, boolean nameRequired) {
|
||||
if (!nameRequired && atSet(nameFollow)) return; // no name
|
||||
private boolean parseFunctionOrPropertyName(boolean receiverFound, String title, TokenSet nameFollow, boolean nameRequired) {
|
||||
if (!nameRequired && atSet(nameFollow)) return true; // no name
|
||||
|
||||
TokenSet recoverySet = TokenSet.orSet(nameFollow, TokenSet.create(LBRACE, RBRACE), TOP_LEVEL_DECLARATION_FIRST);
|
||||
if (!receiverFound) {
|
||||
expect(IDENTIFIER, "Expecting " + title + " name or receiver type", recoverySet);
|
||||
return expect(IDENTIFIER, "Expecting " + title + " name or receiver type", recoverySet);
|
||||
}
|
||||
else {
|
||||
expect(IDENTIFIER, "Expecting " + title + " name", recoverySet);
|
||||
return expect(IDENTIFIER, "Expecting " + title + " name", recoverySet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -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}<!>
|
||||
|
||||
+29
@@ -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
|
||||
}
|
||||
+18
@@ -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
|
||||
}
|
||||
+22
@@ -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
|
||||
}
|
||||
+15
@@ -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
|
||||
}
|
||||
+3
-3
@@ -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)('}')
|
||||
@@ -8723,6 +8723,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("declarationAfterDotSelectorExpected.kt")
|
||||
public void testDeclarationAfterDotSelectorExpected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/declarationAfterDotSelectorExpected.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("declarationAfterIncompleteElvis.kt")
|
||||
public void testDeclarationAfterIncompleteElvis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/declarationAfterIncompleteElvis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("funEquals.kt")
|
||||
public void testFunEquals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funEquals.kt");
|
||||
|
||||
@@ -1992,6 +1992,18 @@ public class ParsingTestGenerated extends AbstractParsingTest {
|
||||
doParsingTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DeclarationAfterDotSelectorExpected.kt")
|
||||
public void testDeclarationAfterDotSelectorExpected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/recovery/DeclarationAfterDotSelectorExpected.kt");
|
||||
doParsingTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DeclarationAfterIncompleteElvis.kt")
|
||||
public void testDeclarationAfterIncompleteElvis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/recovery/DeclarationAfterIncompleteElvis.kt");
|
||||
doParsingTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DoWhileWithEmptyCondition.kt")
|
||||
public void testDoWhileWithEmptyCondition() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/recovery/DoWhileWithEmptyCondition.kt");
|
||||
|
||||
Reference in New Issue
Block a user