IDEA-148907 Gradle executions view support

This commit is contained in:
Vladislav.Soroka
2015-12-04 15:26:24 +03:00
parent 9cb0a648a2
commit 009a37a984
26 changed files with 1442 additions and 115 deletions
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public class BaseExternalSystemProgressEvent implements ExternalSystemProgressEvent {
@NotNull private final String myEventId;
@NotNull private final String myDescription;
@Nullable private final String myParentEventId;
private final long myEventTime;
public BaseExternalSystemProgressEvent(@NotNull String eventId,
@Nullable String parentEventId,
@NotNull String description,
long eventTime) {
myEventId = eventId;
myDescription = description;
myParentEventId = parentEventId;
myEventTime = eventTime;
}
@NotNull
@Override
public String getEventId() {
return myEventId;
}
@Nullable
@Override
public String getParentEventId() {
return myParentEventId;
}
@NotNull
@Override
public String getDescription() {
return myDescription;
}
@Override
public long getEventTime() {
return myEventTime;
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/2/2015
*/
public class DefaultOperationResult implements OperationResult {
private final long myStartTime;
private final long myEndTime;
public DefaultOperationResult(long startTime, long endTime) {
myStartTime = startTime;
myEndTime = endTime;
}
@Override
public long getStartTime() {
return myStartTime;
}
@Override
public long getEndTime() {
return myEndTime;
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public interface ExternalSystemFinishEvent extends ExternalSystemProgressEvent {
OperationResult getOperationResult();
}
@@ -0,0 +1,40 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public class ExternalSystemFinishEventImpl extends BaseExternalSystemProgressEvent implements ExternalSystemFinishEvent {
@NotNull
private final OperationResult myResult;
public ExternalSystemFinishEventImpl(@NotNull String eventId,
@Nullable String parentEventId,
@NotNull String description,
@NotNull OperationResult result) {
super(eventId, parentEventId, description, result.getEndTime());
myResult = result;
}
@Override
public OperationResult getOperationResult() {
return myResult;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public interface ExternalSystemProgressEvent extends Serializable {
@NotNull
String getEventId();
@Nullable
String getParentEventId();
@NotNull
String getDescription();
long getEventTime();
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public interface ExternalSystemStartEvent extends ExternalSystemProgressEvent{
}
@@ -0,0 +1,29 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public class ExternalSystemStartEventImpl extends BaseExternalSystemProgressEvent implements ExternalSystemStartEvent {
public ExternalSystemStartEventImpl(@NotNull String eventId, @Nullable String parentEventId, @NotNull String description, long eventTime) {
super(eventId, parentEventId, description, eventTime);
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public class ExternalSystemTaskExecutionEvent extends ExternalSystemTaskNotificationEvent {
private static final long serialVersionUID = 1L;
@NotNull private final ExternalSystemProgressEvent myProgressEvent;
public ExternalSystemTaskExecutionEvent(@NotNull ExternalSystemTaskId id, @NotNull ExternalSystemProgressEvent progressEvent) {
super(id, progressEvent.getDescription());
myProgressEvent = progressEvent;
}
@NotNull
public ExternalSystemProgressEvent getProgressEvent() {
return myProgressEvent;
}
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public interface FailureResult extends OperationResult {
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/2/2015
*/
public class FailureResultImpl extends DefaultOperationResult implements FailureResult{
public FailureResultImpl(long startTime, long endTime) {
super(startTime, endTime);
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
import java.io.Serializable;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public interface OperationResult extends Serializable {
long getStartTime();
long getEndTime();
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public interface SkippedResult extends OperationResult {
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/2/2015
*/
public class SkippedResultImpl extends DefaultOperationResult implements SkippedResult {
public SkippedResultImpl(long startTime, long endTime) {
super(startTime, endTime);
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public interface SuccessResult extends OperationResult {
boolean isUpToDate();
}
@@ -0,0 +1,35 @@
/*
* Copyright 2000-2015 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.openapi.externalSystem.model.task.event;
/**
* @author Vladislav.Soroka
* @since 12/2/2015
*/
public class SuccessResultImpl extends DefaultOperationResult implements SuccessResult {
private final boolean myUpToDate;
public SuccessResultImpl(long startTime, long endTime, boolean isUpToDate) {
super(startTime, endTime);
myUpToDate = isUpToDate;
}
@Override
public boolean isUpToDate() {
return myUpToDate;
}
}
@@ -37,6 +37,7 @@ gradle.codeInsight.action.add_maven_dependency.text=Add maven artifact dependenc
gradle.codeInsight.action.add_maven_dependency.description=Add selected maven artifact dependency to the project
gradle.runner=Runner
gradle.runner.toggle.tree.text.action.name=Toggle tasks executions/text mode
gradle.preferred_test_runner.ask=Let me choose per test
gradle.preferred_test_runner.PLATFORM_TEST_RUNNER=Platform Test Runner
gradle.preferred_test_runner.GRADLE_TEST_RUNNER=Gradle Test Runner
+1
View File
@@ -91,6 +91,7 @@
order="last"/>
<runConfigurationProducer implementation="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer"
order="last"/>
<externalSystemExecutionConsoleManager implementation="org.jetbrains.plugins.gradle.execution.GradleExecutionConsoleManager" order="last"/>
<externalSystemExecutionConsoleManager implementation="org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsoleManager"/>
<projectImportProvider implementation="org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportProvider"/>
<projectImportBuilder implementation="org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportBuilder"/>
@@ -0,0 +1,100 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.execution;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public class ExecutionInfo {
private final @Nullable String id;
private String myDisplayName;
private long startTime;
private long endTime;
private boolean isFailed;
private boolean isSkipped;
private boolean isUpToDate;
public ExecutionInfo(@Nullable String id, String displayName) {
this.id = id;
this.myDisplayName = displayName;
}
@Nullable
public String getId() {
return id;
}
public String getDisplayName() {
return myDisplayName;
}
public void setDisplayName(String displayName) {
this.myDisplayName = displayName;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
public boolean isFailed() {
return isFailed;
}
public void setFailed(boolean failed) {
isFailed = failed;
}
public boolean isSkipped() {
return isSkipped;
}
public void setSkipped(boolean skipped) {
isSkipped = skipped;
}
public boolean isUpToDate() {
return isUpToDate;
}
public void setUpToDate(boolean upToDate) {
isUpToDate = upToDate;
}
public boolean isRunning() {
return endTime <= 0;
}
@Override
public String toString() {
return myDisplayName;
}
}
@@ -0,0 +1,122 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.execution;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.treeStructure.CachingSimpleNode;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public class ExecutionNode extends CachingSimpleNode {
@NotNull
private ExecutionInfo myInfo;
private final List<ExecutionNode> myNodes = ContainerUtil.newArrayList();
protected ExecutionNode(Project project) {
super(project, null);
this.myInfo = new ExecutionInfo(null, "--");
}
public void add(ExecutionNode node) {
myNodes.add(node);
cleanUpCache();
}
@NotNull
public ExecutionInfo getInfo() {
return myInfo;
}
public void setInfo(@NotNull ExecutionInfo info) {
myInfo = info;
}
@Override
public String getName() {
return myInfo.getDisplayName();
}
public String getDuration() {
if (myInfo.isRunning()) {
final long duration = myInfo.getStartTime() == 0 ? 0 : System.currentTimeMillis() - myInfo.getStartTime();
return "Running for " + StringUtil.formatDuration(duration);
}
else {
return StringUtil.formatDuration(myInfo.getEndTime() - myInfo.getStartTime());
}
}
@Override
public boolean isAutoExpandNode() {
return true;
}
@Override
protected ExecutionNode[] buildChildren() {
return ContainerUtil.toArray(myNodes, new ExecutionNode[myNodes.size()]);
}
@Override
protected void doUpdate() {
setNameAndTooltip(getName(), null, myInfo.isUpToDate() ? "UP-TO-DATE" : null);
setIcon(
myInfo.isRunning() ? NodeProgressAnimator.getCurrentFrame() :
myInfo.isFailed() ? AllIcons.RunConfigurations.TestError :
myInfo.isSkipped() ? AllIcons.RunConfigurations.TestError :
AllIcons.RunConfigurations.TestPassed
);
}
@Override
public void handleSelection(SimpleTree tree) {
super.handleSelection(tree);
}
protected void setNameAndTooltip(String name, @Nullable String tooltip) {
setNameAndTooltip(name, tooltip, (String)null);
}
protected void setNameAndTooltip(String name, @Nullable String tooltip, @Nullable String hint) {
final SimpleTextAttributes textAttributes = getPlainAttributes();
setNameAndTooltip(name, tooltip, textAttributes);
if (!StringUtil.isEmptyOrSpaces(hint)) {
addColoredFragment(" " + hint, SimpleTextAttributes.GRAY_ATTRIBUTES);
}
}
protected void setNameAndTooltip(String name, @Nullable String tooltip, SimpleTextAttributes attributes) {
clearColoredText();
addColoredFragment(name, prepareAttributes(attributes));
final String s = (tooltip != null ? tooltip + "\n\r" : "");
getTemplatePresentation().setTooltip(s);
}
private static SimpleTextAttributes prepareAttributes(SimpleTextAttributes from) {
return new SimpleTextAttributes(from.getBgColor(), from.getFgColor(), null, from.getStyle());
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.execution;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTask;
import com.intellij.openapi.externalSystem.service.execution.DefaultExternalSystemExecutionConsoleManager;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.attachTaskExecutionView;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public class GradleExecutionConsoleManager extends DefaultExternalSystemExecutionConsoleManager {
@NotNull
@Override
public ProjectSystemId getExternalSystemId() {
return GradleConstants.SYSTEM_ID;
}
@NotNull
@Override
public ExecutionConsole attachExecutionConsole(@NotNull ExternalSystemTask task,
@NotNull Project project,
@NotNull ExternalSystemRunConfiguration configuration,
@NotNull Executor executor,
@NotNull ExecutionEnvironment env,
@NotNull ProcessHandler processHandler) throws ExecutionException {
final ConsoleView textConsole = TextConsoleBuilderFactory.getInstance().createBuilder(project).getConsole();
textConsole.attachToProcess(processHandler);
return attachTaskExecutionView(project, textConsole, true, "gradle.runner.text.console", processHandler, task.getId());
}
}
@@ -0,0 +1,122 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.execution;
import com.intellij.execution.console.DuplexConsoleView;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter;
import com.intellij.openapi.externalSystem.model.task.event.ExternalSystemTaskExecutionEvent;
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 12/4/2015
*/
public class GradleRunnerUtil {
public static DuplexConsoleView attachTaskExecutionView(@NotNull final Project project,
@NotNull final ConsoleView consoleView,
final boolean isTaskConsoleEnabledByDefault,
@Nullable final String stateStorageKey,
@NotNull final ProcessHandler processHandler,
@NotNull final ExternalSystemTaskId taskId) {
if (stateStorageKey != null && isTaskConsoleEnabledByDefault && !PropertiesComponent.getInstance().isValueSet(stateStorageKey)) {
PropertiesComponent.getInstance().setValue(stateStorageKey, true);
}
;
final TaskExecutionView gradleExecutionConsole = new TaskExecutionView(project);
final Ref<DuplexConsoleView> duplexConsoleViewRef = Ref.create();
final DuplexConsoleView duplexConsoleView =
new DuplexConsoleView<ConsoleView, ConsoleView>(gradleExecutionConsole, consoleView, stateStorageKey) {
@NotNull
@Override
public AnAction[] createConsoleActions() {
final DefaultActionGroup textActionGroup = new DefaultActionGroup() {
@Override
public void update(AnActionEvent e) {
super.update(e);
if (duplexConsoleViewRef.get() != null) {
e.getPresentation().setVisible(!duplexConsoleViewRef.get().isPrimaryConsoleEnabled());
}
}
};
final AnAction[] consoleActions = consoleView.createConsoleActions();
for (AnAction anAction : consoleActions) {
textActionGroup.add(anAction);
}
final List<AnAction> anActions = ContainerUtil.newArrayList(super.createConsoleActions());
anActions.add(textActionGroup);
return ArrayUtil.toObjectArray(anActions, AnAction.class);
}
};
duplexConsoleViewRef.set(duplexConsoleView);
duplexConsoleView.setDisableSwitchConsoleActionOnProcessEnd(false);
duplexConsoleView.getSwitchConsoleActionPresentation().setIcon(AllIcons.Debugger.Console);
duplexConsoleView.getSwitchConsoleActionPresentation().setText(GradleBundle.message("gradle.runner.toggle.tree.text.action.name"));
final ExternalSystemProgressNotificationManager progressManager =
ServiceManager.getService(ExternalSystemProgressNotificationManager.class);
final ExternalSystemTaskNotificationListenerAdapter taskListener = new ExternalSystemTaskNotificationListenerAdapter() {
@Override
public void onStatusChange(@NotNull final ExternalSystemTaskNotificationEvent event) {
if (event instanceof ExternalSystemTaskExecutionEvent) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
gradleExecutionConsole.onStatusChange((ExternalSystemTaskExecutionEvent)event);
}
});
}
}
};
progressManager.addNotificationListener(taskId, taskListener);
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(ProcessEvent event) {
progressManager.removeNotificationListener(taskListener);
}
});
return duplexConsoleView;
}
}
@@ -0,0 +1,152 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.execution;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.ide.util.treeView.AbstractTreeUi;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.treeStructure.SimpleNode;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
/**
* @author Vladislav.Soroka
* @since 11/27/2015
*/
public class NodeProgressAnimator implements Runnable, Disposable {
private static final int FRAMES_COUNT = 8;
private static final int MOVIE_TIME = 800;
private static final int FRAME_TIME = MOVIE_TIME / FRAMES_COUNT;
public static final Icon[] FRAMES = new Icon[FRAMES_COUNT];
private long myLastInvocationTime = -1;
private Alarm myAlarm;
private SimpleNode myCurrentNode;
private AbstractTreeBuilder myTreeBuilder;
public NodeProgressAnimator(AbstractTreeBuilder builder) {
Disposer.register(builder, this);
init(builder);
}
static {
FRAMES[0] = AllIcons.RunConfigurations.TestInProgress1;
FRAMES[1] = AllIcons.RunConfigurations.TestInProgress2;
FRAMES[2] = AllIcons.RunConfigurations.TestInProgress3;
FRAMES[3] = AllIcons.RunConfigurations.TestInProgress4;
FRAMES[4] = AllIcons.RunConfigurations.TestInProgress5;
FRAMES[5] = AllIcons.RunConfigurations.TestInProgress6;
FRAMES[6] = AllIcons.RunConfigurations.TestInProgress7;
FRAMES[7] = AllIcons.RunConfigurations.TestInProgress8;
}
public static int getCurrentFrameIndex() {
return (int) ((System.currentTimeMillis() % MOVIE_TIME) / FRAME_TIME);
}
public static Icon getCurrentFrame() {
return FRAMES[getCurrentFrameIndex()];
}
/**
* Initializes animator: creates alarm and sets tree builder
* @param treeBuilder tree builder
*/
protected void init(final AbstractTreeBuilder treeBuilder) {
myAlarm = new Alarm();
myTreeBuilder = treeBuilder;
}
public SimpleNode getCurrentNode() {
return myCurrentNode;
}
public void run() {
if (myCurrentNode != null) {
final long time = System.currentTimeMillis();
// optimization:
// we shouldn't repaint if this frame was painted in current interval
if (time - myLastInvocationTime >= FRAME_TIME) {
repaintSubTree();
myLastInvocationTime = time;
}
}
scheduleRepaint();
}
public void setCurrentNode(@Nullable final SimpleNode node) {
myCurrentNode = node;
scheduleRepaint();
}
public void stopMovie() {
repaintSubTree();
setCurrentNode(null);
cancelAlarm();
}
public void dispose() {
myTreeBuilder = null;
myCurrentNode = null;
cancelAlarm();
}
private void cancelAlarm() {
if (myAlarm != null) {
myAlarm.cancelAllRequests();
myAlarm = null;
}
}
private void repaintSubTree() {
if (myTreeBuilder != null && myCurrentNode != null) {
repaintWithParents(myCurrentNode);
}
}
public void repaintWithParents(final SimpleNode element) {
SimpleNode current = element;
do {
DefaultMutableTreeNode node = myTreeBuilder.getNodeForElement(current);
if (node != null) {
final AbstractTreeUi treeUi = myTreeBuilder.getUi();
treeUi.addSubtreeToUpdate(node, false);
}
current = current.getParent();
}
while (current != null);
}
private void scheduleRepaint() {
if (myAlarm == null) {
return;
}
myAlarm.cancelAllRequests();
if (myCurrentNode != null) {
myAlarm.addRequest(this, FRAME_TIME);
}
}
}
@@ -0,0 +1,309 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.execution;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.externalSystem.model.task.event.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.*;
import com.intellij.ui.speedSearch.SpeedSearchUtil;
import com.intellij.ui.treeStructure.SimpleTreeBuilder;
import com.intellij.ui.treeStructure.SimpleTreeStructure;
import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
import com.intellij.ui.treeStructure.treetable.TreeColumnInfo;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.ui.treeStructure.treetable.TreeTableTree;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
import java.util.Map;
/**
* @author Vladislav.Soroka
* @since 12/1/2015
*/
public class TaskExecutionView implements ConsoleView {
private static final int TIME_COLUMN_WIDTH = 140;
private final Project myProject;
private final Map<String, ExecutionNode> nodeMap = ContainerUtil.newHashMap();
private final JScrollPane myPane;
private final TreeTable myTreeTable;
private final SimpleTreeBuilder myBuilder;
private final NodeProgressAnimator myProgressAnimator;
private final ExecutionNode myRoot;
public TaskExecutionView(Project project) {
myProject = project;
final ColumnInfo[] COLUMNS = new ColumnInfo[]{
new TreeColumnInfo("name"),
new ColumnInfo("time elapsed") {
@Nullable
@Override
public Object valueOf(Object o) {
if (o instanceof DefaultMutableTreeNode) {
final Object userObject = ((DefaultMutableTreeNode)o).getUserObject();
if (userObject instanceof ExecutionNode) {
return ((ExecutionNode)userObject).getDuration();
}
}
return null;
}
}
,
new ColumnInfo("") {
@Nullable
@Override
public Object valueOf(Object o) {
return "";
}
}
};
myRoot = new ExecutionNode(project);
myRoot.setInfo(new ExecutionInfo(null, "Run build"));
final ListTreeTableModelOnColumns model = new ListTreeTableModelOnColumns(new DefaultMutableTreeNode(myRoot), COLUMNS);
myTreeTable = new TreeTable(model) {
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
if (column == 1) {
return new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setHorizontalAlignment(SwingConstants.RIGHT);
return this;
}
};
}
return super.getCellRenderer(row, column);
}
};
final TreeCellRenderer treeCellRenderer = myTreeTable.getTree().getCellRenderer();
myTreeTable.getTree().setCellRenderer(new TreeCellRenderer() {
@Override
public Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
final Component rendererComponent =
treeCellRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if (rendererComponent instanceof SimpleColoredComponent) {
final Color bg = selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground();
final Color fg = selected ? UIUtil.getTreeSelectionForeground() : UIUtil.getTreeForeground();
if (selected) {
for (SimpleColoredComponent.ColoredIterator it = ((SimpleColoredComponent)rendererComponent).iterator(); it.hasNext(); ) {
it.next();
int offset = it.getOffset();
int endOffset = it.getEndOffset();
SimpleTextAttributes currentAttributes = it.getTextAttributes();
SimpleTextAttributes newAttributes =
new SimpleTextAttributes(bg, fg, currentAttributes.getWaveColor(), currentAttributes.getStyle());
it.split(endOffset - offset, newAttributes);
}
}
SpeedSearchUtil.applySpeedSearchHighlighting(myTreeTable, (SimpleColoredComponent)rendererComponent, true, selected);
}
return rendererComponent;
}
});
new TreeTableSpeedSearch(myTreeTable).setComparator(new SpeedSearchComparator(false));
myTreeTable.setTableHeader(null);
final TableColumn treeColumn = myTreeTable.getColumnModel().getColumn(0);
treeColumn.setMinWidth(300);
final TableColumn timeColumn = myTreeTable.getColumnModel().getColumn(1);
timeColumn.setMaxWidth(TIME_COLUMN_WIDTH);
timeColumn.setMinWidth(TIME_COLUMN_WIDTH);
TreeTableTree tree = myTreeTable.getTree();
final SimpleTreeStructure treeStructure = new SimpleTreeStructure.Impl(myRoot);
myBuilder = new SimpleTreeBuilder(tree, model, treeStructure, null);
Disposer.register(this, myBuilder);
myBuilder.expand(treeStructure.getRootElement(), null);
myBuilder.initRoot();
myBuilder.expand(myRoot, null);
myProgressAnimator = new NodeProgressAnimator(myBuilder);
myProgressAnimator.setCurrentNode(myRoot);
myBuilder.queueUpdateFrom(myRoot, false, true);
myPane = ScrollPaneFactory.createScrollPane(myTreeTable,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
public void onStatusChange(ExternalSystemTaskExecutionEvent event) {
final ExternalSystemProgressEvent progressEvent = event.getProgressEvent();
final String parentEventId = progressEvent.getParentEventId();
if (progressEvent instanceof ExternalSystemStartEvent) {
final ExecutionInfo executionInfo = new ExecutionInfo(progressEvent.getEventId(), progressEvent.getDescription());
executionInfo.setStartTime(progressEvent.getEventTime());
final ExecutionNode currentNode = parentEventId == null ? myRoot : new ExecutionNode(myProject);
if (parentEventId != null) {
final ExecutionNode parentNode = nodeMap.get(parentEventId);
if (parentNode != null) {
parentNode.add(currentNode);
}
}
currentNode.setInfo(executionInfo);
nodeMap.put(progressEvent.getEventId(), currentNode);
myProgressAnimator.setCurrentNode(currentNode);
myBuilder.queueUpdateFrom(currentNode, false, true);
}
else if (progressEvent instanceof ExternalSystemFinishEvent) {
final ExecutionInfo executionInfo;
final ExecutionNode node = nodeMap.get(progressEvent.getEventId());
executionInfo = node.getInfo();
executionInfo.setDisplayName(progressEvent.getDescription());
executionInfo.setEndTime(progressEvent.getEventTime());
final OperationResult operationResult = ((ExternalSystemFinishEvent)progressEvent).getOperationResult();
if (operationResult instanceof FailureResult) {
executionInfo.setFailed(true);
}
else if (operationResult instanceof SkippedResult) {
executionInfo.setSkipped(true);
}
else if (operationResult instanceof SuccessResult) {
executionInfo.setUpToDate(((SuccessResult)operationResult).isUpToDate());
}
if (parentEventId == null) {
myProgressAnimator.stopMovie();
}
myBuilder.queueUpdateFrom(node, false, false);
}
}
@Override
public void print(@NotNull String s, @NotNull ConsoleViewContentType contentType) {
}
@Override
public void clear() {
}
@Override
public void scrollTo(int offset) {
}
@Override
public void attachToProcess(ProcessHandler processHandler) {
}
@Override
public void setOutputPaused(boolean value) {
}
@Override
public boolean isOutputPaused() {
return false;
}
@Override
public boolean hasDeferredOutput() {
return false;
}
@Override
public void performWhenNoDeferredOutput(Runnable runnable) {
}
@Override
public void setHelpId(String helpId) {
}
@Override
public void addMessageFilter(Filter filter) {
}
@Override
public void printHyperlink(String hyperlinkText, HyperlinkInfo info) {
}
@Override
public int getContentSize() {
return 0;
}
@Override
public boolean canPause() {
return false;
}
@NotNull
@Override
public AnAction[] createConsoleActions() {
return new AnAction[0];
}
@Override
public void allowHeavyFilters() {
}
@Override
public JComponent getComponent() {
return myPane;
}
@Override
public JComponent getPreferredFocusableComponent() {
return myTreeTable;
}
@Override
public void dispose() {
}
}
@@ -15,35 +15,45 @@
*/
package org.jetbrains.plugins.gradle.execution.test.runner;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.console.DuplexConsoleView;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.testframework.TestConsoleProperties;
import com.intellij.execution.testframework.sm.runner.SMTestLocator;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.execution.testframework.sm.runner.ui.SMTestRunnerResultsForm;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Map;
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.attachTaskExecutionView;
/**
* @author Vladislav.Soroka
* @since 10/28/2015
*/
public class GradleTestsExecutionConsole implements ConsoleView {
public class GradleTestsExecutionConsole extends SMTRunnerConsoleView {
private Map<String, SMTestProxy> testsMap = ContainerUtil.newHashMap();
private StringBuilder myBuffer = new StringBuilder();
private SMTRunnerConsoleView myExecutionConsole;
private DuplexConsoleView myConsoleView;
public GradleTestsExecutionConsole(SMTRunnerConsoleView executionConsole) {
myExecutionConsole = executionConsole;
public GradleTestsExecutionConsole(TestConsoleProperties consoleProperties, @Nullable String splitterProperty) {
super(consoleProperties, splitterProperty);
}
public void initTaskExecutionView(Project project, ProcessHandler processHandler, ExternalSystemTaskId taskId) {
myConsoleView = attachTaskExecutionView(project, super.getConsole(), false, "gradle.test.runner.text.console", processHandler, taskId);
}
@NotNull
@Override
public ConsoleView getConsole() {
return myConsoleView != null ? myConsoleView : super.getConsole();
}
public Map<String, SMTestProxy> getTestsMap() {
@@ -54,103 +64,10 @@ public class GradleTestsExecutionConsole implements ConsoleView {
return myBuffer;
}
@Override
public void print(@NotNull String s, @NotNull ConsoleViewContentType contentType) {
myExecutionConsole.print(s, contentType);
}
@Override
public void clear() {
myExecutionConsole.clear();
}
@Override
public void scrollTo(int offset) {
myExecutionConsole.scrollTo(offset);
}
@Override
public void attachToProcess(ProcessHandler processHandler) {
myExecutionConsole.attachToProcess(processHandler);
}
@Override
public void setOutputPaused(boolean value) {
myExecutionConsole.setOutputPaused(value);
}
@Override
public boolean isOutputPaused() {
return myExecutionConsole.isOutputPaused();
}
@Override
public boolean hasDeferredOutput() {
return myExecutionConsole.hasDeferredOutput();
}
@Override
public void performWhenNoDeferredOutput(Runnable runnable) {
myExecutionConsole.performWhenNoDeferredOutput(runnable);
}
@Override
public void setHelpId(String helpId) {
myExecutionConsole.setHelpId(helpId);
}
@Override
public void addMessageFilter(Filter filter) {
myExecutionConsole.addMessageFilter(filter);
}
@Override
public void printHyperlink(String hyperlinkText, HyperlinkInfo info) {
myExecutionConsole.printHyperlink(hyperlinkText, info);
}
@Override
public int getContentSize() {
return myExecutionConsole.getContentSize();
}
@Override
public boolean canPause() {
return myExecutionConsole.canPause();
}
@NotNull
@Override
public AnAction[] createConsoleActions() {
return myExecutionConsole.createConsoleActions();
}
@Override
public void allowHeavyFilters() {
myExecutionConsole.allowHeavyFilters();
}
@Override
public JComponent getComponent() {
return myExecutionConsole.getComponent();
}
@Override
public JComponent getPreferredFocusableComponent() {
return myExecutionConsole.getPreferredFocusableComponent();
}
@Override
public void dispose() {
Disposer.dispose(myExecutionConsole);
}
public SMTestRunnerResultsForm getResultsViewer() {
return myExecutionConsole.getResultsViewer();
}
public TestConsoleProperties getProperties() {
return myExecutionConsole.getProperties();
super.dispose();
Disposer.dispose(myConsoleView);
}
public SMTestLocator getUrlProvider() {
@@ -26,6 +26,7 @@ import com.intellij.execution.testframework.sm.runner.states.TestStateInfo;
import com.intellij.execution.testframework.sm.runner.ui.SMRootTestProxyFormatter;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.execution.testframework.sm.runner.ui.TestTreeRenderer;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -76,10 +77,15 @@ public class GradleTestsExecutionConsoleManager
@NotNull final Executor executor,
@NotNull final ExecutionEnvironment env,
@NotNull final ProcessHandler processHandler) throws ExecutionException {
final GradleConsoleProperties properties = new GradleConsoleProperties(configuration, executor);
final SMTRunnerConsoleView executionConsole = (SMTRunnerConsoleView)SMTestRunnerConnectionUtil.createAndAttachConsole(
configuration.getSettings().getExternalSystemId().getReadableName(), processHandler, properties);
final TestTreeView testTreeView = executionConsole.getResultsViewer().getTreeView();
final GradleConsoleProperties consoleProperties = new GradleConsoleProperties(configuration, executor);
String testFrameworkName = configuration.getSettings().getExternalSystemId().getReadableName();
String splitterPropertyName = SMTestRunnerConnectionUtil.getSplitterPropertyName(testFrameworkName);
final GradleTestsExecutionConsole consoleView = new GradleTestsExecutionConsole(consoleProperties, splitterPropertyName);
consoleView.initTaskExecutionView(project, processHandler, task.getId());
SMTestRunnerConnectionUtil.initConsoleView(consoleView, testFrameworkName);
consoleView.attachToProcess(processHandler);
final TestTreeView testTreeView = consoleView.getResultsViewer().getTreeView();
if (testTreeView != null) {
TestTreeRenderer originalRenderer = ObjectUtils.tryCast(testTreeView.getCellRenderer(), TestTreeRenderer.class);
if (originalRenderer != null) {
@@ -113,7 +119,7 @@ public class GradleTestsExecutionConsoleManager
}
}
return new GradleTestsExecutionConsole(executionConsole);
return consoleView;
}
@Override
@@ -24,6 +24,7 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemException;
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.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -34,9 +35,17 @@ import org.gradle.initialization.BuildLayoutParameters;
import org.gradle.internal.nativeintegration.services.NativeServices;
import org.gradle.process.internal.JvmOptions;
import org.gradle.tooling.*;
import org.gradle.tooling.events.FailureResult;
import org.gradle.tooling.events.FinishEvent;
import org.gradle.tooling.events.SkippedResult;
import org.gradle.tooling.events.StartEvent;
import org.gradle.tooling.events.internal.DefaultOperationDescriptor;
import org.gradle.tooling.events.task.TaskProgressEvent;
import org.gradle.tooling.events.task.TaskSuccessResult;
import org.gradle.tooling.internal.consumer.DefaultExecutorServiceFactory;
import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
import org.gradle.tooling.internal.consumer.Distribution;
import org.gradle.tooling.internal.protocol.events.InternalOperationDescriptor;
import org.gradle.tooling.model.build.BuildEnvironment;
import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.NotNull;
@@ -154,12 +163,12 @@ public class GradleExecutionHelper {
operation.setJvmArguments(ArrayUtil.toStringArray(filteredArgs));
}
if(settings.isOfflineWork()) {
if (settings.isOfflineWork()) {
commandLineArgs.add(GradleConstants.OFFLINE_MODE_CMD_OPTION);
}
final Application application = ApplicationManager.getApplication();
if(application != null && application.isUnitTestMode()) {
if (application != null && application.isUnitTestMode()) {
commandLineArgs.add("--info");
commandLineArgs.add("--recompile-scripts");
}
@@ -193,13 +202,59 @@ public class GradleExecutionHelper {
operation.addProgressListener(new org.gradle.tooling.events.ProgressListener() {
@Override
public void statusChanged(org.gradle.tooling.events.ProgressEvent event) {
listener.onStatusChange(new ExternalSystemTaskNotificationEvent(id, event.getDisplayName()));
listener.onStatusChange(convert(id, event));
}
});
operation.setStandardOutput(standardOutput);
operation.setStandardError(standardError);
}
@NotNull
private static ExternalSystemTaskNotificationEvent convert(ExternalSystemTaskId id, org.gradle.tooling.events.ProgressEvent event) {
final InternalOperationDescriptor internalDesc =
event.getDescriptor() instanceof DefaultOperationDescriptor ? ((DefaultOperationDescriptor)event.getDescriptor())
.getInternalOperationDescriptor() : null;
final String eventId = internalDesc == null ? event.getDescriptor().getDisplayName() : internalDesc.getId().toString();
final String parentEventId;
if (event.getDescriptor().getParent() == null) {
parentEventId = null;
}
else {
parentEventId = internalDesc == null ? event.getDescriptor().getParent().getDisplayName() : internalDesc.getParentId().toString();
}
final String description = event.getDescriptor().getName();
if (event instanceof StartEvent) {
return new ExternalSystemTaskExecutionEvent(
id, new ExternalSystemStartEventImpl(eventId, parentEventId, description, event.getEventTime()));
}
else if (event instanceof FinishEvent) {
return new ExternalSystemTaskExecutionEvent(
id, new ExternalSystemFinishEventImpl(eventId, parentEventId, description, convert(((FinishEvent)event).getResult())));
}
else if (event instanceof TaskProgressEvent) {
return new ExternalSystemTaskExecutionEvent(
id, new BaseExternalSystemProgressEvent(eventId, parentEventId, description, event.getEventTime()));
}
else {
return new ExternalSystemTaskNotificationEvent(id, description);
}
}
@NotNull
private static OperationResult convert(org.gradle.tooling.events.OperationResult operationResult) {
if (operationResult instanceof FailureResult) {
return new FailureResultImpl(operationResult.getStartTime(), operationResult.getEndTime());
}
else if (operationResult instanceof SkippedResult) {
return new SkippedResultImpl(operationResult.getStartTime(), operationResult.getEndTime());
}
else {
final boolean isUpToDate = operationResult instanceof TaskSuccessResult && ((TaskSuccessResult)operationResult).isUpToDate();
return new SuccessResultImpl(operationResult.getStartTime(), operationResult.getEndTime(), isUpToDate);
}
}
public <T> T execute(@NotNull String projectPath, @Nullable GradleExecutionSettings settings, @NotNull Function<ProjectConnection, T> f) {
final String projectDir;
@@ -275,8 +330,9 @@ public class GradleExecutionHelper {
};
final File tempFile = writeToFileGradleInitScript(StringUtil.join(lines, SystemProperties.getLineSeparator()));
BuildLauncher launcher = getBuildLauncher(id, connection, settings, listener, ContainerUtil.<String>newArrayList(),
ContainerUtil.newArrayList(GradleConstants.INIT_SCRIPT_CMD_OPTION, tempFile.getAbsolutePath()));
BuildLauncher launcher = getBuildLauncher(
id, connection, settings, listener, ContainerUtil.<String>newArrayList(),
ContainerUtil.newArrayList(GradleConstants.INIT_SCRIPT_CMD_OPTION, tempFile.getAbsolutePath()));
launcher.forTasks("wrapper");
launcher.run();
String wrapperPropertyFile = FileUtil.loadFile(wrapperPropertyFileLocation);