choose correct test file
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / checker / StudyCheckUtils.java
1 package com.jetbrains.edu.learning.checker;
2
3 import com.intellij.execution.impl.ConsoleViewImpl;
4 import com.intellij.execution.ui.ConsoleViewContentType;
5 import com.intellij.openapi.application.ApplicationManager;
6 import com.intellij.openapi.diagnostic.Logger;
7 import com.intellij.openapi.editor.Document;
8 import com.intellij.openapi.editor.Editor;
9 import com.intellij.openapi.fileEditor.FileDocumentManager;
10 import com.intellij.openapi.fileEditor.FileEditor;
11 import com.intellij.openapi.fileEditor.FileEditorManager;
12 import com.intellij.openapi.progress.ProgressIndicator;
13 import com.intellij.openapi.progress.TaskInfo;
14 import com.intellij.openapi.project.Project;
15 import com.intellij.openapi.ui.popup.Balloon;
16 import com.intellij.openapi.ui.popup.BalloonBuilder;
17 import com.intellij.openapi.ui.popup.JBPopupFactory;
18 import com.intellij.openapi.util.Pair;
19 import com.intellij.openapi.vfs.VirtualFile;
20 import com.intellij.openapi.wm.*;
21 import com.intellij.openapi.wm.ex.StatusBarEx;
22 import com.intellij.openapi.wm.ex.WindowManagerEx;
23 import com.intellij.ui.content.Content;
24 import com.jetbrains.edu.learning.StudyState;
25 import com.jetbrains.edu.learning.StudyTaskManager;
26 import com.jetbrains.edu.learning.StudyUtils;
27 import com.jetbrains.edu.learning.core.EduDocumentListener;
28 import com.jetbrains.edu.learning.core.EduNames;
29 import com.jetbrains.edu.learning.core.EduUtils;
30 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
31 import com.jetbrains.edu.learning.courseFormat.Task;
32 import com.jetbrains.edu.learning.courseFormat.TaskFile;
33 import com.jetbrains.edu.learning.editor.StudyEditor;
34 import com.jetbrains.edu.learning.navigation.StudyNavigator;
35 import com.jetbrains.edu.learning.ui.StudyTestResultsToolWindowFactory;
36 import com.jetbrains.edu.learning.ui.StudyTestResultsToolWindowFactoryKt;
37 import org.jetbrains.annotations.NotNull;
38
39 import javax.swing.*;
40 import java.awt.*;
41 import java.io.IOException;
42 import java.util.List;
43 import java.util.Map;
44
45 public class StudyCheckUtils {
46   private static final Logger LOG = Logger.getInstance(StudyCheckUtils.class);
47
48   private StudyCheckUtils() {
49   }
50
51   public static void drawAllPlaceholders(@NotNull final Project project, @NotNull final Task task, @NotNull final VirtualFile taskDir) {
52     for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
53       String name = entry.getKey();
54       TaskFile taskFile = entry.getValue();
55       VirtualFile virtualFile = taskDir.findChild(name);
56       if (virtualFile == null) {
57         continue;
58       }
59       FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
60       if (fileEditor instanceof StudyEditor) {
61         StudyEditor studyEditor = (StudyEditor)fileEditor;
62         StudyUtils.drawAllAnswerPlaceholders(studyEditor.getEditor(), taskFile);
63       }
64     }
65   }
66
67   public static void navigateToFailedPlaceholder(@NotNull final StudyState studyState,
68                                                  @NotNull final Task task,
69                                                  @NotNull final VirtualFile taskDir,
70                                                  @NotNull final Project project) {
71     TaskFile selectedTaskFile = studyState.getTaskFile();
72     Editor editor = studyState.getEditor();
73     TaskFile taskFileToNavigate = selectedTaskFile;
74     VirtualFile fileToNavigate = studyState.getVirtualFile();
75     final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
76     if (!taskManager.hasFailedAnswerPlaceholders(selectedTaskFile)) {
77       for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
78         String name = entry.getKey();
79         TaskFile taskFile = entry.getValue();
80         if (taskManager.hasFailedAnswerPlaceholders(taskFile)) {
81           taskFileToNavigate = taskFile;
82           VirtualFile virtualFile = taskDir.findChild(name);
83           if (virtualFile == null) {
84             continue;
85           }
86           FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
87           if (fileEditor instanceof StudyEditor) {
88             StudyEditor studyEditor = (StudyEditor)fileEditor;
89             editor = studyEditor.getEditor();
90           }
91           fileToNavigate = virtualFile;
92           break;
93         }
94       }
95     }
96     if (fileToNavigate != null) {
97       FileEditorManager.getInstance(project).openFile(fileToNavigate, true);
98     }
99     final Editor editorToNavigate = editor;
100     ApplicationManager.getApplication().invokeLater(
101       () -> IdeFocusManager.getInstance(project).requestFocus(editorToNavigate.getContentComponent(), true));
102
103     StudyNavigator.navigateToFirstFailedAnswerPlaceholder(editor, taskFileToNavigate);
104   }
105
106
107   public static void showTestResultPopUp(final String text, Color color, @NotNull final Project project) {
108     BalloonBuilder balloonBuilder =
109       JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
110     final Balloon balloon = balloonBuilder.createBalloon();
111     StudyUtils.showCheckPopUp(project, balloon);
112   }
113
114
115   public static void runSmartTestProcess(@NotNull final VirtualFile taskDir,
116                                          @NotNull final StudyTestRunner testRunner,
117                                          final String taskFileName,
118                                          @NotNull final TaskFile taskFile,
119                                          @NotNull final Project project) {
120     final TaskFile answerTaskFile = new TaskFile();
121     answerTaskFile.name = taskFileName;
122     final VirtualFile virtualFile = taskDir.findChild(taskFileName);
123     if (virtualFile == null) {
124       return;
125     }
126     final VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
127     for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) {
128       final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
129       if (document == null) {
130         continue;
131       }
132       StudySmartChecker.smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner,
133                                    virtualFile, document);
134     }
135     StudyUtils.deleteFile(answerFile);
136   }
137
138
139   private static VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
140                                                 @NotNull final VirtualFile file,
141                                                 @NotNull final TaskFile source,
142                                                 @NotNull TaskFile target) {
143     VirtualFile copy = null;
144     try {
145
146       copy = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension());
147       final FileDocumentManager documentManager = FileDocumentManager.getInstance();
148       final Document document = documentManager.getDocument(copy);
149       if (document != null) {
150         target = source.getTask().copy().getTaskFile(file.getName());
151         if (target == null) {
152           return copy;
153         }
154         EduDocumentListener listener = new EduDocumentListener(target);
155         document.addDocumentListener(listener);
156         for (AnswerPlaceholder answerPlaceholder : target.getActivePlaceholders()) {
157           final int start = answerPlaceholder.getOffset();
158           final int end = start + answerPlaceholder.getRealLength();
159           final String text = answerPlaceholder.getPossibleAnswer();
160           document.replaceString(start, end, text);
161         }
162         ApplicationManager.getApplication().runWriteAction(() -> documentManager.saveDocument(document));
163       }
164     }
165     catch (IOException e) {
166       LOG.error(e);
167     }
168     return copy;
169   }
170
171
172   public static boolean hasBackgroundProcesses(@NotNull Project project) {
173     final IdeFrame frame = ((WindowManagerEx)WindowManager.getInstance()).findFrameFor(project);
174     final StatusBarEx statusBar = frame == null ? null : (StatusBarEx)frame.getStatusBar();
175     if (statusBar != null) {
176       final List<Pair<TaskInfo, ProgressIndicator>> processes = statusBar.getBackgroundProcesses();
177       if (!processes.isEmpty()) return true;
178     }
179     return false;
180   }
181
182
183   public static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
184     for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
185       String name = entry.getKey();
186       TaskFile taskFile = entry.getValue();
187       VirtualFile virtualFile = taskDir.findChild(name);
188       if (virtualFile == null) {
189         continue;
190       }
191       EduUtils.flushWindows(taskFile, virtualFile);
192     }
193   }
194
195   public static void showTestResultsToolWindow(@NotNull final Project project, @NotNull final String message, boolean solved) {
196     final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
197     ToolWindow window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
198     if (window == null) {
199       toolWindowManager.registerToolWindow(StudyTestResultsToolWindowFactoryKt.ID, true, ToolWindowAnchor.BOTTOM);
200       window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
201       new StudyTestResultsToolWindowFactory().createToolWindowContent(project, window);
202     }
203
204     final Content[] contents = window.getContentManager().getContents();
205     for (Content content : contents) {
206       final JComponent component = content.getComponent();
207       if (component instanceof ConsoleViewImpl) {
208         ((ConsoleViewImpl)component).clear();
209         if (!solved) {
210           ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.ERROR_OUTPUT);
211         }
212         else {
213           ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.NORMAL_OUTPUT);
214         }
215         window.setAvailable(true, () -> {});
216         window.show(() -> {});
217         return;
218       }
219     }
220   }
221 }