fixes after IDEA-CR-14348 review pycharm/171.1053
authorLiana.Bakradze <liana.bakradze@jetbrains.com>
Tue, 15 Nov 2016 11:16:09 +0000 (14:16 +0300)
committerliana.bakradze <liana.bakradze@jetbrains.com>
Thu, 17 Nov 2016 14:09:05 +0000 (17:09 +0300)
20 files changed:
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCSubtaskEditorNotificationProvider.java
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/placeholder/CCActivatePlaceholder.java
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/placeholder/CCAddAnswerPlaceholder.java
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/placeholder/CCDeactivatePlaceholder.java
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/placeholder/CCDeleteAnswerPlaceholder.java
python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/placeholder/CCSubtaskPlaceholderAction.java
python/educational-core/student/src/com/jetbrains/edu/learning/StudySerializationUtils.java
python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java
python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java
python/educational-core/student/src/com/jetbrains/edu/learning/core/EduAnswerPlaceholderPainter.java
python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/AnswerPlaceholder.java
python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/AnswerPlaceholderSubtaskInfo.java
python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/TaskFile.java
python/educational-core/student/src/com/jetbrains/edu/learning/navigation/StudyNavigator.java
python/educational-core/student/src/com/jetbrains/edu/learning/projectView/LessonDirectoryNode.java
python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java
python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCLanguageManager.java

index d0911b18080f1d70502d22b491cf66219261e2c1..a2a49225e1552119964bf96ba8c80a1659fd84b6 100644 (file)
@@ -74,10 +74,10 @@ public class CCSubtaskEditorNotificationProvider extends EditorNotifications.Pro
         return color == null ? super.getBackground() : color;
       }
     };
-    String header = isTestFile ? "test" : "task file";
+    String header = (isTestFile ? "test" : "task") + " file";
     int activeSubtaskIndex = task.getActiveSubtaskIndex() + 1;
     int subtaskSize = task.getLastSubtaskIndex() + 1;
