refactored checker
authorliana.bakradze <liana.bakradze@jetbrains.com>
Tue, 9 Feb 2016 11:06:14 +0000 (14:06 +0300)
committerliana.bakradze <liana.bakradze@jetbrains.com>
Tue, 9 Feb 2016 11:06:14 +0000 (14:06 +0300)
12 files changed:
python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java
python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java [new file with mode: 0644]
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java [new file with mode: 0644]
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyExecutor.java [moved from python/educational-core/student/src/com/jetbrains/edu/learning/run/StudyExecutor.java with 97% similarity]
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java [moved from python/educational-core/student/src/com/jetbrains/edu/learning/run/StudySmartChecker.java with 90% similarity]
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java [new file with mode: 0644]
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyTestsOutputParser.java [moved from python/educational-core/student/src/com/jetbrains/edu/learning/run/StudyTestRunner.java with 63% similarity]
python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java [new file with mode: 0644]
python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyExecutor.java
python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java
python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyToolWindowConfigurator.java

index 24c8b751c85e770c6538676484b530889105bd46..a97e979f06f651b9e4c630a4da75936ba70b4137 100644 (file)
@@ -39,8 +39,8 @@ import com.jetbrains.edu.EduNames;
 import com.jetbrains.edu.EduUtils;
 import com.jetbrains.edu.courseFormat.*;
 import com.jetbrains.edu.learning.editor.StudyEditor;
-import com.jetbrains.edu.learning.run.StudyExecutor;
-import com.jetbrains.edu.learning.run.StudyTestRunner;
+import com.jetbrains.edu.learning.checker.StudyExecutor;
+import com.jetbrains.edu.learning.checker.StudyTestRunner;
 import com.jetbrains.edu.learning.ui.StudyProgressToolWindowFactory;
 import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
 import org.jetbrains.annotations.NotNull;
index 3a7486a4d859fa963d434d3aa3a5a486624df465..5fb40889376dcef922821083e7401805799cbd4c 100644 (file)
 package com.jetbrains.edu.learning.actions;
 
-import com.intellij.execution.ExecutionException;
-import com.intellij.execution.process.CapturingProcessHandler;
-import com.intellij.execution.process.ProcessOutput;
-import com.intellij.ide.projectView.ProjectView;
-import com.intellij.openapi.actionSystem.ActionManager;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.KeyboardShortcut;
 import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.FileEditor;
-import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.keymap.KeymapUtil;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.TaskInfo;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.BalloonBuilder;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.wm.IdeFocusManager;
-import com.intellij.openapi.wm.IdeFrame;
-import com.intellij.openapi.wm.WindowManager;
-import com.intellij.openapi.wm.ex.StatusBarEx;
-import com.intellij.openapi.wm.ex.WindowManagerEx;
-import com.jetbrains.edu.EduDocumentListener;
-import com.jetbrains.edu.EduUtils;
-import com.jetbrains.edu.courseFormat.AnswerPlaceholder;
-import com.jetbrains.edu.courseFormat.StudyStatus;
-import com.jetbrains.edu.courseFormat.Task;
-import com.jetbrains.edu.courseFormat.TaskFile;
-import com.jetbrains.edu.learning.StudyState;
-import com.jetbrains.edu.learning.StudyTaskManager;
+import com.intellij.openapi.util.Ref;
 import com.jetbrains.edu.learning.StudyUtils;
-import com.jetbrains.edu.learning.editor.StudyEditor;
-import com.jetbrains.edu.learning.navigation.StudyNavigator;
-import com.jetbrains.edu.learning.run.StudySmartChecker;
-import com.jetbrains.edu.learning.run.StudyTestRunner;
-import com.jetbrains.edu.stepic.EduStepicConnector;
-import com.jetbrains.edu.stepic.StudySettings;
+import com.jetbrains.edu.learning.checker.StudyCheckUtils;
 import icons.InteractiveLearningIcons;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.awt.*;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
