external system: before_sync/after_sync actions
authorVladislav.Soroka <Vladislav.Soroka@jetbrains.com>
Mon, 16 Feb 2015 10:58:25 +0000 (13:58 +0300)
committerVladislav.Soroka <Vladislav.Soroka@jetbrains.com>
Mon, 16 Feb 2015 11:04:39 +0000 (14:04 +0300)
platform/external-system-api/resources/i18n/ExternalSystemBundle.properties
platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleBeforeSyncTaskAction.java [new file with mode: 0644]
platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsState.java
platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemTaskActivator.java
platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/TaskActivationState.java
platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java
platform/platform-resources/src/idea/ExternalSystemActions.xml

index 3a93a5bdf9fc8ec26f0f30bc963836251f6d4dff..cfafb91db5603012e3e661086baf02246c0e040c 100644 (file)
@@ -64,6 +64,7 @@ tasks.recent.title=Recent tasks
 tasks.all.title=All tasks
 
 external.system.keymap.group=External Build Systems
+external.system.task.before.sync=Before Import
 external.system.task.after.sync=After Import
 external.system.task.before.compile=Before Make
 external.system.task.after.compile=After Make
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleBeforeSyncTaskAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ToggleBeforeSyncTaskAction.java
new file mode 100644 (file)
index 0000000..abddb05
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.action.task;
+
+import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 10/29/2014
+ */
+public class ToggleBeforeSyncTaskAction extends ToggleTaskActivationAction {
+  protected ToggleBeforeSyncTaskAction() {
+    super(ExternalSystemTaskActivator.Phase.BEFORE_SYNC);
+  }
+}
index 3a0532696758d256e53739f298e5a2ed82bacc0a..7821268fd60f8c47afec7d26b6603d1458c8da7b 100644 (file)
@@ -22,6 +22,7 @@ import com.intellij.util.xmlb.annotations.Property;
 import com.intellij.util.xmlb.annotations.Tag;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 /**
@@ -67,6 +68,11 @@ public class ExternalProjectsState {
         if(value == null) return null;
         return super.put(key, value);
       }
+
+      @Override
+      protected Map<String, TaskActivationState> createMap() {
+        return new LinkedHashMap<String, TaskActivationState>();
+      }
     };
 
     @Property(surroundWithTag = false)
index 053517021fca8f0d097097cb8646d02a62ef9dc6..fb635544e78905b6db007d9bef7becbe7acaa219 100644 (file)
@@ -30,12 +30,15 @@ import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunCo
 import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
 import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager.ExternalProjectsStateProvider;
 import com.intellij.openapi.externalSystem.task.TaskCallback;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
 import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
 import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
+import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
 import com.intellij.util.Function;
 import com.intellij.util.concurrency.Semaphore;
 import com.intellij.util.containers.ContainerUtil;
@@ -76,7 +79,7 @@ public class ExternalSystemTaskActivator {
 
       @Override
       public boolean execute(CompileContext context) {
-        return doExecute(myBefore, context);
+        return doExecuteCompileTasks(myBefore, context);
       }
     }
 
@@ -101,8 +104,35 @@ public class ExternalSystemTaskActivator {
     return StringUtil.join(result, ", ");
   }
 
-  private boolean doExecute(boolean before, CompileContext context) {
+  private boolean doExecuteCompileTasks(boolean myBefore, @NotNull CompileContext context) {
+    final List<String> modules = ContainerUtil.map(context.getCompileScope().getAffectedModules(), new Function<Module, String>() {
+      @Override
+      public String fun(Module module) {
+        return ExternalSystemApiUtil.getExternalProjectPath(module);
+      }
+    });
+
+    final Collection<Phase> phases = ContainerUtil.newArrayList();
+    if (myBefore) {
+      if(context.isRebuild()) {
+        phases.add(Phase.BEFORE_REBUILD);
+      }
+      phases.add(Phase.BEFORE_COMPILE);
+    }
+    else {
+      phases.add(Phase.AFTER_COMPILE);
+      if(context.isRebuild()) {
+        phases.add(Phase.AFTER_REBUILD);
+      }
+    }
+    return runTasks(modules, ArrayUtil.toObjectArray(phases, Phase.class));
+  }
+
+  public boolean runTasks(@NotNull String modulePath, @NotNull Phase... phases) {
+    return runTasks(Collections.singleton(modulePath), phases);
+  }
 
+  public boolean runTasks(@NotNull Collection<String> modules, @NotNull Phase... phases) {
     final ExternalProjectsStateProvider stateProvider = ExternalProjectsManager.getInstance(myProject).getStateProvider();
 
     final Queue<Pair<ProjectSystemId, ExternalSystemTaskExecutionSettings>> tasksQueue =
@@ -128,10 +158,14 @@ public class ExternalSystemTaskActivator {
       };
 
     for (final ExternalProjectsStateProvider.TasksActivation activation : stateProvider.getAllTasksActivation()) {
-      Set<String> tasks = ContainerUtil.newTroveSet(activation.state.getTasks(before ? Phase.BEFORE_COMPILE : Phase.AFTER_COMPILE));
-      if (context.isRebuild()) {
-        tasks = ContainerUtil.union(tasks, (before ? activation.state.beforeRebuildTask : activation.state.afterRebuildTask));
+      final boolean hashPath = modules.contains(activation.projectPath);
+
+      final Set<String> tasks = ContainerUtil.newLinkedHashSet();
+      for (Phase phase : phases) {
+        if(hashPath || phase.isSyncPhase())
+        ContainerUtil.addAll(tasks, activation.state.getTasks(phase));
       }
+
       if (tasks.isEmpty()) continue;
 
       for (Iterator<String> iterator = tasks.iterator(); iterator.hasNext(); ) {
@@ -240,6 +274,7 @@ public class ExternalSystemTaskActivator {
   }
 
   public enum Phase {
+    BEFORE_SYNC("external.system.task.before.sync"),
     AFTER_SYNC("external.system.task.after.sync"),
     BEFORE_COMPILE("external.system.task.before.compile"),
     AFTER_COMPILE("external.system.task.after.compile"),
@@ -251,6 +286,10 @@ public class ExternalSystemTaskActivator {
     Phase(String messageKey) {
       myMessageKey = messageKey;
     }
+
+    public boolean isSyncPhase () {
+      return this == BEFORE_SYNC || this == AFTER_SYNC;
+    }
   }
 
   public interface Listener {
index 2099e404e7483b5a4218c5a21bc664c9007a9e2f..2623e5087425f78ce941e2955a823e5cafde3c87 100644 (file)
@@ -19,6 +19,7 @@ import com.intellij.util.xmlb.annotations.AbstractCollection;
 import com.intellij.util.xmlb.annotations.Tag;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -28,41 +29,47 @@ import java.util.TreeSet;
 */
 @Tag("activation")
 public class TaskActivationState {
+  @Tag("before_sync")
+  @AbstractCollection(surroundWithTag = false, elementTag = "task", elementValueAttribute = "name")
+  public Set<String> beforeSyncTasks = new LinkedHashSet<String>();
+
   @Tag("after_sync")
   @AbstractCollection(surroundWithTag = false, elementTag = "task", elementValueAttribute = "name")
-  public Set<String> afterSyncTasks = new TreeSet<String>();
+  public Set<String> afterSyncTasks = new LinkedHashSet<String>();
 
   @Tag("before_compile")
   @AbstractCollection(surroundWithTag = false, elementTag = "task", elementValueAttribute = "name")
-  public Set<String> beforeCompileTasks = new TreeSet<String>();
+  public Set<String> beforeCompileTasks = new LinkedHashSet<String>();
 
   @Tag("after_compile")
   @AbstractCollection(surroundWithTag = false, elementTag = "task", elementValueAttribute = "name")
-  public Set<String> afterCompileTasks = new TreeSet<String>();
+  public Set<String> afterCompileTasks = new LinkedHashSet<String>();
 
   @Tag("after_rebuild")
   @AbstractCollection(surroundWithTag = false, elementTag = "task", elementValueAttribute = "name")
-  public Set<String> afterRebuildTask = new TreeSet<String>();
+  public Set<String> afterRebuildTask = new LinkedHashSet<String>();
 
   @Tag("before_rebuild")
   @AbstractCollection(surroundWithTag = false, elementTag = "task", elementValueAttribute = "name")
-  public Set<String> beforeRebuildTask = new TreeSet<String>();
+  public Set<String> beforeRebuildTask = new LinkedHashSet<String>();
 
   @NotNull
   public Set<String> getTasks(@NotNull ExternalSystemTaskActivator.Phase phase) {
     switch (phase) {
       case AFTER_COMPILE:
         return afterCompileTasks;
-      case AFTER_SYNC:
-        return afterSyncTasks;
       case BEFORE_COMPILE:
         return beforeCompileTasks;
+      case AFTER_SYNC:
+        return afterSyncTasks;
+      case BEFORE_SYNC:
+        return beforeSyncTasks;
       case AFTER_REBUILD:
         return afterRebuildTask;
       case BEFORE_REBUILD:
         return beforeRebuildTask;
       default:
-        throw new RuntimeException();
+        throw new IllegalArgumentException("Unknown task activation phase: " + phase);
     }
   }
 }