-    panel.setText("This is " + header + " for " + EduNames.SUBTASK + " " + activeSubtaskIndex + "/" + subtaskSize);
+    panel.setText("This is " + header + " for " + EduNames.SUBTASK + " " + activeSubtaskIndex + "/" + subtaskSize);
     panel.createActionLabel(SWITCH_SUBTASK, () -> {
       ArrayList<Integer> values = new ArrayList<>();
       for (int i = 0; i <= task.getLastSubtaskIndex(); i++) {
index ea697bdc1ded757c336925b8be4840bac33438ea..2dd6270f5d674278920429f011313c235fef059d 100644 (file)
@@ -13,6 +13,8 @@ import com.intellij.openapi.actionSystem.Presentation;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.DumbModePermission;
+import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.ModuleRootModificationUtil;
 import com.intellij.openapi.roots.ProjectRootManager;
@@ -48,7 +50,7 @@ public class CCUtils {
   public static final String GENERATED_FILES_FOLDER = ".coursecreator";
   public static final String COURSE_MODE = "Course Creator";
 
-  public static int getSubtaskIndex(Project project, VirtualFile file) {
+  public static int getSubtaskIndex(@NotNull Project project, @NotNull VirtualFile file) {
     String fileName = file.getName();
     String name = FileUtil.getNameWithoutExtension(fileName);
     boolean canBeSubtaskFile = isTestsFile(project, file) || StudyUtils.isTaskDescriptionFile(fileName);
@@ -65,7 +67,8 @@ public class CCUtils {
     }
     try {
       return Integer.valueOf(index);
-    } catch (NumberFormatException e) {
+    }
+    catch (NumberFormatException e) {
       return -1;
     }
   }
@@ -147,21 +150,27 @@ public class CCUtils {
       return folder;
     }
     final Ref<VirtualFile> generatedRoot = new Ref<>();
-    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+    DumbService.allowStartingDumbModeInside(DumbModePermission.MAY_START_BACKGROUND, new Runnable() {
       @Override
       public void run() {
-        try {
-          generatedRoot.set(baseDir.createChildDirectory(this, GENERATED_FILES_FOLDER));
-          VirtualFile contentRootForFile =
-            ProjectRootManager.getInstance(module.getProject()).getFileIndex().getContentRootForFile(generatedRoot.get());
-          if (contentRootForFile == null) {
-            return;
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          @Override
+          public void run() {
+            try {
+              generatedRoot.set(baseDir.createChildDirectory(this, GENERATED_FILES_FOLDER));
+              VirtualFile contentRootForFile =
+                ProjectRootManager.getInstance(module.getProject()).getFileIndex().getContentRootForFile(generatedRoot.get());
+              if (contentRootForFile == null) {
+                return;
+              }
+              ModuleRootModificationUtil.updateExcludedFolders(module, contentRootForFile, Collections.emptyList(),
+                                                               Collections.singletonList(generatedRoot.get().getUrl()));
+            }
+            catch (IOException e) {
+              LOG.info("Failed to create folder for generated files", e);
+            }
           }
-          ModuleRootModificationUtil.updateExcludedFolders(module, contentRootForFile, Collections.emptyList(), Collections.singletonList(generatedRoot.get().getUrl()));
-        }
-        catch (IOException e) {
-          LOG.info("Failed to create folder for generated files", e);
-        }
+        });
       }
     });
     return generatedRoot.get();
@@ -292,9 +301,9 @@ public class CCUtils {
   }
 
   public static void createTaskContent(@NotNull Project project,
-                                   @Nullable IdeView view,
-                                   @NotNull Course course,
-                                   PsiDirectory taskDirectory) {
+                                       @Nullable IdeView view,
+                                       @NotNull Course course,
+                                       PsiDirectory taskDirectory) {
     CCLanguageManager manager = getStudyLanguageManager(course);
     if (manager == null) {
       return;
index e34d3246ec763c0569e96b9d651e7a5544828cd9..0bb15cfbbe2983da1e11bc203e2acae70a08b23a 100644 (file)
@@ -1,9 +1,11 @@
 package com.jetbrains.edu.coursecreator.actions.placeholder;
 
 import com.intellij.openapi.util.TextRange;
+import com.jetbrains.edu.learning.StudyUtils;
 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholderSubtaskInfo;
 import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import org.jetbrains.annotations.NotNull;
 
 public class CCActivatePlaceholder extends CCSubtaskPlaceholderAction {
 
@@ -14,9 +16,9 @@ public class CCActivatePlaceholder extends CCSubtaskPlaceholderAction {
   }
 
   @Override
-  protected AnswerPlaceholderSubtaskInfo getInfo(CCState state,
+  protected AnswerPlaceholderSubtaskInfo getInfo(@NotNull CCState state,
                                                  int subtaskIndex,
-                                                 AnswerPlaceholder existingPlaceholder) {
+                                                 @NotNull AnswerPlaceholder existingPlaceholder) {
     int visibleLength = existingPlaceholder.getVisibleLength(subtaskIndex);
     int placeholderOffset = existingPlaceholder.getOffset();
     String possibleAnswer = state.getEditor().getDocument().getText(TextRange.create(placeholderOffset, placeholderOffset + visibleLength));
@@ -31,18 +33,18 @@ public class CCActivatePlaceholder extends CCSubtaskPlaceholderAction {
   }
 
   @Override
-  protected void redoAction(AnswerPlaceholder existingPlaceholder, int subtaskIndex, AnswerPlaceholderSubtaskInfo info) {
+  protected void redoAction(@NotNull AnswerPlaceholder existingPlaceholder, int subtaskIndex, @NotNull AnswerPlaceholderSubtaskInfo info) {
     existingPlaceholder.getSubtaskInfos().put(subtaskIndex, info);
   }
 
   @Override
-  protected void undoAction(AnswerPlaceholder existingPlaceholder, int subtaskIndex, AnswerPlaceholderSubtaskInfo info) {
+  protected void undoAction(@NotNull AnswerPlaceholder existingPlaceholder, int subtaskIndex, @NotNull AnswerPlaceholderSubtaskInfo info) {
     existingPlaceholder.getSubtaskInfos().remove(subtaskIndex);
   }
 
   @Override
   protected boolean isAvailable(TaskFile taskFile, int offset) {
-    AnswerPlaceholder existingPlaceholder = taskFile.getAnswerPlaceholder(offset, taskFile.getAnswerPlaceholders());
+    AnswerPlaceholder existingPlaceholder = StudyUtils.getAnswerPlaceholder(offset, taskFile.getAnswerPlaceholders());
     return existingPlaceholder != null && !existingPlaceholder.isActive();
   }
 }
index d7220ff519190687523ace32894f45f1f0c3907a..9651adf4e9dc1e9d4573b585cf93cac8e03dc5c6 100644 (file)
@@ -145,7 +145,7 @@ public class CCAddAnswerPlaceholder extends CCAnswerPlaceholderAction {
       return !arePlaceholdersIntersect(taskFile, start, end);
     }
     int offset = editor.getCaretModel().getOffset();
-    return taskFile.getAnswerPlaceholder(offset, taskFile.getAnswerPlaceholders()) == null;
+    return StudyUtils.getAnswerPlaceholder(offset, taskFile.getAnswerPlaceholders()) == null;
   }
 
   protected CCCreateAnswerPlaceholderDialog createDialog(Project project, AnswerPlaceholder answerPlaceholder) {
index 75db3a889eaa48cb8c9f37598c79ffc6e6446221..12f462e09d98eecde20299616e05723fd9c503b0 100644 (file)
@@ -3,6 +3,7 @@ package com.jetbrains.edu.coursecreator.actions.placeholder;
 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholderSubtaskInfo;
 import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Collections;
 
@@ -14,14 +15,14 @@ public class CCDeactivatePlaceholder extends CCSubtaskPlaceholderAction {
     super(TITLE, TITLE);
   }
 
-  protected void undoAction(AnswerPlaceholder existingPlaceholder, int subtaskIndex, AnswerPlaceholderSubtaskInfo info) {
+  protected void undoAction(@NotNull AnswerPlaceholder existingPlaceholder, int subtaskIndex, @NotNull AnswerPlaceholderSubtaskInfo info) {
     existingPlaceholder.getSubtaskInfos().put(subtaskIndex, info);
   }
 
   @Override
-  protected AnswerPlaceholderSubtaskInfo getInfo(CCState state,
+  protected AnswerPlaceholderSubtaskInfo getInfo(@NotNull CCState state,
                                                  int subtaskIndex,
-                                                 AnswerPlaceholder existingPlaceholder) {
+                                                 @NotNull AnswerPlaceholder existingPlaceholder) {
     return existingPlaceholder.getSubtaskInfos().get(subtaskIndex);
   }
 
@@ -30,7 +31,7 @@ public class CCDeactivatePlaceholder extends CCSubtaskPlaceholderAction {
     return TITLE;
   }
 
-  protected void redoAction(AnswerPlaceholder existingPlaceholder, int subtaskIndex, AnswerPlaceholderSubtaskInfo info) {
+  protected void redoAction(@NotNull AnswerPlaceholder existingPlaceholder, int subtaskIndex, @NotNull AnswerPlaceholderSubtaskInfo info) {
     existingPlaceholder.getSubtaskInfos().remove(subtaskIndex);
   }
 
index 559385f3fbff1b3df7e3354c411cb2f01e4b04b2..508da6af06b06ce5cc19a17d8e4e06b5b084c01a 100644 (file)
@@ -23,21 +23,20 @@ public class CCDeleteAnswerPlaceholder extends CCAnswerPlaceholderAction {
     Project project = state.getProject();
     TaskFile taskFile = state.getTaskFile();
     AnswerPlaceholder answerPlaceholder = state.getAnswerPlaceholder();
-    EduUtils.runUndoableAction(project, "Delete Answer Placeholder", new CCAddAnswerPlaceholder.AddAction(answerPlaceholder, taskFile, state.getEditor()) {
-      @Override
-      public void undo() throws UnexpectedUndoException {
-        super.redo();
-      }
-
-      @Override
-      public void redo() throws UnexpectedUndoException {
-        super.undo();
-      }
-    });
+    EduUtils.runUndoableAction(project, "Delete Answer Placeholder",
+                               new CCAddAnswerPlaceholder.AddAction(answerPlaceholder, taskFile, state.getEditor()) {
+                                 @Override
+                                 public void undo() throws UnexpectedUndoException {
+                                   super.redo();
+                                 }
+
+                                 @Override
+                                 public void redo() throws UnexpectedUndoException {
+                                   super.undo();
+                                 }
+                               });
   }
 
-
-
   private static boolean canDeletePlaceholder(@NotNull CCState state) {
     if (state.getEditor().getSelectionModel().hasSelection()) {
       return false;
@@ -59,5 +58,4 @@ public class CCDeleteAnswerPlaceholder extends CCAnswerPlaceholderAction {
       presentation.setEnabledAndVisible(true);
     }
   }
-
 }
index 77d6aa13ee8ee4f57af7086840835fff80ee7d34..550ad1a8e4d5644d1e089b89381fddf72d90b76c 100644 (file)
@@ -24,7 +24,7 @@ public abstract class CCSubtaskPlaceholderAction extends CCAnswerPlaceholderActi
     final int offset = editor.getCaretModel().getOffset();
     TaskFile taskFile = state.getTaskFile();
     int subtaskIndex = state.getTaskFile().getTask().getActiveSubtaskIndex();
-    AnswerPlaceholder existingPlaceholder = taskFile.getAnswerPlaceholder(offset, taskFile.getAnswerPlaceholders());
+    AnswerPlaceholder existingPlaceholder = StudyUtils.getAnswerPlaceholder(offset, taskFile.getAnswerPlaceholders());
     if (existingPlaceholder == null) {
       return;
     }
@@ -47,13 +47,13 @@ public abstract class CCSubtaskPlaceholderAction extends CCAnswerPlaceholderActi
     });
   }
 
-  protected abstract AnswerPlaceholderSubtaskInfo getInfo(CCState state, int subtaskIndex, AnswerPlaceholder existingPlaceholder);
+  protected abstract AnswerPlaceholderSubtaskInfo getInfo(@NotNull CCState state, int subtaskIndex, @NotNull AnswerPlaceholder existingPlaceholder);
 
   protected abstract String getTitle();
 
-  protected abstract void redoAction(AnswerPlaceholder existingPlaceholder, int subtaskIndex, AnswerPlaceholderSubtaskInfo info);
+  protected abstract void redoAction(@NotNull AnswerPlaceholder existingPlaceholder, int subtaskIndex, @NotNull AnswerPlaceholderSubtaskInfo info);
 
-  protected abstract void undoAction(AnswerPlaceholder existingPlaceholder, int subtaskIndex, AnswerPlaceholderSubtaskInfo info);
+  protected abstract void undoAction(@NotNull AnswerPlaceholder existingPlaceholder, int subtaskIndex, @NotNull AnswerPlaceholderSubtaskInfo info);
 
   @Override
   public void update(AnActionEvent e) {
index 076d3ef73b76ffb5bc0b53d1b8a376605d033f3b..279fad1248fc81356bbc0cada53022f1b00fa7c9 100644 (file)
@@ -219,8 +219,7 @@ public class StudySerializationUtils {
             for (Element placeholder : getChildList(taskFileElement, ANSWER_PLACEHOLDERS)) {
               Element valueElement = new Element(SUBTASK_INFO);
               addChildMap(placeholder, SUBTASK_INFOS, Collections.singletonMap(String.valueOf(0), valueElement));
-              for (String childName : ContainerUtil
-                .list(HINT, ADDITIONAL_HINTS, POSSIBLE_ANSWER, SELECTED, STATUS, TASK_TEXT)) {
+              for (String childName : ContainerUtil.list(HINT, ADDITIONAL_HINTS, POSSIBLE_ANSWER, SELECTED, STATUS, TASK_TEXT)) {
                 Element child = getChildWithName(placeholder, childName);
                 valueElement.addContent(child.clone());
               }
index 9505f6d63eabb5c0b8fe244d6a3c586ab3c2a139..9dcf390cd048f28a4a8e098339c7b3651500f215 100644 (file)
@@ -798,4 +798,15 @@ public class StudyUtils {
       toolWindowManager.registerToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW, true, ToolWindowAnchor.RIGHT, project, true);
     }
   }
+
+  @Nullable public static AnswerPlaceholder getAnswerPlaceholder(int offset, List<AnswerPlaceholder> placeholders) {
+    for (AnswerPlaceholder placeholder : placeholders) {
+      int placeholderStart = placeholder.getOffset();
+      int placeholderEnd = placeholderStart + placeholder.getRealLength();
+      if (placeholderStart <= offset && offset <= placeholderEnd) {
+        return placeholder;
+      }
+    }
+    return null;
+  }
 }
index cf054406f5d8f6fbc39324c348251d1bbb17ad0e..6e11bc7a7b2468ebf85f6271d030e803a0f80912 100644 (file)
@@ -193,8 +193,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
         int visibleSubtaskIndex = myTask.getActiveSubtaskIndex() + 1;
         ApplicationManager.getApplication().invokeLater(() -> {
           int subtaskSize = myTask.getLastSubtaskIndex() + 1;
-          String resultMessage = !hasMoreSubtasks ? message : "Subtask " + visibleSubtaskIndex + "/" +
-                                                              subtaskSize + " solved";
+          String resultMessage = !hasMoreSubtasks ? message : "Subtask " + visibleSubtaskIndex + "/" + subtaskSize + " solved";
           StudyCheckUtils.showTestResultPopUp(resultMessage, MessageType.INFO.getPopupBackground(), myProject);
           if (hasMoreSubtasks) {
             int nextSubtaskIndex = myTask.getActiveSubtaskIndex() + 1;
index 92cc5aff9283e77ff68c00c9806a39dd9fe97b3d..520e5d87d2cfba49d362225e07c2ee9a1ac17c40 100644 (file)
@@ -114,16 +114,19 @@ public class StudyCheckUtils {
 
   public static void runSmartTestProcess(@NotNull final VirtualFile taskDir,
                                          @NotNull final StudyTestRunner testRunner,
-                                         final String taskFileName,
+                                         @NotNull 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);
+    Pair<VirtualFile, TaskFile> pair = getCopyWithAnswers(taskDir, virtualFile, taskFile);
+    if (pair == null) {
+      return;
+    }
+    VirtualFile answerFile = pair.getFirst();
+    TaskFile answerTaskFile = pair.getSecond();
     for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) {
       final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
       if (document == null) {
@@ -136,36 +139,34 @@ public class StudyCheckUtils {
   }
 
 
-  private static VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
+  private static Pair<VirtualFile, TaskFile> getCopyWithAnswers(@NotNull final VirtualFile taskDir,
                                                 @NotNull final VirtualFile file,
-                                                @NotNull final TaskFile source,
-                                                @NotNull TaskFile target) {
-    VirtualFile copy = null;
+                                                @NotNull final TaskFile source) {
     try {
-
-      copy = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension());
+      VirtualFile answerFile = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension());
       final FileDocumentManager documentManager = FileDocumentManager.getInstance();
-      final Document document = documentManager.getDocument(copy);
+      final Document document = documentManager.getDocument(answerFile);
       if (document != null) {
-        target = source.getTask().copy().getTaskFile(file.getName());
-        if (target == null) {
-          return copy;
+        TaskFile answerTaskFile = source.getTask().copy().getTaskFile(file.getName());
+        if (answerTaskFile == null) {
+          return null;
         }
-        EduDocumentListener listener = new EduDocumentListener(target);
+        EduDocumentListener listener = new EduDocumentListener(answerTaskFile);
         document.addDocumentListener(listener);
-        for (AnswerPlaceholder answerPlaceholder : target.getActivePlaceholders()) {
+        for (AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) {
           final int start = answerPlaceholder.getOffset();
           final int end = start + answerPlaceholder.getRealLength();
           final String text = answerPlaceholder.getPossibleAnswer();
           document.replaceString(start, end, text);
         }
         ApplicationManager.getApplication().runWriteAction(() -> documentManager.saveDocument(document));
+        return Pair.create(answerFile, answerTaskFile);
       }
     }
     catch (IOException e) {
       LOG.error(e);
     }
-    return copy;
+    return null;
   }
 
 
index 48ff8e48b24de9f80571bfbe3cc5b20381cb32df..11b94b633933bc199d78d0074796593f62adcf37 100644 (file)
@@ -50,8 +50,10 @@ public class StudySmartChecker {
       if (windowDocument != null) {
         final File resourceFile =
           StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask());
-        final TaskFile windowTaskFile = new TaskFile();
-        TaskFile.copy(answerTaskFile, windowTaskFile);
+        TaskFile windowTaskFile = answerTaskFile.getTask().copy().getTaskFile(virtualFile.getName());
+        if (windowTaskFile == null) {
+          return;
+        }
         EduDocumentListener listener = new EduDocumentListener(windowTaskFile);
         windowDocument.addDocumentListener(listener);
         int start = placeholder.getOffset();
index 7d29f15b7e71f628824af3e26cca63562a3bb9b9..6d05809fcba02dadabd58bfe6fac81642b64d581 100644 (file)
@@ -16,6 +16,7 @@ import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholderSubtaskInfo;
 import com.jetbrains.edu.learning.courseFormat.TaskFile;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 import java.util.List;
@@ -37,7 +38,8 @@ public class EduAnswerPlaceholderPainter {
     textAttributes.setEffectColor(color);
     if (placeholder.isActive()) {
       drawAnswerPlaceholder(editor, placeholder, textAttributes, PLACEHOLDERS_LAYER);
-    } else if (!placeholder.getUseLength()) {
+    }
+    else if (!placeholder.getUseLength()) {
       int offset = placeholder.getOffset();
       drawAnswerPlaceholderFromPrevStep(editor, offset, offset + placeholder.getVisibleLength(placeholder.getActiveSubtaskIndex()));
     }
@@ -45,7 +47,7 @@ public class EduAnswerPlaceholderPainter {
 
   public static void drawAnswerPlaceholder(@NotNull Editor editor,
                                            @NotNull AnswerPlaceholder placeholder,
-                                           TextAttributes textAttributes,
+                                           @Nullable TextAttributes textAttributes,
                                            int placeholdersLayer) {
     int startOffset = placeholder.getOffset();
     if (startOffset == -1) {
@@ -69,16 +71,15 @@ public class EduAnswerPlaceholderPainter {
   public static void drawAnswerPlaceholder(@NotNull Editor editor,
                                            int start,
                                            int end,
-                                           TextAttributes textAttributes,
+                                           @Nullable TextAttributes textAttributes,
                                            int placeholdersLayer) {
     final Project project = editor.getProject();
     assert project != null;
     if (start == -1) {
       return;
     }
-    RangeHighlighter
-      highlighter = editor.getMarkupModel().addRangeHighlighter(start, end, placeholdersLayer,
-                                                                textAttributes, HighlighterTargetArea.EXACT_RANGE);
+    RangeHighlighter highlighter = editor.getMarkupModel().addRangeHighlighter(start, end, placeholdersLayer,
+                                                                               textAttributes, HighlighterTargetArea.EXACT_RANGE);
     highlighter.setGreedyToLeft(true);
     highlighter.setGreedyToRight(true);
   }
index ab23d693e6a3e6db2ed45bf19487d3600d352e08..6cfb41eeb03bbccea0ff0732b740a375386ffcc5 100644 (file)
@@ -24,7 +24,8 @@ public class AnswerPlaceholder {
   @SerializedName("offset")
   @Expose private int myOffset = -1;
 
-  @Expose private int length = -1;
+  @SerializedName("length")
+  @Expose private int myLength = -1;
 
   private int myIndex = -1;
   private MyInitialState myInitialState;
@@ -41,7 +42,7 @@ public class AnswerPlaceholder {
   public void initAnswerPlaceholder(final TaskFile file, boolean isRestarted) {
     setTaskFile(file);
     if (!isRestarted) {
-      setInitialState(new MyInitialState(myOffset, length));
+      setInitialState(new MyInitialState(myOffset, myLength));
       for (AnswerPlaceholderSubtaskInfo info : getSubtaskInfos().values()) {
         info.setStatus(file.getTask().getStatus());
       }
@@ -60,11 +61,11 @@ public class AnswerPlaceholder {
    * in actions {@link AnswerPlaceholder#getRealLength()} should be used
    */
   public int getLength() {
-    return length;
+    return myLength;
   }
 
   public void setLength(int length) {
-    this.length = length;
+    myLength = length;
   }
 
   @Transient
@@ -114,7 +115,7 @@ public class AnswerPlaceholder {
    */
   public void reset() {
     myOffset = myInitialState.getOffset();
-    length = myInitialState.getLength();
+    myLength = myInitialState.getLength();
   }
 
   @Transient
@@ -237,13 +238,13 @@ public class AnswerPlaceholder {
     int minIndex = Collections.min(mySubtaskInfos.keySet());
     AnswerPlaceholderSubtaskInfo minInfo = mySubtaskInfos.get(minIndex);
     if (minIndex == subtaskIndex) {
-      return getUseLength() ? length : minInfo.getPossibleAnswer().length();
+      return getUseLength() ? myLength : minInfo.getPossibleAnswer().length();
     }
     if (minIndex > subtaskIndex) {
       return minInfo.isNeedInsertText() ? 0 : minInfo.getPlaceholderText().length();
     }
     int maxIndex = Collections.max(ContainerUtil.filter(mySubtaskInfos.keySet(), i -> i <= subtaskIndex));
-    return getUseLength() ? length : mySubtaskInfos.get(maxIndex).getPossibleAnswer().length();
+    return getUseLength() ? myLength : mySubtaskInfos.get(maxIndex).getPossibleAnswer().length();
   }
 
   public void switchSubtask(@NotNull Project project, @NotNull Document document, int fromSubtask, int toSubtask) {
index 33b7cda8de1d4fc14e9a1d64925ed6f882ddb6c9..3c3c931d9d4ecde178ba6935169530f5e2323984 100644 (file)
@@ -15,7 +15,7 @@ public class AnswerPlaceholderSubtaskInfo {
   @Expose private List<String> myHints = new ArrayList<>();
 
   @SerializedName("possible_answer")
-  @Expose private String possibleAnswer = "";
+  @Expose private String myPossibleAnswer = "";
 
   @SerializedName("placeholder_text")
   @Expose private String myPlaceholderText;
@@ -60,11 +60,11 @@ public class AnswerPlaceholderSubtaskInfo {
   }
 
   public String getPossibleAnswer() {
-    return possibleAnswer;
+    return myPossibleAnswer;
   }
 
   public void setPossibleAnswer(String possibleAnswer) {
-    this.possibleAnswer = possibleAnswer;
+    myPossibleAnswer = possibleAnswer;
   }
 
   public String getPlaceholderText() {
index 4358ee62d62cf50d67580314679d1cadf85c07c6..cd6ec7377689de51cfdd01489dd0956080061bed 100644 (file)
@@ -3,6 +3,7 @@ package com.jetbrains.edu.learning.courseFormat;
 import com.google.gson.annotations.Expose;
 import com.google.gson.annotations.SerializedName;
 import com.intellij.util.xmlb.annotations.Transient;
+import com.jetbrains.edu.learning.StudyUtils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -87,18 +88,7 @@ public class TaskFile {
    */
   @Nullable
   public AnswerPlaceholder getAnswerPlaceholder(int offset) {
-    return getAnswerPlaceholder(offset, getActivePlaceholders());
-  }
-
-  @Nullable public AnswerPlaceholder getAnswerPlaceholder(int offset, List<AnswerPlaceholder> placeholders) {
-    for (AnswerPlaceholder placeholder : placeholders) {
-      int placeholderStart = placeholder.getOffset();
-      int placeholderEnd = placeholderStart + placeholder.getRealLength();
-      if (placeholderStart <= offset && offset <= placeholderEnd) {
-        return placeholder;
-      }
-    }
-    return null;
+    return StudyUtils.getAnswerPlaceholder(offset, getActivePlaceholders());
   }
 
   public boolean isTrackLengths() {
index 748893afaacfaac99650f10d6341e55c49fd68db..525719dd95de1157c44263cf3aa5f6f145cff6cb 100644 (file)
@@ -109,22 +109,22 @@ public class StudyNavigator {
 
   @Nullable
   public static VirtualFile getFileToActivate(@NotNull Project project, Map<String, TaskFile> nextTaskFiles, VirtualFile taskDir) {
-    VirtualFile shouldBeActive = null;
+    VirtualFile fileToActivate = null;
     for (Map.Entry<String, TaskFile> entry : nextTaskFiles.entrySet()) {
       String name = entry.getKey();
       TaskFile taskFile = entry.getValue();
       VirtualFile srcDir = taskDir.findChild(EduNames.SRC);
       VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name);
       if (vf != null) {
-        if (shouldBeActive != null) {
+        if (fileToActivate != null) {
           FileEditorManager.getInstance(project).openFile(vf, true);
         }
-        if (shouldBeActive == null && !taskFile.getActivePlaceholders().isEmpty()) {
-          shouldBeActive = vf;
+        if (fileToActivate == null && !taskFile.getActivePlaceholders().isEmpty()) {
+          fileToActivate = vf;
         }
       }
     }
-    return shouldBeActive != null ? shouldBeActive : getFirstTaskFile(taskDir, project);
+    return fileToActivate != null ? fileToActivate : getFirstTaskFile(taskDir, project);
   }
 
   @Nullable
@@ -178,9 +178,10 @@ public class StudyNavigator {
       FileEditorManager.getInstance(project).openFile(virtualFile, true);
     }
     EduUsagesCollector.taskNavigation();
-    VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir);
-
-    updateProjectView(project, shouldBeActive);
+    VirtualFile fileToActivate = getFileToActivate(project, nextTaskFiles, taskDir);
+    if (fileToActivate != null) {
+      updateProjectView(project, fileToActivate);
+    }
 
     StudyUtils.selectFirstAnswerPlaceholder(StudyUtils.getSelectedStudyEditor(project), project);
     ToolWindow runToolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN);
@@ -189,38 +190,37 @@ public class StudyNavigator {
     }
   }
 
-  private static void updateProjectView(@NotNull Project project, VirtualFile shouldBeActive) {
+  private static void updateProjectView(@NotNull Project project, @NotNull VirtualFile fileToActivate) {
     JTree tree = ProjectView.getInstance(project).getCurrentProjectViewPane().getTree();
-    if (shouldBeActive != null) {
-      ProjectView.getInstance(project).selectCB(shouldBeActive, shouldBeActive, false).doWhenDone(() -> {
-        List<TreePath> paths = TreeUtil.collectExpandedPaths(tree);
-        List<TreePath> toCollapse = new ArrayList<>();
-        TreePath selectedPath = tree.getSelectionPath();
-        for (TreePath treePath : paths) {
-          if (treePath.isDescendant(selectedPath)) {
-            continue;
-          }
-          if (toCollapse.isEmpty()) {
-            toCollapse.add(treePath);
-            continue;
+    ProjectView.getInstance(project).selectCB(fileToActivate, fileToActivate, false).doWhenDone(() -> {
+      List<TreePath> paths = TreeUtil.collectExpandedPaths(tree);
+      List<TreePath> toCollapse = new ArrayList<>();
+      TreePath selectedPath = tree.getSelectionPath();
+      for (TreePath treePath : paths) {
+        if (treePath.isDescendant(selectedPath)) {
+          continue;
+        }
+        if (toCollapse.isEmpty()) {
+          toCollapse.add(treePath);
+          continue;
+        }
+        for (int i = 0; i < toCollapse.size(); i++) {
+          TreePath path = toCollapse.get(i);
+          if (treePath.isDescendant(path)) {
+            toCollapse.set(i, treePath);
           }
-          for (int i = 0; i < toCollapse.size(); i++) {
-            TreePath path = toCollapse.get(i);
-            if (treePath.isDescendant(path)) {
-              toCollapse.set(i, treePath);
-            }  else {
-              if (!path.isDescendant(treePath)) {
-                toCollapse.add(treePath);
-              }
+          else {
+            if (!path.isDescendant(treePath)) {
+              toCollapse.add(treePath);
             }
           }
         }
-        for (TreePath path : toCollapse) {
-          tree.collapsePath(path);
-          tree.fireTreeCollapsed(path);
-        }
-      });
-      FileEditorManager.getInstance(project).openFile(shouldBeActive, true);
-    }
+      }
+      for (TreePath path : toCollapse) {
+        tree.collapsePath(path);
+        tree.fireTreeCollapsed(path);
+      }
+    });
+    FileEditorManager.getInstance(project).openFile(fileToActivate, true);
   }
 }
index 4810bab66e95d82aea08a99b6734d67d4e0392b1..03b81f24c40df61fe663df9c632563298db8959b 100644 (file)
@@ -41,7 +41,6 @@ public class LessonDirectoryNode extends StudyDirectoryNode {
     JBColor color = isSolved ? JBColor.BLACK : LIGHT_GREEN;
     Icon icon = isSolved ? InteractiveLearningIcons.Lesson : InteractiveLearningIcons.LessonCompl;
     updatePresentation(data, myLesson.getName(), color, icon, null);
-
   }
 
   @Override
index 2fe31bbbe410e41cf2a79129b555000b67a63a8d..13184eea6432082d71c0ecdaf81d1aa2c43de9a5 100644 (file)
@@ -119,13 +119,14 @@ public class EduStepicConnector {
     final URI url;
     try {
       url = new URIBuilder(EduStepicNames.COURSES).addParameter("is_idea_compatible", "true").
-          addParameter("page", String.valueOf(pageNumber)).build();
+        addParameter("page", String.valueOf(pageNumber)).build();
     }
     catch (URISyntaxException e) {
       LOG.error(e.getMessage());
       return false;
     }
-    final StepicWrappers.CoursesContainer coursesContainer = EduStepicClient.getFromStepic(url.toString(), StepicWrappers.CoursesContainer.class);
+    final StepicWrappers.CoursesContainer coursesContainer =
+      EduStepicClient.getFromStepic(url.toString(), StepicWrappers.CoursesContainer.class);
     addAvailableCourses(result, coursesContainer);
     return coursesContainer.meta.containsKey("has_next") && coursesContainer.meta.get("has_next") == Boolean.TRUE;
   }
@@ -167,7 +168,8 @@ public class EduStepicConnector {
     try {
       Integer version = Integer.valueOf(versionString);
       return version <= CURRENT_VERSION;
-    } catch (NumberFormatException e) {
+    }
+    catch (NumberFormatException e) {
       LOG.info("Wrong version format", e);
       return false;
     }
@@ -180,7 +182,7 @@ public class EduStepicConnector {
     course.setAdaptive(info.isAdaptive());
     course.setId(info.getId());
     course.setUpdateDate(getCourseUpdateDate(info.getId()));
-    
+
     if (!course.isAdaptive()) {
       String courseType = info.getType();
       course.setName(info.getName());
@@ -216,7 +218,8 @@ public class EduStepicConnector {
 
   public static List<Lesson> getLessons(int sectionId) throws IOException {
     final StepicWrappers.SectionContainer
-      sectionContainer = EduStepicClient.getFromStepic(EduStepicNames.SECTIONS + String.valueOf(sectionId), StepicWrappers.SectionContainer.class);
+      sectionContainer =
+      EduStepicClient.getFromStepic(EduStepicNames.SECTIONS + String.valueOf(sectionId), StepicWrappers.SectionContainer.class);
     List<Integer> unitIds = sectionContainer.sections.get(0).units;
     final List<Lesson> lessons = new ArrayList<>();
     for (Integer unitId : unitIds) {
@@ -224,14 +227,16 @@ public class EduStepicConnector {
         unit = EduStepicClient.getFromStepic(EduStepicNames.UNITS + "/" + String.valueOf(unitId), StepicWrappers.UnitContainer.class);
       int lessonID = unit.units.get(0).lesson;
       StepicWrappers.LessonContainer
-        lessonContainer = EduStepicClient.getFromStepic(EduStepicNames.LESSONS + String.valueOf(lessonID), StepicWrappers.LessonContainer.class);
+        lessonContainer =
+        EduStepicClient.getFromStepic(EduStepicNames.LESSONS + String.valueOf(lessonID), StepicWrappers.LessonContainer.class);
       Lesson lesson = lessonContainer.lessons.get(0);
       lesson.taskList = new ArrayList<>();
       for (Integer s : lesson.steps) {
         createTask(lesson, s);
       }
-      if (!lesson.taskList.isEmpty())
+      if (!lesson.taskList.isEmpty()) {
         lessons.add(lesson);
+      }
     }
 
     return lessons;
@@ -260,7 +265,8 @@ public class EduStepicConnector {
   }
 
   public static StepicWrappers.StepSource getStep(Integer step) throws IOException {
-    return EduStepicClient.getFromStepic(EduStepicNames.STEPS + "/" + String.valueOf(step), StepicWrappers.StepContainer.class).steps.get(0);
+    return EduStepicClient.getFromStepic(EduStepicNames.STEPS + "/" + String.valueOf(step), StepicWrappers.StepContainer.class).steps
+      .get(0);
   }
 
   public static void postAttempt(@NotNull final Task task, boolean passed, @NotNull final Project project) {
@@ -282,7 +288,8 @@ public class EduStepicConnector {
       if (statusLine.getStatusCode() != HttpStatus.SC_CREATED) {
         LOG.warn("Failed to make attempt " + attemptResponseString);
       }
-      final StepicWrappers.AttemptWrapper.Attempt attempt = new Gson().fromJson(attemptResponseString, StepicWrappers.AttemptContainer.class).attempts.get(0);
+      final StepicWrappers.AttemptWrapper.Attempt attempt =
+        new Gson().fromJson(attemptResponseString, StepicWrappers.AttemptContainer.class).attempts.get(0);
 
       final Map<String, TaskFile> taskFiles = task.getTaskFiles();
       final ArrayList<StepicWrappers.SolutionFile> files = new ArrayList<>();
index 6748590975f13c553b5ef9cbcab21f71b30969db..fd731c7cbd5914e1526846cc2a844313e2d9fff7 100644 (file)
@@ -2,16 +2,15 @@ package com.jetbrains.edu.coursecreator;
 
 import com.intellij.ide.fileTemplates.FileTemplate;
 import com.intellij.ide.fileTemplates.FileTemplateManager;
+import com.intellij.ide.fileTemplates.FileTemplateUtil;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
 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.DocumentUtil;
-import com.jetbrains.edu.learning.StudyTaskManager;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiManager;
 import com.jetbrains.edu.learning.core.EduNames;
 import com.jetbrains.edu.learning.courseFormat.Task;
 import org.jetbrains.annotations.NotNull;
@@ -69,38 +68,23 @@ public class PyCCLanguageManager implements CCLanguageManager {
     if (taskDir == null) {
       return;
     }
-
-    int prevSubtaskIndex = task.getLastSubtaskIndex();
-    String name = prevSubtaskIndex == 0 ? EduNames.TESTS_FILE : getSubtaskTestsFileName(prevSubtaskIndex);
-    VirtualFile testsFile = taskDir.findChild(name);
-    if (testsFile == null) {
-      return;
-    }
-    Document document = FileDocumentManager.getInstance().getDocument(testsFile);
-    if (document == null) {
-      return;
-    }
-    CharSequence prevTestText = document.getCharsSequence();
-    int nextSubtaskIndex = prevSubtaskIndex + 1;
+    int nextSubtaskIndex = task.getLastSubtaskIndex() + 1;
     String nextSubtaskTestsFileName = getSubtaskTestsFileName(nextSubtaskIndex);
     ApplicationManager.getApplication().runWriteAction(() -> {
       try {
-        VirtualFile nextSubtaskTestsFile = taskDir.createChildData(this, nextSubtaskTestsFileName);
-        StudyTaskManager.getInstance(project).addInvisibleFiles(nextSubtaskTestsFile.getPath());
-        Document nextSubtaskDocument = FileDocumentManager.getInstance().getDocument(nextSubtaskTestsFile);
-        if (nextSubtaskDocument == null) {
+        PsiDirectory taskPsiDir = PsiManager.getInstance(project).findDirectory(taskDir);
+        FileTemplate testsTemplate = getTestsTemplate(project);
+        if (taskPsiDir == null || testsTemplate == null) {
           return;
         }
-        String header = "# This is test for subtask " + nextSubtaskIndex + ". We've already copied tests from previous subtask here.\n\n";
-        DocumentUtil.writeInRunUndoTransparentAction(() -> {
-          nextSubtaskDocument.insertString(0, header);
-          nextSubtaskDocument.insertString(header.length(), prevTestText);
-          FileDocumentManager.getInstance().saveDocument(nextSubtaskDocument);
-        });
+        FileTemplateUtil.createFromTemplate(testsTemplate, nextSubtaskTestsFileName, null, taskPsiDir);
       }
       catch (IOException e) {
         LOG.error(e);
       }
+      catch (Exception e) {
+        LOG.error(e);
+      }
     });
   }