Simplify KotlinOutputParser, remove old reflection-based logic that didn't work well with the newer versions of Android Studio
This commit is contained in:
committed by
Yan Zhulanow
parent
74bda80ec2
commit
69051a4764
+3
-2
@@ -18,13 +18,14 @@ package org.jetbrains.kotlin.android;
|
||||
|
||||
import com.android.ide.common.blame.parser.PatternAwareOutputParser;
|
||||
import com.android.ide.common.blame.parser.util.OutputLineReader;
|
||||
import com.android.ide.common.blame.Message;
|
||||
import com.android.utils.ILogger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KotlinOutputParser implements PatternAwareOutputParser {
|
||||
@Override
|
||||
public boolean parse(String s, OutputLineReader reader, List list, ILogger logger) {
|
||||
return KotlinOutputParserHelperKt.parse(s, reader, list, logger);
|
||||
public boolean parse(String s, OutputLineReader reader, List<Message> list, ILogger logger) {
|
||||
return KotlinOutputParserHelperKt.parse(s, reader, list);
|
||||
}
|
||||
}
|
||||
|
||||
+41
-190
@@ -16,18 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.android
|
||||
|
||||
import com.android.ide.common.blame.Message
|
||||
import com.android.ide.common.blame.SourceFilePosition
|
||||
import com.android.ide.common.blame.SourcePosition
|
||||
import com.android.ide.common.blame.parser.util.OutputLineReader
|
||||
import com.android.utils.ILogger
|
||||
import com.google.common.base.Optional
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import java.io.File
|
||||
import java.lang.reflect.Constructor
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
import java.lang.reflect.Array as RArray
|
||||
|
||||
fun parse(line: String, reader: OutputLineReader, messages: MutableList<Any>, logger: ILogger): Boolean {
|
||||
fun parse(line: String, reader: OutputLineReader, messages: MutableList<Message>): Boolean {
|
||||
val colonIndex1 = line.colon()
|
||||
val severity = if (colonIndex1 >= 0) line.substringBeforeAndTrim(colonIndex1) else return false
|
||||
if (!severity.startsWithSeverityPrefix()) return false
|
||||
@@ -37,8 +37,10 @@ fun parse(line: String, reader: OutputLineReader, messages: MutableList<Any>, lo
|
||||
if (colonIndex2 >= 0) {
|
||||
val path = lineWoSeverity.substringBeforeAndTrim(colonIndex2)
|
||||
val file = File(path)
|
||||
if (!file.isFile && FileUtilRt.getExtension(file.name) != "kt") {
|
||||
return addMessage(KotlinOutputParserHelper.createMessage(logger, severity, lineWoSeverity.amendNextLinesIfNeeded(reader)), messages)
|
||||
|
||||
val fileExtension = file.extension.toLowerCase()
|
||||
if (!file.isFile || (fileExtension != "kt" && fileExtension != "java")) {
|
||||
return addMessage(createMessage(getMessageKind(severity), lineWoSeverity.amendNextLinesIfNeeded(reader)), messages)
|
||||
}
|
||||
|
||||
val lineWoPath = lineWoSeverity.substringAfterAndTrim(colonIndex2)
|
||||
@@ -51,22 +53,18 @@ fun parse(line: String, reader: OutputLineReader, messages: MutableList<Any>, lo
|
||||
|
||||
if (matcher.matches()) {
|
||||
val lineNumber = matcher.group(1)
|
||||
val symbolNumber = matcher.group(2)
|
||||
if (lineNumber != null && symbolNumber != null) {
|
||||
try {
|
||||
return addMessage(KotlinOutputParserHelper.createMessage(logger, severity, message, path, lineNumber.toInt(), symbolNumber.toInt(), symbolNumber.toInt()), messages)
|
||||
}
|
||||
catch (e: NumberFormatException) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
val symbolNumber = if (matcher.groupCount() >= 2) matcher.group(2) else "1"
|
||||
if (lineNumber != null) {
|
||||
val symbolNumberText = symbolNumber.toInt()
|
||||
return addMessage(createMessageWithLocation(
|
||||
getMessageKind(severity), message, path, lineNumber.toInt(), symbolNumberText, symbolNumberText), messages)
|
||||
}
|
||||
}
|
||||
|
||||
return addMessage(KotlinOutputParserHelper.createMessage(logger, severity, message), messages)
|
||||
return addMessage(createMessage(getMessageKind(severity), message), messages)
|
||||
}
|
||||
else {
|
||||
return addMessage(KotlinOutputParserHelper.createMessage(logger, severity, lineWoSeverity.amendNextLinesIfNeeded(reader)), messages)
|
||||
return addMessage(createMessage(getMessageKind(severity), lineWoSeverity.amendNextLinesIfNeeded(reader)), messages)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,11 +110,14 @@ private fun String.isNextMessage(): Boolean {
|
||||
|| StringUtil.containsIgnoreCase(this, "FAILED")
|
||||
}
|
||||
|
||||
private fun String.startsWithSeverityPrefix(): Boolean {
|
||||
return when (this.trim()) {
|
||||
"e", "w", "i", "v" -> true
|
||||
else -> false
|
||||
}
|
||||
private fun String.startsWithSeverityPrefix() = getMessageKind(this) != Message.Kind.UNKNOWN
|
||||
|
||||
private fun getMessageKind(kind: String) = when (kind) {
|
||||
"e" -> Message.Kind.ERROR
|
||||
"w" -> Message.Kind.WARNING
|
||||
"i" -> Message.Kind.INFO
|
||||
"v" -> Message.Kind.SIMPLE
|
||||
else -> Message.Kind.UNKNOWN
|
||||
}
|
||||
|
||||
private fun String.substringAfterAndTrim(index: Int) = substring(index + 1).trim()
|
||||
@@ -126,12 +127,11 @@ private fun Int.skipDriveOnWin(line: String): Int {
|
||||
return if (this == 1) line.indexOf(COLON, this + 1) else this
|
||||
}
|
||||
|
||||
private fun addMessage(message: Any?, messages: MutableList<Any>): Boolean {
|
||||
if (message == null) return false
|
||||
private fun addMessage(message: Message, messages: MutableList<Message>): Boolean {
|
||||
var duplicatesPrevious = false
|
||||
val messageCount = messages.size
|
||||
if (messageCount > 0) {
|
||||
val lastMessage = messages.get(messageCount - 1)
|
||||
val lastMessage = messages[messageCount - 1]
|
||||
duplicatesPrevious = lastMessage == message
|
||||
}
|
||||
if (!duplicatesPrevious) {
|
||||
@@ -140,168 +140,19 @@ private fun addMessage(message: Any?, messages: MutableList<Any>): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
object KotlinOutputParserHelper {
|
||||
private val isNewAndroidPlugin: Boolean
|
||||
private val packagePrefix: String
|
||||
private val severityObjectMap: HashMap<String, Any> = HashMap()
|
||||
|
||||
init {
|
||||
isNewAndroidPlugin = try {
|
||||
Class.forName("com.android.ide.common.blame.Message")
|
||||
true
|
||||
}
|
||||
catch (e: ClassNotFoundException) {
|
||||
false
|
||||
}
|
||||
|
||||
packagePrefix = if (isNewAndroidPlugin) "com.android.ide.common.blame" else "com.android.ide.common.blame.output"
|
||||
|
||||
loadSeverityEnums()
|
||||
}
|
||||
|
||||
private val simpleMessageConstructor: Constructor<*> by lazy {
|
||||
if (!isNewAndroidPlugin) {
|
||||
val messageClass = Class.forName("$packagePrefix.GradleMessage")
|
||||
val messageKindClass = Class.forName("$packagePrefix.GradleMessage\$Kind")
|
||||
messageClass.getConstructor(messageKindClass, String::class.java)
|
||||
}
|
||||
else {
|
||||
val messageClass = Class.forName("$packagePrefix.Message")
|
||||
val messageKindClass = Class.forName("$packagePrefix.Message\$Kind")
|
||||
messageClass.getConstructor(
|
||||
messageKindClass,
|
||||
String::class.java,
|
||||
String::class.java,
|
||||
ImmutableList::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private val complexMessageConstructor: Constructor<*> by lazy {
|
||||
if (!isNewAndroidPlugin) {
|
||||
val messageClass = Class.forName("$packagePrefix.GradleMessage")
|
||||
val messageKindClass = Class.forName("$packagePrefix.GradleMessage\$Kind")
|
||||
messageClass.getConstructor(
|
||||
messageKindClass,
|
||||
String::class.java, String::class.java,
|
||||
Int::class.java, Int::class.java)
|
||||
}
|
||||
else {
|
||||
val messageClass = Class.forName("$packagePrefix.Message")
|
||||
val messageKindClass = Class.forName("$packagePrefix.Message\$Kind")
|
||||
val sourceFilePositionClass = Class.forName("$packagePrefix.SourceFilePosition")
|
||||
val sourceFilePositionArrayClass = Class.forName("[L$packagePrefix.SourceFilePosition;")
|
||||
messageClass.getConstructor(
|
||||
messageKindClass,
|
||||
String::class.java,
|
||||
sourceFilePositionClass,
|
||||
sourceFilePositionArrayClass)
|
||||
}
|
||||
}
|
||||
|
||||
private val sourceFilePositionConstructor: Constructor<*> by lazy {
|
||||
assert(isNewAndroidPlugin) { "This property should be used only for New Android Plugin" }
|
||||
val sourcePositionClass = Class.forName("$packagePrefix.SourcePosition")
|
||||
val sourceFilePositionClass = Class.forName("$packagePrefix.SourceFilePosition")
|
||||
sourceFilePositionClass.getConstructor(File::class.java, sourcePositionClass)
|
||||
}
|
||||
|
||||
private val sourcePositionConstructor: Constructor<*> by lazy {
|
||||
assert(isNewAndroidPlugin) { "This property should be used only for New Android Plugin" }
|
||||
val sourcePositionClass = Class.forName("$packagePrefix.SourcePosition")
|
||||
sourcePositionClass.getConstructor(Int::class.java, Int::class.java, Int::class.java)
|
||||
}
|
||||
|
||||
private val sourcePositionVarargArg: Any by lazy {
|
||||
assert(isNewAndroidPlugin) { "This property should be used only for New Android Plugin" }
|
||||
val sourceFilePositionClass = Class.forName("$packagePrefix.SourceFilePosition")
|
||||
RArray.newInstance(sourceFilePositionClass, 0)
|
||||
}
|
||||
|
||||
private fun loadSeverityEnums() {
|
||||
val messageKindClass = if (isNewAndroidPlugin)
|
||||
Class.forName("$packagePrefix.Message\$Kind")
|
||||
else
|
||||
Class.forName("$packagePrefix.GradleMessage\$Kind")
|
||||
|
||||
val messageKindConstants = messageKindClass.enumConstants as Array<Any>
|
||||
for (kind in messageKindConstants) {
|
||||
when(kind.toString()) {
|
||||
"ERROR" -> severityObjectMap.put("e", kind)
|
||||
"WARNING" -> severityObjectMap.put("w", kind)
|
||||
"INFO" -> severityObjectMap.put("i", kind)
|
||||
"SIMPLE" -> severityObjectMap.put("v", kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createMessage(
|
||||
logger: ILogger,
|
||||
severity: String,
|
||||
text: String,
|
||||
file: String? = null,
|
||||
lineNumber: Int? = null,
|
||||
columnIndex: Int? = null,
|
||||
offset: Int? = null
|
||||
): Any? {
|
||||
try {
|
||||
val severityConst: Any = severityObjectMap[severity] ?: return null
|
||||
|
||||
return if (isNewAndroidPlugin) {
|
||||
createNewMessage(severityConst, text.trim(), file, lineNumber, columnIndex, offset)
|
||||
}
|
||||
else {
|
||||
createOldMessage(severityConst, text.trim(), file, lineNumber, columnIndex)
|
||||
}
|
||||
}
|
||||
catch(e: Throwable) {
|
||||
logger.error(e, "Exception from KotlinOutputParser")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun createNewMessage(
|
||||
severityConst: Any,
|
||||
text: String,
|
||||
file: String?,
|
||||
lineNumber: Int?,
|
||||
columnIndex: Int?,
|
||||
offset: Int?
|
||||
): Any? {
|
||||
if (file == null || lineNumber == null || columnIndex == null || offset == null) {
|
||||
return simpleMessageConstructor.newInstance(
|
||||
severityConst,
|
||||
text,
|
||||
text,
|
||||
ImmutableList.of<Any>())
|
||||
}
|
||||
else {
|
||||
val sourcePositionObj = sourcePositionConstructor.newInstance(lineNumber - 1, columnIndex - 1, offset)
|
||||
val sourceFilePositionObj = sourceFilePositionConstructor.newInstance(File(file), sourcePositionObj)
|
||||
|
||||
return complexMessageConstructor.newInstance(
|
||||
severityConst,
|
||||
text,
|
||||
sourceFilePositionObj,
|
||||
sourcePositionVarargArg)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createOldMessage(
|
||||
severityConst: Any,
|
||||
text: String,
|
||||
file: String?,
|
||||
lineNumber: Int?,
|
||||
columnIndex: Int?
|
||||
): Any? {
|
||||
return if (file == null || lineNumber == null || columnIndex == null) {
|
||||
simpleMessageConstructor.newInstance(severityConst, text)
|
||||
}
|
||||
else {
|
||||
complexMessageConstructor.newInstance(
|
||||
severityConst,
|
||||
text, file,
|
||||
lineNumber, columnIndex)
|
||||
}
|
||||
}
|
||||
private fun createMessage(messageKind: Message.Kind, text: String): Message {
|
||||
return Message(messageKind, text.trim(), text, Optional.absent<String>(), ImmutableList.of())
|
||||
}
|
||||
|
||||
private fun createMessageWithLocation(
|
||||
messageKind: Message.Kind,
|
||||
text: String,
|
||||
file: String,
|
||||
lineNumber: Int,
|
||||
columnIndex: Int,
|
||||
offset: Int
|
||||
): Message {
|
||||
val sourcePosition = SourcePosition(lineNumber - 1, columnIndex - 1, offset)
|
||||
val sourceFilePosition = SourceFilePosition(File(file), sourcePosition)
|
||||
return Message(messageKind, text.trim(), sourceFilePosition)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user