Search in sources :

Example 6 with SourceFile

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;
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) SourcePosition(com.android.ide.common.blame.SourcePosition) PositionInFile(com.android.tools.idea.gradle.util.PositionInFile) SourceFile(com.android.ide.common.blame.SourceFile) Nullable(org.jetbrains.annotations.Nullable)

Example 7 with SourceFile

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;
}
Also used : SourceFilePosition(com.android.ide.common.blame.SourceFilePosition) Message(com.android.ide.common.blame.Message) Matcher(java.util.regex.Matcher) SourcePosition(com.android.ide.common.blame.SourcePosition) SourceFile(com.android.ide.common.blame.SourceFile) SourceFile(com.android.ide.common.blame.SourceFile) File(java.io.File)

Example 8 with SourceFile

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;
            }
        }
    }
}
Also used : Message(com.android.ide.common.blame.Message) Matcher(java.util.regex.Matcher) SourceFilePosition(com.android.ide.common.blame.SourceFilePosition) SourcePosition(com.android.ide.common.blame.SourcePosition) SourceFile(com.android.ide.common.blame.SourceFile) SourceFile(com.android.ide.common.blame.SourceFile) File(java.io.File)

Aggregations

SourceFile (com.android.ide.common.blame.SourceFile)8 SourcePosition (com.android.ide.common.blame.SourcePosition)6 File (java.io.File)6 SourceFilePosition (com.android.ide.common.blame.SourceFilePosition)5 VirtualFile (com.intellij.openapi.vfs.VirtualFile)4 Message (com.android.ide.common.blame.Message)3 XmlFile (com.intellij.psi.xml.XmlFile)3 Actions (com.android.manifmerger.Actions)2 GradleBuildFile (com.android.tools.idea.gradle.parser.GradleBuildFile)2 Module (com.intellij.openapi.module.Module)2 Matcher (java.util.regex.Matcher)2 LayoutXmlProcessor (android.databinding.tool.LayoutXmlProcessor)1 AndroidLibrary (com.android.builder.model.AndroidLibrary)1 MavenCoordinates (com.android.builder.model.MavenCoordinates)1 MergingLog (com.android.ide.common.blame.MergingLog)1 XmlNode (com.android.manifmerger.XmlNode)1 AndroidModuleModel (com.android.tools.idea.gradle.project.model.AndroidModuleModel)1 PositionInFile (com.android.tools.idea.gradle.util.PositionInFile)1 MergedManifest (com.android.tools.idea.model.MergedManifest)1 IdeActions (com.intellij.openapi.actionSystem.IdeActions)1