Search in sources :

Example 11 with SourcePosition

use of com.android.ide.common.blame.SourcePosition in project android by JetBrains.

the class JavacOutputParser method parse.

@Override
public boolean parse(@NotNull String line, @NotNull OutputLineReader reader, @NotNull List<Message> messages, @NotNull ILogger logger) throws ParsingFailedException {
    int colonIndex1 = line.indexOf(COLON);
    if (colonIndex1 == 1) {
        // drive letter (Windows)
        colonIndex1 = line.indexOf(COLON, colonIndex1 + 1);
    }
    if (colonIndex1 >= 0) {
        // looks like found something like a file path.
        String part1 = line.substring(0, colonIndex1).trim();
        if (part1.equalsIgnoreCase("error") || /* jikes */
        part1.equalsIgnoreCase("Caused by")) {
            // +1 so we don't include the colon
            String text = line.substring(colonIndex1 + 1).trim();
            addMessage(new Message(Message.Kind.ERROR, text, SourceFilePosition.UNKNOWN), messages);
            return true;
        }
        if (part1.equalsIgnoreCase("warning")) {
            // +1 so we don't include the colon
            String text = line.substring(colonIndex1 + 1).trim();
            addMessage(new Message(Message.Kind.WARNING, text, SourceFilePosition.UNKNOWN), messages);
            return true;
        }
        if (part1.equalsIgnoreCase("javac")) {
            addMessage(new Message(Message.Kind.ERROR, line, SourceFilePosition.UNKNOWN), messages);
            return true;
        }
        int colonIndex2 = line.indexOf(COLON, colonIndex1 + 1);
        if (colonIndex2 >= 0) {
            File file = new File(part1);
            if (!file.isFile()) {
                // the part one is not a file path.
                return false;
            }
            try {
                // 1-based.
                int lineNumber = Integer.parseInt(line.substring(colonIndex1 + 1, colonIndex2).trim());
                String text = line.substring(colonIndex2 + 1).trim();
                Message.Kind kind = Message.Kind.ERROR;
                if (text.startsWith(WARNING_PREFIX)) {
                    text = text.substring(WARNING_PREFIX.length()).trim();
                    kind = Message.Kind.WARNING;
                }
                // Only slurp up line pointer (^) information if this is really javac
                if (!file.getPath().endsWith(SdkConstants.DOT_JAVA)) {
                    // Fall back to the MergingExceptionParser (which handles similar messages in a more general way)
                    return false;
                }
                List<String> messageList = Lists.newArrayList();
                messageList.add(text);
                // 0-based.
                int column;
                String prevLine = null;
                do {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return false;
                    }
                    if (nextLine.trim().equals("^")) {
                        column = nextLine.indexOf('^');
                        String messageEnd = reader.readLine();
                        while (isMessageEnd(messageEnd)) {
                            messageList.add(messageEnd.trim());
                            messageEnd = reader.readLine();
                        }
                        if (messageEnd != null) {
                            reader.pushBack();
                        }
                        break;
                    }
                    if (prevLine != null) {
                        messageList.add(prevLine);
                    }
                    prevLine = nextLine;
                } while (true);
                if (column >= 0) {
                    messageList = convertMessages(messageList);
                    StringBuilder buf = StringBuilderSpinAllocator.alloc();
                    try {
                        for (String m : messageList) {
                            if (buf.length() > 0) {
                                buf.append(SystemProperties.getLineSeparator());
                            }
                            buf.append(m);
                        }
                        Message msg = new Message(kind, buf.toString(), new SourceFilePosition(file, new SourcePosition(lineNumber - 1, column, -1)));
                        addMessage(msg, messages);
                    } finally {
                        StringBuilderSpinAllocator.dispose(buf);
                    }
                    return true;
                }
            } catch (NumberFormatException ignored) {
            }
        }
    }
    if (line.endsWith("java.lang.OutOfMemoryError")) {
        addMessage(new Message(Message.Kind.ERROR, "Out of memory.", SourceFilePosition.UNKNOWN), messages);
        return true;
    }
    return false;
}
Also used : SourceFilePosition(com.android.ide.common.blame.SourceFilePosition) Message(com.android.ide.common.blame.Message) SourcePosition(com.android.ide.common.blame.SourcePosition) File(java.io.File)

Example 12 with SourcePosition

use of com.android.ide.common.blame.SourcePosition 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)

Example 13 with SourcePosition

use of com.android.ide.common.blame.SourcePosition in project android by JetBrains.

