From 731956db71a5c8851f5a8b4d8f8ac03da34bce3e Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Tue, 29 Jan 2019 12:35:32 +0300 Subject: [PATCH] 191: Uast: `UInjectionHost` moved under flag `kotlin.uast.force.uinjectionhost` (KT-27283) --- idea/resources/META-INF/jvm.xml.191 | 198 ++++++++++++++++++ .../uast/kotlin/KotlinAbstractUElement.kt.191 | 13 +- .../kotlin/KotlinUastLanguagePlugin.kt.191 | 23 +- ...ingTemplateComplexForUInjectionHost.kt.191 | 17 ++ ...mplateComplexForUInjectionHost.log.txt.191 | 80 +++++++ ...ateComplexForUInjectionHost.render.txt.191 | 20 ++ .../tests/SimpleKotlinRenderLogTest.kt.191 | 103 +++++++++ 7 files changed, 449 insertions(+), 5 deletions(-) create mode 100644 idea/resources/META-INF/jvm.xml.191 create mode 100644 plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191 create mode 100644 plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191 create mode 100644 plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191 create mode 100644 plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191 diff --git a/idea/resources/META-INF/jvm.xml.191 b/idea/resources/META-INF/jvm.xml.191 new file mode 100644 index 00000000000..6bbe371b8ec --- /dev/null +++ b/idea/resources/META-INF/jvm.xml.191 @@ -0,0 +1,198 @@ + + + + + + + + org.jetbrains.kotlin.idea.JvmPluginStartupComponent + + + + + + org.jetbrains.kotlin.idea.compiler.KotlinCompilerManager + + + org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent + + + org.jetbrains.kotlin.idea.scratch.ui.ScratchFileHook + + + org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191 index 2c62d83f432..7af3e07f69b 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191 @@ -79,9 +79,14 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl parent = parent.parent } - if (parent is KtBlockStringTemplateEntry) { - parent = parent.parent - } + if (KotlinConverter.forceUInjectionHost) { + if (parent is KtBlockStringTemplateEntry) { + parent = parent.parent + } + } else + while (parent is KtStringTemplateEntryWithExpression || parent is KtStringTemplateExpression && parent.entries.size == 1) { + parent = parent.parent + } if (parent is KtWhenConditionWithExpression) { parent = parent.parent @@ -109,7 +114,7 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl val result = doConvertParent(this, parent) if (result == this) { - throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}]") + throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}], result = $result") } return result diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191 index 07ea7a0808c..d1c2a09b61c 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191 @@ -19,9 +19,11 @@ package org.jetbrains.uast.kotlin import com.intellij.lang.Language import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.util.Key +import com.intellij.openapi.util.registry.Registry import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.impl.source.tree.LeafPsiElement +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade @@ -394,6 +396,12 @@ internal object KotlinConverter { } } + var forceUInjectionHost = Registry.`is`("kotlin.uast.force.uinjectionhost", false) + @TestOnly + set(value) { + field = value + } + internal fun convertExpression(expression: KtExpression, givenParent: UElement?, requiredType: Class? = null): UExpression? { @@ -404,7 +412,20 @@ internal object KotlinConverter { return with (requiredType) { when (expression) { is KtVariableDeclaration -> expr(build(::convertVariablesDeclaration)) - is KtStringTemplateExpression -> expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) } + is KtStringTemplateExpression -> { + when { + forceUInjectionHost || (requiredType != null && UInjectionHost::class.java.isAssignableFrom(requiredType)) -> + expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) } + expression.entries.isEmpty() -> { + expr { KotlinStringULiteralExpression(expression, givenParent, "") } + } + + expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType) + + else -> + expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) } + } + } is KtDestructuringDeclaration -> expr { val declarationsExpression = KotlinUDestructuringDeclarationExpression(givenParent, expression) declarationsExpression.apply { diff --git a/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191 b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191 new file mode 100644 index 00000000000..5f4748f3f3a --- /dev/null +++ b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191 @@ -0,0 +1,17 @@ +val muchRecur = "${"${"${"abc"}"}"}" + +val case4 = "a ${"literal"} z" + +val case5 = "a ${"literal"} ${"literal"} z" + +val literalInLiteral = "a ${"literal$case4"} z" + +val literalInLiteral2 = "a ${"literal$case4".repeat(4)} z" + +fun simpleForTemplate(i: Int = 0) = "$i" + +fun foo() { + println("$baz") + val template1 = "${simpleForTemplate()}" + val template2 = ".${simpleForTemplate()}" +} diff --git a/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191 b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191 new file mode 100644 index 00000000000..9458b707d90 --- /dev/null +++ b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191 @@ -0,0 +1,80 @@ +UFile (package = ) + UClass (name = StringTemplateComplexForUInjectionHostKt) + UField (name = muchRecur) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UPolyadicExpression (operator = +) + UPolyadicExpression (operator = +) + UPolyadicExpression (operator = +) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "abc") + UField (name = case4) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "a ") + UPolyadicExpression (operator = +) + ULiteralExpression (value = "literal") + ULiteralExpression (value = " z") + UField (name = case5) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "a ") + UPolyadicExpression (operator = +) + ULiteralExpression (value = "literal") + ULiteralExpression (value = " ") + UPolyadicExpression (operator = +) + ULiteralExpression (value = "literal") + ULiteralExpression (value = " z") + UField (name = literalInLiteral) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "a ") + UPolyadicExpression (operator = +) + ULiteralExpression (value = "literal") + USimpleNameReferenceExpression (identifier = case4) + ULiteralExpression (value = " z") + UField (name = literalInLiteral2) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UPolyadicExpression (operator = +) + ULiteralExpression (value = "a ") + UQualifiedReferenceExpression + UPolyadicExpression (operator = +) + ULiteralExpression (value = "literal") + USimpleNameReferenceExpression (identifier = case4) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (repeat)) + USimpleNameReferenceExpression (identifier = repeat) + ULiteralExpression (value = 4) + ULiteralExpression (value = " z") + UAnnotationMethod (name = getMuchRecur) + UAnnotationMethod (name = getCase4) + UAnnotationMethod (name = getCase5) + UAnnotationMethod (name = getLiteralInLiteral) + UAnnotationMethod (name = getLiteralInLiteral2) + UAnnotationMethod (name = simpleForTemplate) + UParameter (name = i) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + ULiteralExpression (value = 0) + UBlockExpression + UReturnExpression + UPolyadicExpression (operator = +) + USimpleNameReferenceExpression (identifier = i) + UAnnotationMethod (name = foo) + UBlockExpression + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (println)) + USimpleNameReferenceExpression (identifier = println) + UPolyadicExpression (operator = +) + USimpleNameReferenceExpression (identifier = baz) + UDeclarationsExpression + ULocalVariable (name = template1) + UPolyadicExpression (operator = +) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (simpleForTemplate)) + USimpleNameReferenceExpression (identifier = simpleForTemplate) + UDeclarationsExpression + ULocalVariable (name = template2) + UPolyadicExpression (operator = +) + ULiteralExpression (value = ".") + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (simpleForTemplate)) + USimpleNameReferenceExpression (identifier = simpleForTemplate) diff --git a/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191 b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191 new file mode 100644 index 00000000000..c6ab7798351 --- /dev/null +++ b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191 @@ -0,0 +1,20 @@ +public final class StringTemplateComplexForUInjectionHostKt { + @org.jetbrains.annotations.NotNull private static final var muchRecur: java.lang.String = "abc" + @org.jetbrains.annotations.NotNull private static final var case4: java.lang.String = "a " + "literal" + " z" + @org.jetbrains.annotations.NotNull private static final var case5: java.lang.String = "a " + "literal" + " " + "literal" + " z" + @org.jetbrains.annotations.NotNull private static final var literalInLiteral: java.lang.String = "a " + "literal" + case4 + " z" + @org.jetbrains.annotations.NotNull private static final var literalInLiteral2: java.lang.String = "a " + "literal" + case4.repeat(4) + " z" + public static final fun getMuchRecur() : java.lang.String = UastEmptyExpression + public static final fun getCase4() : java.lang.String = UastEmptyExpression + public static final fun getCase5() : java.lang.String = UastEmptyExpression + public static final fun getLiteralInLiteral() : java.lang.String = UastEmptyExpression + public static final fun getLiteralInLiteral2() : java.lang.String = UastEmptyExpression + public static final fun simpleForTemplate(@org.jetbrains.annotations.NotNull i: int) : java.lang.String { + return i + } + public static final fun foo() : void { + println(baz) + var template1: java.lang.String = simpleForTemplate() + var template2: java.lang.String = "." + simpleForTemplate() + } +} diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191 b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191 new file mode 100644 index 00000000000..d33aa51ac19 --- /dev/null +++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191 @@ -0,0 +1,103 @@ +package org.jetbrains.uast.test.kotlin + +import org.jetbrains.uast.kotlin.KotlinConverter +import org.junit.Test + +class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() { + @Test fun testLocalDeclarations() = doTest("LocalDeclarations") + + @Test fun testSimple() = doTest("Simple") + + @Test fun testWhenIs() = doTest("WhenIs") + + @Test fun testDefaultImpls() = doTest("DefaultImpls") + + @Test fun testElvis() = doTest("Elvis") + + @Test fun testPropertyAccessors() = doTest("PropertyAccessors") + + @Test fun testPropertyInitializer() = doTest("PropertyInitializer") + + @Test fun testPropertyInitializerWithoutSetter() = doTest("PropertyInitializerWithoutSetter") + + @Test fun testAnnotationParameters() = doTest("AnnotationParameters") + + @Test fun testEnumValueMembers() = doTest("EnumValueMembers") + + @Test fun testStringTemplate() = doTest("StringTemplate") + + @Test fun testStringTemplateComplex() = doTest("StringTemplateComplex") + + @Test + fun testStringTemplateComplexForUInjectionHost() = withForceUInjectionHostValue { + doTest("StringTemplateComplexForUInjectionHost") + } + + @Test fun testQualifiedConstructorCall() = doTest("QualifiedConstructorCall") + + @Test fun testPropertyDelegate() = doTest("PropertyDelegate") + + @Test fun testLocalVariableWithAnnotation() = doTest("LocalVariableWithAnnotation") + + @Test fun testPropertyWithAnnotation() = doTest("PropertyWithAnnotation") + + @Test fun testIfStatement() = doTest("IfStatement") + + @Test fun testInnerClasses() = doTest("InnerClasses") + + @Test fun testSimpleScript() = doTest("SimpleScript") { testName, file -> check(testName, file, false) } + + @Test fun testDestructuringDeclaration() = doTest("DestructuringDeclaration") + + @Test fun testDefaultParameterValues() = doTest("DefaultParameterValues") + + @Test fun testParameterPropertyWithAnnotation() = doTest("ParameterPropertyWithAnnotation") + + @Test fun testParametersWithDefaultValues() = doTest("ParametersWithDefaultValues") + + @Test + fun testUnexpectedContainer() = doTest("UnexpectedContainerException") + + @Test + fun testWhenStringLiteral() = doTest("WhenStringLiteral") + + @Test + fun testWhenAndDestructing() = doTest("WhenAndDestructing") { testName, file -> check(testName, file, false) } + + @Test + fun testSuperCalls() = doTest("SuperCalls") + + @Test + fun testConstructors() = doTest("Constructors") + + @Test + fun testClassAnnotation() = doTest("ClassAnnotation") + + @Test + fun testReceiverFun() = doTest("ReceiverFun") + + @Test + fun testAnonymous() = doTest("Anonymous") + + @Test + fun testAnnotationComplex() = doTest("AnnotationComplex") + + @Test + fun testParametersDisorder() = doTest("ParametersDisorder") { testName, file -> + // disabled due to inconsistent parents for 2-receivers call (KT-22344) + check(testName, file, false) + } + + @Test + fun testLambdas() = doTest("Lambdas") +} + +fun withForceUInjectionHostValue(call: () -> Unit) { + val prev = KotlinConverter.forceUInjectionHost + KotlinConverter.forceUInjectionHost = true + try { + call.invoke() + } finally { + KotlinConverter.forceUInjectionHost = prev + } +} \ No newline at end of file