mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-CR-41634: [uast] convertToAlternatives for java PsiMethodCallExpression
(cherry picked from commit f6480f5ad7ae402974c6a5a35a558ccddc5302ae)
This commit is contained in:
committed by
Nicolay Mitropolsky
parent
aedeb95e4e
commit
26a2e7e4dd
@@ -114,6 +114,11 @@ interface UastLanguagePlugin {
|
||||
?.takeIf { result -> requiredTypes.any { it.isAssignableFrom(result.javaClass) } }
|
||||
} as? T
|
||||
|
||||
|
||||
@JvmDefault
|
||||
fun <T : UElement> convertToAlternatives(element: PsiElement, requiredTypes: List<Class<out T>>): Sequence<T> =
|
||||
sequenceOf(convertElementWithParent(element, requiredTypes)).filterNotNull()
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified T : UElement> UastLanguagePlugin.convertOpt(element: PsiElement?, parent: UElement?): T? {
|
||||
|
||||
@@ -100,7 +100,7 @@ class JavaUastLanguagePlugin : UastLanguagePlugin {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : UElement> convertElement(element: PsiElement, parent: UElement?, requiredTypes: List<Class<out T>>): T? {
|
||||
val nonEmptyRequiredTypes = requiredTypes.takeIf { it.isNotEmpty() } ?: DEFAULT_TYPES_LIST
|
||||
val nonEmptyRequiredTypes = requiredTypes.nonEmptyOr(DEFAULT_TYPES_LIST)
|
||||
if (checkCanConvert && !canConvert(element.javaClass, nonEmptyRequiredTypes)) return null
|
||||
|
||||
return (convertDeclaration(element, parent, nonEmptyRequiredTypes)
|
||||
@@ -111,6 +111,14 @@ class JavaUastLanguagePlugin : UastLanguagePlugin {
|
||||
return convertElement(element, null, requiredTypes)
|
||||
}
|
||||
|
||||
override fun <T : UElement> convertToAlternatives(element: PsiElement, requiredTypes: List<Class<out T>>) = when (element) {
|
||||
is `PsiMethodCallExpression` ->
|
||||
JavaConverter.psiMethodCallConversionAlternatives(element,
|
||||
null,
|
||||
requiredTypes.nonEmptyOr(DEFAULT_EXPRESSION_TYPES_LIST)) as Sequence<T>
|
||||
else -> sequenceOf(convertElementWithParent(element, requiredTypes.nonEmptyOr(DEFAULT_TYPES_LIST)) as? T).filterNotNull()
|
||||
}
|
||||
|
||||
private fun convertDeclaration(element: PsiElement,
|
||||
givenParent: UElement?,
|
||||
requiredType: List<Class<out UElement>>): UElement? {
|
||||
@@ -143,7 +151,7 @@ class JavaUastLanguagePlugin : UastLanguagePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <reified ActualT : UElement> Class<out UElement>?.el(f: () -> UElement?): UElement? {
|
||||
internal inline fun <reified ActualT : UElement> Class<*>?.el(f: () -> UElement?): UElement? {
|
||||
return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null
|
||||
}
|
||||
|
||||
@@ -237,25 +245,7 @@ internal object JavaConverter {
|
||||
else
|
||||
expr<UCallExpression>(build(::JavaConstructorUCallExpression))
|
||||
}
|
||||
is PsiMethodCallExpression -> {
|
||||
if (el.methodExpression.qualifierExpression != null) {
|
||||
if (requiredType.isAssignableFrom(UQualifiedReferenceExpression::class.java) ||
|
||||
requiredType.isAssignableFrom(UCallExpression::class.java)) {
|
||||
val expr = JavaUCompositeQualifiedExpression(el, givenParent).apply {
|
||||
receiverInitializer = { convertOrEmpty(el.methodExpression.qualifierExpression!!, this) }
|
||||
selector = JavaUCallExpression(el, this)
|
||||
}
|
||||
if (!requiredType.isAssignableFrom(UQualifiedReferenceExpression::class.java))
|
||||
expr.selector
|
||||
else
|
||||
expr
|
||||
}
|
||||
else
|
||||
null
|
||||
}
|
||||
else
|
||||
expr<UCallExpression>(build(::JavaUCallExpression))
|
||||
}
|
||||
is PsiMethodCallExpression -> psiMethodCallConversionAlternatives(el, givenParent, requiredType).firstOrNull()
|
||||
is PsiArrayInitializerExpression -> expr<UCallExpression>(build(::JavaArrayInitializerUCallExpression))
|
||||
is PsiBinaryExpression -> expr<UBinaryExpression>(build(::JavaUBinaryExpression))
|
||||
// Should go after PsiBinaryExpression since it implements PsiPolyadicExpression
|
||||
@@ -279,6 +269,28 @@ internal object JavaConverter {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun psiMethodCallConversionAlternatives(element: PsiMethodCallExpression,
|
||||
givenParent: UElement?,
|
||||
requiredTypes: List<Class<out UElement>>): Sequence<UExpression> {
|
||||
if (element.methodExpression.qualifierExpression == null) {
|
||||
return sequenceOf(requiredTypes.expr<UCallExpression> { JavaUCallExpression(element, givenParent) }).filterNotNull()
|
||||
}
|
||||
|
||||
if (!requiredTypes.isAssignableFrom(UQualifiedReferenceExpression::class.java) &&
|
||||
!requiredTypes.isAssignableFrom(UCallExpression::class.java)) return emptySequence()
|
||||
|
||||
|
||||
val expr = JavaUCompositeQualifiedExpression(element, givenParent).apply {
|
||||
receiverInitializer = {
|
||||
convertOrEmpty(element.methodExpression.qualifierExpression!!, this@apply)
|
||||
}
|
||||
selector = JavaUCallExpression(element, this@apply)
|
||||
}
|
||||
|
||||
val results = sequenceOf(expr, expr.selector)
|
||||
return requiredTypes.asSequence().flatMap { required -> results.filter { required.isInstance(it) } }.distinct()
|
||||
}
|
||||
|
||||
internal fun convertStatement(el: PsiStatement,
|
||||
givenParent: UElement?,
|
||||
requiredType: List<Class<out UElement>> = DEFAULT_EXPRESSION_TYPES_LIST): UExpression? {
|
||||
@@ -363,4 +375,6 @@ internal object JavaConverter {
|
||||
|
||||
private fun expressionTypes(requiredType: Class<out UElement>?) = requiredType?.let { listOf(it) } ?: DEFAULT_EXPRESSION_TYPES_LIST
|
||||
|
||||
private fun elementTypes(requiredType: Class<out UElement>?) = requiredType?.let { listOf(it) } ?: DEFAULT_TYPES_LIST
|
||||
private fun elementTypes(requiredType: Class<out UElement>?) = requiredType?.let { listOf(it) } ?: DEFAULT_TYPES_LIST
|
||||
|
||||
private fun <T : UElement> List<Class<out T>>.nonEmptyOr(default: List<Class<out UElement>>) = takeIf { it.isNotEmpty() } ?: default
|
||||
@@ -75,6 +75,36 @@ class JavaUastApiTest : AbstractJavaUastTest() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testCallExpressionAlternatives() {
|
||||
doTest("Simple/CallExpression.java") { name, file ->
|
||||
val index = file.psi.text.indexOf("format")
|
||||
val callExpression = PsiTreeUtil.getParentOfType(file.psi.findElementAt(index), PsiCallExpression::class.java)!!
|
||||
|
||||
val javaUastLanguagePlugin = UastLanguagePlugin.byLanguage(callExpression.language)!!
|
||||
|
||||
javaUastLanguagePlugin.convertToAlternatives(callExpression, listOf(UCallExpression::class.java)).let {
|
||||
assertEquals("format(\"q\")", it.joinToString(transform = UExpression::asRenderString))
|
||||
}
|
||||
|
||||
javaUastLanguagePlugin.convertToAlternatives<UExpression>(callExpression, listOf(UQualifiedReferenceExpression::class.java,
|
||||
UCallExpression::class.java)).let {
|
||||
assertEquals("String.format(\"q\"), format(\"q\")", it.joinToString(transform = UExpression::asRenderString))
|
||||
}
|
||||
|
||||
javaUastLanguagePlugin.convertToAlternatives<UExpression>(callExpression, listOf(UCallExpression::class.java,
|
||||
UQualifiedReferenceExpression::class.java)).let {
|
||||
assertEquals("format(\"q\"), String.format(\"q\")", it.joinToString(transform = UExpression::asRenderString))
|
||||
}
|
||||
|
||||
javaUastLanguagePlugin.convertToAlternatives(callExpression, listOf(UExpression::class.java)).let {
|
||||
assertEquals("String.format(\"q\"), format(\"q\")", it.joinToString(transform = UExpression::asRenderString))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCallExpressionArguments() {
|
||||
doTest("Simple/CallExpression.java") { name, file ->
|
||||
|
||||
Reference in New Issue
Block a user