21d0983f252d56c48ff8c63a9642c89a3dc8ac2f
[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.drawAllWindows(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.getAnswerPlaceholders()) {
128       final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
129       if (document == null) {
130         continue;
131       }
132       if (!answerPlaceholder.isValid(document)) {
133         continue;
134       }
135       StudySmartChecker.smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner,
136                                    virtualFile, document);
137     }
138     StudyUtils.deleteFile(answerFile);
139   }
140
141
142   private static VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
143                                                 @NotNull final VirtualFile file,
144                                                 @NotNull final TaskFile source,
145                                                 @NotNull final TaskFile target) {
146     VirtualFile copy = null;
147     try {
148
149       copy = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension());
150       final FileDocumentManager documentManager = FileDocumentManager.getInstance();
151       final Document document = documentManager.getDocument(copy);
152       if (document != null) {
153         TaskFile.copy(source, target);
154         EduDocumentListener listener = new EduDocumentListener(target);
155         document.addDocumentListener(listener);
156         for (AnswerPlaceholder answerPlaceholder : target.getAnswerPlaceholders()) {
157           if (!answerPlaceholder.isValid(document)) {
158             continue;
159           }
160           final int start = answerPlaceholder.getOffset();
161           final int end = start + answerPlaceholder.getRealLength();
162           final String text = answerPlaceholder.getPossibleAnswer();
163           document.replaceString(start, end, text);
164         }
165         ApplicationManager.getApplication().runWriteAction(() -> documentManager.saveDocument(document));
166       }
167     }
168     catch (IOException e) {
169       LOG.error(e);
170     }
171     return copy;
172   }
173
174
175   public static boolean hasBackgroundProcesses(@NotNull Project project) {
176     final IdeFrame frame = ((WindowManagerEx)WindowManager.getInstance()).findFrameFor(project);
177     final StatusBarEx statusBar = frame == null ? null : (StatusBarEx)frame.getStatusBar();
178     if (statusBar != null) {
179       final List<Pair<TaskInfo, ProgressIndicator>> processes = statusBar.getBackgroundProcesses();
180       if (!processes.isEmpty()) return true;
181     }
182     return false;
183   }
184
185
186   public static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
187     for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
188       String name = entry.getKey();
189       TaskFile taskFile = entry.getValue();
190       VirtualFile virtualFile = taskDir.findChild(name);
191       if (virtualFile == null) {
192         continue;
193       }
194       EduUtils.flushWindows(taskFile, virtualFile, true);
195     }
196   }
197
198   public static void showTestResultsToolWindow(@NotNull final Project project, @NotNull final String message, boolean solved) {
199     final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
200     ToolWindow window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
201     if (window == null) {
202       toolWindowManager.registerToolWindow(StudyTestResultsToolWindowFactoryKt.ID, true, ToolWindowAnchor.BOTTOM);
203       window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
204       new StudyTestResultsToolWindowFactory().createToolWindowContent(project, window);
205     }
206
207     final Content[] contents = window.getContentManager().getContents();
208     for (Content content : contents) {
209       final JComponent component = content.getComponent();
210       if (component instanceof ConsoleViewImpl) {
211         ((ConsoleViewImpl)component).clear();
212         if (!solved) {
213           ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.ERROR_OUTPUT);
214         }
215         else {
216           ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.NORMAL_OUTPUT);
217         }
218         window.setAvailable(true, () -> {});
219         window.show(() -> {});
220         return;
221       }
222     }
223   }
224 }