191: Uast: support convertToAlternatives for KtParameter
This commit is contained in:
@@ -222,16 +222,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
|||||||
convertNonLocalProperty(original, givenParent, expectedTypes).firstOrNull()
|
convertNonLocalProperty(original, givenParent, expectedTypes).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtParameter -> el<UParameter> {
|
is KtParameter -> convertParameter(original, givenParent, this).firstOrNull()
|
||||||
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 KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
|
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
|
||||||
is FakeFileForLightClass -> el<UFile> { KotlinUFile(original.navigationElement, 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? {
|
private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? {
|
||||||
return LightClassUtil.getLightClassBackingField(original)?.let { psiField ->
|
return LightClassUtil.getLightClassBackingField(original)?.let { psiField ->
|
||||||
if (psiField is KtLightFieldImpl.KtLightEnumConstant) {
|
if (psiField is KtLightFieldImpl.KtLightEnumConstant) {
|
||||||
@@ -282,6 +274,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T : UElement> convertToAlternatives(element: PsiElement, requiredTypes: Array<out Class<out T>>): Sequence<T> = when {
|
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 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()
|
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) }
|
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(
|
private fun convertNonLocalProperty(
|
||||||
property: KtProperty,
|
property: KtProperty,
|
||||||
givenParent: UElement?,
|
givenParent: UElement?,
|
||||||
requiredType: Array<out Class<out UElement>>
|
requiredType: Array<out Class<out UElement>>
|
||||||
): Sequence<UElement> {
|
): Sequence<UElement> =
|
||||||
val methods = LightClassUtil.getLightClassPropertyMethods(property)
|
requiredType.accommodate(*convertToPropertyAlternatives(LightClassUtil.getLightClassPropertyMethods(property), givenParent))
|
||||||
return requiredType.accommodate(
|
|
||||||
alternative {
|
|
||||||
methods.backingField?.let { KotlinUField(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, givenParent) }
|
private fun convertParameter(
|
||||||
},
|
element: KtParameter,
|
||||||
alternative {
|
givenParent: UElement?,
|
||||||
// TODO: make it possible to use `convertDeclaration` without `KotlinUastLanguagePlugin` creation
|
requiredTypes: Array<out Class<out UElement>>
|
||||||
methods.getter?.let { KotlinUastLanguagePlugin().convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod }
|
): Sequence<UElement> = requiredTypes.accommodate(
|
||||||
},
|
alternative uParam@{
|
||||||
alternative {
|
val ownerFunction = element.ownerFunction as? KtFunction ?: return@uParam null
|
||||||
methods.setter?.let { KotlinUastLanguagePlugin().convertDeclaration(it, givenParent, arrayOf(UMethod::class.java)) as? UMethod }
|
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 object KotlinConverter {
|
||||||
internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) {
|
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
|
var writebleProp: Int = 0
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
package org.jetbrains.uast.test.kotlin
|
package org.jetbrains.uast.test.kotlin
|
||||||
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
|
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.assertInstanceOf
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
import org.junit.Test
|
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