@NotNull
  private static AbstractGradleDependency buildDependency(
      @NotNull GradleModule ownerModule,
      @NotNull IdeaModuleDependency dependency,
      @NotNull GradleProject intellijProject)
      throws IllegalStateException {
    IdeaModule module = dependency.getDependencyModule();
    if (module == null) {
      throw new IllegalStateException(
          String.format(
              "Can't parse gradle module dependency '%s'. Reason: referenced module is null",
              dependency));
    }

    String moduleName = module.getName();
    if (moduleName == null) {
      throw new IllegalStateException(
          String.format(
              "Can't parse gradle module dependency '%s'. Reason: referenced module name is undefined (module: '%s') ",
              dependency, module));
    }

    Set<String> registeredModuleNames = new HashSet<String>();
    for (GradleModule gradleModule : intellijProject.getModules()) {
      registeredModuleNames.add(gradleModule.getName());
      if (gradleModule.getName().equals(moduleName)) {
        return new GradleModuleDependency(ownerModule, gradleModule);
      }
    }
    throw new IllegalStateException(
        String.format(
            "Can't parse gradle module dependency '%s'. Reason: no module with such name (%s) is found. Registered modules: %s",
            dependency, moduleName, registeredModuleNames));
  }
 @NotNull
 private static Map<String, Pair<GradleModule, IdeaModule>> createModules(
     @NotNull IdeaProject gradleProject, @NotNull GradleProject intellijProject)
     throws IllegalStateException {
   DomainObjectSet<? extends IdeaModule> gradleModules = gradleProject.getModules();
   if (gradleModules == null || gradleModules.isEmpty()) {
     throw new IllegalStateException("No modules found for the target project: " + gradleProject);
   }
   Map<String, Pair<GradleModule, IdeaModule>> result =
       new HashMap<String, Pair<GradleModule, IdeaModule>>();
   for (IdeaModule gradleModule : gradleModules) {
     if (gradleModule == null) {
       continue;
     }
     String moduleName = gradleModule.getName();
     if (moduleName == null) {
       throw new IllegalStateException("Module with undefined name detected: " + gradleModule);
     }
     GradleModule intellijModule =
         new GradleModule(moduleName, intellijProject.getProjectFileDirectoryPath());
     Pair<GradleModule, IdeaModule> previouslyParsedModule = result.get(moduleName);
     if (previouslyParsedModule != null) {
       throw new IllegalStateException(
           String.format(
               "Modules with duplicate name (%s) detected: '%s' and '%s'",
               moduleName, intellijModule, previouslyParsedModule));
     }
     result.put(moduleName, new Pair<GradleModule, IdeaModule>(intellijModule, gradleModule));
     intellijProject.addModule(intellijModule);
   }
   return result;
 }
  private static void populateDependencies(
      @NotNull IdeaModule gradleModule,
      @NotNull GradleModule intellijModule,
      @NotNull GradleProject intellijProject) {
    DomainObjectSet<? extends IdeaDependency> dependencies = gradleModule.getDependencies();
    if (dependencies == null) {
      return;
    }
    for (IdeaDependency dependency : dependencies) {
      if (dependency == null) {
        continue;
      }
      AbstractGradleDependency intellijDependency = null;
      if (dependency instanceof IdeaModuleDependency) {
        intellijDependency =
            buildDependency(intellijModule, (IdeaModuleDependency) dependency, intellijProject);
      } else if (dependency instanceof IdeaSingleEntryLibraryDependency) {
        intellijDependency =
            buildDependency(
                intellijModule, (IdeaSingleEntryLibraryDependency) dependency, intellijProject);
      }

      if (intellijDependency == null) {
        continue;
      }

      intellijDependency.setExported(dependency.getExported());
      DependencyScope scope = parseScope(dependency.getScope());
      if (scope != null) {
        intellijDependency.setScope(scope);
      }
      intellijModule.addDependency(intellijDependency);
    }
  }
 /**
  * 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;
   }
   for (IdeaContentRoot gradleContentRoot : contentRoots) {
     if (gradleContentRoot == null) {
       continue;
     }
     File rootDirectory = gradleContentRoot.getRootDirectory();
     if (rootDirectory == null) {
       continue;
     }
     GradleContentRoot intellijContentRoot =
         new GradleContentRoot(intellijModule, rootDirectory.getAbsolutePath());
     populateContentRoot(
         intellijContentRoot, SourceType.SOURCE, gradleContentRoot.getSourceDirectories());
     populateContentRoot(
         intellijContentRoot, SourceType.TEST, gradleContentRoot.getTestDirectories());
     Set<File> excluded = gradleContentRoot.getExcludeDirectories();
     if (excluded != null) {
       for (File file : excluded) {
         intellijContentRoot.storePath(SourceType.EXCLUDED, file.getAbsolutePath());
       }
     }
     intellijModule.addContentRoot(intellijContentRoot);
   }
 }
 private static void populateModule(
     @NotNull IdeaModule gradleModule,
     @NotNull GradleModule intellijModule,
     @NotNull GradleProject intellijProject)
     throws IllegalArgumentException, IllegalStateException {
   populateContentRoots(gradleModule, intellijModule);
   populateCompileOutputSettings(gradleModule.getCompilerOutput(), intellijModule);
   populateDependencies(gradleModule, intellijModule, intellijProject);
 }
  @NotNull
  private DataNode<ProjectData> doResolveProjectInfo(
      @NotNull final ProjectResolverContext resolverCtx,
      @NotNull final GradleProjectResolverExtension projectResolverChain)
      throws IllegalArgumentException, IllegalStateException {

    final ProjectImportAction projectImportAction =
        new ProjectImportAction(resolverCtx.isPreviewMode());

    // inject ProjectResolverContext into gradle project resolver extensions
    // collect extra JVM arguments provided by gradle project resolver extensions
    // and register classes of extra gradle project models required for extensions (e.g.
    // com.android.builder.model.AndroidProject)
    final List<KeyValue<String, String>> extraJvmArgs = new ArrayList<KeyValue<String, String>>();
    for (GradleProjectResolverExtension resolverExtension = projectResolverChain;
        resolverExtension != null;
        resolverExtension = resolverExtension.getNext()) {
      resolverExtension.setProjectResolverContext(resolverCtx);
      projectImportAction.addExtraProjectModelClasses(
          resolverExtension.getExtraProjectModelClasses());
      extraJvmArgs.addAll(resolverExtension.getExtraJvmArgs());
    }
    final ParametersList parametersList = new ParametersList();
    for (KeyValue<String, String> jvmArg : extraJvmArgs) {
      parametersList.addProperty(jvmArg.getKey(), jvmArg.getValue());
    }

    BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor =
        resolverCtx.getConnection().action(projectImportAction);
    GradleExecutionHelper.prepare(
        buildActionExecutor,
        resolverCtx.getExternalSystemTaskId(),
        resolverCtx.getSettings(),
        resolverCtx.getListener(),
        parametersList.getParameters(),
        resolverCtx.getConnection());

    // TODO [vlad] remove the check
    if (GradleEnvironment.USE_ENHANCED_TOOLING_API) {
      GradleExecutionHelper.setInitScript(buildActionExecutor);
    }

    ProjectImportAction.AllModels allModels;
    try {
      allModels = buildActionExecutor.run();
      if (allModels == null) {
        throw new IllegalStateException(
            "Unable to get project model for the project: " + resolverCtx.getProjectPath());
      }
    } catch (UnsupportedVersionException unsupportedVersionException) {
      // Old gradle distribution version used (before ver. 1.8)
      // fallback to use ModelBuilder gradle tooling API
      ModelBuilder<? extends IdeaProject> modelBuilder =
          myHelper.getModelBuilder(
              resolverCtx.isPreviewMode() ? BasicIdeaProject.class : IdeaProject.class,
              resolverCtx.getExternalSystemTaskId(),
              resolverCtx.getSettings(),
              resolverCtx.getConnection(),
              resolverCtx.getListener(),
              parametersList.getParameters());

      final IdeaProject ideaProject = modelBuilder.get();
      allModels = new ProjectImportAction.AllModels(ideaProject);
    }

    final BuildEnvironment buildEnvironment = getBuildEnvironment(resolverCtx);
    allModels.setBuildEnvironment(buildEnvironment);
    resolverCtx.setModels(allModels);

    // import project data
    ProjectData projectData = projectResolverChain.createProject();
    DataNode<ProjectData> projectDataNode =
        new DataNode<ProjectData>(ProjectKeys.PROJECT, projectData, null);

    // import java project data
    JavaProjectData javaProjectData = projectResolverChain.createJavaProjectData();
    projectDataNode.createChild(JavaProjectData.KEY, javaProjectData);

    IdeaProject ideaProject = resolverCtx.getModels().getIdeaProject();
    DomainObjectSet<? extends IdeaModule> gradleModules = ideaProject.getModules();
    if (gradleModules == null || gradleModules.isEmpty()) {
      throw new IllegalStateException("No modules found for the target project: " + ideaProject);
    }
    final Map<String, Pair<DataNode<ModuleData>, IdeaModule>> moduleMap =
        ContainerUtilRt.newHashMap();

    // import modules data
    for (IdeaModule gradleModule : gradleModules) {
      if (gradleModule == null) {
        continue;
      }
      final String moduleName = gradleModule.getName();
      if (moduleName == null) {
        throw new IllegalStateException("Module with undefined name detected: " + gradleModule);
      }

      ModuleData moduleData = projectResolverChain.createModule(gradleModule, projectData);

      Pair<DataNode<ModuleData>, IdeaModule> previouslyParsedModule = moduleMap.get(moduleName);
      if (previouslyParsedModule != null) {
        throw new IllegalStateException(
            String.format(
                "Modules with duplicate name (%s) detected: '%s' and '%s'",
                moduleName, moduleData, previouslyParsedModule));
      }
      DataNode<ModuleData> moduleDataNode =
          projectDataNode.createChild(ProjectKeys.MODULE, moduleData);
      moduleMap.put(
          moduleName, new Pair<DataNode<ModuleData>, IdeaModule>(moduleDataNode, gradleModule));
    }

    // populate modules nodes
    final List<TaskData> allTasks = ContainerUtil.newArrayList();
    for (final Pair<DataNode<ModuleData>, IdeaModule> pair : moduleMap.values()) {
      final DataNode<ModuleData> moduleDataNode = pair.first;
      final IdeaModule ideaModule = pair.second;
      projectResolverChain.populateModuleExtraModels(ideaModule, moduleDataNode);
      projectResolverChain.populateModuleContentRoots(ideaModule, moduleDataNode);
      projectResolverChain.populateModuleCompileOutputSettings(ideaModule, moduleDataNode);
      projectResolverChain.populateModuleDependencies(ideaModule, moduleDataNode, projectDataNode);
      final Collection<TaskData> moduleTasks =
          projectResolverChain.populateModuleTasks(ideaModule, moduleDataNode, projectDataNode);
      allTasks.addAll(moduleTasks);
    }

    // populate root project tasks
    final Collection<TaskData> rootProjectTaskCandidates =
        projectResolverChain.filterRootProjectTasks(allTasks);

    Set<Pair<String /* task name */, String /* task description */>> rootProjectTaskCandidatesMap =
        ContainerUtilRt.newHashSet();
    for (final TaskData taskData : rootProjectTaskCandidates) {
      rootProjectTaskCandidatesMap.add(Pair.create(taskData.getName(), taskData.getDescription()));
    }
    for (final Pair<String, String> p : rootProjectTaskCandidatesMap) {
      projectDataNode.createChild(
          ProjectKeys.TASK,
          new TaskData(
              GradleConstants.SYSTEM_ID,
              p.first,
              projectData.getLinkedExternalProjectPath(),
              p.second));
    }

    // ensure unique library names
    Collection<DataNode<LibraryData>> libraries =
        ExternalSystemApiUtil.getChildren(projectDataNode, ProjectKeys.LIBRARY);
    myLibraryNamesMixer.mixNames(libraries);

    return projectDataNode;
  }