diff --git a/python/educational-core/course-creator/resources/META-INF/plugin.xml b/python/educational-core/course-creator/resources/META-INF/plugin.xml
index 37c7704f87e1..2491e1cde81c 100644
--- a/python/educational-core/course-creator/resources/META-INF/plugin.xml
+++ b/python/educational-core/course-creator/resources/META-INF/plugin.xml
@@ -33,6 +33,7 @@
+
diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCSubtaskChangeListener.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCSubtaskChangeListener.java
new file mode 100644
index 000000000000..5b9370453bab
--- /dev/null
+++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCSubtaskChangeListener.java
@@ -0,0 +1,56 @@
+package com.jetbrains.edu.coursecreator;
+
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import com.jetbrains.edu.learning.StudyLanguageManager;
+import com.jetbrains.edu.learning.StudySubtaskChangeListener;
+import com.jetbrains.edu.learning.StudyTaskManager;
+import com.jetbrains.edu.learning.StudyUtils;
+import com.jetbrains.edu.learning.core.EduNames;
+import com.jetbrains.edu.learning.courseFormat.Course;
+import com.jetbrains.edu.learning.courseFormat.Task;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class CCSubtaskChangeListener implements StudySubtaskChangeListener {
+ @Override
+ public void subtaskChanged(@NotNull Project project, @NotNull Task task, int oldSubtaskNumber, int newSubtaskNumber) {
+ VirtualFile taskDir = task.getTaskDir(project);
+ if (taskDir == null) {
+ return;
+ }
+ Course course = StudyTaskManager.getInstance(project).getCourse();
+ if (course == null) {
+ return;
+ }
+ StudyLanguageManager manager = StudyUtils.getLanguageManager(course);
+ if (manager == null) {
+ return;
+ }
+ String testFileName = manager.getTestFileName();
+ if (newSubtaskNumber != 0) {
+ String nameWithoutExtension = FileUtil.getNameWithoutExtension(testFileName);
+ String extension = FileUtilRt.getExtension(testFileName);
+ testFileName = nameWithoutExtension + EduNames.SUBTASK_MARKER + newSubtaskNumber + "." + extension;
+ }
+ VirtualFile newTestFile = taskDir.findChild(testFileName);
+ if (newTestFile == null) {
+ return;
+ }
+ FileEditorManager editorManager = FileEditorManager.getInstance(project);
+ List testFiles =
+ ContainerUtil.filter(taskDir.getChildren(), file -> CCUtils.isTestsFile(project, file) && editorManager.isFileOpen(file));
+ if (testFiles.isEmpty()) {
+ return;
+ }
+ for (VirtualFile testFile : testFiles) {
+ editorManager.closeFile(testFile);
+ }
+ editorManager.openFile(newTestFile, false);
+ }
+}
diff --git a/python/educational-core/student/resources/META-INF/plugin.xml b/python/educational-core/student/resources/META-INF/plugin.xml
index 3058bd39f937..f8de6c5cf790 100644
--- a/python/educational-core/student/resources/META-INF/plugin.xml
+++ b/python/educational-core/student/resources/META-INF/plugin.xml
@@ -45,7 +45,8 @@
- >
+
+
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskChangeListener.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskChangeListener.java
new file mode 100644
index 000000000000..8ea064faa128
--- /dev/null
+++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskChangeListener.java
@@ -0,0 +1,12 @@
+package com.jetbrains.edu.learning;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.edu.learning.courseFormat.Task;
+import org.jetbrains.annotations.NotNull;
+
+public interface StudySubtaskChangeListener {
+ ExtensionPointName EP_NAME = ExtensionPointName.create("Edu.studySubtaskChangeListener");
+
+ void subtaskChanged(@NotNull Project project, @NotNull Task task, int oldSubtaskNumber, int newSubtaskNumber);
+}
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskUtils.java
index 2f2c2c211192..f595eaaa7183 100644
--- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskUtils.java
+++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudySubtaskUtils.java
@@ -5,6 +5,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
@@ -65,6 +66,10 @@ public class StudySubtaskUtils {
transformTestFile(project, toSubtaskIndex, taskDir);
task.setActiveSubtaskIndex(toSubtaskIndex);
updateUI(project, task, taskDir);
+
+ for (StudySubtaskChangeListener listener : Extensions.getExtensions(StudySubtaskChangeListener.EP_NAME)) {
+ listener.subtaskChanged(project, task, fromSubtaskIndex, toSubtaskIndex);
+ }
}
private static void transformTestFile(@NotNull Project project, int toSubtaskIndex, VirtualFile taskDir) {