index 9579c9630be5365adff8b166cca951c872788506..dffc648648d27e8bc53917f9aea0dc8a58aba433 100644 (file)
@@ -54,6 +54,7 @@ import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefres
 import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
 import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
 import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
+import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator;
 import com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService;
 import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
 import com.intellij.openapi.externalSystem.service.settings.ExternalSystemConfigLocator;
@@ -482,6 +483,11 @@ public class ExternalSystemUtil {
             .clearNotifications(null, NotificationSource.PROJECT_SYNC, externalSystemId);
         }
 
+        final ExternalSystemTaskActivator externalSystemTaskActivator = ExternalProjectsManager.getInstance(project).getTaskActivator();
+        if (!isPreviewMode && !externalSystemTaskActivator.runTasks(externalProjectPath, ExternalSystemTaskActivator.Phase.BEFORE_SYNC)) {
+          return;
+        }
+
         myTask.execute(indicator, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
         if(project.isDisposed()) return;
 
@@ -511,6 +517,10 @@ public class ExternalSystemUtil {
           }
 
           callback.onSuccess(externalProject);
+
+          if(!isPreviewMode) {
+            externalSystemTaskActivator.runTasks(externalProjectPath, ExternalSystemTaskActivator.Phase.AFTER_SYNC);
+          }
           return;
         }
         if(error instanceof ImportCanceledException) {
index b99b75929dc59713cfdb4f1175ae63172f67d7eb..bfe5909b96267409886ec350aa7ff7a3194fd6c6 100644 (file)
             description="Assign shortcut to the selected Run Configuration">
     </action>
 
+    <action id="ExternalSystem.BeforeSync"
+            class="com.intellij.openapi.externalSystem.action.task.ToggleBeforeSyncTaskAction" text="Execute Before Sync"
+            description="Execute selected task before the project import">
+    </action>
+    <action id="ExternalSystem.AfterSync"
+            class="com.intellij.openapi.externalSystem.action.task.ToggleAfterSyncTaskAction" text="Execute After Sync"
+            description="Execute selected task after the project import">
+    </action>
     <action id="ExternalSystem.BeforeCompile"
             class="com.intellij.openapi.externalSystem.action.task.ToggleBeforeCompileTasksAction" text="Execute Before Make"
             description="Execute selected task before Make">
     <group id="ExternalSystemView.ActionsToolbar.RightPanel">
     </group>
 
+    <group id="ExternalSystemView.TaskActivationGroup">
+      <reference id="ExternalSystem.BeforeSync"/>
+      <reference id="ExternalSystem.AfterSync"/>
+      <reference id="ExternalSystem.BeforeCompile"/>
+      <reference id="ExternalSystem.AfterCompile"/>
+      <reference id="ExternalSystem.BeforeRebuild"/>
+      <reference id="ExternalSystem.AfterRebuild"/>
+      <!--<reference id="ExternalSystem.BeforeRun"/>-->
+    </group>
+
     <group id="ExternalSystemView.ActionsToolbar">
       <reference ref="ExternalSystemView.ActionsToolbar.LeftPanel"/>
       <separator/>
       <separator/>
       <reference id="EditSource"/>
       <separator/>
-      <reference id="ExternalSystem.BeforeCompile"/>
-      <reference id="ExternalSystem.AfterCompile"/>
-      <reference id="ExternalSystem.BeforeRebuild"/>
-      <reference id="ExternalSystem.AfterRebuild"/>
-      <!--<reference id="ExternalSystem.BeforeRun"/>-->
+      <reference ref="ExternalSystemView.TaskActivationGroup"/>
       <separator/>
       <reference id="ExternalSystem.AssignShortcut"/>
     </group>
               text="Remove Run Configuration" icon="AllIcons.General.Remove"
               class="com.intellij.openapi.externalSystem.action.RemoveExternalSystemRunConfigurationAction" />
       <separator/>
-      <reference id="ExternalSystem.BeforeCompile"/>
-      <reference id="ExternalSystem.AfterCompile"/>
-      <reference id="ExternalSystem.BeforeRebuild"/>
-      <reference id="ExternalSystem.AfterRebuild"/>
-      <!--<reference id="ExternalSystem.BeforeRun"/>-->
+      <reference ref="ExternalSystemView.TaskActivationGroup"/>
       <separator/>
       <reference id="ExternalSystem.AssignRunConfigurationShortcut"/>
     </group>