replace run tests action with run configuration

This commit is contained in:
liana.bakradze
2016-04-20 17:51:31 +03:00
parent 2f01baafba
commit 70d306893d
13 changed files with 462 additions and 353 deletions
@@ -2,20 +2,13 @@ package com.jetbrains.edu.coursecreator;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.DocumentUtil;
import com.jetbrains.edu.learning.StudyActionListener;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
import com.jetbrains.edu.learning.courseFormat.Task;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
import java.util.Map;
public class CCStudyActionListener implements StudyActionListener {
@Override
public void beforeCheck(AnActionEvent event) {
@@ -38,28 +31,6 @@ public class CCStudyActionListener implements StudyActionListener {
if (taskDir == null) {
return;
}
Map<String, TaskFile> files = task.getTaskFiles();
for (Map.Entry<String, TaskFile> entry : files.entrySet()) {
String name = entry.getKey();
VirtualFile child = taskDir.findChild(name);
if (child == null) {
continue;
}
Document patternDocument = StudyUtils.getPatternDocument(entry.getValue(), name);
Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
if (document == null || patternDocument == null) {
return;
}
DocumentUtil.writeInRunUndoTransparentAction(() -> {
patternDocument.replaceString(0, patternDocument.getTextLength(), document.getCharsSequence());
FileDocumentManager.getInstance().saveDocument(patternDocument);
});
TaskFile target = new TaskFile();
TaskFile.copy(taskFile, target);
for (AnswerPlaceholder placeholder : target.getAnswerPlaceholders()) {
placeholder.setUseLength(false);
}
EduUtils.createStudentDocument(project, target, child, patternDocument);
}
CCUtils.createResources(project, task, taskDir);
}
}
@@ -6,6 +6,8 @@ import com.intellij.ide.projectView.actions.MarkRootActionBase;
import com.intellij.lang.Language;
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.module.Module;
import com.intellij.openapi.project.DumbModePermission;
import com.intellij.openapi.project.DumbService;
@@ -18,20 +20,18 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileEvent;
import com.intellij.psi.PsiDirectory;
import com.intellij.util.DocumentUtil;
import com.intellij.util.Function;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.StudyItem;
import com.jetbrains.edu.learning.courseFormat.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.*;
public class CCUtils {
private static final Logger LOG = Logger.getInstance(CCUtils.class);
@@ -214,4 +214,31 @@ public class CCUtils {
LOG.info("Failed to copy created task file to resources " + createdFile.getPath());
}
}
public static void createResources(Project project, Task task, VirtualFile taskDir) {
Map<String, TaskFile> files = task.getTaskFiles();
for (Map.Entry<String, TaskFile> entry : files.entrySet()) {
String name = entry.getKey();
VirtualFile child = taskDir.findChild(name);
if (child == null) {
continue;
}
Document patternDocument = StudyUtils.getPatternDocument(entry.getValue(), name);
Document document = FileDocumentManager.getInstance().getDocument(child);
if (document == null || patternDocument == null) {
return;
}
DocumentUtil.writeInRunUndoTransparentAction(() -> {
patternDocument.replaceString(0, patternDocument.getTextLength(), document.getCharsSequence());
FileDocumentManager.getInstance().saveDocument(patternDocument);
});
TaskFile target = new TaskFile();
TaskFile.copy(entry.getValue(), target);
for (AnswerPlaceholder placeholder : target.getAnswerPlaceholders()) {
placeholder.setUseLength(false);
}
EduUtils.createStudentDocument(project, target, child, patternDocument);
}
}
}
@@ -1,222 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.edu.coursecreator.actions;
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.icons.AllIcons;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.openapi.actionSystem.AnAction;
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.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Lesson;
import com.jetbrains.edu.learning.courseFormat.Task;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
import com.jetbrains.edu.coursecreator.CCLanguageManager;
import com.jetbrains.edu.coursecreator.CCProjectService;
import com.jetbrains.edu.coursecreator.CCUtils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Map;
public abstract class CCRunTestsAction extends AnAction {
private static final Logger LOG = Logger.getInstance(CCRunTestsAction.class.getName());
public CCRunTestsAction() {
getTemplatePresentation().setIcon(AllIcons.Actions.Lightning);
}
@Override
public void update(@NotNull AnActionEvent e) {
final Presentation presentation = e.getPresentation();
if (!CCProjectService.setCCActionAvailable(e)) {
presentation.setEnabledAndVisible(false);
return;
}
presentation.setEnabledAndVisible(false);
final ConfigurationContext context = ConfigurationContext.getFromContext(e.getDataContext());
Location location = context.getLocation();
if (location == null) {
return;
}
PsiElement psiElement = location.getPsiElement();
PsiFile psiFile = psiElement.getContainingFile();
Project project = e.getProject();
if (project == null || psiFile == null) {
return;
}
TaskFile taskFile = CCProjectService.getInstance(project).getTaskFile(psiFile.getVirtualFile());
if (taskFile == null) {
return;
}
presentation.setEnabledAndVisible(true);
presentation.setText("Run tests from '" + FileUtil.getNameWithoutExtension(psiFile.getName()) + "'");
}
public void actionPerformed(@NotNull AnActionEvent e) {
final ConfigurationContext context = ConfigurationContext.getFromContext(e.getDataContext());
run(context);
}
private void run(final @NotNull ConfigurationContext context) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
final Project project = context.getProject();
PsiElement location = context.getPsiLocation();
final Course course = CCProjectService.getInstance(project).getCourse();
if (course == null || location == null) {
return;
}
PsiFile psiFile = location.getContainingFile();
final VirtualFile virtualFile = psiFile.getVirtualFile();
final VirtualFile taskDir = virtualFile.getParent();
if (taskDir == null) {
return;
}
VirtualFile lessonDir = taskDir.getParent();
Lesson lesson = course.getLesson(lessonDir.getName());
if (lesson == null) {
return;
}
final Task task = lesson.getTask(taskDir.getName());
if (task == null) {
return;
}
clearTestEnvironment(taskDir, project);
CCLanguageManager manager = CCUtils.getStudyLanguageManager(course);
if (manager == null) {
return;
}
for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
final String name = entry.getKey();
createTaskFileForTest(taskDir, name, entry.getValue(), project);
}
FileTemplate testsTemplate = manager.getTestsTemplate(project);
if (testsTemplate == null) {
return;
}
VirtualFile testFile = taskDir.findChild(testsTemplate.getName() + "." + testsTemplate.getExtension());
if (testFile == null) {
return;
}
executeTests(project, virtualFile, taskDir, testFile);
}
});
}
private static void createTaskFileForTest(@NotNull final VirtualFile taskDir, final String fileName, @NotNull final TaskFile taskFile,
@NotNull final Project project) {
final VirtualFile answerFile = taskDir.findChild(fileName);
if (answerFile == null) {
LOG.debug("could not find answer file " + fileName);
return;
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
final FileDocumentManager documentManager = FileDocumentManager.getInstance();
documentManager.saveAllDocuments();
}
});
EduUtils.flushWindows(taskFile, answerFile, false);
createResourceFiles(answerFile, project);
}
public static void clearTestEnvironment(@NotNull final VirtualFile taskDir, @NotNull final Project project) {
try {
VirtualFile ideaDir = project.getBaseDir().findChild(".idea");
if (ideaDir == null) {
LOG.debug("idea directory doesn't exist");
return;
}
VirtualFile courseResourceDir = ideaDir.findChild(EduNames.COURSE);
if (courseResourceDir != null) {
courseResourceDir.delete(project);
}
VirtualFile[] taskDirChildren = taskDir.getChildren();
for (VirtualFile file : taskDirChildren) {
if (file.getName().contains(EduNames.WINDOWS_POSTFIX)) {
file.delete(project);
}
}
}
catch (IOException e) {
LOG.error(e);
}
}
protected abstract void executeTests(@NotNull final Project project,
@NotNull final VirtualFile virtualFile,
@NotNull final VirtualFile taskDir,
@NotNull final VirtualFile testFile);
//some tests could compare task files after user modifications with initial task files
private static void createResourceFiles(@NotNull final VirtualFile file, @NotNull final Project project) {
VirtualFile taskDir = file.getParent();
int index = EduUtils.getIndex(taskDir.getName(), EduNames.TASK);
VirtualFile lessonDir = taskDir.getParent();
int lessonIndex = EduUtils.getIndex(lessonDir.getName(), EduNames.LESSON);
Course course = CCProjectService.getInstance(project).getCourse();
if (course == null) {
return;
}
VirtualFile ideaDir = project.getBaseDir().findChild(".idea");
assert ideaDir != null;
try {
VirtualFile courseResourceDir = findOrCreateDir(project, ideaDir, EduNames.COURSE);
VirtualFile lessonResourceDir = findOrCreateDir(project, courseResourceDir, lessonDir.getName());
VirtualFile taskResourceDir = findOrCreateDir(project, lessonResourceDir, taskDir.getName());
if (EduUtils.indexIsValid(lessonIndex, course.getLessons())) {
Lesson lesson = course.getLessons().get(lessonIndex);
if (EduUtils.indexIsValid(index, lesson.getTaskList())) {
Task task = lesson.getTaskList().get(index);
for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
TaskFile taskFile = new TaskFile();
TaskFile.copy(entry.getValue(), taskFile);
EduUtils.createStudentFileFromAnswer(project, taskResourceDir, taskDir, entry.getKey(), taskFile);
}
}
}
}
catch (IOException e) {
LOG.error(e);
}
}
private static VirtualFile findOrCreateDir(@NotNull final Project project, @NotNull final VirtualFile dir, String name)
throws IOException {
VirtualFile targetDir = dir.findChild(name);
if (targetDir == null) {
targetDir = dir.createChildDirectory(project, name);
}
return targetDir;
}
}
@@ -21,27 +21,16 @@
<extensions defaultExtensionNs="com.intellij">
<directoryProjectGenerator implementation="com.jetbrains.edu.coursecreator.PyCCProjectGenerator"/>
<configurationType implementation="com.jetbrains.edu.coursecreator.run.PyCCRunTestsConfigurationType"/>
<runConfigurationProducer implementation="com.jetbrains.edu.coursecreator.run.PyCCRunTestsConfigurationProducer"/>
</extensions>
<extensions defaultExtensionNs="Edu">
<CCLanguageManager implementationClass="com.jetbrains.edu.coursecreator.PyCCLanguageManager" language="Python"/>
<executeFile implementation="com.jetbrains.edu.coursecreator.PyCCRunTests"/>
</extensions>
<extensions defaultExtensionNs="Pythonid">
<pyReferenceResolveProvider implementation="com.jetbrains.edu.coursecreator.PyCCReferenceResolveProvider"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<action id="CCRunTests" class="com.jetbrains.edu.coursecreator.actions.PyCCRunTestsAction" text="Run Tests" description="Run tests"/>
</actions>
</idea-plugin>
@@ -1,20 +0,0 @@
package com.jetbrains.edu.coursecreator;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.project.Project;
import com.jetbrains.edu.coursecreator.actions.PyCCRunTestsAction;
import com.jetbrains.python.edu.PyExecuteFileExtensionPoint;
import org.jetbrains.annotations.NotNull;
public class PyCCRunTests implements PyExecuteFileExtensionPoint {
@NotNull
public AnAction getRunAction() {
return new PyCCRunTestsAction();
}
@Override
public boolean accept(Project project) {
return CCProjectService.getInstance(project).getCourse() != null;
}
}
@@ -1,62 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.edu.coursecreator.actions;
import com.intellij.execution.Executor;
import com.intellij.execution.ProgramRunnerUtil;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.PathUtil;
import com.jetbrains.python.run.PythonConfigurationType;
import com.jetbrains.python.run.PythonRunConfiguration;
import org.jetbrains.annotations.NotNull;
public class PyCCRunTestsAction extends CCRunTestsAction {
@Override
protected void executeTests(@NotNull final Project project,
@NotNull final VirtualFile virtualFile,
@NotNull final VirtualFile taskDir,
@NotNull final VirtualFile testFile) {
final ConfigurationFactory factory = PythonConfigurationType.getInstance().getConfigurationFactories()[0];
final RunnerAndConfigurationSettings settings =
RunManager.getInstance(project).createRunConfiguration("test", factory);
final PythonRunConfiguration configuration = (PythonRunConfiguration)settings.getConfiguration();
configuration.setScriptName(testFile.getPath());
configuration.setWorkingDirectory(taskDir.getPath());
String taskFileName = virtualFile.getName();
VirtualFile userFile = taskDir.findChild(taskFileName);
if (userFile == null) {
return;
}
VirtualFile ideaDir = project.getBaseDir().findChild(".idea");
if (ideaDir == null) {
return;
}
VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
ProjectView.getInstance(project).refresh();
configuration.setScriptParameters(PathUtil.toSystemDependentName(project.getBasePath()) + " " + PathUtil.toSystemDependentName(userFile.getPath()));
Executor executor = DefaultRunExecutor.getRunExecutorInstance();
ProgramRunnerUtil.executeConfiguration(project, settings, executor);
}
}
@@ -0,0 +1,89 @@
package com.jetbrains.edu.coursecreator.run;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParamsGroup;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.coursecreator.CCUtils;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.checker.StudyCheckUtils;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Task;
import com.jetbrains.python.run.CommandLinePatcher;
import com.jetbrains.python.run.PythonCommandLineState;
import org.jetbrains.annotations.NotNull;
public class PyCCCommandLineState extends PythonCommandLineState {
private final PyCCRunTestConfiguration myRunConfiguration;
private final VirtualFile myTaskDir;
private final Task myTask;
public PyCCCommandLineState(PyCCRunTestConfiguration runConfiguration,
ExecutionEnvironment env) {
super(runConfiguration, env);
myRunConfiguration = runConfiguration;
VirtualFile testsFile = LocalFileSystem.getInstance().findFileByPath(myRunConfiguration.getPathToTest());
assert testsFile != null;
myTaskDir = StudyUtils.getTaskDir(testsFile);
assert myTaskDir != null;
myTask = StudyUtils.getTask(myRunConfiguration.getProject(), myTaskDir);
assert myTask != null;
}
@Override
protected void buildCommandLineParameters(GeneralCommandLine commandLine) {
ParamsGroup group = commandLine.getParametersList().getParamsGroup(GROUP_SCRIPT);
assert group != null;
Project project = myRunConfiguration.getProject();
Course course = StudyTaskManager.getInstance(project).getCourse();
assert course != null;
group.addParameter(myRunConfiguration.getPathToTest());
group.addParameter(course.getCourseDirectory());
group.addParameter(getFirstTaskFilePath());
}
@NotNull
private String getFirstTaskFilePath() {
String firstTaskFileName = StudyUtils.getFirst(myTask.getTaskFiles().keySet());
return myTaskDir.findChild(EduNames.SRC) != null ?
FileUtil.join(myTaskDir.getPath(), EduNames.SRC, firstTaskFileName) :
FileUtil.join(myTaskDir.getPath(), firstTaskFileName);
}
@Override
public ExecutionResult execute(Executor executor, CommandLinePatcher... patchers) throws ExecutionException {
CCUtils.createResources(myRunConfiguration.getProject(), myTask, myTaskDir);
ApplicationManager.getApplication().runWriteAction(() -> StudyCheckUtils.flushWindows(myTask, myTaskDir));
return super.execute(executor, patchers);
}
@Override
protected ProcessHandler doCreateProcess(GeneralCommandLine commandLine) throws ExecutionException {
ProcessHandler handler = super.doCreateProcess(commandLine);
handler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(ProcessEvent event) {
ApplicationManager.getApplication().invokeLater(() -> EduUtils.deleteWindowDescriptions(myTask, myTaskDir));
}
});
return handler;
}
}
@@ -0,0 +1,80 @@
package com.jetbrains.edu.coursecreator.run;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizerUtil;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class PyCCRunTestConfiguration extends AbstractPythonRunConfiguration<PyCCRunTestConfiguration> {
public static final String PATH_ATTR = "studyTest";
private Project myProject;
private String myPathToTest;
public PyCCRunTestConfiguration(Project project, ConfigurationFactory factory) {
super(project, factory);
myProject = project;
}
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException {
return new PyCCCommandLineState(this, environment);
}
@Override
protected SettingsEditor<PyCCRunTestConfiguration> createConfigurationEditor() {
return new PyCCSettingsEditor(myProject);
}
public String getPathToTest() {
return myPathToTest;
}
public void setPathToTest(String pathToTest) {
myPathToTest = pathToTest;
}
@Override
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
myPathToTest = JDOMExternalizerUtil.readField(element, PATH_ATTR);
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
super.writeExternal(element);
JDOMExternalizerUtil.writeField(element, PATH_ATTR, myPathToTest);
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
super.checkConfiguration();
String message = "Select valid path to the file with tests";
VirtualFile testsFile = LocalFileSystem.getInstance().findFileByPath(myPathToTest);
if (testsFile == null) {
throw new RuntimeConfigurationException(message);
}
VirtualFile taskDir = StudyUtils.getTaskDir(testsFile);
if (taskDir == null) {
throw new RuntimeConfigurationException(message);
}
if (StudyUtils.getTask(myProject, taskDir) == null) {
throw new RuntimeConfigurationException(message);
}
}
}
@@ -0,0 +1,19 @@
package com.jetbrains.edu.coursecreator.run;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
public class PyCCRunTestsConfigurationFactory extends ConfigurationFactory {
protected PyCCRunTestsConfigurationFactory(@NotNull ConfigurationType type) {
super(type);
}
@NotNull
@Override
public RunConfiguration createTemplateConfiguration(@NotNull Project project) {
return new PyCCRunTestConfiguration(project, this);
}
}
@@ -0,0 +1,94 @@
package com.jetbrains.edu.coursecreator.run;
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.RunConfigurationProducer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.jetbrains.edu.coursecreator.CCUtils;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Task;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyCCRunTestsConfigurationProducer extends RunConfigurationProducer<PyCCRunTestConfiguration> {
protected PyCCRunTestsConfigurationProducer() {
super(PyCCRunTestsConfigurationType.getInstance());
}
@Override
protected boolean setupConfigurationFromContext(PyCCRunTestConfiguration configuration,
ConfigurationContext context,
Ref<PsiElement> sourceElement) {
Project project = context.getProject();
if (!CCUtils.isCourseCreator(project)) {
return false;
}
String testsPath = getTestPath(context);
if (testsPath == null) {
return false;
}
VirtualFile testsFile = LocalFileSystem.getInstance().findFileByPath(testsPath);
if (testsFile == null) {
return false;
}
String generatedName = generateName(testsFile, project);
if (generatedName == null) {
return false;
}
configuration.setPathToTest(testsPath);
configuration.setName(generatedName);
return true;
}
@Nullable
private static String generateName(@NotNull VirtualFile testsFile, @NotNull Project project) {
VirtualFile taskDir = StudyUtils.getTaskDir(testsFile);
if (taskDir == null) {
return null;
}
Task task = StudyUtils.getTask(project, taskDir);
if (task == null) {
return null;
}
return task.getLesson().getName() + "/" + task.getName();
}
@Nullable
private static String getTestPath(@NotNull ConfigurationContext context) {
Location location = context.getLocation();
if (location == null) {
return null;
}
VirtualFile file = location.getVirtualFile();
if (file == null) {
return null;
}
VirtualFile taskDir = StudyUtils.getTaskDir(file);
if (taskDir == null) {
return null;
}
String testsPath = taskDir.findChild(EduNames.SRC) != null ?
FileUtil.join(taskDir.getPath(), EduNames.SRC, EduNames.TESTS_FILE) :
FileUtil.join(taskDir.getPath(), EduNames.TESTS_FILE);
return file.getPath().equals(testsPath) ? testsPath : null;
}
@Override
public boolean isConfigurationFromContext(PyCCRunTestConfiguration configuration, ConfigurationContext context) {
String path = getTestPath(context);
if (path == null) {
return false;
}
return path.equals(configuration.getPathToTest());
}
}
@@ -0,0 +1,41 @@
package com.jetbrains.edu.coursecreator.run;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.icons.AllIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class PyCCRunTestsConfigurationType implements ConfigurationType {
@Override
public String getDisplayName() {
return "Run Study Tests";
}
@Override
public String getConfigurationTypeDescription() {
return "Study Test Runner";
}
@Override
public Icon getIcon() {
return AllIcons.Actions.Lightning;
}
@NotNull
@Override
public String getId() {
return "ccruntests";
}
@Override
public ConfigurationFactory[] getConfigurationFactories() {
return new ConfigurationFactory[]{new PyCCRunTestsConfigurationFactory(this)};
}
public static PyCCRunTestsConfigurationType getInstance() {
return ConfigurationTypeUtil.findConfigurationType(PyCCRunTestsConfigurationType.class);
}
}
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.coursecreator.run.PyCCSettingsEditor">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="ae76e" class="javax.swing.JTextField" binding="myPathToTestFileField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<vspacer id="d7ebc">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="704f6" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Path to Test File"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -0,0 +1,69 @@
package com.jetbrains.edu.coursecreator.run;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.run.AbstractPyCommonOptionsForm;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import com.jetbrains.python.run.PyCommonOptionsFormData;
import com.jetbrains.python.run.PyCommonOptionsFormFactory;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class PyCCSettingsEditor extends SettingsEditor<PyCCRunTestConfiguration> {
private AbstractPyCommonOptionsForm myForm;
private Project myProject;
private JTextField myPathToTestFileField;
private JPanel myPanel;
public PyCCSettingsEditor(Project project) {
myProject = project;
}
@Override
protected void resetEditorFrom(PyCCRunTestConfiguration s) {
AbstractPythonRunConfiguration.copyParams(s, myForm);
myPathToTestFileField.setText(s.getPathToTest());
}
@Override
protected void applyEditorTo(PyCCRunTestConfiguration s) throws ConfigurationException {
AbstractPythonRunConfiguration.copyParams(myForm, s);
s.setPathToTest(myPathToTestFileField.getText());
}
@NotNull
@Override
protected JComponent createEditor() {
final JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(myPanel, BorderLayout.NORTH);
myForm = createEnvPanel();
mainPanel.add(myForm.getMainPanel(), BorderLayout.SOUTH);
return mainPanel;
}
@NotNull
private AbstractPyCommonOptionsForm createEnvPanel() {
return PyCommonOptionsFormFactory.getInstance().createForm(new PyCommonOptionsFormData() {
@Override
public Project getProject() {
return myProject;
}
@Override
public List<Module> getValidModules() {
return AbstractPythonRunConfiguration.getValidModules(myProject);
}
@Override
public boolean showConfigureInterpretersLink() {
return false;
}
});
}
}