Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Batkovich
2016-06-29 12:22:05 +03:00
30 changed files with 228 additions and 50 deletions
@@ -150,13 +150,12 @@ public class LocalVariablesUtil {
com.sun.jdi.Method method = frameProxy.location().method();
final int firstLocalVariableSlot = getFirstLocalsSlot(method);
final int firstArgsSlot = getFirstArgsSlot(method);
// gather code variables names
MultiMap<Integer, String> namesMap = calcNames(new SimpleStackFrameContext(frameProxy, process), firstLocalVariableSlot, firstArgsSlot);
MultiMap<Integer, String> namesMap = calcNames(new SimpleStackFrameContext(frameProxy, process), firstLocalVariableSlot);
// first add arguments
int slot = firstArgsSlot;
int slot = getFirstArgsSlot(method);
List<String> typeNames = method.argumentTypeNames();
List<Value> argValues = frameProxy.getArgumentValues();
for (int i = 0; i < argValues.size(); i++) {
@@ -317,9 +316,7 @@ public class LocalVariablesUtil {
}
@NotNull
private static MultiMap<Integer, String> calcNames(@NotNull final StackFrameContext context,
final int firstLocalsSlot,
final int firstArgsSlot) {
private static MultiMap<Integer, String> calcNames(@NotNull final StackFrameContext context, final int firstLocalsSlot) {
return ApplicationManager.getApplication().runReadAction(new Computable<MultiMap<Integer, String>>() {
@Override
public MultiMap<Integer, String> compute() {
@@ -329,7 +326,7 @@ public class LocalVariablesUtil {
PsiElement method = DebuggerUtilsEx.getContainingMethod(element);
if (method != null) {
MultiMap<Integer, String> res = new MultiMap<>();
int slot = Math.max(0, firstArgsSlot + firstLocalsSlot - getFirstLocalsSlot(method));
int slot = Math.max(0, firstLocalsSlot - getParametersStackSize(method));
for (PsiParameter parameter : DebuggerUtilsEx.getParameters(method)) {
res.putValue(slot, parameter.getName());
slot += getTypeSlotSize(parameter.getType());
@@ -481,11 +478,8 @@ public class LocalVariablesUtil {
}
}
private static int getFirstLocalsSlot(PsiElement method) {
private static int getParametersStackSize(PsiElement method) {
int startSlot = 0;
if (method instanceof PsiModifierListOwner) {
startSlot = ((PsiModifierListOwner)method).hasModifierProperty(PsiModifier.STATIC) ? 0 : 1;
}
for (PsiParameter parameter : DebuggerUtilsEx.getParameters(method)) {
startSlot += getTypeSlotSize(parameter.getType());
}
@@ -0,0 +1,15 @@
class TryWithFinally {
static class Resource implements AutoCloseable {
public void close() throws Exception { }
boolean find() { throw new UnsupportedOperationException(); }
}
void test() throws Exception {
boolean found = <warning descr="Variable 'found' initializer 'false' is redundant">false</warning>;
try (Resource r = new Resource()) {
found = r.find();
}
finally { }
System.out.println(found);
}
}
@@ -0,0 +1,14 @@
class TryWithoutFinally {
static class Resource implements AutoCloseable {
public void close() throws Exception { }
boolean find() { throw new UnsupportedOperationException(); }
}
void test() throws Exception {
boolean found = <warning descr="Variable 'found' initializer 'false' is redundant">false</warning>;
try (Resource r = new Resource()) {
found = r.find();
}
System.out.println(found);
}
}
@@ -17,8 +17,11 @@ package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.defUse.DefUseInspection;
import com.intellij.idea.Bombed;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import java.util.Calendar;
public class DefUseTest extends LightCodeInsightFixtureTestCase {
@Override
protected String getBasePath() {
@@ -35,6 +38,8 @@ public class DefUseTest extends LightCodeInsightFixtureTestCase {
public void testUsedInArrayInitializer() { doTest(); }
public void testHang() { doTest(); }
public void testOperatorAssignment() { doTest(); }
@Bombed(user="roman.shevchenko@jetbrains.com", day=1, month=Calendar.AUGUST, year=2017) public void testTryWithFinally() { doTest(); }
public void testTryWithoutFinally() { doTest(); }
private void doTest() {
myFixture.enableInspections(new DefUseInspection());
@@ -109,6 +109,18 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
"}"
);
}
public void test_format_only_selected_range() {
myTextRange = new TextRange(18, 19);
doTextTest(
"public class X {\n" +
" public int a = 2;\n" +
"}",
"public class X {\n" +
" public int a = 2;\n" +
"}"
);
}
public void testNew() throws Exception {
final CommonCodeStyleSettings settings = getSettings();
@@ -18,8 +18,8 @@ package com.intellij.formatting;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.util.IncorrectOperationException;
@@ -113,8 +113,10 @@ public abstract class FormatterEx{
final CommonCodeStyleSettings.IndentOptions indentOptions,
final TextRange rangeToAdjust);
public abstract void formatAroundRange(final FormattingModel model, final CodeStyleSettings settings,
final TextRange textRange, final FileType fileType);
public abstract void formatAroundRange(final FormattingModel model,
final CodeStyleSettings settings,
final PsiFile file,
final TextRange textRange);
public abstract void adjustTextRange(FormattingModel model,
CodeStyleSettings settings,
@@ -22,7 +22,6 @@ import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
@@ -393,17 +392,17 @@ public class FormatterImpl extends FormatterEx
}
@Override
public void formatAroundRange(final FormattingModel model,
final CodeStyleSettings settings,
final TextRange textRange,
final FileType fileType) {
public void formatAroundRange(FormattingModel model,
CodeStyleSettings settings,
PsiFile file,
TextRange textRange) {
disableFormatting();
try {
validateModel(model);
final FormattingDocumentModel documentModel = model.getDocumentModel();
final Block block = model.getRootBlock();
final FormatProcessor processor = buildProcessorAndWrapBlocks(
documentModel, block, settings, settings.getIndentOptions(fileType), null
documentModel, block, settings, settings.getIndentOptionsByFile(file), null
);
LeafBlockWrapper tokenBlock = processor.getFirstTokenBlock();
while (tokenBlock != null) {
@@ -319,7 +319,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(containingFile);
if (builder != null) {
final FormattingModel model = CoreFormatterUtil.buildModel(builder, containingFile, getSettings(), FormattingMode.REFORMAT);
FormatterEx.getInstanceEx().formatAroundRange(model, getSettings(), textRange, containingFile.getFileType());
FormatterEx.getInstanceEx().formatAroundRange(model, getSettings(), containingFile, textRange);
}
adjustLineIndent(containingFile, textRange);
@@ -20,6 +20,7 @@ import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -54,6 +55,8 @@ import java.util.zip.GZIPInputStream;
* }</pre>
*/
public final class HttpRequests {
private static final Logger LOG = Logger.getInstance(HttpRequests.class);
private static final int BLOCK_SIZE = 16 * 1024;
private static final Pattern CHARSET_PATTERN = Pattern.compile("charset=([^;]+)");
@@ -353,6 +356,9 @@ public final class HttpRequests {
}
private static <T> T process(RequestBuilderImpl builder, RequestProcessor<T> processor) throws IOException {
LOG.assertTrue(!ApplicationManager.getApplication().isReadAccessAllowed(),
"Network shouldn't be accessed in EDT or inside read action");
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
if (Patches.JDK_BUG_ID_8032832 && !UrlClassLoader.isRegisteredAsParallelCapable(contextLoader)) {
// hack-around for class loader lock in sun.net.www.protocol.http.NegotiateAuthentication (IDEA-131621)
@@ -64,10 +64,11 @@ public abstract class AbstractProjectImportErrorHandler {
if (location == null) {
location = getLocationFrom(rootCause);
}
if (rootCause.getCause() == null || rootCause.getCause().getMessage() == null) {
Throwable cause = rootCause.getCause();
if (cause == null || cause.getMessage() == null && !(cause instanceof StackOverflowError)) {
break;
}
rootCause = rootCause.getCause();
rootCause = cause;
}
//noinspection ConstantConditions
return Pair.create(rootCause, location);
@@ -17,6 +17,7 @@ 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.learning.statistics.EduUsagesCollector;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -104,6 +105,7 @@ public class CCProjectComponent extends AbstractProjectComponent {
public void projectOpened() {
migrateIfNeeded();
VirtualFileManager.getInstance().addVirtualFileListener(myTaskFileLifeListener);
EduUsagesCollector.projectTypeOpened(CCUtils.COURSE_MODE);
}
public void projectClosed() {
@@ -224,7 +224,8 @@ public class CCUtils {
Document patternDocument = StudyUtils.getPatternDocument(entry.getValue(), name);
Document document = FileDocumentManager.getInstance().getDocument(child);
if (document == null || patternDocument == null) {
return;
LOG.info("pattern file for " + child.getPath() + " not found");
continue;
}
DocumentUtil.writeInRunUndoTransparentAction(() -> {
patternDocument.replaceString(0, patternDocument.getTextLength(), document.getCharsSequence());
@@ -27,6 +27,7 @@ import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.*;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import org.jetbrains.annotations.NotNull;
import java.io.*;
@@ -71,6 +72,7 @@ public class CCCreateCourseArchive extends DumbAwareAction {
return;
}
createCourseArchive(project, module, myZipName, myLocationDir, true);
EduUsagesCollector.createdCourseArchive();
}
public static void createCourseArchive(final Project project, Module module, String zipName, String locationDir, boolean showMessage) {
@@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project;
import com.jetbrains.edu.coursecreator.CCUtils;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import com.jetbrains.edu.learning.stepic.EduStepicConnector;
import org.jetbrains.annotations.NotNull;
@@ -37,6 +38,7 @@ public class CCPushCourse extends DumbAwareAction {
return;
}
EduStepicConnector.postCourseWithProgress(project, course);
EduUsagesCollector.courseUploaded();
}
}
@@ -17,6 +17,7 @@ public class CCCreateAnswerPlaceholderPanel extends JPanel {
myHintText.setLineWrap(true);
myHintText.setWrapStyleWord(true);
myHintText.setBorder(BorderFactory.createLineBorder(JBColor.border()));
myHintText.setFont(myAnswerPlaceholderText.getFont());
myAnswerPlaceholderText.grabFocus();
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" 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="666" height="488"/>
@@ -20,7 +20,7 @@
</component>
<component id="7e88" class="javax.swing.JTextField" binding="myName">
<constraints>
<grid row="0" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
@@ -46,7 +46,7 @@
</component>
<component id="41fe6" class="javax.swing.JTextField" binding="myAuthorField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
@@ -60,14 +60,6 @@
<lineWrap value="true"/>
</properties>
</component>
<hspacer id="a7865">
<constraints>
<grid row="2" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="0" height="-1"/>
<maximum-size width="0" height="-1"/>
</grid>
</constraints>
</hspacer>
</children>
</grid>
</form>
@@ -27,6 +27,7 @@ public class CCNewProjectPanel {
myAuthorField.getDocument().addDocumentListener(new MyValidator());
myDescription.setBorder(BorderFactory.createLineBorder(JBColor.border()));
myDescription.setFont(myAuthorField.getFont());
}
public CCNewProjectPanel(String name, String author, String description) {
@@ -98,6 +98,9 @@
<extendWordSelectionHandler implementation="com.jetbrains.edu.learning.StudyAnswerPlaceholderExtendWordHandler"/>
<renameHandler implementation="com.jetbrains.edu.learning.StudyRenameHandler"/>
<refactoring.moveHandler implementation="com.jetbrains.edu.learning.StudyMoveDelegate" order="first"/>
<statistics.usagesCollector implementation="com.jetbrains.edu.learning.statistics.EduUsagesCollector"/>
<applicationService serviceImplementation="com.jetbrains.edu.learning.statistics.EduUsagesCollector"/>
</extensions>
<extensions defaultExtensionNs="Edu">
<optionsProvider instance="com.jetbrains.edu.learning.stepic.StepicStudyOptions"/>
@@ -35,6 +35,7 @@ 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.learning.editor.StudyEditorFactoryListener;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import com.jetbrains.edu.learning.ui.StudyToolWindow;
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
import javafx.application.Platform;
@@ -82,6 +83,7 @@ public class StudyProjectComponent implements ProjectComponent {
UISettings.getInstance().HIDE_TOOL_STRIPES = false;
UISettings.getInstance().fireUISettingsChanged();
registerShortcuts();
EduUsagesCollector.projectTypeOpened(course.isAdaptive() ? EduNames.ADAPTIVE : EduNames.STUDY);
}
}
});
@@ -334,7 +334,7 @@ public class StudySerializationUtils {
for (Map.Entry<String, JsonElement> taskFile : taskObject.getAsJsonObject(TASK_FILES).entrySet()) {
String name = taskFile.getKey();
String filePath = FileUtil.join(myCourseFile.getParent(), EduNames.LESSON + lessonIndex, EduNames.TASK + taskIndex, name);
VirtualFile resourceFile = LocalFileSystem.getInstance().findFileByIoFile(new File(filePath));
VirtualFile resourceFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(filePath));
if (resourceFile == null) {
continue;
}
@@ -18,6 +18,7 @@ import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import icons.InteractiveLearningIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,6 +60,7 @@ public class StudyShowHintAction extends StudyActionWithShortcut {
if (file == null) {
return;
}
EduUsagesCollector.hintShown();
String hintText = ourWarningMessage;
if (answerPlaceholder != null) {
String hint = answerPlaceholder.getHint();
@@ -15,6 +15,7 @@ import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Task;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,16 +37,16 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut
if (!studyState.isValid()) {
return;
}
Task nextTask = getTargetTask(studyState.getTask());
if (nextTask == null) {
Task targetTask = getTargetTask(studyState.getTask());
if (targetTask == null) {
return;
}
for (VirtualFile file : FileEditorManager.getInstance(project).getOpenFiles()) {
FileEditorManager.getInstance(project).closeFile(file);
}
int nextTaskIndex = nextTask.getIndex();
int lessonIndex = nextTask.getLesson().getIndex();
Map<String, TaskFile> nextTaskFiles = nextTask.getTaskFiles();
int nextTaskIndex = targetTask.getIndex();
int lessonIndex = targetTask.getLesson().getIndex();
Map<String, TaskFile> nextTaskFiles = targetTask.getTaskFiles();
VirtualFile projectDir = project.getBaseDir();
String lessonDirName = EduNames.LESSON + String.valueOf(lessonIndex);
if (projectDir == null) {
@@ -64,7 +65,7 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut
ProjectView.getInstance(project).select(taskDir, taskDir, false);
return;
}
EduUsagesCollector.taskNavigation();
VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir);
updateProjectView(project, shouldBeActive);
@@ -40,10 +40,12 @@ public class EduNames {
public static final String SANDBOX_DIR = "Sandbox";
public static final String COURSE_META_FILE = "course.json";
public static final String STUDY = "Study";
public static final String PYCHARM_ADDITIONAL = "PyCharm additional materials";
public static final String PYCHARM = "PyCharm";
public static final String STUDY = "Study";
public static final String ADAPTIVE = "Adaptive";
public static final String PLACEHOLDER = "Answer Placeholder";
public static final String SRC = "src";
private EduNames() {
@@ -33,6 +33,7 @@ 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.learning.statistics.EduUsagesCollector;
import com.jetbrains.edu.learning.stepic.CourseInfo;
import com.jetbrains.edu.learning.stepic.EduStepicConnector;
import com.jetbrains.edu.learning.stepic.StepicUser;
@@ -102,6 +103,7 @@ public class StudyProjectGenerator {
VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
StudyProjectComponent.getInstance(project).registerStudyToolWindow(course);
openFirstTask(course, project);
EduUsagesCollector.projectTypeCreated(course.isAdaptive() ? EduNames.ADAPTIVE : EduNames.STUDY);
});
}
@@ -0,0 +1,84 @@
/*
* Copyright 2000-2016 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.learning.statistics;
import com.intellij.internal.statistic.CollectUsagesException;
import com.intellij.internal.statistic.UsagesCollector;
import com.intellij.internal.statistic.beans.GroupDescriptor;
import com.intellij.internal.statistic.beans.UsageDescriptor;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public class EduUsagesCollector extends UsagesCollector {
private static final String GROUP_ID = "educational";
private final FactoryMap<String, UsageDescriptor> myUsageDescriptors = new FactoryMap<String, UsageDescriptor>() {
@Nullable
@Override
protected UsageDescriptor create(String key) {
return new UsageDescriptor(key, 0);
}
};
public static void projectTypeCreated(@NotNull String projectTypeId) {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("project.created." + projectTypeId).advance();
}
public static void projectTypeOpened(@NotNull String projectTypeId) {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("project.opened." + projectTypeId).advance();
}
public static void taskChecked() {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("checkTask.").advance();
}
public static void hintShown() {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("showHint.").advance();
}
public static void taskNavigation() {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("navigateToTask.").advance();
}
public static void courseUploaded() {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("uploadCourse.").advance();
}
public static void createdCourseArchive() {
ServiceManager.getService(EduUsagesCollector.class).myUsageDescriptors.get("courseArchive.").advance();
}
@NotNull
@Override
public Set<UsageDescriptor> getUsages() throws CollectUsagesException {
HashSet<UsageDescriptor> descriptors = new HashSet<>();
descriptors.addAll(myUsageDescriptors.values());
myUsageDescriptors.clear();
return descriptors;
}
@NotNull
@Override
public GroupDescriptor getGroupId() {
return GroupDescriptor.create(GROUP_ID);
}
}
@@ -1,6 +1,8 @@
package com.jetbrains.edu.learning.stepic;
import com.google.gson.*;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
@@ -297,6 +299,9 @@ public class EduStepicConnector {
info.addAuthor(author);
}
String name = info.getName().replaceAll("[^a-zA-Z0-9\\s]", "");
info.setName(name.trim());
result.add(info);
}
}
@@ -105,6 +105,7 @@ public class StudyNewProjectPanel extends JPanel implements PanelWithAnchor {
myDescriptionPane.setEnabled(true);
myAuthorLabel.setEnabled(true);
myDescriptionPane.setPreferredSize(new Dimension(150, 100));
myDescriptionPane.setFont(coursesCombo.getFont());
myInfoPanel.add(myAuthorLabel);
myInfoPanel.add(myDescriptionPane);
myInfoPanel.setBorder(BorderFactory.createLineBorder(new JBColor(10067616, 10067616)));
@@ -24,6 +24,7 @@ import com.jetbrains.edu.learning.StudyProjectComponent;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.newProject.PythonProjectGenerator;
import icons.CourseCreatorPythonIcons;
@@ -63,6 +64,7 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire
@NotNull final String name, @NotNull final String[] authors,
@NotNull final String description) {
final Course course = getCourse(project, name, authors, description);
EduUsagesCollector.projectTypeCreated(CCUtils.COURSE_MODE);
final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir);
if (projectDir == null) return;
@@ -10,6 +10,7 @@ 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.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -22,11 +23,13 @@ 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.edu.learning.courseFormat.TaskFile;
import com.jetbrains.python.run.CommandLinePatcher;
import com.jetbrains.python.run.PythonCommandLineState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Map;
public class PyCCCommandLineState extends PythonCommandLineState {
private final PyCCRunTestConfiguration myRunConfiguration;
@@ -58,16 +61,36 @@ public class PyCCCommandLineState extends PythonCommandLineState {
group.addParameter(myRunConfiguration.getPathToTest());
group.addParameter(new File(course.getCourseDirectory()).getPath());
group.addParameter(getFirstTaskFilePath());
String path = getFirstTaskFilePath();
if (path != null) {
group.addParameter(path);
}
}
@NotNull
@Nullable
private String getFirstTaskFilePath() {
String firstTaskFileName = StudyUtils.getFirst(myTask.getTaskFiles().keySet());
for (Map.Entry<String, TaskFile> entry : myTask.getTaskFiles().entrySet()) {
String path = getTaskFilePath(entry.getKey());
if (!entry.getValue().getAnswerPlaceholders().isEmpty()) {
return path;
}
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
if (virtualFile == null) {
continue;
}
if (TextEditorProvider.isTextFile(virtualFile)) {
return path;
}
}
return null;
}
private String getTaskFilePath(String name) {
String taskDirPath = FileUtil.toSystemDependentName(myTaskDir.getPath());
return myTaskDir.findChild(EduNames.SRC) != null ?
FileUtil.join(taskDirPath, EduNames.SRC, firstTaskFileName) :
FileUtil.join(taskDirPath, firstTaskFileName);
FileUtil.join(taskDirPath, EduNames.SRC, name) :
FileUtil.join(taskDirPath, name);
}
@Override
@@ -21,6 +21,7 @@ import com.jetbrains.edu.learning.courseFormat.StudyStatus;
import com.jetbrains.edu.learning.courseFormat.Task;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
import com.jetbrains.edu.learning.ui.StudyToolWindow;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,6 +33,7 @@ public class PyStudyCheckAction extends StudyCheckAction {
public static final String ACTION_ID = "PyCheckAction";
public void check(@NotNull Project project) {
EduUsagesCollector.taskChecked();
ApplicationManager.getApplication().runWriteAction(() -> CommandProcessor.getInstance().runUndoTransparentAction(() -> {
final StudyEditor selectedEditor = StudyUtils.getSelectedStudyEditor(project);
if (selectedEditor == null) return;