mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
UAST: Fix receiverType for JavaUCallExpression
Return correct receiver class for a method call with implicit receiver instead of super class, when method defined in one of super classes #IDEA-177417 Fixed
This commit is contained in:
committed by
Dmitry Jemerov
parent
605474caf4
commit
3bbbfc3b5b
@@ -16,7 +16,7 @@
|
||||
package org.jetbrains.uast.java
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTypesUtil
|
||||
import com.intellij.psi.util.*
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.psi.UElementWithLocation
|
||||
|
||||
@@ -52,9 +52,8 @@ class JavaUCallExpression(
|
||||
|
||||
override fun resolve() = psi.resolveMethod()
|
||||
|
||||
override fun getStartOffset(): Int {
|
||||
return psi.methodExpression.referenceNameElement?.textOffset ?: psi.methodExpression.textOffset
|
||||
}
|
||||
override fun getStartOffset(): Int =
|
||||
psi.methodExpression.referenceNameElement?.textOffset ?: psi.methodExpression.textOffset
|
||||
|
||||
override fun getEndOffset() = psi.textRange.endOffset
|
||||
|
||||
@@ -72,10 +71,27 @@ class JavaUCallExpression(
|
||||
if (qualifierType != null) {
|
||||
return qualifierType
|
||||
}
|
||||
|
||||
|
||||
val method = resolve() ?: return null
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) return null
|
||||
return method.containingClass?.let { PsiTypesUtil.getClassType(it) }
|
||||
|
||||
val psiManager = psi.manager
|
||||
val containingClassForMethod = method.containingClass ?: return null
|
||||
|
||||
val containingClass = PsiTreeUtil.getParentOfType(psi, PsiClass::class.java)
|
||||
val containingClassSequence = generateSequence(containingClass) {
|
||||
if (it.hasModifierProperty(PsiModifier.STATIC))
|
||||
null
|
||||
else
|
||||
PsiTreeUtil.getParentOfType(it, PsiClass::class.java)
|
||||
}
|
||||
|
||||
val receiverClass = containingClassSequence.find { containingClassForExpression ->
|
||||
psiManager.areElementsEquivalent(containingClassForMethod, containingClassForExpression) ||
|
||||
containingClassForExpression.isInheritor(containingClassForMethod, true)
|
||||
}
|
||||
|
||||
return receiverClass?.let { PsiTypesUtil.getClassType(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,25 +125,19 @@ class JavaConstructorUCallExpression(
|
||||
override val valueArgumentCount: Int
|
||||
get() {
|
||||
val initializer = psi.arrayInitializer
|
||||
return if (initializer != null) {
|
||||
initializer.initializers.size
|
||||
} else if (psi.arrayDimensions.isNotEmpty()) {
|
||||
psi.arrayDimensions.size
|
||||
} else {
|
||||
psi.argumentList?.expressions?.size ?: 0
|
||||
return when {
|
||||
initializer != null -> initializer.initializers.size
|
||||
psi.arrayDimensions.isNotEmpty() -> psi.arrayDimensions.size
|
||||
else -> psi.argumentList?.expressions?.size ?: 0
|
||||
}
|
||||
}
|
||||
|
||||
override val valueArguments by lz {
|
||||
val initializer = psi.arrayInitializer
|
||||
if (initializer != null) {
|
||||
initializer.initializers.map { JavaConverter.convertOrEmpty(it, this) }
|
||||
}
|
||||
else if (psi.arrayDimensions.isNotEmpty()) {
|
||||
psi.arrayDimensions.map { JavaConverter.convertOrEmpty(it, this) }
|
||||
}
|
||||
else {
|
||||
psi.argumentList?.expressions?.map { JavaConverter.convertOrEmpty(it, this) } ?: emptyList()
|
||||
when {
|
||||
initializer != null -> initializer.initializers.map { JavaConverter.convertOrEmpty(it, this) }
|
||||
psi.arrayDimensions.isNotEmpty() -> psi.arrayDimensions.map { JavaConverter.convertOrEmpty(it, this) }
|
||||
else -> psi.argumentList?.expressions?.map { JavaConverter.convertOrEmpty(it, this) } ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
93
uast/uast-tests/java/Simple/ReceiverType.java
Normal file
93
uast/uast-tests/java/Simple/ReceiverType.java
Normal file
@@ -0,0 +1,93 @@
|
||||
class TestBaseBase {
|
||||
void bazBaseBase(int i) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class TestBase extends TestBaseBase {
|
||||
void fooBase(int i) {
|
||||
|
||||
}
|
||||
|
||||
void barBase(int i) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends TestBase {
|
||||
Test() {
|
||||
foo(1);
|
||||
fooBase(1);
|
||||
this.barBase(1);
|
||||
staticMethod(1);
|
||||
bazBaseBase(1);
|
||||
}
|
||||
|
||||
void foo(int i) {
|
||||
|
||||
}
|
||||
|
||||
static void staticMethod(int i) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
class InnerTest {
|
||||
InnerTest() {
|
||||
foo(2);
|
||||
fooBase(2);
|
||||
bar(2);
|
||||
staticMethod(2);
|
||||
|
||||
TestBase t = new TestBase() {
|
||||
void fooBase(int i) {
|
||||
bazBaseBase(7);
|
||||
bar(7);
|
||||
barBase(7);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void bar(int i) {
|
||||
|
||||
}
|
||||
|
||||
class InnerInnerTest {
|
||||
InnerInnerTest() {
|
||||
foo(3);
|
||||
fooBase(3);
|
||||
bar(3);
|
||||
baz(3);
|
||||
staticMethod(3);
|
||||
}
|
||||
|
||||
void baz(int i) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InnerTest2 extends TestBase {
|
||||
InnerTest2() {
|
||||
foo(4);
|
||||
fooBase(4);
|
||||
}
|
||||
}
|
||||
|
||||
static class StaticTest {
|
||||
StaticTest() {
|
||||
bar(5);
|
||||
staticMethod(5);
|
||||
}
|
||||
|
||||
void bar(int i) {
|
||||
|
||||
}
|
||||
|
||||
class InnerInStatic {
|
||||
InnerInStatic() {
|
||||
bar(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,4 +61,37 @@ class JavaUastApiTest : AbstractJavaUastTest() {
|
||||
"java.lang.Runnable")
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun testReceiverType() {
|
||||
doTest("Simple/ReceiverType.java") { name, file ->
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("foo(1)").receiverType?.canonicalText)
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("fooBase(1)").receiverType?.canonicalText)
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("this.barBase(1)").receiverType?.canonicalText)
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("bazBaseBase(1)").receiverType?.canonicalText)
|
||||
assertNull(file.findElementByText<UCallExpression>("staticMethod(1)").receiverType)
|
||||
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("foo(2)").receiverType?.canonicalText)
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("fooBase(2)").receiverType?.canonicalText)
|
||||
assertEquals("Test.InnerTest", file.findElementByText<UCallExpression>("bar(2)").receiverType?.canonicalText)
|
||||
assertNull(file.findElementByText<UCallExpression>("staticMethod(2)").receiverType)
|
||||
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("foo(3)").receiverType?.canonicalText)
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("fooBase(3)").receiverType?.canonicalText)
|
||||
assertEquals("Test.InnerTest", file.findElementByText<UCallExpression>("bar(3)").receiverType?.canonicalText)
|
||||
assertEquals("Test.InnerTest.InnerInnerTest", file.findElementByText<UCallExpression>("baz(3)").receiverType?.canonicalText)
|
||||
assertNull(file.findElementByText<UCallExpression>("staticMethod(3)").receiverType)
|
||||
|
||||
assertEquals("Test", file.findElementByText<UCallExpression>("foo(4)").receiverType?.canonicalText)
|
||||
assertEquals("Test.InnerTest2", file.findElementByText<UCallExpression>("fooBase(4)").receiverType?.canonicalText)
|
||||
|
||||
assertEquals("Test.StaticTest", file.findElementByText<UCallExpression>("bar(5)").receiverType?.canonicalText)
|
||||
assertNull(file.findElementByText<UCallExpression>("staticMethod(5)").receiverType)
|
||||
|
||||
assertEquals("Test.StaticTest", file.findElementByText<UCallExpression>("bar(6)").receiverType?.canonicalText)
|
||||
|
||||
assertEquals("TestBase", file.findElementByText<UCallExpression>("bazBaseBase(7)").receiverType?.canonicalText)
|
||||
assertEquals("Test.InnerTest", file.findElementByText<UCallExpression>("bar(7)").receiverType?.canonicalText)
|
||||
assertEquals("TestBase", file.findElementByText<UCallExpression>("barBase(7)").receiverType?.canonicalText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user