Uast: returning back secondary constructors bodies (KT-21575)
but secondary constructors without primary constructor will not contain initializers, it is still an issue
This commit is contained in:
committed by
xiexed
parent
962c512882
commit
b8069b48c5
@@ -128,27 +128,37 @@ class KotlinConstructorUMethod(
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val initializers = ktClass?.getAnonymousInitializers().orEmpty()
|
val bodyExpressions = getBodyExpressions()
|
||||||
if (delegationCall == null && initializers.isEmpty()) return@lz null
|
if (delegationCall == null && bodyExpressions.isEmpty()) return@lz null
|
||||||
KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent ->
|
KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent ->
|
||||||
SmartList<UExpression>().apply {
|
SmartList<UExpression>().apply {
|
||||||
delegationCall?.let {
|
delegationCall?.let {
|
||||||
add(KotlinUFunctionCallExpression(it, uastParent))
|
add(KotlinUFunctionCallExpression(it, uastParent))
|
||||||
}
|
}
|
||||||
val languagePlugin = uastParent.getLanguagePlugin()
|
val languagePlugin = uastParent.getLanguagePlugin()
|
||||||
initializers.forEach {
|
bodyExpressions.forEach {
|
||||||
addIfNotNull(languagePlugin.convertOpt(it.body, uastParent))
|
addIfNotNull(languagePlugin.convertOpt(it, uastParent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getBodyExpressions(): List<KtExpression> {
|
||||||
|
if (isPrimary) return getInitializers()
|
||||||
|
val bodyExpression = (psi.kotlinOrigin as? KtFunction)?.bodyExpression ?: return emptyList()
|
||||||
|
if (bodyExpression is KtBlockExpression) return bodyExpression.statements
|
||||||
|
return listOf(bodyExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInitializers() = ktClass?.getAnonymousInitializers()?.mapNotNull { it.body } ?: emptyList()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinUAnonymousClass(
|
class KotlinUAnonymousClass(
|
||||||
psi: PsiAnonymousClass,
|
psi: PsiAnonymousClass,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : AbstractKotlinUClass(givenParent), UAnonymousClass, PsiAnonymousClass by psi {
|
) : AbstractKotlinUClass(givenParent), UAnonymousClass, PsiAnonymousClass by psi {
|
||||||
|
|
||||||
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
|
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
|
||||||
|
|
||||||
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUClass>.getOriginalElement()
|
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUClass>.getOriginalElement()
|
||||||
@@ -163,7 +173,7 @@ class KotlinUAnonymousClass(
|
|||||||
|
|
||||||
override val uastAnchor: UElement?
|
override val uastAnchor: UElement?
|
||||||
get() {
|
get() {
|
||||||
val ktClassOrObject = (psi.originalElement as? KtLightClass)?.kotlinOrigin as? KtObjectDeclaration ?: return null
|
val ktClassOrObject = (psi.originalElement as? KtLightClass)?.kotlinOrigin as? KtObjectDeclaration ?: return null
|
||||||
return UIdentifier(ktClassOrObject.getObjectKeyword(), this)
|
return UIdentifier(ktClassOrObject.getObjectKeyword(), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
class A(val str: String) {
|
||||||
|
|
||||||
|
constructor(i: Int) : this(i.toString())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class AWithInit(val str: String) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(i: Int) : this(i.toString())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class AWith2Init(val str: String) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(i: Int) : this(i.toString())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class AOnlyInit {
|
||||||
|
|
||||||
|
init {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AWithSecondary {
|
||||||
|
|
||||||
|
lateinit var a: String
|
||||||
|
|
||||||
|
constructor(i: Int) {
|
||||||
|
a = i.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(s: String) {
|
||||||
|
a = s
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class AWithSecondaryInit {
|
||||||
|
|
||||||
|
lateinit var a: String
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This body will not be picked by UAST because no lightMethod contains it.
|
||||||
|
// Of course it is not a desired behaviour, so fix it if you know how
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(i: Int) {
|
||||||
|
a = i.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(s: String) {
|
||||||
|
a = s
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
UFile (package = )
|
||||||
|
UClass (name = A)
|
||||||
|
UField (name = str)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = getStr)
|
||||||
|
UAnnotationMethod (name = A)
|
||||||
|
UParameter (name = str)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = A)
|
||||||
|
UParameter (name = i)
|
||||||
|
UAnnotation (fqName = null)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (this))
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UQualifiedReferenceExpression
|
||||||
|
USimpleNameReferenceExpression (identifier = i)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (toString))
|
||||||
|
USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
UClass (name = AWithInit)
|
||||||
|
UField (name = str)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = getStr)
|
||||||
|
UAnnotationMethod (name = AWithInit)
|
||||||
|
UParameter (name = str)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UBlockExpression
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
|
UAnnotationMethod (name = AWithInit)
|
||||||
|
UParameter (name = i)
|
||||||
|
UAnnotation (fqName = null)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (this))
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UQualifiedReferenceExpression
|
||||||
|
USimpleNameReferenceExpression (identifier = i)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (toString))
|
||||||
|
USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
UClass (name = AWith2Init)
|
||||||
|
UField (name = str)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = getStr)
|
||||||
|
UAnnotationMethod (name = AWith2Init)
|
||||||
|
UParameter (name = str)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UBlockExpression
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
|
ULiteralExpression (value = 1)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
|
ULiteralExpression (value = 2)
|
||||||
|
UAnnotationMethod (name = AWith2Init)
|
||||||
|
UParameter (name = i)
|
||||||
|
UAnnotation (fqName = null)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (this))
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UQualifiedReferenceExpression
|
||||||
|
USimpleNameReferenceExpression (identifier = i)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (toString))
|
||||||
|
USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
UClass (name = AOnlyInit)
|
||||||
|
UAnnotationMethod (name = AOnlyInit)
|
||||||
|
UBlockExpression
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
|
ULiteralExpression (value = 1)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
|
ULiteralExpression (value = 2)
|
||||||
|
UClass (name = AWithSecondary)
|
||||||
|
UField (name = a)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = getA)
|
||||||
|
UAnnotationMethod (name = setA)
|
||||||
|
UParameter (name = p)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = AWithSecondary)
|
||||||
|
UParameter (name = i)
|
||||||
|
UAnnotation (fqName = null)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier ())
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UBinaryExpression (operator = =)
|
||||||
|
USimpleNameReferenceExpression (identifier = a)
|
||||||
|
UQualifiedReferenceExpression
|
||||||
|
USimpleNameReferenceExpression (identifier = i)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (toString))
|
||||||
|
USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
UAnnotationMethod (name = AWithSecondary)
|
||||||
|
UParameter (name = s)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier ())
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UBinaryExpression (operator = =)
|
||||||
|
USimpleNameReferenceExpression (identifier = a)
|
||||||
|
USimpleNameReferenceExpression (identifier = s)
|
||||||
|
UClass (name = AWithSecondaryInit)
|
||||||
|
UField (name = a)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = getA)
|
||||||
|
UAnnotationMethod (name = setA)
|
||||||
|
UParameter (name = p)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UAnnotationMethod (name = AWithSecondaryInit)
|
||||||
|
UParameter (name = i)
|
||||||
|
UAnnotation (fqName = null)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier ())
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UBinaryExpression (operator = =)
|
||||||
|
USimpleNameReferenceExpression (identifier = a)
|
||||||
|
UQualifiedReferenceExpression
|
||||||
|
USimpleNameReferenceExpression (identifier = i)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (toString))
|
||||||
|
USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
UAnnotationMethod (name = AWithSecondaryInit)
|
||||||
|
UParameter (name = s)
|
||||||
|
UAnnotation (fqName = org.jetbrains.annotations.NotNull)
|
||||||
|
UBlockExpression
|
||||||
|
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier ())
|
||||||
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
|
UBinaryExpression (operator = =)
|
||||||
|
USimpleNameReferenceExpression (identifier = a)
|
||||||
|
USimpleNameReferenceExpression (identifier = s)
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
public final class A {
|
||||||
|
private final var str: java.lang.String
|
||||||
|
public final fun getStr() : java.lang.String = UastEmptyExpression
|
||||||
|
public fun A(str: java.lang.String) = UastEmptyExpression
|
||||||
|
public fun A(i: int) {
|
||||||
|
<init>(i.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class AWithInit {
|
||||||
|
private final var str: java.lang.String
|
||||||
|
public final fun getStr() : java.lang.String = UastEmptyExpression
|
||||||
|
public fun AWithInit(str: java.lang.String) {
|
||||||
|
{
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public fun AWithInit(i: int) {
|
||||||
|
<init>(i.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class AWith2Init {
|
||||||
|
private final var str: java.lang.String
|
||||||
|
public final fun getStr() : java.lang.String = UastEmptyExpression
|
||||||
|
public fun AWith2Init(str: java.lang.String) {
|
||||||
|
{
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public fun AWith2Init(i: int) {
|
||||||
|
<init>(i.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class AOnlyInit {
|
||||||
|
public fun AOnlyInit() {
|
||||||
|
{
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class AWithSecondary {
|
||||||
|
public var a: java.lang.String
|
||||||
|
public final fun getA() : java.lang.String = UastEmptyExpression
|
||||||
|
public final fun setA(p: java.lang.String) : void = UastEmptyExpression
|
||||||
|
public fun AWithSecondary(i: int) {
|
||||||
|
<init>()
|
||||||
|
a = i.toString()
|
||||||
|
}
|
||||||
|
public fun AWithSecondary(s: java.lang.String) {
|
||||||
|
<init>()
|
||||||
|
a = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class AWithSecondaryInit {
|
||||||
|
public var a: java.lang.String
|
||||||
|
public final fun getA() : java.lang.String = UastEmptyExpression
|
||||||
|
public final fun setA(p: java.lang.String) : void = UastEmptyExpression
|
||||||
|
public fun AWithSecondaryInit(i: int) {
|
||||||
|
<init>()
|
||||||
|
a = i.toString()
|
||||||
|
}
|
||||||
|
public fun AWithSecondaryInit(s: java.lang.String) {
|
||||||
|
<init>()
|
||||||
|
a = s
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -11,7 +11,9 @@ class B(param: String) : A(param)
|
|||||||
class C : A {
|
class C : A {
|
||||||
constructor(p: String) : super(p)
|
constructor(p: String) : super(p)
|
||||||
|
|
||||||
constructor(i: Int) : super(i)
|
constructor(i: Int) : super(i) {
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
override fun foo(a: Long) {
|
override fun foo(a: Long) {
|
||||||
super.foo(a)
|
super.foo(a)
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ UFile (package = )
|
|||||||
UIdentifier (Identifier (super))
|
UIdentifier (Identifier (super))
|
||||||
USimpleNameReferenceExpression (identifier = <init>)
|
USimpleNameReferenceExpression (identifier = <init>)
|
||||||
USimpleNameReferenceExpression (identifier = i)
|
USimpleNameReferenceExpression (identifier = i)
|
||||||
|
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
|
||||||
|
UIdentifier (Identifier (println))
|
||||||
|
USimpleNameReferenceExpression (identifier = println)
|
||||||
UClass (name = O)
|
UClass (name = O)
|
||||||
UField (name = INSTANCE)
|
UField (name = INSTANCE)
|
||||||
UAnnotation (fqName = null)
|
UAnnotation (fqName = null)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public final class C : A {
|
|||||||
}
|
}
|
||||||
public fun C(i: int) {
|
public fun C(i: int) {
|
||||||
<init>(i)
|
<init>(i)
|
||||||
|
println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
|||||||
if (expectedParents != null) {
|
if (expectedParents != null) {
|
||||||
assertNotNull("Expected to be able to convert PSI element $element", uElement)
|
assertNotNull("Expected to be able to convert PSI element $element", uElement)
|
||||||
val parents = generateSequence(uElement!!.uastParent) { it.uastParent }.joinToString { it.asLogString() }
|
val parents = generateSequence(uElement!!.uastParent) { it.uastParent }.joinToString { it.asLogString() }
|
||||||
assertEquals("Inconsistent parents for ${uElement.asLogString()} (converted from $element)", expectedParents, parents)
|
assertEquals("Inconsistent parents for ${uElement.asRenderString()}(${uElement.asLogString()})(${uElement.javaClass}) (converted from $element[${element.text}])", expectedParents, parents)
|
||||||
}
|
}
|
||||||
super.visitElement(element)
|
super.visitElement(element)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,4 +56,7 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSuperCalls() = doTest("SuperCalls")
|
fun testSuperCalls() = doTest("SuperCalls")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testConstructors() = doTest("Constructors")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user