blob: 368e33dd15226dad84e81c358ef834790d41733c [file] [log] [blame]
package com.android.tools.idea.gradle.output.parser.androidPlugin;
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.ParsingFailedException;
import com.android.ide.common.blame.parser.PatternAwareOutputParser;
import com.android.ide.common.blame.parser.util.OutputLineReader;
import com.android.utils.ILogger;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
/**
* A parser for errors that happen during resource merging, usually via
* a {@link com.android.ide.common.res2.MergingException}
* <p/>
* The error will be in one of these formats:
* <pre>
* path: Error: message
* path: error: message
* path:line: Error: message
* path:line: error: message
* path:line:column: Error: message
* path:line:column: error: message
* path: Warning: message
* path: warning: message
* path:line: Warning: message
* path:line: warning: message
* path:line:column: Warning: message
* path:line:column: warning: message
* </pre>
*/
public class MergingExceptionParser implements PatternAwareOutputParser {
@Override
public boolean parse(@NotNull String line, @NotNull OutputLineReader reader, @NotNull List<Message> messages, @NotNull ILogger logger)
throws ParsingFailedException {
boolean hasError = false;
int messageIndex;
Message.Kind kind = null;
//noinspection SpellCheckingInspection
if (line.contains("rror: ")) {
messageIndex = line.indexOf(": Error: ");
if (messageIndex == -1) {
messageIndex = line.indexOf(": error: ");
if (messageIndex == -1) {
return false;
}
}
kind = Message.Kind.ERROR;
} else { //noinspection SpellCheckingInspection
if (line.contains("arning: ")) {
messageIndex = line.indexOf(": Warning: ");
if (messageIndex == -1) {
messageIndex = line.indexOf(": warning: ");
if (messageIndex == -1) {
return false;
}
}
kind = Message.Kind.WARNING;
} else {
return false;
}
}
// TODO: This doesn't handle ambiguous scenarios where the error message itself contains ": " or the path contains " : ".
// I could disambiguate this by checking file existence on the path component containing a ":" !
// See if it's preceded by a line number and/or a column
String path;
int lineNumber = -1;
int column = -1;
int colon = line.lastIndexOf(':', messageIndex - 1);
if (colon != -1) {
// Is there a column?
int colon2 = line.lastIndexOf(':', colon - 1);
if (colon2 != -1) {
// Both line number and column
//lineNumber =
String columnString = line.substring(colon + 1, messageIndex);
String lineString = line.substring(colon2 + 1, colon);
try {
column = Integer.parseInt(columnString);
lineNumber = Integer.parseInt(lineString);
} catch (NumberFormatException e) {
// Could it be a Windows path with drive letters (and no line number) ?
if (colon2 == 1) {
String p = line.substring(0, colon);
if (new File(p).exists()) {
colon2 = colon;
} else {
return false;
}
} else {
return false;
}
}
path = line.substring(0, colon2);
} else {
// Just one number: it's the line
try {
lineNumber = Integer.parseInt(line.substring(colon + 1, messageIndex));
} catch (NumberFormatException e) {
// Could it be a Windows path with drive letters (and no line number) ?
if (colon == 1) {
String p = line.substring(0, messageIndex);
if (new File(p).exists()) {
colon = messageIndex;
} else {
return false;
}
} else {
return false;
}
}
path = line.substring(0, colon);
}
} else {
path = line.substring(0, messageIndex );
}
String message = line.substring(messageIndex + 2);
messages.add(new Message(kind, message, new SourceFilePosition(new File(path), new SourcePosition(lineNumber - 1, column -1, -1))));
return true;
}
}