mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
Conflicts: python/edu/learn-python/resources/courses/introduction_course.zip
This commit is contained in:
-1
@@ -54,7 +54,6 @@ public class SimpleAccessorReferenceSearcher extends QueryExecutorBase<PsiRefere
|
||||
for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) {
|
||||
additional = additional.union(provider.getScope(method.getProject()));
|
||||
}
|
||||
assert propertyName != null;
|
||||
final SearchScope propScope = scope.intersectWith(method.getUseScope()).intersectWith(additional);
|
||||
collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, method);
|
||||
}
|
||||
|
||||
@@ -246,6 +246,15 @@ public class UsageInfo {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
PsiReference reference = getReference();
|
||||
if (reference == null) {
|
||||
return super.toString();
|
||||
}
|
||||
return reference.getCanonicalText() + " (" + reference.getClass() + ")";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiFile getFile() {
|
||||
return mySmartPointer.getContainingFile();
|
||||
|
||||
@@ -54,6 +54,7 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
|
||||
super();
|
||||
setLayout(new BorderLayout());
|
||||
myRepositoryCheckbox = new JBCheckBox();
|
||||
myRepositoryCheckbox.setFocusable(false);
|
||||
myRepositoryCheckbox.setOpaque(false);
|
||||
myRepositoryCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@@ -77,15 +78,17 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
|
||||
protected void updateBorder(@NotNull final EditorEx editor) {
|
||||
}
|
||||
};
|
||||
myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder());//getTextFieldBorder());
|
||||
myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder());
|
||||
myDestBranchTextField.setOneLineMode(true);
|
||||
myDestBranchTextField.setOpaque(true);
|
||||
myDestBranchTextField.addFocusListener(new FocusAdapter() {
|
||||
FocusAdapter focusListener = new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
myDestBranchTextField.selectAll();
|
||||
}
|
||||
});
|
||||
};
|
||||
myDestBranchTextField.addFocusListener(focusListener);
|
||||
addFocusListener(focusListener);
|
||||
|
||||
myTextRenderer = new ColoredTreeCellRenderer() {
|
||||
public void customizeCellRenderer(@NotNull JTree tree,
|
||||
|
||||
+78
-7
@@ -18,8 +18,10 @@ package com.intellij.xdebugger.impl.evaluate;
|
||||
import com.intellij.openapi.editor.EditorLinePainter;
|
||||
import com.intellij.openapi.editor.LineExtensionInfo;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleColoredText;
|
||||
@@ -30,15 +32,13 @@ import com.intellij.xdebugger.impl.ui.tree.nodes.XValueTextRendererImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class XDebuggerEditorLinePainter extends EditorLinePainter {
|
||||
public static final Key<Map<Variable, VariableValue>> CACHE = Key.create("debug.frame");
|
||||
@Override
|
||||
public Collection<LineExtensionInfo> getLineExtensions(@NotNull Project project, @NotNull VirtualFile file, int lineNumber) {
|
||||
if (!Registry.is("ide.debugger.inline")) {
|
||||
@@ -46,6 +46,11 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
|
||||
}
|
||||
|
||||
Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = project.getUserData(XVariablesView.DEBUG_VARIABLES);
|
||||
Map<Variable, VariableValue> oldValues = project.getUserData(CACHE);
|
||||
if (oldValues == null) {
|
||||
oldValues = new HashMap<Variable, VariableValue>();
|
||||
project.putUserData(CACHE, oldValues);
|
||||
}
|
||||
if (map != null) {
|
||||
Set<XValueNodeImpl> values = map.get(Pair.create(file, lineNumber));
|
||||
if (values != null && !values.isEmpty()) {
|
||||
@@ -61,9 +66,29 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
|
||||
presentation.renderValue(renderer);
|
||||
}
|
||||
final Color color = new JBColor(new Color(61, 128, 101), new Color(61, 128, 101));
|
||||
result.add(new LineExtensionInfo(" " + value.getName() + ": ", color, null, null, Font.PLAIN));
|
||||
for (String s : text.getTexts()) {
|
||||
result.add(new LineExtensionInfo(s, color, null, null, Font.PLAIN));
|
||||
final String name = value.getName();
|
||||
result.add(new LineExtensionInfo(" " + name + ": ", color, null, null, Font.PLAIN));
|
||||
|
||||
Variable var = new Variable(name, value.hashCode(), lineNumber);
|
||||
VariableValue variableValue = oldValues.get(var);
|
||||
if (variableValue == null) {
|
||||
variableValue = new VariableValue(text.toString(), null, value.hashCode());
|
||||
oldValues.put(var, variableValue);
|
||||
}
|
||||
if (variableValue.valueNodeHashCode != value.hashCode()) {
|
||||
variableValue.old = variableValue.actual;
|
||||
variableValue.actual = text.toString();
|
||||
variableValue.valueNodeHashCode = value.hashCode();
|
||||
}
|
||||
|
||||
if (!variableValue.isChanged()) {
|
||||
for (String s : text.getTexts()) {
|
||||
result.add(new LineExtensionInfo(s, color, null, null, Font.PLAIN));
|
||||
}
|
||||
} else {
|
||||
for (String s : text.getTexts()) {
|
||||
result.add(new LineExtensionInfo(s, new JBColor(new Color(202, 128, 33), new Color(116, 114, 4)), null, null, Font.BOLD));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -72,4 +97,50 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static class Variable {
|
||||
private int lineNumber;
|
||||
private String name;
|
||||
|
||||
public Variable(String name, int nodeHashCode, int lineNumber) {
|
||||
this.lineNumber = lineNumber;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Variable variable = (Variable)o;
|
||||
|
||||
if (lineNumber != variable.lineNumber) return false;
|
||||
if (!name.equals(variable.name)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = lineNumber;
|
||||
result = 31 * result + name.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static class VariableValue {
|
||||
private String actual;
|
||||
private String old;
|
||||
private int valueNodeHashCode;
|
||||
|
||||
public VariableValue(String actual, String old, int valueNodeHashCode) {
|
||||
this.actual = actual;
|
||||
this.old = old;
|
||||
this.valueNodeHashCode = valueNodeHashCode;
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
return old != null && !StringUtil.equals(actual, old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class HgChangeProvider implements ChangeProvider {
|
||||
|
||||
public void getChanges(VcsDirtyScope dirtyScope, ChangelistBuilder builder,
|
||||
ProgressIndicator progress, ChangeListManagerGate addGate) throws VcsException {
|
||||
if (myProject.isDisposed()) return;
|
||||
final Collection<HgChange> changes = new HashSet<HgChange>();
|
||||
changes.addAll(process(builder, dirtyScope.getRecursivelyDirtyDirectories()));
|
||||
changes.addAll(process(builder, dirtyScope.getDirtyFiles()));
|
||||
|
||||
@@ -366,7 +366,7 @@ private layoutWin(Map args, String target) {
|
||||
winScripts(target, ch, "pycharm.bat", args)
|
||||
winVMOptions(target, null, "pycharm.exe")
|
||||
|
||||
ant.copy(file: "$home/python/help/pycharm-eduhelp.jar ", todir: "$target/help", failonerror: false)
|
||||
ant.copy(file: "$home/python/help/pycharm-eduhelp.jar", todir: "$target/help", failonerror: false)
|
||||
}
|
||||
|
||||
private layoutUnix(Map args, String target) {
|
||||
@@ -383,7 +383,7 @@ private layoutUnix(Map args, String target) {
|
||||
unixScripts(target, ch, "pycharm.sh", args)
|
||||
unixVMOptions(target, "pycharm")
|
||||
|
||||
ant.copy(file: "$home/python/help/pycharm-eduhelp.jar ", todir: "$target/help", failonerror: false)
|
||||
ant.copy(file: "$home/python/help/pycharm-eduhelp.jar", todir: "$target/help", failonerror: false)
|
||||
}
|
||||
|
||||
private layoutMac(Map _args, String target) {
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,56 @@
|
||||
package com.jetbrains.python.edu;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.python.edu.course.Task;
|
||||
import com.jetbrains.python.edu.course.TaskFile;
|
||||
import com.jetbrains.python.edu.editor.StudyEditor;
|
||||
|
||||
public class StudyState {
|
||||
private final StudyEditor myStudyEditor;
|
||||
private final Editor myEditor;
|
||||
private final TaskFile myTaskFile;
|
||||
private final VirtualFile myVirtualFile;
|
||||
private final Task myTask;
|
||||
private final VirtualFile myTaskDir;
|
||||
|
||||
public StudyState(StudyEditor studyEditor) {
|
||||
myStudyEditor = studyEditor;
|
||||
myEditor = studyEditor != null ? studyEditor.getEditor() : null;
|
||||
myTaskFile = studyEditor != null ? studyEditor.getTaskFile() : null;
|
||||
myVirtualFile = myEditor != null ? FileDocumentManager.getInstance().getFile(myEditor.getDocument()) : null;
|
||||
myTaskDir = myVirtualFile != null ? myVirtualFile.getParent() : null;
|
||||
myTask = myTaskFile != null ? myTaskFile.getTask() : null;
|
||||
}
|
||||
|
||||
public StudyEditor getStudyEditor() {
|
||||
return myStudyEditor;
|
||||
}
|
||||
|
||||
public Editor getEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
public TaskFile getTaskFile() {
|
||||
return myTaskFile;
|
||||
}
|
||||
|
||||
public VirtualFile getVirtualFile() {
|
||||
return myVirtualFile;
|
||||
}
|
||||
|
||||
public Task getTask() {
|
||||
return myTask;
|
||||
}
|
||||
|
||||
public VirtualFile getTaskDir() {
|
||||
return myTaskDir;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return myStudyEditor != null && myEditor != null &&
|
||||
myTaskFile != null && myVirtualFile != null &&
|
||||
myTask != null && myTaskDir != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.jetbrains.python.edu;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.python.edu.course.Course;
|
||||
import com.jetbrains.python.edu.course.Task;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class StudyTestRunner {
|
||||
public static final String TEST_OK = "#study_plugin test OK";
|
||||
private static final String TEST_FAILED = "#study_plugin FAILED + ";
|
||||
private static final String PYTHONPATH = "PYTHONPATH";
|
||||
private static final Logger LOG = Logger.getInstance(StudyTestRunner.class);
|
||||
private final Task myTask;
|
||||
private final VirtualFile myTaskDir;
|
||||
|
||||
public StudyTestRunner(Task task, VirtualFile taskDir) {
|
||||
myTask = task;
|
||||
myTaskDir = taskDir;
|
||||
}
|
||||
|
||||
public 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();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public 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);
|
||||
}
|
||||
finally {
|
||||
StudyUtils.closeSilently(testOutputReader);
|
||||
}
|
||||
return TEST_OK;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.jetbrains.python.edu;
|
||||
import com.intellij.ide.SaveAndSyncHandlerImpl;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
@@ -10,12 +11,12 @@ import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.edu.course.TaskFile;
|
||||
import com.jetbrains.python.edu.course.TaskWindow;
|
||||
import com.jetbrains.python.edu.course.*;
|
||||
import com.jetbrains.python.edu.editor.StudyEditor;
|
||||
import com.jetbrains.python.edu.ui.StudyToolWindowFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -119,14 +120,18 @@ public class StudyUtils {
|
||||
}
|
||||
|
||||
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||
public static VirtualFile flushWindows(Document document, TaskFile taskFile, VirtualFile file) {
|
||||
public static VirtualFile flushWindows(TaskFile taskFile, VirtualFile file) {
|
||||
VirtualFile taskDir = file.getParent();
|
||||
VirtualFile fileWindows = null;
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(file);
|
||||
if (document == null) {
|
||||
LOG.debug("Couldn't flush windows");
|
||||
return null;
|
||||
}
|
||||
if (taskDir != null) {
|
||||
String name = file.getNameWithoutExtension() + "_windows";
|
||||
PrintWriter printWriter = null;
|
||||
try {
|
||||
|
||||
fileWindows = taskDir.createChildData(taskFile, name);
|
||||
printWriter = new PrintWriter(new FileOutputStream(fileWindows.getPath()));
|
||||
for (TaskWindow taskWindow : taskFile.getTaskWindows()) {
|
||||
@@ -137,6 +142,12 @@ public class StudyUtils {
|
||||
String windowDescription = document.getText(new TextRange(start, start + taskWindow.getLength()));
|
||||
printWriter.println("#study_plugin_window = " + windowDescription);
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
@@ -148,4 +159,27 @@ public class StudyUtils {
|
||||
}
|
||||
return fileWindows;
|
||||
}
|
||||
|
||||
public static void deleteFile(VirtualFile file) {
|
||||
try {
|
||||
file.delete(StudyUtils.class);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static File copyResourceFile(String sourceName, String copyName, Project project, Task task)
|
||||
throws IOException {
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
Course course = taskManager.getCourse();
|
||||
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, copyName);
|
||||
FileUtil.copy(new File(pathToResource, sourceName), resourceFile);
|
||||
return resourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
+147
-226
@@ -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,94 +12,80 @@ 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.vfs.VirtualFile;
|
||||
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.ArrayList;
|
||||
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;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
finally {
|
||||
StudyUtils.closeSilently(testOutputReader);
|
||||
}
|
||||
return TEST_OK;
|
||||
StudyUtils.flushWindows(taskFile, virtualFile);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
|
||||
if (fileEditor instanceof StudyEditor) {
|
||||
StudyEditor studyEditor = (StudyEditor)fileEditor;
|
||||
taskFile.drawAllWindows(studyEditor.getEditor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void check(@NotNull final Project project) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
@@ -108,188 +93,126 @@ 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);
|
||||
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);
|
||||
}
|
||||
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!", MessageType.INFO.getPopupBackground(), project);
|
||||
return;
|
||||
}
|
||||
currentTask.setStatus(StudyStatus.Failed, oldStatus);
|
||||
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);
|
||||
}
|
||||
}
|
||||
StudyUtils.updateStudyToolWindow(project);
|
||||
createTestResultPopUp(failedMessage, MessageType.ERROR.getPopupBackground(), 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);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
FileEditorManager.getInstance(project).openFile(fileToNavigate, true);
|
||||
IdeFocusManager.getInstance(project).requestFocus(editor.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;
|
||||
}
|
||||
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) {
|
||||
@@ -316,8 +239,6 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -11,6 +11,8 @@ 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.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.jetbrains.python.edu.StudyTaskManager;
|
||||
import com.jetbrains.python.edu.course.Lesson;
|
||||
import com.jetbrains.python.edu.course.Task;
|
||||
@@ -82,6 +84,7 @@ abstract public class StudyTaskNavigationAction extends DumbAwareAction {
|
||||
if (shouldBeActive != null) {
|
||||
FileEditorManager.getInstance(project).openFile(shouldBeActive, true);
|
||||
}
|
||||
ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN).hide(null);
|
||||
}
|
||||
|
||||
protected abstract JButton getButton(StudyEditor selectedStudyEditor);
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
* which is visible to student in project view
|
||||
*/
|
||||
|
||||
public class TaskFile implements Stateful{
|
||||
public class TaskFile implements Stateful {
|
||||
public List<TaskWindow> taskWindows = new ArrayList<TaskWindow>();
|
||||
private Task myTask;
|
||||
@Transient
|
||||
@@ -217,12 +217,30 @@ public class TaskFile implements Stateful{
|
||||
public void navigateToFirstTaskWindow(@NotNull final Editor editor) {
|
||||
if (!taskWindows.isEmpty()) {
|
||||
TaskWindow firstTaskWindow = StudyUtils.getFirst(taskWindows);
|
||||
mySelectedTaskWindow = firstTaskWindow;
|
||||
LogicalPosition taskWindowStart = new LogicalPosition(firstTaskWindow.getLine(), firstTaskWindow.getStart());
|
||||
editor.getCaretModel().moveToLogicalPosition(taskWindowStart);
|
||||
int startOffset = firstTaskWindow.getRealStartOffset(editor.getDocument());
|
||||
int endOffset = startOffset + firstTaskWindow.getLength();
|
||||
editor.getSelectionModel().setSelection(startOffset, endOffset);
|
||||
navigateToTaskWindow(editor, firstTaskWindow);
|
||||
}
|
||||
}
|
||||
|
||||
private void navigateToTaskWindow(@NotNull final Editor editor, @NotNull final TaskWindow firstTaskWindow) {
|
||||
mySelectedTaskWindow = firstTaskWindow;
|
||||
LogicalPosition taskWindowStart = new LogicalPosition(firstTaskWindow.getLine(), firstTaskWindow.getStart());
|
||||
editor.getCaretModel().moveToLogicalPosition(taskWindowStart);
|
||||
int startOffset = firstTaskWindow.getRealStartOffset(editor.getDocument());
|
||||
int endOffset = startOffset + firstTaskWindow.getLength();
|
||||
editor.getSelectionModel().setSelection(startOffset, endOffset);
|
||||
}
|
||||
|
||||
public void navigateToFirstFailedTaskWindow(@NotNull final Editor editor) {
|
||||
for (TaskWindow taskWindow : taskWindows) {
|
||||
if (taskWindow.getStatus() != StudyStatus.Failed) {
|
||||
continue;
|
||||
}
|
||||
navigateToTaskWindow(editor, taskWindow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasFailedTaskWindows() {
|
||||
return taskWindows.size() > 0 && getStatus() == StudyStatus.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.jetbrains.python.edu.course;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
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.editor.colors.EditorColors;
|
||||
@@ -8,16 +11,27 @@ import com.intellij.openapi.editor.markup.HighlighterLayer;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.jetbrains.python.edu.StudyDocumentListener;
|
||||
import com.jetbrains.python.edu.StudyTestRunner;
|
||||
import com.jetbrains.python.edu.StudyUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Implementation of windows which user should type in
|
||||
*/
|
||||
|
||||
|
||||
public class TaskWindow implements Comparable, Stateful {
|
||||
|
||||
private static final String WINDOW_POSTFIX = "_window.py";
|
||||
private static final Logger LOG = Logger.getInstance(TaskWindow.class);
|
||||
public int line = 0;
|
||||
public int start = 0;
|
||||
public String hint = "";
|
||||
@@ -174,4 +188,55 @@ public class TaskWindow implements Comparable, Stateful {
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public void smartCheck(@NotNull final Project project,
|
||||
@NotNull final VirtualFile answerFile,
|
||||
@NotNull final TaskFile answerTaskFile,
|
||||
@NotNull final TaskFile usersTaskFile,
|
||||
@NotNull final StudyTestRunner testRunner,
|
||||
@NotNull final VirtualFile virtualFile,
|
||||
@NotNull final Document usersDocument) {
|
||||
|
||||
try {
|
||||
VirtualFile windowCopy =
|
||||
answerFile.copy(this, answerFile.getParent(), answerFile.getNameWithoutExtension() + WINDOW_POSTFIX);
|
||||
final FileDocumentManager documentManager = FileDocumentManager.getInstance();
|
||||
final Document windowDocument = documentManager.getDocument(windowCopy);
|
||||
if (windowDocument != null) {
|
||||
File resourceFile = StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask());
|
||||
TaskFile windowTaskFile = new TaskFile();
|
||||
TaskFile.copy(answerTaskFile, windowTaskFile);
|
||||
StudyDocumentListener listener = new StudyDocumentListener(windowTaskFile);
|
||||
windowDocument.addDocumentListener(listener);
|
||||
int start = getRealStartOffset(windowDocument);
|
||||
int end = start + getLength();
|
||||
TaskWindow userTaskWindow = usersTaskFile.getTaskWindows().get(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);
|
||||
}
|
||||
});
|
||||
VirtualFile fileWindows = StudyUtils.flushWindows(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);
|
||||
StudyUtils.deleteFile(windowCopy);
|
||||
StudyUtils.deleteFile(fileWindows);
|
||||
if (!resourceFile.delete()) {
|
||||
LOG.error("failed to delete", resourceFile.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ public class StudyEditor implements TextEditor {
|
||||
private static final String TASK_TEXT_HEADER = "Task Text";
|
||||
private final FileEditor myDefaultEditor;
|
||||
private final JComponent myComponent;
|
||||
private final TaskFile myTaskFile;
|
||||
private JButton myCheckButton;
|
||||
private JButton myNextTaskButton;
|
||||
private JButton myPrevTaskButton;
|
||||
@@ -67,6 +68,10 @@ public class StudyEditor implements TextEditor {
|
||||
return myPrevTaskButton;
|
||||
}
|
||||
|
||||
public TaskFile getTaskFile() {
|
||||
return myTaskFile;
|
||||
}
|
||||
|
||||
private static JButton addButton(@NotNull final JComponent parentComponent, String toolTipText, Icon icon) {
|
||||
JButton newButton = new JButton();
|
||||
newButton.setToolTipText(toolTipText);
|
||||
@@ -91,16 +96,16 @@ public class StudyEditor implements TextEditor {
|
||||
myComponent = myDefaultEditor.getComponent();
|
||||
JPanel studyPanel = new JPanel();
|
||||
studyPanel.setLayout(new BoxLayout(studyPanel, BoxLayout.Y_AXIS));
|
||||
TaskFile taskFile = StudyTaskManager.getInstance(myProject).getTaskFile(file);
|
||||
if (taskFile != null) {
|
||||
Task currentTask = taskFile.getTask();
|
||||
myTaskFile = StudyTaskManager.getInstance(myProject).getTaskFile(file);
|
||||
if (myTaskFile != null) {
|
||||
Task currentTask = myTaskFile.getTask();
|
||||
String taskText = currentTask.getResourceText(project, currentTask.getText(), false);
|
||||
initializeTaskText(studyPanel, taskText);
|
||||
JPanel studyButtonPanel = new JPanel(new GridLayout(1, 2));
|
||||
JPanel taskActionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
studyButtonPanel.add(taskActionsPanel);
|
||||
studyButtonPanel.add(new JPanel());
|
||||
initializeButtons(taskActionsPanel, taskFile);
|
||||
initializeButtons(taskActionsPanel, myTaskFile);
|
||||
studyPanel.add(studyButtonPanel);
|
||||
myComponent.add(studyPanel, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
@@ -35,14 +35,15 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
|
||||
import com.intellij.openapi.keymap.impl.KeymapImpl;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerAdapter;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.wm.ToolWindowEP;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.*;
|
||||
import com.intellij.platform.DirectoryProjectConfigurator;
|
||||
import com.intellij.platform.PlatformProjectViewOpener;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
@@ -93,6 +94,8 @@ public class PyCharmEduInitialConfigurator {
|
||||
uiSettings.SHOW_MAIN_TOOLBAR = false;
|
||||
codeInsightSettings.REFORMAT_ON_PASTE = CodeInsightSettings.NO_REFORMAT;
|
||||
|
||||
Registry.get("ide.file.settings.order.new").setValue(true);
|
||||
|
||||
GeneralSettings.getInstance().setShowTipsOnStartup(false);
|
||||
|
||||
EditorSettingsExternalizable.getInstance().setVirtualSpace(false);
|
||||
@@ -147,6 +150,29 @@ public class PyCharmEduInitialConfigurator {
|
||||
}
|
||||
|
||||
patchProjectAreaExtensions(project);
|
||||
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
ToolWindowManager.getInstance(project).invokeLater(new Runnable() {
|
||||
int count = 0;
|
||||
|
||||
public void run() {
|
||||
if (project.isDisposed()) return;
|
||||
if (count++ < 3) { // we need to call this after ToolWindowManagerImpl.registerToolWindowsFromBeans
|
||||
ToolWindowManager.getInstance(project).invokeLater(this);
|
||||
return;
|
||||
}
|
||||
ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project");
|
||||
if (toolWindow.getType() != ToolWindowType.SLIDING) {
|
||||
toolWindow.activate(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user