the class DataBindingOutputParser method parseErrorIn.

private static boolean parseErrorIn(@NotNull String output, @NotNull List<Message> messages) {
    String message;
    String file = "";
    List<Location> locations = new ArrayList<Location>();
    int msgStart = output.indexOf(MSG_KEY);
    if (msgStart < 0) {
        message = output;
    } else {
        int fileStart = output.indexOf(FILE_KEY, msgStart + MSG_KEY.length());
        if (fileStart < 0) {
            message = output;
        } else {
            message = output.substring(msgStart + MSG_KEY.length(), fileStart);
            int locStart = output.indexOf(LOCATION_KEY, fileStart + FILE_KEY.length());
            if (locStart < 0) {
                file = output.substring(fileStart + FILE_KEY.length()).trim();
            } else {
                file = output.substring(fileStart + FILE_KEY.length(), locStart).trim();
                int nextLoc = 0;
                while (nextLoc >= 0) {
                    nextLoc = output.indexOf(LOCATION_KEY, locStart + LOCATION_KEY.length());
                    Location loc;
                    if (nextLoc < 0) {
                        loc = Location.fromUserReadableString(output.substring(locStart + LOCATION_KEY.length()));
                    } else {
                        loc = Location.fromUserReadableString(output.substring(locStart + LOCATION_KEY.length(), nextLoc));
                    }
                    if (loc.isValid()) {
                        locations.add(loc);
                    }
                    locStart = nextLoc;
                }
            }
        }
    }
    if (StringUtil.isEmpty(file)) {
        return false;
    }
    List<SourceFilePosition> sourceFilePositions = new ArrayList<SourceFilePosition>();
    File sourceFile = new File(file);
    if (locations.size() == 0) {
        messages.add(new Message(Message.Kind.ERROR, message, SourceFilePosition.UNKNOWN));
    } else {
        for (Location location : locations) {
            sourceFilePositions.add(new SourceFilePosition(sourceFile, new SourcePosition(location.startLine, location.startOffset, 0, location.endLine, location.endOffset, 0)));
        }
        SourceFilePosition first = sourceFilePositions.get(0);
        if (locations.size() == 1) {
            messages.add(new Message(Message.Kind.ERROR, message, first));
        } else {
            SourceFilePosition[] rest = new SourceFilePosition[sourceFilePositions.size() - 1];
            for (int i = 1; i < sourceFilePositions.size(); i++) {
                rest[i - 1] = sourceFilePositions.get(i);
            }
            messages.add(new Message(Message.Kind.ERROR, message, first, rest));
        }
    }
    return true;
}
Also used : SourceFilePosition(com.android.ide.common.blame.SourceFilePosition) Message(com.android.ide.common.blame.Message) SourcePosition(com.android.ide.common.blame.SourcePosition) ArrayList(java.util.ArrayList) File(java.io.File)

Example 14 with SourcePosition

use of com.android.ide.common.blame.SourcePosition in project android by JetBrains.

the class AndroidManifestMergingBuilder method doMergeManifests.

