181: Uast: weak consistency check and fixes for UIdentifiers
This commit is contained in:
committed by
Nikolay Krasko
parent
1bf12841ae
commit
8ce65dc715
@@ -293,6 +293,7 @@ internal object KotlinConverter {
|
|||||||
is KtContainerNode -> unwrapElements(element.parent)
|
is KtContainerNode -> unwrapElements(element.parent)
|
||||||
is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent)
|
is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent)
|
||||||
is KtLightParameterList -> unwrapElements(element.parent)
|
is KtLightParameterList -> unwrapElements(element.parent)
|
||||||
|
is KtTypeElement -> unwrapElements(element.parent)
|
||||||
else -> element
|
else -> element
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +354,7 @@ internal object KotlinConverter {
|
|||||||
is KtImportDirective -> el<UImportStatement>(build(::KotlinUImportStatement))
|
is KtImportDirective -> el<UImportStatement>(build(::KotlinUImportStatement))
|
||||||
else -> {
|
else -> {
|
||||||
if (element is LeafPsiElement) {
|
if (element is LeafPsiElement) {
|
||||||
if (element.elementType == KtTokens.IDENTIFIER)
|
if (element.elementType == KtTokens.IDENTIFIER || element.elementType == KtTokens.CONSTRUCTOR_KEYWORD)
|
||||||
el<UIdentifier>(build(::KotlinUIdentifier))
|
el<UIdentifier>(build(::KotlinUIdentifier))
|
||||||
else if (element.elementType == KtTokens.LBRACKET && element.parent is KtCollectionLiteralExpression)
|
else if (element.elementType == KtTokens.LBRACKET && element.parent is KtCollectionLiteralExpression)
|
||||||
el<UIdentifier> {
|
el<UIdentifier> {
|
||||||
|
|||||||
@@ -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 javaPsi = psi
|
||||||
|
|
||||||
override val sourcePsi = psi.kotlinOrigin
|
override val sourcePsi = psi.kotlinOrigin
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
A -> UClass (name = A)
|
A -> UClass (name = A)
|
||||||
str -> UParameter (name = str)
|
str -> UParameter (name = str)
|
||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
|
constructor -> UAnnotationMethod (name = A)
|
||||||
i -> UParameter (name = i)
|
i -> UParameter (name = i)
|
||||||
Int -> USimpleNameReferenceExpression (identifier = Int)
|
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||||
i -> USimpleNameReferenceExpression (identifier = i)
|
i -> USimpleNameReferenceExpression (identifier = i)
|
||||||
@@ -9,6 +10,7 @@ AWithInit -> UClass (name = AWithInit)
|
|||||||
str -> UParameter (name = str)
|
str -> UParameter (name = str)
|
||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
println -> USimpleNameReferenceExpression (identifier = println)
|
println -> USimpleNameReferenceExpression (identifier = println)
|
||||||
|
constructor -> UAnnotationMethod (name = AWithInit)
|
||||||
i -> UParameter (name = i)
|
i -> UParameter (name = i)
|
||||||
Int -> USimpleNameReferenceExpression (identifier = Int)
|
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||||
i -> USimpleNameReferenceExpression (identifier = i)
|
i -> USimpleNameReferenceExpression (identifier = i)
|
||||||
@@ -18,6 +20,7 @@ str -> UParameter (name = str)
|
|||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
println -> USimpleNameReferenceExpression (identifier = println)
|
println -> USimpleNameReferenceExpression (identifier = println)
|
||||||
println -> USimpleNameReferenceExpression (identifier = println)
|
println -> USimpleNameReferenceExpression (identifier = println)
|
||||||
|
constructor -> UAnnotationMethod (name = AWith2Init)
|
||||||
i -> UParameter (name = i)
|
i -> UParameter (name = i)
|
||||||
Int -> USimpleNameReferenceExpression (identifier = Int)
|
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||||
i -> USimpleNameReferenceExpression (identifier = i)
|
i -> USimpleNameReferenceExpression (identifier = i)
|
||||||
@@ -28,11 +31,13 @@ AOnlyInit -> UClass (name = AOnlyInit)
|
|||||||
AWithSecondary -> UClass (name = AWithSecondary)
|
AWithSecondary -> UClass (name = AWithSecondary)
|
||||||
a -> UField (name = a)
|
a -> UField (name = a)
|
||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
|
constructor -> UAnnotationMethod (name = AWithSecondary)
|
||||||
i -> UParameter (name = i)
|
i -> UParameter (name = i)
|
||||||
Int -> USimpleNameReferenceExpression (identifier = Int)
|
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||||
a -> USimpleNameReferenceExpression (identifier = a)
|
a -> USimpleNameReferenceExpression (identifier = a)
|
||||||
i -> USimpleNameReferenceExpression (identifier = i)
|
i -> USimpleNameReferenceExpression (identifier = i)
|
||||||
toString -> USimpleNameReferenceExpression (identifier = toString)
|
toString -> USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
constructor -> UAnnotationMethod (name = AWithSecondary)
|
||||||
s -> UParameter (name = s)
|
s -> UParameter (name = s)
|
||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
a -> USimpleNameReferenceExpression (identifier = a)
|
a -> USimpleNameReferenceExpression (identifier = a)
|
||||||
@@ -41,11 +46,13 @@ AWithSecondaryInit -> UClass (name = AWithSecondaryInit)
|
|||||||
a -> UField (name = a)
|
a -> UField (name = a)
|
||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
println -> USimpleNameReferenceExpression (identifier = println)
|
println -> USimpleNameReferenceExpression (identifier = println)
|
||||||
|
constructor -> UAnnotationMethod (name = AWithSecondaryInit)
|
||||||
i -> UParameter (name = i)
|
i -> UParameter (name = i)
|
||||||
Int -> USimpleNameReferenceExpression (identifier = Int)
|
Int -> USimpleNameReferenceExpression (identifier = Int)
|
||||||
a -> USimpleNameReferenceExpression (identifier = a)
|
a -> USimpleNameReferenceExpression (identifier = a)
|
||||||
i -> USimpleNameReferenceExpression (identifier = i)
|
i -> USimpleNameReferenceExpression (identifier = i)
|
||||||
toString -> USimpleNameReferenceExpression (identifier = toString)
|
toString -> USimpleNameReferenceExpression (identifier = toString)
|
||||||
|
constructor -> UAnnotationMethod (name = AWithSecondaryInit)
|
||||||
s -> UParameter (name = s)
|
s -> UParameter (name = s)
|
||||||
String -> USimpleNameReferenceExpression (identifier = String)
|
String -> USimpleNameReferenceExpression (identifier = String)
|
||||||
a -> USimpleNameReferenceExpression (identifier = a)
|
a -> USimpleNameReferenceExpression (identifier = a)
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -7,7 +7,10 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement
|
|||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
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.KOTLIN_CACHED_UELEMENT_KEY
|
||||||
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
|
import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin
|
||||||
import org.jetbrains.uast.test.common.RenderLogTestBase
|
import org.jetbrains.uast.test.common.RenderLogTestBase
|
||||||
@@ -87,7 +90,7 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog
|
|||||||
node.containingFile.assertedCast<KtFile> { "containingFile should be KtFile for ${node.asLogString()}" }
|
node.containingFile.assertedCast<KtFile> { "containingFile should be KtFile for ${node.asLogString()}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
val anchorPsi = (node as? UDeclaration)?.uastAnchor?.psi
|
val anchorPsi = (node as? UAnchorOwner)?.uastAnchor?.sourcePsi
|
||||||
if (anchorPsi != null) {
|
if (anchorPsi != null) {
|
||||||
anchorPsi.containingFile.assertedCast<KtFile> { "uastAnchor.containingFile should be KtFile for ${node.asLogString()}" }
|
anchorPsi.containingFile.assertedCast<KtFile> { "uastAnchor.containingFile should be KtFile for ${node.asLogString()}" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,8 @@ class KotlinUastIdentifiersTest : AbstractKotlinIdentifiersTest() {
|
|||||||
fun testConstructors() = doTest("Constructors")
|
fun testConstructors() = doTest("Constructors")
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSimpleAnnotated() = doTest("SimpleAnnotated")
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+37
-4
@@ -9,11 +9,10 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiElementVisitor
|
import com.intellij.psi.PsiElementVisitor
|
||||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.uast.UFile
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.UIdentifier
|
|
||||||
import org.jetbrains.uast.sourcePsiElement
|
|
||||||
import org.jetbrains.uast.test.env.assertEqualsToFile
|
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
|
import java.io.File
|
||||||
|
|
||||||
interface IdentifiersTestBase {
|
interface IdentifiersTestBase {
|
||||||
@@ -40,10 +39,44 @@ interface IdentifiersTestBase {
|
|||||||
return builder.toString()
|
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<UIdentifier>()
|
||||||
|
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<UElement>.log() = this.joinToString { it.asLogString() }
|
||||||
|
|
||||||
fun check(testName: String, file: UFile) {
|
fun check(testName: String, file: UFile) {
|
||||||
val valuesFile = getIdentifiersFile(testName)
|
val valuesFile = getIdentifiersFile(testName)
|
||||||
|
|
||||||
assertEqualsToFile("Identifiers", valuesFile, file.asIdentifiersWithParents())
|
assertEqualsToFile("Identifiers", valuesFile, file.asIdentifiersWithParents())
|
||||||
|
file.testIdentifiersParents()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user