use of com.android.ide.common.blame.SourceFile in project android by JetBrains.
the class ExternalNdkBuildIssuesReporter method createPosition.
@Nullable
private static PositionInFile createPosition(@NotNull List<SourceFilePosition> sourceFilePositions) {
assert !sourceFilePositions.isEmpty();
VirtualFile sourceFile = null;
SourceFile source = sourceFilePositions.get(0).getFile();
if (source.getSourceFile() != null) {
sourceFile = findFileByIoFile(source.getSourceFile(), true);
}
if (sourceFile != null) {
SourcePosition sourcePosition = sourceFilePositions.get(0).getPosition();
return new PositionInFile(sourceFile, sourcePosition.getStartLine(), sourcePosition.getStartColumn());
}
return null;
}
use of com.android.ide.common.blame.SourceFile in project android by JetBrains.
the class XmlValidationErrorParser method parse.
@Override
public boolean parse(@NotNull String line, @NotNull OutputLineReader reader, @NotNull List<Message> messages, @NotNull ILogger logger) throws ParsingFailedException {
Matcher m1 = FATAL_ERROR.matcher(line);
if (!m1.matches()) {
// Sometimes the parse failure message appears by itself (for example with duplicate resources);
// in this case also recognize the line by itself even though it's separated from the next message
Matcher m2 = FILE_REFERENCE.matcher(line);
if (m2.matches()) {
File sourceFile = new File(m2.group(1));
if (sourceFile.exists()) {
String message = line;
// Eat the entire stacktrace
String exceptionMessage = ParserUtil.digestStackTrace(reader);
if (exceptionMessage != null) {
message = exceptionMessage + ": " + message;
}
messages.add(new Message(Message.Kind.ERROR, message, new SourceFilePosition(sourceFile, SourcePosition.UNKNOWN)));
return true;
}
}
return false;
}
String message = m1.group(3);
int lineNumber = Integer.parseInt(m1.group(1));
int column = Integer.parseInt(m1.group(2));
SourceFile sourceFile = SourceFile.UNKNOWN;
String nextLine = reader.peek(0);
if (nextLine == null) {
return false;
}
Matcher m2 = FILE_REFERENCE.matcher(nextLine);
if (m2.matches()) {
// digest peeked line
reader.readLine();
File possibleSourceFile = new File(m2.group(1));
if (possibleSourceFile.exists()) {
sourceFile = new SourceFile(possibleSourceFile);
}
}
messages.add(new Message(Message.Kind.ERROR, message, new SourceFilePosition(sourceFile, new SourcePosition(lineNumber - 1, column - 1, -1))));
return true;
}
use of com.android.ide.common.blame.SourceFile in project android by JetBrains.
the class BuildFailureParser method parse.
@Override
public boolean parse(@NotNull String line, @NotNull OutputLineReader reader, @NotNull List<Message> messages, @NotNull ILogger logger) throws ParsingFailedException {
State state = State.BEGINNING;
int pos = 0;
String currentLine = line;
SourceFile file = SourceFile.UNKNOWN;
SourcePosition position = SourcePosition.UNKNOWN;
String lastQuotedLine = null;
StringBuilder errorMessage = new StringBuilder();
Matcher matcher;
// some of the output. We should fall back to emitting all the output in that case.
while (true) {
switch(state) {
case BEGINNING:
if (WHERE_LINE_1.matcher(currentLine).matches()) {
state = State.WHERE;
} else if (!BEGINNING_PATTERNS[pos].matcher(currentLine).matches()) {
return false;
} else if (++pos >= BEGINNING_PATTERNS.length) {
state = State.MESSAGE;
}
break;
case WHERE:
matcher = WHERE_LINE_2.matcher(currentLine);
if (!matcher.matches()) {
return false;
}
file = new SourceFile(new File(matcher.group(1)));
position = new SourcePosition(Integer.parseInt(matcher.group(2)) - 1, 0, -1);
state = State.BEGINNING;
break;
case MESSAGE:
if (ENDING_PATTERNS[0].matcher(currentLine).matches()) {
state = State.ENDING;
pos = 1;
} else if (COMMAND_FAILURE_MESSAGE.matcher(currentLine).matches()) {
state = State.COMMAND_FAILURE_COMMAND_LINE;
} else if (COMPILE_FAILURE_MESSAGE.matcher(currentLine).matches()) {
state = State.COMPILE_FAILURE_OUTPUT;
// We don't need errorMessage anymore.
// Individual errors will be reported.
errorMessage.setLength(0);
} else {
// Determine whether the string starts with ">" (possibly indented by whitespace), and if so, where
int quoted = -1;
for (int i = 0, n = currentLine.length(); i < n; i++) {
char c = currentLine.charAt(i);
if (c == '>') {
quoted = i;
break;
} else if (!Character.isWhitespace(c)) {
break;
}
}
if (quoted != -1) {
if (currentLine.startsWith("> In DataSet ", quoted) && currentLine.contains("no data file for changedFile")) {
matcher = Pattern.compile("\\s*> In DataSet '.+', no data file for changedFile '(.+)'").matcher(currentLine);
if (matcher.find()) {
file = new SourceFile(new File(matcher.group(1)));
}
} else if (currentLine.startsWith("> Duplicate resources: ", quoted)) {
// For exact format, see com.android.ide.common.res2.DuplicateDataException
matcher = Pattern.compile("\\s*> Duplicate resources: (.+):(.+), (.+):(.+)\\s*").matcher(currentLine);
if (matcher.matches()) {
file = new SourceFile(new File(matcher.group(1)));
position = AbstractAaptOutputParser.findResourceLine(file.getSourceFile(), matcher.group(2), logger);
File other = new File(matcher.group(3));
SourcePosition otherPos = AbstractAaptOutputParser.findResourceLine(other, matcher.group(4), logger);
messages.add(new Message(Message.Kind.ERROR, currentLine, new SourceFilePosition(file, position), new SourceFilePosition(other, otherPos)));
// Skip appending to the errorMessage buffer; we've already added both locations to the message
break;
}
} else if (currentLine.startsWith("> Problems pinging owner of lock ", quoted)) {
String text = "Possibly unstable network connection: Failed to connect to lock owner. Try to rebuild.";
messages.add(new Message(Message.Kind.ERROR, text, SourceFilePosition.UNKNOWN));
}
}
boolean handledByDataBinding = myDataBindingParser.parse(currentLine, reader, messages, logger);
if (!handledByDataBinding) {
if (errorMessage.length() > 0) {
errorMessage.append("\n");
}
errorMessage.append(currentLine);
}
if (isGradleQuotedLine(currentLine)) {
lastQuotedLine = currentLine;
}
}
break;
case COMMAND_FAILURE_COMMAND_LINE:
// Gradle can put an unescaped "Android Studio" in its command-line output. (It doesn't care because this doesn't have to be
// a perfectly valid command line; it's just an error message). To keep it from messing up our parsing, let's convert those
// to "Android_Studio". If there are other spaces in the command-line path, though, it will mess up our parsing. Oh, well.
currentLine = currentLine.replaceAll("Android Studio", "Android_Studio");
matcher = COMMAND_LINE_PARSER.matcher(currentLine);
if (matcher.matches()) {
String message = String.format("Error while executing %s command", matcher.group(2));
messages.add(new Message(Message.Kind.ERROR, message, SourceFilePosition.UNKNOWN));
} else if (COMMAND_LINE_ERROR_OUTPUT.matcher(currentLine).matches()) {
state = State.COMMAND_FAILURE_OUTPUT;
} else if (ENDING_PATTERNS[0].matcher(currentLine).matches()) {
state = State.ENDING;
pos = 1;
}
break;
case COMMAND_FAILURE_OUTPUT:
if (ENDING_PATTERNS[0].matcher(currentLine).matches()) {
state = State.ENDING;
pos = 1;
} else {
currentLine = currentLine.trim();
if (!myAaptParser.parse(currentLine, reader, messages, logger)) {
// The AAPT parser punted on it. Just create a message with the unparsed error.
messages.add(new Message(Message.Kind.ERROR, currentLine, SourceFilePosition.UNKNOWN));
}
}
break;
case COMPILE_FAILURE_OUTPUT:
if (ENDING_PATTERNS[0].matcher(currentLine).matches()) {
state = State.ENDING;
pos = 1;
} else {
matcher = COMPILE_LINE_PARSER.matcher(currentLine);
if (matcher.matches()) {
file = new SourceFile(new File(matcher.group(1)));
position = new SourcePosition(Integer.parseInt(matcher.group(2)) - 1, Integer.parseInt(matcher.group(3)) - 1, 0);
String text = matcher.group(4);
String type = matcher.group(5);
Message.Kind kind = Message.Kind.UNKNOWN;
if (type.endsWith("error")) {
kind = Message.Kind.ERROR;
} else if (type.equals("warning")) {
kind = Message.Kind.WARNING;
} else if (type.equals("note")) {
kind = Message.Kind.INFO;
}
messages.add(new Message(kind, text, new SourceFilePosition(file, position)));
}
}
break;
case ENDING:
if (!ENDING_PATTERNS[pos].matcher(currentLine).matches()) {
return false;
} else if (++pos >= ENDING_PATTERNS.length) {
if (errorMessage.length() > 0) {
String text = errorMessage.toString();
// duplicate resources.
if (SourceFile.UNKNOWN.equals(file) && lastQuotedLine != null) {
String msg = unquoteGradleLine(lastQuotedLine);
Message rootCause = findRootCause(msg, messages);
if (rootCause == null) {
// Try searching there instead.
if (msg.endsWith("Failed to run command:")) {
String[] lines = text.split("\n");
if (lines.length > 2 && lines[lines.length - 2].contains("Output:")) {
String lastLine = lines[lines.length - 1];
if (!lastLine.isEmpty()) {
rootCause = findRootCause(lastLine.trim(), messages);
}
}
}
}
if (rootCause != null) {
if (!rootCause.getSourceFilePositions().isEmpty()) {
SourceFilePosition sourceFilePosition = rootCause.getSourceFilePositions().get(0);
file = sourceFilePosition.getFile();
position = sourceFilePosition.getPosition();
}
}
}
if (!SourceFile.UNKNOWN.equals(file)) {
messages.add(new Message(Message.Kind.ERROR, text, new SourceFilePosition(file, position)));
} else if (text.contains("Build cancelled")) {
// Gradle throws an exception (BuildCancelledException) when we cancel task processing
// (org.gradle.tooling.CancellationTokenSource.cancel()). We don't want to report that as an error though.
messages.add(new Message(Message.Kind.INFO, text, SourceFilePosition.UNKNOWN));
} else {
messages.add(new Message(Message.Kind.ERROR, text, SourceFilePosition.UNKNOWN));
}
}
return true;
}
break;
}
while (true) {
currentLine = reader.readLine();
if (currentLine == null) {
return false;
}
if (!currentLine.trim().isEmpty()) {
break;
}
}
}
}
Aggregations