From 5668a7af924a1e09d0e94d82f2d1645037cd5461 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Mon, 15 Jan 2018 22:49:58 +0900 Subject: [PATCH] Kapt: Replace original Javac diagnostic messages with those with Kotlin location mapped There is no Messages dialog in newer versions of IDEA/Android Studio in which the error messages were mapped before. The new Build window shows only the original locations, so now we need to replace Java file diagnostics with ones mapped to Kotlin source files. The side effect is that diagnostics on the same locations are automatically merged. --- .../android/KotlinOutputParserHelper.kt | 22 +-------- .../kotlin/kapt3/javac/KaptJavaLog.kt | 47 +++++++++++++++---- .../kapt3/stubs/KaptLineMappingCollector.kt | 20 +++----- .../kapt3/test/AbstractKotlinKapt3Test.kt | 42 ++++++++++++++--- .../converter/errorLocationMapping.kt | 25 ++++------ .../testData/converter/invalidFieldName.kt | 4 +- .../testData/converter/maxErrorCount.kt | 2 +- .../testData/converter/strangeIdentifiers.kt | 2 +- 8 files changed, 95 insertions(+), 69 deletions(-) diff --git a/idea/idea-android/idea-android-output-parser/src/org/jetbrains/kotlin/android/KotlinOutputParserHelper.kt b/idea/idea-android/idea-android-output-parser/src/org/jetbrains/kotlin/android/KotlinOutputParserHelper.kt index dd29e184431..18136cc8a6e 100644 --- a/idea/idea-android/idea-android-output-parser/src/org/jetbrains/kotlin/android/KotlinOutputParserHelper.kt +++ b/idea/idea-android/idea-android-output-parser/src/org/jetbrains/kotlin/android/KotlinOutputParserHelper.kt @@ -57,9 +57,8 @@ fun parse(lineText: String, reader: OutputLineReader, messages: MutableList= 2) matcher.group(2)?.toInt() ?: 1 else 1 if (line != null) { - val mainPosition = SourceFilePosition(file, SourcePosition(line, column, column)) - val kotlinKaptPosition = findAdditionalKotlinLocationFromKapt(message) - return addMessage(Message(getMessageKind(severity), message.trim(), kotlinKaptPosition ?: mainPosition), messages) + val position = SourceFilePosition(file, SourcePosition(line, column, column)) + return addMessage(Message(getMessageKind(severity), message.trim(), position), messages) } } @@ -73,26 +72,9 @@ fun parse(lineText: String, reader: OutputLineReader, messages: MutableList @@ -67,10 +65,9 @@ class KaptLineMappingCollector(private val kaptContext: KaptContext<*>) { val fqName = ois.readUTF() val path = ois.readUTF() val isRelative = ois.readBoolean() - val line = ois.readInt() - val column = ois.readInt() + val pos = ois.readInt() - lineInfo[fqName] = KotlinPosition(path, isRelative, line, column) + lineInfo[fqName] = KotlinPosition(path, isRelative, pos) } val signatureCount = ois.readInt() @@ -119,13 +116,9 @@ class KaptLineMappingCollector(private val kaptContext: KaptContext<*>) { private fun register(fqName: String, psiElement: PsiElement) { val textRange = psiElement.textRange ?: return - val psiFile = psiElement.containingFile - val lineAndColumn = DiagnosticUtils.getLineAndColumnInPsiFile(psiFile, textRange) - if (lineAndColumn.line >= 0 && lineAndColumn.column >= 0) { - val (path, isRelative) = getFilePathRelativePreferred(psiFile) - lineInfo[fqName] = KotlinPosition(path, isRelative, lineAndColumn.line, lineAndColumn.column) - } + val (path, isRelative) = getFilePathRelativePreferred(psiElement.containingFile) + lineInfo[fqName] = KotlinPosition(path, isRelative, textRange.startOffset) } private fun getFilePathRelativePreferred(file: PsiFile): Pair { @@ -156,8 +149,7 @@ class KaptLineMappingCollector(private val kaptContext: KaptContext<*>) { oos.writeUTF(fqName) oos.writeUTF(kotlinPosition.path) oos.writeBoolean(kotlinPosition.isRelativePath) - oos.writeInt(kotlinPosition.line) - oos.writeInt(kotlinPosition.column) + oos.writeInt(kotlinPosition.pos) } oos.writeInt(signatureInfo.size) diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt index 94d02a0f10e..2efd04769df 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt @@ -17,16 +17,20 @@ package org.jetbrains.kotlin.kapt3.test import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.psi.PsiManager import com.sun.tools.javac.comp.CompileStates import com.sun.tools.javac.tree.JCTree.JCCompilationUnit import com.sun.tools.javac.util.JCDiagnostic import com.sun.tools.javac.util.Log import junit.framework.TestCase +import org.jetbrains.kotlin.checkers.CheckerTestUtil import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.codegen.CodegenTestCase +import org.jetbrains.kotlin.codegen.CodegenTestFiles import org.jetbrains.kotlin.codegen.GenerationUtils import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.kapt3.Kapt3BuilderFactory @@ -38,6 +42,7 @@ import org.jetbrains.kotlin.kapt3.parseJavaFiles import org.jetbrains.kotlin.kapt3.prettyPrint import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter import org.jetbrains.kotlin.kapt3.util.KaptLogger +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension import org.jetbrains.kotlin.test.ConfigurationKind @@ -65,6 +70,26 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() { } } + override fun loadMultiFiles(files: List) { + val project = myEnvironment.project + val psiManager = PsiManager.getInstance(project) + + val tmpDir = Files.createTempDirectory("kaptTest").toFile() + tempFiles += tmpDir + + val ktFiles = ArrayList(files.size) + for (file in files.sorted()) { + if (file.name.endsWith(".kt")) { + val content = CheckerTestUtil.parseDiagnosedRanges(file.content, ArrayList(0)) + val tmpKtFile = File(tmpDir, file.name).apply { writeText(content) } + val virtualFile = StandardFileSystems.local().findFileByPath(tmpKtFile.path) ?: error("Can't find ${file.name}") + ktFiles.add(psiManager.findFile(virtualFile) as? KtFile ?: error("Can't load ${file.name}")) + } + } + + myFiles = CodegenTestFiles.create(ktFiles) + } + override fun doMultiFileTest(wholeFile: File, files: List, javaFilesDir: File?) { val javaSources = javaFilesDir?.let { arrayOf(it) } ?: emptyArray() @@ -102,7 +127,7 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() { throw RuntimeException(e) } finally { javaFiles.forEach { it.delete() } - tempFiles.forEach { it.delete() } + tempFiles.forEach { if (it.isFile) it.delete() else it.deleteRecursively() } tempFiles.clear() kaptContext.close() } @@ -213,13 +238,16 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test( val actualErrors = log.reportedDiagnostics .filter { it.type == JCDiagnostic.DiagnosticType.ERROR } .map { - val location = it.subdiagnostics - .firstOrNull { it.getMessage(Locale.US).startsWith("Kotlin location:") } - ?.getMessage(Locale.US) + // Unfortunately, we can't use the file name as it can contain temporary prefix + val name = it.source?.name?.substringAfterLast("/") ?: "" + val kind = when (name.substringAfterLast(".").toLowerCase()) { + "kt" -> "kotlin" + "java" -> "java" + else -> "other" + } - val javaLocation = "(${it.lineNumber};${it.columnNumber}) " - val message = javaLocation + it.getMessage(Locale.US).lines().first() - if (location != null) "$message ($location)" else message + val javaLocation = "($kind:${it.lineNumber}:${it.columnNumber}) " + javaLocation + it.getMessage(Locale.US).lines().first() } .map { "// " + EXPECTED_ERROR + it } .sorted() diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/errorLocationMapping.kt b/plugins/kapt3/kapt3-compiler/testData/converter/errorLocationMapping.kt index 00b737ab144..ba36685d1aa 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/errorLocationMapping.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/errorLocationMapping.kt @@ -1,21 +1,14 @@ // CORRECT_ERROR_TYPES -// EXPECTED_ERROR(11;12) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (34, 5)) -// EXPECTED_ERROR(11;34) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (26, 62)) -// EXPECTED_ERROR(19;18) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (26, 50)) -// EXPECTED_ERROR(23;18) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (33, 5)) -// EXPECTED_ERROR(24;33) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (26, 62)) -// EXPECTED_ERROR(28;5) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (33, 5)) -// EXPECTED_ERROR(30;5) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (26, 34)) -// EXPECTED_ERROR(31;30) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (26, 34)) -// EXPECTED_ERROR(32;18) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (34, 5)) -// EXPECTED_ERROR(37;5) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (34, 5)) -// EXPECTED_ERROR(45;5) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (37, 5)) -// EXPECTED_ERROR(50;5) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (39, 5)) -// EXPECTED_ERROR(5;11) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (23, 1)) -// EXPECTED_ERROR(60;18) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (42, 5)) -// EXPECTED_ERROR(9;12) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (33, 5)) -// EXPECTED_ERROR(9;19) cannot find symbol (Kotlin location: /errorLocationMapping.kt: (26, 50)) +// EXPECTED_ERROR(kotlin:16:1) cannot find symbol +// EXPECTED_ERROR(kotlin:19:34) cannot find symbol +// EXPECTED_ERROR(kotlin:19:50) cannot find symbol +// EXPECTED_ERROR(kotlin:19:62) cannot find symbol +// EXPECTED_ERROR(kotlin:26:5) cannot find symbol +// EXPECTED_ERROR(kotlin:27:5) cannot find symbol +// EXPECTED_ERROR(kotlin:30:5) cannot find symbol +// EXPECTED_ERROR(kotlin:32:5) cannot find symbol +// EXPECTED_ERROR(kotlin:35:5) cannot find symbol @file:Suppress("UNRESOLVED_REFERENCE", "ANNOTATION_PARAMETER_MUST_BE_CONST", "NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION") import kotlin.reflect.KClass diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/invalidFieldName.kt b/plugins/kapt3/kapt3-compiler/testData/converter/invalidFieldName.kt index 0a9c3d361b1..d340bbc4ad1 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/invalidFieldName.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/invalidFieldName.kt @@ -1,5 +1,5 @@ -// EXPECTED_ERROR(-1;-1) 'WHI-TE' is an invalid Java enum value name -// EXPECTED_ERROR(6;20) cannot find symbol (Kotlin location: /invalidFieldName.kt: (8, 1)) +// EXPECTED_ERROR(kotlin:8:1) cannot find symbol +// EXPECTED_ERROR(other:-1:-1) 'WHI-TE' is an invalid Java enum value name enum class Color { BLACK, `WHI-TE` diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/maxErrorCount.kt b/plugins/kapt3/kapt3-compiler/testData/converter/maxErrorCount.kt index d0b1d8e0b1e..2e4ddf3bea1 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/maxErrorCount.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/maxErrorCount.kt @@ -1,5 +1,5 @@ // CORRECT_ERROR_TYPES -// EXPECTED_ERROR(8;5) cannot find symbol (Kotlin location: /maxErrorCount.kt: (9, 5)) +// EXPECTED_ERROR(kotlin:9:5) cannot find symbol // JAVAC_OPTION -Xmaxerrs=1 @file:Suppress("UNRESOLVED_REFERENCE") diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/strangeIdentifiers.kt b/plugins/kapt3/kapt3-compiler/testData/converter/strangeIdentifiers.kt index 381ee920627..ecb0c2c4090 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/strangeIdentifiers.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/strangeIdentifiers.kt @@ -1,4 +1,4 @@ -// EXPECTED_ERROR(-1;-1) '60x60' is an invalid Java enum value name +// EXPECTED_ERROR(other:-1:-1) '60x60' is an invalid Java enum value name class `:)` { lateinit val f: String