@Nullable
  protected String resolveProjectPath(@NotNull Module module) {
    final String rootProjectPath = ExternalSystemApiUtil.getExternalRootProjectPath(module);
    String projectPath = ExternalSystemApiUtil.getExternalProjectPath(module);

    if (rootProjectPath == null || projectPath == null) return null;
    if (!FileUtil.isAncestor(rootProjectPath, projectPath, false)) {
      projectPath = rootProjectPath;
    }
    return projectPath;
  }
 @Override
 protected void validateConfiguration(
     @NotNull RunConfigurationBase configuration, boolean isExecution) throws Exception {
   super.validateConfiguration(configuration, isExecution);
   if (configuration instanceof ModuleBasedConfiguration
       && configuration instanceof CommonProgramRunConfigurationParameters) {
     final String workingDirectory =
         ((CommonProgramRunConfigurationParameters) configuration).getWorkingDirectory();
     if (("$" + PathMacroUtil.MODULE_DIR_MACRO_NAME + "$").equals(workingDirectory)) {
       final RunConfigurationModule runConfigurationModule =
           ((ModuleBasedConfiguration) configuration).getConfigurationModule();
       final String projectPath =
           ExternalSystemApiUtil.getExternalProjectPath(runConfigurationModule.getModule());
       if (StringUtil.isNotEmpty(projectPath)) {
         ((CommonProgramRunConfigurationParameters) configuration)
             .setWorkingDirectory(projectPath);
       }
     }
   }
 }
  @Override
  public void computeInReadAction(@NotNull ProgressIndicator indicator) {
    if (myProject.isDisposed()) return;
    if (ApplicationManager.getApplication().isUnitTestMode()) return;

    final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
    final List<PsiFile> psiFileList = ContainerUtil.newArrayList();

    final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
    for (Module module : moduleManager.getModules()) {
      if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module))
        continue;

      final String modulePath = ExternalSystemApiUtil.getExternalProjectPath(module);
      if (modulePath == null) continue;

      String buildScript =
          FileUtil.findFileInProvidedPath(modulePath, GradleConstants.DEFAULT_SCRIPT_NAME);
      if (StringUtil.isEmpty(buildScript)) continue;

      VirtualFile virtualFile = localFileSystem.refreshAndFindFileByPath(buildScript);
      if (virtualFile == null) continue;

      final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(virtualFile);
      if (psiFile == null) continue;
      psiFileList.add(psiFile);
    }

    final PsiFile[] psiFiles = ArrayUtil.toObjectArray(psiFileList, PsiFile.class);

    final Set<MavenRemoteRepository> mavenRemoteRepositories =
        new ReadAction<Set<MavenRemoteRepository>>() {
          @Override
          protected void run(@NotNull Result<Set<MavenRemoteRepository>> result) throws Throwable {
            Set<MavenRemoteRepository> myRemoteRepositories = ContainerUtil.newHashSet();
            for (PsiFile psiFile : psiFiles) {
              List<GrClosableBlock> repositoriesBlocks = ContainerUtil.newArrayList();
              repositoriesBlocks.addAll(findClosableBlocks(psiFile, "repositories"));

              for (GrClosableBlock closableBlock :
                  findClosableBlocks(
                      psiFile,
                      "buildscript",
                      "subprojects",
                      "allprojects",
                      "project",
                      "configure")) {
                repositoriesBlocks.addAll(findClosableBlocks(closableBlock, "repositories"));
              }

              for (GrClosableBlock repositoriesBlock : repositoriesBlocks) {
                myRemoteRepositories.addAll(findMavenRemoteRepositories(repositoriesBlock));
              }
            }

            result.setResult(myRemoteRepositories);
          }
        }.execute().getResultObject();

    if (mavenRemoteRepositories == null || mavenRemoteRepositories.isEmpty()) return;

    // register imported maven repository URLs but do not force to download the index
    // the index can be downloaded and/or updated later using Maven Configuration UI (Settings ->
    // Build, Execution, Deployment -> Build tools -> Maven -> Repositories)
    MavenRepositoriesHolder.getInstance(myProject).update(mavenRemoteRepositories);
    MavenProjectIndicesManager.getInstance(myProject)
        .scheduleUpdateIndicesList(
            new Consumer<List<MavenIndex>>() {
              @Override
              public void consume(List<MavenIndex> indexes) {
                if (myProject.isDisposed()) return;

                final List<String> repositoriesWithEmptyIndex =
                    ContainerUtil.mapNotNull(
                        indexes,
                        new Function<MavenIndex, String>() {
                          @Override
                          public String fun(MavenIndex index) {
                            return index.getUpdateTimestamp() == -1
                                    && MavenRepositoriesHolder.getInstance(myProject)
                                        .contains(index.getRepositoryPathOrUrl())
                                ? index.getRepositoryPathOrUrl()
                                : null;
                          }
                        });

                if (!repositoriesWithEmptyIndex.isEmpty()) {
                  final NotificationData notificationData =
                      new NotificationData(
                          GradleBundle.message(
                              "gradle.integrations.maven.notification.not_updated_repository.title"),
                          "\n<br>"
                              + GradleBundle.message(
                                  "gradle.integrations.maven.notification.not_updated_repository.text",
                                  StringUtil.join(repositoriesWithEmptyIndex, "<br>")),
                          NotificationCategory.WARNING,
                          NotificationSource.PROJECT_SYNC);
                  notificationData.setBalloonNotification(true);
                  notificationData.setBalloonGroup(UNINDEXED_MAVEN_REPOSITORIES_NOTIFICATION_GROUP);
                  notificationData.setListener(
                      "#open",
                      new NotificationListener.Adapter() {
                        @Override
                        protected void hyperlinkActivated(
                            @NotNull Notification notification, @NotNull HyperlinkEvent e) {
                          ShowSettingsUtil.getInstance()
                              .showSettingsDialog(myProject, MavenRepositoriesConfigurable.class);
                        }
                      });

                  notificationData.setListener(
                      "#disable",
                      new NotificationListener.Adapter() {
                        @Override
                        protected void hyperlinkActivated(
                            @NotNull Notification notification, @NotNull HyperlinkEvent e) {
                          final int result =
                              Messages.showYesNoDialog(
                                  myProject,
                                  "Notification will be disabled for all projects.\n\n"
                                      + "Settings | Appearance & Behavior | Notifications | "
                                      + UNINDEXED_MAVEN_REPOSITORIES_NOTIFICATION_GROUP
                                      + "\ncan be used to configure the notification.",
                                  "Unindexed Maven Repositories Gradle Detection",
                                  "Disable Notification",
                                  CommonBundle.getCancelButtonText(),
                                  Messages.getWarningIcon());
                          if (result == Messages.YES) {
                            NotificationsConfigurationImpl.getInstanceImpl()
                                .changeSettings(
                                    UNINDEXED_MAVEN_REPOSITORIES_NOTIFICATION_GROUP,
                                    NotificationDisplayType.NONE,
                                    false,
                                    false);

                            notification.hideBalloon();
                          }
                        }
                      });

                  ExternalSystemNotificationManager.getInstance(myProject)
                      .showNotification(GradleConstants.SYSTEM_ID, notificationData);
                }
              }
            });
  }
  @NotNull
  static List<String> getTasksToRun(Module module) {
    final List<String> result;
    final String externalProjectId = ExternalSystemApiUtil.getExternalProjectId(module);
    if (externalProjectId == null) return ContainerUtil.emptyList();
    final String projectPath = ExternalSystemApiUtil.getExternalProjectPath(module);
    if (projectPath == null) return ContainerUtil.emptyList();
    final ExternalProjectInfo externalProjectInfo =
        ExternalSystemUtil.getExternalProjectInfo(
            module.getProject(), GradleConstants.SYSTEM_ID, projectPath);
    if (externalProjectInfo == null) return ContainerUtil.emptyList();

    if (StringUtil.endsWith(externalProjectId, ":test")
        || StringUtil.endsWith(externalProjectId, ":main")) {
      result = TEST_SOURCE_SET_TASKS;
    } else {
      final DataNode<ModuleData> moduleNode =
          GradleProjectResolverUtil.findModule(
              externalProjectInfo.getExternalProjectStructure(), projectPath);
      if (moduleNode == null) return ContainerUtil.emptyList();
      final String sourceSetId =
          StringUtil.substringAfter(
              externalProjectId, moduleNode.getData().getExternalName() + ':');
      if (sourceSetId == null) return ContainerUtil.emptyList();

      final DataNode<TaskData> taskNode =
          ExternalSystemApiUtil.find(
              moduleNode,
              ProjectKeys.TASK,
              new BooleanFunction<DataNode<TaskData>>() {
                @Override
                public boolean fun(DataNode<TaskData> node) {
                  return GradleCommonClassNames.GRADLE_API_TASKS_TESTING_TEST.equals(
                          node.getData().getType())
                      && StringUtil.startsWith(sourceSetId, node.getData().getName());
                }
              });

      if (taskNode == null) return ContainerUtil.emptyList();
      final String taskName = taskNode.getData().getName();
      result = ContainerUtil.list("clean" + StringUtil.capitalize(taskName), taskName);
    }

    final String path;
    if (!externalProjectId.startsWith(":")) {
      path = ":";
    } else {
      final List<String> pathParts = StringUtil.split(externalProjectId, ":");
      if (!pathParts.isEmpty()) pathParts.remove(pathParts.size() - 1);
      final String join = StringUtil.join(pathParts, ":");
      path = ":" + join + (!join.isEmpty() ? ":" : "");
    }
    return ContainerUtil.map(
        result,
        new Function<String, String>() {
          @Override
          public String fun(String s) {
            return path + s;
          }
        });
  }