mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
GRADLE-1856 Tooling API: Make it possible to get IntelliJ IDEA view to the gradle project
Improved gradle api exceptions reporting
This commit is contained in:
+12
-3
@@ -17,6 +17,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
|
||||
import com.intellij.projectImport.ProjectImportBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,6 +28,7 @@ import org.jetbrains.plugins.gradle.importing.model.GradleModule;
|
||||
import org.jetbrains.plugins.gradle.importing.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiException;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleIcons;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
@@ -157,14 +159,21 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
|
||||
}
|
||||
catch (Exception e) {
|
||||
Throwable unwrapped = RemoteUtil.unwrap(e);
|
||||
String reason = unwrapped.getLocalizedMessage();
|
||||
if (!StringUtil.isEmpty(reason)) {
|
||||
errorReason.set(reason);
|
||||
}
|
||||
if (unwrapped.getClass() == NoClassDefFoundError.class) {
|
||||
errorReason.set(GradleBundle.message("gradle.import.text.incomplete.tooling.api"));
|
||||
}
|
||||
else if (unwrapped.getClass() == GradleApiException.class) {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project. Reason: gradle api threw an exception:\n"
|
||||
+ ((GradleApiException)unwrapped).getOriginalReason()
|
||||
);
|
||||
}
|
||||
else {
|
||||
errorReason.set(unwrapped.getLocalizedMessage());
|
||||
GradleLog.LOG.warn("Can't resolve gradle project", e);
|
||||
}
|
||||
// Ignore here because it will be reported on method exit.
|
||||
GradleLog.LOG.warn("Can't resolve gradle project", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* We talk to Gradle API from the dedicated process, i.e. all gradle classes are loaded at that process in order to avoid
|
||||
* memory problems at IJ process. That means that if Gradle API throws an exception, it can't be correctly read at IJ process
|
||||
* (NoClassDefFoundError and ClassNotFoundException).
|
||||
* <p/>
|
||||
* This class allows to extract textual description of the target problem and deliver it for further processing without risking to
|
||||
* get the problems mentioned above. I.e. it doesn't require anything specific can be safely delivered to IJ process then.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 10/21/11 11:42 AM
|
||||
*/
|
||||
public class GradleApiException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String myOriginalReason;
|
||||
|
||||
public GradleApiException() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public GradleApiException(@Nullable String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
public GradleApiException(@Nullable Throwable cause) {
|
||||
this("", cause);
|
||||
}
|
||||
|
||||
public GradleApiException(@Nullable String message, @Nullable Throwable cause) {
|
||||
super(extractMessage(message, cause));
|
||||
if (cause == null) {
|
||||
myOriginalReason = "";
|
||||
return;
|
||||
}
|
||||
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
PrintWriter printWriter = new PrintWriter(stringWriter);
|
||||
try {
|
||||
cause.printStackTrace(printWriter);
|
||||
}
|
||||
finally {
|
||||
printWriter.close();
|
||||
}
|
||||
myOriginalReason = stringWriter.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return textual description of the wrapped exception (if any); empty string otherwise
|
||||
*/
|
||||
@NotNull
|
||||
public String getOriginalReason() {
|
||||
return myOriginalReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter s) {
|
||||
super.printStackTrace(s);
|
||||
s.println(myOriginalReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintStream s) {
|
||||
super.printStackTrace(s);
|
||||
s.println(myOriginalReason);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String extractMessage(@Nullable String message, @Nullable Throwable cause) {
|
||||
if (message != null) {
|
||||
return message;
|
||||
}
|
||||
return cause == null ? "" : cause.getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,11 +25,12 @@ public interface GradleProjectResolver extends Remote {
|
||||
* @param downloadLibraries flag that specifies if third-party libraries that are not available locally should be resolved (downloaded)
|
||||
* @return object-level representation of the target gradle project
|
||||
* @throws RemoteException in case of unexpected exception during remote communications
|
||||
* @throws GradleApiException in case of unexpected exception thrown from Gradle API
|
||||
* @throws IllegalArgumentException if given path doesn't point to directory that contains gradle project or if gradle api
|
||||
* returns invalid data
|
||||
* @throws IllegalStateException if it's not possible to resolve target project info
|
||||
*/
|
||||
@NotNull
|
||||
GradleProject resolveProjectInfo(@NotNull String projectPath, boolean downloadLibraries)
|
||||
throws RemoteException, IllegalArgumentException, IllegalStateException;
|
||||
throws RemoteException, GradleApiException, IllegalArgumentException, IllegalStateException;
|
||||
}
|
||||
|
||||
+18
-52
@@ -13,16 +13,13 @@ import org.gradle.tooling.model.idea.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.importing.model.*;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleService;
|
||||
import org.jetbrains.plugins.gradle.remote.*;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -37,16 +34,25 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
*/
|
||||
public class GradleProjectResolverImpl extends RemoteObject implements GradleProjectResolver, RemoteGradleService {
|
||||
|
||||
private static final Set<String> NON_UNIQUE_PATH_ENTRIES = new HashSet<String>(Arrays.asList(
|
||||
"src", "main", "java", "test", "resources"
|
||||
));
|
||||
|
||||
private final BlockingQueue<ProjectConnection> myConnections = new LinkedBlockingQueue<ProjectConnection>();
|
||||
private final AtomicReference<RemoteGradleProcessSettings> mySettings = new AtomicReference<RemoteGradleProcessSettings>();
|
||||
|
||||
private final BlockingQueue<ProjectConnection> myConnections = new LinkedBlockingQueue<ProjectConnection>();
|
||||
private final AtomicReference<RemoteGradleProcessSettings> mySettings = new AtomicReference<RemoteGradleProcessSettings>();
|
||||
private final GradleLibraryNamesMixer myLibraryNamesMixer = new GradleLibraryNamesMixer();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GradleProject resolveProjectInfo(@NotNull String projectPath, boolean downloadLibraries)
|
||||
throws RemoteException, GradleApiException, IllegalArgumentException, IllegalStateException
|
||||
{
|
||||
try {
|
||||
return doResolveProjectInfo(projectPath, downloadLibraries);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new GradleApiException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GradleProject doResolveProjectInfo(@NotNull String projectPath, boolean downloadLibraries)
|
||||
throws RemoteException, IllegalArgumentException, IllegalStateException
|
||||
{
|
||||
ProjectConnection connection = getConnection(projectPath);
|
||||
@@ -58,7 +64,7 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
|
||||
// populating dependent module object.
|
||||
Map<String, Pair<GradleModule, IdeaModule>> modules = createModules(project, result);
|
||||
populateModules(modules.values(), result);
|
||||
diversifyLibraryNamesIfNecessary(result);
|
||||
myLibraryNamesMixer.mixNames(result.getLibraries());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -315,46 +321,6 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gradle API doesn't provide library names at the moment, so, we deduce them from the path. However, it's possible to have identical
|
||||
* names then.
|
||||
* <p/>
|
||||
* This method solves that by diversifying duplicate library names.
|
||||
*
|
||||
* @param project target project which library names should be diversified if necessary
|
||||
*/
|
||||
private static void diversifyLibraryNamesIfNecessary(@NotNull GradleProject project) {
|
||||
Map<String, GradleLibrary> libraries = new HashMap<String, GradleLibrary>();
|
||||
for (GradleLibrary library : project.getLibraries()) {
|
||||
GradleLibrary previous = libraries.remove(library.getName());
|
||||
if (previous == null) {
|
||||
libraries.put(library.getName(), library);
|
||||
continue;
|
||||
}
|
||||
previous.setName(generateName(previous));
|
||||
libraries.put(previous.getName(), previous);
|
||||
library.setName(generateName(library));
|
||||
libraries.put(library.getName(), library);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String generateName(@NotNull GradleLibrary library) {
|
||||
for (LibraryPathType pathType : LibraryPathType.values()) {
|
||||
String path = library.getPath(pathType);
|
||||
if (path == null) {
|
||||
continue;
|
||||
}
|
||||
File file = new File(path).getParentFile();
|
||||
for (; file != null; file = file.getParentFile()) {
|
||||
if (!NON_UNIQUE_PATH_ENTRIES.contains(file.getName())) {
|
||||
return file.getName() + "-" + library.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return library.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to retrieve gradle api connection to use for the given project.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user