From 3266d8c29a8ef5fc3bbbdcb1bee3ae56874f2b6f Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Fri, 19 Jun 2015 14:43:29 +0300 Subject: [PATCH] Parser: Disable joining complex tokens while parsing type references #KT-8141 Fixed --- .../jetbrains/kotlin/parsing/JetParsing.java | 13 +- .../psi/greatSyntacticShift/functionTypes.txt | 82 +++-- .../psi/greatSyntacticShift/nullableTypes.kt | 17 + .../psi/greatSyntacticShift/nullableTypes.txt | 292 ++++++++++++++++++ .../parsing/JetParsingTestGenerated.java | 6 + 5 files changed, 375 insertions(+), 35 deletions(-) create mode 100644 compiler/testData/psi/greatSyntacticShift/nullableTypes.kt create mode 100644 compiler/testData/psi/greatSyntacticShift/nullableTypes.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java index 80fcc21612a..17e41d2ea35 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java @@ -1835,10 +1835,6 @@ public class JetParsing extends AbstractJetParsing { // The extraRecoverySet is needed for the foo(bar(z)) case, to tell whether we should stop // on expression-indicating symbols or not private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet) { - // Disabling token merge is required for cases like - // Int?.(Foo) -> Bar - // we don't support this case now -// myBuilder.disableJoiningComplexTokens(); PsiBuilder.Marker typeRefMarker = mark(); parseAnnotations(ONLY_ESCAPED_REGULAR_ANNOTATIONS); @@ -1898,7 +1894,11 @@ public class JetParsing extends AbstractJetParsing { typeBeforeDot = false; } + // Disabling token merge is required for cases like + // Int?.(Foo) -> Bar + myBuilder.disableJoiningComplexTokens(); typeRefMarker = parseNullableTypeSuffix(typeRefMarker); + myBuilder.restoreJoiningComplexTokensState(); if (typeBeforeDot && at(DOT)) { // This is a receiver for a function type @@ -1922,13 +1922,14 @@ public class JetParsing extends AbstractJetParsing { functionType.done(FUNCTION_TYPE); } -// myBuilder.restoreJoiningComplexTokensState(); + return typeRefMarker; } @NotNull PsiBuilder.Marker parseNullableTypeSuffix(@NotNull PsiBuilder.Marker typeRefMarker) { - while (at(QUEST)) { + // ?: is joined regardless of joining state + while (at(QUEST) && myBuilder.rawLookup(1) != COLON) { PsiBuilder.Marker precede = typeRefMarker.precede(); advance(); // QUEST typeRefMarker.done(NULLABLE_TYPE); diff --git a/compiler/testData/psi/greatSyntacticShift/functionTypes.txt b/compiler/testData/psi/greatSyntacticShift/functionTypes.txt index 98d012b695c..41433048b8b 100644 --- a/compiler/testData/psi/greatSyntacticShift/functionTypes.txt +++ b/compiler/testData/psi/greatSyntacticShift/functionTypes.txt @@ -503,18 +503,30 @@ JetFile: functionTypes.kt PsiElement(COLON)(':') PsiWhiteSpace(' ') TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Int') - PsiErrorElement:Property getter or setter expected - PsiElement(SAFE_ACCESS)('?.') - PsiElement(LPAR)('(') - PsiElement(IDENTIFIER)('Int') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('Int') + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(QUEST)('?') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') PsiWhiteSpace('\n ') PROPERTY MODIFIER_LIST @@ -1050,22 +1062,34 @@ JetFile: functionTypes.kt PsiElement(COLON)(':') PsiWhiteSpace(' ') TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Int') - PsiErrorElement:Property getter or setter expected - PsiElement(SAFE_ACCESS)('?.') - PsiElement(LPAR)('(') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('Int') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('Int') + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(QUEST)('?') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') PsiWhiteSpace('\n ') PROPERTY MODIFIER_LIST @@ -1273,4 +1297,4 @@ JetFile: functionTypes.kt REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('Int') PsiWhiteSpace('\n') - PsiElement(RBRACE)('}') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/greatSyntacticShift/nullableTypes.kt b/compiler/testData/psi/greatSyntacticShift/nullableTypes.kt new file mode 100644 index 00000000000..a85a83b810e --- /dev/null +++ b/compiler/testData/psi/greatSyntacticShift/nullableTypes.kt @@ -0,0 +1,17 @@ +fun test() { + x as? X ?: return + x as? X? : return + x as X? ?: return + + X?::x + X ?:: x + X? ?:: x + X ??:: x + X ?? :: x + + val x: X?.() -> Unit + val x: X??.() -> Unit + val x: X?? .() -> Unit + val x: X ? .() -> Unit + val x: X ?.() -> Unit +} \ No newline at end of file diff --git a/compiler/testData/psi/greatSyntacticShift/nullableTypes.txt b/compiler/testData/psi/greatSyntacticShift/nullableTypes.txt new file mode 100644 index 00000000000..427410192b8 --- /dev/null +++ b/compiler/testData/psi/greatSyntacticShift/nullableTypes.txt @@ -0,0 +1,292 @@ +JetFile: nullableTypes.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BINARY_EXPRESSION + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(AS_SAFE)('as?') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(ELVIS)('?:') + PsiWhiteSpace(' ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace('\n ') + BINARY_WITH_TYPE + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(AS_SAFE)('as?') + PsiWhiteSpace(' ') + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + PsiElement(return)('return') + PsiWhiteSpace('\n ') + BINARY_EXPRESSION + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(as)('as') + PsiWhiteSpace(' ') + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(ELVIS)('?:') + PsiWhiteSpace(' ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace('\n\n ') + CALLABLE_REFERENCE_EXPRESSION + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiElement(COLONCOLON)('::') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + PsiElement(QUEST)('?') + PsiElement(COLONCOLON)('::') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + TYPE_REFERENCE + NULLABLE_TYPE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiWhiteSpace(' ') + PsiElement(QUEST)('?') + PsiElement(COLONCOLON)('::') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + TYPE_REFERENCE + NULLABLE_TYPE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + PsiElement(QUEST)('?') + PsiElement(QUEST)('?') + PsiElement(COLONCOLON)('::') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + TYPE_REFERENCE + NULLABLE_TYPE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + PsiElement(QUEST)('?') + PsiElement(QUEST)('?') + PsiWhiteSpace(' ') + PsiElement(COLONCOLON)('::') + PsiWhiteSpace(' ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace('\n\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Unit') + PsiWhiteSpace('\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiElement(QUEST)('?') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Unit') + PsiWhiteSpace('\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiElement(QUEST)('?') + PsiElement(QUEST)('?') + PsiWhiteSpace(' ') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Unit') + PsiWhiteSpace('\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + PsiElement(QUEST)('?') + PsiWhiteSpace(' ') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Unit') + PsiWhiteSpace('\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + FUNCTION_TYPE_RECEIVER + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + PsiElement(QUEST)('?') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Unit') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java index a9abc6588af..0d212813153 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java @@ -1244,6 +1244,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/greatSyntacticShift/FunctionTypesAsArguments.kt"); doParsingTest(fileName); } + + @TestMetadata("nullableTypes.kt") + public void testNullableTypes() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/greatSyntacticShift/nullableTypes.kt"); + doParsingTest(fileName); + } } @TestMetadata("compiler/testData/psi/kdoc")