+
 
 public class StudyCheckAction extends DumbAwareAction {
 
-  private static final Logger LOG = Logger.getInstance(StudyCheckAction.class.getName());
-  private static final String ANSWERS_POSTFIX = "_answers";
   public static final String ACTION_ID = "CheckAction";
   public static final String SHORTCUT = "ctrl alt pressed ENTER";
 
-  boolean checkInProgress = false;
+  protected Ref<Boolean> myCheckInProgress = new Ref<>(false);
 
   public StudyCheckAction() {
     super("Check Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Check current task", InteractiveLearningIcons.Resolve);
   }
 
-  private static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
-    for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
-      String name = entry.getKey();
-      TaskFile taskFile = entry.getValue();
-      VirtualFile virtualFile = taskDir.findChild(name);
-      if (virtualFile == null) {
-        continue;
-      }
-      EduUtils.flushWindows(taskFile, virtualFile, true);
-    }
-  }
-
-  private static void drawAllPlaceholders(@NotNull final Project project, @NotNull final Task task, @NotNull final VirtualFile taskDir) {
-    for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
-      String name = entry.getKey();
-      TaskFile taskFile = entry.getValue();
-      VirtualFile virtualFile = taskDir.findChild(name);
-      if (virtualFile == null) {
-        continue;
-      }
-      FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
-      if (fileEditor instanceof StudyEditor) {
-        StudyEditor studyEditor = (StudyEditor)fileEditor;
-        StudyUtils.drawAllWindows(studyEditor.getEditor(), taskFile);
-      }
-    }
-  }
-
-
-  protected void check(@NotNull final Project project) {
-    if (DumbService.isDumb(project)) {
-      DumbService.getInstance(project).showDumbModeNotification("Check Action is not available while indexing is in progress");
-      return;
-    }
-    ApplicationManager.getApplication().runWriteAction(new Runnable() {
-      @Override
-      public void run() {
-        CommandProcessor.getInstance().runUndoTransparentAction(() -> {
-          final StudyEditor selectedEditor = StudyUtils.getSelectedStudyEditor(project);
-          if (selectedEditor == null) return;
-          final StudyState studyState = new StudyState(selectedEditor);
-          if (!studyState.isValid()) {
-            LOG.error("StudyCheckAction was invoked outside study editor");
-            return;
-          }
-          final IdeFrame frame = ((WindowManagerEx)WindowManager.getInstance()).findFrameFor(project);
-          final StatusBarEx statusBar = frame == null ? null : (StatusBarEx)frame.getStatusBar();
-          if (statusBar != null) {
-            final List<Pair<TaskInfo, ProgressIndicator>> processes = statusBar.getBackgroundProcesses();
-            if (!processes.isEmpty()) return;
-          }
-
-          final Task task = studyState.getTask();
-          final VirtualFile taskDir = studyState.getTaskDir();
-          flushWindows(task, taskDir);
-          final StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
-          if (runAction == null) {
-            return;
-          }
-          runAction.run(project);
-          ApplicationManager.getApplication().invokeLater(
-            () -> IdeFocusManager.getInstance(project).requestFocus(studyState.getEditor().getComponent(), true));
-
-          final StudyTestRunner testRunner = StudyUtils.getTestRunner(task, taskDir);
-          Process testProcess = null;
-          String commandLine = "";
-          try {
-            final VirtualFile executablePath = getTaskVirtualFile(studyState, task, taskDir);
-            if (executablePath != null) {
-              commandLine = executablePath.getPath();
-              testProcess = testRunner.createCheckProcess(project, commandLine);
-            }
-          }
-          catch (ExecutionException e) {
-            LOG.error(e);
-          }
-          if (testProcess == null) {
-            return;
-          }
-          checkInProgress = true;
-          ProgressManager.getInstance().run(getCheckTask(studyState, testRunner, testProcess, commandLine, project, selectedEditor));
-        });
-      }
-
-      @Nullable
-      private VirtualFile getTaskVirtualFile(@NotNull final StudyState studyState,
-                                             @NotNull final Task task,
-                                             @NotNull final VirtualFile taskDir) {
-        VirtualFile taskVirtualFile = studyState.getVirtualFile();
-        for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
-          String name = entry.getKey();
-          TaskFile taskFile = entry.getValue();
-          VirtualFile virtualFile = taskDir.findChild(name);
-          if (virtualFile != null) {
-            if (!taskFile.getAnswerPlaceholders().isEmpty()) {
-              taskVirtualFile = virtualFile;
-            }
-          }
-        }
-        return taskVirtualFile;
-      }
-    });
-  }
-
-  @NotNull
-  protected com.intellij.openapi.progress.Task.Backgroundable getCheckTask(final StudyState studyState,
-                                                                         final StudyTestRunner testRunner,
-                                                                         final Process testProcess,
-                                                                         @NotNull final String commandLine, @NotNull final Project project,
-                                                                         final StudyEditor selectedEditor) {
-    final Task task = studyState.getTask();
-    final VirtualFile taskDir = studyState.getTaskDir();
-
-    final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
-    final StudyStatus statusBeforeCheck = taskManager.getStatus(task);
-    return new com.intellij.openapi.progress.Task.Backgroundable(project, "Checking Task", true) {
-      @Override
-      public void onSuccess() {
-        StudyUtils.updateToolWindows(project);
-        drawAllPlaceholders(project, task, taskDir);
-        ProjectView.getInstance(project).refresh();
-        EduUtils.deleteWindowDescriptions(task, taskDir);
-        checkInProgress = false;
-      }
-
-      @Override
-      public void onCancel() {
-        taskManager.setStatus(task, statusBeforeCheck);
-        EduUtils.deleteWindowDescriptions(task, taskDir);
-        checkInProgress = false;
-      }
-
-      @Override
-      public void run(@NotNull ProgressIndicator indicator) {
-        final Map<String, TaskFile> taskFiles = task.getTaskFiles();
-        final CapturingProcessHandler handler = new CapturingProcessHandler(testProcess, null, commandLine);
-        final ProcessOutput output = handler.runProcessWithProgressIndicator(indicator);
-        if (indicator.isCanceled()) {
-          ApplicationManager.getApplication().invokeLater(
-            () -> showTestResultPopUp("Tests check cancelled.", MessageType.WARNING.getPopupBackground(), project));
-          return;
-        }
-        final StudyTestRunner.TestsOutput testsOutput = testRunner.getTestsOutput(output);
-        String stderr = output.getStderr();
-        if (!stderr.isEmpty()) {
-          LOG.info("#educational " + stderr);
-        }
-        final StudySettings studySettings = StudySettings.getInstance();
-
-        final String login = studySettings.getLogin();
-        final String password = StringUtil.isEmptyOrSpaces(login) ? "" : studySettings.getPassword();
-        if (testsOutput.isSuccess()) {
-          taskManager.setStatus(task, StudyStatus.Solved);
-          EduStepicConnector.postAttempt(task, true, login, password);
-          ApplicationManager.getApplication().invokeLater(
-            () -> showTestResultPopUp(testsOutput.getMessage(), MessageType.INFO.getPopupBackground(), project));
-        }
-        else {
-          ApplicationManager.getApplication().invokeLater(() -> {
-            if (taskDir == null) return;
-            EduStepicConnector.postAttempt(task, false, login, password);
-            taskManager.setStatus(task, StudyStatus.Failed);
-            for (Map.Entry<String, TaskFile> entry : taskFiles.entrySet()) {
-              final String name = entry.getKey();
-              final TaskFile taskFile = entry.getValue();
-              if (taskFile.getAnswerPlaceholders().size() < 2) {
-                taskManager.setStatus(taskFile, StudyStatus.Failed);
-                continue;
-              }
-              CommandProcessor.getInstance().runUndoTransparentAction(() -> ApplicationManager.getApplication().runWriteAction(() -> {
-                runSmartTestProcess(taskDir, testRunner, name, taskFile, project);
-              }));
-            }
-            showTestResultPopUp(testsOutput.getMessage(), MessageType.ERROR.getPopupBackground(), project);
-            navigateToFailedPlaceholder(studyState, task, taskDir, project);
-          });
-        }
-      }
-    };
-  }
-
-  private static void navigateToFailedPlaceholder(@NotNull final StudyState studyState,
-                                                  @NotNull final Task task,
-                                                  @NotNull final VirtualFile taskDir,
-                                                  @NotNull final Project project) {
-    TaskFile selectedTaskFile = studyState.getTaskFile();
-    Editor editor = studyState.getEditor();
-    TaskFile taskFileToNavigate = selectedTaskFile;
-    VirtualFile fileToNavigate = studyState.getVirtualFile();
-    final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
-    if (!taskManager.hasFailedAnswerPlaceholders(selectedTaskFile)) {
-      for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
-        String name = entry.getKey();
-        TaskFile taskFile = entry.getValue();
-        if (taskManager.hasFailedAnswerPlaceholders(taskFile)) {
-          taskFileToNavigate = taskFile;
-          VirtualFile virtualFile = taskDir.findChild(name);
-          if (virtualFile == null) {
-            continue;
-          }
-          FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
-          if (fileEditor instanceof StudyEditor) {
-            StudyEditor studyEditor = (StudyEditor)fileEditor;
-            editor = studyEditor.getEditor();
-          }
-          fileToNavigate = virtualFile;
-          break;
-        }
-      }
-    }
-    if (fileToNavigate != null) {
-      FileEditorManager.getInstance(project).openFile(fileToNavigate, true);
-    }
-    final Editor editorToNavigate = editor;
-    ApplicationManager.getApplication().invokeLater(
-      () -> IdeFocusManager.getInstance(project).requestFocus(editorToNavigate.getContentComponent(), true));
-
-    StudyNavigator.navigateToFirstFailedAnswerPlaceholder(editor, taskFileToNavigate);
-  }
-
-  protected void runSmartTestProcess(@NotNull final VirtualFile taskDir,
-                                   @NotNull final StudyTestRunner testRunner,
-                                   final String taskFileName,
-                                   @NotNull final TaskFile taskFile,
-                                   @NotNull final Project project) {
-    final TaskFile answerTaskFile = new TaskFile();
-    answerTaskFile.name = taskFileName;
-    final VirtualFile virtualFile = taskDir.findChild(taskFileName);
-    if (virtualFile == null) {
-      return;
-    }
-    final VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
-    for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getAnswerPlaceholders()) {
-      final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
-      if (document == null) {
-        continue;
-      }
-      if (!answerPlaceholder.isValid(document)) {
-        continue;
-      }
-      StudySmartChecker.smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner,
-                                   virtualFile, document);
-    }
-    StudyUtils.deleteFile(answerFile);
-  }
-
-  private VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
-                                         @NotNull final VirtualFile file,
-                                         @NotNull final TaskFile source,
-                                         @NotNull final TaskFile target) {
-    VirtualFile copy = null;
-    try {
-
-      copy = file.copy(this, taskDir, file.getNameWithoutExtension() + ANSWERS_POSTFIX + "." + file.getExtension());
-      final FileDocumentManager documentManager = FileDocumentManager.getInstance();
-      final Document document = documentManager.getDocument(copy);
-      if (document != null) {
-        TaskFile.copy(source, target);
-        EduDocumentListener listener = new EduDocumentListener(target);
-        document.addDocumentListener(listener);
-        for (AnswerPlaceholder answerPlaceholder : target.getAnswerPlaceholders()) {
-          if (!answerPlaceholder.isValid(document)) {
-            continue;
-          }
-          final int start = answerPlaceholder.getRealStartOffset(document);
-          final int end = start + answerPlaceholder.getLength();
-          final String text = answerPlaceholder.getPossibleAnswer();
-          document.replaceString(start, end, text);
-        }
-        ApplicationManager.getApplication().runWriteAction(() -> {
-          documentManager.saveDocument(document);
-        });
-      }
-    }
-    catch (IOException e) {
-      LOG.error(e);
-    }
-    return copy;
-  }
-
-  protected static void showTestResultPopUp(final String text, Color color, @NotNull final Project project) {
-    BalloonBuilder balloonBuilder =
-      JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
-    final Balloon balloon = balloonBuilder.createBalloon();
-    StudyUtils.showCheckPopUp(project, balloon);
-  }
+  protected void check(@NotNull final Project project) {}
 
   @Override
   public void actionPerformed(@NotNull AnActionEvent e) {
     Project project = e.getProject();
-    if (project != null) {
-      check(project);
+    if (project == null) {
+      return;
+    }
+    if (DumbService.isDumb(project)) {
+      StudyCheckUtils.showTestResultPopUp("Checking is not available while indexing is in progress", MessageType.WARNING.getPopupBackground(), project);
+      return;
     }
+    check(project);
   }
 
   @Override
@@ -373,7 +48,7 @@ public class StudyCheckAction extends DumbAwareAction {
     final Presentation presentation = e.getPresentation();
     StudyUtils.updateAction(e);
     if (presentation.isEnabled()) {
-      presentation.setEnabled(!checkInProgress);
+      presentation.setEnabled(!myCheckInProgress.get());
     }
   }
 }
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java
new file mode 100644 (file)
index 0000000..633189f
--- /dev/null
@@ -0,0 +1,121 @@
+package com.jetbrains.edu.learning.checker;
+
+import com.intellij.execution.process.CapturingProcessHandler;
+import com.intellij.execution.process.ProcessOutput;
+import com.intellij.ide.projectView.ProjectView;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.edu.EduUtils;
+import com.jetbrains.edu.courseFormat.StudyStatus;
+import com.jetbrains.edu.courseFormat.Task;
+import com.jetbrains.edu.learning.StudyState;
+import com.jetbrains.edu.learning.StudyTaskManager;
+import com.jetbrains.edu.learning.StudyUtils;
+import com.jetbrains.edu.stepic.EduStepicConnector;
+import com.jetbrains.edu.stepic.StudySettings;
+import org.jetbrains.annotations.NotNull;
+
+public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroundable {
+
+  private static final Logger LOG = Logger.getInstance(StudyCheckTask.class);
+  private final Project myProject;
+  protected final StudyState myStudyState;
+  protected final Task myTask;
+  protected final VirtualFile myTaskDir;
+  protected final StudyTaskManager myTaskManger;
+  private final StudyStatus myStatusBeforeCheck;
+  private Ref<Boolean> myCheckInProcess;
+  private final Process myTestProcess;
+  private final String myCommandLine;
+
+  public StudyCheckTask(Project project, StudyState studyState, Ref<Boolean> checkInProcess, Process testProcess, String commandLine) {
+    super(project, "Checking Task");
+    myProject = project;
+    myStudyState = studyState;
+    myCheckInProcess = checkInProcess;
+    myTestProcess = testProcess;
+    myCommandLine = commandLine;
+    myTask = studyState.getTask();
+    myTaskDir = studyState.getTaskDir();
+    myTaskManger = StudyTaskManager.getInstance(myProject);
+    myStatusBeforeCheck = myTaskManger.getStatus(myTask);
+  }
+
+  @Override
+  public void onSuccess() {
+    StudyUtils.updateToolWindows(myProject);
+    StudyCheckUtils.drawAllPlaceholders(myProject, myTask, myTaskDir);
+    ProjectView.getInstance(myProject).refresh();
+    clearState();
+  }
+
+  protected void clearState() {
+    EduUtils.deleteWindowDescriptions(myTask, myTaskDir);
+    myCheckInProcess.set(false);
+  }
+
+  @Override
+  public void onCancel() {
+    myTaskManger.setStatus(myTask, myStatusBeforeCheck);
+    clearState();
+  }
+
+  @Override
+  public void run(@NotNull ProgressIndicator indicator) {
+    final CapturingProcessHandler handler = new CapturingProcessHandler(myTestProcess, null, myCommandLine);
+    final ProcessOutput output = handler.runProcessWithProgressIndicator(indicator);
+    if (indicator.isCanceled()) {
+      ApplicationManager.getApplication().invokeLater(
+        () -> StudyCheckUtils.showTestResultPopUp("Check cancelled", MessageType.WARNING.getPopupBackground(), myProject));
+      return;
+    }
+
+
+    final StudyTestsOutputParser.TestsOutput testsOutput = StudyTestsOutputParser.getTestsOutput(output);
+    String stderr = output.getStderr();
+    if (!stderr.isEmpty()) {
+      ApplicationManager.getApplication().invokeLater(() ->
+                                                        StudyCheckUtils.showTestResultPopUp("Failed to launch checking",
+                                                                                            MessageType.WARNING.getPopupBackground(),
+                                                                                            myProject));
+      //log error output of tests
+      LOG.info("#educational " + stderr);
+      return;
+    }
+
+    postAttemptToStepic(testsOutput);
+
+
+    if (testsOutput.isSuccess()) {
+      onTaskSolved(testsOutput);
+    }
+    else {
+      onTaskFailed(testsOutput);
+    }
+  }
+
+  protected void onTaskFailed(StudyTestsOutputParser.TestsOutput testsOutput) {
+    myTaskManger.setStatus(myTask, StudyStatus.Failed);
+    ApplicationManager.getApplication().invokeLater(
+      () -> StudyCheckUtils.showTestResultPopUp(testsOutput.getMessage(), MessageType.ERROR.getPopupBackground(), myProject));
+  }
+
+  protected void onTaskSolved(StudyTestsOutputParser.TestsOutput testsOutput) {
+    myTaskManger.setStatus(myTask, StudyStatus.Solved);
+    ApplicationManager.getApplication().invokeLater(
+      () -> StudyCheckUtils.showTestResultPopUp(testsOutput.getMessage(), MessageType.INFO.getPopupBackground(), myProject));
+  }
+
+  protected void postAttemptToStepic(StudyTestsOutputParser.TestsOutput testsOutput) {
+    final StudySettings studySettings = StudySettings.getInstance();
+    final String login = studySettings.getLogin();
+    final String password = StringUtil.isEmptyOrSpaces(login) ? "" : studySettings.getPassword();
+    EduStepicConnector.postAttempt(myTask, testsOutput.isSuccess(), login, password);
+  }
+}
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java
new file mode 100644 (file)
index 0000000..ac6332a
--- /dev/null
@@ -0,0 +1,196 @@
+package com.jetbrains.edu.learning.checker;
+
+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.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.TaskInfo;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.BalloonBuilder;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.openapi.wm.IdeFrame;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.openapi.wm.ex.StatusBarEx;
+import com.intellij.openapi.wm.ex.WindowManagerEx;
+import com.jetbrains.edu.EduDocumentListener;
+import com.jetbrains.edu.EduUtils;
+import com.jetbrains.edu.courseFormat.AnswerPlaceholder;
+import com.jetbrains.edu.courseFormat.Task;
+import com.jetbrains.edu.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.StudyState;
+import com.jetbrains.edu.learning.StudyTaskManager;
+import com.jetbrains.edu.learning.StudyUtils;
+import com.jetbrains.edu.learning.editor.StudyEditor;
+import com.jetbrains.edu.learning.navigation.StudyNavigator;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class StudyCheckUtils {
+  private static final String ANSWERS_POSTFIX = "_answers";
+  private static final Logger LOG = Logger.getInstance(StudyCheckUtils.class);
+
+  private StudyCheckUtils() {
+  }
+
+  public static void drawAllPlaceholders(@NotNull final Project project, @NotNull final Task task, @NotNull final VirtualFile taskDir) {
+    for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
+      String name = entry.getKey();
+      TaskFile taskFile = entry.getValue();
+      VirtualFile virtualFile = taskDir.findChild(name);
+      if (virtualFile == null) {
+        continue;
+      }
+      FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
+      if (fileEditor instanceof StudyEditor) {
+        StudyEditor studyEditor = (StudyEditor)fileEditor;
+        StudyUtils.drawAllWindows(studyEditor.getEditor(), taskFile);
+      }
+    }
+  }
+
+  public static void navigateToFailedPlaceholder(@NotNull final StudyState studyState,
+                                                  @NotNull final Task task,
+                                                  @NotNull final VirtualFile taskDir,
+                                                  @NotNull final Project project) {
+    TaskFile selectedTaskFile = studyState.getTaskFile();
+    Editor editor = studyState.getEditor();
+    TaskFile taskFileToNavigate = selectedTaskFile;
+    VirtualFile fileToNavigate = studyState.getVirtualFile();
+    final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+    if (!taskManager.hasFailedAnswerPlaceholders(selectedTaskFile)) {
+      for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
+        String name = entry.getKey();
+        TaskFile taskFile = entry.getValue();
+        if (taskManager.hasFailedAnswerPlaceholders(taskFile)) {
+          taskFileToNavigate = taskFile;
+          VirtualFile virtualFile = taskDir.findChild(name);
+          if (virtualFile == null) {
+            continue;
+          }
+          FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
+          if (fileEditor instanceof StudyEditor) {
+            StudyEditor studyEditor = (StudyEditor)fileEditor;
+            editor = studyEditor.getEditor();
+          }
+          fileToNavigate = virtualFile;
+          break;
+        }
+      }
+    }
+    if (fileToNavigate != null) {
+      FileEditorManager.getInstance(project).openFile(fileToNavigate, true);
+    }
+    final Editor editorToNavigate = editor;
+    ApplicationManager.getApplication().invokeLater(
+      () -> IdeFocusManager.getInstance(project).requestFocus(editorToNavigate.getContentComponent(), true));
+
+    StudyNavigator.navigateToFirstFailedAnswerPlaceholder(editor, taskFileToNavigate);
+  }
+
+
+  public static void showTestResultPopUp(final String text, Color color, @NotNull final Project project) {
+    BalloonBuilder balloonBuilder =
+      JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
+    final Balloon balloon = balloonBuilder.createBalloon();
+    StudyUtils.showCheckPopUp(project, balloon);
+  }
+
+
+  public static void runSmartTestProcess(@NotNull final VirtualFile taskDir,
+                                     @NotNull final StudyTestRunner testRunner,
+                                     final String taskFileName,
+                                     @NotNull final TaskFile taskFile,
+                                     @NotNull final Project project) {
+    final TaskFile answerTaskFile = new TaskFile();
+    answerTaskFile.name = taskFileName;
+    final VirtualFile virtualFile = taskDir.findChild(taskFileName);
+    if (virtualFile == null) {
+      return;
+    }
+    final VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
+    for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getAnswerPlaceholders()) {
+      final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+      if (document == null) {
+        continue;
+      }
+      if (!answerPlaceholder.isValid(document)) {
+        continue;
+      }
+      StudySmartChecker.smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner,
+                                   virtualFile, document);
+    }
+    StudyUtils.deleteFile(answerFile);
+  }
+
+
+
+  private static VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
+                                         @NotNull final VirtualFile file,
+                                         @NotNull final TaskFile source,
+                                         @NotNull final TaskFile target) {
+    VirtualFile copy = null;
+    try {
+
+      copy = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + ANSWERS_POSTFIX + "." + file.getExtension());
+      final FileDocumentManager documentManager = FileDocumentManager.getInstance();
+      final Document document = documentManager.getDocument(copy);
+      if (document != null) {
+        TaskFile.copy(source, target);
+        EduDocumentListener listener = new EduDocumentListener(target);
+        document.addDocumentListener(listener);
+        for (AnswerPlaceholder answerPlaceholder : target.getAnswerPlaceholders()) {
+          if (!answerPlaceholder.isValid(document)) {
+            continue;
+          }
+          final int start = answerPlaceholder.getRealStartOffset(document);
+          final int end = start + answerPlaceholder.getLength();
+          final String text = answerPlaceholder.getPossibleAnswer();
+          document.replaceString(start, end, text);
+        }
+        ApplicationManager.getApplication().runWriteAction(() -> {
+          documentManager.saveDocument(document);
+        });
+      }
+    }
+    catch (IOException e) {
+      LOG.error(e);
+    }
+    return copy;
+  }
+
+
+  public static boolean hasBackgroundProcesses(@NotNull Project project) {
+    final IdeFrame frame = ((WindowManagerEx)WindowManager.getInstance()).findFrameFor(project);
+    final StatusBarEx statusBar = frame == null ? null : (StatusBarEx)frame.getStatusBar();
+    if (statusBar != null) {
+      final List<Pair<TaskInfo, ProgressIndicator>> processes = statusBar.getBackgroundProcesses();
+      if (!processes.isEmpty()) return true;
+    }
+    return false;
+  }
+
+
+  public static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
+    for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
+      String name = entry.getKey();
+      TaskFile taskFile = entry.getValue();
+      VirtualFile virtualFile = taskDir.findChild(name);
+      if (virtualFile == null) {
+        continue;
+      }
+      EduUtils.flushWindows(taskFile, virtualFile, true);
+    }
+  }
+}
similarity index 97%
rename from python/educational-core/student/src/com/jetbrains/edu/learning/run/StudyExecutor.java
rename to python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyExecutor.java
index 5023281082572e8f5d8afa25cd886a0ec4908996..69073cfc97dcd395bcf96b14ef2e4c050c65fd62 100644 (file)
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.jetbrains.edu.learning.run;
+package com.jetbrains.edu.learning.checker;
 
 import com.intellij.execution.RunContentExecutor;
 import com.intellij.execution.configurations.GeneralCommandLine;
