191: Uast: support convertToAlternatives for KtParameter
This commit is contained in:
@@ -222,16 +222,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
||||
convertNonLocalProperty(original, givenParent, expectedTypes).firstOrNull()
|
||||
}
|
||||
|
||||
is KtParameter -> el<UParameter> {
|
||||
val ownerFunction = original.ownerFunction as? KtFunction ?: return@el null
|
||||
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return@el null
|
||||
val lightParameter = lightMethod.parameterList.parameters.find { it.name == original.name } ?: return@el null
|
||||
KotlinUParameter(lightParameter, original, givenParent)
|
||||
} ?: el<UField> {
|
||||
if (!original.hasValOrVar()) return@el null
|
||||
val lightField = LightClassUtil.getLightClassBackingField(original) ?: return@el null
|
||||
KotlinUField(lightField, original, givenParent)
|
||||
}
|
||||
is KtParameter -> convertParameter(original, givenParent, this).firstOrNull()
|
||||
|
||||
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
|
||||
is FakeFileForLightClass -> el<UFile> { KotlinUFile(original.navigationElement, this@KotlinUastLanguagePlugin) }
|
||||
@@ -246,6 +237,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? {
|
||||
return LightClassUtil.getLightClassBackingField(original)?.let { psiField ->
|
||||
if (psiField is KtLightFieldImpl.KtLightEnumConstant) {
|
||||
@@ -282,6 +274,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : UElement> convertToAlternatives(element: PsiElement, requiredTypes: Array<out Class<out T>>): Sequence<T> = when {
|
||||
(element is KtProperty && !element.isLocal) -> convertNonLocalProperty(element, null, requiredTypes) as Sequence<T>
|
||||
element is KtParameter -> convertParameter(element, null, requiredTypes) as Sequence<T>
|
||||
else -> sequenceOf(convertElementWithParent(element, requiredTypes.nonEmptyOr(DEFAULT_TYPES_LIST)) as? T).filterNotNull()
|
||||
}
|
||||
}
|
||||
@@ -300,25 +293,44 @@ internal inline fun <reified ActualT : UElement> Array<out Class<out UElement>>.
|
||||
|
||||
internal fun Array<out Class<out UElement>>.isAssignableFrom(cls: Class<*>) = any { it.isAssignableFrom(cls) }
|
||||
|
||||
|
||||
private fun convertToPropertyAlternatives(
|
||||
methods: LightClassUtil.PropertyAccessorsPsiMethods?,
|
||||
givenParent: UElement?
|
||||
): Array<UElementAlternative<*>> = if (methods != null) arrayOf(
|
||||
alternative {
|
||||
methods.backingField?.let { KotlinUField(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, givenParent) }
|
||||
},
|
||||
alternative {
|
||||
// TODO: make it possible to use `convertDeclaration` without `KotlinUastLanguagePlugin` creation
|
||||
methods.getter?.let { KotlinUastLanguagePlugin().convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod }
|
||||
},
|
||||
alternative {
|
||||
methods.setter?.let { KotlinUastLanguagePlugin().convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod }
|
||||
}
|
||||
) else emptyArray()
|
||||
|
||||
private fun convertNonLocalProperty(
|
||||
property: KtProperty,
|
||||
givenParent: UElement?,
|
||||
requiredType: Array<out Class<out UElement>>
|
||||
): Sequence<UElement> {
|
||||
val methods = LightClassUtil.getLightClassPropertyMethods(property)
|
||||
return requiredType.accommodate(
|
||||
alternative {
|
||||
methods.backingField?.let { KotlinUField(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, givenParent) }
|
||||
},
|
||||
alternative {
|
||||
// TODO: make it possible to use `convertDeclaration` without `KotlinUastLanguagePlugin` creation
|
||||
methods.getter?.let { KotlinUastLanguagePlugin().convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod }
|
||||
},
|
||||
alternative {
|
||||
methods.setter?.let { KotlinUastLanguagePlugin().convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod }
|
||||
}
|
||||
)
|
||||
}
|
||||
): Sequence<UElement> =
|
||||
requiredType.accommodate(*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(property), givenParent))
|
||||
|
||||
|
||||
private fun convertParameter(
|
||||
element: KtParameter,
|
||||
givenParent: UElement?,
|
||||
requiredTypes: Array<out Class<out UElement>>
|
||||
): Sequence<UElement> = requiredTypes.accommodate(
|
||||
alternative uParam@{
|
||||
val ownerFunction = element.ownerFunction as? KtFunction ?: return@uParam null
|
||||
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return@uParam null
|
||||
val lightParameter = lightMethod.parameterList.parameters.find { it.name == element.name } ?: return@uParam null
|
||||
KotlinUParameter(lightParameter, element, givenParent)
|
||||
},
|
||||
*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(element), givenParent)
|
||||
)
|
||||
|
||||
internal object KotlinConverter {
|
||||
internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
Test -> UAnnotation (fqName = null)
|
||||
A -> UClass (name = A)
|
||||
MyAnnotation -> UClass (name = MyAnnotation)
|
||||
text -> UAnnotationMethod (name = text)
|
||||
String -> USimpleNameReferenceExpression (identifier = String)
|
||||
MyAnnotation -> UAnnotation (fqName = MyAnnotation)
|
||||
B -> UClass (name = B)
|
||||
MyAnnotation -> UAnnotation (fqName = MyAnnotation)
|
||||
InB -> UClass (name = InB)
|
||||
MyAnnotation -> UAnnotation (fqName = MyAnnotation)
|
||||
object -> UClass (name = Companion)
|
||||
MyAnnotation -> UAnnotation (fqName = MyAnnotation)
|
||||
Obj -> UClass (name = Obj)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
class ClassA {
|
||||
class ClassA(justParam: Int, val paramAndProp: String) {
|
||||
|
||||
var writebleProp: Int = 0
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
package org.jetbrains.uast.test.kotlin
|
||||
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.assertInstanceOf
|
||||
import org.jetbrains.uast.*
|
||||
import org.junit.Test
|
||||
|
||||
@@ -58,4 +60,69 @@ class KotlinUastAlternativesTest : AbstractKotlinUastTest() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testParamAndPropertylternatives() {
|
||||
doTest("ManyAlternatives") { name, file ->
|
||||
val index = file.psi.text.indexOf("paramAndProp")
|
||||
val ktProperty = PsiTreeUtil.getParentOfType(file.psi.findElementAt(index), KtParameter::class.java)!!
|
||||
val plugin = UastLanguagePlugin.byLanguage(ktProperty.language)!!
|
||||
|
||||
plugin.convertToAlternatives<UElement>(ktProperty, arrayOf(UField::class.java)).let {
|
||||
assertInstanceOf(it.single(), UField::class.java)
|
||||
assertEquals(
|
||||
"@org.jetbrains.annotations.NotNull private final var paramAndProp: java.lang.String",
|
||||
it.joinToString(transform = UElement::asRenderString)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.convertToAlternatives<UElement>(ktProperty, arrayOf(UParameter::class.java)).let {
|
||||
assertInstanceOf(it.single(), UParameter::class.java)
|
||||
assertEquals(
|
||||
"@org.jetbrains.annotations.NotNull var paramAndProp: java.lang.String",
|
||||
it.joinToString(transform = UElement::asRenderString)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.convertToAlternatives<UElement>(ktProperty, arrayOf(UElement::class.java)).let {
|
||||
assertEquals(
|
||||
"@org.jetbrains.annotations.NotNull var paramAndProp: java.lang.String, " +
|
||||
"@org.jetbrains.annotations.NotNull private final var paramAndProp: java.lang.String, " +
|
||||
"public final fun getParamAndProp() : java.lang.String = UastEmptyExpression",
|
||||
it.joinToString(transform = UElement::asRenderString)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJustParamAlternatives() {
|
||||
doTest("ManyAlternatives") { name, file ->
|
||||
val index = file.psi.text.indexOf("justParam")
|
||||
val ktProperty = PsiTreeUtil.getParentOfType(file.psi.findElementAt(index), KtParameter::class.java)!!
|
||||
val plugin = UastLanguagePlugin.byLanguage(ktProperty.language)!!
|
||||
|
||||
plugin.convertToAlternatives<UElement>(ktProperty, arrayOf(UField::class.java)).let {
|
||||
assertEquals("", it.joinToString(transform = UElement::asRenderString))
|
||||
}
|
||||
|
||||
plugin.convertToAlternatives<UElement>(ktProperty, arrayOf(UParameter::class.java)).let {
|
||||
assertInstanceOf(it.single(), UParameter::class.java)
|
||||
assertEquals(
|
||||
"@org.jetbrains.annotations.NotNull var justParam: int",
|
||||
it.joinToString(transform = UElement::asRenderString)
|
||||
)
|
||||
}
|
||||
|
||||
plugin.convertToAlternatives<UElement>(ktProperty, arrayOf(UElement::class.java)).let {
|
||||
assertEquals(
|
||||
"@org.jetbrains.annotations.NotNull var justParam: int",
|
||||
it.joinToString(transform = UElement::asRenderString)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user