IDEA-53476 Gradle integration (Maven's level - dependencies, modules, repositories)

1. IJ modules are properly configured on importing from gradle now;
2. Module path received from the gradle api are checked now to be compatible with the content root;
3. 'Project icon' is displayed during importing project from gradle;
4. Improved error notification;
This commit is contained in:
Denis.Zhdanov
2011-09-01 14:05:57 +04:00
parent f7f7b9deb6
commit fc5688b16f
14 changed files with 344 additions and 59 deletions
@@ -4,11 +4,9 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.util.containers.ConcurrentFactoryMap;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.*;
import java.rmi.Remote;
import java.util.Map;
@@ -137,4 +135,24 @@ public class RemoteUtil {
thread.setContextClassLoader(prev);
}
}
/**
* There is a possible case that remotely called code throws exception during processing. That exception is wrapped at different
* levels then - {@link InvocationTargetException}, {@link UndeclaredThrowableException} etc.
* <p/>
* This method tries to extract the 'real exception' from the given potentially wrapped one.
*
* @param e exception to process
* @return extracted 'real exception' if any; given exception otherwise
*/
@NotNull
public static Throwable unwrap(@NotNull Throwable e) {
for (Throwable candidate = e; candidate != null; candidate = candidate.getCause()) {
Class<? extends Throwable> clazz = candidate.getClass();
if (clazz != InvocationTargetException.class && clazz != UndeclaredThrowableException.class) {
return candidate;
}
}
return e;
}
}
@@ -12,11 +12,14 @@ gradle.import.structure.settings.label.name=Name:
gradle.import.structure.settings.label.language.level=Language level:
gradle.import.title.error.resolve.generic=Resolve error
gradle.import.text.error.resolve.generic=Can't resolve target gradle project at '{0}'
gradle.import.text.error.resolve.generic.without.reason=Can''t resolve target gradle project at ''{0}''
gradle.import.text.error.resolve.generic.with.reason=Can''t resolve target gradle project at ''{0}''.\nReason: {1}
gradle.import.text.error.project.undefined=No project file is defined
gradle.import.text.error.directory.instead.file=Given path points to directory instead of gradle build file
gradle.import.text.error.invalid.path=Can't resolve gradle project. Reason: given path ({0}) doesn't point to a file
gradle.import.text.error.cannot.parse.project=Can not parse gradle project
gradle.import.text.error.undefined.name=Name is undefined
gradle.library.resolve.progress.text=Resolving gradle libraries
gradle.generic.text.error.sdk.undefined=Gradle installation is unknown
@@ -1,12 +1,20 @@
package org.jetbrains.plugins.gradle.importing;
import com.intellij.openapi.application.*;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.util.Alarm;
import com.intellij.util.containers.hash.HashMap;
@@ -14,6 +22,9 @@ import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.importing.model.*;
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleLog;
import java.io.File;
@@ -42,27 +53,28 @@ public class GradleModulesImporter {
/**
* Entry point for the whole 'import modules' procedure.
*
* @param modules module info containers received from the gradle api
* @param project project that should host the modules
* @param model modules model
* @return mappings between the given gradle modules and newly created intellij modules
* @param modules module info containers received from the gradle api
* @param project project that should host the modules
* @param model modules model
* @param gradleProjectPath file system path to the gradle project file being imported
* @return mappings between the given gradle modules and newly created intellij modules
*/
@NotNull
public Map<GradleModule, Module> importModules(@NotNull final Iterable<GradleModule> modules, @Nullable final Project project,
@Nullable final ModifiableModuleModel model)
@Nullable final ModifiableModuleModel model, @NotNull String gradleProjectPath)
{
if (project == null) {
return Collections.emptyMap();
}
removeExistingModulesSettings(modules);
if (!project.isInitialized()) {
myAlarm.addRequest(new ImportModulesTask(project, modules), PROJECT_INITIALISATION_DELAY_MS);
myAlarm.addRequest(new ImportModulesTask(project, modules, gradleProjectPath), PROJECT_INITIALISATION_DELAY_MS);
return Collections.emptyMap();
}
if (model == null) {
return Collections.emptyMap();
}
return importModules(modules, model);
return importModules(modules, model, project, gradleProjectPath);
}
private static void removeExistingModulesSettings(@NotNull Iterable<GradleModule> modules) {
@@ -80,7 +92,9 @@ public class GradleModulesImporter {
}
public Map<GradleModule, Module> importModules(@NotNull final Iterable<GradleModule> modules,
@NotNull final ModifiableModuleModel model)
@NotNull final ModifiableModuleModel model,
@NotNull final Project intellijProject,
@NotNull final String gradleProjectPath)
{
final Map<GradleModule, Module> result = new HashMap<GradleModule, Module>();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@@ -90,7 +104,13 @@ public class GradleModulesImporter {
AccessToken writeLock = application.acquireWriteActionLock(getClass());
try {
try {
result.putAll(doImportModules(modules, model));
Map<GradleModule, Module> moduleMappings = doImportModules(modules, model);
result.putAll(moduleMappings);
myAlarm.cancelAllRequests();
myAlarm.addRequest(
new SetupExternalLibrariesTask(moduleMappings, gradleProjectPath, intellijProject),
PROJECT_INITIALISATION_DELAY_MS
);
}
finally {
model.commit();
@@ -105,7 +125,7 @@ public class GradleModulesImporter {
}
/**
* Actual implementation of {@link #importModules(Iterable, Project, ModifiableModuleModel)}. Insists on all arguments to
* Actual implementation of {@link #importModules(Iterable, Project, ModifiableModuleModel, String)}. Insists on all arguments to
* be ready to use.
*
* @param modules modules to import
@@ -216,6 +236,156 @@ public class GradleModulesImporter {
}
}
/**
* Resolves (downloads if necessary) external libraries necessary for the gradle project located at the given path and configures
* them for the corresponding intellij project.
* <p/>
* <b>Note:</b> is assumed to be executed under write action.
*
* @param moduleMappings gradle-intellij module mappings
* @param intellijProject intellij project for the target gradle project
* @param gradleProjectPath file system path to the target gradle project
*/
private static void setupLibraries(@NotNull final Map<GradleModule, Module> moduleMappings,
@NotNull final Project intellijProject,
@NotNull final String gradleProjectPath)
{
final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
Runnable edtAction = new Runnable() {
@Override
public void run() {
final Ref<GradleProject> gradleProjectRef = new Ref<GradleProject>();
//ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
ProgressManager.getInstance().run(
new Task.Backgroundable(intellijProject, GradleBundle.message("gradle.library.resolve.progress.text"), false) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
indicator.setIndeterminate(true);
try {
GradleProjectResolver resolver = manager.getFacade().getResolver();
gradleProjectRef.set(resolver.resolveProjectInfo(gradleProjectPath, true));
}
catch (Exception e) {
GradleLog.LOG.warn("Can't resolve external dependencies of the target gradle project (" + gradleProjectPath + ")", e);
}
}
});
final GradleProject gradleProject = gradleProjectRef.get();
if (gradleProject == null) {
return;
}
Application application = ApplicationManager.getApplication();
AccessToken writeLock = application.acquireWriteActionLock(getClass());
try {
doSetupLibraries(moduleMappings, gradleProject, intellijProject);
}
finally {
writeLock.finish();
}
}
};
UIUtil.invokeLaterIfNeeded(edtAction);
}
private static void doSetupLibraries(@NotNull Map<GradleModule, Module> moduleMappings,
@NotNull GradleProject gradleProject,
@NotNull Project intellijProject)
{
Application application = ApplicationManager.getApplication();
application.assertWriteAccessAllowed();
Map<GradleLibrary, Library> libraryMappings = registerProjectLibraries(gradleProject, intellijProject);
if (libraryMappings == null) {
return;
}
configureModulesLibraryDependencies(moduleMappings, libraryMappings, gradleProject);
}
/**
* Registers {@link GradleProject#getLibraries() libraries} of the given gradle project at the intellij project.
*
* @param gradleProject target gradle project being imported
* @param intellijProject intellij representation of the given gradle project
* @return mapping between libraries of the given gradle and intellij projects
*/
@Nullable
private static Map<GradleLibrary, Library> registerProjectLibraries(GradleProject gradleProject, Project intellijProject) {
LibraryTable projectLibraryTable = ProjectLibraryTable.getInstance(intellijProject);
if (projectLibraryTable == null) {
GradleLog.LOG.warn(
"Can't resolve external dependencies of the target gradle project (" + intellijProject + "). Reason: project "
+ "library table is undefined"
);
return null;
}
Map<GradleLibrary, Library> libraryMappings = new HashMap<GradleLibrary, Library>();
for (GradleLibrary gradleLibrary : gradleProject.getLibraries()) {
Library intellijLibrary = projectLibraryTable.createLibrary(gradleLibrary.getName());
libraryMappings.put(gradleLibrary, intellijLibrary);
Library.ModifiableModel model = intellijLibrary.getModifiableModel();
try {
registerPath(gradleLibrary, model);
}
finally {
model.commit();
}
}
return libraryMappings;
}
private static void configureModulesLibraryDependencies(@NotNull Map<GradleModule, Module> moduleMappings,
@NotNull final Map<GradleLibrary, Library> libraryMappings,
@NotNull GradleProject gradleProject) {
for (GradleModule gradleModule : gradleProject.getModules()) {
Module intellijModule = moduleMappings.get(gradleModule);
if (intellijModule == null) {
GradleLog.LOG.warn(String.format(
"Can't find intellij module for the gradle module '%s'. Registered mappings: %s", gradleModule, moduleMappings
));
continue;
}
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(intellijModule);
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
GradleEntityVisitor visitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
GradleLibrary gradleLibrary = dependency.getLibrary();
Library intellijLibrary = libraryMappings.get(gradleLibrary);
if (intellijLibrary == null) {
GradleLog.LOG.warn(String.format(
"Can't find registered intellij library for gradle library '%s'. Registered mappings: %s", gradleLibrary, libraryMappings
));
return;
}
LibraryOrderEntry orderEntry = moduleRootModel.addLibraryEntry(intellijLibrary);
orderEntry.setExported(dependency.isExported());
orderEntry.setScope(dependency.getScope());
}
};
try {
for (GradleDependency dependency : gradleModule.getDependencies()) {
dependency.invite(visitor);
}
}
finally {
moduleRootModel.commit();
}
}
}
private static void registerPath(@NotNull GradleLibrary gradleLibrary, @NotNull Library.ModifiableModel model) {
for (LibraryPathType pathType : LibraryPathType.values()) {
String path = gradleLibrary.getPath(pathType);
if (path != null) {
model.addRoot(toVfsUrl(path), pathType.getRootType());
}
}
}
private static String toVfsUrl(@NotNull String path) {
return LocalFileSystem.PROTOCOL_PREFIX + path;
}
@@ -224,17 +394,19 @@ public class GradleModulesImporter {
private final Project myProject;
private final Iterable<GradleModule> myModules;
private final String myGradleProjectPath;
private ImportModulesTask(@NotNull Project project, @NotNull Iterable<GradleModule> modules) {
private ImportModulesTask(@NotNull Project project, @NotNull Iterable<GradleModule> modules, @NotNull String gradleProjectPath) {
myProject = project;
myModules = modules;
myGradleProjectPath = gradleProjectPath;
}
@Override
public void run() {
myAlarm.cancelAllRequests();
if (!myProject.isInitialized()) {
myAlarm.addRequest(new ImportModulesTask(myProject, myModules), PROJECT_INITIALISATION_DELAY_MS);
myAlarm.addRequest(new ImportModulesTask(myProject, myModules, myGradleProjectPath), PROJECT_INITIALISATION_DELAY_MS);
return;
}
@@ -243,8 +415,26 @@ public class GradleModulesImporter {
result.setResult(ModuleManager.getInstance(myProject).getModifiableModel());
}
}.execute().getResultObject();
importModules(myModules, model, myProject, myGradleProjectPath);
}
}
private static class SetupExternalLibrariesTask implements Runnable {
importModules(myModules, model);
private final Map<GradleModule, Module> myModules;
private final String myGradleProjectPath;
private final Project myIntellijProject;
SetupExternalLibrariesTask(@NotNull Map<GradleModule, Module> modules, @NotNull String gradleProjectPath, Project intellijProject) {
myModules = modules;
myGradleProjectPath = gradleProjectPath;
myIntellijProject = intellijProject;
}
@Override
public void run() {
setupLibraries(myModules, myIntellijProject, myGradleProjectPath);
}
}
}
@@ -1,8 +1,10 @@
package org.jetbrains.plugins.gradle.importing.model;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.io.File;
import java.util.*;
/**
@@ -39,7 +41,21 @@ public class GradleContentRoot extends AbstractGradleEntity {
return myData.get(type);
}
public void storePath(@NotNull SourceType type, @NotNull String path) {
/**
* Ask to remember that directory at the given path contains sources of the given type.
*
* @param type target sources type
* @param path target source directory path
* @throws IllegalArgumentException if given path points to the directory that is not located
* under the {@link #getRootPath() content root}
*/
public void storePath(@NotNull SourceType type, @NotNull String path) throws IllegalArgumentException {
if (!FileUtil.isAncestor(new File(getRootPath()), new File(path), false)) {
throw new IllegalArgumentException(String.format(
"Can't register given path of type '%s' because it's out of content root.%nContent root: '%s'%nGiven path: '%s'",
type, getRootPath(), new File(path).getAbsolutePath()
));
}
myData.get(type).add(GradleUtil.toCanonicalPath(path));
}
@@ -138,6 +138,7 @@ public class GradleModule extends AbstractNamedGradleEntity implements Named {
@Override
public GradleModule clone() {
GradleModule result = new GradleModule(getName(), new File(getModuleFilePath()).getParent());
result.setInheritProjectCompileOutputPath(isInheritProjectCompileOutputPath());
for (GradleContentRoot contentRoot : getContentRoots()) {
result.addContentRoot(contentRoot.clone());
}
@@ -1,8 +1,27 @@
package org.jetbrains.plugins.gradle.importing.model;
import com.intellij.openapi.roots.OrderRootType;
import org.jetbrains.annotations.NotNull;
/**
* Note that current enum duplicates {@link OrderRootType}. We can't use the later directly because it's not properly setup
* for serialization/deserialization.
*
* @author Denis Zhdanov
* @since 8/10/11 6:37 PM
*/
public enum LibraryPathType {
BINARY, SOURCE, JAVADOC}
BINARY(OrderRootType.CLASSES), SOURCE(OrderRootType.SOURCES), JAVADOC(OrderRootType.DOCUMENTATION);
private final transient OrderRootType myRootType;
LibraryPathType(@NotNull OrderRootType rootType) {
myRootType = rootType;
}
@NotNull
public OrderRootType getRootType() {
return myRootType;
}
}
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.gradle.importing.wizard;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.projectImport.ProjectImportWizardStep;
import org.jetbrains.annotations.NotNull;
/**
@@ -10,21 +10,20 @@ import org.jetbrains.annotations.NotNull;
* @author Denis Zhdanov
* @since 8/2/11 3:22 PM
*/
public abstract class AbstractImportFromGradleWizardStep extends ModuleWizardStep {
public abstract class AbstractImportFromGradleWizardStep extends ProjectImportWizardStep {
private final WizardContext myContext;
protected AbstractImportFromGradleWizardStep(@NotNull WizardContext context) {
myContext = context;
super(context);
}
@NotNull
public WizardContext getContext() {
return myContext;
@Override
public WizardContext getWizardContext() {
return super.getWizardContext();
}
@Override
@NotNull
protected GradleProjectImportBuilder getBuilder() {
return (GradleProjectImportBuilder)myContext.getProjectBuilder();
return (GradleProjectImportBuilder)getWizardContext().getProjectBuilder();
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.plugins.gradle.importing.wizard;
import com.intellij.execution.rmi.RemoteUtil;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.components.ServiceManager;
@@ -15,6 +16,7 @@ import com.intellij.openapi.projectRoots.JavaSdk;
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.packaging.artifacts.ModifiableArtifactModel;
import com.intellij.projectImport.ProjectImportBuilder;
import org.jetbrains.annotations.NotNull;
@@ -84,7 +86,7 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
ModifiableArtifactModel artifactModel)
{
GradleModulesImporter importer = new GradleModulesImporter();
Map<GradleModule, Module> mappings = importer.importModules(myModuleMappings.values(), project, model);
Map<GradleModule, Module> mappings = importer.importModules(myModuleMappings.values(), project, model, myProjectFile.getAbsolutePath());
return new ArrayList<Module>(mappings.values());
}
@@ -139,19 +141,22 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
if (myProjectFile.isDirectory()) {
throw new ConfigurationException(GradleBundle.message("gradle.import.text.error.directory.instead.file"));
}
final Ref<String> errorReason = new Ref<String>();
try {
// TODO den derive target project for 'import module from gradle' (for 'add module' functionality).
Project project = ProjectManager.getInstance().getDefaultProject();
ProgressManager.getInstance().run(new Task.Modal(project, GradleBundle.message("gradle.import.progress.text"), true) {
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
@Override
public void run(@NotNull ProgressIndicator indicator) {
indicator.setIndeterminate(true);
GradleApiFacadeManager manager = ServiceManager.getService(getProject(), GradleApiFacadeManager.class);
GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
try {
GradleProjectResolver resolver = manager.getFacade().getResolver();
myGradleProject = resolver.resolveProjectInfo(myProjectFile.getAbsolutePath(), false);
}
catch (Exception e) {
errorReason.set(RemoteUtil.unwrap(e).getLocalizedMessage());
// Ignore here because it will be reported on method exit.
GradleLog.LOG.warn("Can't resolve gradle project", e);
}
@@ -162,10 +167,12 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
throw new ConfigurationException(e.getMessage(), GradleBundle.message("gradle.import.text.error.cannot.parse.project"));
}
if (myGradleProject == null) {
throw new ConfigurationException(
GradleBundle.message("gradle.import.text.error.resolve.generic", myProjectFile.getPath()),
GradleBundle.message("gradle.import.title.error.resolve.generic")
);
String errorMessage = GradleBundle.message("gradle.import.text.error.resolve.generic.without.reason", myProjectFile.getPath());
String reason = errorReason.get();
if (reason != null) {
errorMessage = GradleBundle.message("gradle.import.text.error.resolve.generic.with.reason", myProjectFile.getPath(), reason);
}
throw new ConfigurationException(errorMessage, GradleBundle.message("gradle.import.title.error.resolve.generic"));
}
}
@@ -156,7 +156,7 @@ public class GradleAdjustImportSettingsStep extends AbstractImportFromGradleWiza
if (project == null) {
throw new IllegalStateException(String.format(
"Can't init 'adjust importing settings' step. Reason: no project is defined. Context: '%s', builder: '%s'",
getContext(), getBuilder()
getWizardContext(), getBuilder()
));
}
@@ -289,7 +289,7 @@ public class GradleAdjustImportSettingsStep extends AbstractImportFromGradleWiza
return false;
}
}
getBuilder().applyProjectSettings(getContext());
getBuilder().applyProjectSettings(getWizardContext());
return true;
}
@@ -59,7 +59,7 @@ public class GradleSelectProjectStep extends AbstractImportFromGradleWizardStep
@Override
public void updateStep() {
if (isPathChanged()) {
myProjectPathComponent.setText(getBuilder().getProjectPath(getContext()));
myProjectPathComponent.setText(getBuilder().getProjectPath(getWizardContext()));
}
}
@@ -86,6 +86,6 @@ public class GradleSelectProjectStep extends AbstractImportFromGradleWizardStep
}
private boolean isPathChanged() {
return !StringUtil.equals(myProjectPathComponent.getText(), getBuilder().getProjectPath(getContext()));
return !StringUtil.equals(myProjectPathComponent.getText(), getBuilder().getProjectPath(getWizardContext()));
}
}
@@ -15,6 +15,7 @@ import com.intellij.execution.rmi.RemoteProcessSupport;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.JdkUtil;
import com.intellij.openapi.projectRoots.Sdk;
@@ -121,6 +122,7 @@ public class GradleApiFacadeManager {
ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(PsiBundle.class), classPath);
ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Alarm.class), classPath);
ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(DependencyScope.class), classPath);
ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(ExtensionPointName.class), classPath);
ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(getClass()), classPath);
for (File library : gradleLibraries) {
classPath.add(library.getAbsolutePath());
@@ -25,7 +25,8 @@ 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 IllegalArgumentException if given path doesn't point to directory that contains gradle project
* @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
@@ -43,21 +43,13 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
@NotNull
@Override
public GradleProject resolveProjectInfo(@NotNull String projectPath, boolean downloadLibraries) throws RemoteException {
try {
return doResolve(projectPath, downloadLibraries);
}
catch (Throwable e) {
throw new IllegalStateException(GradleBundle.message("gradle.import.text.error.resolve.generic", projectPath), e);
}
}
@NotNull
private GradleProject doResolve(@NotNull String projectPath, boolean downloadLibraries) {
public GradleProject resolveProjectInfo(@NotNull String projectPath, boolean downloadLibraries)
throws RemoteException, IllegalArgumentException, IllegalStateException
{
ProjectConnection connection = getConnection(projectPath);
IdeaProject project = connection.getModel(downloadLibraries ? IdeaProject.class : OfflineIdeaProject.class);
GradleProject result = populateProject(project, projectPath);
// We need two different steps ('create' and 'populate') in order to handle module dependencies, i.e. when one module is
// configured to be dependency for another one, corresponding dependency module object should be available during
// populating dependent module object.
@@ -107,25 +99,36 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
return result;
}
private static void populateModules(@NotNull Iterable<Pair<GradleModule, IdeaModule>> modules,
private static void populateModules(@NotNull Iterable<Pair<GradleModule,IdeaModule>> modules,
@NotNull GradleProject intellijProject)
throws IllegalStateException
throws IllegalArgumentException, IllegalStateException
{
for (Pair<GradleModule, IdeaModule> pair : modules) {
populateModule(pair.second, pair.first, intellijProject);
}
}
private static void populateModule(@NotNull IdeaModule gradleModule, @NotNull GradleModule intellijModule,
private static void populateModule(@NotNull IdeaModule gradleModule,
@NotNull GradleModule intellijModule,
@NotNull GradleProject intellijProject)
throws IllegalStateException
throws IllegalArgumentException, IllegalStateException
{
populateContentRoots(gradleModule, intellijModule);
populateCompileOutputSettings(gradleModule.getCompilerOutput(), intellijModule);
populateDependencies(gradleModule, intellijModule, intellijProject);
}
private static void populateContentRoots(@NotNull IdeaModule gradleModule, @NotNull GradleModule intellijModule) {
/**
* Populates {@link GradleModule#getContentRoots() content roots} of the given intellij module on the basis of the information
* contained at the given gradle module.
*
* @param gradleModule holder of the module information received from the gradle tooling api
* @param intellijModule corresponding module from intellij gradle plugin domain
* @throws IllegalArgumentException if given gradle module contains invalid data
*/
private static void populateContentRoots(@NotNull IdeaModule gradleModule, @NotNull GradleModule intellijModule)
throws IllegalArgumentException
{
DomainObjectSet<? extends IdeaContentRoot> contentRoots = gradleModule.getContentRoots();
if (contentRoots == null) {
return;
@@ -150,9 +153,19 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
intellijModule.addContentRoot(intellijContentRoot);
}
}
private static void populateContentRoot(@NotNull GradleContentRoot contentRoot, SourceType type,
/**
* Stores information about given directories at the given content root
*
* @param contentRoot target paths info holder
* @param type type of data located at the given directories
* @param dirs directories which paths should be stored at the given content root
* @throws IllegalArgumentException if specified by {@link GradleContentRoot#storePath(SourceType, String)}
*/
private static void populateContentRoot(@NotNull GradleContentRoot contentRoot,
@NotNull SourceType type,
@Nullable Iterable<? extends IdeaSourceDirectory> dirs)
throws IllegalArgumentException
{
if (dirs == null) {
return;
@@ -0,0 +1,16 @@
package org.jetbrains.plugins.gradle.importing.model;
import org.junit.Test;
/**
* @author Denis Zhdanov
* @since 8/31/11 1:33 PM
*/
public class GradleContentRootTest {
@Test(expected = IllegalArgumentException.class)
public void pathOutOfContentRoot() {
GradleContentRoot contentRoot = new GradleContentRoot("./my-content-root");
contentRoot.storePath(SourceType.SOURCE, "./my-dir-out-of-content-root");
}
}