Java UAST: uastParent made lazy (IDEA-175404)

This commit is contained in:
Nicolay Mitropolsky
2017-10-09 15:22:29 +03:00
parent b82aad2cef
commit 7a8a748363
45 changed files with 252 additions and 180 deletions
@@ -16,15 +16,20 @@
package org.jetbrains.uast.java
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiType
import com.intellij.psi.*
import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.java.internal.JavaUElementWithComments
import org.jetbrains.uast.toUElement
abstract class JavaAbstractUElement(givenParent: UElement?) : JavaUElementWithComments {
@Suppress("unused") // Used in Kotlin 1.2, to be removed in 2018.1
@Deprecated("use JavaAbstractUElement(givenParent)", ReplaceWith("JavaAbstractUElement(givenParent)"))
constructor() : this(null)
abstract class JavaAbstractUElement : JavaUElementWithComments {
override fun equals(other: Any?): Boolean {
if (other !is UElement || other.javaClass != this.javaClass) return false
return if (this.psi != null) this.psi == other.psi else this === other
@@ -37,9 +42,25 @@ abstract class JavaAbstractUElement : JavaUElementWithComments {
}
override fun toString() = asRenderString()
override val uastParent: UElement? by lz { givenParent ?: convertParent() }
protected open fun convertParent(): UElement? =
getPsiParentForLazyConversion()?.let { JavaConverter.unwrapElements(it).toUElement() }?.also {
if (it === this) throw IllegalStateException("lazy parent loop for $this")
if (it.psi != null && it.psi === this.psi) throw IllegalStateException(
"lazy parent loop: psi ${this.psi}(${this.psi?.javaClass}) for $this of ${this.javaClass}")
}
protected open fun getPsiParentForLazyConversion() = this.psi?.parent
}
abstract class JavaAbstractUExpression : JavaAbstractUElement(), UExpression {
abstract class JavaAbstractUExpression(givenParent: UElement?) : JavaAbstractUElement(givenParent), UExpression {
@Suppress("unused") // Used in Kotlin 1.2, to be removed in 2018.1
@Deprecated("use JavaAbstractUExpression(givenParent)", ReplaceWith("JavaAbstractUExpression(givenParent)"))
constructor() : this(null)
override fun evaluate(): Any? {
val project = psi?.project ?: return null
return JavaPsiFacade.getInstance(project).constantEvaluationHelper.computeConstantExpression(psi)
@@ -52,4 +73,11 @@ abstract class JavaAbstractUExpression : JavaAbstractUElement(), UExpression {
val expression = psi as? PsiExpression ?: return null
return expression.type
}
}
override fun getPsiParentForLazyConversion(): PsiElement? = super.getPsiParentForLazyConversion()?.let {
when (it) {
is PsiResourceExpression -> it.parent
else -> it
}
}
}
@@ -83,9 +83,8 @@ class JavaUastLanguagePlugin : UastLanguagePlugin {
override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (element !is PsiElement) return null
val parentCallback = parent.toCallback()
return convertDeclaration(element, parentCallback, requiredType) ?:
JavaConverter.convertPsiElement(element, parentCallback, requiredType)
return convertDeclaration(element, parent, requiredType) ?:
JavaConverter.convertPsiElement(element, parent, requiredType)
}
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
@@ -93,21 +92,16 @@ class JavaUastLanguagePlugin : UastLanguagePlugin {
if (element is PsiJavaFile) return requiredType.el<UFile> { JavaUFile(element, this) }
JavaConverter.getCached<UElement>(element)?.let { return it }
val parentCallback = fun(): UElement? {
val parent = JavaConverter.unwrapElements(element.parent) ?: return null
return convertElementWithParent(parent, null) ?: return null
}
return convertDeclaration(element, parentCallback, requiredType) ?:
JavaConverter.convertPsiElement(element, parentCallback, requiredType)
return convertDeclaration(element, null, requiredType) ?:
JavaConverter.convertPsiElement(element, null, requiredType)
}
private fun convertDeclaration(element: PsiElement,
parentCallback: (() -> UElement?)?,
givenParent: UElement?,
requiredType: Class<out UElement>?): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return fun(): UElement? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(element as P, parent)
return ctor(element as P, givenParent)
}
}
@@ -119,12 +113,10 @@ class JavaUastLanguagePlugin : UastLanguagePlugin {
is PsiJavaFile -> el<UFile> { JavaUFile(element, this@JavaUastLanguagePlugin) }
is UDeclaration -> el<UDeclaration> { element }
is PsiClass -> el<UClass> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
JavaUClass.create(element, parent)
JavaUClass.create(element, givenParent)
}
is PsiMethod -> el<UMethod> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
JavaUMethod.create(element, this@JavaUastLanguagePlugin, parent)
JavaUMethod.create(element, this@JavaUastLanguagePlugin, givenParent)
}
is PsiClassInitializer -> el<UClassInitializer>(build(::JavaUClassInitializer))
is PsiEnumConstant -> el<UEnumConstant>(build(::JavaUEnumConstant))
@@ -165,30 +157,28 @@ internal object JavaConverter {
}
internal fun convertPsiElement(el: PsiElement,
parentCallback: (() -> UElement?)?,
givenParent: UElement?,
requiredType: Class<out UElement>? = null): UElement? {
getCached<UElement>(el)?.let { return it }
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return fun(): UElement? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(el as P, parent)
return ctor(el as P, givenParent)
}
}
return with (requiredType) { when (el) {
is PsiCodeBlock -> el<UBlockExpression>(build(::JavaUCodeBlockExpression))
is PsiResourceExpression -> convertExpression(el.expression, parentCallback, requiredType)
is PsiExpression -> convertExpression(el, parentCallback, requiredType)
is PsiStatement -> convertStatement(el, parentCallback, requiredType)
is PsiResourceExpression -> convertExpression(el.expression, givenParent, requiredType)
is PsiExpression -> convertExpression(el, givenParent, requiredType)
is PsiStatement -> convertStatement(el, givenParent, requiredType)
is PsiIdentifier -> el<USimpleNameReferenceExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
JavaUSimpleNameReferenceExpression(el, el.text, parent)
JavaUSimpleNameReferenceExpression(el, el.text, givenParent)
}
is PsiNameValuePair -> el<UNamedExpression>(build(::JavaUNamedExpression))
is PsiArrayInitializerMemberValue -> el<UCallExpression>(build(::JavaAnnotationArrayInitializerUCallExpression))
is PsiTypeElement -> el<UTypeReferenceExpression>(build(::JavaUTypeReferenceExpression))
is PsiJavaCodeReferenceElement -> convertReference(el, parentCallback, requiredType)
is PsiJavaCodeReferenceElement -> convertReference(el, givenParent, requiredType)
else -> null
}}
}
@@ -196,27 +186,25 @@ internal object JavaConverter {
internal fun convertBlock(block: PsiCodeBlock, parent: UElement?): UBlockExpression =
getCached(block) ?: JavaUCodeBlockExpression(block, parent)
internal fun convertReference(reference: PsiJavaCodeReferenceElement, parentCallback: (() -> UElement?)?, requiredType: Class<out UElement>?): UExpression? {
internal fun convertReference(reference: PsiJavaCodeReferenceElement, givenParent: UElement?, requiredType: Class<out UElement>?): UExpression? {
return with (requiredType) {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
if (reference.isQualified) {
expr<UQualifiedReferenceExpression> { JavaUQualifiedReferenceExpression(reference, parent) }
expr<UQualifiedReferenceExpression> { JavaUQualifiedReferenceExpression(reference, givenParent) }
} else {
val name = reference.referenceName ?: "<error name>"
expr<USimpleNameReferenceExpression> { JavaUSimpleNameReferenceExpression(reference, name, parent, reference) }
expr<USimpleNameReferenceExpression> { JavaUSimpleNameReferenceExpression(reference, name, givenParent, reference) }
}
}
}
internal fun convertExpression(el: PsiExpression,
parentCallback: (() -> UElement?)?,
givenParent: UElement?,
requiredType: Class<out UElement>? = null): UExpression? {
getCached<UExpression>(el)?.let { return it }
fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? {
return fun(): UExpression? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(el as P, parent)
return ctor(el as P, givenParent)
}
}
@@ -234,8 +222,7 @@ internal object JavaConverter {
if (requiredType == null ||
requiredType.isAssignableFrom(UQualifiedReferenceExpression::class.java) ||
requiredType.isAssignableFrom(UCallExpression::class.java)) {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
val expr = JavaUCompositeQualifiedExpression(el, parent).apply {
val expr = JavaUCompositeQualifiedExpression(el, givenParent).apply {
receiver = convertOrEmpty(el.methodExpression.qualifierExpression!!, this)
selector = JavaUCallExpression(el, this)
}
@@ -259,7 +246,7 @@ internal object JavaConverter {
is PsiPostfixExpression -> expr<UPostfixExpression>(build(::JavaUPostfixExpression))
is PsiLiteralExpression -> expr<ULiteralExpression>(build(::JavaULiteralExpression))
is PsiMethodReferenceExpression -> expr<UCallableReferenceExpression>(build(::JavaUCallableReferenceExpression))
is PsiReferenceExpression -> convertReference(el, parentCallback, requiredType)
is PsiReferenceExpression -> convertReference(el, givenParent, requiredType)
is PsiThisExpression -> expr<UThisExpression>(build(::JavaUThisExpression))
is PsiSuperExpression -> expr<USuperExpression>(build(::JavaUSuperExpression))
is PsiInstanceOfExpression -> expr<UBinaryExpressionWithType>(build(::JavaUInstanceCheckExpression))
@@ -272,29 +259,26 @@ internal object JavaConverter {
}
internal fun convertStatement(el: PsiStatement,
parentCallback: (() -> UElement?)?,
givenParent: UElement?,
requiredType: Class<out UElement>? = null): UExpression? {
getCached<UExpression>(el)?.let { return it }
fun <P : PsiElement> build(ctor: (P, UElement?) -> UExpression): () -> UExpression? {
return fun(): UExpression? {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
return ctor(el as P, parent)
return ctor(el as P, givenParent)
}
}
return with (requiredType) { when (el) {
is PsiDeclarationStatement -> expr<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
convertDeclarations(el.declaredElements, parent!!)
convertDeclarations(el.declaredElements, givenParent ?: JavaConverter.unwrapElements(el.parent).toUElement() !!)
}
is PsiExpressionListStatement -> expr<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
convertDeclarations(el.expressionList.expressions, parent!!)
convertDeclarations(el.expressionList.expressions, givenParent ?: JavaConverter.unwrapElements(el.parent).toUElement() !!)
}
is PsiBlockStatement -> expr<UBlockExpression>(build(::JavaUBlockExpression))
is PsiLabeledStatement -> expr<ULabeledExpression>(build(::JavaULabeledExpression))
is PsiExpressionStatement -> convertExpression(el.expression, parentCallback, requiredType)
is PsiExpressionStatement -> convertExpression(el.expression, givenParent, requiredType)
is PsiIfStatement -> expr<UIfExpression>(build(::JavaUIfExpression))
is PsiSwitchStatement -> expr<USwitchExpression>(build(::JavaUSwitchExpression))
is PsiWhileStatement -> expr<UWhileExpression>(build(::JavaUWhileExpression))
@@ -329,15 +313,15 @@ internal object JavaConverter {
}
internal fun convertOrEmpty(statement: PsiStatement?, parent: UElement?): UExpression {
return statement?.let { convertStatement(it, parent.toCallback(), null) } ?: UastEmptyExpression
return statement?.let { convertStatement(it, parent, null) } ?: UastEmptyExpression
}
internal fun convertOrEmpty(expression: PsiExpression?, parent: UElement?): UExpression {
return expression?.let { convertExpression(it, parent.toCallback()) } ?: UastEmptyExpression
return expression?.let { convertExpression(it, parent) } ?: UastEmptyExpression
}
internal fun convertOrNull(expression: PsiExpression?, parent: UElement?): UExpression? {
return if (expression != null) convertExpression(expression, parent.toCallback()) else null
return if (expression != null) convertExpression(expression, parent) else null
}
internal fun convertOrEmpty(block: PsiCodeBlock?, parent: UElement?): UExpression {
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UIdentifier
class JavaUDoWhileExpression(
override val psi: PsiDoWhileStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UDoWhileExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UDoWhileExpression {
override val condition by lz { JavaConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { JavaConverter.convertOrEmpty(psi.body, this) }
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UParameter
class JavaUForEachExpression(
override val psi: PsiForeachStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UForEachExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UForEachExpression {
override val variable: UParameter
get() = JavaUParameter(psi.iterationParameter, this)
@@ -23,11 +23,11 @@ import org.jetbrains.uast.UIdentifier
class JavaUForExpression(
override val psi: PsiForStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UForExpression {
override val declaration by lz { psi.initialization?.let { JavaConverter.convertStatement(it, { this }) } }
override val condition by lz { psi.condition?.let { JavaConverter.convertExpression(it, { this }) } }
override val update by lz { psi.update?.let { JavaConverter.convertStatement(it, { this }) } }
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UForExpression {
override val declaration by lz { psi.initialization?.let { JavaConverter.convertStatement(it, this) } }
override val condition by lz { psi.condition?.let { JavaConverter.convertExpression(it, this) } }
override val update by lz { psi.update?.let { JavaConverter.convertStatement(it, this) } }
override val body by lz { JavaConverter.convertOrEmpty(psi.body, this) }
override val forIdentifier: UIdentifier
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UIfExpression
class JavaUIfExpression(
override val psi: PsiIfStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UIfExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UIfExpression {
override val condition by lz { JavaConverter.convertOrEmpty(psi.condition, this) }
override val thenExpression by lz { JavaConverter.convertOrEmpty(psi.thenBranch, this) }
override val elseExpression by lz { JavaConverter.convertOrEmpty(psi.elseBranch, this) }
@@ -23,8 +23,8 @@ import org.jetbrains.uast.java.kinds.JavaSpecialExpressionKinds
class JavaUSwitchExpression(
override val psi: PsiSwitchStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), USwitchExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), USwitchExpression {
override val expression by lz { JavaConverter.convertOrEmpty(psi.expression, this) }
override val body: UExpressionList by lz {
@@ -70,8 +70,8 @@ private fun PsiCodeBlock.convertToSwitchEntryList(containingElement: UExpression
class JavaUSwitchEntry(
val labels: List<PsiSwitchLabelStatement>,
val statements: List<PsiStatement>,
override val uastParent: UExpression
) : JavaAbstractUExpression(), USwitchClauseExpressionWithBody {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
override val psi: PsiSwitchLabelStatement = labels.first()
override val caseValues by lz {
@@ -81,7 +81,7 @@ class JavaUSwitchEntry(
}
else {
val value = it.caseValue
value?.let { JavaConverter.convertExpression(it, { this }) }
value?.let { JavaConverter.convertExpression(it, this) }
}
}
}
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UIfExpression
class JavaUTernaryIfExpression(
override val psi: PsiConditionalExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UIfExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UIfExpression {
override val condition by lz { JavaConverter.convertOrEmpty(psi.condition, this) }
override val thenExpression by lz { JavaConverter.convertOrEmpty(psi.thenExpression, this) }
override val elseExpression by lz { JavaConverter.convertOrEmpty(psi.elseExpression, this) }
@@ -21,8 +21,8 @@ import org.jetbrains.uast.*
class JavaUTryExpression(
override val psi: PsiTryStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UTryExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UTryExpression {
override val tryClause by lz { JavaConverter.convertOrEmpty(psi.tryBlock, this) }
override val catchClauses by lz { psi.catchSections.map { JavaUCatchClause(it, this) } }
override val finallyClause by lz { psi.finallyBlock?.let { JavaConverter.convertBlock(it, this) } }
@@ -46,8 +46,8 @@ class JavaUTryExpression(
class JavaUCatchClause(
override val psi: PsiCatchSection,
override val uastParent: UElement?
) : JavaAbstractUElement(), UCatchClause {
givenParent: UElement?
) : JavaAbstractUElement(givenParent), UCatchClause {
override val body by lz { JavaConverter.convertOrEmpty(psi.catchBlock, this) }
override val parameters by lz {
@@ -23,8 +23,8 @@ import org.jetbrains.uast.UWhileExpression
class JavaUWhileExpression(
override val psi: PsiWhileStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UWhileExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UWhileExpression {
override val condition by lz { JavaConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { JavaConverter.convertOrEmpty(psi.body, this) }
@@ -22,13 +22,12 @@ import org.jetbrains.uast.java.expressions.JavaUNamedExpression
class JavaUAnnotation(
override val psi: PsiAnnotation,
override val uastParent: UElement?
) : UAnnotation {
givenParent: UElement?
) : JavaAbstractUElement(givenParent), UAnnotation {
override val qualifiedName: String?
get() = psi.qualifiedName
override val attributeValues: List<UNamedExpression> by lz {
val context = getUastContext()
val attributes = psi.parameterList.attributes
attributes.map { attribute -> JavaUNamedExpression(attribute, this) }
@@ -20,7 +20,12 @@ import com.intellij.psi.*
import org.jetbrains.uast.*
import org.jetbrains.uast.java.internal.JavaUElementWithComments
abstract class AbstractJavaUVariable : PsiVariable, UVariable, JavaUElementWithComments {
abstract class AbstractJavaUVariable(givenParent: UElement?) : JavaAbstractUElement(givenParent), PsiVariable, UVariable, JavaUElementWithComments {
@Suppress("unused") // Used in Kotlin 1.1.4, to be removed in 2018.1
@Deprecated("use AbstractJavaUVariable(givenParent) instead", ReplaceWith("AbstractJavaUVariable(givenParent)"))
constructor() : this(null)
override val uastInitializer by lz {
val initializer = psi.initializer ?: return@lz null
getLanguagePlugin().convertElement(initializer, this) as? UExpression
@@ -38,8 +43,8 @@ abstract class AbstractJavaUVariable : PsiVariable, UVariable, JavaUElementWithC
open class JavaUVariable(
psi: PsiVariable,
override val uastParent: UElement?
) : AbstractJavaUVariable(), UVariable, PsiVariable by psi {
givenParent: UElement?
) : AbstractJavaUVariable(givenParent), UVariable, PsiVariable by psi {
override val psi = unwrap<UVariable, PsiVariable>(psi)
companion object {
@@ -57,29 +62,29 @@ open class JavaUVariable(
open class JavaUParameter(
psi: PsiParameter,
override val uastParent: UElement?
) : AbstractJavaUVariable(), UParameter, PsiParameter by psi {
givenParent: UElement?
) : AbstractJavaUVariable(givenParent), UParameter, PsiParameter by psi {
override val psi = unwrap<UParameter, PsiParameter>(psi)
}
open class JavaUField(
psi: PsiField,
override val uastParent: UElement?
) : AbstractJavaUVariable(), UField, PsiField by psi {
givenParent: UElement?
) : AbstractJavaUVariable(givenParent), UField, PsiField by psi {
override val psi = unwrap<UField, PsiField>(psi)
}
open class JavaULocalVariable(
psi: PsiLocalVariable,
override val uastParent: UElement?
) : AbstractJavaUVariable(), ULocalVariable, PsiLocalVariable by psi {
givenParent: UElement?
) : AbstractJavaUVariable(givenParent), ULocalVariable, PsiLocalVariable by psi {
override val psi = unwrap<ULocalVariable, PsiLocalVariable>(psi)
}
open class JavaUEnumConstant(
psi: PsiEnumConstant,
override val uastParent: UElement?
) : AbstractJavaUVariable(), UEnumConstant, PsiEnumConstant by psi {
givenParent: UElement?
) : AbstractJavaUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi {
override val initializingClass: UClass? by lz { getLanguagePlugin().convertOpt<UClass>(psi.initializingClass, this) }
override val psi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
@@ -117,8 +122,8 @@ open class JavaUEnumConstant(
private class JavaEnumConstantClassReference(
override val psi: PsiEnumConstant,
override val uastParent: UElement?
) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), USimpleNameReferenceExpression {
override fun resolve() = psi.containingClass
override val resolvedName: String?
get() = psi.containingClass?.name
@@ -21,9 +21,9 @@ import org.jetbrains.uast.internal.log
class JavaDumbUElement(
override val psi: PsiElement,
override val uastParent: UElement?,
givenParent: UElement?,
private val customRenderString: String? = null
) : JavaAbstractUElement(), UElement {
) : JavaAbstractUElement(givenParent), UElement {
override fun asLogString() = log()
override fun asRenderString() = customRenderString ?: "<stub@$psi>"
}
@@ -21,8 +21,8 @@ import org.jetbrains.uast.UElement
class JavaUArrayAccessExpression(
override val psi: PsiArrayAccessExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UArrayAccessExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UArrayAccessExpression {
override val receiver by lz { JavaConverter.convertOrEmpty(psi.arrayExpression, this) }
override val indices by lz { singletonListOrEmpty(JavaConverter.convertOrNull(psi.indexExpression, this)) }
}
@@ -23,8 +23,8 @@ import org.jetbrains.uast.*
class JavaUAssertExpression(
override val psi: PsiAssertStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UCallExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UCallExpression {
val condition: UExpression by lz { JavaConverter.convertOrEmpty(psi.assertCondition, this) }
val message: UExpression? by lz { JavaConverter.convertOrNull(psi.assertDescription, this) }
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UIdentifier
class JavaUAssignmentExpression(
override val psi: PsiAssignmentExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBinaryExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBinaryExpression {
override val leftOperand by lz { JavaConverter.convertOrEmpty(psi.lExpression, this) }
override val rightOperand by lz { JavaConverter.convertOrEmpty(psi.rExpression, this) }
override val operator by lz { psi.operationTokenType.getOperatorType() }
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UIdentifier
class JavaUBinaryExpression(
override val psi: PsiBinaryExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBinaryExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBinaryExpression {
override val leftOperand by lz { JavaConverter.convertOrEmpty(psi.lOperand, this) }
override val rightOperand by lz { JavaConverter.convertOrEmpty(psi.rOperand, this) }
override val operator by lz { psi.operationTokenType.getOperatorType() }
@@ -21,7 +21,7 @@ import org.jetbrains.uast.UElement
class JavaUBlockExpression(
override val psi: PsiBlockStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBlockExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBlockExpression {
override val expressions by lz { psi.codeBlock.statements.map { JavaConverter.convertOrEmpty(it, this) } }
}
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UElement
class JavaUBreakExpression(
override val psi: PsiBreakStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBreakExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBreakExpression {
override val label: String?
get() = psi.labelIdentifier?.text
}
@@ -15,7 +15,6 @@
*/
package org.jetbrains.uast.java
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethodReferenceExpression
import com.intellij.psi.PsiNamedElement
import com.intellij.psi.PsiType
@@ -24,8 +23,8 @@ import org.jetbrains.uast.UElement
class JavaUCallableReferenceExpression(
override val psi: PsiMethodReferenceExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UCallableReferenceExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UCallableReferenceExpression {
override val qualifierExpression by lz { JavaConverter.convertOrNull(psi.qualifierExpression, this) }
override val qualifierType: PsiType?
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UElement
class JavaUClassLiteralExpression(
override val psi: PsiClassObjectAccessExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UClassLiteralExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UClassLiteralExpression {
override val type: PsiType
get() = psi.operand.type
@@ -21,7 +21,7 @@ import org.jetbrains.uast.UElement
class JavaUCodeBlockExpression(
override val psi: PsiCodeBlock,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBlockExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBlockExpression {
override val expressions by lz { psi.statements.map { JavaConverter.convertOrEmpty(it, this) } }
}
@@ -21,8 +21,8 @@ import org.jetbrains.uast.*
class JavaUCompositeQualifiedExpression(
override val psi: PsiElement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UQualifiedReferenceExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UQualifiedReferenceExpression {
override lateinit var receiver: UExpression
internal set
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UElement
class JavaUContinueExpression(
override val psi: PsiContinueStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UContinueExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UContinueExpression {
override val label: String?
get() = psi.labelIdentifier?.text
}
@@ -25,8 +25,8 @@ import org.jetbrains.uast.java.JavaAbstractUExpression
open class JavaUExpressionList(
override val psi: PsiElement,
override val kind: UastSpecialExpressionKind, // original element
override val uastParent: UElement?
) : JavaAbstractUExpression(), UExpressionList {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UExpressionList {
override lateinit var expressions: List<UExpression>
internal set
}
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UastErrorType
class JavaUInstanceCheckExpression(
override val psi: PsiInstanceOfExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBinaryExpressionWithType {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBinaryExpressionWithType {
override val operand by lz { JavaConverter.convertOrEmpty(psi.operand, this) }
override val typeReference by lz { psi.checkType?.let { JavaUTypeReferenceExpression(it, this) } }
@@ -22,8 +22,8 @@ import org.jetbrains.uast.ULabeledExpression
class JavaULabeledExpression(
override val psi: PsiLabeledStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), ULabeledExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), ULabeledExpression {
override val label: String
get() = psi.labelIdentifier.text
@@ -25,8 +25,8 @@ import org.jetbrains.uast.UastEmptyExpression
class JavaULambdaExpression(
override val psi: PsiLambdaExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), ULambdaExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), ULambdaExpression {
override val functionalInterfaceType: PsiType?
get() = psi.functionalInterfaceType
@@ -21,8 +21,8 @@ import org.jetbrains.uast.ULiteralExpression
class JavaULiteralExpression(
override val psi: PsiLiteralExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), ULiteralExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), ULiteralExpression {
override fun evaluate() = psi.value
override val value by lz { evaluate() }
}
@@ -26,13 +26,13 @@ import org.jetbrains.uast.java.lz
class JavaUNamedExpression(
override val psi: PsiNameValuePair,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UNamedExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UNamedExpression {
override fun evaluate(): Any? = expression.evaluate()
override val name: String?
get() = psi.name
override val expression: UExpression by lz {
psi.value?.let { value -> JavaConverter.convertPsiElement(value, { this }) } as? UExpression ?: UastEmptyExpression }
psi.value?.let { value -> JavaConverter.convertPsiElement(value, this) } as? UExpression ?: UastEmptyExpression }
}
@@ -23,13 +23,13 @@ import org.jetbrains.uast.UReferenceExpression
class JavaUObjectLiteralExpression(
override val psi: PsiNewExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UObjectLiteralExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UObjectLiteralExpression {
override val declaration by lz { JavaUClass.create(psi.anonymousClass!!, this) }
override val classReference by lz {
psi.classReference?.let { ref ->
JavaConverter.convertReference(ref, { this }, null) as? UReferenceExpression
JavaConverter.convertReference(ref, this, null) as? UReferenceExpression
}
}
@@ -21,8 +21,8 @@ import org.jetbrains.uast.UParenthesizedExpression
class JavaUParenthesizedExpression(
override val psi: PsiParenthesizedExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UParenthesizedExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UParenthesizedExpression {
override val expression by lz { JavaConverter.convertOrEmpty(psi.expression, this) }
override fun evaluate() = expression.evaluate()
}
@@ -16,13 +16,16 @@
package org.jetbrains.uast.java
import com.intellij.psi.PsiPolyadicExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UPolyadicExpression
import org.jetbrains.uast.UastBinaryOperator
class JavaUPolyadicExpression(
override val psi: PsiPolyadicExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UPolyadicExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UPolyadicExpression {
override val operands: List<UExpression> by lz {
psi.operands.map { JavaConverter.convertOrEmpty(it, this) }
}
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UastPostfixOperator
class JavaUPostfixExpression(
override val psi: PsiPostfixExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UPostfixExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UPostfixExpression {
override val operand by lz { JavaConverter.convertOrEmpty(psi.operand, this) }
override val operatorIdentifier: UIdentifier?
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UastPrefixOperator
class JavaUPrefixExpression(
override val psi: PsiPrefixExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UPrefixExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UPrefixExpression {
override val operand by lz { JavaConverter.convertOrEmpty(psi.operand, this) }
override val operatorIdentifier: UIdentifier?
@@ -21,10 +21,10 @@ import org.jetbrains.uast.*
class JavaUQualifiedReferenceExpression(
override val psi: PsiJavaCodeReferenceElement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UQualifiedReferenceExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UQualifiedReferenceExpression {
override val receiver by lz {
psi.qualifier?.let { JavaConverter.convertPsiElement(it, { this }) as? UExpression } ?: UastEmptyExpression
psi.qualifier?.let { JavaConverter.convertPsiElement(it, this) as? UExpression } ?: UastEmptyExpression
}
override val selector by lz {
@@ -22,7 +22,7 @@ import org.jetbrains.uast.UReturnExpression
class JavaUReturnExpression(
override val psi: PsiReturnStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UReturnExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UReturnExpression {
override val returnExpression by lz { JavaConverter.convertOrNull(psi.returnValue, this) }
}
@@ -23,9 +23,9 @@ import org.jetbrains.uast.UTypeReferenceExpression
class JavaUSimpleNameReferenceExpression(
override val psi: PsiElement?,
override val identifier: String,
override val uastParent: UElement?,
givenParent: UElement?,
val reference: PsiReference? = null
) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
) : JavaAbstractUExpression(givenParent), USimpleNameReferenceExpression {
override fun resolve() = (reference ?: psi as? PsiReference)?.resolve()
override val resolvedName: String?
get() = ((reference ?: psi as? PsiReference)?.resolve() as? PsiNamedElement)?.name
@@ -33,17 +33,17 @@ class JavaUSimpleNameReferenceExpression(
class JavaUTypeReferenceExpression(
override val psi: PsiTypeElement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UTypeReferenceExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UTypeReferenceExpression {
override val type: PsiType
get() = psi.type
}
class LazyJavaUTypeReferenceExpression(
override val psi: PsiElement,
override val uastParent: UElement?,
givenParent: UElement?,
private val typeSupplier: () -> PsiType
) : JavaAbstractUExpression(), UTypeReferenceExpression {
) : JavaAbstractUExpression(givenParent), UTypeReferenceExpression {
override val type: PsiType by lz { typeSupplier() }
}
@@ -51,8 +51,8 @@ class JavaClassUSimpleNameReferenceExpression(
override val identifier: String,
val ref: PsiJavaReference,
override val psi: PsiElement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), USimpleNameReferenceExpression {
override fun resolve() = ref.resolve()
override val resolvedName: String?
get() = (ref.resolve() as? PsiNamedElement)?.name
@@ -22,8 +22,8 @@ import org.jetbrains.uast.USuperExpression
class JavaUSuperExpression(
override val psi: PsiSuperExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), USuperExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), USuperExpression {
override val label: String?
get() = psi.qualifier?.qualifiedName
@@ -27,8 +27,8 @@ import org.jetbrains.uast.visitor.UastVisitor
class JavaUSynchronizedExpression(
override val psi: PsiSynchronizedStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBlockExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBlockExpression {
override val expressions by lz { psi.body?.statements?.map { JavaConverter.convertOrEmpty(it, this) } ?: listOf() }
val lockExpression by lz { JavaConverter.convertOrEmpty(psi.lockExpression, this) }
@@ -22,8 +22,8 @@ import org.jetbrains.uast.UThisExpression
class JavaUThisExpression(
override val psi: PsiThisExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UThisExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UThisExpression {
override val label: String?
get() = psi.qualifier?.qualifiedName
@@ -22,7 +22,7 @@ import org.jetbrains.uast.UThrowExpression
class JavaUThrowExpression(
override val psi: PsiThrowStatement,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UThrowExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UThrowExpression {
override val thrownExpression by lz { JavaConverter.convertOrEmpty(psi.exception, this) }
}
@@ -24,8 +24,8 @@ import org.jetbrains.uast.UastErrorType
class JavaUTypeCastExpression(
override val psi: PsiTypeCastExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UBinaryExpressionWithType {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UBinaryExpressionWithType {
override val operand by lz { JavaConverter.convertOrEmpty(psi.operand, this) }
override val type: PsiType
@@ -16,14 +16,15 @@
package org.jetbrains.uast.java
import com.intellij.psi.*
import com.intellij.psi.util.*
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.UElementWithLocation
class JavaUCallExpression(
override val psi: PsiMethodCallExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UCallExpression, UElementWithLocation {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UCallExpression, UElementWithLocation {
override val kind: UastCallKind
get() = UastCallKind.METHOD_CALL
@@ -59,10 +60,12 @@ class JavaUCallExpression(
override val receiver: UExpression?
get() {
return if (uastParent is UQualifiedReferenceExpression && uastParent.selector == this)
uastParent.receiver
else
null
uastParent.let { uastParent ->
return if (uastParent is UQualifiedReferenceExpression && uastParent.selector == this)
uastParent.receiver
else
null
}
}
override val receiverType: PsiType?
@@ -97,8 +100,8 @@ class JavaUCallExpression(
class JavaConstructorUCallExpression(
override val psi: PsiNewExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UCallExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UCallExpression {
override val kind by lz {
when {
psi.arrayInitializer != null -> UastCallKind.NEW_ARRAY_WITH_INITIALIZER
@@ -118,7 +121,7 @@ class JavaConstructorUCallExpression(
override val classReference by lz {
psi.classReference?.let { ref ->
JavaConverter.convertReference(ref, { this }, null) as? UReferenceExpression
JavaConverter.convertReference(ref, this, null) as? UReferenceExpression
}
}
@@ -157,8 +160,8 @@ class JavaConstructorUCallExpression(
class JavaArrayInitializerUCallExpression(
override val psi: PsiArrayInitializerExpression,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UCallExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UCallExpression {
override val methodIdentifier: UIdentifier?
get() = null
@@ -194,8 +197,8 @@ class JavaArrayInitializerUCallExpression(
class JavaAnnotationArrayInitializerUCallExpression(
override val psi: PsiArrayInitializerMemberValue,
override val uastParent: UElement?
) : JavaAbstractUExpression(), UCallExpression {
givenParent: UElement?
) : JavaAbstractUExpression(givenParent), UCallExpression {
override val kind: UastCallKind
get() = UastCallKind.NESTED_ARRAY_INITIALIZER
@@ -212,7 +215,7 @@ class JavaAnnotationArrayInitializerUCallExpression(
override val valueArguments by lz {
psi.initializers.map {
JavaConverter.convertPsiElement(it, { this }) as? UExpression ?: UnknownJavaExpression(it, this)
JavaConverter.convertPsiElement(it, this) as? UExpression ?: UnknownJavaExpression(it, this)
}
}
@@ -0,0 +1,51 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.uast.test.java
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import junit.framework.TestCase
import org.jetbrains.uast.toUElement
import org.junit.Test
class JavaUastPerformanceTest : LightCodeInsightFixtureTestCase() {
class EachPsiToUastWalker : PsiElementVisitor() {
var totalCount = 0
var identityChecksum = 0
override fun visitElement(element: PsiElement) {
val uElement = element.toUElement()
if (uElement != null) {
totalCount++
identityChecksum = 31 * identityChecksum + System.identityHashCode(uElement)
}
element.acceptChildren(this)
}
}
@Test
fun testVeryLongQualifiedReferenceExpression() {
val expectedUElementsCount = 4019
val clazz = myFixture.addClass("""
class MyClass {
String foo(){
return new java.lang.StringBuilder()
${(1..1000).joinToString("\n") { ".append(\"$it\")" }}
.toString();
}
}
""".trimIndent())
val nonCachedWalk = EachPsiToUastWalker().apply {
PlatformTestUtil.startPerformanceTest("convert each element to uast first time", 4000) {
clazz.accept(this)
TestCase.assertEquals(expectedUElementsCount, totalCount)
}.attempts(1).assertTiming()
}
}
}