diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 index 3c612df2c93..33485aecc81 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.181 @@ -293,6 +293,7 @@ internal object KotlinConverter { is KtContainerNode -> unwrapElements(element.parent) is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent) is KtLightParameterList -> unwrapElements(element.parent) + is KtTypeElement -> unwrapElements(element.parent) else -> element } @@ -353,7 +354,7 @@ internal object KotlinConverter { is KtImportDirective -> el(build(::KotlinUImportStatement)) else -> { if (element is LeafPsiElement) { - if (element.elementType == KtTokens.IDENTIFIER) + if (element.elementType == KtTokens.IDENTIFIER || element.elementType == KtTokens.CONSTRUCTOR_KEYWORD) el(build(::KotlinUIdentifier)) else if (element.elementType == KtTokens.LBRACKET && element.parent is KtCollectionLiteralExpression) el { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.181 index 47a17acf3d6..68190da9821 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.181 @@ -164,6 +164,14 @@ open class KotlinConstructorUMethod( } } + override val uastAnchor: KotlinUIdentifier by lazy { + KotlinUIdentifier( + psi.nameIdentifier, + if (isPrimary) ktClass?.nameIdentifier else (psi.kotlinOrigin as? KtSecondaryConstructor)?.getConstructorKeyword(), + this + ) + } + override val javaPsi = psi override val sourcePsi = psi.kotlinOrigin diff --git a/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 b/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 index a268df2e3ab..ee5b0b052c0 100644 --- a/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 +++ b/plugins/uast-kotlin/testData/Constructors.identifiers.txt.181 @@ -1,6 +1,7 @@ A -> UClass (name = A) str -> UParameter (name = str) String -> USimpleNameReferenceExpression (identifier = String) +constructor -> UAnnotationMethod (name = A) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) i -> USimpleNameReferenceExpression (identifier = i) @@ -9,6 +10,7 @@ AWithInit -> UClass (name = AWithInit) str -> UParameter (name = str) String -> USimpleNameReferenceExpression (identifier = String) println -> USimpleNameReferenceExpression (identifier = println) +constructor -> UAnnotationMethod (name = AWithInit) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) i -> USimpleNameReferenceExpression (identifier = i) @@ -18,6 +20,7 @@ str -> UParameter (name = str) String -> USimpleNameReferenceExpression (identifier = String) println -> USimpleNameReferenceExpression (identifier = println) println -> USimpleNameReferenceExpression (identifier = println) +constructor -> UAnnotationMethod (name = AWith2Init) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) i -> USimpleNameReferenceExpression (identifier = i) @@ -28,11 +31,13 @@ AOnlyInit -> UClass (name = AOnlyInit) AWithSecondary -> UClass (name = AWithSecondary) a -> UField (name = a) String -> USimpleNameReferenceExpression (identifier = String) +constructor -> UAnnotationMethod (name = AWithSecondary) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) a -> USimpleNameReferenceExpression (identifier = a) i -> USimpleNameReferenceExpression (identifier = i) toString -> USimpleNameReferenceExpression (identifier = toString) +constructor -> UAnnotationMethod (name = AWithSecondary) s -> UParameter (name = s) String -> USimpleNameReferenceExpression (identifier = String) a -> USimpleNameReferenceExpression (identifier = a) @@ -41,11 +46,13 @@ AWithSecondaryInit -> UClass (name = AWithSecondaryInit) a -> UField (name = a) String -> USimpleNameReferenceExpression (identifier = String) println -> USimpleNameReferenceExpression (identifier = println) +constructor -> UAnnotationMethod (name = AWithSecondaryInit) i -> UParameter (name = i) Int -> USimpleNameReferenceExpression (identifier = Int) a -> USimpleNameReferenceExpression (identifier = a) i -> USimpleNameReferenceExpression (identifier = i) toString -> USimpleNameReferenceExpression (identifier = toString) +constructor -> UAnnotationMethod (name = AWithSecondaryInit) s -> UParameter (name = s) String -> USimpleNameReferenceExpression (identifier = String) a -> USimpleNameReferenceExpression (identifier = a) diff --git a/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 b/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 new file mode 100644 index 00000000000..c6d6cf84480 --- /dev/null +++ b/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.181 @@ -0,0 +1,8 @@ +SimpleAnnotated -> UClass (name = SimpleAnnotated) +Suppress -> USimpleNameReferenceExpression (identifier = Suppress) +method -> UAnnotationMethod (name = method) + println -> USimpleNameReferenceExpression (identifier = println) +kotlin -> USimpleNameReferenceExpression (identifier = kotlin) +SinceKotlin -> USimpleNameReferenceExpression (identifier = SinceKotlin) +property -> UField (name = property) +String -> USimpleNameReferenceExpression (identifier = String) diff --git a/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 b/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 index 04a17e99aff..10c2ce5acb9 100644 --- a/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 +++ b/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 @@ -7,7 +7,10 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.utils.addToStdlib.assertedCast -import org.jetbrains.uast.* +import org.jetbrains.uast.JvmDeclarationUElement +import org.jetbrains.uast.UAnchorOwner +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UFile import org.jetbrains.uast.kotlin.KOTLIN_CACHED_UELEMENT_KEY import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin import org.jetbrains.uast.test.common.RenderLogTestBase @@ -87,7 +90,7 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog node.containingFile.assertedCast { "containingFile should be KtFile for ${node.asLogString()}" } } - val anchorPsi = (node as? UDeclaration)?.uastAnchor?.psi + val anchorPsi = (node as? UAnchorOwner)?.uastAnchor?.sourcePsi if (anchorPsi != null) { anchorPsi.containingFile.assertedCast { "uastAnchor.containingFile should be KtFile for ${node.asLogString()}" } } diff --git a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt.181 b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt.181 index 3330242a36b..5906787d5fc 100644 --- a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt.181 +++ b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt.181 @@ -19,4 +19,8 @@ class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() { fun testConstructors() = doTest("Constructors") + @Test + fun testSimpleAnnotated() = doTest("SimpleAnnotated") + + } \ No newline at end of file diff --git a/plugins/uast-kotlin/tests/org/jetbrains/uast/test/common/IdentifiersTestBase.kt.181 b/plugins/uast-kotlin/tests/org/jetbrains/uast/test/common/IdentifiersTestBase.kt.181 index 8349f1a5f55..0af939c673a 100644 --- a/plugins/uast-kotlin/tests/org/jetbrains/uast/test/common/IdentifiersTestBase.kt.181 +++ b/plugins/uast-kotlin/tests/org/jetbrains/uast/test/common/IdentifiersTestBase.kt.181 @@ -9,11 +9,10 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementVisitor import org.jetbrains.kotlin.psi.KtBlockExpression import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.uast.UFile -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.sourcePsiElement +import org.jetbrains.uast.* import org.jetbrains.uast.test.env.assertEqualsToFile -import org.jetbrains.uast.toUElementOfType +import org.jetbrains.uast.visitor.AbstractUastVisitor +import org.junit.ComparisonFailure import java.io.File interface IdentifiersTestBase { @@ -40,10 +39,44 @@ interface IdentifiersTestBase { return builder.toString() } + private fun UFile.testIdentifiersParents() { + accept(object : AbstractUastVisitor() { + override fun visitElement(node: UElement): Boolean { + if (node is UAnchorOwner) { + val uastAnchor = node.uastAnchor ?: return false + assertParents(node, uastAnchor) + val uastAnchorFromSource = (uastAnchor.sourcePsi ?: return false).toUElementOfType() + assertParents(node, uastAnchorFromSource) + } + return false + } + }) + } + + fun assertParents(node: UAnchorOwner, uastAnchor: UIdentifier?) { + //skipping such elements because they are ambiguous (properties and getters for instance) + if (node.sourcePsi.toUElement() != node) return + if (uastAnchor == null) + throw AssertionError("no uast anchor for ${node.uastAnchor?.sourcePsi}(${node.uastAnchor?.sourcePsi?.javaClass}) for node = $node") + val nodeParents = node.withContainingElements.log() + val anchorParentParents = uastAnchor.uastParent?.withContainingElements?.log() ?: "" + // dropping node itself because we allow children to share identifiers with parents (primary constructor for instance) + val parentsSuffix = node.withContainingElements.drop(1).log() + if (!anchorParentParents.endsWith(parentsSuffix)) + throw ComparisonFailure( + "wrong parents for '${uastAnchor.sourcePsi?.text}' owner: $node[${node.sourcePsi}[${node.sourcePsi?.text}]]", + nodeParents, + anchorParentParents + ) + } + + private fun Sequence.log() = this.joinToString { it.asLogString() } + fun check(testName: String, file: UFile) { val valuesFile = getIdentifiersFile(testName) assertEqualsToFile("Identifiers", valuesFile, file.asIdentifiersWithParents()) + file.testIdentifiersParents() } }