Report declaration that was being analyzed when internal error happened

#KT-12188 Fixed
This commit is contained in:
Denis Zharkov
2016-07-04 18:15:08 +03:00
parent ea7496044e
commit 62e69af53c
5 changed files with 111 additions and 43 deletions
@@ -16,18 +16,16 @@
package org.jetbrains.kotlin.codegen;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.util.ExceptionUtilKt;
public class CompilationException extends RuntimeException {
private final PsiElement element;
public CompilationException(@NotNull String message, @Nullable Throwable cause, @Nullable PsiElement element) {
super(getMessage(message, cause, element), cause);
super(ExceptionUtilKt.getExceptionMessage("Back-end (JVM)", message, cause, element), cause);
this.element = element;
}
@@ -35,40 +33,4 @@ public class CompilationException extends RuntimeException {
public PsiElement getElement() {
return element;
}
private static String where(@NotNull Throwable cause) {
StackTraceElement[] stackTrace = cause.getStackTrace();
if (stackTrace != null && stackTrace.length > 0) {
return stackTrace[0].getFileName() + ":" + stackTrace[0].getLineNumber();
}
return "unknown";
}
public static String getMessage(@NotNull final String message, @Nullable final Throwable cause, @Nullable final PsiElement element) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
StringBuilder result =
new StringBuilder("Back-end (JVM) Internal error: ").append(message).append("\n");
if (cause != null) {
String causeMessage = cause.getMessage();
result.append("Cause: ").append(causeMessage == null ? cause.toString() : causeMessage).append("\n");
}
if (element != null) {
result.append("File being compiled and position: ").append(DiagnosticUtils.atLocation(element)).append("\n");
result.append("PsiElement: ").append(element.getText()).append("\n");
}
else {
result.append("Element is unknown");
}
if (cause != null) {
result.append("The root cause was thrown at: ").append(where(cause));
}
return result.toString();
}
});
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtVisitorVoid
import org.jetbrains.kotlin.util.KotlinFrontEndException
class ExceptionWrappingKtVisitorVoid(private val delegate: KtVisitorVoid) : KtVisitorVoid() {
override fun visitElement(element: PsiElement) {
element.accept(delegate)
}
override fun visitDeclaration(dcl: KtDeclaration) {
try {
dcl.accept(delegate)
} catch (e: KotlinFrontEndException) {
throw e
} catch (t: Throwable) {
throw KotlinFrontEndException("Failed to analyze declaration ${dcl.name}", t, dcl)
}
}
}
@@ -61,10 +61,12 @@ class LazyTopDownAnalyzer(
// fill in the context
for (declaration in declarations) {
declaration.accept(object : KtVisitorVoid() {
// The 'visitor' variable is used inside
var visitor: KtVisitorVoid? = null
visitor = ExceptionWrappingKtVisitorVoid(object : KtVisitorVoid() {
private fun registerDeclarations(declarations: List<KtDeclaration>) {
for (jetDeclaration in declarations) {
jetDeclaration.accept(this)
jetDeclaration.accept(visitor!!)
}
}
@@ -177,6 +179,8 @@ class LazyTopDownAnalyzer(
typeAliases.add(typeAlias)
}
})
declaration.accept(visitor)
}
createFunctionDescriptors(c, functions)
@@ -16,4 +16,12 @@
package org.jetbrains.kotlin.util
class KotlinFrontEndException(message: String, cause: Throwable) : RuntimeException(message, cause)
import com.intellij.psi.PsiElement
class KotlinFrontEndException(message: String, cause: Throwable) : RuntimeException(message, cause) {
constructor(
message: String,
cause: Throwable,
element: PsiElement
) : this(getExceptionMessage("Front-end", message, cause, element), cause)
}
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.util
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
fun getExceptionMessage(
subsystemName: String,
message: String,
cause: Throwable?,
element: PsiElement?
): String = ApplicationManager.getApplication().runReadAction<String> {
val result = StringBuilder(subsystemName + " Internal error: ").append(message).append("\n")
if (cause != null) {
val causeMessage = cause.message
result.append("Cause: ").append(causeMessage ?: cause.toString()).append("\n")
}
if (element != null) {
result.append("File being compiled and position: ").append(DiagnosticUtils.atLocation(element)).append("\n")
result.append("PsiElement: ").append(element.text).append("\n")
}
else {
result.append("Element is unknown")
}
if (cause != null) {
result.append("The root cause was thrown at: ").append(where(cause))
}
result.toString()
}
private fun where(cause: Throwable): String {
val stackTrace = cause.stackTrace
if (stackTrace != null && stackTrace.size > 0) {
return stackTrace[0].fileName + ":" + stackTrace[0].lineNumber
}
return "unknown"
}