diff --git a/uast/uast-common/src/org/jetbrains/uast/UastLanguagePlugin.kt b/uast/uast-common/src/org/jetbrains/uast/UastLanguagePlugin.kt index 5ba2e4b943e0..80d25b33021e 100644 --- a/uast/uast-common/src/org/jetbrains/uast/UastLanguagePlugin.kt +++ b/uast/uast-common/src/org/jetbrains/uast/UastLanguagePlugin.kt @@ -118,6 +118,7 @@ inline fun UastLanguagePlugin.convertOpt(element: PsiElem return convertElement(element, parent) as? T } +@Deprecated("will throw exception if conversion fails", ReplaceWith("convertOpt")) inline fun UastLanguagePlugin.convert(element: PsiElement, parent: UElement?): T { return convertElement(element, parent, T::class.java) as T } diff --git a/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt b/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt index 2c2eecd78ed4..8f2ba45afacd 100644 --- a/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt +++ b/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt @@ -182,6 +182,7 @@ tailrec fun UElement.getUastContext(): UastContext { return (uastParent ?: error("PsiElement should exist at least for UFile")).getUastContext() } +@Deprecated("could unexpectedly throw exception", ReplaceWith("UastFacade.findPlugin")) tailrec fun UElement.getLanguagePlugin(): UastLanguagePlugin { val psi = this.sourcePsi if (psi != null) { diff --git a/uast/uast-common/src/org/jetbrains/uast/declarations/UClass.kt b/uast/uast-common/src/org/jetbrains/uast/declarations/UClass.kt index cef00af76714..316cf335379f 100644 --- a/uast/uast-common/src/org/jetbrains/uast/declarations/UClass.kt +++ b/uast/uast-common/src/org/jetbrains/uast/declarations/UClass.kt @@ -1,8 +1,11 @@ // Copyright 2000-2019 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 +import com.intellij.openapi.diagnostic.Attachment +import com.intellij.openapi.diagnostic.Logger import com.intellij.psi.PsiAnonymousClass import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.internal.log import org.jetbrains.uast.visitor.UastTypedVisitor @@ -39,17 +42,39 @@ interface UClass : UDeclaration, PsiClass { */ val uastDeclarations: List + private inline fun convertOrReport(psiElement: PsiElement, parent: UElement): T? = + convertOrReport(psiElement, parent, T::class.java) + + private fun convertOrReport(psiElement: PsiElement, parent: UElement, expectedType: Class): T? { + fun getInfoString() = buildString { + appendln("context:${this@UClass.javaClass}") + appendln("psiElement:${psiElement.javaClass}") + appendln("psiElementContent:${runCatching { psiElement.text }}") + } + + val plugin = this.sourcePsi?.let { UastFacade.findPlugin(it) } ?: UastFacade.findPlugin(psiElement) + if (plugin == null) { + LOG.error("cant get UAST plugin for $this to convert element $psiElement", Attachment("info.txt", getInfoString())) + return null + } + val result = expectedType.cast(plugin.convertElement(psiElement, parent, expectedType)) + if (result == null) { + LOG.error("failed to convert element $psiElement in $this", Attachment("info.txt", getInfoString())) + } + return result + } + override fun getFields(): Array = - javaPsi.fields.map { getLanguagePlugin().convert(it, this) }.toTypedArray() + javaPsi.fields.mapNotNull { convertOrReport(it, this) }.toTypedArray() override fun getInitializers(): Array = - javaPsi.initializers.map { getLanguagePlugin().convert(it, this) }.toTypedArray() + javaPsi.initializers.mapNotNull { convertOrReport(it, this) }.toTypedArray() override fun getMethods(): Array = - javaPsi.methods.map { getLanguagePlugin().convert(it, this) }.toTypedArray() + javaPsi.methods.mapNotNull { convertOrReport(it, this) }.toTypedArray() override fun getInnerClasses(): Array = - javaPsi.innerClasses.map { getLanguagePlugin().convert(it, this) }.toTypedArray() + javaPsi.innerClasses.mapNotNull { convertOrReport(it, this) }.toTypedArray() override fun asLogString(): String = log("name = $name") @@ -85,6 +110,8 @@ interface UClass : UDeclaration, PsiClass { visitor.visitClass(this, data) } +private val LOG = Logger.getInstance(UClass::class.java) + interface UAnonymousClass : UClass, PsiAnonymousClass { override val psi: PsiAnonymousClass }