similarity index 90%
rename from python/educational-core/student/src/com/jetbrains/edu/learning/run/StudySmartChecker.java
rename to python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java
index d3a1b52f9df0a9a3df592a71e20305fa9173cd02..9a48eba57d58b41299fc08f38c01570d2ea67b7a 100644 (file)
@@ -1,4 +1,4 @@
-package com.jetbrains.edu.learning.run;
+package com.jetbrains.edu.learning.checker;
 
 import com.intellij.execution.ExecutionException;
 import com.intellij.execution.process.CapturingProcessHandler;
@@ -60,17 +60,14 @@ public class StudySmartChecker {
         int userEnd = userStart + userAnswerPlaceholder.getLength();
         String text = usersDocument.getText(new TextRange(userStart, userEnd));
         windowDocument.replaceString(start, end, text);
-        ApplicationManager.getApplication().runWriteAction(new Runnable() {
-          @Override
-          public void run() {
-            documentManager.saveDocument(windowDocument);
-          }
+        ApplicationManager.getApplication().runWriteAction(() -> {
+          documentManager.saveDocument(windowDocument);
         });
         VirtualFile fileWindows = EduUtils.flushWindows(windowTaskFile, windowCopy, true);
         Process smartTestProcess = testRunner.createCheckProcess(project, windowCopy.getPath());
         final CapturingProcessHandler handler = new CapturingProcessHandler(smartTestProcess, null, windowCopy.getPath());
         final ProcessOutput output = handler.runProcess();
-        boolean res = testRunner.getTestsOutput(output).isSuccess();
+        boolean res = StudyTestsOutputParser.getTestsOutput(output).isSuccess();
         StudyTaskManager.getInstance(project).setStatus(userAnswerPlaceholder, res ? StudyStatus.Solved : StudyStatus.Failed);
         StudyUtils.deleteFile(windowCopy);
         if (fileWindows != null) {
@@ -81,10 +78,7 @@ public class StudySmartChecker {
         }
       }
     }
-    catch (ExecutionException e) {
-      LOG.error(e);
-    }
-    catch (IOException e) {
+    catch (ExecutionException | IOException e) {
       LOG.error(e);
     }
   }
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java
new file mode 100644 (file)
index 0000000..914baab
--- /dev/null
@@ -0,0 +1,19 @@
+package com.jetbrains.edu.learning.checker;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.edu.courseFormat.Task;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class StudyTestRunner {protected final Task myTask;
+  protected final VirtualFile myTaskDir;
+
+  public StudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
+    myTask = task;
+    myTaskDir = taskDir;
+  }
+
+  public abstract Process createCheckProcess(@NotNull final Project project, @NotNull final String executablePath) throws ExecutionException;
+
+}
similarity index 63%
rename from python/educational-core/student/src/com/jetbrains/edu/learning/run/StudyTestRunner.java
rename to python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyTestsOutputParser.java
index 2a17d65d5b04ac0143e02a8589a03e998ea7c3b9..55bfe7273bac72814873e355c6a1b0bf89d83efe 100644 (file)
@@ -1,30 +1,36 @@
-package com.jetbrains.edu.learning.run;
+package com.jetbrains.edu.learning.checker;
 
-import com.intellij.execution.ExecutionException;
 import com.intellij.execution.process.ProcessOutput;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.jetbrains.edu.courseFormat.Task;
 import org.jetbrains.annotations.NotNull;
 
-public abstract class StudyTestRunner {
+public class StudyTestsOutputParser {
   private static final String ourStudyPrefix = "#educational_plugin";
   public static final String TEST_OK = "test OK";
   private static final String TEST_FAILED = "FAILED + ";
   private static final String CONGRATS_MESSAGE = "CONGRATS_MESSAGE ";
-  protected final Task myTask;
-  protected final VirtualFile myTaskDir;
+  public static final String CONGRATULATIONS = "Congratulations!";
 
-  public StudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
-    myTask = task;
-    myTaskDir = taskDir;
-  }
+  public static class TestsOutput {
+    private final boolean isSuccess;
+    private final String myMessage;
+
+    public TestsOutput(boolean isSuccess, @NotNull final String message) {
+      this.isSuccess = isSuccess;
+      myMessage = message;
+    }
 
-  public abstract Process createCheckProcess(@NotNull final Project project, @NotNull final String executablePath) throws ExecutionException;
+    public boolean isSuccess() {
+      return isSuccess;
+    }
+
+    public String getMessage() {
+      return myMessage;
+    }
+  }
 
   @NotNull
-  public TestsOutput getTestsOutput(@NotNull final ProcessOutput processOutput) {
-    String congratulations = "Congratulations!";
+  public static TestsOutput getTestsOutput(@NotNull final ProcessOutput processOutput) {
+    String congratulations = CONGRATULATIONS;
     for (String line : processOutput.getStdoutLines()) {
       if (line.startsWith(ourStudyPrefix)) {
         if (line.contains(TEST_OK)) {
@@ -43,23 +49,4 @@ public abstract class StudyTestRunner {
 
     return new TestsOutput(true, congratulations);
   }
-
-  public static class TestsOutput {
-    private final boolean isSuccess;
-    private final String myMessage;
-
-    public TestsOutput(boolean isSuccess, @NotNull final String message) {
-      this.isSuccess = isSuccess;
-      myMessage = message;
-    }
-
-    public boolean isSuccess() {
-      return isSuccess;
-    }
-
-    public String getMessage() {
-      return myMessage;
-    }
-  }
-
 }
diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java
new file mode 100644 (file)
index 0000000..47ac0f9
--- /dev/null
@@ -0,0 +1,135 @@
+package com.jetbrains.edu.learning;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.jetbrains.edu.courseFormat.StudyStatus;
+import com.jetbrains.edu.courseFormat.Task;
+import com.jetbrains.edu.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.actions.StudyCheckAction;
+import com.jetbrains.edu.learning.actions.StudyRunAction;
+import com.jetbrains.edu.learning.checker.StudyCheckTask;
+import com.jetbrains.edu.learning.checker.StudyCheckUtils;
+import com.jetbrains.edu.learning.checker.StudyTestsOutputParser;
+import com.jetbrains.edu.learning.editor.StudyEditor;
+import com.jetbrains.edu.learning.checker.StudyTestRunner;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+public class PyStudyCheckAction extends StudyCheckAction {
+  private static final Logger LOG = Logger.getInstance(PyStudyCheckAction.class);
+
+  @Override
+  protected void check(@NotNull Project project) {
+    ApplicationManager.getApplication().runWriteAction(() -> {
+      CommandProcessor.getInstance().runUndoTransparentAction(() -> {
+        final StudyEditor selectedEditor = StudyUtils.getSelectedStudyEditor(project);
+        if (selectedEditor == null) return;
+        final StudyState studyState = new StudyState(selectedEditor);
+        if (!studyState.isValid()) {
+          LOG.info("StudyCheckAction was invoked outside study editor");
+          return;
+        }
+        if (StudyCheckUtils.hasBackgroundProcesses(project)) return;
+
+
+        if (!runTask(project)) return;
+
+        final Task task = studyState.getTask();
+        final VirtualFile taskDir = studyState.getTaskDir();
+        StudyCheckUtils.flushWindows(task, taskDir);
+
+
+        ApplicationManager.getApplication().invokeLater(
+          () -> IdeFocusManager.getInstance(project).requestFocus(studyState.getEditor().getComponent(), true));
+
+        final StudyTestRunner testRunner = StudyUtils.getTestRunner(task, taskDir);
+        Process testProcess = null;
+        String commandLine = "";
+        try {
+          final VirtualFile executablePath = getTaskVirtualFile(studyState, task, taskDir);
+          if (executablePath != null) {
+            commandLine = executablePath.getPath();
+            testProcess = testRunner.createCheckProcess(project, commandLine);
+          }
+        }
+        catch (ExecutionException e) {
+          LOG.error(e);
+        }
+        if (testProcess == null) {
+          return;
+        }
+        myCheckInProgress.set(true);
+        StudyCheckTask checkTask = getCheckTask(project, studyState, testRunner, testProcess, commandLine);
+        ProgressManager.getInstance().run(checkTask);
+      });
+    });
+  }
+
+  private static boolean runTask(@NotNull Project project) {
+    final StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
+    if (runAction == null) {
+      return false;
+    }
+    runAction.run(project);
+    return true;
+  }
+
+  @NotNull
+  private StudyCheckTask getCheckTask(@NotNull final Project project,
+                                      final StudyState studyState,
+                                      final StudyTestRunner testRunner,
+                                      final Process testProcess,
+                                      final String commandLine) {
+    return new StudyCheckTask(project, studyState, myCheckInProgress, testProcess, commandLine) {
+            @Override
+            protected void onTaskFailed(StudyTestsOutputParser.TestsOutput testsOutput) {
+              ApplicationManager.getApplication().invokeLater(() -> {
+                if (myTaskDir == null) return;
+                myTaskManger.setStatus(myTask, StudyStatus.Failed);
+                for (Map.Entry<String, TaskFile> entry : myTask.getTaskFiles().entrySet()) {
+                  final String name = entry.getKey();
+                  final TaskFile taskFile = entry.getValue();
+                  if (taskFile.getAnswerPlaceholders().size() < 2) {
+                    myTaskManger.setStatus(taskFile, StudyStatus.Failed);
+                    continue;
+                  }
+                  CommandProcessor.getInstance().runUndoTransparentAction(() -> ApplicationManager.getApplication().runWriteAction(() -> {
+                    StudyCheckUtils.runSmartTestProcess(myTaskDir, testRunner, name, taskFile, project);
+                  }));
+                }
+                StudyCheckUtils.showTestResultPopUp(testsOutput.getMessage(), MessageType.ERROR.getPopupBackground(), project);
+                StudyCheckUtils.navigateToFailedPlaceholder(myStudyState, myTask, myTaskDir, project);
+              });
+            }
+          };
+  }
+
+
+  @Nullable
+  private static VirtualFile getTaskVirtualFile(@NotNull final StudyState studyState,
+                                         @NotNull final Task task,
+                                         @NotNull final VirtualFile taskDir) {
+    VirtualFile taskVirtualFile = studyState.getVirtualFile();
+    for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
+      String name = entry.getKey();
+      TaskFile taskFile = entry.getValue();
+      VirtualFile virtualFile = taskDir.findChild(name);
+      if (virtualFile != null) {
+        if (!taskFile.getAnswerPlaceholders().isEmpty()) {
+          taskVirtualFile = virtualFile;
+        }
+      }
+    }
+    return taskVirtualFile;
+  }
+}
index a22a5a677255cca53357cda8a1a92af87b51a4b6..c0f5b10b7341f0708bb2907ac328094a4e4b583c 100644 (file)
@@ -29,15 +29,14 @@ import com.intellij.openapi.ui.popup.BalloonBuilder;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.jetbrains.edu.courseFormat.Task;
+import com.jetbrains.edu.learning.checker.StudyExecutor;
+import com.jetbrains.edu.learning.checker.StudyTestRunner;
 import com.jetbrains.edu.learning.courseFormat.UserTest;
-import com.jetbrains.edu.learning.run.StudyExecutor;
-import com.jetbrains.edu.learning.run.StudyTestRunner;
 import com.jetbrains.python.run.PythonTracebackFilter;
 import com.jetbrains.python.sdk.PythonSdkType;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkListener;
 import java.io.File;
 import java.util.List;
 
@@ -83,18 +82,11 @@ public class PyStudyExecutor implements StudyExecutor {
     final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().
       createHtmlTextBalloonBuilder(text, null,
                                    MessageType.WARNING.getPopupBackground(),
-                                   new HyperlinkListener() {
-                                     @Override
-                                     public void hyperlinkUpdate(HyperlinkEvent event) {
-                                       if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
-                                         ApplicationManager.getApplication()
-                                           .invokeLater(new Runnable() {
-                                             @Override
-                                             public void run() {
-                                               ShowSettingsUtil.getInstance().showSettingsDialog(project, "Project Interpreter");
-                                             }
-                                           });
-                                       }
+                                   event -> {
+                                     if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+                                       ApplicationManager.getApplication()
+                                         .invokeLater(
+                                           () -> ShowSettingsUtil.getInstance().showSettingsDialog(project, "Project Interpreter"));
                                      }
                                    });
     balloonBuilder.setHideOnLinkClick(true);
index e8d1887b11091ccecdc38833ce5e00279c7f6bdc..6c74c41575fbaf04fa17570df039cc995b07488b 100644 (file)
@@ -10,7 +10,7 @@ import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.jetbrains.edu.courseFormat.Course;
 import com.jetbrains.edu.courseFormat.Task;
-import com.jetbrains.edu.learning.run.StudyTestRunner;
+import com.jetbrains.edu.learning.checker.StudyTestRunner;
 import com.jetbrains.python.sdk.PythonSdkType;
 import org.jetbrains.annotations.NotNull;
 
index 23dbbf505db8f20034e666761ca365b30b8d9a4a..21e24aeb810ce30f465173b490ddd5a58698e9d7 100644 (file)
@@ -23,7 +23,7 @@ public class PyStudyToolWindowConfigurator implements StudyToolWindowConfigurato
   @Override
   public DefaultActionGroup getActionGroup(Project project) {
     final DefaultActionGroup group = new DefaultActionGroup();
-    group.add(new StudyCheckAction());
+    group.add(new PyStudyCheckAction());
     group.add(new StudyPreviousStudyTaskAction());
     group.add(new StudyNextStudyTaskAction());
     group.add(new StudyRefreshTaskFileAction());