IDEA-313445 refactored Gradle/ExternalSystem event processing

major changes:
- added message and IO type for message event
- added attaching isolated event trees into build root
- extracted all event convertors code into Gradle and ES event convertors
- added logging for unhandled and unsupported events

GitOrigin-RevId: 1151beb3cb7295d5786d51ec37943b249fb7cd05
This commit is contained in:
Sergei Vorobyov
2023-03-10 15:45:57 +00:00
committed by intellij-monorepo-bot
parent 4c59c49eba
commit 83f9e045d4
18 changed files with 678 additions and 601 deletions
@@ -164,13 +164,15 @@ public class JavaTestLocator implements SMTestLocator {
: new PsiLocation<>(aClass.getProject(), aClass);
}
@NotNull
public static String createLocationUrl(@NotNull String protocol, @NotNull String fqClassName) {
return protocol + SCHEME_SEPARATOR + fqClassName;
public static @NotNull String createLocationUrl(@NotNull String protocol, @NotNull String fqClassName) {
return createLocationUrl(protocol, fqClassName, null);
}
@NotNull
public static String createLocationUrl(@NotNull String protocol, @NotNull String fqClassName, @NotNull String methodName) {
return createLocationUrl(protocol, fqClassName) + "/" + StringUtil.trimEnd(methodName, "()");
public static @NotNull String createLocationUrl(@NotNull String protocol, @NotNull String fqClassName, @Nullable String methodName) {
var baseUrl = protocol + SCHEME_SEPARATOR;
if (methodName == null) {
return baseUrl + fqClassName;
}
return baseUrl + fqClassName + "/" + StringUtil.trimEnd(methodName, "()");
}
}
@@ -1,19 +1,23 @@
// Copyright 2000-2021 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 com.intellij.openapi.externalSystem.model.task.event;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
/**
* An event with textual description.
* @param <T>
*/
public interface ExternalSystemMessageEvent<T extends OperationDescriptor> extends ExternalSystemProgressEvent<T>{
public interface ExternalSystemMessageEvent<T extends OperationDescriptor> extends ExternalSystemProgressEvent<T> {
default boolean isStdOut() { return true; }
default @Nullable @Nls String getMessage() { return null; }
/**
* Textual description of event.
*
* @return arbitrary additional information about status update
*/
@Nullable
default String getDescription() { return null; }
default @Nullable String getDescription() { return null; }
}
@@ -1,24 +1,52 @@
// Copyright 2000-2021 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 com.intellij.openapi.externalSystem.model.task.event;
import com.intellij.openapi.util.NlsSafe;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ExternalSystemMessageEventImpl<T extends OperationDescriptor> extends BaseExternalSystemProgressEvent<T>
public class ExternalSystemMessageEventImpl<T extends OperationDescriptor>
extends BaseExternalSystemProgressEvent<T>
implements ExternalSystemMessageEvent<T> {
private final String myDescription;
private final boolean myStdOut;
private final @Nullable @Nls String myMessage;
private final @Nullable String myDescription;
public ExternalSystemMessageEventImpl(
@NotNull String eventId,
@Nullable String parentEventId,
@NotNull T descriptor,
boolean isStdOut,
@Nullable @Nls String message,
@Nullable String description
) {
super(eventId, parentEventId, descriptor);
myStdOut = isStdOut;
myMessage = message;
myDescription = description;
}
public ExternalSystemMessageEventImpl(@NotNull String eventId,
@Nullable String parentEventId,
@NotNull T descriptor,
@Nullable String message) {
super(eventId, parentEventId, descriptor);
myDescription = message;
@Nullable @NlsSafe String description) {
this(eventId, parentEventId, descriptor, true, description, description);
}
@Nullable
@Override
public String getDescription() {
public boolean isStdOut() {
return myStdOut;
}
@Override
public @Nullable String getMessage() {
return myMessage;
}
@Override
public @Nullable String getDescription() {
return myDescription;
}
}
@@ -0,0 +1,86 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.externalSystem.util;
import com.intellij.build.events.BuildEvent;
import com.intellij.build.events.EventResult;
import com.intellij.build.events.impl.*;
import com.intellij.build.events.impl.FailureImpl;
import com.intellij.build.events.impl.FailureResultImpl;
import com.intellij.build.events.impl.SkippedResultImpl;
import com.intellij.build.events.impl.SuccessResultImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.task.event.*;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ExternalSystemProgressEventConverter {
private static final Logger LOG = Logger.getInstance("com.intellij.openapi.externalSystem.event-processing");
public static @Nullable BuildEvent convertBuildEvent(@NotNull ExternalSystemTaskExecutionEvent event) {
var hint = event.getProgressEvent().getDescriptor().getHint();
var buildEvent = convertAbstractBuildEvent(event);
ObjectUtils.consumeIfNotNull(buildEvent, it -> it.setHint(hint));
return buildEvent;
}
private static @Nullable AbstractBuildEvent convertAbstractBuildEvent(@NotNull ExternalSystemTaskExecutionEvent event) {
var progressEvent = event.getProgressEvent();
var eventId = progressEvent.getEventId();
var descriptor = progressEvent.getDescriptor();
var eventTime = descriptor.getEventTime();
var displayName = descriptor.getDisplayName();
var parentEventId = ObjectUtils.chooseNotNull(progressEvent.getParentEventId(), event.getId());
if (progressEvent instanceof ExternalSystemStartEvent) {
return new StartEventImpl(eventId, parentEventId, eventTime, displayName);
}
else if (progressEvent instanceof ExternalSystemFinishEvent<?> finishEvent) {
var operationResult = finishEvent.getOperationResult();
var eventResult = convertEventResult(operationResult);
if (eventResult != null) {
return new FinishEventImpl(eventId, parentEventId, eventTime, displayName, eventResult);
}
}
else if (progressEvent instanceof ExternalSystemStatusEvent<?> statusEvent) {
var total = statusEvent.getTotal();
var progress = statusEvent.getProgress();
var unit = statusEvent.getUnit();
return new ProgressBuildEventImpl(eventId, parentEventId, eventTime, displayName, total, progress, unit);
}
else if (progressEvent instanceof ExternalSystemMessageEvent<?> messageEvent) {
var message = ObjectUtils.chooseNotNull(messageEvent.getMessage(), displayName);
var isStdOut = messageEvent.isStdOut();
return new OutputBuildEventImpl(eventId, parentEventId, message, isStdOut);
}
LOG.warn("Undefined progress event " + event.getClass().getSimpleName() + " " + event);
return null;
}
private static @Nullable EventResult convertEventResult(@NotNull OperationResult result) {
if (result instanceof FailureResult) {
var failures = convertFailureResult((FailureResult)result);
return new FailureResultImpl(failures);
}
else if (result instanceof SkippedResult) {
return new SkippedResultImpl();
}
else if (result instanceof SuccessResult successResult) {
return new SuccessResultImpl(successResult.isUpToDate());
}
return null;
}
private static @NotNull List<com.intellij.build.events.Failure> convertFailureResult(@NotNull FailureResult failure) {
return ContainerUtil.map(failure.getFailures(), it -> convertFailure(it));
}
private static @NotNull com.intellij.build.events.Failure convertFailure(@NotNull Failure failure) {
var causes = ContainerUtil.map(failure.getCauses(), it -> convertFailure(it));
return new FailureImpl(failure.getMessage(), failure.getDescription(), causes);
}
}
@@ -3,11 +3,10 @@ package com.intellij.openapi.externalSystem.util;
import com.intellij.build.*;
import com.intellij.build.events.BuildEvent;
import com.intellij.build.events.EventResult;
import com.intellij.build.events.FailureResult;
import com.intellij.build.events.FinishBuildEvent;
import com.intellij.build.events.impl.FailureImpl;
import com.intellij.build.events.impl.FailureResultImpl;
import com.intellij.build.events.impl.SkippedResultImpl;
import com.intellij.build.events.impl.SuccessResultImpl;
import com.intellij.build.events.impl.*;
import com.intellij.build.issue.BuildIssue;
@@ -95,7 +94,6 @@ import com.intellij.pom.Navigatable;
import com.intellij.pom.NonNavigatable;
import com.intellij.util.Consumer;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.ThreeState;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.HashingStrategy;
@@ -457,8 +455,7 @@ public final class ExternalSystemUtil {
String title = ExternalSystemBundle.message("notification.project.refresh.fail.title",
externalSystemId.getReadableName(), projectName);
DataContext dataContext = BuildConsoleUtils.getDataContext(id, syncViewManager);
com.intellij.build.events.FailureResult failureResult =
createFailureResult(title, e, externalSystemId, project, dataContext);
FailureResult failureResult = createFailureResult(title, e, externalSystemId, project, dataContext);
finishSyncEventSupplier.set(() -> new FinishBuildEventImpl(id, null, System.currentTimeMillis(),
BuildBundle.message("build.status.failed"), failureResult));
processHandler.notifyProcessTerminated(1);
@@ -545,8 +542,7 @@ public final class ExternalSystemUtil {
ExternalSystemTaskId id = resolveProjectTask.getId();
String title = ExternalSystemBundle.message("notification.project.refresh.fail.title",
externalSystemId.getReadableName(), projectName);
com.intellij.build.events.FailureResult failureResult =
createFailureResult(title, t, externalSystemId, project, DataContext.EMPTY_CONTEXT);
FailureResult failureResult = createFailureResult(title, t, externalSystemId, project, DataContext.EMPTY_CONTEXT);
finishSyncEventSupplier.set(() -> new FinishBuildEventImpl(id, null, System.currentTimeMillis(),
BuildBundle.message("build.status.failed"), failureResult));
@@ -784,58 +780,20 @@ public final class ExternalSystemUtil {
return navigatable == null || navigatable == NonNavigatable.INSTANCE;
}
public static BuildEvent convert(ExternalSystemTaskExecutionEvent taskExecutionEvent) {
ExternalSystemProgressEvent progressEvent = taskExecutionEvent.getProgressEvent();
String displayName = progressEvent.getDescriptor().getDisplayName();
long eventTime = progressEvent.getDescriptor().getEventTime();
Object parentEventId = ObjectUtils.chooseNotNull(progressEvent.getParentEventId(), taskExecutionEvent.getId());
AbstractBuildEvent buildEvent;
if (progressEvent instanceof ExternalSystemStartEvent) {
buildEvent = new StartEventImpl(progressEvent.getEventId(), parentEventId, eventTime, displayName);
public static @NotNull BuildEvent convert(@NotNull ExternalSystemTaskExecutionEvent event) {
var buildEvent = ExternalSystemProgressEventConverter.convertBuildEvent(event);
if (buildEvent == null) {
// Migrated old fallback from previous implementation
return new OutputBuildEventImpl(
event.getProgressEvent().getEventId(),
ObjectUtils.chooseNotNull(event.getProgressEvent().getParentEventId(), event.getId()),
event.getProgressEvent().getDescriptor().getDisplayName(),
true
);
}
else if (progressEvent instanceof ExternalSystemFinishEvent) {
final EventResult eventResult;
final OperationResult operationResult = ((ExternalSystemFinishEvent<?>)progressEvent).getOperationResult();
if (operationResult instanceof FailureResult) {
List<com.intellij.build.events.Failure> failures = new SmartList<>();
for (Failure failure : ((FailureResult)operationResult).getFailures()) {
failures.add(convert(failure));
}
eventResult = new FailureResultImpl(failures);
}
else if (operationResult instanceof SkippedResult) {
eventResult = new SkippedResultImpl();
}
else if (operationResult instanceof SuccessResult) {
eventResult = new SuccessResultImpl(((SuccessResult)operationResult).isUpToDate());
}
else {
eventResult = new SuccessResultImpl();
}
buildEvent = new FinishEventImpl(progressEvent.getEventId(), parentEventId, eventTime, displayName, eventResult);
}
else if (progressEvent instanceof ExternalSystemStatusEvent statusEvent) {
buildEvent = new ProgressBuildEventImpl(progressEvent.getEventId(), progressEvent.getParentEventId(), eventTime, displayName,
statusEvent.getTotal(), statusEvent.getProgress(), statusEvent.getUnit());
}
else {
buildEvent = new OutputBuildEventImpl(progressEvent.getEventId(), parentEventId, displayName, true);
}
String hint = progressEvent.getDescriptor().getHint();
buildEvent.setHint(hint);
return buildEvent;
}
private static com.intellij.build.events.Failure convert(Failure failure) {
List<com.intellij.build.events.Failure> causes = new SmartList<>();
for (Failure cause : failure.getCauses()) {
causes.add(convert(cause));
}
return new FailureImpl(failure.getMessage(), failure.getDescription(), causes);
}
public static void runTask(@NotNull ExternalSystemTaskExecutionSettings taskSettings,
@NotNull String executorId,
@NotNull Project project,
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.execution.test.runner;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.test.runner.events.TestEventResult;
@@ -11,11 +12,11 @@ import org.jetbrains.plugins.gradle.execution.test.runner.events.TestEventResult
*/
public class GradleSMTestProxy extends SMTestProxy {
@Nullable private final String myClassName;
@NotNull private final String myClassName;
@Nullable private String myParentId;
@Nullable private TestEventResult myLastResult;
public GradleSMTestProxy(String testName, boolean isSuite, @Nullable String locationUrl, @Nullable String className) {
public GradleSMTestProxy(String testName, boolean isSuite, @Nullable String locationUrl, @NotNull String className) {
super(testName, isSuite, locationUrl);
myClassName = className;
}
@@ -29,7 +30,7 @@ public class GradleSMTestProxy extends SMTestProxy {
myParentId = parentId;
}
@Nullable
@NotNull
public String getClassName() {
return myClassName;
}
@@ -1,68 +1,48 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.execution.test.runner;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.task.event.*;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.test.runner.events.*;
public final class GradleTestEventsProcessor {
public static void onStatusChange(GradleTestsExecutionConsole console, ExternalSystemProgressEvent<? extends TestOperationDescriptor> event) {
TestOperationDescriptor descriptor = event.getDescriptor();
private static final Logger LOG = Logger.getInstance("com.intellij.openapi.externalSystem.event-processing");
final TestEventType eventType = getEventType(descriptor, event);
if (eventType == null) {
return;
}
TestEventProcessor testEventProcessor = null;
switch (eventType) {
case BEFORE_SUITE:
testEventProcessor = new BeforeSuiteEventProcessor(console);
break;
case BEFORE_TEST:
testEventProcessor = new BeforeTestEventProcessor(console);
break;
case ON_OUTPUT:
testEventProcessor = new OnOutputEventProcessor(console);
break;
case AFTER_TEST:
testEventProcessor = new AfterTestEventProcessor(console);
break;
case AFTER_SUITE:
testEventProcessor = new AfterSuiteEventProcessor(console);
break;
case CONFIGURATION_ERROR:
case REPORT_LOCATION:
case UNKNOWN_EVENT:
break;
}
if (testEventProcessor != null) {
testEventProcessor.process(event);
public static void onStatusChange(
@NotNull GradleTestsExecutionConsole console,
@NotNull ExternalSystemProgressEvent<? extends TestOperationDescriptor> event
) {
var eventProcessor = createEventProcessor(console, event);
if (eventProcessor != null) {
eventProcessor.process(event);
}
}
private static TestEventType getEventType(@NotNull TestOperationDescriptor descriptor,
@NotNull ExternalSystemProgressEvent event) {
private static @Nullable TestEventProcessor createEventProcessor(
@NotNull GradleTestsExecutionConsole console,
@NotNull ExternalSystemProgressEvent<? extends TestOperationDescriptor> event
) {
var descriptor = event.getDescriptor();
if (event instanceof ExternalSystemStartEvent) {
if (StringUtil.isEmpty(descriptor.getMethodName())) {
return TestEventType.BEFORE_SUITE;
} else {
return TestEventType.BEFORE_TEST;
return new BeforeSuiteEventProcessor(console);
}
return new BeforeTestEventProcessor(console);
}
if (event instanceof ExternalSystemFinishEvent) {
if (StringUtil.isEmpty(descriptor.getMethodName())) {
return TestEventType.AFTER_SUITE;
} else {
return TestEventType.AFTER_TEST;
return new AfterSuiteEventProcessor(console);
}
return new AfterTestEventProcessor(console);
}
if (event instanceof ExternalSystemStatusEvent) {
return TestEventType.ON_OUTPUT;
if (event instanceof ExternalSystemMessageEvent) {
return new OnOutputEventProcessor(console);
}
LOG.warn("Undefined progress event " + event.getClass().getSimpleName() + " " + event);
return null;
}
}
@@ -15,20 +15,42 @@ import org.jetbrains.annotations.ApiStatus
*/
@ApiStatus.Internal
internal interface GradleTestLocationCustomizer {
companion object {
@JvmField
val EP_NAME: ExtensionPointName<GradleTestLocationCustomizer> = ExtensionPointName.create("org.jetbrains.plugins.gradle.testLocationCustomizer")
}
data class GradleTestLocationInfo(val fqClassName: String, val methodName : String?)
/**
* Checks that current test is framework-specific test.
*
* @param parent direct parent of a customizable test node
* @param isSuite is true if location url should be created for test suite otherwise for the test method
* @param fqClassName fully-qualified name of the class containing a test method of a customizable test node
* @param methodName name of a test method of a customizable test node
*/
fun isApplicable(
project: Project,
parent: SMTestProxy,
isSuite: Boolean,
suiteName: String,
fqClassName: String,
methodName: String?
): Boolean
/**
* Produces test framework-specific test location by the data of a test node.
*
* @param parent direct parent of a customizable test node
* @param isSuite is true if location url should be created for test suite otherwise for the test method
* @param fqClassName fully-qualified name of the class containing a test method of a customizable test node
* @param methodName name of a test method of a customizable test node
* @param displayName name of a customizable test node that will be displayed in the UI
*/
fun getLocationInfo(project: Project, parent: SMTestProxy, fqClassName: String, methodName: String?, displayName: String?): GradleTestLocationInfo?
fun createLocationUrl(
parent: SMTestProxy,
isSuite: Boolean,
suiteName: String,
fqClassName: String,
methodName: String?
): String
companion object {
@JvmField
val EP_NAME = ExtensionPointName.create<GradleTestLocationCustomizer>("org.jetbrains.plugins.gradle.testLocationCustomizer")
}
}
@@ -59,17 +59,13 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.action.GradleRerunFailedTestsAction;
import org.jetbrains.plugins.gradle.execution.filters.ReRunTaskFilter;
import org.jetbrains.plugins.gradle.service.project.GradleTasksIndices;
import org.jetbrains.plugins.gradle.service.execution.GradleTestExecutionUtil;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleTaskData;
import java.io.File;
import static org.jetbrains.plugins.gradle.util.GradleConstants.RUN_TASK_AS_TEST;
@@ -264,7 +260,12 @@ public class GradleTestsExecutionConsoleManager
public boolean isApplicableFor(@NotNull ExternalSystemTask task) {
if (task instanceof ExternalSystemExecuteTaskTask taskTask) {
if (StringUtil.equals(taskTask.getExternalSystemId().getId(), GradleConstants.SYSTEM_ID.getId())) {
if (hasTestOption(taskTask) || hasTestTasks(taskTask)) {
var project = taskTask.getIdeProject();
var externalProjectPath = taskTask.getExternalProjectPath();
var tasksAndArguments = taskTask.getTasksToExecute();
var arguments = StringUtil.notNullize(taskTask.getArguments());
var commandLine = GradleTestExecutionUtil.parseCommandLine(tasksAndArguments, arguments);
if (GradleTestExecutionUtil.hasTestTasks(commandLine, project, externalProjectPath)) {
taskTask.putUserData(RUN_TASK_AS_TEST, true);
return true;
}
@@ -273,34 +274,6 @@ public class GradleTestsExecutionConsoleManager
return false;
}
private static boolean hasTestOption(@NotNull ExternalSystemExecuteTaskTask task) {
var options = task.getArguments();
var tasksAndArguments = task.getTasksToExecute();
return options != null && StringUtil.contains(options, GradleConstants.TESTS_ARG_NAME)
|| tasksAndArguments.contains(GradleConstants.TESTS_ARG_NAME);
}
private static boolean hasTestTasks(@NotNull ExternalSystemExecuteTaskTask task) {
var modulePath = getModulePath(task);
var tasksAndArguments = task.getTasksToExecute();
var tasksIndices = GradleTasksIndices.getInstance(task.getIdeProject());
var tasks = tasksIndices.findTasks(modulePath, tasksAndArguments);
return ContainerUtil.or(tasks, it -> isTestTask(it));
}
private static boolean isTestTask(@Nullable GradleTaskData task) {
return task != null && (task.isTest() || "check".equals(task.getName()) && "verification".equals(task.getGroup()));
}
private static @NotNull String getModulePath(@NotNull ExternalSystemExecuteTaskTask task) {
var externalProjectPath = task.getExternalProjectPath();
var file = new File(externalProjectPath);
if (file.isFile()) {
return StringUtil.trimEnd(externalProjectPath, "/" + file.getName());
}
return externalProjectPath;
}
@Override
public AnAction[] getRestartActions(@NotNull final GradleTestsExecutionConsole consoleView) {
JavaRerunFailedTestsAction rerunFailedTestsAction =
@@ -14,11 +14,8 @@ import org.jetbrains.plugins.gradle.execution.test.runner.events.*;
*/
public final class GradleTestsExecutionConsoleOutputProcessor {
private static final Logger LOG = Logger.getInstance(GradleTestsExecutionConsoleOutputProcessor.class);
@SuppressWarnings("HardCodedStringLiteral")
private static final String LOG_EOL = "<ijLogEol/>";
@SuppressWarnings("HardCodedStringLiteral")
private static final String LOG_START = "<ijLog>";
@SuppressWarnings("HardCodedStringLiteral")
private static final String LOG_END = "</ijLog>";
public static void onOutput(@NotNull GradleTestsExecutionConsole executionConsole,
@@ -31,32 +28,7 @@ public final class GradleTestsExecutionConsoleOutputProcessor {
final TestEventXmlView xml = new TestEventXPPXmlView(eventMessage);
final TestEventType eventType = TestEventType.fromValue(xml.getTestEventType());
TestEventProcessor testEventProcessor = null;
switch (eventType) {
case CONFIGURATION_ERROR:
testEventProcessor = new ConfigurationErrorEventProcessor(executionConsole);
break;
case REPORT_LOCATION:
testEventProcessor = new ReportLocationEventProcessor(executionConsole);
break;
case BEFORE_TEST:
testEventProcessor = new BeforeTestEventProcessor(executionConsole);
break;
case ON_OUTPUT:
testEventProcessor = new OnOutputEventProcessor(executionConsole);
break;
case AFTER_TEST:
testEventProcessor = new AfterTestEventProcessor(executionConsole);
break;
case BEFORE_SUITE:
testEventProcessor = new BeforeSuiteEventProcessor(executionConsole);
break;
case AFTER_SUITE:
testEventProcessor = new AfterSuiteEventProcessor(executionConsole);
break;
case UNKNOWN_EVENT:
break;
}
var testEventProcessor = createTestEventProcessor(eventType, executionConsole);
if (testEventProcessor != null) {
testEventProcessor.process(xml);
}
@@ -66,6 +38,22 @@ public final class GradleTestsExecutionConsoleOutputProcessor {
}
}
private static @Nullable TestEventProcessor createTestEventProcessor(
@NotNull TestEventType eventType,
@NotNull GradleTestsExecutionConsole executionConsole
) {
return switch (eventType) {
case CONFIGURATION_ERROR -> new ConfigurationErrorEventProcessor(executionConsole);
case REPORT_LOCATION -> new ReportLocationEventProcessor(executionConsole);
case BEFORE_TEST -> new BeforeTestEventProcessor(executionConsole);
case ON_OUTPUT -> new OnOutputEventProcessor(executionConsole);
case AFTER_TEST -> new AfterTestEventProcessor(executionConsole);
case BEFORE_SUITE -> new BeforeSuiteEventProcessor(executionConsole);
case AFTER_SUITE -> new AfterSuiteEventProcessor(executionConsole);
default -> null;
};
}
@Nullable
private static String getEventMessage(@NotNull GradleTestsExecutionConsole executionConsole,
@NotNull String text,
@@ -78,7 +66,7 @@ public final class GradleTestsExecutionConsoleOutputProcessor {
return null;
}
else {
if (consoleBuffer.length() == 0) {
if (consoleBuffer.isEmpty()) {
if (StringUtil.startsWith(trimmedText, LOG_START) && StringUtil.endsWith(trimmedText, LOG_END)) {
eventMessage = text;
}
@@ -102,7 +90,7 @@ public final class GradleTestsExecutionConsoleOutputProcessor {
}
eventMessage = bufferText;
}
assert consoleBuffer.length() == 0;
assert consoleBuffer.isEmpty();
return eventMessage;
}
}
@@ -5,17 +5,18 @@ import com.intellij.execution.testframework.JavaTestLocator;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.testframework.sm.runner.ui.SMTestRunnerResultsForm;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleConsoleProperties;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleSMTestProxy;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestLocationCustomizer;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsole;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import static org.jetbrains.plugins.gradle.execution.test.runner.GradleTestLocationCustomizer.GradleTestLocationInfo;
/**
* @author Vladislav.Soroka
*/
@@ -43,21 +44,24 @@ public abstract class AbstractTestEventProcessor implements TestEventProcessor {
return (GradleConsoleProperties)getExecutionConsole().getProperties();
}
@NotNull
protected String findLocationUrl(@Nullable String name, @NotNull String fqClassName) {
return findLocationUrl(JavaTestLocator.TEST_PROTOCOL, name, fqClassName);
protected boolean isSuite() {
return false;
}
@NotNull
protected static String findLocationUrl(@NotNull String protocol, @Nullable String name, @NotNull String fqClassName) {
return name == null
? JavaTestLocator.createLocationUrl(protocol, fqClassName)
: JavaTestLocator.createLocationUrl(protocol, fqClassName, name);
protected @Nullable SMTestProxy findTestProxy(@Nullable String testId) {
return getExecutionConsole().getTestsMap().get(testId);
}
@Nullable
protected SMTestProxy findTestProxy(final String proxyId) {
return getExecutionConsole().getTestsMap().get(proxyId);
protected @NotNull SMTestProxy findParentTestProxy(@Nullable String parentTestId) {
var rootNode = getResultsViewer().getTestsRootNode();
if (StringUtil.isEmpty(parentTestId)) {
return rootNode;
}
var node = findTestProxy(parentTestId);
if (node == null) {
return rootNode;
}
return node;
}
protected void registerTestProxy(final String proxyId, SMTestProxy testProxy) {
@@ -72,15 +76,62 @@ public abstract class AbstractTestEventProcessor implements TestEventProcessor {
return GradleConsoleProperties.SHOW_INTERNAL_TEST_NODES.value(getProperties());
}
protected final @NotNull String computeLocationUrl(@Nullable SMTestProxy parentProxy, @NotNull String fqClassName, @Nullable String name, @Nullable String displayName) {
if (parentProxy != null) {
for (GradleTestLocationCustomizer customizer : GradleTestLocationCustomizer.EP_NAME.getExtensionList()) {
GradleTestLocationInfo location = customizer.getLocationInfo(getProject(), parentProxy, fqClassName, name, displayName);
if (location != null) {
return findLocationUrl(location.getMethodName(), location.getFqClassName());
}
protected @NotNull GradleSMTestProxy createTestProxy(
@Nullable String parentTestId,
@NotNull String suiteName,
@NotNull String fqClassName,
@Nullable String methodName,
@Nullable String displayName
) {
var parentTestProxy = findParentTestProxy(parentTestId);
var locationUrl = createLocationUrl(parentTestProxy, suiteName, fqClassName, methodName);
var testProxy = new GradleSMTestProxy(displayName, methodName == null, locationUrl, fqClassName);
testProxy.setLocator(getExecutionConsole().getUrlProvider());
testProxy.setParentId(parentTestId);
return testProxy;
}
private @NotNull String createLocationUrl(
@NotNull SMTestProxy parentProxy,
@NotNull String suiteName,
@NotNull String fqClassName,
@Nullable String methodName
) {
var project = getProject();
var isSuite = isSuite();
var testLocationCustomizer = GradleTestLocationCustomizer.EP_NAME
.findFirstSafe(it -> it.isApplicable(project, parentProxy, isSuite, suiteName, fqClassName, methodName));
if (testLocationCustomizer != null) {
return testLocationCustomizer.createLocationUrl(parentProxy, isSuite, suiteName, fqClassName, methodName);
}
var locationProtocol = isSuite ? JavaTestLocator.SUITE_PROTOCOL : JavaTestLocator.TEST_PROTOCOL;
return JavaTestLocator.createLocationUrl(locationProtocol, fqClassName, methodName);
}
protected void setParentForAllNodesInTreePath(@NotNull GradleSMTestProxy node) {
while (node != null) {
var parentId = node.getParentId();
var parentNode = findParentTestProxy(parentId);
if (node.getParent() == null) {
parentNode.addChild(node);
}
if (!node.isInProgress()) {
node.setStarted();
getResultsViewer().onTestStarted(node);
getExecutionConsole().getEventPublisher().onTestStarted(node);
}
node = ObjectUtils.tryCast(parentNode, GradleSMTestProxy.class);
}
}
protected void setStartedForAllNodesInTreePath(@NotNull GradleSMTestProxy node) {
while (node != null) {
if (!node.isInProgress()) {
node.setStarted();
getResultsViewer().onTestStarted(node);
getExecutionConsole().getEventPublisher().onTestStarted(node);
}
node = ObjectUtils.tryCast(node.getParent(), GradleSMTestProxy.class);
}
return findLocationUrl(name, fqClassName);
}
}
@@ -15,13 +15,11 @@
*/
package org.jetbrains.plugins.gradle.execution.test.runner.events;
import com.intellij.execution.testframework.JavaTestLocator;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemFinishEvent;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemProgressEvent;
import com.intellij.openapi.externalSystem.model.task.event.TestOperationDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleSMTestProxy;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsole;
@@ -34,6 +32,10 @@ public class AfterSuiteEventProcessor extends AbstractTestEventProcessor {
super(executionConsole);
}
@Override
protected boolean isSuite() {
return true;
}
@Override
public void process(@NotNull ExternalSystemProgressEvent<? extends TestOperationDescriptor> testEvent) {
@@ -83,10 +85,4 @@ public class AfterSuiteEventProcessor extends AbstractTestEventProcessor {
getExecutionConsole().getEventPublisher().onSuiteFinished(testProxy);
}
}
@Override
@NotNull
protected String findLocationUrl(@Nullable String name, @NotNull String fqClassName) {
return findLocationUrl(JavaTestLocator.SUITE_PROTOCOL, name, fqClassName);
}
}
@@ -1,8 +1,6 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.execution.test.runner.events;
import com.intellij.execution.testframework.JavaTestLocator;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemProgressEvent;
import com.intellij.openapi.externalSystem.model.task.event.TestOperationDescriptor;
import com.intellij.openapi.util.text.StringUtil;
@@ -23,72 +21,76 @@ public class BeforeSuiteEventProcessor extends AbstractTestEventProcessor {
}
@Override
public void process(@NotNull final TestEventXmlView eventXml) throws TestEventXmlView.XmlParserException {
final String testId = eventXml.getTestId();
final String parentTestId = eventXml.getTestParentId();
final String name = eventXml.getTestDisplayName();
final String fqClassName = eventXml.getTestClassName();
protected boolean isSuite() {
return true;
}
doProcess(testId, parentTestId, name, fqClassName);
@Override
public void process(@NotNull final TestEventXmlView eventXml) throws TestEventXmlView.XmlParserException {
var testId = eventXml.getTestId();
var parentTestId = eventXml.getTestParentId();
var suiteName = ObjectUtils.coalesce(StringUtil.nullize(eventXml.getTestClassName()), eventXml.getTestDisplayName());
var fqClassName = eventXml.getTestClassName();
var displayName = eventXml.getTestDisplayName();
doProcess(testId, parentTestId, suiteName, fqClassName, displayName);
}
@Override
public void process(@NotNull ExternalSystemProgressEvent<? extends TestOperationDescriptor> testEvent) {
TestOperationDescriptor testDescriptor = testEvent.getDescriptor();
final String testId = testEvent.getEventId();
final String parentTestId = testEvent.getParentEventId();
final String name = ObjectUtils.coalesce(testDescriptor.getDisplayName(), testDescriptor.getMethodName(), testId);
final String fqClassName = testDescriptor.getClassName();
var testDescriptor = testEvent.getDescriptor();
var testId = testEvent.getEventId();
var parentTestId = testEvent.getParentEventId();
var suiteName = StringUtil.notNullize(testDescriptor.getSuiteName());
var fqClassName = StringUtil.notNullize(testDescriptor.getClassName());
var displayName = testDescriptor.getDisplayName();
doProcess(testId, parentTestId, name, fqClassName);
doProcess(testId, parentTestId, suiteName, fqClassName, displayName);
}
private void doProcess(
@NotNull String testId,
@Nullable String parentTestId,
@NotNull String suiteName,
@NotNull String fqClassName,
@Nullable String displayName
) {
var isCombineSameTests = !showInternalTestNodes();
private void doProcess(String testId, String parentTestId, String name, String fqClassName) {
if (StringUtil.isEmpty(parentTestId)) {
registerTestProxy(testId, getResultsViewer().getTestsRootNode());
if (isCombineSameTests && isHiddenTestNode(suiteName)) {
var parentTestProxy = findParentTestProxy(parentTestId);
registerTestProxy(testId, parentTestProxy);
return;
}
else {
SMTestProxy parentTest = findTestProxy(parentTestId);
if (isHiddenTestNode(name, parentTest)) {
registerTestProxy(testId, parentTest);
}
else {
boolean combineTestsOfTheSameSuite = !showInternalTestNodes();
String sameSuiteId = name + fqClassName;
if (combineTestsOfTheSameSuite) {
SMTestProxy testProxy = findTestProxy(sameSuiteId);
if (testProxy instanceof GradleSMTestProxy && Objects.equals(testProxy.getParent(), parentTest)) {
registerTestProxy(testId, testProxy);
if (!testProxy.isInProgress()) {
testProxy.setStarted();
}
return;
}
}
String locationUrl = computeLocationUrl(parentTest, fqClassName, null, name);
final GradleSMTestProxy testProxy = new GradleSMTestProxy(name, true, locationUrl, null);
testProxy.setLocator(getExecutionConsole().getUrlProvider());
testProxy.setParentId(parentTestId);
testProxy.setStarted();
if (isCombineSameTests) {
var testProxy = findSuiteTestProxy(suiteName, parentTestId);
if (testProxy != null) {
registerTestProxy(testId, testProxy);
if (combineTestsOfTheSameSuite) {
registerTestProxy(sameSuiteId, testProxy);
}
return;
}
}
var testProxy = createTestProxy(parentTestId, suiteName, fqClassName, null, displayName);
registerTestProxy(testId, testProxy);
if (isCombineSameTests) {
registerTestProxy(fqClassName, testProxy);
}
}
@Override
@NotNull
protected String findLocationUrl(@Nullable String name, @NotNull String fqClassName) {
return findLocationUrl(JavaTestLocator.SUITE_PROTOCOL, name, fqClassName);
private @Nullable GradleSMTestProxy findSuiteTestProxy(@NotNull String suiteId, @Nullable String parentTestId) {
var parentTestProxy = findParentTestProxy(parentTestId);
var testProxy = findTestProxy(suiteId);
if (testProxy instanceof GradleSMTestProxy) {
if (Objects.equals(testProxy.getParent(), parentTestProxy)) {
return (GradleSMTestProxy)testProxy;
}
}
return null;
}
private boolean isHiddenTestNode(String name, SMTestProxy parentTest) {
return parentTest != null &&
!showInternalTestNodes() &&
StringUtil.startsWith(name, "Gradle Test Executor");
private static boolean isHiddenTestNode(@Nullable String suiteName) {
return suiteName == null || suiteName.startsWith("Gradle Test Executor") || suiteName.startsWith("Gradle Test Run");
}
}
@@ -1,18 +1,13 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.execution.test.runner.events;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemProgressEvent;
import com.intellij.openapi.externalSystem.model.task.event.TestOperationDescriptor;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleSMTestProxy;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsole;
import java.util.List;
/**
* @author Vladislav.Soroka
*/
@@ -24,62 +19,40 @@ public class BeforeTestEventProcessor extends AbstractTestEventProcessor {
@Override
public void process(@NotNull final TestEventXmlView eventXml) throws TestEventXmlView.XmlParserException {
final String testId = eventXml.getTestId();
final String parentTestId = eventXml.getTestParentId();
final String name = eventXml.getTestName();
final String displayName = eventXml.getTestDisplayName();
final String fqClassName = eventXml.getTestClassName();
var testId = eventXml.getTestId();
var parentTestId = eventXml.getTestParentId();
var suiteName = eventXml.getTestClassName();
var fqClassName = eventXml.getTestClassName();
var methodName = eventXml.getTestName();
var displayName = eventXml.getTestDisplayName();
doProcess(testId, parentTestId, name, displayName, fqClassName);
doProcess(testId, parentTestId, suiteName, fqClassName, methodName, displayName);
}
@Override
public void process(@NotNull ExternalSystemProgressEvent<? extends TestOperationDescriptor> testEvent) {
TestOperationDescriptor testDescriptor = testEvent.getDescriptor();
final String testId = testEvent.getEventId();
final String parentTestId = testEvent.getParentEventId();
final String fqClassName = testDescriptor.getClassName();
var testDescriptor = testEvent.getDescriptor();
var testId = testEvent.getEventId();
var parentTestId = testEvent.getParentEventId();
var suiteName = StringUtil.notNullize(testDescriptor.getSuiteName());
var fqClassName = StringUtil.notNullize(testDescriptor.getClassName());
var methodName = testDescriptor.getMethodName();
var displayName = testDescriptor.getDisplayName();
doProcess(testId, parentTestId, testDescriptor.getMethodName(), testDescriptor.getDisplayName(), fqClassName);
doProcess(testId, parentTestId, suiteName, fqClassName, methodName, displayName);
}
private void doProcess(String testId, String parentTestId, String name, String displayName, String fqClassName) {
String locationUrl = computeLocationUrl(findTestProxy(parentTestId), fqClassName, name, displayName);
final GradleSMTestProxy testProxy = new GradleSMTestProxy(displayName, false, locationUrl, fqClassName);
testProxy.setStarted();
testProxy.setLocator(getExecutionConsole().getUrlProvider());
private void doProcess(
@NotNull String testId,
@Nullable String parentTestId,
@NotNull String suiteName,
@NotNull String fqClassName,
@Nullable String methodName,
@Nullable String displayName
) {
var testProxy = createTestProxy(parentTestId, suiteName, fqClassName, methodName, displayName);
registerTestProxy(testId, testProxy);
if (StringUtil.isEmpty(parentTestId)) {
getResultsViewer().getTestsRootNode().addChild(testProxy);
}
else {
final SMTestProxy parentTestProxy = findTestProxy(parentTestId);
if (parentTestProxy != null) {
final List<GradleSMTestProxy> notYetAddedParents = new SmartList<>();
SMTestProxy currentParentTestProxy = parentTestProxy;
while (currentParentTestProxy instanceof GradleSMTestProxy) {
final String parentId = ((GradleSMTestProxy)currentParentTestProxy).getParentId();
if (currentParentTestProxy.getParent() == null && parentId != null) {
notYetAddedParents.add((GradleSMTestProxy)currentParentTestProxy);
}
currentParentTestProxy = findTestProxy(parentId);
}
for (GradleSMTestProxy gradleSMTestProxy : ContainerUtil.reverse(notYetAddedParents)) {
final SMTestProxy parentTestProxy1 = findTestProxy(gradleSMTestProxy.getParentId());
if (parentTestProxy1 != null) {
parentTestProxy1.addChild(gradleSMTestProxy);
getResultsViewer().onSuiteStarted(gradleSMTestProxy);
getExecutionConsole().getEventPublisher().onSuiteStarted(gradleSMTestProxy);
}
}
parentTestProxy.addChild(testProxy);
}
}
getResultsViewer().onTestStarted(testProxy);
getExecutionConsole().getEventPublisher().onTestStarted(testProxy);
setParentForAllNodesInTreePath(testProxy);
setStartedForAllNodesInTreePath(testProxy);
}
}
@@ -2,13 +2,13 @@
package org.jetbrains.plugins.gradle.execution.test.runner.events;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.testframework.sm.runner.events.TestOutputEvent;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemMessageEvent;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemProgressEvent;
import com.intellij.openapi.externalSystem.model.task.event.TestOperationDescriptor;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsole;
/**
@@ -16,47 +16,37 @@ import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionCo
*/
public class OnOutputEventProcessor extends AbstractTestEventProcessor {
private static final String OUT = "StdOut";
private static final String ERR = "StdErr";
public OnOutputEventProcessor(GradleTestsExecutionConsole executionConsole) {
super(executionConsole);
}
@Override
public void process(@NotNull final TestEventXmlView eventXml) throws TestEventXmlView.XmlParserException {
final String testId = eventXml.getTestId();
final String destinationString = eventXml.getTestEventTestDescription();
final String output = decode(eventXml.getTestEventTest());
public void process(@NotNull TestEventXmlView eventXml) throws TestEventXmlView.XmlParserException {
var testId = eventXml.getTestId();
var output = decode(eventXml.getTestEventTest());
var isStdOut = "StdOut".equals(eventXml.getTestEventTestDescription());
Key destination = OUT.equals(destinationString) ? ProcessOutputTypes.STDOUT : ProcessOutputTypes.STDERR;
doProcess(testId, output, destination);
doProcess(testId, output, isStdOut);
}
@Override
public void process(@NotNull ExternalSystemProgressEvent<? extends TestOperationDescriptor> testEvent) {
if (!(testEvent instanceof ExternalSystemMessageEvent)) {
return;
}
TestOperationDescriptor testDescriptor = testEvent.getDescriptor();
if (testEvent instanceof ExternalSystemMessageEvent<?> messageEvent) {
var parentTestId = testEvent.getParentEventId();
var isStdOut = messageEvent.isStdOut();
var message = StringUtil.notNullize(messageEvent.getMessage());
final String testId = testEvent.getEventId();
final String description = ((ExternalSystemMessageEvent<?>)testEvent).getDescription();
if (description == null) {
doProcess(testId, "", ProcessOutputTypes.STDERR);
} else if (description.startsWith(OUT)) {
doProcess(testId, description.substring(OUT.length()), ProcessOutputTypes.STDOUT);
} else if (description.startsWith(ERR)) {
doProcess(testId, description.substring(ERR.length()), ProcessOutputTypes.STDERR);
doProcess(parentTestId, message, isStdOut);
}
}
private void doProcess(String testId, String output, @NotNull Key type) {
SMTestProxy testProxy = findTestProxy(testId);
if (testProxy == null) return;
private void doProcess(@Nullable String parentTestId, @NotNull String message, boolean isStdOut) {
var testProxy = findParentTestProxy(parentTestId);
var name = testProxy.getName();
var event = new TestOutputEvent(name, message, isStdOut);
var destination = isStdOut ? ProcessOutputTypes.STDOUT : ProcessOutputTypes.STDERR;
testProxy.addOutput(output, type);
getExecutionConsole().getEventPublisher().onTestOutput(testProxy, new TestOutputEvent(testProxy.getName(), output, type == ProcessOutputTypes.STDOUT));
testProxy.addOutput(message, destination);
getExecutionConsole().getEventPublisher().onTestOutput(testProxy, event);
}
}
@@ -1,45 +1,78 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.execution.test.runner.spock
import com.intellij.execution.testframework.JavaTestLocator
import com.intellij.execution.testframework.sm.runner.SMTestProxy
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.io.URLUtil
import com.intellij.util.text.nullize
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestLocationCustomizer
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestLocationCustomizer.GradleTestLocationInfo
import org.jetbrains.plugins.groovy.ext.spock.isSpockSpecification
internal class SpockGradleTestLocationCustomizer : GradleTestLocationCustomizer {
override fun getLocationInfo(project: Project,
parent: SMTestProxy,
fqClassName: String,
methodName: String?,
displayName: String?): GradleTestLocationInfo? {
val className = getClassName(fqClassName, parent)
if (!shouldProcessAsSpock(project, className, methodName)) return null
val actualMethodName = if (fqClassName.isEmpty() && displayName != null && methodName == null) {
displayName
}
else {
parent.name
}
return GradleTestLocationInfo(className, actualMethodName)
}
}
private fun shouldProcessAsSpock(project: Project,
className: String,
name: String?): Boolean {
return runReadAction {
DumbService.getInstance(project).computeWithAlternativeResolveEnabled<Boolean, Throwable> {
val clazz = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project))
clazz != null && clazz.isSpockSpecification() && (name == null || clazz.methods.all { it.name != name })
override fun isApplicable(
project: Project,
parent: SMTestProxy,
isSuite: Boolean,
suiteName: String,
fqClassName: String,
methodName: String?
): Boolean {
return runReadAction {
DumbService.getInstance(project).computeWithAlternativeResolveEnabled<Boolean, Throwable> {
val patchedFqClassName = patchClassName(parent, suiteName, fqClassName)
val patchedMethodName = patchMethodName(parent, isSuite, suiteName, fqClassName, methodName)
val scope = GlobalSearchScope.allScope(project)
val psiFacade = JavaPsiFacade.getInstance(project)
val psiClass = psiFacade.findClass(patchedFqClassName, scope)
psiClass != null && psiClass.isSpockSpecification() && (patchedMethodName == null || psiClass.methods.any { it.name == patchedMethodName })
}
}
}
}
private fun getClassName(fqClassName: String, parent: SMTestProxy): String {
return fqClassName.takeUnless { it.isEmpty() } ?: parent.name
override fun createLocationUrl(
parent: SMTestProxy,
isSuite: Boolean,
suiteName: String,
fqClassName: String,
methodName: String?
): String {
val protocol = if (isSuite) JavaTestLocator.SUITE_PROTOCOL else JavaTestLocator.TEST_PROTOCOL
val patchedFqClassName = patchClassName(parent, suiteName, fqClassName)
val patchedMethodName = patchMethodName(parent, isSuite, suiteName, fqClassName, methodName)
return JavaTestLocator.createLocationUrl(protocol, patchedFqClassName, patchedMethodName)
}
private fun patchClassName(parent: SMTestProxy, suiteName: String, fqClassName: String): String {
return when {
fqClassName.isEmpty() -> getParentClassName(parent) ?: suiteName
else -> fqClassName
}
}
private fun patchMethodName(parent: SMTestProxy, isSuite: Boolean, suiteName: String, fqClassName: String, methodName: String?): String? {
return when {
!isSuite -> getParentMethodName(parent) ?: methodName.nullize() ?: suiteName
fqClassName.isEmpty() -> methodName.nullize() ?: getParentMethodName(parent) ?: suiteName
else -> methodName
}
}
private fun getParentClassName(parent: SMTestProxy): String? {
val locationUrl = parent.locationUrl ?: return null
val locationPath = URLUtil.extractPath(locationUrl)
return StringUtil.substringBefore(locationPath, "/") ?: locationPath
}
private fun getParentMethodName(parent: SMTestProxy): String? {
val locationUrl = parent.locationUrl ?: return null
val locationPath = URLUtil.extractPath(locationUrl)
return StringUtil.substringAfter(locationPath, "/")
}
}
@@ -2,98 +2,197 @@
package org.jetbrains.plugins.gradle.service.execution;
import com.intellij.build.events.EventResult;
import com.intellij.build.events.impl.*;
import com.intellij.build.events.impl.FinishEventImpl;
import com.intellij.build.events.impl.ProgressBuildEventImpl;
import com.intellij.build.events.impl.StartEventImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemBuildEvent;
import com.intellij.openapi.externalSystem.model.task.event.OperationResult;
import com.intellij.openapi.externalSystem.model.task.event.TestOperationDescriptor;
import com.intellij.openapi.externalSystem.model.task.event.*;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import org.gradle.tooling.events.FailureResult;
import org.gradle.tooling.events.OperationDescriptor;
import org.gradle.tooling.events.SkippedResult;
import org.gradle.tooling.events.SuccessResult;
import org.gradle.tooling.events.*;
import org.gradle.tooling.events.task.TaskFinishEvent;
import org.gradle.tooling.events.task.TaskProgressEvent;
import org.gradle.tooling.events.task.TaskStartEvent;
import org.gradle.tooling.events.task.TaskSuccessResult;
import org.gradle.tooling.events.test.TestProgressEvent;
import org.gradle.tooling.events.test.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import java.util.List;
import java.util.StringJoiner;
/**
* @author Vladislav.Soroka
*/
public final class GradleProgressEventConverter {
static EventId getEventId(@NotNull ProgressEvent event, @NotNull String operationId) {
OperationDescriptor descriptor = event.getDescriptor();
String eventId = operationId + descriptor.getDisplayName();
String parentEventId = descriptor.getParent() == null ? null :
operationId + descriptor.getParent().getDisplayName();
return new EventId(eventId, parentEventId);
private static final Logger LOG = Logger.getInstance("com.intellij.openapi.externalSystem.event-processing");
private static @NotNull String createEventId(@NotNull OperationDescriptor descriptor, @NotNull String operationId) {
var joiner = new StringJoiner(" > ");
joiner.add("[" + operationId + "]");
var currentDescriptor = descriptor;
while (currentDescriptor != null) {
joiner.add("[" + currentDescriptor.getDisplayName() + "]");
currentDescriptor = currentDescriptor.getParent();
}
return joiner.toString();
}
@NotNull
public static ExternalSystemTaskNotificationEvent convert(@NotNull ExternalSystemTaskId id,
@NotNull ProgressEvent event,
@NotNull String operationId) {
return convert(id, event, getEventId(event, operationId));
public static @Nullable ExternalSystemTaskNotificationEvent createTaskNotificationEvent(
@NotNull ExternalSystemTaskId taskId,
@NotNull String operationId,
@NotNull ProgressEvent event
) {
if (event instanceof TaskProgressEvent taskProgressEvent) {
return convertTaskProgressEvent(taskProgressEvent, taskId, operationId);
}
return convertTestProgressEvent(event, taskId, operationId);
}
@NotNull
public static ExternalSystemTaskNotificationEvent convert(@NotNull ExternalSystemTaskId id,
@NotNull ProgressEvent event,
@NotNull EventId eventId) {
@NlsSafe final String description = event.getDescriptor().getName();
private static @NotNull ExternalSystemTaskNotificationEvent convertTaskProgressEvent(
@NotNull TaskProgressEvent event,
@NotNull ExternalSystemTaskId taskId,
@NotNull String operationId
) {
var eventId = createEventId(event.getDescriptor(), operationId);
var eventTime = event.getEventTime();
var message = event.getDescriptor().getName();
if (event instanceof StartEvent) {
return new ExternalSystemBuildEvent(
id, new StartEventImpl(eventId.id, eventId.parentId, event.getEventTime(), description));
if (event instanceof TaskStartEvent) {
return new ExternalSystemBuildEvent(taskId, new StartEventImpl(eventId, taskId, eventTime, message));
}
else if (event instanceof TaskFinishEvent finishEvent) {
var result = finishEvent.getResult();
var eventResult = convertTaskProgressEventResult(result);
if (eventResult != null) {
return new ExternalSystemBuildEvent(taskId, new FinishEventImpl(eventId, taskId, eventTime, message, eventResult));
}
}
else if (event instanceof StatusEvent statusEvent) {
return new ExternalSystemBuildEvent(id, new ProgressBuildEventImpl(
eventId.id, eventId.parentId, event.getEventTime(), description, statusEvent.getTotal(), statusEvent.getProgress(),
statusEvent.getUnit()));
}
else if (event instanceof FinishEvent) {
return new ExternalSystemBuildEvent(
id,
new FinishEventImpl(eventId.id, eventId.parentId, event.getEventTime(), description, convert(((FinishEvent)event).getResult())));
}
else if (event instanceof TaskProgressEvent) {
return new ExternalSystemBuildEvent(
id, new ProgressBuildEventImpl(eventId.id, eventId.parentId, event.getEventTime(), description, -1, -1, ""));
}
else {
return new ExternalSystemTaskNotificationEvent(id, description);
var total = statusEvent.getTotal();
var progress = statusEvent.getProgress();
var unit = statusEvent.getUnit();
return new ExternalSystemBuildEvent(taskId, new ProgressBuildEventImpl(eventId, taskId, eventTime, message, total, progress, unit));
}
LOG.warn("Undefined Gradle event " + event.getClass().getSimpleName() + " " + event);
var description = event.getDescriptor().getName();
return new ExternalSystemTaskNotificationEvent(taskId, description);
}
@NotNull
public static ExternalSystemTaskNotificationEvent convert(ExternalSystemTaskId id, ProgressEvent event) {
return convert(id, event, "");
private static @Nullable EventResult convertTaskProgressEventResult(@NotNull org.gradle.tooling.events.OperationResult result) {
if (result instanceof SuccessResult) {
var isUpToDate = result instanceof TaskSuccessResult && ((TaskSuccessResult)result).isUpToDate();
return new com.intellij.build.events.impl.SuccessResultImpl(isUpToDate);
}
if (result instanceof FailureResult) {
return new com.intellij.build.events.impl.FailureResultImpl(null, null);
}
if (result instanceof SkippedResult) {
return new com.intellij.build.events.impl.SkippedResultImpl();
}
LOG.warn("Undefined operation result " + result.getClass().getSimpleName() + " " + result);
return null;
}
@NotNull
private static EventResult convert(OperationResult operationResult) {
if (operationResult instanceof FailureResult) {
return new FailureResultImpl(null, null);
private static @Nullable ExternalSystemTaskNotificationEvent convertTestProgressEvent(
@NotNull ProgressEvent event,
@NotNull ExternalSystemTaskId taskId,
@NotNull String operationId
) {
var eventId = createEventId(event.getDescriptor(), operationId);
var parentEventId = ObjectUtils.doIfNotNull(event.getDescriptor().getParent(), it -> createEventId(it, operationId));
var descriptor = convertDescriptor(event);
if (event instanceof TestStartEvent) {
return new ExternalSystemTaskExecutionEvent(taskId, new ExternalSystemStartEventImpl<>(eventId, parentEventId, descriptor));
}
else if (operationResult instanceof SkippedResult) {
return new SkippedResultImpl();
if (event instanceof TestFinishEvent finishEvent) {
var result = finishEvent.getResult();
var operationResult = convertTestProgressEventResult(result);
if (operationResult != null) {
var esEvent = new ExternalSystemFinishEventImpl<>(eventId, parentEventId, descriptor, operationResult);
return new ExternalSystemTaskExecutionEvent(taskId, esEvent);
}
}
else {
final boolean isUpToDate = operationResult instanceof TaskSuccessResult && ((TaskSuccessResult)operationResult).isUpToDate();
return new SuccessResultImpl(isUpToDate);
if (event instanceof TestOutputEvent outputEvent) {
var outputDescriptor = outputEvent.getDescriptor();
var destination = outputDescriptor.getDestination();
var isStdOut = destination == Destination.StdOut;
var message = outputDescriptor.getMessage();
var description = (isStdOut ? "StdOut" : "StdErr") + message;
var esEvent = new ExternalSystemMessageEventImpl<>(eventId, parentEventId, descriptor, isStdOut, message, description);
return new ExternalSystemTaskExecutionEvent(taskId, esEvent);
}
return null;
}
@Nullable
static ExternalSystemTaskNotificationEvent createProgressBuildEvent(@NotNull ExternalSystemTaskId taskId,
@NotNull Object id,
@NotNull ProgressEvent event) {
private static @Nullable OperationResult convertTestProgressEventResult(@NotNull org.gradle.tooling.events.OperationResult result) {
var startTime = result.getStartTime();
var endTime = result.getEndTime();
if (result instanceof SuccessResult) {
var isUpToDate = result instanceof TaskSuccessResult && ((TaskSuccessResult)result).isUpToDate();
return new SuccessResultImpl(startTime, endTime, isUpToDate);
}
if (result instanceof FailureResult) {
var failures = convertFailureResult((FailureResult)result);
return new FailureResultImpl(startTime, endTime, failures);
}
if (result instanceof SkippedResult) {
return new SkippedResultImpl(startTime, endTime);
}
LOG.warn("Undefined operation result " + result.getClass().getSimpleName() + " " + result);
return null;
}
private static @NotNull List<Failure> convertFailureResult(@NotNull FailureResult failure) {
return ContainerUtil.map(failure.getFailures(), it -> convertFailure(it));
}
private static @NotNull Failure convertFailure(@NotNull org.gradle.tooling.Failure failure) {
return new FailureImpl(
failure.getMessage(),
failure.getDescription(),
ContainerUtil.map(failure.getCauses(), it -> convertFailure(it))
);
}
private static @NotNull TestOperationDescriptor convertDescriptor(@NotNull ProgressEvent event) {
var descriptor = event.getDescriptor();
var eventTime = event.getEventTime();
var displayName = descriptor.getDisplayName();
if (descriptor instanceof JvmTestOperationDescriptor jvmDescriptor) {
var suiteName = jvmDescriptor.getSuiteName();
var className = jvmDescriptor.getClassName();
var methodName = jvmDescriptor.getMethodName();
return new TestOperationDescriptorImpl(displayName, eventTime, suiteName, className, methodName);
}
return new TestOperationDescriptorImpl(displayName, eventTime, null, null, null);
}
public static @Nullable ExternalSystemTaskNotificationEvent createProgressBuildEvent(
@NotNull ExternalSystemTaskId taskId,
@NotNull Object id,
@NotNull ProgressEvent event
) {
long total = -1;
long progress = -1;
String unit = "";
@NlsSafe String operationName = event.getDescriptor().getName();
if (operationName.startsWith("Download ")) {
String path = operationName.substring("Download ".length());
operationName = GradleBundle.message("progress.title.download", getFileName(path));
operationName = GradleBundle.message("progress.title.download", PathUtil.getFileName(path));
}
else if (event instanceof TaskProgressEvent) {
operationName = GradleBundle.message("progress.title.run.tasks");
@@ -116,17 +215,18 @@ public final class GradleProgressEventConverter {
taskId, new ProgressBuildEventImpl(id, null, event.getEventTime(), operationName + "...", total, progress, unit));
}
@Nullable
static ExternalSystemTaskNotificationEvent legacyCreateProgressBuildEvent(@NotNull ExternalSystemTaskId taskId,
@NotNull Object id,
@NotNull String event) {
public static @Nullable ExternalSystemTaskNotificationEvent legacyCreateProgressBuildEvent(
@NotNull ExternalSystemTaskId taskId,
@NotNull Object id,
@NotNull String event
) {
long total = -1;
long progress = -1;
String unit = "";
@NlsSafe String operationName = event;
if (operationName.startsWith("Download ")) {
String path = operationName.substring("Download ".length());
operationName = GradleBundle.message("progress.title.download", getFileName(path));
operationName = GradleBundle.message("progress.title.download", PathUtil.getFileName(path));
}
else if (operationName.startsWith("Task: ")) {
operationName = GradleBundle.message("progress.title.run.tasks");
@@ -147,23 +247,10 @@ public final class GradleProgressEventConverter {
taskId, new ProgressBuildEventImpl(id, null, 0, operationName + "...", total, progress, unit));
}
@NotNull
private static String getFileName(String path) {
int index = path.lastIndexOf('/');
if (index > 0) {
String fileName = path.substring(index + 1);
if (!fileName.isEmpty()) return fileName;
}
return path;
}
static class EventId {
Object id;
Object parentId;
EventId(Object id, Object parentId) {
this.id = id;
this.parentId = parentId;
}
public static @NotNull ExternalSystemTaskNotificationEvent legacyCreateTaskNotificationEvent(
@NotNull ExternalSystemTaskId taskId,
@NotNull String event
) {
return new ExternalSystemTaskNotificationEvent(taskId, event);
}
}
@@ -10,22 +10,17 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
import com.intellij.openapi.externalSystem.model.task.event.TestOperationDescriptor;
import com.intellij.openapi.externalSystem.model.task.event.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.Navigatable;
import com.intellij.util.containers.ContainerUtil;
import org.gradle.internal.impldep.com.google.gson.GsonBuilder;
import org.gradle.tooling.ProgressEvent;
import org.gradle.tooling.ProgressListener;
import org.gradle.tooling.events.FinishEvent;
import org.gradle.tooling.events.OperationResult;
import org.gradle.tooling.events.ProgressEvent;
import org.gradle.tooling.events.ProgressListener;
import org.gradle.tooling.events.StatusEvent;
import org.gradle.tooling.events.task.TaskProgressEvent;
import org.gradle.tooling.events.test.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.tooling.Message;
@@ -42,7 +37,7 @@ import static org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilder.MO
/**
* @author Vladislav.Soroka
*/
public class GradleProgressListener implements ProgressListener, org.gradle.tooling.events.ProgressListener {
public class GradleProgressListener implements ProgressListener, org.gradle.tooling.ProgressListener {
private static final Logger LOG = Logger.getInstance(GradleProgressListener.class);
private final ExternalSystemTaskNotificationListener myListener;
@@ -53,143 +48,60 @@ public class GradleProgressListener implements ProgressListener, org.gradle.tool
private static final String STARTING_GRADLE_DAEMON_EVENT = "Starting Gradle Daemon";
private ExternalSystemTaskNotificationEvent myLastStatusChange = null;
public GradleProgressListener(@NotNull ExternalSystemTaskNotificationListener listener,
@NotNull ExternalSystemTaskId taskId) {
public GradleProgressListener(
@NotNull ExternalSystemTaskNotificationListener listener,
@NotNull ExternalSystemTaskId taskId
) {
this(listener, taskId, null);
}
public GradleProgressListener(@NotNull ExternalSystemTaskNotificationListener listener,
@NotNull ExternalSystemTaskId taskId,
@Nullable String buildRootDir) {
public GradleProgressListener(
@NotNull ExternalSystemTaskNotificationListener listener,
@NotNull ExternalSystemTaskId taskId,
@Nullable String buildRootDir
) {
myListener = listener;
myTaskId = taskId;
myOperationId = (taskId.hashCode() + FileUtil.pathHashCode(buildRootDir == null ? UUID.randomUUID().toString() : buildRootDir)) + "_";
}
@Override
public void statusChanged(org.gradle.tooling.events.ProgressEvent event) {
GradleProgressEventConverter.EventId eventId = GradleProgressEventConverter.getEventId(event, myOperationId);
ExternalSystemTaskNotificationEvent progressBuildEvent =
GradleProgressEventConverter.createProgressBuildEvent(myTaskId, myTaskId, event);
sendProgressToOutputIfNeeded(event);
if (progressBuildEvent != null && event instanceof StatusEvent) {
// update IDE progress determinate indicator
myListener.onStatusChange(progressBuildEvent);
}
maybeUpdateTaskStatus(progressBuildEvent);
if (event instanceof TestOutputEvent) {
final ExternalSystemTaskNotificationEvent testNotificationEvent = convertToTestNotificationEvent((TestOutputEvent)event, eventId);
if (testNotificationEvent != null) {
myListener.onStatusChange(testNotificationEvent);
}
}
if (event instanceof TestProgressEvent) {
final ExternalSystemTaskNotificationEvent testNotificationEvent = convertToTestNotificationEvent((TestProgressEvent)event, eventId);
if (testNotificationEvent != null) {
myListener.onStatusChange(testNotificationEvent);
}
}
if (event instanceof TaskProgressEvent) {
ExternalSystemTaskNotificationEvent notificationEvent = GradleProgressEventConverter.convert(
myTaskId, event, new GradleProgressEventConverter.EventId(eventId.id, myTaskId));
myListener.onStatusChange(notificationEvent);
}
}
private ExternalSystemTaskNotificationEvent convertToTestNotificationEvent(TestOutputEvent outputEvent,
GradleProgressEventConverter.EventId eventId) {
TestOutputDescriptor descriptor = outputEvent.getDescriptor();
String prefix = outputEvent.getDescriptor().getDestination() == Destination.StdOut ? "StdOut" : "StdErr";
String message = prefix + outputEvent.getDescriptor().getMessage();
if (descriptor instanceof JvmTestOperationDescriptor) {
final TestOperationDescriptor operationDescriptor = convertDescriptor(outputEvent, (JvmTestOperationDescriptor)descriptor);
ExternalSystemMessageEvent<TestOperationDescriptor> event = new ExternalSystemMessageEventImpl<>(eventId.id.toString(),
eventId.parentId.toString(),
operationDescriptor,
message);
return new ExternalSystemTaskExecutionEvent(myTaskId, event);
}
return null;
}
private Failure convert(org.gradle.tooling.Failure gradleFailure) {
return new FailureImpl(gradleFailure.getMessage(),
gradleFailure.getDescription(),
ContainerUtil.map(gradleFailure.getCauses(), this::convert));
}
private ExternalSystemTaskNotificationEvent convertToTestNotificationEvent(TestProgressEvent testProgressEvent,
GradleProgressEventConverter.EventId eventId) {
org.gradle.tooling.events.test.TestOperationDescriptor descriptor = testProgressEvent.getDescriptor();
if (descriptor instanceof JvmTestOperationDescriptor) {
final TestOperationDescriptor operationDescriptor = convertDescriptor(testProgressEvent, (JvmTestOperationDescriptor)descriptor);
if (testProgressEvent instanceof TestStartEvent) {
ExternalSystemStartEvent<TestOperationDescriptor> event = new ExternalSystemStartEventImpl<>(eventId.id.toString(),
eventId.parentId.toString(),
operationDescriptor);
return new ExternalSystemTaskExecutionEvent(myTaskId, event);
}
if (testProgressEvent instanceof TestFinishEvent) {
TestOperationResult gradleResult = ((TestFinishEvent)testProgressEvent).getResult();
com.intellij.openapi.externalSystem.model.task.event.OperationResult operationResult = null;
if (gradleResult instanceof TestSuccessResult) {
operationResult = new SuccessResultImpl(gradleResult.getStartTime(), gradleResult.getEndTime(), true);
} else if (gradleResult instanceof TestFailureResult gradleFailure) {
operationResult = new FailureResultImpl(gradleFailure.getStartTime(), gradleFailure.getEndTime(), ContainerUtil.map(gradleFailure.getFailures(), this::convert));
} else if (gradleResult instanceof TestSkippedResult) {
operationResult = new SkippedResultImpl(gradleResult.getStartTime(), gradleResult.getEndTime());
}
if (operationResult != null) {
ExternalSystemFinishEvent<TestOperationDescriptor> event =
new ExternalSystemFinishEventImpl<>(eventId.id.toString(),
eventId.parentId.toString(),
operationDescriptor,
operationResult);
return new ExternalSystemTaskExecutionEvent(myTaskId, event);
}
}
}
return null;
}
@NotNull
private static TestOperationDescriptor convertDescriptor(org.gradle.tooling.events.ProgressEvent testProgressEvent,
JvmTestOperationDescriptor descriptor) {
String id = descriptor.getDisplayName();
boolean parentIsTest = descriptor.getParent() instanceof org.gradle.tooling.events.test.TestOperationDescriptor;
String parentId = parentIsTest ? descriptor.getParent().getDisplayName() : null;
return new TestOperationDescriptorImpl(descriptor.getDisplayName(),
testProgressEvent.getEventTime(),
descriptor.getSuiteName(),
descriptor.getClassName(),
descriptor.getMethodName()
);
myOperationId = taskId.hashCode() + ":" + FileUtil.pathHashCode(buildRootDir == null ? UUID.randomUUID().toString() : buildRootDir);
}
@Override
public void statusChanged(ProgressEvent event) {
String eventDescription = event.getDescription();
if (maybeReportModelBuilderMessage(eventDescription)) {
return;
sendProgressToOutputIfNeeded(event);
var progressBuildEvent = GradleProgressEventConverter.createProgressBuildEvent(myTaskId, myTaskId, event);
if (progressBuildEvent != null) {
if (event instanceof StatusEvent) {
// update IDE progress determinate indicator
myListener.onStatusChange(progressBuildEvent);
}
else if (!progressBuildEvent.equals(myLastStatusChange)) {
myListener.onStatusChange(progressBuildEvent);
myLastStatusChange = progressBuildEvent;
}
}
var taskNotificationEvent = GradleProgressEventConverter.createTaskNotificationEvent(myTaskId, myOperationId, event);
if (taskNotificationEvent != null) {
myListener.onStatusChange(taskNotificationEvent);
}
}
@Override
public void statusChanged(org.gradle.tooling.ProgressEvent event) {
var eventDescription = event.getDescription();
if (!maybeReportModelBuilderMessage(eventDescription)) {
var progressBuildEvent = GradleProgressEventConverter.legacyCreateProgressBuildEvent(myTaskId, myTaskId, eventDescription);
if (progressBuildEvent != null && !progressBuildEvent.equals(myLastStatusChange)) {
myListener.onStatusChange(progressBuildEvent);
myLastStatusChange = progressBuildEvent;
}
var taskNotificationEvent = GradleProgressEventConverter.legacyCreateTaskNotificationEvent(myTaskId, eventDescription);
myListener.onStatusChange(taskNotificationEvent);
reportGradleDaemonStartingEvent(eventDescription);
}
ExternalSystemTaskNotificationEvent progressBuildEvent =
GradleProgressEventConverter.legacyCreateProgressBuildEvent(myTaskId, myTaskId, eventDescription);
maybeUpdateTaskStatus(progressBuildEvent);
myListener.onStatusChange(new ExternalSystemTaskNotificationEvent(myTaskId, eventDescription));
reportGradleDaemonStartingEvent(eventDescription);
}
private boolean maybeReportModelBuilderMessage(String eventDescription) {
@@ -221,16 +133,7 @@ public class GradleProgressListener implements ProgressListener, org.gradle.tool
return false;
}
private void maybeUpdateTaskStatus(@Nullable ExternalSystemTaskNotificationEvent progressBuildEvent) {
if (progressBuildEvent != null) {
if (!progressBuildEvent.equals(myLastStatusChange)) {
myListener.onStatusChange(progressBuildEvent);
myLastStatusChange = progressBuildEvent;
}
}
}
private void sendProgressToOutputIfNeeded(org.gradle.tooling.events.ProgressEvent progressEvent) {
private void sendProgressToOutputIfNeeded(ProgressEvent progressEvent) {
@NlsSafe final String operationName = progressEvent.getDescriptor().getName();
if (progressEvent instanceof StatusEvent) {
StatusEvent statusEvent = ((StatusEvent)progressEvent);
@@ -253,7 +156,7 @@ public class GradleProgressListener implements ProgressListener, org.gradle.tool
else if (progressEvent instanceof FinishEvent finishEvent) {
StatusEvent statusEvent = myDownloadStatusEventIds.remove(operationName);
if (statusEvent != null) {
OperationResult operationResult = finishEvent.getResult();
var operationResult = finishEvent.getResult();
long duration = operationResult.getEndTime() - operationResult.getStartTime();
long progress = statusEvent.getProgress() > 0 ? statusEvent.getProgress() : 0;
long total = statusEvent.getTotal() > 0 ? statusEvent.getTotal() : 0;