IDEA-219019 - fix maven input in build tool window

GitOrigin-RevId: b466ccdb59fbc3594c07984bdeb9bb5f649ff1ca
This commit is contained in:
Alexander Bubenchikov
2019-07-31 14:03:30 +03:00
committed by intellij-monorepo-bot
parent 80d5c095a8
commit fe3cc08693
7 changed files with 391 additions and 60 deletions
@@ -7,12 +7,14 @@ import com.intellij.execution.process.ProcessEvent;
import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.execution.MavenExternalExecutor;
@ApiStatus.Experimental
public class BuildToolConsoleProcessAdapter extends ProcessAdapter {
private final MavenBuildEventProcessor myEventParser;
private final boolean myProcessText;
private final AnsiEscapeDecoder myDecoder = new AnsiEscapeDecoder();
private final MavenExternalExecutor.MavenSpyEventsBuffer myMavenSpyEventsBuffer;
/**
@@ -22,6 +24,13 @@ public class BuildToolConsoleProcessAdapter extends ProcessAdapter {
public BuildToolConsoleProcessAdapter(MavenBuildEventProcessor eventParser, @Deprecated boolean processText) {
myEventParser = eventParser;
myProcessText = processText;
if (processText) {
myMavenSpyEventsBuffer = new MavenExternalExecutor.MavenSpyEventsBuffer((l, k) -> myDecoder.escapeText(l, k, myEventParser));
}
else {
myMavenSpyEventsBuffer = null;
}
}
@Override
@@ -32,7 +41,7 @@ public class BuildToolConsoleProcessAdapter extends ProcessAdapter {
@Override
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
if (myProcessText) {
myDecoder.escapeText(event.getText(), outputType, myEventParser);
myMavenSpyEventsBuffer.addText(event.getText(), outputType);
}
}
@@ -134,7 +134,7 @@ public class BuildViewMavenConsole extends MavenConsole {
myEventParser.onTextAvailable(text, type == OutputType.ERROR);
}
public void onTextAvailable(String text, Key outputType) {
public void sendToEventParser(String text, Key outputType) {
myDecoder.escapeText(text, outputType, myEventParser);
}
@@ -19,6 +19,7 @@
package org.jetbrains.idea.maven.execution;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.process.AnsiEscapeDecoder;
import com.intellij.execution.process.OSProcessHandler;
@@ -27,6 +28,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.Consumer;
import com.intellij.util.io.BaseDataReader;
import com.intellij.util.io.BaseOutputReader;
import org.jetbrains.annotations.NonNls;
@@ -38,6 +40,8 @@ import org.jetbrains.idea.maven.project.MavenConsole;
import org.jetbrains.idea.maven.project.MavenGeneralSettings;
import org.jetbrains.idea.maven.server.MavenServerConsole;
import java.util.function.BiConsumer;
/**
* @deprecated external executor should work through maven run configuration
*/
@@ -51,7 +55,7 @@ public class MavenExternalExecutor extends MavenExecutor {
private JavaParameters myJavaParameters;
private ExecutionException myParameterCreationError;
private final AnsiEscapeDecoder myDecoder = new AnsiEscapeDecoder();
public MavenExternalExecutor(Project project,
@@ -79,40 +83,7 @@ public class MavenExternalExecutor extends MavenExecutor {
}
myProcessHandler =
new OSProcessHandler(myJavaParameters.toCommandLine()) {
@Override
public void notifyTextAvailable(@NotNull String text, @NotNull Key outputType) {
// todo move this logic to ConsoleAdapter class
if (myConsole instanceof BuildViewMavenConsole) {
((BuildViewMavenConsole)myConsole).onTextAvailable(text, outputType);
}
if (!myConsole.isSuppressed(text) && (!MavenSpyOutputParser.isSpyLog(text) || Registry.is("maven.spy.events.debug"))) {
myDecoder.escapeText(text, outputType, (t, ot) -> super.notifyTextAvailable(t, ot));
}
updateProgress(indicator, text);
}
@NotNull
@Override
protected BaseOutputReader.Options readerOptions() {
return new BaseOutputReader.Options() {
@Override
public BaseDataReader.SleepingPolicy policy() {
return BaseDataReader.SleepingPolicy.BLOCKING;
}
@Override
public boolean splitToLines() {
return true;
}
@Override
public boolean sendIncompleteLines() {
return false;
}
};
}
};
new MyLineSplittingProcessHandler(myJavaParameters.toCommandLine(), myConsole, line -> updateProgress(indicator, line));
myConsole.attachToProcess(myProcessHandler);
}
@@ -155,4 +126,133 @@ public class MavenExternalExecutor extends MavenExecutor {
}
}
}
private static class MyLineSplittingProcessHandler extends OSProcessHandler {
private final MavenSpyEventsBuffer mySpyEventsBuffer;
private final MavenSimpleConsoleEventsBuffer mySimpleConsoleEventsBuffer;
private final @NotNull MavenConsole myConsole;
private final AnsiEscapeDecoder myDecoder = new AnsiEscapeDecoder();
@Nullable private final Consumer<String> myProgressConsumer;
MyLineSplittingProcessHandler(@NotNull GeneralCommandLine commandLine,
@NotNull MavenConsole console,
@Nullable Consumer<String> progressConsumer
) throws ExecutionException {
super(commandLine);
myProgressConsumer = progressConsumer;
this.myConsole = console;
mySpyEventsBuffer = new MavenSpyEventsBuffer((line, key) -> {
sendToMavenEventParser(line, key);
if (myProgressConsumer != null) {
myProgressConsumer.consume(line);
}
});
mySimpleConsoleEventsBuffer = new MavenSimpleConsoleEventsBuffer((line, key) -> printSimpleOutput(line, key), Registry
.is("maven.spy.events.debug"));
}
@Override
public void notifyTextAvailable(@NotNull String text, @NotNull Key outputType) {
mySpyEventsBuffer.addText(text, outputType);
mySimpleConsoleEventsBuffer.addText(text, outputType);
}
private void sendToMavenEventParser(@NotNull String text, @NotNull Key outputType) {
if (myConsole instanceof BuildViewMavenConsole) {
((BuildViewMavenConsole)myConsole).sendToEventParser(text, outputType);
}
}
private void printSimpleOutput(@NotNull String text, @NotNull Key outputType) {
if (!myConsole.isSuppressed(text)) {
myDecoder.escapeText(text, outputType, (t, ot) -> super.notifyTextAvailable(t, ot));
}
}
@NotNull
@Override
protected BaseOutputReader.Options readerOptions() {
return new BaseOutputReader.Options() {
@Override
public BaseDataReader.SleepingPolicy policy() {
return BaseDataReader.SleepingPolicy.BLOCKING;
}
@Override
public boolean splitToLines() {
return true;
}
@Override
public boolean sendIncompleteLines() {
return true;
}
};
}
}
/**
* Expect to receive onle one line or part of it. splitToLines should be enabled
*/
public static class MavenSpyEventsBuffer {
private final StringBuilder myBuffer = new StringBuilder();
private final BiConsumer<String, Key> myConsumer;
public MavenSpyEventsBuffer(BiConsumer<String, Key> consumer) {myConsumer = consumer;}
public void addText(@NotNull String text, @NotNull Key outputType) {
if (text.charAt(text.length() - 1) == '\n') {
String textToSend = myBuffer.length() == 0 ? text : myBuffer.toString() + text;
myConsumer.accept(textToSend, outputType);
myBuffer.setLength(0);
}
else {
myBuffer.append(text);
}
}
}
public static class MavenSimpleConsoleEventsBuffer {
private final StringBuilder myBuffer = new StringBuilder();
private final BiConsumer<String, Key> myConsumer;
private final boolean myShowSpyOutput;
private boolean isProcessingSpyNow;
public MavenSimpleConsoleEventsBuffer(BiConsumer<String, Key> consumer, boolean showSpyOutput) {
myConsumer = consumer;
myShowSpyOutput = showSpyOutput;
}
public void addText(@NotNull String text, @NotNull Key outputType) {
if (myShowSpyOutput) {
myConsumer.accept(text, outputType);
return;
}
boolean lastChunk = text.charAt(text.length() - 1) == '\n';
if (isProcessingSpyNow) {
myBuffer.setLength(0);
isProcessingSpyNow = !lastChunk;
return;
}
String textToSend = myBuffer.length() == 0 ? text : myBuffer.toString() + text;
if (textToSend.length() >= MavenSpyOutputParser.PREFIX.length() || lastChunk) {
myBuffer.setLength(0);
if (!MavenSpyOutputParser.isSpyLog(text)) {
myConsumer.accept(textToSend, outputType);
}
else {
isProcessingSpyNow = !lastChunk;
}
}
else {
myBuffer.append(text);
}
}
}
}
@@ -39,7 +39,6 @@ import org.jetbrains.idea.maven.buildtool.MavenBuildEventProcessor;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.dom.MavenPropertyResolver;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.externalSystemIntegration.output.parsers.MavenSpyOutputParser;
import org.jetbrains.idea.maven.model.MavenConstants;
import org.jetbrains.idea.maven.project.MavenGeneralSettings;
import org.jetbrains.idea.maven.project.MavenGeneralSettingsEditor;
@@ -372,7 +371,7 @@ public class MavenRunConfiguration extends LocatableConfigurationBase implements
@Override
public boolean sendIncompleteLines() {
return false;
return true;
}
};
}
@@ -453,29 +452,40 @@ public class MavenRunConfiguration extends LocatableConfigurationBase implements
}
private ProcessListener filtered(ProcessListener listener) {
return new ProcessListener() {
@Override
public void startNotified(@NotNull ProcessEvent event) {
listener.startNotified(event);
}
return new ProcessListenerWithFilteredSpyOutput(listener);
}
@Override
public void processTerminated(@NotNull ProcessEvent event) {
listener.processTerminated(event);
}
private class ProcessListenerWithFilteredSpyOutput implements ProcessListener {
private final ProcessListener myListener;
private final MavenExternalExecutor.MavenSimpleConsoleEventsBuffer mySimpleConsoleEventsBuffer;
@Override
public void processWillTerminate(@NotNull ProcessEvent event, boolean willBeDestroyed) {
listener.processWillTerminate(event, willBeDestroyed);
}
ProcessListenerWithFilteredSpyOutput(ProcessListener listener) {
myListener = listener;
mySimpleConsoleEventsBuffer = new MavenExternalExecutor.MavenSimpleConsoleEventsBuffer(
(l, k) -> myListener.onTextAvailable(new ProcessEvent(MavenHandlerFilterSpyWrapper.this, l), k),
Registry.is("maven.spy.events.debug")
);
}
@Override
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
if (!MavenSpyOutputParser.isSpyLog(event.getText()) || Registry.is("maven.spy.events.debug")) {
listener.onTextAvailable(event, outputType);
}
}
};
@Override
public void startNotified(@NotNull ProcessEvent event) {
myListener.startNotified(event);
}
@Override
public void processTerminated(@NotNull ProcessEvent event) {
myListener.processTerminated(event);
}
@Override
public void processWillTerminate(@NotNull ProcessEvent event, boolean willBeDestroyed) {
myListener.processWillTerminate(event, willBeDestroyed);
}
@Override
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
mySimpleConsoleEventsBuffer.addText(event.getText(), outputType);
}
}
}
}
@@ -19,7 +19,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
public class MavenSpyOutputParser {
private final static String PREFIX = "[IJ]-";
public final static String PREFIX = "[IJ]-";
private final static String SEPARATOR = "-[IJ]-";
private final static String NEWLINE = "-[N]-";
public static final String DOWNLOAD_DEPENDENCIES_NAME = "dependencies";
@@ -0,0 +1,137 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.execution;
import com.intellij.openapi.util.Key;
import com.intellij.testFramework.UsefulTestCase;
public class MavenSimpleConsoleTest extends UsefulTestCase {
public void testSmoke() {
doTest(false, new String[]{
"first\n",
"second\n",
"third\n"
},
"first\n" +
"second\n" +
"third\n"
);
}
public void testIncompleteLine() {
doTest(false, new String[]{
"fi",
"rst\n",
"second\n",
"third\n"
},
"first\n" +
"second\n" +
"third\n"
);
}
public void testIncompleteLineNewLine() {
doTest(false, new String[]{
"fi",
"rst\n",
"second\n",
"third",
"\n"
},
"first\n" +
"second\n" +
"third\n"
);
}
public void testFilterSpy() {
doTest(false, new String[]{
"fi",
"rst\n",
"second\n",
"[IJ]-spy-output\n",
"third",
"\n"
},
"first\n" +
"second\n" +
"third\n"
);
}
public void testShortStrings() {
doTest(false, new String[]{
"1\n",
"2\n",
"three\n",
"[IJ]-spy-output\n",
"end\n",
"\n"
},
"1\n2\nthree\nend\n\n"
);
}
public void testFilterSpySplittedTimes() {
doTest(false, new String[]{
"fi",
"rst\n",
"second\n",
"[IJ]-spy-output",
"-and-this-is-still-spy-output",
"-and-this-is-still-spy-output again\n",
"and this is is not",
"\n"
},
"first\nsecond\nand this is is not\n"
);
}
public void testFilterSpySeveralTimes() {
doTest(false, new String[]{
"fi",
"rst\n",
"second\n",
"[IJ]-spy-output-1\n",
"[IJ]-spy-output-2\n",
"third\n",
"[IJ]-spy-output-3\n",
"end\n"
},
"first\nsecond\nthird\nend\n"
);
}
public void testDoNotFilterSpy() {
doTest(true, new String[]{
"fi",
"rst\n",
"second\n",
"[IJ]-spy-output-1\n",
"[IJ]-spy-output-2\n",
"third\n",
"[IJ]-spy-output-3\n",
"end\n"
},
"first\n" +
"second\n" +
"[IJ]-spy-output-1\n" +
"[IJ]-spy-output-2\n" +
"third\n" +
"[IJ]-spy-output-3\n" +
"end\n"
);
}
private static void doTest(boolean showSpyOutput, String[] text, String expected) {
StringBuilder actual = new StringBuilder();
MavenExternalExecutor.MavenSimpleConsoleEventsBuffer buffer =
new MavenExternalExecutor.MavenSimpleConsoleEventsBuffer((l, k) -> actual.append(l), showSpyOutput);
for (String s : text) {
buffer.addText(s, Key.create("test"));
}
assertEquals(expected, actual.toString());
}
}
@@ -0,0 +1,75 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.execution;
import com.intellij.openapi.util.Key;
import com.intellij.testFramework.UsefulTestCase;
import java.util.ArrayList;
import java.util.List;
public class MavenSpyBufferTest extends UsefulTestCase {
public void testSmoke() {
doTest(new String[]{
"first\n",
"second\n",
"third\n"
}, new String[]{
"first\n",
"second\n",
"third\n"
});
}
public void testIncompleteLine() {
doTest(new String[]{
"fi",
"rst\n",
"second\n",
"third\n"
}, new String[]{
"first\n",
"second\n",
"third\n"
});
}
public void testIncompleteLineNewLine() {
doTest(new String[]{
"fi",
"rst\n",
"second\n",
"third",
"\n"
}, new String[]{
"first\n",
"second\n",
"third\n"
});
}
public void testIJ() {
doTest(new String[]{
"[",
"I",
"J",
"]",
"-",
"very",
" long",
" string\n"
}, new String[]{
"[IJ]-very long string\n"
});
}
private static void doTest(String[] text, String[] expected) {
List<String> actual = new ArrayList<>();
MavenExternalExecutor.MavenSpyEventsBuffer spyEventsBuffer =
new MavenExternalExecutor.MavenSpyEventsBuffer((l, k) -> actual.add(l));
for (String s : text) {
spyEventsBuffer.addText(s, Key.create("test"));
}
assertOrderedEquals(actual, expected);
}
}