[KAPT] Add experimental JDK 17 support
#KT-47583 Fixed
This commit is contained in:
@@ -15,10 +15,9 @@ import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
|||||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager
|
import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager
|
||||||
import org.jetbrains.kotlin.kapt3.base.incremental.SourcesToReprocess
|
import org.jetbrains.kotlin.kapt3.base.incremental.SourcesToReprocess
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaCompiler
|
import org.jetbrains.kotlin.kapt3.base.javac.*
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaFileManager
|
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.util.isJava17OrLater
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.isJava9OrLater
|
import org.jetbrains.kotlin.kapt3.base.util.isJava9OrLater
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.putJavacOption
|
import org.jetbrains.kotlin.kapt3.base.util.putJavacOption
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
@@ -30,7 +29,7 @@ open class KaptContext(val options: KaptOptions, val withJdk: Boolean, val logge
|
|||||||
val compiler: KaptJavaCompiler
|
val compiler: KaptJavaCompiler
|
||||||
val fileManager: KaptJavaFileManager
|
val fileManager: KaptJavaFileManager
|
||||||
private val javacOptions: Options
|
private val javacOptions: Options
|
||||||
val javaLog: KaptJavaLog
|
val javaLog: KaptJavaLogBase
|
||||||
val cacheManager: JavaClassCacheManager?
|
val cacheManager: JavaClassCacheManager?
|
||||||
|
|
||||||
val sourcesToReprocess: SourcesToReprocess
|
val sourcesToReprocess: SourcesToReprocess
|
||||||
@@ -38,12 +37,24 @@ open class KaptContext(val options: KaptOptions, val withJdk: Boolean, val logge
|
|||||||
protected open fun preregisterTreeMaker(context: Context) {}
|
protected open fun preregisterTreeMaker(context: Context) {}
|
||||||
|
|
||||||
private fun preregisterLog(context: Context) {
|
private fun preregisterLog(context: Context) {
|
||||||
val interceptorData = KaptJavaLog.DiagnosticInterceptorData()
|
val interceptorData = KaptJavaLogBase.DiagnosticInterceptorData()
|
||||||
context.put(Log.logKey, Context.Factory<Log> { newContext ->
|
context.put(Log.logKey, Context.Factory<Log> { newContext ->
|
||||||
KaptJavaLog(
|
if (isJava17OrLater()) {
|
||||||
options.projectBaseDir, newContext, logger.errorWriter, logger.warnWriter, logger.infoWriter,
|
newContext.put(Log.outKey, logger.infoWriter)
|
||||||
interceptorData, options[KaptFlag.MAP_DIAGNOSTIC_LOCATIONS]
|
val errKey = (Log::class.java.fields.firstOrNull() { it.name == "errKey" }
|
||||||
)
|
?: error("Can't find errKey field in Log.class")).get(null)
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
newContext.put(errKey as Context.Key<java.io.PrintWriter>, logger.errorWriter)
|
||||||
|
KaptJavaLog17(
|
||||||
|
options.projectBaseDir, newContext,
|
||||||
|
interceptorData, options[KaptFlag.MAP_DIAGNOSTIC_LOCATIONS]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
KaptJavaLog(
|
||||||
|
options.projectBaseDir, newContext, logger.errorWriter, logger.warnWriter, logger.infoWriter,
|
||||||
|
interceptorData, options[KaptFlag.MAP_DIAGNOSTIC_LOCATIONS]
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +165,7 @@ open class KaptContext(val options: KaptOptions, val withJdk: Boolean, val logge
|
|||||||
|
|
||||||
ClassReader.instance(context).saveParameterNames = true
|
ClassReader.instance(context).saveParameterNames = true
|
||||||
|
|
||||||
javaLog = compiler.log as KaptJavaLog
|
javaLog = compiler.log as KaptJavaLogBase
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
|||||||
@@ -17,7 +17,20 @@ import javax.tools.Diagnostic
|
|||||||
import javax.tools.JavaFileObject
|
import javax.tools.JavaFileObject
|
||||||
import javax.tools.JavaFileObject.Kind
|
import javax.tools.JavaFileObject.Kind
|
||||||
import javax.tools.SimpleJavaFileObject
|
import javax.tools.SimpleJavaFileObject
|
||||||
import com.sun.tools.javac.util.List as JavacList
|
|
||||||
|
interface KaptJavaLogBase {
|
||||||
|
val interceptorData: DiagnosticInterceptorData
|
||||||
|
|
||||||
|
val reportedDiagnostics: List<JCDiagnostic>
|
||||||
|
|
||||||
|
fun flush(kind: Log.WriterKind?)
|
||||||
|
|
||||||
|
fun flush()
|
||||||
|
|
||||||
|
class DiagnosticInterceptorData {
|
||||||
|
var files: Map<JavaFileObject, JCTree.JCCompilationUnit> = emptyMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class KaptJavaLog(
|
class KaptJavaLog(
|
||||||
private val projectBaseDir: File?,
|
private val projectBaseDir: File?,
|
||||||
@@ -25,9 +38,9 @@ class KaptJavaLog(
|
|||||||
errWriter: PrintWriter,
|
errWriter: PrintWriter,
|
||||||
warnWriter: PrintWriter,
|
warnWriter: PrintWriter,
|
||||||
noticeWriter: PrintWriter,
|
noticeWriter: PrintWriter,
|
||||||
val interceptorData: DiagnosticInterceptorData,
|
override val interceptorData: KaptJavaLogBase.DiagnosticInterceptorData,
|
||||||
private val mapDiagnosticLocations: Boolean
|
private val mapDiagnosticLocations: Boolean
|
||||||
) : Log(context, errWriter, warnWriter, noticeWriter) {
|
) : Log(context, errWriter, warnWriter, noticeWriter), KaptJavaLogBase {
|
||||||
private val stubLineInfo = KaptStubLineInformation()
|
private val stubLineInfo = KaptStubLineInformation()
|
||||||
private val javacMessages = JavacMessages.instance(context)
|
private val javacMessages = JavacMessages.instance(context)
|
||||||
|
|
||||||
@@ -35,7 +48,7 @@ class KaptJavaLog(
|
|||||||
context.put(Log.outKey, noticeWriter)
|
context.put(Log.outKey, noticeWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
val reportedDiagnostics: List<JCDiagnostic>
|
override val reportedDiagnostics: List<JCDiagnostic>
|
||||||
get() = _reportedDiagnostics
|
get() = _reportedDiagnostics
|
||||||
|
|
||||||
private val _reportedDiagnostics = mutableListOf<JCDiagnostic>()
|
private val _reportedDiagnostics = mutableListOf<JCDiagnostic>()
|
||||||
@@ -217,10 +230,6 @@ class KaptJavaLog(
|
|||||||
"compiler.err.not.def.public.cant.access"
|
"compiler.err.not.def.public.cant.access"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiagnosticInterceptorData {
|
|
||||||
var files: Map<JavaFileObject, JCTree.JCCompilationUnit> = emptyMap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val LINE_SEPARATOR: String = System.getProperty("line.separator")
|
private val LINE_SEPARATOR: String = System.getProperty("line.separator")
|
||||||
@@ -256,7 +265,7 @@ private fun JCDiagnostic.Factory.errorJava9Aware(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class KotlinFileObject(val file: File) : SimpleJavaFileObject(file.toURI(), Kind.SOURCE) {
|
/*private*/internal data class KotlinFileObject(val file: File) : SimpleJavaFileObject(file.toURI(), Kind.SOURCE) {
|
||||||
override fun openOutputStream() = file.outputStream()
|
override fun openOutputStream() = file.outputStream()
|
||||||
override fun openWriter() = file.writer()
|
override fun openWriter() = file.writer()
|
||||||
override fun openInputStream() = file.inputStream()
|
override fun openInputStream() = file.inputStream()
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 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.kapt3.base.javac
|
||||||
|
|
||||||
|
import com.sun.tools.javac.tree.JCTree
|
||||||
|
import com.sun.tools.javac.util.*
|
||||||
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.stubs.KotlinPosition
|
||||||
|
import java.io.*
|
||||||
|
import javax.tools.Diagnostic
|
||||||
|
|
||||||
|
// It's copy/paste as is of KaptJavaLog
|
||||||
|
// TODO: most likely KaptJavaLog could be substituted with this version.
|
||||||
|
// The only difference that is writers are passed through context
|
||||||
|
class KaptJavaLog17(
|
||||||
|
private val projectBaseDir: File?,
|
||||||
|
context: Context,
|
||||||
|
override val interceptorData: KaptJavaLogBase.DiagnosticInterceptorData,
|
||||||
|
private val mapDiagnosticLocations: Boolean
|
||||||
|
) : Log(context), KaptJavaLogBase {
|
||||||
|
private val stubLineInfo = KaptStubLineInformation()
|
||||||
|
private val javacMessages = JavacMessages.instance(context)
|
||||||
|
|
||||||
|
override val reportedDiagnostics: List<JCDiagnostic>
|
||||||
|
get() = _reportedDiagnostics
|
||||||
|
|
||||||
|
private val _reportedDiagnostics = mutableListOf<JCDiagnostic>()
|
||||||
|
|
||||||
|
override fun flush(kind: WriterKind?) {
|
||||||
|
super.flush(kind)
|
||||||
|
|
||||||
|
val diagnosticKind = when (kind) {
|
||||||
|
WriterKind.ERROR -> JCDiagnostic.DiagnosticType.ERROR
|
||||||
|
WriterKind.WARNING -> JCDiagnostic.DiagnosticType.WARNING
|
||||||
|
WriterKind.NOTICE -> JCDiagnostic.DiagnosticType.NOTE
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
_reportedDiagnostics.removeAll { it.type == diagnosticKind }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun flush() {
|
||||||
|
super.flush()
|
||||||
|
_reportedDiagnostics.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun report(diagnostic: JCDiagnostic) {
|
||||||
|
if (diagnostic.type == JCDiagnostic.DiagnosticType.ERROR && diagnostic.code in IGNORED_DIAGNOSTICS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diagnostic.type == JCDiagnostic.DiagnosticType.WARNING
|
||||||
|
&& diagnostic.code == "compiler.warn.proc.unmatched.processor.options"
|
||||||
|
&& diagnostic.args.singleOrNull() == "[kapt.kotlin.generated]"
|
||||||
|
) {
|
||||||
|
// Do not report the warning about "kapt.kotlin.generated" option being ignored if it's the only ignored option
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetElement = diagnostic.diagnosticPosition
|
||||||
|
val sourceFile = interceptorData.files[diagnostic.source]
|
||||||
|
|
||||||
|
if (diagnostic.code.contains("err.cant.resolve") && targetElement != null) {
|
||||||
|
if (sourceFile != null) {
|
||||||
|
val insideImports = targetElement.tree in sourceFile.imports
|
||||||
|
// Ignore resolve errors in import statements
|
||||||
|
if (insideImports) return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapDiagnosticLocations && sourceFile != null && targetElement?.tree != null) {
|
||||||
|
val kotlinPosition = stubLineInfo.getPositionInKotlinFile(sourceFile, targetElement.tree)
|
||||||
|
val kotlinFile = kotlinPosition?.let { getKotlinSourceFile(it) }
|
||||||
|
if (kotlinPosition != null && kotlinFile != null) {
|
||||||
|
val flags = JCDiagnostic.DiagnosticFlag.values().filterTo(mutableSetOf(), diagnostic::isFlagSet)
|
||||||
|
|
||||||
|
val kotlinDiagnostic = diags.create(
|
||||||
|
diagnostic.type,
|
||||||
|
diagnostic.lintCategory,
|
||||||
|
flags,
|
||||||
|
DiagnosticSource(KotlinFileObject(kotlinFile), this),
|
||||||
|
JCDiagnostic.SimpleDiagnosticPosition(kotlinPosition.pos),
|
||||||
|
diagnostic.code.stripCompilerKeyPrefix(),
|
||||||
|
*diagnostic.args
|
||||||
|
)
|
||||||
|
|
||||||
|
reportDiagnostic(kotlinDiagnostic)
|
||||||
|
|
||||||
|
// Avoid reporting the diagnostic twice
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reportDiagnostic(diagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.stripCompilerKeyPrefix(): String {
|
||||||
|
for (kind in listOf("err", "warn", "misc", "note")) {
|
||||||
|
val prefix = "compiler.$kind."
|
||||||
|
if (startsWith(prefix)) {
|
||||||
|
return drop(prefix.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportDiagnostic(diagnostic: JCDiagnostic) {
|
||||||
|
if (diagnostic.kind == Diagnostic.Kind.ERROR) {
|
||||||
|
val oldErrors = nerrors
|
||||||
|
super.report(diagnostic)
|
||||||
|
if (nerrors > oldErrors) {
|
||||||
|
_reportedDiagnostics += diagnostic
|
||||||
|
}
|
||||||
|
} else if (diagnostic.kind == Diagnostic.Kind.WARNING) {
|
||||||
|
val oldWarnings = nwarnings
|
||||||
|
super.report(diagnostic)
|
||||||
|
if (nwarnings > oldWarnings) {
|
||||||
|
_reportedDiagnostics += diagnostic
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.report(diagnostic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeDiagnostic(diagnostic: JCDiagnostic) {
|
||||||
|
if (hasDiagnosticListener()) {
|
||||||
|
diagListener.report(diagnostic)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val writer = when (diagnostic.type) {
|
||||||
|
DiagnosticType.FRAGMENT, null -> kotlin.error("Invalid root diagnostic type: ${diagnostic.type}")
|
||||||
|
DiagnosticType.NOTE -> super.getWriter(WriterKind.NOTICE)
|
||||||
|
DiagnosticType.WARNING -> super.getWriter(WriterKind.WARNING)
|
||||||
|
DiagnosticType.ERROR -> super.getWriter(WriterKind.ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
|
val formattedMessage = diagnosticFormatter.format(diagnostic, javacMessages.currentLocale)
|
||||||
|
.lines()
|
||||||
|
.joinToString(LINE_SEPARATOR, postfix = LINE_SEPARATOR) { original ->
|
||||||
|
// Kotlin location is put as a sub-diagnostic, so the formatter indents it with four additional spaces (6 in total).
|
||||||
|
// It looks weird, especially in the build log inside IntelliJ, so let's make things a bit better.
|
||||||
|
val trimmed = original.trimStart()
|
||||||
|
// Typically, javac places additional details about the diagnostics indented by two spaces
|
||||||
|
if (trimmed.startsWith(KOTLIN_LOCATION_PREFIX)) " " + trimmed else original
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.print(formattedMessage)
|
||||||
|
writer.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getKotlinSourceFile(pos: KotlinPosition): File? {
|
||||||
|
return if (pos.isRelativePath) {
|
||||||
|
val basePath = this.projectBaseDir
|
||||||
|
if (basePath != null) File(basePath, pos.path) else null
|
||||||
|
} else {
|
||||||
|
File(pos.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private operator fun <T : JCTree> Iterable<T>.contains(element: JCTree?): Boolean {
|
||||||
|
if (element == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var found = false
|
||||||
|
val visitor = object : JCTree.Visitor() {
|
||||||
|
override fun visitImport(that: JCTree.JCImport) {
|
||||||
|
super.visitImport(that)
|
||||||
|
if (!found) that.qualid.accept(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSelect(that: JCTree.JCFieldAccess) {
|
||||||
|
super.visitSelect(that)
|
||||||
|
if (!found) that.selected.accept(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTree(that: JCTree) {
|
||||||
|
if (!found && element == that) found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.forEach { if (!found) it.accept(visitor) }
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LINE_SEPARATOR: String = System.getProperty("line.separator")
|
||||||
|
private val KOTLIN_LOCATION_PREFIX = "Kotlin location: "
|
||||||
|
|
||||||
|
private val IGNORED_DIAGNOSTICS = setOf(
|
||||||
|
"compiler.err.name.clash.same.erasure",
|
||||||
|
"compiler.err.name.clash.same.erasure.no.override",
|
||||||
|
"compiler.err.name.clash.same.erasure.no.override.1",
|
||||||
|
"compiler.err.name.clash.same.erasure.no.hide",
|
||||||
|
"compiler.err.already.defined",
|
||||||
|
"compiler.err.annotation.type.not.applicable",
|
||||||
|
"compiler.err.doesnt.exist",
|
||||||
|
"compiler.err.cant.resolve.location",
|
||||||
|
"compiler.err.duplicate.annotation.missing.container",
|
||||||
|
"compiler.err.not.def.access.package.cant.access",
|
||||||
|
"compiler.err.package.not.visible",
|
||||||
|
"compiler.err.not.def.public.cant.access"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -10,7 +10,7 @@ import java.io.PrintWriter
|
|||||||
class WriterBackedKaptLogger(
|
class WriterBackedKaptLogger(
|
||||||
override val isVerbose: Boolean,
|
override val isVerbose: Boolean,
|
||||||
override val infoWriter: PrintWriter = PrintWriter(System.out),
|
override val infoWriter: PrintWriter = PrintWriter(System.out),
|
||||||
override val warnWriter: PrintWriter = PrintWriter(System.out),
|
override val warnWriter: PrintWriter = if (isJava17OrLater()) infoWriter else PrintWriter(System.out),
|
||||||
override val errorWriter: PrintWriter = PrintWriter(System.err)
|
override val errorWriter: PrintWriter = PrintWriter(System.err)
|
||||||
) : KaptLogger {
|
) : KaptLogger {
|
||||||
override fun info(message: String) {
|
override fun info(message: String) {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ private fun getJavaVersion(): Int =
|
|||||||
|
|
||||||
fun isJava9OrLater() = getJavaVersion() >= 9
|
fun isJava9OrLater() = getJavaVersion() >= 9
|
||||||
fun isJava11OrLater() = getJavaVersion() >= 11
|
fun isJava11OrLater() = getJavaVersion() >= 11
|
||||||
|
fun isJava17OrLater() = getJavaVersion() >= 17
|
||||||
|
|
||||||
fun Options.putJavacOption(jdk8Name: String, jdk9Name: String, value: String) {
|
fun Options.putJavacOption(jdk8Name: String, jdk9Name: String, value: String) {
|
||||||
val option = if (isJava9OrLater()) {
|
val option = if (isJava9OrLater()) {
|
||||||
|
|||||||
+2
-2
@@ -43,7 +43,7 @@ import org.jetbrains.kotlin.kapt3.Kapt3ComponentRegistrar.KaptComponentContribut
|
|||||||
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
|
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||||
import org.jetbrains.kotlin.kapt3.base.doAnnotationProcessing
|
import org.jetbrains.kotlin.kapt3.base.doAnnotationProcessing
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLogBase
|
||||||
import org.jetbrains.kotlin.kapt3.base.parseJavaFiles
|
import org.jetbrains.kotlin.kapt3.base.parseJavaFiles
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||||
import org.jetbrains.kotlin.kapt3.prettyPrint
|
import org.jetbrains.kotlin.kapt3.prettyPrint
|
||||||
@@ -287,7 +287,7 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
|
|||||||
.let { removeMetadataAnnotationContents(it) }
|
.let { removeMetadataAnnotationContents(it) }
|
||||||
|
|
||||||
if (kaptContext.compiler.shouldStop(CompileStates.CompileState.ENTER)) {
|
if (kaptContext.compiler.shouldStop(CompileStates.CompileState.ENTER)) {
|
||||||
val log = Log.instance(kaptContext.context) as KaptJavaLog
|
val log = Log.instance(kaptContext.context) as KaptJavaLogBase
|
||||||
|
|
||||||
val actualErrors = log.reportedDiagnostics
|
val actualErrors = log.reportedDiagnostics
|
||||||
.filter { it.type == JCDiagnostic.DiagnosticType.ERROR }
|
.filter { it.type == JCDiagnostic.DiagnosticType.ERROR }
|
||||||
|
|||||||
Reference in New Issue
Block a user