From fc517baac7ba381f0f4f2529e59700b1191dd0ce Mon Sep 17 00:00:00 2001
From: Simon Ogorodnik <Simon.Ogorodnik@jetbrains.com>
Date: Wed, 10 Jan 2018 21:56:20 +0300
Subject: Fix crash on incorrect sample conversion

---
 .../KotlinWebsiteSampleProcessingService.kt        | 48 ++++++++++++++++++++--
 1 file changed, 45 insertions(+), 3 deletions(-)

(limited to 'core/src/main/kotlin/Samples')

diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt
index b5801457..b12e3a66 100644
--- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt
+++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt
@@ -1,15 +1,18 @@
 package org.jetbrains.dokka.Samples
 
 import com.google.inject.Inject
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.*
 import com.intellij.psi.impl.source.tree.LeafPsiElement
 import com.intellij.psi.util.PsiTreeUtil
 import org.jetbrains.dokka.*
 import org.jetbrains.kotlin.psi.*
 import org.jetbrains.kotlin.psi.psiUtil.allChildren
 import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
 import org.jetbrains.kotlin.resolve.ImportPath
+import java.io.PrintWriter
+import java.io.StringWriter
+
 
 open class KotlinWebsiteSampleProcessingService
 @Inject constructor(dokkaConfiguration: DokkaConfiguration,
@@ -22,6 +25,10 @@ open class KotlinWebsiteSampleProcessingService
         val text: String
             get() = builder.toString()
 
+        val errors = mutableListOf<ConvertError>()
+
+        data class ConvertError(val e: Exception, val text: String, val loc: String)
+
         fun KtValueArgument.extractStringArgumentValue() =
                 (getArgumentExpression() as KtStringTemplateExpression)
                         .entries.joinToString("") { it.text }
@@ -92,16 +99,51 @@ open class KotlinWebsiteSampleProcessingService
             }
         }
 
+        private fun reportProblemConvertingElement(element: PsiElement, e: Exception) {
+            val text = element.text
+            val document = PsiDocumentManager.getInstance(element.project).getDocument(element.containingFile)
+
+            val lineInfo = if (document != null) {
+                val lineNumber = document.getLineNumber(element.startOffset)
+                "$lineNumber, ${element.startOffset - document.getLineStartOffset(lineNumber)}"
+            } else {
+                "offset: ${element.startOffset}"
+            }
+            errors += ConvertError(e, text, lineInfo)
+        }
+
         override fun visitElement(element: PsiElement) {
             if (element is LeafPsiElement)
                 builder.append(element.text)
-            super.visitElement(element)
+
+            element.acceptChildren(object : PsiElementVisitor() {
+                override fun visitElement(element: PsiElement) {
+                    try {
+                        element.accept(this@SampleBuilder)
+                    } catch (e: Exception) {
+                        try {
+                            reportProblemConvertingElement(element, e)
+                        } finally {
+                            builder.append(element.text) //recover
+                        }
+                    }
+                }
+            })
         }
+
     }
 
     private fun PsiElement.buildSampleText(): String {
         val sampleBuilder = SampleBuilder()
         this.accept(sampleBuilder)
+
+        sampleBuilder.errors.forEach {
+            val sw = StringWriter()
+            val pw = PrintWriter(sw)
+            it.e.printStackTrace(pw)
+
+            logger.error("${containingFile.name}: (${it.loc}): Exception thrown while converting \n```\n${it.text}\n```\n$sw")
+        }
         return sampleBuilder.text
     }
 
-- 
cgit