blob: 3af6d25c5c8279348e8ec57ec729922f4de13fa3 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.lang.ant.config.execution;
import com.intellij.compiler.impl.javaCompiler.javac.JavacOutputParser;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.lang.ant.AntBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.problems.Problem;
import com.intellij.problems.WolfTheProblemSolver;
import com.intellij.rt.ant.execution.IdeaAntLogger2;
import com.intellij.util.text.StringTokenizer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class OutputParser{
@NonNls private static final String JAVAC = "javac";
@NonNls private static final String ECHO = "echo";
private static final Logger LOG = Logger.getInstance("#com.intellij.ant.execution.OutputParser");
private final Project myProject;
private final AntBuildMessageView myMessageView;
private final WeakReference<ProgressIndicator> myProgress;
private final String myBuildName;
private final OSProcessHandler myProcessHandler;
private volatile boolean isStopped;
private List<String> myJavacMessages;
private boolean myFirstLineProcessed;
private boolean myStartedSuccessfully;
private boolean myIsEcho;
public OutputParser(Project project,
OSProcessHandler processHandler,
AntBuildMessageView errorsView,
ProgressIndicator progress,
String buildName) {
myProject = project;
myProcessHandler = processHandler;
myMessageView = errorsView;
myProgress = new WeakReference<ProgressIndicator>(progress);
myBuildName = buildName;
myMessageView.setParsingThread(this);
}
public final void stopProcess() {
myProcessHandler.destroyProcess();
}
public boolean isTerminateInvoked() {
return myProcessHandler.isProcessTerminating() || myProcessHandler.isProcessTerminated();
}
protected Project getProject() {
return myProject;
}
protected OSProcessHandler getProcessHandler() {
return myProcessHandler;
}
public final boolean isStopped() {
return isStopped;
}
public final void setStopped(boolean stopped) {
isStopped = stopped;
}
private void setProgressStatistics(String s) {
final ProgressIndicator progress = myProgress.get();
if (progress != null) {
progress.setText2(s);
}
}
private void setProgressText(String s) {
final ProgressIndicator progress = myProgress.get();
if (progress != null) {
progress.setText(s);
}
}
private void printRawError(String text) {
myMessageView.outputError(text, 0);
}
public final void readErrorOutput(String text) {
if (!myFirstLineProcessed) {
myFirstLineProcessed = true;
myStartedSuccessfully = false;
myMessageView.buildFailed(myBuildName);
}
if (!myStartedSuccessfully) {
printRawError(text);
}
}
protected final void processTag(char tagName, final String tagValue, final int priority) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.valueOf(tagName) + priority + "=" + tagValue);
}
if (IdeaAntLogger2.TARGET == tagName) {
setProgressStatistics(AntBundle.message("target.tag.name.status.text", tagValue));
}
else if (IdeaAntLogger2.TASK == tagName) {
setProgressText(AntBundle.message("executing.task.tag.value.status.text", tagValue));
if (JAVAC.equals(tagValue)) {
myJavacMessages = new ArrayList<String>();
}
else if (ECHO.equals(tagValue)) {
myIsEcho = true;
}
}
if (myJavacMessages != null && (IdeaAntLogger2.MESSAGE == tagName || IdeaAntLogger2.ERROR == tagName)) {
myJavacMessages.add(tagValue);
return;
}
if (IdeaAntLogger2.MESSAGE == tagName) {
if (myIsEcho) {
myMessageView.outputMessage(tagValue, AntBuildMessageView.PRIORITY_VERBOSE);
}
else {
myMessageView.outputMessage(tagValue, priority);
}
}
else if (IdeaAntLogger2.TARGET == tagName) {
myMessageView.startTarget(tagValue);
}
else if (IdeaAntLogger2.TASK == tagName) {
myMessageView.startTask(tagValue);
}
else if (IdeaAntLogger2.ERROR == tagName) {
myMessageView.outputError(tagValue, priority);
}
else if (IdeaAntLogger2.EXCEPTION == tagName) {
String exceptionText = tagValue.replace(IdeaAntLogger2.EXCEPTION_LINE_SEPARATOR, '\n');
myMessageView.outputException(exceptionText);
}
else if (IdeaAntLogger2.BUILD == tagName) {
myMessageView.startBuild(myBuildName);
}
else if (IdeaAntLogger2.TARGET_END == tagName || IdeaAntLogger2.TASK_END == tagName) {
final List<String> javacMessages = myJavacMessages;
myJavacMessages = null;
processJavacMessages(javacMessages, myMessageView, myProject);
myIsEcho = false;
if (IdeaAntLogger2.TARGET_END == tagName) {
myMessageView.finishTarget();
}
else {
myMessageView.finishTask();
}
}
}
private static int getNextTwoPoints(int offset, String message) {
for (int i = offset + 1; i < message.length(); i++) {
char c = message.charAt(i);
if (c == ':') {
return i;
}
if (Character.isDigit(c)) {
continue;
}
return -1;
}
return -1;
}
private static void processJavacMessages(final List<String> javacMessages, final AntBuildMessageView messageView, final Project project) {
if (javacMessages == null) {
return;
}
final com.intellij.compiler.OutputParser outputParser = new JavacOutputParser(project);
com.intellij.compiler.OutputParser.Callback callback = new com.intellij.compiler.OutputParser.Callback() {
private int myIndex = -1;
@Nullable
public String getCurrentLine() {
if (myIndex >= javacMessages.size()) {
return null;
}
return javacMessages.get(myIndex);
}
public String getNextLine() {
final int size = javacMessages.size();
final int next = Math.min(myIndex + 1, javacMessages.size());
myIndex = next;
if (next >= size) {
return null;
}
return javacMessages.get(next);
}
@Override
public void pushBack(String line) {
myIndex--;
}
public void message(final CompilerMessageCategory category,
final String message,
final String url,
final int lineNum,
final int columnNum) {
StringTokenizer tokenizer = new StringTokenizer(message, "\n", false);
final String[] strings = new String[tokenizer.countTokens()];
//noinspection ForLoopThatDoesntUseLoopVariable
for (int idx = 0; tokenizer.hasMoreTokens(); idx++) {
strings[idx] = tokenizer.nextToken();
}
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
VirtualFile file = url == null ? null : VirtualFileManager.getInstance().findFileByUrl(url);
messageView.outputJavacMessage(convertCategory(category), strings, file, url, lineNum, columnNum);
if (file != null && category == CompilerMessageCategory.ERROR) {
final WolfTheProblemSolver wolf = WolfTheProblemSolver.getInstance(project);
final Problem problem = wolf.convertToProblem(file, lineNum, columnNum, strings);
wolf.weHaveGotNonIgnorableProblems(file, Collections.singletonList(problem));
}
}
});
}
public void setProgressText(String text) {
}
public void fileProcessed(String path) {
}
public void fileGenerated(String path) {
}
};
try {
while (true) {
if (!outputParser.processMessageLine(callback)) {
break;
}
}
}
catch (Exception e) {
//ignore
}
}
private static AntBuildMessageView.MessageType convertCategory(CompilerMessageCategory category) {
if (CompilerMessageCategory.ERROR.equals(category)) {
return AntBuildMessageView.MessageType.ERROR;
}
return AntBuildMessageView.MessageType.MESSAGE;
}
}