private static boolean doMergeManifests(final CompileContext context, File manifestFile, List<File> libManifests, File outputFile) throws IOException {
    final AndroidBuildTestingManager testingManager = AndroidBuildTestingManager.getTestingManager();
    if (testingManager != null) {
        final StringBuilder messageBuilder = new StringBuilder("manifest_merging\n");
        messageBuilder.append(manifestFile.getPath()).append('\n');
        Collections.sort(libManifests);
        for (File libManifest : libManifests) {
            messageBuilder.append(libManifest.getPath()).append('\n');
        }
        messageBuilder.append(outputFile.getPath());
        testingManager.getCommandExecutor().log(messageBuilder.toString());
    }
    ImmutableList.Builder<Pair<String, File>> libraryFiles = ImmutableList.builder();
    for (File f : libManifests) {
        libraryFiles.add(Pair.of(f.getName(), f));
    }
    final ManifestMerger2.Invoker manifestMergerInvoker = ManifestMerger2.newMerger(manifestFile, NullLogger.getLogger(), ManifestMerger2.MergeType.APPLICATION).addBundleManifests(libraryFiles.build());
    MergingReport mergingReport;
    try {
        mergingReport = manifestMergerInvoker.merge();
    } catch (ManifestMerger2.MergeFailureException e) {
        context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, e.getMessage()));
        return false;
    }
    MergingReport.Result result = mergingReport.getResult();
    for (MergingReport.Record record : mergingReport.getLoggingRecords()) {
        SourceFilePosition position = record.getSourceLocation();
        File sourceFile = position.getFile().getSourceFile();
        String sourceFilePath = sourceFile != null ? sourceFile.getAbsolutePath() : null;
        SourcePosition pos = position.getPosition();
        MergingReport.Record.Severity severity = record.getSeverity();
        if (severity != MergingReport.Record.Severity.INFO) {
            context.processMessage(new CompilerMessage(BUILDER_NAME, toBuildMessageKind(record.getSeverity()), record.getMessage(), sourceFilePath, pos.getStartOffset(), pos.getEndOffset(), pos.getEndOffset(), pos.getEndLine(), pos.getEndColumn()));
        }
    }
    if (!result.isError()) {
        String xmlDocument = mergingReport.getMergedDocument(MergingReport.MergedManifestKind.MERGED);
        Files.write(xmlDocument, outputFile, Charsets.UTF_8);
    }
    return result.isSuccess();
}
Also used : MergingReport(com.android.manifmerger.MergingReport) AndroidBuildTestingManager(org.jetbrains.android.util.AndroidBuildTestingManager) CompilerMessage(org.jetbrains.jps.incremental.messages.CompilerMessage) ImmutableList(com.google.common.collect.ImmutableList) ManifestMerger2(com.android.manifmerger.ManifestMerger2) SourceFilePosition(com.android.ide.common.blame.SourceFilePosition) SourcePosition(com.android.ide.common.blame.SourcePosition) File(java.io.File) Pair(com.android.utils.Pair)

Example 15 with SourcePosition

use of com.android.ide.common.blame.SourcePosition in project android by JetBrains.

the class BuildOutputParserTest method parseParsedBuildIssue.

@Test
public void parseParsedBuildIssue() throws IOException {
    // Do not run tests on Windows (see http://b.android.com/222904)
    assumeFalse(SystemInfo.isWindows);
    String output = "AGPBI: {\"kind\":\"ERROR\",\"text\":\"" + "No resource identifier found for attribute \\u0027a\\u0027 in package" + " \\u0027android\\u0027\",\"sourcePath\":\"/usr/local/google/home/cmw/" + "udacity/Sunshine/app/src/main/res/menu/detail.xml\",\"position\":" + "{\"startLine\":5},\"original\":\"\"}";
    List<Message> Messages = parser.parseGradleOutput(output);
    assertEquals("Expect one message.", 1, Messages.size());
    Message message = Messages.iterator().next();
    assertEquals("No resource identifier found for attribute 'a' in package 'android'", message.getText());
    assertEquals(Message.Kind.ERROR, message.getKind());
    assertEquals("/usr/local/google/home/cmw/udacity/Sunshine/app/src/main/res/menu/detail.xml", message.getSourcePath());
    assertEquals(new SourcePosition(5, -1, -1), message.getSourceFilePositions().get(0).getPosition());
}
Also used : Message(com.android.ide.common.blame.Message) SourcePosition(com.android.ide.common.blame.SourcePosition) Test(org.junit.Test)

Aggregations

SourcePosition (com.android.ide.common.blame.SourcePosition)15 SourceFilePosition (com.android.ide.common.blame.SourceFilePosition)12 File (java.io.File)11 Message (com.android.ide.common.blame.Message)9 SourceFile (com.android.ide.common.blame.SourceFile)7 VirtualFile (com.intellij.openapi.vfs.VirtualFile)6 Module (com.intellij.openapi.module.Module)4 XmlFile (com.intellij.psi.xml.XmlFile)3 Matcher (java.util.regex.Matcher)3 Actions (com.android.manifmerger.Actions)2 GradleBuildFile (com.android.tools.idea.gradle.parser.GradleBuildFile)2 SyncMessage (com.android.tools.idea.gradle.project.sync.messages.SyncMessage)2 SyncMessageSubject.syncMessage (com.android.tools.idea.gradle.project.sync.messages.SyncMessageSubject.syncMessage)2 PositionInFile (com.android.tools.idea.gradle.util.PositionInFile)2 ArrayList (java.util.ArrayList)2 NotNull (org.jetbrains.annotations.NotNull)2 CompilerMessage (org.jetbrains.jps.incremental.messages.CompilerMessage)2 AndroidLibrary (com.android.builder.model.AndroidLibrary)1 MavenCoordinates (com.android.builder.model.MavenCoordinates)1 ParsingFailedException (com.android.ide.common.blame.parser.ParsingFailedException)1