Safe reporting PSI elements in KEWA
This commit is contained in:
committed by
teamcity
parent
20871dd555
commit
5dc2442872
+4
-4
@@ -57,12 +57,12 @@ object DecompiledLightClassesFactory {
|
||||
innerClass != null,
|
||||
{ "Could not find corresponding inner/nested class " + relativeFqName + " in class " + decompiledClassOrObject.fqName + "\nFile: " + decompiledClassOrObject.containingKtFile.virtualFile.name },
|
||||
{
|
||||
it.withAttachment("decompiledClassOrObject.txt", decompiledClassOrObject.text)
|
||||
it.withPsiAttachment("decompiledClassOrObject.txt", decompiledClassOrObject)
|
||||
it.withAttachment("fileClass.txt", decompiledClassOrObject.containingFile::class)
|
||||
it.withAttachment("file.txt", decompiledClassOrObject.containingFile.text)
|
||||
it.withAttachment("root.txt", rootLightClassForDecompiledFile.text)
|
||||
it.withPsiAttachment("file.txt", decompiledClassOrObject.containingFile)
|
||||
it.withPsiAttachment("root.txt", rootLightClassForDecompiledFile)
|
||||
it.withAttachment("currentName.txt", current.name)
|
||||
it.withAttachment("current.txt", current.text)
|
||||
it.withPsiAttachment("current.txt", current)
|
||||
it.withAttachment("innerClasses.txt", current.innerClasses.map { psiClass -> psiClass.name })
|
||||
it.withAttachment("innerName.txt", name.asString())
|
||||
},
|
||||
|
||||
@@ -156,7 +156,7 @@ object LightClassUtil {
|
||||
checkWithAttachment(parent.parent is KtClassOrObject, {
|
||||
"Bad parent: ${parent.parent?.javaClass}"
|
||||
}) {
|
||||
it.withAttachment("parent", parent.text)
|
||||
it.withPsiAttachment("parent", parent)
|
||||
}
|
||||
return (parent.parent as KtClassOrObject).toLightClass()
|
||||
}
|
||||
|
||||
@@ -21,9 +21,7 @@ public class CompilationException extends KotlinExceptionWithAttachments {
|
||||
cause);
|
||||
this.element = element;
|
||||
|
||||
if (element != null) {
|
||||
withAttachment("element.kt", element.getText());
|
||||
}
|
||||
withPsiAttachment("element.kt", element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -174,7 +174,7 @@ public class PackageCodegenImpl implements PackageCodegen {
|
||||
if (fragment == null) {
|
||||
LOG.error(new KotlinExceptionWithAttachments(
|
||||
"package fragment is not found for module:" + state.getModule() + " file:" + file)
|
||||
.withAttachment("file.kt", file.getText()));
|
||||
.withPsiAttachment("file.kt", file));
|
||||
} else if (!expectedPackageFqName.equals(fragment.getFqName())) {
|
||||
LOG.error("expected package fq name: " + expectedPackageFqName + ", actual: " + fragment.getFqName());
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public class CodegenBinding {
|
||||
Type result = asmTypeForAnonymousClassOrNull(bindingContext, expression);
|
||||
if (result == null) {
|
||||
throw new KotlinExceptionWithAttachments("Couldn't compute ASM type for expression")
|
||||
.withAttachment("expression.kt", PsiUtilsKt.getElementTextWithContext(expression));
|
||||
.withPsiAttachment("expression.kt", expression);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -42,7 +42,7 @@ class MainFunctionDetector {
|
||||
this.getFunctionDescriptor = { function ->
|
||||
bindingContext.get(BindingContext.FUNCTION, function)
|
||||
?: throw throw KotlinExceptionWithAttachments("No descriptor resolved for $function")
|
||||
.withAttachment("function.text", function.text)
|
||||
.withPsiAttachment("function.text", function)
|
||||
}
|
||||
this.languageVersionSettings = languageVersionSettings
|
||||
}
|
||||
|
||||
+2
-2
@@ -146,13 +146,13 @@ fun getEnclosingDescriptor(context: BindingContext, element: KtElement): Declara
|
||||
val declaration =
|
||||
element.getParentOfTypeCodeFragmentAware(KtNamedDeclaration::class.java)
|
||||
?: throw KotlinExceptionWithAttachments("No parent KtNamedDeclaration for of type ${element.javaClass}")
|
||||
.withAttachment("element.kt", element.text)
|
||||
.withPsiAttachment("element.kt", element)
|
||||
return if (declaration is KtFunctionLiteral) {
|
||||
getEnclosingDescriptor(context, declaration)
|
||||
} else {
|
||||
context.get(DECLARATION_TO_DESCRIPTOR, declaration)
|
||||
?: throw KotlinExceptionWithAttachments("No descriptor for named declaration of type ${declaration.javaClass}")
|
||||
.withAttachment("declaration.kt", declaration.text)
|
||||
.withPsiAttachment("declaration.kt", declaration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -626,8 +626,8 @@ class PSICallResolver(
|
||||
}
|
||||
if (allValueArguments.isEmpty()) {
|
||||
throw KotlinExceptionWithAttachments("Can not find an external argument for 'set' method")
|
||||
.withAttachment("callElement.kt", oldCall.callElement.text)
|
||||
.withAttachment("file.kt", oldCall.callElement.takeIf { it.isValid }?.containingFile?.text ?: "<no file>")
|
||||
.withPsiAttachment("callElement.kt", oldCall.callElement)
|
||||
.withPsiAttachment("file.kt", oldCall.callElement.takeIf { it.isValid }?.containingFile)
|
||||
}
|
||||
allValueArguments.last()
|
||||
} else {
|
||||
|
||||
@@ -24,6 +24,6 @@ class NoDescriptorForDeclarationException @JvmOverloads constructor(declaration:
|
||||
+ (additionalDetails?.let { "\n---------------------------------------------------\n$it" } ?: "")
|
||||
) {
|
||||
init {
|
||||
withAttachment("declaration.kt", declaration.getElementTextWithContext())
|
||||
withPsiAttachment("declaration.kt", declaration)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -252,7 +252,7 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
|
||||
// This trows AssertionError in CLI and reports the error in the IDE
|
||||
LOG.error(
|
||||
new KotlinExceptionWithAttachments("Exception while analyzing expression" + location, e)
|
||||
.withAttachment("expression.kt", expression.getText())
|
||||
.withPsiAttachment("expression.kt", expression)
|
||||
);
|
||||
}
|
||||
catch (AssertionError errorFromLogger) {
|
||||
|
||||
@@ -15,13 +15,6 @@ class KotlinFrontEndException(message: String, cause: Throwable) : KotlinExcepti
|
||||
cause: Throwable,
|
||||
element: PsiElement
|
||||
) : this(getExceptionMessage("Front-end", message, cause, PsiDiagnosticUtils.atLocation(element)), cause) {
|
||||
withAttachment(
|
||||
"element.kt",
|
||||
if (element.isValid) {
|
||||
element.text
|
||||
} else {
|
||||
"PsiElement (invalid): " + element.toString()
|
||||
}
|
||||
)
|
||||
withPsiAttachment("element.kt", element)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class KtDotQualifiedExpression : KtExpressionImplStub<KotlinPlaceHolderStub<KtDo
|
||||
LOG.error(
|
||||
KotlinExceptionWithAttachments(
|
||||
"Invalid stub structure. DOT_QUALIFIED_EXPRESSION must have one or two children. Was: ${expressions.size}\n"
|
||||
).withAttachment("file.kt", containingFile.text)
|
||||
).withPsiAttachment("file.kt", containingFile)
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
||||
checkWithAttachment(declarations.size == 1, { "unexpected ${declarations.size} declarations" }) {
|
||||
it.withAttachment("text.kt", text)
|
||||
for (d in declarations.withIndex()) {
|
||||
it.withAttachment("declaration${d.index}.kt", d.value.text)
|
||||
it.withPsiAttachment("declaration${d.index}.kt", d.value)
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi.psiUtil
|
||||
|
||||
import com.intellij.injected.editor.VirtualFileWindow
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.*
|
||||
@@ -381,29 +380,7 @@ fun PsiElement.startsWithComment(): Boolean = firstChild is PsiComment
|
||||
|
||||
// ---------------------------------- Debug/logging ----------------------------------------------------------------------------------------
|
||||
|
||||
fun PsiElement.getElementTextWithContext(): String {
|
||||
if (!isValid) return "<invalid element $this>"
|
||||
|
||||
if (this is PsiFile) {
|
||||
return containingFile.text
|
||||
}
|
||||
|
||||
// Find parent for element among file children
|
||||
val topLevelElement = PsiTreeUtil.findFirstParent(this, { it.parent is PsiFile })
|
||||
?: throw AssertionError("For non-file element we should always be able to find parent in file children")
|
||||
|
||||
val startContextOffset = topLevelElement.startOffset
|
||||
val elementContextOffset = textRange.startOffset
|
||||
|
||||
val inFileParentOffset = elementContextOffset - startContextOffset
|
||||
|
||||
|
||||
val isInjected = containingFile is VirtualFileWindow
|
||||
return StringBuilder(topLevelElement.text)
|
||||
.insert(inFileParentOffset, "<caret>")
|
||||
.insert(0, "File name: ${containingFile.name} Physical: ${containingFile.isPhysical} Injected: $isInjected\n")
|
||||
.toString()
|
||||
}
|
||||
fun PsiElement.getElementTextWithContext(): String = org.jetbrains.kotlin.utils.getElementTextWithContext(this)
|
||||
|
||||
fun PsiElement.getTextWithLocation(): String = "'${this.text}' at ${PsiDiagnosticUtils.atLocation(this)}"
|
||||
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.utils
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Attachment
|
||||
import com.intellij.openapi.diagnostic.ExceptionWithAttachments
|
||||
import java.nio.charset.StandardCharsets
|
||||
import com.intellij.psi.*
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@@ -38,6 +40,12 @@ open class KotlinExceptionWithAttachments : RuntimeException, ExceptionWithAttac
|
||||
attachments.add(Attachment(name, content?.toString() ?: "<null>"))
|
||||
return this
|
||||
}
|
||||
|
||||
fun withPsiAttachment(name: String, element: PsiElement?): KotlinExceptionWithAttachments {
|
||||
kotlin.runCatching { ApplicationManager.getApplication().runReadAction<String> { element?.let(::getElementTextWithContext) } }
|
||||
.getOrNull()?.let { withAttachment(name, it) }
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,4 +58,4 @@ inline fun checkWithAttachment(value: Boolean, lazyMessage: () -> String, attach
|
||||
attachments(e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.utils
|
||||
|
||||
import com.intellij.injected.editor.VirtualFileWindow
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
fun getElementTextWithContext(psiElement: PsiElement): String {
|
||||
if (!psiElement.isValid) return "<invalid element $psiElement>"
|
||||
|
||||
if (psiElement is PsiFile) {
|
||||
return psiElement.containingFile.text
|
||||
}
|
||||
|
||||
// Find parent for element among file children
|
||||
val topLevelElement = PsiTreeUtil.findFirstParent(psiElement) { it.parent is PsiFile }
|
||||
?: throw AssertionError("For non-file element we should always be able to find parent in file children")
|
||||
|
||||
val startContextOffset = topLevelElement.textRange.startOffset
|
||||
val elementContextOffset = psiElement.textRange.startOffset
|
||||
|
||||
val inFileParentOffset = elementContextOffset - startContextOffset
|
||||
|
||||
|
||||
val containingFile = psiElement.containingFile
|
||||
val isInjected = containingFile is VirtualFileWindow
|
||||
return StringBuilder(topLevelElement.text)
|
||||
.insert(inFileParentOffset, "<caret>")
|
||||
.insert(0, "File name: ${containingFile.name} Physical: ${containingFile.isPhysical} Injected: $isInjected\n")
|
||||
.toString()
|
||||
}
|
||||
Reference in New Issue
Block a user