191: Uast: UInjectionHost moved under flag kotlin.uast.force.uinjectionhost (KT-27283)

This commit is contained in:
Nicolay Mitropolsky
2019-01-29 12:35:32 +03:00
parent 9ecd69760b
commit 731956db71
7 changed files with 449 additions and 5 deletions
@@ -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
@@ -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<out UElement>? = null): UExpression? {
@@ -404,7 +412,20 @@ internal object KotlinConverter {
return with (requiredType) { when (expression) {
is KtVariableDeclaration -> expr<UDeclarationsExpression>(build(::convertVariablesDeclaration))
is KtStringTemplateExpression -> expr<UInjectionHost> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
is KtStringTemplateExpression -> {
when {
forceUInjectionHost || (requiredType != null && UInjectionHost::class.java.isAssignableFrom(requiredType)) ->
expr<UInjectionHost> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
expression.entries.isEmpty() -> {
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, givenParent, "") }
}
expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType)
else ->
expr<KotlinStringTemplateUPolyadicExpression> { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
}
}
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
val declarationsExpression = KotlinUDestructuringDeclarationExpression(givenParent, expression)
declarationsExpression.apply {
@@ -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()}"
}
@@ -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)
@@ -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()
}
}
@@ -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
}
}