2 * Copyright 2000-2014 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.jps.incremental.groovy;
18 import com.intellij.util.containers.ContainerUtil;
19 import org.jetbrains.annotations.Nullable;
20 import org.jetbrains.jps.ModuleChunk;
21 import org.jetbrains.jps.incremental.messages.BuildMessage;
22 import org.jetbrains.jps.incremental.messages.CompilerMessage;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
30 * Adapted from org.codehaus.groovy.eclipse.compiler.GroovyEclipseCompiler, part of maven groovy-eclipse-compiler plugin.
32 * The source is distributed under Eclipse Public License (http://www.eclipse.org/legal/epl-v10.html, eclipse_license.txt).
36 class EclipseOutputParser {
37 private final String myBuilderName;
38 private final ModuleChunk myChunk;
40 public EclipseOutputParser(String builderName, ModuleChunk chunk) {
41 myBuilderName = builderName;
45 private static final String PROB_SEPARATOR = "----------\n";
47 List<CompilerMessage> parseMessages(String input) throws IOException {
48 if (input.contains("The type groovy.lang.GroovyObject cannot be resolved. It is indirectly referenced from required .class files")) {
49 return Arrays.asList(new CompilerMessage(myBuilderName, BuildMessage.Kind.ERROR,
50 "Cannot compile Groovy files: no Groovy library is defined for module '" + myChunk.representativeTarget().getModule().getName() + "'"));
53 List<CompilerMessage> parsedMessages = new ArrayList<CompilerMessage>();
55 String[] msgs = input.split(PROB_SEPARATOR);
56 for (String msg : msgs) {
57 if (msg.length() > 1) {
59 CompilerMessage message = parseMessage(msg);
60 if (message != null) {
61 parsedMessages.add(message);
64 // assume that there are one or more non-normal messages here
65 // All messages start with <num>. ERROR or <num>. WARNING
66 String[] extraMsgs = msg.split("\n");
67 StringBuilder sb = new StringBuilder();
68 for (String extraMsg : extraMsgs) {
69 if (extraMsg.indexOf(". WARNING") > 0 || extraMsg.indexOf(". ERROR") > 0) {
70 handleCurrentMessage(parsedMessages, sb);
71 sb = new StringBuilder("\n").append(extraMsg).append("\n");
74 if (!PROB_SEPARATOR.equals(extraMsg)) {
75 sb.append(extraMsg).append("\n");
79 handleCurrentMessage(parsedMessages, sb);
83 return parsedMessages;
86 private void handleCurrentMessage(final List<CompilerMessage> parsedMessages, final StringBuilder sb) {
87 if (sb.length() > 0) {
88 ContainerUtil.addIfNotNull(parsedMessages, parseMessage(sb.toString()));
93 private CompilerMessage parseMessage(String msgText) {
94 // message should look like this:
95 // 1. WARNING in /Users/andrew/git-repos/foo/src/main/java/packAction.java (at line 47)
96 // public abstract class AbstractScmTagAction extends TaskAction implements BuildBadgeAction {
97 // ^^^^^^^^^^^^^^^^^^^^
99 // But there will also be messages contributed from annotation processors that will look non-normal
100 int dotIndex = msgText.indexOf('.');
101 BuildMessage.Kind kind;
102 boolean isNormal = false;
104 if (msgText.substring(dotIndex, dotIndex + ". WARNING".length()).equals(". WARNING")) {
105 kind = BuildMessage.Kind.WARNING;
107 dotIndex += ". WARNING in ".length();
108 } else if (msgText.substring(dotIndex, dotIndex + ". ERROR".length()).equals(". ERROR")) {
109 kind = BuildMessage.Kind.ERROR;
111 dotIndex += ". ERROR in ".length();
113 kind = BuildMessage.Kind.INFO;
116 kind = BuildMessage.Kind.INFO;
119 int firstNewline = msgText.indexOf('\n');
120 String firstLine = firstNewline > 0 ? msgText.substring(0, firstNewline) : msgText;
121 String rest = firstNewline > 0 ? msgText.substring(firstNewline+1).trim() : "";
125 int parenIndex = firstLine.indexOf(" (");
126 String file = firstLine.substring(dotIndex, parenIndex);
127 int line = Integer.parseInt(firstLine.substring(parenIndex + " (at line ".length(), firstLine.indexOf(')')));
128 int lastLineIndex = rest.lastIndexOf("\n");
129 return new CompilerMessage(myBuilderName, kind, rest.substring(lastLineIndex + 1), file, -1, -1, -1, line, -1);
131 catch (RuntimeException ignore) {
135 if (msgText.trim().matches("(\\d)+ problem(s)? \\((\\d)+ (error|warning)(s)?\\)")) {
139 return new CompilerMessage(myBuilderName, kind, msgText);