summaryrefslogtreecommitdiff
path: root/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
diff options
context:
space:
mode:
Diffstat (limited to 'python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java')
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java378
1 files changed, 157 insertions, 221 deletions
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
index f8e10c9c4521..5d02f7149aab 100644
--- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
@@ -1,7 +1,6 @@
package com.jetbrains.python.edu.actions;
import com.intellij.execution.ExecutionException;
-import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -13,93 +12,81 @@ 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.module.ModuleManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
+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.TextRange;
-import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.JBColor;
+import com.intellij.openapi.wm.IdeFocusManager;
import com.jetbrains.python.edu.StudyDocumentListener;
-import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyState;
+import com.jetbrains.python.edu.StudyTestRunner;
import com.jetbrains.python.edu.StudyUtils;
-import com.jetbrains.python.edu.course.*;
+import com.jetbrains.python.edu.course.StudyStatus;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.python.edu.editor.StudyEditor;
-import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
-import java.io.*;
-import java.util.*;
-import java.util.List;
+import java.io.IOException;
+import java.util.Map;
public class StudyCheckAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(StudyCheckAction.class.getName());
- public static final String PYTHONPATH = "PYTHONPATH";
+ private static final String ANSWERS_POSTFIX = "_answers.py";
- static class StudyTestRunner {
- public static final String TEST_OK = "#study_plugin test OK";
- private static final String TEST_FAILED = "#study_plugin FAILED + ";
- private final Task myTask;
- private final VirtualFile myTaskDir;
- StudyTestRunner(Task task, VirtualFile taskDir) {
- myTask = task;
- myTaskDir = taskDir;
+ 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;
+ }
+ StudyUtils.flushWindows(taskFile, virtualFile);
}
+ }
- Process launchTests(Project project, String executablePath) throws ExecutionException {
- Sdk sdk = PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
- File testRunner = new File(myTaskDir.getPath(), myTask.getTestFile());
- GeneralCommandLine commandLine = new GeneralCommandLine();
- commandLine.setWorkDirectory(myTaskDir.getPath());
- final Map<String, String> env = commandLine.getEnvironment();
- final VirtualFile courseDir = project.getBaseDir();
- if (courseDir != null)
- env.put(PYTHONPATH, courseDir.getPath());
- if (sdk != null) {
- String pythonPath = sdk.getHomePath();
- if (pythonPath != null) {
- commandLine.setExePath(pythonPath);
- commandLine.addParameter(testRunner.getPath());
- final Course course = StudyTaskManager.getInstance(project).getCourse();
- assert course != null;
- commandLine.addParameter(new File(course.getResourcePath()).getParent());
- commandLine.addParameter(FileUtil.toSystemDependentName(executablePath));
- return commandLine.createProcess();
- }
+ private static void deleteWindowDescriptions(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
+ for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
+ String name = entry.getKey();
+ VirtualFile virtualFile = taskDir.findChild(name);
+ if (virtualFile == null) {
+ continue;
+ }
+ String windowsFileName = virtualFile.getNameWithoutExtension() + "_windows";
+ VirtualFile windowsFile = taskDir.findChild(windowsFileName);
+ if (windowsFile != null) {
+ StudyUtils.deleteFile(windowsFile);
}
- return null;
}
+ }
-
- String getPassedTests(Process p) {
- InputStream testOutput = p.getInputStream();
- BufferedReader testOutputReader = new BufferedReader(new InputStreamReader(testOutput));
- String line;
- try {
- while ((line = testOutputReader.readLine()) != null) {
- if (line.contains(TEST_FAILED)) {
- return line.substring(TEST_FAILED.length(), line.length());
- }
- }
- }
- catch (IOException e) {
- LOG.error(e);
+ private static void drawAllTaskWindows(@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;
}
- finally {
- StudyUtils.closeSilently(testOutputReader);
+ FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
+ if (fileEditor instanceof StudyEditor) {
+ StudyEditor studyEditor = (StudyEditor)fileEditor;
+ taskFile.drawAllWindows(studyEditor.getEditor());
}
- return TEST_OK;
}
}
+
public void check(@NotNull final Project project) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -107,188 +94,138 @@ public class StudyCheckAction extends DumbAwareAction {
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
public void run() {
- final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
- if (selectedEditor != null) {
- final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
- final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
- if (openedFile != null) {
- StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
- final TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
- List<VirtualFile> filesToDelete = new ArrayList<VirtualFile>();
- if (selectedTaskFile != null) {
- final VirtualFile taskDir = openedFile.getParent();
- Task currentTask = selectedTaskFile.getTask();
- StudyStatus oldStatus = currentTask.getStatus();
- Map<String, TaskFile> taskFiles = selectedTaskFile.getTask().getTaskFiles();
+ final StudyEditor selectedEditor = StudyEditor.getSelectedStudyEditor(project);
+ final StudyState studyState = new StudyState(selectedEditor);
+ if (!studyState.isValid()) {
+ LOG.error("StudyCheckAction was invokes outside study editor");
+ return;
+ }
+ Task task = studyState.getTask();
+ StudyStatus oldStatus = task.getStatus();
+ Map<String, TaskFile> taskFiles = task.getTaskFiles();
+ VirtualFile taskDir = studyState.getTaskDir();
+ flushWindows(task, taskDir);
+ StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
+ if (runAction != null && taskFiles.size() == 1) {
+ runAction.run(project);
+ }
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ IdeFocusManager.getInstance(project).requestFocus(studyState.getEditor().getComponent(), true);
+ }
+ });
+ final StudyTestRunner testRunner = new StudyTestRunner(task, taskDir);
+ Process testProcess = null;
+ try {
+ testProcess = testRunner.launchTests(project, studyState.getVirtualFile().getPath());
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ }
+ if (testProcess == null) {
+ return;
+ }
+ String failedMessage = testRunner.getPassedTests(testProcess);
+ if (failedMessage.equals(StudyTestRunner.TEST_OK)) {
+ task.setStatus(StudyStatus.Solved, oldStatus);
+ createTestResultPopUp("Congratulations!", MessageType.INFO.getPopupBackground(), project);
+ }
+ else {
+ task.setStatus(StudyStatus.Failed, oldStatus);
for (Map.Entry<String, TaskFile> entry : taskFiles.entrySet()) {
String name = entry.getKey();
TaskFile taskFile = entry.getValue();
- VirtualFile virtualFile = taskDir.findChild(name);
- if (virtualFile == null) {
+ if (taskFile.getTaskWindows().size() < 2) {
+ taskFile.setStatus(StudyStatus.Failed, StudyStatus.Unchecked);
continue;
}
- VirtualFile windowFile = StudyUtils.flushWindows(FileDocumentManager.getInstance().getDocument(virtualFile), taskFile, virtualFile);
- filesToDelete.add(windowFile);
- FileDocumentManager.getInstance().saveAllDocuments();
- }
-
- StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
- if (runAction != null && currentTask.getTaskFiles().size() == 1) {
- runAction.run(project);
- }
- final StudyTestRunner testRunner = new StudyTestRunner(currentTask, taskDir);
- Process testProcess = null;
- try {
- testProcess = testRunner.launchTests(project, openedFile.getPath());
- }
- catch (ExecutionException e) {
- LOG.error(e);
- }
- if (testProcess != null) {
- String failedMessage = testRunner.getPassedTests(testProcess);
- if (failedMessage.equals(StudyTestRunner.TEST_OK)) {
- currentTask.setStatus(StudyStatus.Solved, oldStatus);
- StudyUtils.updateStudyToolWindow(project);
- selectedTaskFile.drawAllWindows(selectedEditor);
- ProjectView.getInstance(project).refresh();
- for (VirtualFile file:filesToDelete) {
- try {
- file.delete(this);
- }
- catch (IOException e) {
- LOG.error(e);
- }
- }
- createTestResultPopUp("Congratulations!", JBColor.GREEN, project);
- return;
- }
- for (Map.Entry<String, TaskFile> entry : taskFiles.entrySet()) {
- String name = entry.getKey();
- TaskFile taskFile = entry.getValue();
- TaskFile answerTaskFile = new TaskFile();
- VirtualFile virtualFile = taskDir.findChild(name);
- if (virtualFile == null) {
- continue;
- }
- VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
- for (TaskWindow taskWindow : answerTaskFile.getTaskWindows()) {
- Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
- if (document == null) {
- continue;
- }
- if (!taskWindow.isValid(document)) {
- continue;
- }
- check(project, taskWindow, answerFile, answerTaskFile, taskFile, document, testRunner, virtualFile);
- }
- FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
- Editor editor = null;
- if (fileEditor instanceof StudyEditor) {
- StudyEditor studyEditor = (StudyEditor) fileEditor;
- editor = studyEditor.getEditor();
- }
-
- if (editor != null) {
- taskFile.drawAllWindows(editor);
- StudyUtils.synchronize();
- }
- try {
- answerFile.delete(this);
- }
- catch (IOException e) {
- LOG.error(e);
- }
- }
- for (VirtualFile file:filesToDelete) {
- try {
- file.delete(this);
- }
- catch (IOException e) {
- LOG.error(e);
- }
- }
- currentTask.setStatus(StudyStatus.Failed, oldStatus);
- StudyUtils.updateStudyToolWindow(project);
- createTestResultPopUp(failedMessage, JBColor.RED, project);
+ runSmartTestProcess(taskDir, testRunner, name, taskFile, project);
}
+ createTestResultPopUp(failedMessage, MessageType.ERROR.getPopupBackground(), project);
+ navigateToFailedTaskWindow(studyState, task, taskDir, project);
}
+ StudyUtils.updateStudyToolWindow(project);
+ drawAllTaskWindows(project, task, taskDir);
+ ProjectView.getInstance(project).refresh();
+ deleteWindowDescriptions(task, taskDir);
}
- }
-
- }
- });
+ });
}
});
}
- private void check(Project project,
- TaskWindow taskWindow,
- VirtualFile answerFile,
- TaskFile answerTaskFile,
- TaskFile usersTaskFile,
- Document usersDocument,
- StudyTestRunner testRunner,
- VirtualFile openedFile) {
-
- try {
- VirtualFile windowCopy = answerFile.copy(this, answerFile.getParent(), answerFile.getNameWithoutExtension() + "_window" + taskWindow.getIndex() + ".py");
- final FileDocumentManager documentManager = FileDocumentManager.getInstance();
- final Document windowDocument = documentManager.getDocument(windowCopy);
- if (windowDocument != null) {
- StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
- Course course = taskManager.getCourse();
- Task task = usersTaskFile.getTask();
- int taskNum = task.getIndex() + 1;
- int lessonNum = task.getLesson().getIndex() + 1;
- assert course != null;
- String pathToResource = FileUtil.join(new File(course.getResourcePath()).getParent(), Lesson.LESSON_DIR + lessonNum, Task.TASK_DIR + taskNum);
- File resourceFile = new File(pathToResource, windowCopy.getName());
- FileUtil.copy(new File(pathToResource, openedFile.getName()), resourceFile);
- TaskFile windowTaskFile = new TaskFile();
- TaskFile.copy(answerTaskFile, windowTaskFile);
- StudyDocumentListener listener = new StudyDocumentListener(windowTaskFile);
- windowDocument.addDocumentListener(listener);
- int start = taskWindow.getRealStartOffset(windowDocument);
- int end = start + taskWindow.getLength();
- TaskWindow userTaskWindow = usersTaskFile.getTaskWindows().get(taskWindow.getIndex());
- int userStart = userTaskWindow.getRealStartOffset(usersDocument);
- int userEnd = userStart + userTaskWindow.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);
+ private static void navigateToFailedTaskWindow(@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();
+ if (!selectedTaskFile.hasFailedTaskWindows()) {
+ for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
+ String name = entry.getKey();
+ TaskFile taskFile = entry.getValue();
+ if (taskFile.hasFailedTaskWindows()) {
+ taskFileToNavigate = taskFile;
+ VirtualFile virtualFile = taskDir.findChild(name);
+ if (virtualFile == null) {
+ continue;
}
- });
- VirtualFile fileWindows = StudyUtils.flushWindows(windowDocument, windowTaskFile, windowCopy);
- Process smartTestProcess = testRunner.launchTests(project, windowCopy.getPath());
- boolean res = testRunner.getPassedTests(smartTestProcess).equals(StudyTestRunner.TEST_OK);
- userTaskWindow.setStatus(res ? StudyStatus.Solved : StudyStatus.Failed, StudyStatus.Unchecked);
- windowCopy.delete(this);
- fileWindows.delete(this);
- if (!resourceFile.delete()) {
- LOG.error("failed to delete", resourceFile.getPath());
+ FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
+ if (fileEditor instanceof StudyEditor) {
+ StudyEditor studyEditor = (StudyEditor)fileEditor;
+ editor = studyEditor.getEditor();
+ }
+ fileToNavigate = virtualFile;
+ break;
}
}
}
- catch (IOException e) {
- LOG.error(e);
+ FileEditorManager.getInstance(project).openFile(fileToNavigate, true);
+ final Editor editorToNavigate = editor;
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ IdeFocusManager.getInstance(project).requestFocus(editorToNavigate.getContentComponent(), true);
+ }
+ });
+ taskFileToNavigate.navigateToFirstFailedTaskWindow(editor);
+ }
+
+ private void runSmartTestProcess(@NotNull final VirtualFile taskDir,
+ @NotNull final StudyTestRunner testRunner,
+ final String taskFileName,
+ @NotNull final TaskFile taskFile,
+ @NotNull final Project project) {
+ TaskFile answerTaskFile = new TaskFile();
+ VirtualFile virtualFile = taskDir.findChild(taskFileName);
+ if (virtualFile == null) {
+ return;
}
- catch (ExecutionException e) {
- LOG.error(e);
+ VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
+ for (TaskWindow taskWindow : answerTaskFile.getTaskWindows()) {
+ Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+ if (document == null) {
+ continue;
+ }
+ if (!taskWindow.isValid(document)) {
+ continue;
+ }
+ taskWindow.smartCheck(project, answerFile, answerTaskFile, taskFile, testRunner, virtualFile, document);
}
+ StudyUtils.deleteFile(answerFile);
}
-
- private VirtualFile getCopyWithAnswers(final VirtualFile taskDir,
- final VirtualFile file,
- final TaskFile source,
- TaskFile target) {
+ 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.py");
+ copy = file.copy(this, taskDir, file.getNameWithoutExtension() + ANSWERS_POSTFIX);
final FileDocumentManager documentManager = FileDocumentManager.getInstance();
final Document document = documentManager.getDocument(copy);
if (document != null) {
@@ -315,19 +252,18 @@ public class StudyCheckAction extends DumbAwareAction {
catch (IOException e) {
LOG.error(e);
}
-
-
return copy;
}
private static void createTestResultPopUp(final String text, Color color, @NotNull final Project project) {
BalloonBuilder balloonBuilder =
JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
- Balloon balloon = balloonBuilder.createBalloon();
+ final Balloon balloon = balloonBuilder.createBalloon();
StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
assert studyEditor != null;
JButton checkButton = studyEditor.getCheckButton();
balloon.showInCenterOf(checkButton);
+ Disposer.register(project, balloon);
}
@Override