UAST: JavaConstructorUCallExpression multiResolve() must resolve to PsiMethod in case there is explicit constructor

GitOrigin-RevId: 3ebd0a55953d0482638287aa8b90cdb386f67e9b
This commit is contained in:
Yuriy Artamonov
2019-12-16 20:36:06 +00:00
committed by intellij-monorepo-bot
parent 6c8a87e245
commit 46b8dbe4c2
7 changed files with 102 additions and 2 deletions
@@ -180,8 +180,16 @@ class JavaConstructorUCallExpression(
get() = null
override fun resolve(): PsiMethod? = sourcePsi.resolveMethod()
override fun multiResolve(): Iterable<ResolveResult> =
sourcePsi.classReference?.multiResolve(false)?.asIterable() ?: emptyList()
override fun multiResolve(): Iterable<ResolveResult> {
val methodResolve = sourcePsi.resolveMethodGenerics()
if (methodResolve != JavaResolveResult.EMPTY) {
// if there is a non-default constructor
return arrayOf<ResolveResult>(methodResolve).asIterable()
}
// no default constructor - resolve to class
val classResolve = sourcePsi.classReference?.multiResolve(false) ?: emptyArray()
return classResolve.asIterable()
}
}
class JavaArrayInitializerUCallExpression(
@@ -0,0 +1,11 @@
public class Foo {
private int number;
public Foo(int number) {
this.number = number;
}
public static void test() {
new Foo(10);
}
}
@@ -0,0 +1,14 @@
UField (name = number) -> UTypeReferenceExpression (name = int) -> null
UParameter (name = number) -> UTypeReferenceExpression (name = int) -> null
UMethod (name = Foo) -> UBlockExpression -> null
UBlockExpression -> UBinaryExpression (operator = =) -> null
UBlockExpression -> UBinaryExpression (operator = =) -> null
UBinaryExpression (operator = =) -> UQualifiedReferenceExpression -> [M] PsiFieldImpl
UQualifiedReferenceExpression -> UThisExpression (label = null) -> [M]
UBinaryExpression (operator = =) -> USimpleNameReferenceExpression (identifier = number) -> [M] PsiParameterImpl
UMethod (name = test) -> UTypeReferenceExpression (name = void) -> null
UMethod (name = test) -> UBlockExpression -> null
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) -> [M] PsiMethodImpl
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) -> [M] PsiMethodImpl
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) -> USimpleNameReferenceExpression (identifier = Foo) -> [M] PsiClassImpl
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) -> ULiteralExpression (value = 10) -> null
@@ -0,0 +1,5 @@
public class Foo {
public static void test() {
new Foo();
}
}
@@ -0,0 +1,5 @@
UMethod (name = test) -> UTypeReferenceExpression (name = void) -> null
UMethod (name = test) -> UBlockExpression -> null
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> [M] PsiClassImpl
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> [M] PsiClassImpl
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> USimpleNameReferenceExpression (identifier = Foo) -> [M] PsiClassImpl
@@ -0,0 +1,45 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.uast.test.java
import com.intellij.psi.PsiCodeBlock
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiIdentifier
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.uast.*
import org.jetbrains.uast.test.common.visitUFileAndGetResult
import org.jetbrains.uast.test.env.assertEqualsToFile
import org.jetbrains.uast.util.IndentedPrintingVisitor
import java.io.File
abstract class AbstractJavaExpressionMultiResolveTest : AbstractJavaUastTest() {
private fun UFile.resolvableWithTargets() = object : IndentedPrintingVisitor(PsiCodeBlock::class, PsiModifierListOwner::class) {
override fun render(element: PsiElement): CharSequence? =
element
.takeIf { it !is PsiIdentifier } // no sense to handle PsiIdentifier, see IDEA-207979
?.toUElementOfType<UExpression>()?.let { ref ->
StringBuilder().apply {
val parent = ref.uastParent
append(parent?.asLogString())
append(" -> ")
append(ref.asLogString())
append(" -> ")
append(multiResolve(ref))
}
}
}.visitUFileAndGetResult(this)
private fun multiResolve(ref: UExpression): String {
if (ref is UMultiResolvable) {
return "[M] " + ref.multiResolve().joinToString(",") { it.element?.javaClass?.simpleName ?: "null" }
}
if (ref is UResolvable) {
return "[S] " + (ref.resolve()?.toString() ?: "null")
}
return "null"
}
override fun check(testName: String, file: UFile) {
val expected = File(testDataPath, testName.substringBeforeLast('.') + ".resolved.txt")
assertEqualsToFile("resolved", expected, file.resolvableWithTargets())
}
}
@@ -0,0 +1,12 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.uast.test.java
import org.junit.Test
class JavaExpressionMultiResolveTest : AbstractJavaExpressionMultiResolveTest() {
@Test
fun testConstructorCallWithParameters() = doTest("Simple/ConstructorCallWithParameters.java") // must resolve to PsiMethodImpl
@Test
fun testDefaultConstructorCall() = doTest("Simple/DefaultConstructorCall.java") // must resolve to PsiClassImpl
}