Better diagnostic for Element has no prototype error

This commit is contained in:
Valentin Kipyatkov
2014-10-08 11:01:35 +04:00
parent 0213d37d82
commit 5008682bef
3 changed files with 40 additions and 12 deletions
+11 -4
View File
@@ -46,6 +46,8 @@ fun CodeBuilder.append(elements: Collection<Element>, separator: String, prefix:
return append(elements.filter { !it.isEmpty }.map { { append(it) } }, separator, prefix, suffix)
}
class ElementCreationStackTraceRequiredException : RuntimeException()
class CodeBuilder(private val topElement: PsiElement?) {
private val builder = StringBuilder()
private var endOfLineCommentAtEnd = false
@@ -81,10 +83,15 @@ class CodeBuilder(private val topElement: PsiElement?) {
if (element.isEmpty) return this // do not insert comment and spaces for empty elements to avoid multiple blank lines
if (element.prototypes == null && topElement != null) {
val s = "Element $element has no prototypes assigned.\n" +
"Use Element.assignPrototype() or Element.assignNoPrototype().\n" +
"Element created at:\n${element.createdAt}"
throw RuntimeException(s)
if (element.createdAt == null) {
throw ElementCreationStackTraceRequiredException()
}
else {
val s = "Element $element has no prototypes assigned.\n" +
"Use Element.assignPrototype() or Element.assignNoPrototype().\n" +
"Element created at:\n${element.createdAt}"
throw RuntimeException(s)
}
}
if (topElement == null || element.prototypes!!.isEmpty()) {
+20 -7
View File
@@ -99,14 +99,27 @@ public class Converter private(val project: Project,
State(state.methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory, state.specialContext, state.importList, importsToAdd))
public fun elementToKotlin(element: PsiElement): String {
val converted = convertTopElement(element) ?: return ""
val builder = CodeBuilder(element)
builder.append(converted)
if (postProcessor != null) {
return AfterConversionPass(project, postProcessor).run(builder.result)
try {
val converted = convertTopElement(element) ?: return ""
val builder = CodeBuilder(element)
builder.append(converted)
if (postProcessor != null) {
return AfterConversionPass(project, postProcessor).run(builder.result)
}
else {
return builder.result
}
}
else {
return builder.result
catch(e: ElementCreationStackTraceRequiredException) {
// if we got this exception then we need to turn element creation stack traces on to get better diagnostic
Element.saveCreationStacktraces = true
try {
return elementToKotlin(element)
}
finally {
Element.saveCreationStacktraces = false
}
}
}
+9 -1
View File
@@ -67,7 +67,11 @@ abstract class Element {
$prototypes = value
}
public var createdAt: String = "Element creation stacktraces turned off. Uncomment initializer of Element.createdAt." //Exception().getStackTrace().joinToString("\n")
public var createdAt: String?
= if (saveCreationStacktraces)
Exception().getStackTrace().joinToString("\n")
else
null
/** This method should not be used anywhere except for CodeBuilder! Use CodeBuilder.append instead. */
public abstract fun generateCode(builder: CodeBuilder)
@@ -80,4 +84,8 @@ abstract class Element {
override fun generateCode(builder: CodeBuilder) { }
override val isEmpty: Boolean get() = true
}
class object {
var saveCreationStacktraces = false
}
}