From 3cd1e36de37245ae83f42dee94434fc28529e27f Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Tue, 9 Jan 2018 18:09:51 +0300 Subject: [PATCH] Gradle: handle and report errors happened before the gradle invocation, e.g. when the Gradle JDK is invalid (IDEA-181146, IDEA-183962, IDEA-184410) --- .../com/intellij/build/BuildConsoleUtils.java | 78 +++++++++++++++++++ .../intellij/build/BuildTreeConsoleView.java | 59 ++------------ .../execution/ExternalSystemJdkException.java | 13 +++- .../ExternalSystemRunConfiguration.java | 11 +-- .../ExternalSystemExecuteTaskTask.java | 57 +++++++++----- .../ExternalSystemResolveProjectTask.java | 37 ++++++--- .../ExternalSystemTaskManagerWrapper.java | 1 - .../util/ExternalSystemUtil.java | 33 ++++++-- .../service/GradleInstallationManager.java | 9 +-- 9 files changed, 189 insertions(+), 109 deletions(-) create mode 100644 java/compiler/impl/src/com/intellij/build/BuildConsoleUtils.java diff --git a/java/compiler/impl/src/com/intellij/build/BuildConsoleUtils.java b/java/compiler/impl/src/com/intellij/build/BuildConsoleUtils.java new file mode 100644 index 000000000000..4799cf92474d --- /dev/null +++ b/java/compiler/impl/src/com/intellij/build/BuildConsoleUtils.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2018 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.build; + +import com.intellij.build.events.Failure; +import com.intellij.execution.filters.HyperlinkInfo; +import com.intellij.execution.ui.ConsoleView; +import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.notification.Notification; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.IJSwingUtilities; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; + +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Vladislav.Soroka + */ +public class BuildConsoleUtils { + private static final Pattern TAG_PATTERN = Pattern.compile("<[^>]*>"); + private static final Pattern A_PATTERN = Pattern.compile("]* )?href=[\"\']([^>]*)[\"\'][^>]*>"); + private static final String A_CLOSING = ""; + private static final Set NEW_LINES = ContainerUtil.set("
", "
", "
", "

", "

", "

", "

", "
"); + + public static boolean printFailure(ConsoleView consoleView, Failure failure) { + String text = ObjectUtils.chooseNotNull(failure.getDescription(), failure.getMessage()); + if (text == null && failure.getError() != null) { + text = failure.getError().getMessage(); + } + if (text == null) return false; + + String content = StringUtil.convertLineSeparators(text); + while (true) { + Matcher tagMatcher = TAG_PATTERN.matcher(content); + if (!tagMatcher.find()) { + consoleView.print(content, ConsoleViewContentType.ERROR_OUTPUT); + break; + } + String tagStart = tagMatcher.group(); + consoleView.print(content.substring(0, tagMatcher.start()), ConsoleViewContentType.ERROR_OUTPUT); + Matcher aMatcher = A_PATTERN.matcher(tagStart); + if (aMatcher.matches()) { + final String href = aMatcher.group(2); + int linkEnd = content.indexOf(A_CLOSING, tagMatcher.end()); + if (linkEnd > 0) { + String linkText = content.substring(tagMatcher.end(), linkEnd).replaceAll(TAG_PATTERN.pattern(), ""); + consoleView.printHyperlink(linkText, new HyperlinkInfo() { + @Override + public void navigate(Project project) { + Notification notification = failure.getNotification(); + if (notification != null && notification.getListener() != null) { + notification.getListener().hyperlinkUpdate( + notification, IJSwingUtilities.createHyperlinkEvent(href, consoleView.getComponent())); + } + } + }); + content = content.substring(linkEnd + A_CLOSING.length()); + continue; + } + } + if (NEW_LINES.contains(tagStart)) { + consoleView.print("\n", ConsoleViewContentType.SYSTEM_OUTPUT); + } + else { + consoleView.print(content.substring(tagMatcher.start(), tagMatcher.end()), ConsoleViewContentType.ERROR_OUTPUT); + } + content = content.substring(tagMatcher.end()); + } + + consoleView.print("\n", ConsoleViewContentType.SYSTEM_OUTPUT); + return true; + } +} diff --git a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java index 4dba9d59c9fb..c6149106cccf 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java +++ b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java @@ -9,7 +9,6 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.icons.AllIcons; -import com.intellij.notification.Notification; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -32,7 +31,9 @@ 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.*; +import com.intellij.util.Alarm; +import com.intellij.util.EditSourceOnDoubleClickHandler; +import com.intellij.util.EditSourceOnEnterKeyHandler; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.ColumnInfo; @@ -57,8 +58,6 @@ import java.util.*; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * @author Vladislav.Soroka @@ -600,11 +599,6 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon } private static class DetailsHandler { - private static final Pattern TAG_PATTERN = Pattern.compile("<[^>]*>"); - private static final Pattern A_PATTERN = Pattern.compile("]* )?href=[\"\']([^>]*)[\"\'][^>]*>"); - private static final String A_CLOSING = ""; - private static final Set NEW_LINES = ContainerUtil.set("
", "
", "
", "

", "

", "

", "

", "
"); - private final ThreeComponentsSplitter mySplitter; @Nullable private ExecutionNode myExecutionNode; @@ -650,12 +644,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon boolean hasChanged = false; for (Iterator iterator = failures.iterator(); iterator.hasNext(); ) { Failure failure = iterator.next(); - String text = ObjectUtils.chooseNotNull(failure.getDescription(), failure.getMessage()); - if (text == null && failure.getError() != null) { - text = failure.getError().getMessage(); - } - if (text == null) continue; - printDetails(failure, text); + if (!printFailure(failure)) continue; hasChanged = true; if (iterator.hasNext()) { myConsole.print("\n\n", ConsoleViewContentType.NORMAL_OUTPUT); @@ -675,44 +664,8 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon return true; } - public void printDetails(Failure failure, String text) { - String content = StringUtil.convertLineSeparators(text); - while (true) { - Matcher tagMatcher = TAG_PATTERN.matcher(content); - if (!tagMatcher.find()) { - myConsole.print(content, ConsoleViewContentType.ERROR_OUTPUT); - break; - } - String tagStart = tagMatcher.group(); - myConsole.print(content.substring(0, tagMatcher.start()), ConsoleViewContentType.ERROR_OUTPUT); - Matcher aMatcher = A_PATTERN.matcher(tagStart); - if (aMatcher.matches()) { - final String href = aMatcher.group(2); - int linkEnd = content.indexOf(A_CLOSING, tagMatcher.end()); - if (linkEnd > 0) { - String linkText = content.substring(tagMatcher.end(), linkEnd).replaceAll(TAG_PATTERN.pattern(), ""); - myConsole.printHyperlink(linkText, new HyperlinkInfo() { - @Override - public void navigate(Project project) { - Notification notification = failure.getNotification(); - if (notification != null && notification.getListener() != null) { - notification.getListener().hyperlinkUpdate( - notification, IJSwingUtilities.createHyperlinkEvent(href, myConsole.getComponent())); - } - } - }); - content = content.substring(linkEnd + A_CLOSING.length()); - continue; - } - } - if (NEW_LINES.contains(tagStart)) { - myConsole.print("\n", ConsoleViewContentType.SYSTEM_OUTPUT); - } - else { - myConsole.print(content.substring(tagMatcher.start(), tagMatcher.end()), ConsoleViewContentType.ERROR_OUTPUT); - } - content = content.substring(tagMatcher.end()); - } + private boolean printFailure(Failure failure) { + return BuildConsoleUtils.printFailure(myConsole, failure); } public void setNode(@Nullable DefaultMutableTreeNode node) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkException.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkException.java index 074338eca960..0c2dd33eeae8 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkException.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkException.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.externalSystem.service.execution; -import com.intellij.openapi.externalSystem.model.LocationAwareExternalSystemException; +import com.intellij.openapi.externalSystem.model.ExternalSystemException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,12 +23,19 @@ import org.jetbrains.annotations.Nullable; * @author Vladislav.Soroka * @since 12/12/2014 */ -public class ExternalSystemJdkException extends LocationAwareExternalSystemException { +public class ExternalSystemJdkException extends ExternalSystemException { + @Deprecated public ExternalSystemJdkException(@Nullable String message, @Nullable String filePath, @Nullable Throwable cause, @NotNull String... quickFixes) { - super(message, cause, filePath, -1, -1, quickFixes); + this(message, cause, quickFixes); + } + + public ExternalSystemJdkException(@Nullable String message, + @Nullable Throwable cause, + @NotNull String... quickFixes) { + super(message, cause, quickFixes); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java index 809d40cf4aaf..f8f40fe90102 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java @@ -5,7 +5,7 @@ package com.intellij.openapi.externalSystem.service.execution; import com.intellij.build.*; import com.intellij.build.events.BuildEvent; -import com.intellij.build.events.impl.FailureResultImpl; +import com.intellij.build.events.FailureResult; import com.intellij.build.events.impl.FinishBuildEventImpl; import com.intellij.build.events.impl.StartBuildEventImpl; import com.intellij.build.events.impl.SuccessResultImpl; @@ -63,7 +63,6 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.ArrayUtil; -import com.intellij.util.ExceptionUtil; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.net.NetUtils; @@ -386,15 +385,13 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i @Override public void onFailure(@NotNull ExternalSystemTaskId id, @NotNull Exception e) { + FailureResult failureResult = + ExternalSystemUtil.createFailureResult(executionName + " failed", e, id.getProjectSystemId(), myProject); if (progressListener != null) { - FailureResultImpl failureResult = - ExternalSystemUtil.createFailureResult(executionName + " failed", e, id.getProjectSystemId(), myProject); progressListener.onEvent(new FinishBuildEventImpl( id, null, System.currentTimeMillis(), "failed", failureResult)); } - String exceptionMessage = ExceptionUtil.getMessage(e); - String text = exceptionMessage == null ? e.toString() : exceptionMessage; - processHandler.notifyTextAvailable(text + '\n', ProcessOutputTypes.STDERR); + ExternalSystemUtil.printFailure(e, failureResult, consoleView, processHandler); processHandler.notifyProcessTerminated(1); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java index a538b5d1977e..44485e0d1cec 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemExecuteTaskTask.java @@ -20,9 +20,12 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings; +import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType; import com.intellij.openapi.externalSystem.service.ExternalSystemFacadeManager; import com.intellij.openapi.externalSystem.service.RemoteExternalSystemFacade; +import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager; +import com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl; import com.intellij.openapi.externalSystem.service.remote.RemoteExternalSystemTaskManager; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.project.Project; @@ -130,26 +133,42 @@ public class ExternalSystemExecuteTaskTask extends AbstractExternalSystemTask { @SuppressWarnings("unchecked") @Override protected void doExecute() throws Exception { - final ExternalSystemFacadeManager manager = ServiceManager.getService(ExternalSystemFacadeManager.class); - ExternalSystemExecutionSettings settings = ExternalSystemApiUtil.getExecutionSettings(getIdeProject(), - getExternalProjectPath(), - getExternalSystemId()); - KeyFMap keyFMap = getUserMap(); - for (Key key : keyFMap.getKeys()) { - settings.putUserData(key, keyFMap.get(key)); - } - - RemoteExternalSystemFacade facade = manager.getFacade(getIdeProject(), getExternalProjectPath(), getExternalSystemId()); - RemoteExternalSystemTaskManager taskManager = facade.getTaskManager(); - final List vmOptions = parseCmdParameters(myVmOptions); - final List arguments = parseCmdParameters(myArguments); - settings - .withVmOptions(vmOptions) - .withArguments(arguments) - .withEnvironmentVariables(myEnv) - .passParentEnvs(myPassParentEnvs); + ExternalSystemProgressNotificationManagerImpl progressNotificationManager = + (ExternalSystemProgressNotificationManagerImpl)ServiceManager.getService(ExternalSystemProgressNotificationManager.class); + ExternalSystemTaskId id = getId(); + String projectPath = getExternalProjectPath(); - taskManager.executeTasks(getId(), myTasksToExecute, getExternalProjectPath(), settings, myJvmAgentSetup); + ExternalSystemExecutionSettings settings; + RemoteExternalSystemTaskManager taskManager; + try { + progressNotificationManager.onStart(id, projectPath); + + final ExternalSystemFacadeManager manager = ServiceManager.getService(ExternalSystemFacadeManager.class); + settings = ExternalSystemApiUtil.getExecutionSettings(getIdeProject(), + projectPath, + getExternalSystemId()); + KeyFMap keyFMap = getUserMap(); + for (Key key : keyFMap.getKeys()) { + settings.putUserData(key, keyFMap.get(key)); + } + + RemoteExternalSystemFacade facade = manager.getFacade(getIdeProject(), projectPath, getExternalSystemId()); + taskManager = facade.getTaskManager(); + final List vmOptions = parseCmdParameters(myVmOptions); + final List arguments = parseCmdParameters(myArguments); + settings + .withVmOptions(vmOptions) + .withArguments(arguments) + .withEnvironmentVariables(myEnv) + .passParentEnvs(myPassParentEnvs); + } + catch (Exception e) { + progressNotificationManager.onFailure(id, e); + progressNotificationManager.onEnd(id); + throw e; + } + + taskManager.executeTasks(id, myTasksToExecute, projectPath, settings, myJvmAgentSetup); } @Override diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java index 6b5398f2b320..32f161a8bbbb 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java @@ -3,6 +3,7 @@ package com.intellij.openapi.externalSystem.service.internal; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ExternalSystemException; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo; @@ -68,21 +69,33 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask @SuppressWarnings("unchecked") protected void doExecute() throws Exception { - final ExternalSystemFacadeManager manager = ServiceManager.getService(ExternalSystemFacadeManager.class); - Project ideProject = getIdeProject(); - RemoteExternalSystemProjectResolver resolver = manager.getFacade(ideProject, myProjectPath, getExternalSystemId()).getResolver(); - ExternalSystemExecutionSettings settings = ExternalSystemApiUtil.getExecutionSettings(ideProject, myProjectPath, getExternalSystemId()); - if(StringUtil.isNotEmpty(myVmOptions)) { - settings.withVmOptions(ParametersListUtil.parse(myVmOptions)); - } - if(StringUtil.isNotEmpty(myArguments)) { - settings.withArguments(ParametersListUtil.parse(myArguments)); - } - ExternalSystemProgressNotificationManagerImpl progressNotificationManager = (ExternalSystemProgressNotificationManagerImpl)ServiceManager.getService(ExternalSystemProgressNotificationManager.class); ExternalSystemTaskId id = getId(); - progressNotificationManager.onStart(id, myProjectPath); + + Project ideProject; + RemoteExternalSystemProjectResolver resolver; + ExternalSystemExecutionSettings settings; + try { + progressNotificationManager.onStart(id, myProjectPath); + + final ExternalSystemFacadeManager manager = ServiceManager.getService(ExternalSystemFacadeManager.class); + ideProject = getIdeProject(); + resolver = manager.getFacade(ideProject, myProjectPath, getExternalSystemId()).getResolver(); + settings = ExternalSystemApiUtil.getExecutionSettings(ideProject, myProjectPath, getExternalSystemId()); + if (StringUtil.isNotEmpty(myVmOptions)) { + settings.withVmOptions(ParametersListUtil.parse(myVmOptions)); + } + if (StringUtil.isNotEmpty(myArguments)) { + settings.withArguments(ParametersListUtil.parse(myArguments)); + } + } + catch (Exception e) { + progressNotificationManager.onFailure(id, e); + progressNotificationManager.onEnd(id); + throw e; + } + try { DataNode project = resolver.resolveProjectInfo(id, myProjectPath, myIsPreviewMode, settings); if (project != null) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemTaskManagerWrapper.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemTaskManagerWrapper.java index b4b50c17385c..14dbabdec27d 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemTaskManagerWrapper.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/remote/wrapper/ExternalSystemTaskManagerWrapper.java @@ -48,7 +48,6 @@ public class ExternalSystemTaskManagerWrapperOpen Gradle Settings \n", - OpenExternalSystemSettingsCallback.ID), - linkedProjectPath, e, OpenExternalSystemSettingsCallback.ID); + OpenExternalSystemSettingsCallback.ID), e, OpenExternalSystemSettingsCallback.ID); } if (sdk == null && gradleJvm != null) { throw new ExternalSystemJdkException( String.format("Invalid Gradle JDK configuration found. Open Gradle Settings \n", - OpenExternalSystemSettingsCallback.ID), - linkedProjectPath, null, OpenExternalSystemSettingsCallback.ID); + OpenExternalSystemSettingsCallback.ID), null, OpenExternalSystemSettingsCallback.ID); } String sdkHomePath = sdk != null ? sdk.getHomePath() : null; if (sdkHomePath != null && JdkUtil.checkForJre(sdkHomePath) && !JdkUtil.checkForJdk(sdkHomePath)) { throw new ExternalSystemJdkException( String.format("Please, use JDK instead of JRE for Gradle importer. Open Gradle Settings \n", - OpenExternalSystemSettingsCallback.ID), - linkedProjectPath, null, OpenExternalSystemSettingsCallback.ID); + OpenExternalSystemSettingsCallback.ID), null, OpenExternalSystemSettingsCallback.ID); } return sdk;