From ce963db18f600acbcf8e1def96059716772db2d2 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 13 Jan 2015 18:44:52 +0300 Subject: [PATCH 01/55] refactoring pycharm educational first iteration extracted course-creator (language independent) and course-creator-python modules --- .../resources/META-INF/plugin.xml | 86 ------------------ .../course-creator/resources/icons/gutter.png | Bin 500 -> 0 bytes .../coursecreator/CCAnswerFileType.java | 40 -------- .../plugins/coursecreator/CCRunTests.java | 30 ------ python/edu/main_pycharm_edu.iml | 4 +- .../course-creator-python.iml} | 7 +- .../resources/META-INF/plugin.xml | 43 +++++++++ .../fileTemplates/internal/task.answer.ft | 0 .../fileTemplates/internal/task.html.ft | 0 .../fileTemplates/internal/test_helper.py.ft | 0 .../fileTemplates/internal/tests.py.ft | 0 .../icons/CourseCreationProjectType.png | Bin .../icons/CourseCreationProjectType@2x.png | Bin .../CourseCreationProjectType@2x_dark.png | Bin .../icons/CourseCreationProjectType_dark.png | Bin .../PyCCAnswerFileTypeFactory.java} | 7 +- .../coursecreator/PyCCProjectGenerator.java} | 43 ++------- .../actions/PyCCRunTestsAction.java | 66 ++++++++++++++ .../src/icons/CourseCreatorPythonIcons.java} | 5 +- .../testData/helloworld.py | 0 .../testData/helloworld.xml | 0 .../tests/CCDocumentListenerTest.java | 6 +- .../tests/CCTestCase.java | 2 +- .../educational-python/educational-python.iml | 11 +++ .../interactive-learning-python.iml | 11 +++ .../course-creator/course-creator.iml | 14 +++ .../resources/META-INF/plugin.xml | 78 ++++++++++++++++ .../coursecreator/CCDocumentListener.java | 6 +- .../CCEditorFactoryListener.java | 7 +- .../coursecreator/CCProjectComponent.java | 12 +-- .../coursecreator/CCProjectGeneratorUtil.java | 45 +++++++++ .../edu}/coursecreator/CCProjectService.java | 4 +- .../CCRefactoringElementListenerProvider.java | 12 +-- .../jetbrains/edu}/coursecreator/CCUtils.java | 2 +- .../actions/CCAddTaskWindow.java | 8 +- .../actions/CCChangeCourseInfo.java | 8 +- .../actions/CCCreateCourseArchive.java | 10 +- .../coursecreator/actions/CCCreateLesson.java | 8 +- .../coursecreator/actions/CCCreateTask.java | 12 +-- .../actions/CCCreateTaskFile.java | 14 +-- .../actions/CCDeleteTaskWindow.java | 10 +- .../edu}/coursecreator/actions/CCRename.java | 6 +- .../coursecreator/actions/CCRenameLesson.java | 6 +- .../coursecreator/actions/CCRenameTask.java | 8 +- .../actions/CCRunTestsAction.java | 47 ++-------- .../coursecreator/actions/CCShowPreview.java | 11 +-- .../actions/CCShowTaskWindowDetails.java | 8 +- .../actions/CCTaskWindowAction.java | 8 +- .../edu}/coursecreator/format/Course.java | 2 +- .../edu}/coursecreator/format/Lesson.java | 2 +- .../edu}/coursecreator/format/Task.java | 4 +- .../edu}/coursecreator/format/TaskFile.java | 2 +- .../edu}/coursecreator/format/TaskWindow.java | 4 +- .../projectView/CCDirectoryNode.java | 10 +- .../projectView/CCTreeStructureProvider.java | 4 +- .../coursecreator/ui/CCNewProjectPanel.form | 2 +- .../coursecreator/ui/CCNewProjectPanel.java | 2 +- .../ui/CreateCourseArchiveDialog.java | 4 +- .../ui/CreateCourseArchivePanel.form | 2 +- .../ui/CreateCourseArchivePanel.java | 2 +- .../ui/CreateTaskWindowDialog.java | 6 +- .../ui/CreateTaskWindowPanel.form | 2 +- .../ui/CreateTaskWindowPanel.java | 2 +- python/educational/educational.iml | 11 +++ .../interactive-learning.iml | 11 +++ 65 files changed, 426 insertions(+), 351 deletions(-) delete mode 100644 python/edu/course-creator/resources/META-INF/plugin.xml delete mode 100644 python/edu/course-creator/resources/icons/gutter.png delete mode 100644 python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCAnswerFileType.java delete mode 100644 python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRunTests.java rename python/{edu/course-creator/course-creator.iml => educational-python/course-creator-python/course-creator-python.iml} (86%) create mode 100644 python/educational-python/course-creator-python/resources/META-INF/plugin.xml rename python/{edu/course-creator => educational-python/course-creator-python}/resources/fileTemplates/internal/task.answer.ft (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/fileTemplates/internal/task.html.ft (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/fileTemplates/internal/test_helper.py.ft (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/fileTemplates/internal/tests.py.ft (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/icons/CourseCreationProjectType.png (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/icons/CourseCreationProjectType@2x.png (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/icons/CourseCreationProjectType@2x_dark.png (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/resources/icons/CourseCreationProjectType_dark.png (100%) rename python/{edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCAnswerFileTypeFactory.java => educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java} (79%) rename python/{edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectGenerator.java => educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java} (53%) create mode 100644 python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java rename python/{edu/course-creator/src/icons/CourseCreatorIcons.java => educational-python/course-creator-python/src/icons/CourseCreatorPythonIcons.java} (67%) rename python/{edu/course-creator => educational-python/course-creator-python}/testData/helloworld.py (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/testData/helloworld.xml (100%) rename python/{edu/course-creator => educational-python/course-creator-python}/tests/CCDocumentListenerTest.java (93%) rename python/{edu/course-creator => educational-python/course-creator-python}/tests/CCTestCase.java (96%) create mode 100644 python/educational-python/educational-python.iml create mode 100644 python/educational-python/interactive-learning-python/interactive-learning-python.iml create mode 100644 python/educational/course-creator/course-creator.iml create mode 100644 python/educational/course-creator/resources/META-INF/plugin.xml rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/CCDocumentListener.java (94%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/CCEditorFactoryListener.java (93%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/CCProjectComponent.java (95%) create mode 100644 python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/CCProjectService.java (98%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/CCRefactoringElementListenerProvider.java (90%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/CCUtils.java (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCAddTaskWindow.java (96%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCChangeCourseInfo.java (93%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCCreateCourseArchive.java (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCCreateLesson.java (93%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCCreateTask.java (94%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCCreateTaskFile.java (90%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCDeleteTaskWindow.java (83%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCRename.java (95%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCRenameLesson.java (88%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCRenameTask.java (87%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCRunTestsAction.java (84%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCShowPreview.java (94%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCShowTaskWindowDetails.java (85%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/actions/CCTaskWindowAction.java (93%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/format/Course.java (96%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/format/Lesson.java (96%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/format/Task.java (91%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/format/TaskFile.java (98%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/format/TaskWindow.java (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/projectView/CCDirectoryNode.java (88%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/projectView/CCTreeStructureProvider.java (95%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CCNewProjectPanel.form (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CCNewProjectPanel.java (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CreateCourseArchiveDialog.java (88%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CreateCourseArchivePanel.form (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CreateCourseArchivePanel.java (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CreateTaskWindowDialog.java (97%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CreateTaskWindowPanel.form (98%) rename python/{edu/course-creator/src/org/jetbrains/plugins => educational/course-creator/src/com/jetbrains/edu}/coursecreator/ui/CreateTaskWindowPanel.java (98%) create mode 100644 python/educational/educational.iml create mode 100644 python/educational/interactive-learning/interactive-learning.iml diff --git a/python/edu/course-creator/resources/META-INF/plugin.xml b/python/edu/course-creator/resources/META-INF/plugin.xml deleted file mode 100644 index 0e7391d1a18b..000000000000 --- a/python/edu/course-creator/resources/META-INF/plugin.xml +++ /dev/null @@ -1,86 +0,0 @@ - - org.jetbrains.plugins.coursecreator - Course Creator for PyCharm Educational - 1.2 - - - - - - - - - - - com.intellij.modules.python - - - - - - - - - - - - - - - - - - - - - - org.jetbrains.plugins.coursecreator.CCProjectComponent - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/python/edu/course-creator/resources/icons/gutter.png b/python/edu/course-creator/resources/icons/gutter.png deleted file mode 100644 index 244e6ca045c50a130086ac388b560a12761544b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 500 zcmV z!-sF!^gVb+8rtpyctW0#N6uWni0LCt_6PoOdbjll_d4>B|?abUmpo8>v>h}Zj|Ya;Eu#qwvU1IVc9khP8VrtAsT2=e83P~$#!xXbw)n}FlPSEe7Hq1uCb zR8w;xqmBrUgA^pnkB=O@-lq0DPz$ay0yh_~I_IDpzxRb(4=Iy9CT||k!08w)Pe>W4 zElmH8fF;68$GMwZ#7{4ozI(ySrR%I+xs4-G1q^UxnUV7rlf9>Rn&_6Wike0000 + - - + \ No newline at end of file diff --git a/python/edu/course-creator/course-creator.iml b/python/educational-python/course-creator-python/course-creator-python.iml similarity index 86% rename from python/edu/course-creator/course-creator.iml rename to python/educational-python/course-creator-python/course-creator-python.iml index 18baaf4ed068..e08d029ad3ce 100644 --- a/python/edu/course-creator/course-creator.iml +++ b/python/educational-python/course-creator-python/course-creator-python.iml @@ -9,11 +9,10 @@ - + - - + - + \ No newline at end of file diff --git a/python/educational-python/course-creator-python/resources/META-INF/plugin.xml b/python/educational-python/course-creator-python/resources/META-INF/plugin.xml new file mode 100644 index 000000000000..b9148d8f1de2 --- /dev/null +++ b/python/educational-python/course-creator-python/resources/META-INF/plugin.xml @@ -0,0 +1,43 @@ + + com.jetbrains.edu.coursecreator.python + Course Creator for PyCharm Educational + 2.0 + + + + + + + + + + + com.intellij.modules.platform + com.intellij.modules.python + com.jetbrains.edu.coursecreator + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/edu/course-creator/resources/fileTemplates/internal/task.answer.ft b/python/educational-python/course-creator-python/resources/fileTemplates/internal/task.answer.ft similarity index 100% rename from python/edu/course-creator/resources/fileTemplates/internal/task.answer.ft rename to python/educational-python/course-creator-python/resources/fileTemplates/internal/task.answer.ft diff --git a/python/edu/course-creator/resources/fileTemplates/internal/task.html.ft b/python/educational-python/course-creator-python/resources/fileTemplates/internal/task.html.ft similarity index 100% rename from python/edu/course-creator/resources/fileTemplates/internal/task.html.ft rename to python/educational-python/course-creator-python/resources/fileTemplates/internal/task.html.ft diff --git a/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft b/python/educational-python/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft similarity index 100% rename from python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft rename to python/educational-python/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft diff --git a/python/edu/course-creator/resources/fileTemplates/internal/tests.py.ft b/python/educational-python/course-creator-python/resources/fileTemplates/internal/tests.py.ft similarity index 100% rename from python/edu/course-creator/resources/fileTemplates/internal/tests.py.ft rename to python/educational-python/course-creator-python/resources/fileTemplates/internal/tests.py.ft diff --git a/python/edu/course-creator/resources/icons/CourseCreationProjectType.png b/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType.png similarity index 100% rename from python/edu/course-creator/resources/icons/CourseCreationProjectType.png rename to python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType.png diff --git a/python/edu/course-creator/resources/icons/CourseCreationProjectType@2x.png b/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x.png similarity index 100% rename from python/edu/course-creator/resources/icons/CourseCreationProjectType@2x.png rename to python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x.png diff --git a/python/edu/course-creator/resources/icons/CourseCreationProjectType@2x_dark.png b/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png similarity index 100% rename from python/edu/course-creator/resources/icons/CourseCreationProjectType@2x_dark.png rename to python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png diff --git a/python/edu/course-creator/resources/icons/CourseCreationProjectType_dark.png b/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType_dark.png similarity index 100% rename from python/edu/course-creator/resources/icons/CourseCreationProjectType_dark.png rename to python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType_dark.png diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCAnswerFileTypeFactory.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java similarity index 79% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCAnswerFileTypeFactory.java rename to python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java index 7c49b8e61658..4585963375a3 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCAnswerFileTypeFactory.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.openapi.fileTypes.FileTypeConsumer; import com.intellij.openapi.fileTypes.FileTypeFactory; +import com.jetbrains.python.PythonFileType; import org.jetbrains.annotations.NotNull; -public class CCAnswerFileTypeFactory extends FileTypeFactory { +public class PyCCAnswerFileTypeFactory extends FileTypeFactory { @Override public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) { - fileTypeConsumer.consume(CCAnswerFileType.INSTANCE, "answer"); + fileTypeConsumer.consume(PythonFileType.INSTANCE, "answer"); } } diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectGenerator.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java similarity index 53% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectGenerator.java rename to python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index 667134d767b5..0cb33f31733a 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectGenerator.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -1,34 +1,24 @@ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.facet.ui.FacetEditorValidator; import com.intellij.facet.ui.FacetValidatorsManager; import com.intellij.facet.ui.ValidationResult; -import com.intellij.ide.fileTemplates.FileTemplate; -import com.intellij.ide.fileTemplates.FileTemplateManager; -import com.intellij.ide.fileTemplates.FileTemplateUtil; -import com.intellij.ide.util.DirectoryUtil; -import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiManager; +import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel; import com.jetbrains.python.newProject.PythonProjectGenerator; -import icons.CourseCreatorIcons; +import icons.CourseCreatorPythonIcons; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.actions.CCCreateLesson; -import org.jetbrains.plugins.coursecreator.actions.CCCreateTask; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.ui.CCNewProjectPanel; import javax.swing.*; -public class CCProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator { +public class PyCCProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator { private CCNewProjectPanel mySettingsPanel; @Nls @@ -47,34 +37,15 @@ public class CCProjectGenerator extends PythonProjectGenerator implements Direct @Nullable @Override public Icon getLogo() { - return CourseCreatorIcons.CourseCreationProjectType; + return CourseCreatorPythonIcons.CourseCreationProjectType; } @Override public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, @Nullable Object settings, @NotNull Module module) { - - final CCProjectService service = CCProjectService.getInstance(project); - final Course course = new Course(mySettingsPanel.getName(), mySettingsPanel.getAuthor(), mySettingsPanel.getDescription()); - service.setCourse(course); - - final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir); - if (projectDir == null) return; - new WriteCommandAction.Simple(project) { - @Override - protected void run() throws Throwable { - final FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate("test_helper"); - try { - FileTemplateUtil.createFromTemplate(template, "test_helper.py", null, projectDir); - } - catch (Exception ignored) { - } - DirectoryUtil.createSubdirectories("hints", projectDir, "\\/"); - final PsiDirectory lessonDir = CCCreateLesson.createLesson(projectDir, 1, null, null, course); - CCCreateTask.createTask(null, project, lessonDir, false); - } - }.execute(); + CCProjectGeneratorUtil.generateProject(project, baseDir, mySettingsPanel.getName(), + mySettingsPanel.getAuthor(), mySettingsPanel.getDescription()); } @NotNull diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java new file mode 100644 index 000000000000..ee002b64c45a --- /dev/null +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java @@ -0,0 +1,66 @@ +/* + * 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()); + VirtualFile userFile = taskDir.findChild(virtualFile.getNameWithoutExtension() + ".py"); + if (userFile == null) { + return; + } + VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); + if (ideaDir == null) { + return; + } + VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); + ProjectView.getInstance(project).refresh(); + VirtualFile courseDir = ideaDir.findChild("course"); + if (courseDir == null) { + return; + } + configuration.setScriptParameters(PathUtil.toSystemDependentName(courseDir.getPath()) + " " + PathUtil.toSystemDependentName(userFile.getPath())); + Executor executor = DefaultRunExecutor.getRunExecutorInstance(); + ProgramRunnerUtil.executeConfiguration(project, settings, executor); + } + + +} diff --git a/python/edu/course-creator/src/icons/CourseCreatorIcons.java b/python/educational-python/course-creator-python/src/icons/CourseCreatorPythonIcons.java similarity index 67% rename from python/edu/course-creator/src/icons/CourseCreatorIcons.java rename to python/educational-python/course-creator-python/src/icons/CourseCreatorPythonIcons.java index 191ce0d55b30..2342897dc53e 100644 --- a/python/edu/course-creator/src/icons/CourseCreatorIcons.java +++ b/python/educational-python/course-creator-python/src/icons/CourseCreatorPythonIcons.java @@ -8,11 +8,10 @@ import javax.swing.*; * NOTE THIS FILE IS AUTO-GENERATED * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead */ -public class CourseCreatorIcons { +public class CourseCreatorPythonIcons { private static Icon load(String path) { - return IconLoader.getIcon(path, CourseCreatorIcons.class); + return IconLoader.getIcon(path, CourseCreatorPythonIcons.class); } public static final Icon CourseCreationProjectType = load("/icons/CourseCreationProjectType.png"); // 32x32 - public static final Icon Gutter = load("/icons/gutter.png"); // 16x16 } diff --git a/python/edu/course-creator/testData/helloworld.py b/python/educational-python/course-creator-python/testData/helloworld.py similarity index 100% rename from python/edu/course-creator/testData/helloworld.py rename to python/educational-python/course-creator-python/testData/helloworld.py diff --git a/python/edu/course-creator/testData/helloworld.xml b/python/educational-python/course-creator-python/testData/helloworld.xml similarity index 100% rename from python/edu/course-creator/testData/helloworld.xml rename to python/educational-python/course-creator-python/testData/helloworld.xml diff --git a/python/edu/course-creator/tests/CCDocumentListenerTest.java b/python/educational-python/course-creator-python/tests/CCDocumentListenerTest.java similarity index 93% rename from python/edu/course-creator/tests/CCDocumentListenerTest.java rename to python/educational-python/course-creator-python/tests/CCDocumentListenerTest.java index 24e9e85bf1ca..b489513d2123 100644 --- a/python/edu/course-creator/tests/CCDocumentListenerTest.java +++ b/python/educational-python/course-creator-python/tests/CCDocumentListenerTest.java @@ -5,11 +5,11 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.util.xmlb.XmlSerializer; +import com.jetbrains.edu.coursecreator.actions.CCCreateCourseArchive; +import com.jetbrains.edu.coursecreator.format.TaskFile; +import com.jetbrains.edu.coursecreator.format.TaskWindow; import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.actions.CCCreateCourseArchive; -import org.jetbrains.plugins.coursecreator.format.TaskFile; -import org.jetbrains.plugins.coursecreator.format.TaskWindow; import java.util.List; diff --git a/python/edu/course-creator/tests/CCTestCase.java b/python/educational-python/course-creator-python/tests/CCTestCase.java similarity index 96% rename from python/edu/course-creator/tests/CCTestCase.java rename to python/educational-python/course-creator-python/tests/CCTestCase.java index c7dbe46308c9..66c33ebf859b 100644 --- a/python/edu/course-creator/tests/CCTestCase.java +++ b/python/educational-python/course-creator-python/tests/CCTestCase.java @@ -25,7 +25,7 @@ public abstract class CCTestCase extends UsefulTestCase { } protected String getTestDataPath() { - return PythonHelpersLocator.getPythonCommunityPath() + "/edu/course-creator/testData"; + return PythonHelpersLocator.getPythonCommunityPath() + "/educational_python/course_creator_python/testData"; } @Override diff --git a/python/educational-python/educational-python.iml b/python/educational-python/educational-python.iml new file mode 100644 index 000000000000..c90834f2d607 --- /dev/null +++ b/python/educational-python/educational-python.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/python/educational-python/interactive-learning-python/interactive-learning-python.iml b/python/educational-python/interactive-learning-python/interactive-learning-python.iml new file mode 100644 index 000000000000..c90834f2d607 --- /dev/null +++ b/python/educational-python/interactive-learning-python/interactive-learning-python.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/python/educational/course-creator/course-creator.iml b/python/educational/course-creator/course-creator.iml new file mode 100644 index 000000000000..75a2690f8e0f --- /dev/null +++ b/python/educational/course-creator/course-creator.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/educational/course-creator/resources/META-INF/plugin.xml b/python/educational/course-creator/resources/META-INF/plugin.xml new file mode 100644 index 000000000000..6fb2817bff05 --- /dev/null +++ b/python/educational/course-creator/resources/META-INF/plugin.xml @@ -0,0 +1,78 @@ + + com.jetbrains.edu.coursecreator + Course Creator Plugin + 2.0 + + + + + + + + + + com.intellij.modules.platform + + + + + + + + + + + + + + + + com.jetbrains.edu.coursecreator.CCProjectComponent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCDocumentListener.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java similarity index 94% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCDocumentListener.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java index b1917292df32..e2621bfa0342 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCDocumentListener.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java @@ -1,11 +1,11 @@ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; -import org.jetbrains.plugins.coursecreator.format.TaskFile; -import org.jetbrains.plugins.coursecreator.format.TaskWindow; +import com.jetbrains.edu.coursecreator.format.TaskFile; +import com.jetbrains.edu.coursecreator.format.TaskWindow; import java.util.ArrayList; import java.util.List; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java similarity index 93% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java index c61ab10d7332..57d7d73a9fe5 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.codeInsight.hint.HintManager; import com.intellij.openapi.editor.Document; @@ -12,8 +12,11 @@ import com.intellij.openapi.editor.event.EditorFactoryListener; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; +import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.format.*; public class CCEditorFactoryListener implements EditorFactoryListener { @Override diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectComponent.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java similarity index 95% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectComponent.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java index 88a242492581..e4c44a97e62f 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectComponent.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; @@ -16,12 +16,12 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileAdapter; import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.openapi.vfs.VirtualFileManager; +import com.jetbrains.edu.coursecreator.actions.CCRunTestsAction; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; +import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.actions.CCRunTestsAction; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; -import org.jetbrains.plugins.coursecreator.format.Task; -import org.jetbrains.plugins.coursecreator.format.TaskFile; import java.io.IOException; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java new file mode 100644 index 000000000000..7ccd9a8d7f6a --- /dev/null +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java @@ -0,0 +1,45 @@ +package com.jetbrains.edu.coursecreator; + +import com.intellij.ide.fileTemplates.FileTemplate; +import com.intellij.ide.fileTemplates.FileTemplateManager; +import com.intellij.ide.fileTemplates.FileTemplateUtil; +import com.intellij.ide.util.DirectoryUtil; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiManager; +import com.jetbrains.edu.coursecreator.actions.CCCreateLesson; +import com.jetbrains.edu.coursecreator.actions.CCCreateTask; +import com.jetbrains.edu.coursecreator.format.Course; +import org.jetbrains.annotations.NotNull; + + +public class CCProjectGeneratorUtil { + public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, + @NotNull final String name, @NotNull final String author, + @NotNull final String description) { + + final CCProjectService service = CCProjectService.getInstance(project); + final Course course = new Course(name, author, description); + service.setCourse(course); + + final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir); + if (projectDir == null) return; + new WriteCommandAction.Simple(project) { + @Override + protected void run() throws Throwable { + final FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate("test_helper"); + try { + FileTemplateUtil.createFromTemplate(template, "test_helper.py", null, projectDir); + } + catch (Exception ignored) { + } + DirectoryUtil.createSubdirectories("hints", projectDir, "\\/"); + final PsiDirectory lessonDir = CCCreateLesson.createLesson(projectDir, 1, null, null, course); + CCCreateTask.createTask(null, project, lessonDir, false); + } + }.execute(); + } + +} diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectService.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java similarity index 98% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectService.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java index 6d56fe6b5962..028e449f6fda 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCProjectService.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -29,10 +29,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.xmlb.XmlSerializer; +import com.jetbrains.edu.coursecreator.format.*; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.format.*; import java.io.File; import java.util.Collection; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRefactoringElementListenerProvider.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java similarity index 90% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRefactoringElementListenerProvider.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java index 9ff6aa77fd44..50a4693d29cc 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCRefactoringElementListenerProvider.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.PsiDirectory; @@ -22,13 +22,13 @@ import com.intellij.psi.PsiFile; import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.RefactoringElementListenerProvider; +import com.jetbrains.edu.coursecreator.actions.CCRunTestsAction; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; +import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.actions.CCRunTestsAction; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; -import org.jetbrains.plugins.coursecreator.format.Task; -import org.jetbrains.plugins.coursecreator.format.TaskFile; import java.util.Map; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCUtils.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCUtils.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java index e2cc9d575638..130952e8ebaa 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCUtils.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator; +package com.jetbrains.edu.coursecreator; import com.intellij.ide.projectView.actions.MarkRootActionBase; import com.intellij.openapi.application.ApplicationManager; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddTaskWindow.java similarity index 96% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddTaskWindow.java index 244de123a33d..17f62ce19ef8 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddTaskWindow.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -13,10 +13,10 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.*; +import com.jetbrains.edu.coursecreator.ui.CreateTaskWindowDialog; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.*; -import org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowDialog; import java.util.List; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java similarity index 93% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java index 653af6c691f6..81ee890989bb 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.ide.IdeView; import com.intellij.ide.projectView.ProjectView; @@ -11,11 +11,11 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiDirectory; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.ui.CCNewProjectPanel; import javax.swing.*; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java index a3d4f56e2b34..5a2cf63af8cb 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -18,11 +18,11 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.io.ZipUtil; +import com.jetbrains.edu.coursecreator.CCDocumentListener; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.*; +import com.jetbrains.edu.coursecreator.ui.CreateCourseArchiveDialog; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCDocumentListener; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.*; -import org.jetbrains.plugins.coursecreator.ui.CreateCourseArchiveDialog; import java.io.*; import java.util.Collections; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateLesson.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java similarity index 93% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateLesson.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java index 58b950b5a637..a92bdd7a87fb 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateLesson.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.ide.IdeView; import com.intellij.ide.util.DirectoryChooserUtil; @@ -13,11 +13,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDirectory; import com.intellij.util.PlatformIcons; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; public class CCCreateLesson extends DumbAwareAction { public CCCreateLesson() { diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateTask.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java similarity index 94% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateTask.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java index 216727cb266d..1a83436de9dd 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateTask.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.ide.IdeView; import com.intellij.ide.fileTemplates.FileTemplate; @@ -20,12 +20,12 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.util.PlatformIcons; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.CCUtils; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; -import org.jetbrains.plugins.coursecreator.format.Task; public class CCCreateTask extends DumbAwareAction { public CCCreateTask() { diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateTaskFile.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java similarity index 90% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateTaskFile.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java index 69b67190346a..6296ee839af4 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateTaskFile.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java @@ -1,5 +1,6 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; +import com.intellij.icons.AllIcons; import com.intellij.ide.IdeView; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; @@ -16,17 +17,16 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; -import icons.PythonPsiApiIcons; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; -import org.jetbrains.plugins.coursecreator.format.Task; public class CCCreateTaskFile extends DumbAwareAction { public CCCreateTaskFile() { - super("Task File", "Create new Task File", PythonPsiApiIcons.PythonFile); + super("Task File", "Create new Task File", AllIcons.FileTypes.Text); } @Override diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java similarity index 83% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java index f7245a05fe9f..a1ebd24f4c2e 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -6,11 +6,11 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.TaskFile; +import com.jetbrains.edu.coursecreator.format.TaskWindow; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.TaskFile; -import org.jetbrains.plugins.coursecreator.format.TaskWindow; import java.util.List; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRename.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java similarity index 95% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRename.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java index dbaee7590277..30265ae05b6e 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRename.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.ide.IdeView; import com.intellij.ide.projectView.ProjectView; @@ -26,9 +26,9 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.Course; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.Course; import javax.swing.*; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRenameLesson.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java similarity index 88% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRenameLesson.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java index 3f580454ed6e..eaea9bf7e0ad 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRenameLesson.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDirectory; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; public class CCRenameLesson extends CCRename { diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRenameTask.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java similarity index 87% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRenameTask.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java index 342621bf0d47..4690d0d1993f 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRenameTask.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDirectory; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; -import org.jetbrains.plugins.coursecreator.format.Task; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; public class CCRenameTask extends CCRename { public CCRenameTask() { diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java similarity index 84% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java index 777afc4e1a85..2d8d3a6980a3 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java @@ -13,14 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; -import com.intellij.execution.*; +import com.intellij.execution.Location; import com.intellij.execution.actions.ConfigurationContext; -import com.intellij.execution.configurations.ConfigurationFactory; -import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.icons.AllIcons; -import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; @@ -32,25 +29,21 @@ 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.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.util.PathUtil; import com.intellij.util.containers.HashMap; -import com.jetbrains.python.run.PythonConfigurationType; -import com.jetbrains.python.run.PythonRunConfiguration; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.*; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; -public class CCRunTestsAction extends AnAction { +public abstract class CCRunTestsAction extends AnAction { private static final Logger LOG = Logger.getInstance(CCRunTestsAction.class.getName()); public CCRunTestsAction() { @@ -114,7 +107,7 @@ public class CCRunTestsAction extends AnAction { run(context); } - public static void run(final @NotNull ConfigurationContext context) { + public void run(final @NotNull ConfigurationContext context) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -199,34 +192,10 @@ public class CCRunTestsAction extends AnAction { } } - private static void executeTests(@NotNull final Project project, + protected abstract 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()); - VirtualFile userFile = taskDir.findChild(virtualFile.getNameWithoutExtension() + ".py"); - if (userFile == null) { - return; - } - VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); - if (ideaDir == null) { - return; - } - VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); - ProjectView.getInstance(project).refresh(); - VirtualFile courseDir = ideaDir.findChild("course"); - if (courseDir == null) { - return; - } - configuration.setScriptParameters(PathUtil.toSystemDependentName(courseDir.getPath()) + " " + PathUtil.toSystemDependentName(userFile.getPath())); - Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - ProgramRunnerUtil.executeConfiguration(project, settings, executor); - } + @NotNull final VirtualFile testFile); @Nullable private static Task getTask(@NotNull final Course course, @NotNull final VirtualFile taskDir) { diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowPreview.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java similarity index 94% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowPreview.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java index 97a1b0300688..4578ba87388d 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowPreview.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -34,16 +34,15 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; -import com.intellij.util.containers.hash.HashMap; -import com.jetbrains.python.PythonFileType; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.*; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.*; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.HashMap; import java.util.Map; public class CCShowPreview extends DumbAwareAction { @@ -118,7 +117,7 @@ public class CCShowPreview extends DumbAwareAction { if (document == null) { return; } - final EditorEx createdEditor = (EditorEx)factory.createEditor(document, project, PythonFileType.INSTANCE, true); + final EditorEx createdEditor = (EditorEx)factory.createEditor(document, project, userFile, true); Disposer.register(project, new Disposable() { public void dispose() { factory.releaseEditor(createdEditor); diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java similarity index 85% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java index e8ae02bf44fa..fc235c2e8c69 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java @@ -1,12 +1,12 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.*; +import com.jetbrains.edu.coursecreator.ui.CreateTaskWindowDialog; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.*; -import org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowDialog; public class CCShowTaskWindowDetails extends CCTaskWindowAction { diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCTaskWindowAction.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java similarity index 93% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCTaskWindowAction.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java index 1917c308c1e7..1d7a8e31adca 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCTaskWindowAction.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.actions; +package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -8,11 +8,11 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.TaskFile; +import com.jetbrains.edu.coursecreator.format.TaskWindow; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.TaskFile; -import org.jetbrains.plugins.coursecreator.format.TaskWindow; import javax.swing.*; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Course.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Course.java similarity index 96% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Course.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Course.java index e9af3472f260..7d725e7b19c9 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Course.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Course.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.format; +package com.jetbrains.edu.coursecreator.format; import com.google.gson.annotations.Expose; import com.intellij.psi.PsiDirectory; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Lesson.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Lesson.java similarity index 96% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Lesson.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Lesson.java index bd91e8ec30af..360c37244a1a 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Lesson.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Lesson.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.format; +package com.jetbrains.edu.coursecreator.format; import com.google.gson.annotations.Expose; import com.intellij.psi.PsiDirectory; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Task.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Task.java similarity index 91% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Task.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Task.java index 886add86ceb4..453fa007b28b 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/Task.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Task.java @@ -1,8 +1,8 @@ -package org.jetbrains.plugins.coursecreator.format; +package com.jetbrains.edu.coursecreator.format; import com.google.gson.annotations.Expose; +import com.jetbrains.edu.coursecreator.CCProjectService; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; import java.util.HashMap; import java.util.Map; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskFile.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/TaskFile.java similarity index 98% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskFile.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/TaskFile.java index 9fb10eaa179a..df5e5d0bc521 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskFile.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/TaskFile.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.format; +package com.jetbrains.edu.coursecreator.format; import com.google.gson.annotations.Expose; import com.intellij.openapi.editor.Document; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskWindow.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/TaskWindow.java similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskWindow.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/TaskWindow.java index 385aaeddf26e..edcca8a7e7e7 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskWindow.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/TaskWindow.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.format; +package com.jetbrains.edu.coursecreator.format; import com.google.gson.annotations.Expose; import com.intellij.openapi.editor.Document; @@ -14,8 +14,8 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBColor; +import com.jetbrains.edu.coursecreator.CCProjectService; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; import java.io.File; import java.util.List; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/projectView/CCDirectoryNode.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java similarity index 88% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/projectView/CCDirectoryNode.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java index 0969c54563c2..eb48a7af42a8 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/projectView/CCDirectoryNode.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.projectView; +package com.jetbrains.edu.coursecreator.projectView; import com.intellij.ide.projectView.PresentationData; import com.intellij.ide.projectView.ViewSettings; @@ -6,11 +6,11 @@ import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.ui.SimpleTextAttributes; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.coursecreator.format.Task; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.Course; -import org.jetbrains.plugins.coursecreator.format.Lesson; -import org.jetbrains.plugins.coursecreator.format.Task; public class CCDirectoryNode extends PsiDirectoryNode { private final PsiDirectory myValue; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/projectView/CCTreeStructureProvider.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java similarity index 95% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/projectView/CCTreeStructureProvider.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java index 89d09f73c28c..e3a0ae7a3127 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/projectView/CCTreeStructureProvider.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.projectView; +package com.jetbrains.edu.coursecreator.projectView; import com.intellij.ide.projectView.TreeStructureProvider; import com.intellij.ide.projectView.ViewSettings; @@ -8,9 +8,9 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; +import com.jetbrains.edu.coursecreator.CCProjectService; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.CCProjectService; import java.util.ArrayList; import java.util.Collection; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CCNewProjectPanel.form b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CCNewProjectPanel.form rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form index d0a931467943..67b2e6c3e5fe 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CCNewProjectPanel.form +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form @@ -1,5 +1,5 @@ -
+ diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CCNewProjectPanel.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CCNewProjectPanel.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java index 82041dc7734f..116104929d68 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CCNewProjectPanel.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.ui; +package com.jetbrains.edu.coursecreator.ui; import com.intellij.facet.ui.FacetValidatorsManager; import com.intellij.openapi.util.text.StringUtil; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchiveDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchiveDialog.java similarity index 88% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchiveDialog.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchiveDialog.java index 0ce36e3f2cc5..6412f30b99e0 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchiveDialog.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchiveDialog.java @@ -1,10 +1,10 @@ -package org.jetbrains.plugins.coursecreator.ui; +package com.jetbrains.edu.coursecreator.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.jetbrains.edu.coursecreator.actions.CCCreateCourseArchive; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.actions.CCCreateCourseArchive; import javax.swing.*; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchivePanel.form b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchivePanel.form similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchivePanel.form rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchivePanel.form index 096a85f8da59..ca2414a7c282 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchivePanel.form +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchivePanel.form @@ -1,5 +1,5 @@ - + diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchivePanel.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchivePanel.java similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchivePanel.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchivePanel.java index 4e7deedf7e47..293426598828 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateCourseArchivePanel.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateCourseArchivePanel.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.ui; +package com.jetbrains.edu.coursecreator.ui; import com.intellij.icons.AllIcons; import com.intellij.openapi.fileChooser.FileChooserDescriptor; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java similarity index 97% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java index bcde449693b0..fc0a094623c4 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.ui; +package com.jetbrains.edu.coursecreator.ui; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.diagnostic.Logger; @@ -8,10 +8,10 @@ import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; +import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.format.TaskWindow; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.coursecreator.CCProjectService; -import org.jetbrains.plugins.coursecreator.format.TaskWindow; import javax.swing.*; import java.io.*; diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowPanel.form b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form similarity index 98% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowPanel.form rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form index 5348fbbc016f..182dd58629e8 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowPanel.form +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form @@ -1,5 +1,5 @@ - + diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowPanel.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java similarity index 98% rename from python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowPanel.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java index a09945718aaa..9ab4d9a8c448 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowPanel.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java @@ -1,4 +1,4 @@ -package org.jetbrains.plugins.coursecreator.ui; +package com.jetbrains.edu.coursecreator.ui; import com.intellij.ui.DocumentAdapter; diff --git a/python/educational/educational.iml b/python/educational/educational.iml new file mode 100644 index 000000000000..c90834f2d607 --- /dev/null +++ b/python/educational/educational.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/python/educational/interactive-learning/interactive-learning.iml b/python/educational/interactive-learning/interactive-learning.iml new file mode 100644 index 000000000000..c90834f2d607 --- /dev/null +++ b/python/educational/interactive-learning/interactive-learning.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file From 7e7608c8009500729329a3be3c56d2bca75c5e01 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 14 Jan 2015 14:28:55 +0300 Subject: [PATCH 02/55] IDEA-131754 Catch and finally blocks have no line information --- .../modules/code/DeadCodeHelper.java | 3 ++- .../engine/testData/results/TestClassLoop.dec | 10 ++++++++-- .../TestClassSimpleBytecodeMapping.dec | 11 +++++++++-- .../engine/testData/results/TestClassVar.dec | 5 ++++- .../results/TestSynchronizedMapping.dec | 1 + .../testData/results/TestTryCatchFinally.dec | 19 ++++++++++++++++--- 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/code/DeadCodeHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/code/DeadCodeHelper.java index c7dd8ca1c173..233011df296a 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/code/DeadCodeHelper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/code/DeadCodeHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -416,6 +416,7 @@ public class DeadCodeHelper { if (sameRanges) { seq.addSequence(next.getSeq()); + block.getInstrOldOffsets().addAll(next.getInstrOldOffsets()); next.getSeq().clear(); removeEmptyBlock(graph, next, true); diff --git a/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec b/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec index 5384a981e0f3..f3bf0e07304d 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec @@ -16,7 +16,7 @@ public class TestClassLoop { return; } } finally { - System.out.println("1"); + System.out.println("1");// 38 } } } @@ -30,7 +30,7 @@ public class TestClassLoop { System.out.println("1");// 49 break; } finally { - if(var0) { + if(var0) {// 52 System.out.println("3");// 53 continue; } @@ -54,6 +54,9 @@ class 'pkg/TestClassLoop' { 4 10 d 10 f 14 + 26 18 + 27 18 + 2a 18 } method 'testFinallyContinue ()V' { @@ -64,6 +67,7 @@ class 'pkg/TestClassLoop' { e 29 11 29 13 29 + 26 32 2a 33 2d 33 2f 33 @@ -74,6 +78,8 @@ Lines mapping: 23 <-> 6 29 <-> 11 33 <-> 15 +38 <-> 19 45 <-> 25 49 <-> 30 +52 <-> 33 53 <-> 34 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec index 291151311a18..b6b6bba690cb 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec @@ -22,9 +22,9 @@ public class TestClassSimpleBytecodeMapping { try { Integer.parseInt(var1);// 34 } catch (Exception var6) { - System.out.println(var6); + System.out.println(var6);// 36 } finally { - System.out.println("Finally"); + System.out.println("Finally");// 38 } } @@ -80,6 +80,11 @@ class 'pkg/TestClassSimpleBytecodeMapping' { method 'test2 (Ljava/lang/String;)V' { 1 22 + 11 24 + 15 24 + 23 26 + 24 26 + 27 26 } method 'run (Ljava/lang/Runnable;)V' { @@ -114,6 +119,8 @@ Lines mapping: 27 <-> 16 28 <-> 17 34 <-> 23 +36 <-> 25 +38 <-> 27 44 <-> 44 49 <-> 33 54 <-> 38 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassVar.dec b/plugins/java-decompiler/engine/testData/results/TestClassVar.dec index 14d2e070393d..cedd9c0d80a0 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassVar.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassVar.dec @@ -9,7 +9,7 @@ public class TestClassVar { try { System.out.println();// 29 } finally { - if(this.field_boolean) { + if(this.field_boolean) {// 32 System.out.println();// 33 } @@ -46,6 +46,8 @@ class 'pkg/TestClassVar' { 3 7 8 9 b 9 + 1f 11 + 20 11 26 12 29 12 } @@ -73,6 +75,7 @@ class 'pkg/TestClassVar' { Lines mapping: 26 <-> 8 29 <-> 10 +32 <-> 12 33 <-> 13 40 <-> 22 45 <-> 26 diff --git a/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec b/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec index ca38d8c0e732..6ba9f3352815 100644 --- a/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec @@ -16,6 +16,7 @@ class 'pkg/TestSynchronizedMapping' { method 'test (I)I' { 3 4 5 5 + a 5 } method 'test2 (Ljava/lang/String;)V' { diff --git a/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec b/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec index 673238ec14fb..2dc71a58633f 100644 --- a/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec +++ b/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec @@ -11,7 +11,7 @@ public class TestTryCatchFinally { ; } } finally { - System.out.println("finally"); + System.out.println("finally");// 34 } } @@ -31,9 +31,9 @@ public class TestTryCatchFinally { int var2 = Integer.parseInt(var1);// 51 return var2; } catch (Exception var6) { - System.out.println("Error" + var6); + System.out.println("Error" + var6);// 53 } finally { - System.out.println("Finally"); + System.out.println("Finally");// 55 } return -1; @@ -48,6 +48,9 @@ class 'pkg/TestTryCatchFinally' { 14 8 17 8 19 8 + 2b 13 + 2d 13 + 30 13 } method 'foo (I)I' { @@ -63,15 +66,25 @@ class 'pkg/TestTryCatchFinally' { method 'test (Ljava/lang/String;)I' { 1 30 4 30 + 10 33 + 1a 33 + 23 33 + 26 33 + 34 35 + 35 35 + 38 35 } } Lines mapping: 24 <-> 6 27 <-> 9 +34 <-> 14 39 <-> 20 40 <-> 21 41 <-> 22 42 <-> 23 45 <-> 25 51 <-> 31 +53 <-> 34 +55 <-> 36 From 34441726d64cd97f4018ab53fff3f911485a931d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 14 Jan 2015 11:26:25 +0100 Subject: [PATCH 03/55] IDEA-135185 (Exception in "Cyclic class dependency" inspection) --- .../CyclicClassDependencyInspection.java | 15 ++++----------- .../cyclic_class_dependency/expected.xml | 7 ------- .../cyclic_class_dependency/src/Cyclic.java | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicClassDependencyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicClassDependencyInspection.java index cb512f97ecbd..b501653d6dc1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicClassDependencyInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicClassDependencyInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2013 Dave Griffith, Bas Leijdekkers + * Copyright 2006-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,7 +52,7 @@ public class CyclicClassDependencyInspection extends BaseGlobalInspection { } final RefClass refClass = (RefClass)refEntity; final PsiClass aClass = refClass.getElement(); - if (aClass == null || aClass.getContainingClass() != null) { + if (aClass == null || aClass.getContainingClass() != null || aClass instanceof PsiAnonymousClass) { return null; } final Set dependencies = DependencyUtils.calculateTransitiveDependenciesForClass(refClass); @@ -79,15 +79,8 @@ public class CyclicClassDependencyInspection extends BaseGlobalInspection { errorString = InspectionGadgetsBundle.message("cyclic.class.dependency.problem.descriptor", refEntity.getName(), Integer.valueOf(numMutualDependents)); } - final PsiElement anchor; - if (aClass instanceof PsiAnonymousClass) { - final PsiAnonymousClass anonymousClass = (PsiAnonymousClass)aClass; - anchor = anonymousClass.getBaseClassReference(); - } - else { - anchor = aClass.getNameIdentifier(); - if (anchor == null) return null; - } + final PsiElement anchor = aClass.getNameIdentifier(); + if (anchor == null) return null; return new CommonProblemDescriptor[]{ inspectionManager.createProblemDescriptor(anchor, errorString, (LocalQuickFix)null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false) diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml index 4e19f4850c1b..d75c4d2e2d95 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml @@ -1,12 +1,5 @@ - - Cyclic.java - 9 - Cyclic class dependency - Class 'anonymous (java.lang.Object)' is cyclically dependent on 3 other classes - - Cyclic.java 17 diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java index e0f9cf48061a..e8f750c99fa3 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java @@ -27,3 +27,18 @@ interface FiveOClock { } interface Coffee extends FiveOClock {} +enum MyEnum { + ONE { + public int value() { + return 0; + } + }, + + TWO { + public int value() { + return ONE.value(); + } + }; + + abstract int value(); +} From f8a49b10a3a90b60520aaeac830c2a8bf15f6bfe Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 14 Jan 2015 11:35:44 +0100 Subject: [PATCH 04/55] IG: fix option so it is useful --- .../siyeh/InspectionGadgetsBundle.properties | 3 ++- ...oneDeclaresCloneNotSupportedInspection.java | 18 +++++++++--------- .../CloneDeclaresCloneNotSupported.html | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 459950f67bf8..547635b92ad1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2135,7 +2135,8 @@ utility.class.code.can.be.enum.quickfix=Convert to 'enum' non.public.clone.display.name='clone()' method not 'public' non.public.clone.problem.descriptor=#ref() method not 'public' #loc only.warn.on.public.clone.methods=Only warn on 'public' clone methods +only.warn.on.protected.clone.methods=Only warn on 'protected' clone methods clone.returns.class.type.display.name='clone()' should have return type equal to the class it contains clone.returns.class.type.problem.descriptor=''clone()'' should have return type ''{0}'' #loc -clone.returns.class.type.quickfix=Change return type to '{0}' +clone.returns.class.type.quickfix=Change return type to ''{0}'' clone.returns.class.type.family.quickfix=Change return type to class type diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java index 3f605269bff4..b91bec416a28 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspection.java @@ -39,7 +39,7 @@ import javax.swing.*; public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection { - private boolean onlyWarnOnPublicClone = true; + private boolean onlyWarnOnProtectedClone = true; @Override @NotNull @@ -67,16 +67,16 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection { @Nullable @Override public JComponent createOptionsPanel() { - return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("only.warn.on.public.clone.methods"), - this, "onlyWarnOnPublicClone"); + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("only.warn.on.protected.clone.methods"), + this, "onlyWarnOnProtectedClone"); } @Override public void readSettings(@NotNull Element node) throws InvalidDataException { super.readSettings(node); for (Element option : node.getChildren("option")) { - if ("onlyWarnOnPublicClone".equals(option.getAttributeValue("name"))) { - onlyWarnOnPublicClone = Boolean.parseBoolean(option.getAttributeValue("value")); + if ("onlyWarnOnProtectedClone".equals(option.getAttributeValue("name"))) { + onlyWarnOnProtectedClone = Boolean.parseBoolean(option.getAttributeValue("value")); } } } @@ -84,9 +84,9 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection { @Override public void writeSettings(@NotNull Element node) throws WriteExternalException { super.writeSettings(node); - if (!onlyWarnOnPublicClone) { - node.addContent(new Element("option").setAttribute("name", "onlyWarnOnPublicClone") - .setAttribute("value", String.valueOf(onlyWarnOnPublicClone))); + if (!onlyWarnOnProtectedClone) { + node.addContent(new Element("option").setAttribute("name", "onlyWarnOnProtectedClone") + .setAttribute("value", String.valueOf(onlyWarnOnProtectedClone))); } } @@ -131,7 +131,7 @@ public class CloneDeclaresCloneNotSupportedInspection extends BaseInspection { if (method.hasModifierProperty(PsiModifier.FINAL)) { return; } - if (onlyWarnOnPublicClone && !method.hasModifierProperty(PsiModifier.PUBLIC)) { + if (onlyWarnOnProtectedClone && method.hasModifierProperty(PsiModifier.PUBLIC)) { return; } final PsiClass containingClass = method.getContainingClass(); diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/CloneDeclaresCloneNotSupported.html b/plugins/InspectionGadgets/src/inspectionDescriptions/CloneDeclaresCloneNotSupported.html index e50bfac4f8df..b1f175d56f7e 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/CloneDeclaresCloneNotSupported.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/CloneDeclaresCloneNotSupported.html @@ -8,9 +8,9 @@ prohibit cloning will not be able to do so in the standard way. This inspection or clone() methods on final classes.

-Use the checkbox below to indicate if this inspection should only warn on public methods. +Use the checkbox below to indicate if this inspection should only warn on protected methods. In Effective Java, Second Edition (but not in the first edition) it is recommended to omit the CloneNotSupportedException -declaration, because methods that don't throw checked exceptions are easier to use. +declaration on public methods, because methods that don't throw checked exceptions are easier to use.

From 852b48aaaf946fc3ff23490d1c5c320ed5cf4a4c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 14 Jan 2015 11:44:26 +0100 Subject: [PATCH 05/55] make IG test light and test new option --- .../CloneDeclaresCloneNonSupportedException.java | 12 +++++++++++- .../expected.xml | 9 --------- ...eDeclaresCloneNotSupportedInspectionTest.java | 16 ++++++++++++---- 3 files changed, 23 insertions(+), 14 deletions(-) delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/CloneDeclaresCloneNonSupportedException.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/CloneDeclaresCloneNonSupportedException.java index 461fd61ca5d7..4c71a4ad77ef 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/CloneDeclaresCloneNonSupportedException.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/CloneDeclaresCloneNonSupportedException.java @@ -8,7 +8,7 @@ public class CloneDeclaresCloneNonSupportedException implements Cloneable } - public Object clone() + protected Object clone() { try { @@ -34,3 +34,13 @@ class Child extends CloneDeclaresCloneNonSupportedException { return super.clone(); } } +class NoWarnOnPublic implements Cloneable { + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); + } + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/expected.xml deleted file mode 100644 index 017ae12ebb44..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_declares_clone_not_supported/expected.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - CloneDeclaresCloneNonSupportedException.java - 11 - 'clone()' does not declare 'CloneNotSupportedException' - <code>clone()</code> does not declare 'CloneNotSupportedException' - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspectionTest.java index 5b88db3d2659..3f3a0e373801 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneDeclaresCloneNotSupportedInspectionTest.java @@ -1,10 +1,18 @@ package com.siyeh.ig.cloneable; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; -public class CloneDeclaresCloneNotSupportedInspectionTest extends IGInspectionTestCase { +public class CloneDeclaresCloneNotSupportedInspectionTest extends LightInspectionTestCase { - public void test() throws Exception { - doTest("com/siyeh/igtest/cloneable/clone_declares_clone_not_supported", new CloneDeclaresCloneNotSupportedInspection()); + public void testCloneDeclaresCloneNonSupportedException() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new CloneDeclaresCloneNotSupportedInspection(); } } \ No newline at end of file From 3f2212a179f4ae7a9166def4323866b59aef681c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 14 Jan 2015 12:35:09 +0100 Subject: [PATCH 06/55] IDEA-135189 (False positive of "Type may be weakened") --- .../TypeMayBeWeakenedInspection.java | 5 ++-- .../siyeh/ig/psiutils/WeakestTypeFinder.java | 14 +++++++---- .../abstraction/weaken_type/Lambda.java | 23 +++++++++++++++++++ .../TypeMayBeWeakenedInspectionTest.java | 6 +++++ 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/Lambda.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java index 2787f34e4dcf..ec2778f79c5b 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2014 Bas Leijdekkers + * Copyright 2006-2015 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package com.siyeh.ig.abstraction; import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -294,7 +295,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection { @Override public void visitMethod(PsiMethod method) { super.visitMethod(method); - if (isOnTheFly() && !method.hasModifierProperty(PsiModifier.PRIVATE)) { + if (isOnTheFly() && !method.hasModifierProperty(PsiModifier.PRIVATE) && !ApplicationManager.getApplication().isUnitTestMode()) { // checking methods with greater visibility is too expensive. // for error checking in the editor return; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java index 835d841e0de8..23851eed4952 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2014 Bas Leijdekkers + * Copyright 2008-2015 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -155,11 +155,17 @@ public class WeakestTypeFinder { checkClass(javaLangIterableClass, weakestTypeClasses); } else if (referenceParent instanceof PsiReturnStatement) { - final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(referenceParent, PsiMethod.class); - if (containingMethod == null) { + final PsiElement owner = PsiTreeUtil.getParentOfType(referenceParent, PsiMethod.class, PsiLambdaExpression.class); + final PsiType type; + if (owner instanceof PsiMethod) { + type = ((PsiMethod)owner).getReturnType(); + } + else if (owner instanceof PsiLambdaExpression) { + type = LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)owner); + } + else { return Collections.emptyList(); } - final PsiType type = containingMethod.getReturnType(); if (!checkType(type, weakestTypeClasses)) { return Collections.emptyList(); } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/Lambda.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/Lambda.java new file mode 100644 index 000000000000..01cdacd79161 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/Lambda.java @@ -0,0 +1,23 @@ +package com.siyeh.igtest.abstraction.weaken_type; + +import java.util.function.Supplier; + +public interface Lambda { + + int count(); + + static Lambda newWeaken(int value) { + return new Lambda() { + @Override + public int count() { + return value; + } + }; + } + + static Supplier newSupplier() { + return () -> { + return Lambda.newWeaken(0); + }; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java index 52e5e8cc3db2..20e587914e40 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java @@ -9,6 +9,7 @@ public class TypeMayBeWeakenedInspectionTest extends LightInspectionTestCase { public void testTypeMayBeWeakened() { doTest(); } public void testNumberAdderDemo() { doTest(); } public void testAutoClosableTest() { doTest(); } + public void testLambda() { doTest(); } @Override protected String[] getEnvironmentClasses() { @@ -33,6 +34,11 @@ public class TypeMayBeWeakenedInspectionTest extends LightInspectionTestCase { "@FunctionalInterface " + "public interface Function {" + " R apply(T t);" + + "}", + "package java.util.function;\n" + + "@FunctionalInterface\n" + + "public interface Supplier {\n" + + " T get();\n" + "}" }; } From 1854a24555bebb3142bc137a7f49366aa7ae9bca Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 14 Jan 2015 12:42:16 +0100 Subject: [PATCH 07/55] Platform: help topic for 'Non-project file edit' dialog (IDEA-121829) + clarified options' test IDEA-133451 Default action for return key unlocks framework headers --- .../fileEditor/impl/NonProjectFileWritingAccessDialog.form | 4 ++-- .../fileEditor/impl/NonProjectFileWritingAccessDialog.java | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form index 33a20bc8b164..01173794cbeb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form @@ -22,7 +22,7 @@ - + @@ -30,7 +30,7 @@ - + diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java index f85a0bf52ab1..397ff73da184 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java @@ -38,9 +38,13 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper { myFileList.setCellRenderer(new FileListRenderer()); myFileList.setModel(new CollectionListModel(nonProjectFiles)); + getOKAction().putValue(DEFAULT_ACTION, null); + getCancelAction().putValue(DEFAULT_ACTION, true); + init(); } + @Nullable @Override protected JComponent createCenterPanel() { @@ -54,6 +58,6 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper { } protected String getHelpId() { - return "readOnlyHandler.nonProjectFilesDialog"; + return "Non-Project_Files_Access_Dialog"; } } From e546f26c2265972f227b6011afb1e0ca89a53d45 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 14 Jan 2015 12:48:15 +0100 Subject: [PATCH 08/55] ability to cancel during reading index data chunks (e.g. there can be many chunks IDEA-132648) --- .../util/indexing/MapIndexStorage.java | 16 ++++++++++++++-- .../io/PersistentHashMapValueStorage.java | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java index ec7795d01585..010972cd18c3 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java @@ -84,9 +84,21 @@ public final class MapIndexStorage implements IndexStorage map = new ValueContainerMap(myStorageFile, myKeyDescriptor, myDataExternalizer, - myKeyIsUniqueForIndexedFile); + final ValueContainerMap map; + PersistentHashMapValueStorage.CreationTimeOptions.EXCEPTIONAL_IO_CANCELLATION.set(ourProgressManagerCheckCancelledIOCanceller); + try { + map = new ValueContainerMap(myStorageFile, myKeyDescriptor, myDataExternalizer, myKeyIsUniqueForIndexedFile); + } finally { + PersistentHashMapValueStorage.CreationTimeOptions.EXCEPTIONAL_IO_CANCELLATION.set(null); + } myCache = new SLRUCache>(myCacheSize, (int)(Math.ceil(myCacheSize * 0.25)) /* 25% from the main cache size*/) { @Override @NotNull diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java b/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java index ee596a2ac9aa..bb6b90b97926 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java @@ -38,11 +38,20 @@ public class PersistentHashMapValueStorage { private volatile long mySize; private final File myFile; private final String myPath; + private final ExceptionalIOCancellationCallback myExceptionalIOCancellationCallback; private boolean myCompactionMode = false; private static final int CACHE_PROTECTED_QUEUE_SIZE = 10; private static final int CACHE_PROBATIONAL_QUEUE_SIZE = 20; + public static class CreationTimeOptions { + public static final ThreadLocal EXCEPTIONAL_IO_CANCELLATION = new ThreadLocal(); + } + + public interface ExceptionalIOCancellationCallback { + void checkCancellation(); + } + // cache size is twice larger than constants because (when used) it replaces two caches private static final FileAccessorCache ourRandomAccessFileCache = new FileAccessorCache( 2*CACHE_PROTECTED_QUEUE_SIZE, 2*CACHE_PROBATIONAL_QUEUE_SIZE) { @@ -93,6 +102,7 @@ public class PersistentHashMapValueStorage { }; public PersistentHashMapValueStorage(String path) throws IOException { + myExceptionalIOCancellationCallback = CreationTimeOptions.EXCEPTIONAL_IO_CANCELLATION.get(); myPath = path; myFile = new File(path); mySize = myFile.length(); // volatile write @@ -322,6 +332,7 @@ public class PersistentHashMapValueStorage { public ReadResult readBytes(long tailChunkAddress) throws IOException { force(); + checkCancellation(); long chunk = tailChunkAddress; int chunkCount = 0; @@ -362,6 +373,8 @@ public class PersistentHashMapValueStorage { chunk = prevChunkAddress; chunkCount++; + + if (prevChunkAddress != 0) checkCancellation(); if (result.length > mySize) { throw new PersistentEnumeratorBase.CorruptedException(myFile); } @@ -377,6 +390,7 @@ public class PersistentHashMapValueStorage { } if (chunkCount > 1 && !myCompactionMode) { + checkCancellation(); long l = appendBytes(new ByteSequence(result), 0); return new ReadResult(l, result); } @@ -384,6 +398,11 @@ public class PersistentHashMapValueStorage { return new ReadResult(tailChunkAddress, result); } + // hook for exceptional termination of long io operation + protected void checkCancellation() { + if (myExceptionalIOCancellationCallback != null) myExceptionalIOCancellationCallback.checkCancellation(); + } + private long readPrevChunkAddress(long chunk) throws IOException { final long prevOffsetDiff = DataInputOutputUtil.readLONG(myBufferDataStreamWrapper); assert prevOffsetDiff < chunk:chunk + "," + prevOffsetDiff + "," + mySize; From 301f512e336ade26451200bceb56636641b8993b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 13 Jan 2015 11:21:59 +0100 Subject: [PATCH 09/55] jps: toString() for root types (debuggability) --- .../jps/model/java/JpsAnnotationRootType.java | 8 ++++++-- .../jps/model/java/JpsNativeLibraryRootType.java | 8 ++++++-- .../jps/model/library/JpsOrderRootType.java | 14 +++++++++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java index b62cc2cbf04a..e9219efcab20 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsAnnotationRootType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -23,6 +23,10 @@ import org.jetbrains.jps.model.library.JpsOrderRootType; public class JpsAnnotationRootType extends JpsOrderRootType { public static final JpsAnnotationRootType INSTANCE = new JpsAnnotationRootType(); - private JpsAnnotationRootType() { + private JpsAnnotationRootType() { } + + @Override + public String toString() { + return "annotation root"; } } diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsNativeLibraryRootType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsNativeLibraryRootType.java index ae2e87b966f1..2134e19f5116 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/JpsNativeLibraryRootType.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsNativeLibraryRootType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -23,6 +23,10 @@ import org.jetbrains.jps.model.library.JpsOrderRootType; public class JpsNativeLibraryRootType extends JpsOrderRootType { public static final JpsNativeLibraryRootType INSTANCE = new JpsNativeLibraryRootType(); - private JpsNativeLibraryRootType() { + private JpsNativeLibraryRootType() { } + + @Override + public String toString() { + return "native lib root"; } } diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java index 89fa4efc4187..36ba254bfbd3 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java +++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsOrderRootType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,9 +20,21 @@ package org.jetbrains.jps.model.library; */ public abstract class JpsOrderRootType { public static final JpsOrderRootType COMPILED = new JpsOrderRootType() { + @Override + public String toString() { + return "compiled root"; + } }; public static final JpsOrderRootType SOURCES = new JpsOrderRootType() { + @Override + public String toString() { + return "sources root"; + } }; public static final JpsOrderRootType DOCUMENTATION = new JpsOrderRootType() { + @Override + public String toString() { + return "documentation root"; + } }; } From 2a8ecbc6f38b839a14d21a3ac4c042a112b7dc66 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 12 Jan 2015 16:15:36 +0100 Subject: [PATCH 10/55] Cleanup (formatting; explicit assertions; dead code) --- .../projectRoots/impl/JavaSdkImpl.java | 82 +++++++++---------- .../jps/model/java/impl/JavaSdkUtil.java | 23 +++--- .../projectRoots/ui/SdkPathEditor.java | 3 +- .../src/com/intellij/openapi/vfs/VfsUtil.java | 3 +- 4 files changed, 53 insertions(+), 58 deletions(-) diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index f3d6575e9fd9..fa166a711999 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.intellij.openapi.projectRoots.impl; +import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.DataKey; @@ -28,12 +29,12 @@ import com.intellij.openapi.roots.JavadocOrderRootType; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.impl.JavaSdkUtil; @@ -51,13 +52,14 @@ import java.util.regex.Pattern; */ public class JavaSdkImpl extends JavaSdk { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.JavaSdkImpl"); - // do not use javaw.exe for Windows because of issues with encoding - @NonNls private static final String VM_EXE_NAME = "java"; - @NonNls private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$"); - @NonNls private static final String JAVA_VERSION_PREFIX = "java version "; - @NonNls private static final String OPENJDK_VERSION_PREFIX = "openjdk version "; + public static final DataKey KEY = DataKey.create("JavaSdk"); + private static final String VM_EXE_NAME = "java"; // do not use JavaW.exe for Windows because of issues with encoding + private static final Pattern VERSION_STRING_PATTERN = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$"); + private static final String JAVA_VERSION_PREFIX = "java version "; + private static final String OPENJDK_VERSION_PREFIX = "openjdk version "; + public JavaSdkImpl() { super("JavaSDK"); } @@ -83,7 +85,6 @@ public class JavaSdkImpl extends JavaSdk { return AllIcons.General.AddJdk; } - @NonNls @Override @Nullable public String getDefaultDocumentationUrl(@NotNull final Sdk sdk) { @@ -119,7 +120,6 @@ public class JavaSdkImpl extends JavaSdk { } @Override - @NonNls public String getToolsPath(@NotNull Sdk sdk) { final String versionString = sdk.getVersionString(); final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1")); @@ -128,11 +128,6 @@ public class JavaSdkImpl extends JavaSdk { @Override public String getVMExecutablePath(@NotNull Sdk sdk) { - /* - if ("64".equals(System.getProperty("sun.arch.data.model"))) { - return getBinPath(sdk) + File.separator + System.getProperty("os.arch") + File.separator + VM_EXE_NAME; - } - */ return getBinPath(sdk) + File.separator + VM_EXE_NAME; } @@ -150,8 +145,8 @@ public class JavaSdkImpl extends JavaSdk { @SuppressWarnings({"HardCodedStringLiteral"}) public String suggestHomePath() { if (SystemInfo.isMac) { - if (new File("/usr/libexec/java_home").exists()) { - final String path = ExecUtil.execAndReadLine("/usr/libexec/java_home"); + if (new File("/usr/libexec/java_home").canExecute()) { + String path = ExecUtil.execAndReadLine(new GeneralCommandLine("/usr/libexec/java_home")); if (path != null && new File(path).exists()) { return path; } @@ -180,6 +175,7 @@ public class JavaSdkImpl extends JavaSdk { return javaHome.getAbsolutePath(); } } + return null; } @@ -244,15 +240,13 @@ public class JavaSdkImpl extends JavaSdk { return descriptor; } - @NonNls public static final String MAC_HOME_PATH = "/Home"; - @Override public String adjustSelectedSdkHome(String homePath) { if (SystemInfo.isMac) { - File home = new File(homePath, MAC_HOME_PATH); + File home = new File(homePath, "/Home"); if (home.exists()) return home.getPath(); - home = new File(new File(homePath, "Contents"), "Home"); + home = new File(homePath, "Contents/Home"); if (home.exists()) return home.getPath(); } @@ -268,7 +262,7 @@ public class JavaSdkImpl extends JavaSdk { public String suggestSdkName(String currentSdkName, String sdkHome) { final String suggestedName; if (currentSdkName != null && !currentSdkName.isEmpty()) { - final Matcher matcher = myVersionStringPattern.matcher(currentSdkName); + final Matcher matcher = VERSION_STRING_PATTERN.matcher(currentSdkName); final boolean replaceNameWithVersion = matcher.matches(); if (replaceNameWithVersion){ // user did not change name -> set it automatically @@ -315,13 +309,16 @@ public class JavaSdkImpl extends JavaSdk { @Override @SuppressWarnings({"HardCodedStringLiteral"}) public void setupSdkPaths(@NotNull Sdk sdk) { - final File jdkHome = new File(sdk.getHomePath()); + String homePath = sdk.getHomePath(); + assert homePath != null : sdk; + + File jdkHome = new File(homePath); List classes = findClasses(jdkHome, false); VirtualFile sources = findSources(jdkHome); VirtualFile docs = findDocs(jdkHome, "docs/api"); + SdkModificator sdkModificator = sdk.getSdkModificator(); - final SdkModificator sdkModificator = sdk.getSdkModificator(); - final Set previousRoots = new LinkedHashSet(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES))); + Set previousRoots = new LinkedHashSet(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES))); sdkModificator.removeRoots(OrderRootType.CLASSES); previousRoots.removeAll(new HashSet(classes)); for (VirtualFile aClass : classes) { @@ -330,14 +327,16 @@ public class JavaSdkImpl extends JavaSdk { for (VirtualFile root : previousRoots) { sdkModificator.addRoot(root, OrderRootType.CLASSES); } - if(sources != null){ + + if (sources != null) { sdkModificator.addRoot(sources, OrderRootType.SOURCES); } - final VirtualFile javaFxSources = findSources(jdkHome, "javafx-src"); + VirtualFile javaFxSources = findSources(jdkHome, "javafx-src"); if (javaFxSources != null) { sdkModificator.addRoot(javaFxSources, OrderRootType.SOURCES); } - if(docs != null){ + + if (docs != null) { sdkModificator.addRoot(docs, JavadocOrderRootType.getInstance()); } else if (SystemInfo.isMac) { @@ -366,12 +365,14 @@ public class JavaSdkImpl extends JavaSdk { sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl(url), JavadocOrderRootType.getInstance()); } } - } else { - if (getVersion(sdk) == JavaSdkVersion.JDK_1_7) { - sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl("http://docs.oracle.com/javafx/2/api/"), JavadocOrderRootType.getInstance()); - } } + else if (getVersion(sdk) == JavaSdkVersion.JDK_1_7) { + VirtualFile url = VirtualFileManager.getInstance().findFileByUrl("http://docs.oracle.com/javafx/2/api/"); + sdkModificator.addRoot(url, JavadocOrderRootType.getInstance()); + } + attachJdkAnnotations(sdkModificator); + sdkModificator.commitChanges(); } @@ -399,19 +400,14 @@ public class JavaSdkImpl extends JavaSdk { private final Map myCachedVersionStrings = new HashMap(); @Override - public final String getVersionString(final String sdkHome) { - if (myCachedVersionStrings.containsKey(sdkHome)) { - return myCachedVersionStrings.get(sdkHome); + public final String getVersionString(String sdkHome) { + String versionString = myCachedVersionStrings.get(sdkHome); + if (versionString == null) { + versionString = getJdkVersion(sdkHome); + if (!StringUtil.isEmpty(versionString)) { + myCachedVersionStrings.put(sdkHome, versionString); + } } - String versionString = getJdkVersion(sdkHome); - if (versionString != null && versionString.isEmpty()) { - versionString = null; - } - - if (versionString != null){ - myCachedVersionStrings.put(sdkHome, versionString); - } - return versionString; } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java index 66f7b4959938..a5a38dad44a1 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JavaSdkUtil.java @@ -33,13 +33,6 @@ import java.util.Set; public class JavaSdkUtil { @NotNull public static List getJdkClassesRoots(@NotNull File home, boolean isJre) { - FileFilter jarFileFilter = new FileFilter() { - @Override - public boolean accept(@NotNull File f) { - return !f.isDirectory() && f.getName().endsWith(".jar"); - } - }; - File[] jarDirs; if (SystemInfo.isMac && !home.getName().startsWith("mockJDK")) { File openJdkRtJar = new File(home, "jre/lib/rt.jar"); @@ -58,7 +51,7 @@ public class JavaSdkUtil { jarDirs = new File[]{libEndorsedDir, libDir, classesDir, libExtDir}; } } - else if (new File(home, "lib/modules").exists()) { + else if (new File(home, "lib/modules").isDirectory()) { File libDir = new File(home, "lib"); jarDirs = new File[]{libDir}; } @@ -69,6 +62,12 @@ public class JavaSdkUtil { jarDirs = new File[]{libEndorsedDir, libDir, libExtDir}; } + FileFilter jarFileFilter = new FileFilter() { + @Override + public boolean accept(@NotNull File f) { + return !f.isDirectory() && f.getName().endsWith(".jar"); + } + }; Set pathFilter = ContainerUtil.newTroveSet(FileUtil.PATH_HASHING_STRATEGY); List rootFiles = ContainerUtil.newArrayList(); for (File jarDir : jarDirs) { @@ -104,9 +103,11 @@ public class JavaSdkUtil { } } - File classesDir = new File(home, "classes"); - if (rootFiles.isEmpty() && classesDir.isDirectory()) { - rootFiles.add(classesDir); + if (rootFiles.isEmpty()) { + File classesDir = new File(home, "classes"); + if (classesDir.isDirectory()) { + rootFiles.add(classesDir); + } } return rootFiles; diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java index bb6f39dc5c2c..9d85290c249e 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -56,5 +56,4 @@ public class SdkPathEditor extends PathEditor { setEnabled(false); } } - } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java index 254f7749fb25..14c9d319b2d5 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -406,7 +406,6 @@ public class VfsUtil extends VfsUtilCore { * @return the relative path, or null if the files have no common ancestor. * @since 5.0.2 */ - @Nullable public static String getPath(@NotNull VirtualFile src, @NotNull VirtualFile dst, char separatorChar) { final VirtualFile commonAncestor = getCommonAncestor(src, dst); From 0591b4e1245abc0785297fa1973970ce35b90d7b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 12 Jan 2015 17:24:42 +0100 Subject: [PATCH 11/55] Cleanup (formatting; minor fixes; API usability) --- .../openapi/projectRoots/ui/PathEditor.java | 154 +++++++++--------- .../impl/ProjectRootManagerComponent.java | 65 ++++---- .../openapi/vfs/newvfs/ArchiveFileSystem.java | 11 +- .../com/intellij/util/io/HttpRequests.java | 5 +- .../vfs/impl/jar/JarFileSystemImpl.java | 16 +- .../vfs/impl/local/LocalFileSystemImpl.java | 15 +- .../openapi/vfs/newvfs/VfsImplUtil.java | 100 +++++++----- 7 files changed, 184 insertions(+), 182 deletions(-) diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java index ae9f0142f246..dd6415419249 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -26,10 +26,7 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.ex.http.HttpFileSystem; import com.intellij.ui.*; import com.intellij.ui.components.JBList; @@ -111,33 +108,36 @@ public class PathEditor { myList = new JBList(getListModel()); myList.setCellRenderer(createListCellRenderer(myList)); - ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myList).disableUpDownActions() + ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myList) + .disableUpDownActions() + .setAddActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + return myEnabled; + } + }) + .setRemoveActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + return isRemoveActionEnabled(PathEditor.this.getSelectedRoots()); + } + }) .setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { - final VirtualFile[] added = doAdd(); + final VirtualFile[] added = doAddItems(); if (added.length > 0) { setModified(true); } requestDefaultFocus(); setSelectedRoots(added); } - }).setRemoveAction(new AnActionButtonRunnable() { + }) + .setRemoveAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { - int[] idxs = myList.getSelectedIndices(); - doRemoveItems(idxs, myList); - } - }).setAddActionUpdater(new AnActionButtonUpdater() { - @Override - public boolean isEnabled(AnActionEvent e) { - return myEnabled; - } - }).setRemoveActionUpdater(new AnActionButtonUpdater() { - @Override - public boolean isEnabled(AnActionEvent e) { - Object[] values = getSelectedRoots(); - return values.length > 0 && myEnabled; + int[] indices = myList.getSelectedIndices(); + doRemoveItems(indices, myList); } }); @@ -152,28 +152,11 @@ public class PathEditor { protected void addToolbarButtons(ToolbarDecorator toolbarDecorator) { } - protected void doRemoveItems(int[] idxs, JList list) { - List removedItems = ListUtil.removeIndices(list, idxs); - itemsRemoved(removedItems); + protected boolean isRemoveActionEnabled(Object[] values) { + return values.length > 0 && myEnabled; } - protected DefaultListModel createListModel() { - return new DefaultListModel(); - } - - protected ListCellRenderer createListCellRenderer(JBList list) { - return new MyCellRenderer(); - } - - protected void itemsRemoved(List removedItems) { - myAllFiles.removeAll(removedItems); - if (removedItems.size() > 0) { - setModified(true); - } - requestDefaultFocus(); - } - - protected VirtualFile[] doAdd() { + protected VirtualFile[] doAddItems() { Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(myPanel)); VirtualFile[] files = FileChooser.chooseFiles(myDescriptor, myPanel, project, myAddBaseDir); files = adjustAddedFileSet(myPanel, files); @@ -183,7 +166,28 @@ public class PathEditor { added.add(vFile); } } - return VfsUtil.toVirtualFileArray(added); + return VfsUtilCore.toVirtualFileArray(added); + } + + protected void doRemoveItems(int[] indices, JList list) { + List removedItems = ListUtil.removeIndices(list, indices); + itemsRemoved(removedItems); + } + + protected DefaultListModel createListModel() { + return new DefaultListModel(); + } + + protected ListCellRenderer createListCellRenderer(JBList list) { + return new PathCellRenderer(); + } + + protected void itemsRemoved(List removedItems) { + myAllFiles.removeAll(removedItems); + if (removedItems.size() > 0) { + setModified(true); + } + requestDefaultFocus(); } /** @@ -284,17 +288,18 @@ public class PathEditor { private void keepSelectionState() { final Object[] selectedItems = getSelectedRoots(); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (selectedItems != null) { + if (selectedItems != null) { + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { setSelectedRoots(selectedItems); } - } - }); + }); + } } + @SuppressWarnings("deprecation") protected Object[] getSelectedRoots() { return myList.getSelectedValues(); } @@ -332,59 +337,46 @@ public class PathEditor { }).booleanValue(); } - /** - * @return icon for displaying parameter (ProjectRoot or VirtualFile) - * If parameter is not ProjectRoot or VirtualFile, returns empty icon "/nodes/emptyNode.png" - */ private static Icon getIconForRoot(Object projectRoot) { if (projectRoot instanceof VirtualFile) { - final VirtualFile file = (VirtualFile)projectRoot; + VirtualFile file = (VirtualFile)projectRoot; if (!file.isValid()) { return AllIcons.Nodes.PpInvalid; } - else if (isHttpRoot(file)) { + else if (file.getFileSystem() instanceof HttpFileSystem) { return PlatformIcons.WEB_ICON; } - else { - return isJarFile(file) ? PlatformIcons.JAR_ICON : PlatformIcons.FILE_ICON; + else if (isJarFile(file)) { + return PlatformIcons.JAR_ICON; } + return PlatformIcons.FILE_ICON; } + return AllIcons.Nodes.EmptyNode; } - private static boolean isHttpRoot(VirtualFile virtualFileOrProjectRoot) { - if (virtualFileOrProjectRoot != null) { - return (virtualFileOrProjectRoot.getFileSystem() instanceof HttpFileSystem); + protected static class PathCellRenderer extends DefaultListCellRenderer { + protected String getItemText(Object value) { + return value instanceof VirtualFile ? ((VirtualFile)value).getPresentableUrl() : "UNKNOWN OBJECT"; } - return false; - } - private final class MyCellRenderer extends DefaultListCellRenderer { - private String getPresentableString(final Object value) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public String compute() { - //noinspection HardCodedStringLiteral - return (value instanceof VirtualFile) ? ((VirtualFile)value).getPresentableUrl() : "UNKNOWN OBJECT"; - } - }); + protected Icon getItemIcon(Object value) { + return getIconForRoot(value); } @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - super.getListCellRendererComponent(list, getPresentableString(value), index, isSelected, cellHasFocus); + public final Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, getItemText(value), index, isSelected, cellHasFocus); + if (isSelected) { setForeground(UIUtil.getListSelectionForeground()); } - else { - if (value instanceof VirtualFile) { - VirtualFile file = (VirtualFile)value; - if (!file.isValid()) { - setForeground(INVALID_COLOR); - } - } + else if (value instanceof VirtualFile && !((VirtualFile)value).isValid()) { + setForeground(INVALID_COLOR); } - setIcon(getIconForRoot(value)); + + setIcon(getItemIcon(value)); + return this; } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java index 4ba8b7b03a8d..c5c263131f92 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -32,7 +32,6 @@ import com.intellij.openapi.project.DumbModeTask; import com.intellij.openapi.project.DumbServiceImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; -import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.*; @@ -59,15 +58,17 @@ import java.util.Set; */ public class ProjectRootManagerComponent extends ProjectRootManagerImpl { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.ProjectManagerComponent"); - private static final boolean ourScheduleCacheUpdateInDumbMode = SystemProperties.getBooleanProperty( - "idea.schedule.cache.update.in.dumb.mode", true); + + private static final boolean ourScheduleCacheUpdateInDumbMode = + SystemProperties.getBooleanProperty("idea.schedule.cache.update.in.dumb.mode", true); + private boolean myPointerChangesDetected = false; private int myInsideRefresh = 0; private final BatchUpdateListener myHandler; private final MessageBusConnection myConnection; - protected final List myRootsChangeUpdaters = new ArrayList(); - protected final List myRefreshCacheUpdaters = new ArrayList(); + @SuppressWarnings("deprecation") protected final List myRootsChangeUpdaters = new ArrayList(); + @SuppressWarnings("deprecation") protected final List myRefreshCacheUpdaters = new ArrayList(); private Set myRootsToWatch = new THashSet(); private final boolean myDoLogCachesUpdate; @@ -120,19 +121,23 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl { myDoLogCachesUpdate = ApplicationManager.getApplication().isInternal() && !ApplicationManager.getApplication().isUnitTestMode(); } + @SuppressWarnings({"deprecation", "unused"}) public void registerRootsChangeUpdater(CacheUpdater updater) { myRootsChangeUpdaters.add(updater); } + @SuppressWarnings({"deprecation", "unused"}) public void unregisterRootsChangeUpdater(CacheUpdater updater) { boolean removed = myRootsChangeUpdaters.remove(updater); LOG.assertTrue(removed); } + @SuppressWarnings({"deprecation", "unused"}) public void registerRefreshUpdater(CacheUpdater updater) { myRefreshCacheUpdaters.add(updater); } + @SuppressWarnings({"deprecation", "unused"}) public void unregisterRefreshUpdater(CacheUpdater updater) { boolean removed = myRefreshCacheUpdaters.remove(updater); LOG.assertTrue(removed); @@ -273,27 +278,22 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl { final Module[] modules = ModuleManager.getInstance(myProject).getModules(); for (Module module : modules) { + flat.add(module.getModuleFilePath()); + final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); addRootsToTrack(moduleRootManager.getContentRootUrls(), recursive, flat); + if (includeSourceRoots) { addRootsToTrack(moduleRootManager.getSourceRootUrls(), recursive, flat); } - flat.add(module.getModuleFilePath()); final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries(); for (OrderEntry entry : orderEntries) { - if (entry instanceof LibraryOrderEntry) { - final Library library = ((LibraryOrderEntry)entry).getLibrary(); - if (library != null) { - for (OrderRootType orderRootType : OrderRootType.getAllTypes()) { - addRootsToTrack(library.getUrls(orderRootType), recursive, flat); - } - } - } - else if (entry instanceof JdkOrderEntry) { + if (entry instanceof LibraryOrSdkOrderEntry) { + final LibraryOrSdkOrderEntry libSdkEntry = (LibraryOrSdkOrderEntry)entry; for (OrderRootType orderRootType : OrderRootType.getAllTypes()) { - addRootsToTrack(((JdkOrderEntry)entry).getRootUrls(orderRootType), recursive, flat); + addRootsToTrack(libSdkEntry.getRootUrls(orderRootType), recursive, flat); } } } @@ -302,6 +302,20 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl { return Pair.create(recursive, flat); } + private static void addRootsToTrack(final String[] urls, final Collection recursive, final Collection flat) { + for (String url : urls) { + if (url != null) { + final String protocol = VirtualFileManager.extractProtocol(url); + if (protocol == null || LocalFileSystem.PROTOCOL.equals(protocol)) { + recursive.add(extractLocalPath(url)); + } + else if (JarFileSystem.PROTOCOL.equals(protocol)) { + flat.add(extractLocalPath(url)); + } + } + } + } + @Override protected void doSynchronizeRoots() { if (!myStartupActivityPerformed) return; @@ -315,22 +329,9 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl { if (ourScheduleCacheUpdateInDumbMode) { dumbService.queueCacheUpdateInDumbMode(myRootsChangeUpdaters); - } else { - dumbService.queueCacheUpdate(myRootsChangeUpdaters); } - } - - private static void addRootsToTrack(final String[] urls, final Collection recursive, final Collection flat) { - for (String url : urls) { - if (url != null) { - final String protocol = VirtualFileManager.extractProtocol(url); - if (protocol == null || LocalFileSystem.PROTOCOL.equals(protocol)) { - recursive.add(extractLocalPath(url)); - } - else if (JarFileSystem.PROTOCOL.equals(protocol)) { - flat.add(extractLocalPath(url)); - } - } + else { + dumbService.queueCacheUpdate(myRootsChangeUpdaters); } } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java index 427786101d12..0cb60f76bcd7 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -41,7 +41,9 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem { * or null if the file does not host this file system. */ @Nullable - public abstract VirtualFile getRootByLocal(@NotNull VirtualFile file); + public VirtualFile getRootByLocal(@NotNull VirtualFile file) { + return findFileByPath(composeRootPath(file.getPath())); + } /** * Returns a root entry of an archive which hosts a given entry file @@ -73,8 +75,11 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem { @NotNull protected abstract String extractLocalPath(@NotNull String rootPath); + /** + * A reverse to {@link #extractLocalPath(String)} - i.e. dresses a local file path to make it a suitable root path for this filesystem. + */ @NotNull - protected abstract String convertLocalToRootPath(@NotNull String localPath); + protected abstract String composeRootPath(@NotNull String localPath); @NotNull protected abstract ArchiveHandler getHandler(@NotNull VirtualFile entryFile); diff --git a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java index 7012dd83d476..72e2737eba25 100644 --- a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java +++ b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -50,8 +50,7 @@ import java.util.zip.GZIPInputStream; * } */ public final class HttpRequests { - private HttpRequests() { - } + private HttpRequests() { } public interface Request { @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index 11ba63776be4..277489dd5aad 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -105,27 +105,21 @@ public class JarFileSystemImpl extends JarFileSystem { @NotNull @Override - protected String convertLocalToRootPath(@NotNull String localPath) { + protected String composeRootPath(@NotNull String localPath) { return localPath + JAR_SEPARATOR; } @NotNull @Override protected JarHandler getHandler(@NotNull VirtualFile entryFile) { - return VfsImplUtil.getHandler(entryFile, this, new Function() { + return VfsImplUtil.getHandler(this, entryFile, new Function() { @Override - public JarHandler fun(String rootPath) { - return new JarHandler(extractLocalPath(rootPath)); + public JarHandler fun(String localPath) { + return new JarHandler(localPath); } }); } - @Nullable - @Override - public VirtualFile getRootByLocal(@NotNull VirtualFile file) { - return findFileByPath(convertLocalToRootPath(file.getPath())); - } - @Override public VirtualFile findFileByPath(@NotNull String path) { return VfsImplUtil.findFileByPath(this, path); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java index b8eb6c5f06e2..132d61496687 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -53,11 +53,11 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap private final FileWatcher myWatcher; private static class WatchRequestImpl implements WatchRequest { - private final boolean myToWatchRecursively; - private String myFSRootPath; + private final String myFSRootPath; + private final boolean myWatchRecursively; private boolean myDominated; - public WatchRequestImpl(String rootPath, boolean toWatchRecursively) throws FileNotFoundException { + public WatchRequestImpl(String rootPath, boolean watchRecursively) throws FileNotFoundException { int index = rootPath.indexOf(JarFileSystem.JAR_SEPARATOR); if (index >= 0) rootPath = rootPath.substring(0, index); @@ -73,7 +73,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap } myFSRootPath = rootFile.getAbsolutePath(); - myToWatchRecursively = toWatchRecursively; + myWatchRecursively = watchRecursively; } @Override @@ -84,7 +84,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap @Override public boolean isToWatchRecursively() { - return myToWatchRecursively; + return myWatchRecursively; } @Override @@ -112,8 +112,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap } @Override - public void initComponent() { - } + public void initComponent() { } @Override public void disposeComponent() { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java index ec4e2feea5d0..a46a221bbe58 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vfs.newvfs; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; @@ -22,10 +23,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.ZipFileCache; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VFileProperty; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.impl.ArchiveHandler; import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; @@ -34,22 +32,26 @@ import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent; import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.messages.MessageBus; -import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import static com.intellij.util.containers.ContainerUtil.newTroveMap; + public class VfsImplUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.VfsImplUtil"); private static final String FILE_SEPARATORS = "/" + File.separator; - private VfsImplUtil() { } + private VfsImplUtil() { + } @Nullable public static NewVirtualFile findFileByPath(@NotNull NewVirtualFileSystem vfs, @NotNull @NonNls String path) { @@ -176,34 +178,40 @@ public class VfsImplUtil { private static final AtomicBoolean ourSubscribed = new AtomicBoolean(false); private static final Object ourLock = new Object(); - private static final Map> ourHandlers = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); - private static final Map> ourDominatorsMap = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); + private static final Map> ourHandlers = newTroveMap(FileUtil.PATH_HASHING_STRATEGY); + private static final Map> ourDominatorsMap = newTroveMap(FileUtil.PATH_HASHING_STRATEGY); @NotNull - public static T getHandler(@NotNull VirtualFile entryFile, - @NotNull ArchiveFileSystem vfs, + public static T getHandler(@NotNull ArchiveFileSystem vfs, + @NotNull VirtualFile entryFile, + @NotNull Function producer) { + String localPath = vfs.extractLocalPath(vfs.extractRootPath(entryFile.getPath())); + return getHandler(vfs, localPath, producer); + } + + @NotNull + public static T getHandler(@NotNull ArchiveFileSystem vfs, + @NotNull String localPath, @NotNull Function producer) { checkSubscription(); - String rootPath = vfs.extractRootPath(entryFile.getPath()); - rootPath = vfs.extractLocalPath(rootPath); ArchiveHandler handler; boolean refresh = false; synchronized (ourLock) { - Pair record = ourHandlers.get(rootPath); + Pair record = ourHandlers.get(localPath); if (record == null) { - handler = producer.fun(rootPath); + handler = producer.fun(localPath); record = Pair.create(vfs, handler); - ourHandlers.put(rootPath, record); + ourHandlers.put(localPath, record); - final String finalRootPath = rootPath; - forEachDirectoryComponent(rootPath, new Processor() { + final String finalRootPath = localPath; + forEachDirectoryComponent(localPath, new Processor() { @Override public boolean process(String containingDirectoryPath) { Set handlers = ourDominatorsMap.get(containingDirectoryPath); if (handlers == null) { - ourDominatorsMap.put(containingDirectoryPath, handlers = new THashSet()); + ourDominatorsMap.put(containingDirectoryPath, handlers = ContainerUtil.newTroveSet()); } handlers.add(finalRootPath); return true; @@ -230,7 +238,7 @@ public class VfsImplUtil { private static void forEachDirectoryComponent(String rootPath, Processor processor) { int index = rootPath.lastIndexOf('/'); - while(index > 0) { + while (index > 0) { String containingDirectoryPath = rootPath.substring(0, index); if (!processor.process(containingDirectoryPath)) return; index = rootPath.lastIndexOf('/', index - 1); @@ -240,8 +248,8 @@ public class VfsImplUtil { private static void checkSubscription() { if (ourSubscribed.getAndSet(true)) return; - MessageBus bus = ApplicationManager.getApplication().getMessageBus(); - bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { + Application app = ApplicationManager.getApplication(); + app.getMessageBus().connect(app).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { @Override public void after(@NotNull List events) { InvalidationState state = null; @@ -257,22 +265,25 @@ public class VfsImplUtil { continue; } - VirtualFile file = event.getFile(); String path = event.getPath(); if (event instanceof VFilePropertyChangeEvent) { path = ((VFilePropertyChangeEvent)event).getOldPath(); - } else if (event instanceof VFileMoveEvent) { + } + else if (event instanceof VFileMoveEvent) { path = ((VFileMoveEvent)event).getOldPath(); } + + VirtualFile file = event.getFile(); if (file == null || !file.isDirectory()) { - if (state == null) state = new InvalidationState(); - state.invalidateHandlerForPath(path); - } else { + state = InvalidationState.invalidate(state, path); + } + else { Collection affectedPaths = ourDominatorsMap.get(path); if (affectedPaths != null) { - affectedPaths = new ArrayList(affectedPaths); // defensive copying, we will modify original during invalidate - if (state == null) state = new InvalidationState(); - for (String affectedPath : affectedPaths) state.invalidateHandlerForPath(affectedPath); + affectedPaths = ContainerUtil.newArrayList(affectedPaths); // defensive copying; original may be updated on invalidation + for (String affectedPath : affectedPaths) { + state = InvalidationState.invalidate(state, affectedPath); + } } } } @@ -286,38 +297,39 @@ public class VfsImplUtil { private static class InvalidationState { private Map rootsToRefresh; - boolean invalidateHandlerForPath(final String path) { + @Nullable + public static InvalidationState invalidate(@Nullable InvalidationState state, final String path) { Pair handlerPair = ourHandlers.remove(path); if (handlerPair != null) { forEachDirectoryComponent(path, new Processor() { @Override public boolean process(String containingDirectoryPath) { Set handlers = ourDominatorsMap.get(containingDirectoryPath); - if (handlers != null) { - if(handlers.remove(path) && handlers.size() == 0) { - ourDominatorsMap.remove(containingDirectoryPath); - } + if (handlers != null && handlers.remove(path) && handlers.size() == 0) { + ourDominatorsMap.remove(containingDirectoryPath); } return true; } }); - registerPathToRefresh(handlerPair, path); + + if (state == null) state = new InvalidationState(); + state.registerPathToRefresh(path, handlerPair.first); } - return handlerPair != null; + + return state; } - private void registerPathToRefresh(Pair handlerPair, String path) { - String rootPath = handlerPair.first.convertLocalToRootPath(path); - NewVirtualFile root = ManagingFS.getInstance().findRoot(rootPath, handlerPair.first); + private void registerPathToRefresh(String path, ArchiveFileSystem vfs) { + NewVirtualFile root = ManagingFS.getInstance().findRoot(vfs.composeRootPath(path), vfs); if (root != null) { if (rootsToRefresh == null) rootsToRefresh = ContainerUtil.newHashMap(); rootsToRefresh.put(path, root); } } - void scheduleRefresh() { + public void scheduleRefresh() { if (rootsToRefresh != null) { - for(VirtualFile root:rootsToRefresh.values()) { + for (VirtualFile root : rootsToRefresh.values()) { ((NewVirtualFile)root).markDirtyRecursively(); } ZipFileCache.reset(rootsToRefresh.keySet()); From af61161c1ea952611ab1c67e9fb22382c9b2994e Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 14 Jan 2015 12:48:18 +0100 Subject: [PATCH 12/55] IDEA-134641 (modular JDK recognition and indexing) --- .../ClassesOrderRootTypeUIFactory.java | 47 ++++- .../JavaNavBarExtension.java | 5 + .../impl/JavaProjectViewDirectoryHelper.java | 6 + .../projectRoots/impl/JavaSdkImpl.java | 35 +++- .../intellij/openapi/vfs/JrtFileSystem.java | 144 +++++++++++++ .../com/intellij/openapi/vfs/JrtHandler.java | 198 ++++++++++++++++++ .../intellij/openapi/vfs/JrtHandlerStub.java | 41 ++++ .../psi/impl/JavaDirectoryIconProvider.java | 6 +- .../openapi/vfs/JrtFileSystemTest.java | 61 ++++++ .../model/library/impl/JpsLibraryImpl.java | 6 +- .../src/messages/LangBundle.properties | 7 +- resources/src/META-INF/IdeaPlugin.xml | 3 + 12 files changed, 544 insertions(+), 15 deletions(-) create mode 100644 java/java-impl/src/com/intellij/openapi/vfs/JrtFileSystem.java create mode 100644 java/java-impl/src/com/intellij/openapi/vfs/JrtHandler.java create mode 100644 java/java-impl/src/com/intellij/openapi/vfs/JrtHandlerStub.java create mode 100644 java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java index c2d3d801a211..6a8a34320365 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,12 +16,17 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.icons.AllIcons; +import com.intellij.lang.LangBundle; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; +import com.intellij.openapi.vfs.JrtFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.components.JBList; +import com.intellij.util.PlatformIcons; import javax.swing.*; @@ -33,7 +38,7 @@ public class ClassesOrderRootTypeUIFactory implements OrderRootTypeUIFactory { @Override public SdkPathEditor createPathEditor(Sdk sdk) { FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, true, false, true, true); - return new SdkPathEditor(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, descriptor); + return new MySdkPathEditor(descriptor); } @Override @@ -45,4 +50,42 @@ public class ClassesOrderRootTypeUIFactory implements OrderRootTypeUIFactory { public String getNodeText() { return ProjectBundle.message("library.classes.node"); } + + private static class MySdkPathEditor extends SdkPathEditor { + public MySdkPathEditor(FileChooserDescriptor descriptor) { + super(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, descriptor); + } + + @Override + protected boolean isRemoveActionEnabled(Object[] values) { + if (!super.isRemoveActionEnabled(values)) { + return false; + } + for (Object value : values) { + if (isJrtRoot(value)) { + return false; + } + } + return true; + } + + @Override + protected ListCellRenderer createListCellRenderer(JBList list) { + return new PathCellRenderer() { + @Override + protected String getItemText(Object value) { + return isJrtRoot(value) ? LangBundle.message("jrt.node.long") : super.getItemText(value); + } + + @Override + protected Icon getItemIcon(Object value) { + return isJrtRoot(value) ? PlatformIcons.JAR_ICON : super.getItemIcon(value); + } + }; + } + } + + private static boolean isJrtRoot(Object value) { + return value instanceof VirtualFile && JrtFileSystem.isRoot((VirtualFile)value); + } } diff --git a/java/java-impl/src/com/intellij/ide/navigationToolbar/JavaNavBarExtension.java b/java/java-impl/src/com/intellij/ide/navigationToolbar/JavaNavBarExtension.java index c5db82aca2e7..563f5d25ebd5 100644 --- a/java/java-impl/src/com/intellij/ide/navigationToolbar/JavaNavBarExtension.java +++ b/java/java-impl/src/com/intellij/ide/navigationToolbar/JavaNavBarExtension.java @@ -16,9 +16,11 @@ package com.intellij.ide.navigationToolbar; import com.intellij.analysis.AnalysisScopeBundle; +import com.intellij.lang.LangBundle; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.JrtFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.presentation.java.ClassPresentationUtil; @@ -39,6 +41,9 @@ public class JavaNavBarExtension extends AbstractNavBarModelExtension { final String name = ((PsiPackage)object).getName(); return name != null ? name : AnalysisScopeBundle.message("dependencies.tree.node.default.package.abbreviation"); } + else if (object instanceof PsiDirectory && JrtFileSystem.isRoot(((PsiDirectory)object).getVirtualFile())) { + return LangBundle.message("jrt.node.short"); + } return null; } diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java b/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java index 78fedc9034bf..b85bda71ab44 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/JavaProjectViewDirectoryHelper.java @@ -20,8 +20,10 @@ import com.intellij.ide.projectView.impl.nodes.PackageElement; import com.intellij.ide.projectView.impl.nodes.PackageUtil; import com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper; import com.intellij.ide.util.treeView.TreeViewUtil; +import com.intellij.lang.LangBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.impl.DirectoryIndex; +import com.intellij.openapi.vfs.JrtFileSystem; import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiPackage; @@ -61,6 +63,10 @@ public class JavaProjectViewDirectoryHelper extends ProjectViewDirectoryHelper { @Nullable @Override public String getNodeName(final ViewSettings settings, final Object parentValue, final PsiDirectory directory) { + if (JrtFileSystem.isRoot(directory.getVirtualFile())) { + return LangBundle.message("jrt.node.short"); + } + PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory); PsiPackage parentPackage; diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index fa166a711999..bce0308619e2 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -18,6 +18,7 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; import com.intellij.icons.AllIcons; +import com.intellij.lang.LangBundle; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; @@ -235,7 +236,16 @@ public class JavaSdkImpl extends JavaSdk { @Override public FileChooserDescriptor getHomeChooserDescriptor() { - FileChooserDescriptor descriptor = super.getHomeChooserDescriptor(); + final FileChooserDescriptor baseDescriptor = super.getHomeChooserDescriptor(); + final FileChooserDescriptor descriptor = new FileChooserDescriptor(baseDescriptor) { + @Override + public void validateSelectedFiles(VirtualFile[] files) throws Exception { + if (files.length > 0 && JrtFileSystem.isModularJdk(files[0].getPath()) && !JrtFileSystem.isSupported()) { + throw new Exception(LangBundle.message("jrt.not.available.message")); + } + baseDescriptor.validateSelectedFiles(files); + } + }; descriptor.putUserData(KEY, Boolean.TRUE); return descriptor; } @@ -255,7 +265,13 @@ public class JavaSdkImpl extends JavaSdk { @Override public boolean isValidSdkHome(String path) { - return checkForJdk(new File(path)); + if (!checkForJdk(new File(path))) { + return false; + } + if (JrtFileSystem.isModularJdk(path) && !JrtFileSystem.isSupported()) { + return false; + } + return true; } @Override @@ -460,17 +476,22 @@ public class JavaSdkImpl extends JavaSdk { } private static List findClasses(File file, boolean isJre) { - List result = ContainerUtil.newArrayList(); + List roots = JavaSdkUtil.getJdkClassesRoots(file, isJre); + List urls = ContainerUtil.newArrayListWithCapacity(roots.size() + 1); + if (JrtFileSystem.isModularJdk(file.getPath())) { + urls.add(VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(file.getPath()) + JrtFileSystem.SEPARATOR)); + } + for (File root : roots) { + urls.add(VfsUtil.getUrlForLibraryRoot(root)); + } - List rootFiles = JavaSdkUtil.getJdkClassesRoots(file, isJre); - for (File child : rootFiles) { - String url = VfsUtil.getUrlForLibraryRoot(child); + List result = ContainerUtil.newArrayListWithCapacity(urls.size()); + for (String url : urls) { VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url); if (vFile != null) { result.add(vFile); } } - return result; } diff --git a/java/java-impl/src/com/intellij/openapi/vfs/JrtFileSystem.java b/java/java-impl/src/com/intellij/openapi/vfs/JrtFileSystem.java new file mode 100644 index 000000000000..853a8b44d4c5 --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/vfs/JrtFileSystem.java @@ -0,0 +1,144 @@ +/* + * Copyright 2000-2015 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.intellij.openapi.vfs; + +import com.intellij.ide.AppLifecycleListener; +import com.intellij.lang.LangBundle; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdkType; +import com.intellij.openapi.projectRoots.ProjectJdkTable; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.impl.ArchiveHandler; +import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem; +import com.intellij.openapi.vfs.newvfs.VfsImplUtil; +import com.intellij.util.Function; +import com.intellij.util.messages.MessageBusConnection; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class JrtFileSystem extends ArchiveFileSystem { + public static final String PROTOCOL = "jrt"; + public static final String SEPARATOR = JarFileSystem.JAR_SEPARATOR; + + public JrtFileSystem() { + scheduleConfiguredSdkCheck(); + } + + private static void scheduleConfiguredSdkCheck() { + if (isSupported()) return; + final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); + connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { + @Override + public void appStarting(Project project) { + for (Sdk sdk : ProjectJdkTable.getInstance().getAllJdks()) { + if (getHomePathIfModular(sdk) != null) { + String title = LangBundle.message("jrt.not.available.title", sdk.getName()); + String message = LangBundle.message("jrt.not.available.message"); + Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, title, message, NotificationType.WARNING)); + } + } + connection.disconnect(); + } + }); + } + + private static String getHomePathIfModular(Sdk sdk) { + if (sdk != null && sdk.getSdkType() instanceof JavaSdkType) { + String homePath = sdk.getHomePath(); + if (homePath != null && isModularJdk(homePath)) { + return homePath; + } + } + return null; + } + + @NotNull + @Override + public String getProtocol() { + return PROTOCOL; + } + + @NotNull + @Override + protected String extractLocalPath(@NotNull String rootPath) { + return StringUtil.trimEnd(rootPath, SEPARATOR); + } + + @NotNull + @Override + protected String composeRootPath(@NotNull String localPath) { + return localPath + SEPARATOR; + } + + @NotNull + @Override + protected String extractRootPath(@NotNull String entryPath) { + int separatorIndex = entryPath.indexOf(SEPARATOR); + assert separatorIndex >= 0 : "Path passed to JrtFileSystem must have a separator '!/': " + entryPath; + return entryPath.substring(0, separatorIndex + SEPARATOR.length()); + } + + @NotNull + @Override + protected ArchiveHandler getHandler(@NotNull VirtualFile entryFile) { + final String homePath = extractLocalPath(extractRootPath(entryFile.getPath())); + return VfsImplUtil.getHandler(this, homePath + "/lib/modules", new Function() { + @Override + public ArchiveHandler fun(String localPath) { + return isSupported() ? new JrtHandler(homePath) : new JrtHandlerStub(homePath); + } + }); + } + + @Override + public VirtualFile findFileByPath(@NotNull String path) { + return VfsImplUtil.findFileByPath(this, path); + } + + @Override + public VirtualFile findFileByPathIfCached(@NotNull String path) { + return VfsImplUtil.findFileByPathIfCached(this, path); + } + + @Override + public VirtualFile refreshAndFindFileByPath(@NotNull String path) { + return VfsImplUtil.refreshAndFindFileByPath(this, path); + } + + @Override + public void refresh(boolean asynchronous) { + VfsImplUtil.refresh(this, asynchronous); + } + + public static boolean isSupported() { + return SystemInfo.isJavaVersionAtLeast("1.8") && !SystemInfo.isJavaVersionAtLeast("1.9"); + } + + public static boolean isModularJdk(@NotNull String homePath) { + return new File(homePath, "lib/modules").isDirectory(); + } + + public static boolean isRoot(@NotNull VirtualFile file) { + return file.getParent() == null && file.getFileSystem() instanceof JrtFileSystem; + } +} diff --git a/java/java-impl/src/com/intellij/openapi/vfs/JrtHandler.java b/java/java-impl/src/com/intellij/openapi/vfs/JrtHandler.java new file mode 100644 index 000000000000..dae670dbfef0 --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/vfs/JrtHandler.java @@ -0,0 +1,198 @@ +/* + * Copyright 2000-2015 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.intellij.openapi.vfs; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.impl.ArchiveHandler; +import com.intellij.reference.SoftReference; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.*; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +class JrtHandler extends ArchiveHandler { + private static final URI ROOT_URI = URI.create("jrt:/"); + private static final Map EMPTY_ENV = Collections.emptyMap(); + + private static class JrtEntryInfo extends EntryInfo { + private final String myModule; + + public JrtEntryInfo(EntryInfo parent, @NotNull String shortName, @NotNull String module, long length, long timestamp) { + super(parent, shortName, false, length, timestamp); + myModule = module; + } + } + + private SoftReference myFileSystem; + + public JrtHandler(@NotNull String path) { + super(path); + } + + private synchronized Object getFileSystem() throws IOException { + Object fs = SoftReference.dereference(myFileSystem); + if (fs == null) { + URL url = new File(getFile(), "jrt-fs.jar").toURI().toURL(); + ClassLoader loader = new URLClassLoader(new URL[]{url}, null); + //fs = FileSystems.newFileSystem(ROOT_URI, EMPTY_ENV, loader); + fs = call(newFileSystem, ROOT_URI, EMPTY_ENV, loader); + myFileSystem = new SoftReference(fs); + } + return fs; + } + + @NotNull + @Override + protected Map createEntriesMap() throws IOException { + final Map map = ContainerUtil.newHashMap(); + map.put("", createRootEntry()); + + //FileSystem fs = (FileSystem)getFileSystem(); + //Path root = fs.getPath("/"); + //Files.walk(root).forEachOrdered((p) -> { + Object fs = getFileSystem(); + Object root = call(getPath, fs, "/", ArrayUtil.EMPTY_STRING_ARRAY); + Object stream = call(walk, root, Array.newInstance(cls("java.nio.file.FileVisitOption"), 0)); + call(forEachOrdered, stream, Proxy.newProxyInstance( + getClass().getClassLoader(), new Class[]{cls("java.util.function.Consumer")}, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + //String path = p.toString(); + String path = args[0].toString(); + + int p = path.indexOf('/', 1); + if (p < 0) return null; + String module = path.substring(1, p); + path = path.substring(p + 1); + if (map.containsKey(path)) return null; + + String shortName; + EntryInfo parent; + + p = path.lastIndexOf('/'); + if (p < 0) { + shortName = path; + parent = map.get(""); + } + else { + shortName = path.substring(p + 1); + parent = map.get(path.substring(0, p)); + } + assert parent != null : path; + + //BasicFileAttributes attributes = Files.readAttributes(p, BasicFileAttributes.class); + //boolean dir = attributes.isDirectory(); + //long length = attributes.size(); + //long modified = attributes.lastModifiedTime().toMillis(); + Object attributes = call(readAttributes, args[0], cls("java.nio.file.attribute.BasicFileAttributes"), linkOptions); + boolean dir = (Boolean)call(isDirectory, attributes); + long length = (Long)call(size, attributes); + long modified = (Long)call(toMillis, call(lastModifiedTime, attributes)); + EntryInfo entry = dir ? new EntryInfo(parent, shortName, true, length, modified) + : new JrtEntryInfo(parent, shortName, module, length, modified); + map.put(path, entry); + + return null; + } + })); + //}); + + return map; + } + + @NotNull + @Override + public byte[] contentsToByteArray(@NotNull String relativePath) throws IOException { + EntryInfo entry = getEntryInfo(relativePath); + if (!(entry instanceof JrtEntryInfo)) { + return ArrayUtil.EMPTY_BYTE_ARRAY; + } + + //FileSystem fs = (FileSystem)getFileSystem(); + //Path path = fs.getPath(((JrtEntryInfo)entry).myModule, relativePath); + //return Files.readAllBytes(path); + Object fs = getFileSystem(); + Object path = call(getPath, fs, ((JrtEntryInfo)entry).myModule, new String[]{relativePath}); + return (byte[])call(readAllBytes, path); + } + + // reflection stuff + // todo[r.sh] drop reflection after migration to Java 8 + + private static final Method newFileSystem = method("java.nio.file.FileSystems#newFileSystem", URI.class, Map.class, ClassLoader.class); + private static final Method getPath = method("java.nio.file.FileSystem#getPath", String.class, String[].class); + private static final Method walk = method("java.nio.file.Files#walk", cls("java.nio.file.Path"), cls("java.nio.file.FileVisitOption", true)); + private static final Method forEachOrdered = method("java.util.stream.Stream#forEachOrdered", cls("java.util.function.Consumer")); + private static final Method readAttributes = + method("java.nio.file.Files#readAttributes", cls("java.nio.file.Path"), Class.class, cls("java.nio.file.LinkOption", true)); + private static final Method isDirectory = method("java.nio.file.attribute.BasicFileAttributes#isDirectory"); + private static final Method size = method("java.nio.file.attribute.BasicFileAttributes#size"); + private static final Method lastModifiedTime = method("java.nio.file.attribute.BasicFileAttributes#lastModifiedTime"); + private static final Method toMillis = method("java.nio.file.attribute.FileTime#toMillis"); + private static final Method readAllBytes = method("java.nio.file.Files#readAllBytes", cls("java.nio.file.Path")); + private static final Object linkOptions = Array.newInstance(cls("java.nio.file.LinkOption"), 0); + + private static Class cls(String name) { + return cls(name, false); + } + + private static Class cls(String name, boolean array) { + try { + if (array) name = "[L" + name + ";"; + return Class.forName(name); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static Method method(String name, Class... parameterTypes) { + try { + List parts = StringUtil.split(name, "#"); + Class aClass = cls(parts.get(0)); + Method method = aClass.getMethod(parts.get(1), parameterTypes); + method.setAccessible(true); + return method; + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static Object call(Method method, Object... args) { + try { + if (Modifier.isStatic(method.getModifiers())) { + return method.invoke(null, args); + } + else { + return method.invoke(args[0], Arrays.copyOfRange(args, 1, args.length)); + } + } + catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/java-impl/src/com/intellij/openapi/vfs/JrtHandlerStub.java b/java/java-impl/src/com/intellij/openapi/vfs/JrtHandlerStub.java new file mode 100644 index 000000000000..fa3f036e12e5 --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/vfs/JrtHandlerStub.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2015 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.intellij.openapi.vfs; + +import com.intellij.openapi.vfs.impl.ArchiveHandler; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; + +class JrtHandlerStub extends ArchiveHandler { + public JrtHandlerStub(@NotNull String path) { + super(path); + } + + @NotNull + @Override + protected Map createEntriesMap() throws IOException { + return Collections.emptyMap(); + } + + @NotNull + @Override + public byte[] contentsToByteArray(@NotNull String relativePath) throws IOException { + return new byte[0]; + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java b/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java index b80324ad0aee..e4989828d363 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java @@ -26,8 +26,8 @@ import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.SourceFolder; import com.intellij.openapi.roots.ui.configuration.SourceRootPresentation; import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem; import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -43,7 +43,7 @@ import javax.swing.*; public class JavaDirectoryIconProvider extends IconProvider implements DumbAware { @Override @Nullable - public Icon getIcon(@NotNull final PsiElement element, final int flags) { + public Icon getIcon(@NotNull PsiElement element, int flags) { if (element instanceof PsiDirectory) { final PsiDirectory psiDirectory = (PsiDirectory)element; final VirtualFile vFile = psiDirectory.getVirtualFile(); @@ -51,7 +51,7 @@ public class JavaDirectoryIconProvider extends IconProvider implements DumbAware SourceFolder sourceFolder; Icon symbolIcon; - if (vFile.getParent() == null && vFile.getFileSystem() instanceof JarFileSystem) { + if (vFile.getParent() == null && vFile.getFileSystem() instanceof ArchiveFileSystem) { symbolIcon = PlatformIcons.JAR_ICON; } else if (ProjectRootsUtil.isModuleContentRoot(vFile, project)) { diff --git a/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java b/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java new file mode 100644 index 000000000000..bbaadf8f7f81 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/openapi/vfs/JrtFileSystemTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2015 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.intellij.openapi.vfs; + +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.LightPlatformTestCase; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import static org.junit.Assert.*; +import static org.junit.Assume.assumeNotNull; +import static org.junit.Assume.assumeTrue; + +public class JrtFileSystemTest { + private static String ourJdkHome = System.getenv("JDK_19"); + + @BeforeClass + public static void setUpClass() { + assumeTrue("skipped: java=" + SystemInfo.JAVA_VERSION, JrtFileSystem.isSupported()); + assumeTrue("skipped: JDK_19=" + ourJdkHome, ourJdkHome != null && JrtFileSystem.isModularJdk(ourJdkHome)); + + IdeaTestCase.initPlatformPrefix(); + LightPlatformTestCase.initApplication(); + } + + @Test + public void testBasicOps() throws IOException { + String url = VirtualFileManager.constructUrl(JrtFileSystem.PROTOCOL, FileUtil.toSystemIndependentName(ourJdkHome) + JrtFileSystem.SEPARATOR); + VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url); + assertNotNull(root); + assertTrue(JrtFileSystem.isRoot(root)); + + assumeNotNull(root.findChild("java")); + assumeNotNull(root.findChild("javax")); + + VirtualFile object = root.findFileByRelativePath("java/lang/Object.class"); + assertNotNull(object); + + byte[] bytes = object.contentsToByteArray(); + assertTrue(bytes.length > 10); + assertEquals(0xCAFEBABE, ByteBuffer.wrap(bytes).getInt()); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java index 2e581d27f15b..e2a4c5031004 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -138,7 +138,9 @@ public class JpsLibraryImpl

extends JpsNamedCompositeEleme List urls = getRootUrls(rootType); List files = new ArrayList(urls.size()); for (String url : urls) { - files.add(JpsPathUtil.urlToFile(url)); + if (!url.startsWith("jrt://")) { + files.add(JpsPathUtil.urlToFile(url)); + } } return files; } diff --git a/platform/platform-resources-en/src/messages/LangBundle.properties b/platform/platform-resources-en/src/messages/LangBundle.properties index f6db968e554c..885f1706ebaa 100644 --- a/platform/platform-resources-en/src/messages/LangBundle.properties +++ b/platform/platform-resources-en/src/messages/LangBundle.properties @@ -31,7 +31,7 @@ completion.no.suggestions=No suggestions completion.quick.javadoc.ad=Did you know that Quick Documentation View ({0}) works in completion lookups as well? completion.quick.implementations.ad=Did you know that Quick Definition View ({0}) works in completion lookups as well? completion.dot.etc.ad=Dot, space and some other keys will also close this lookup and be inserted into editor -completion.smart.enter.ad=Use {0} to syntactically correct your code after completing (balance parentheses etc.) +completion.smart.enter.ad=Use {0} to syntactically correct your code after completing (balance parentheses etc.) xml.terms.tag=tag xml.terms.entity=entity @@ -52,3 +52,8 @@ template.data.language.override.warning.text=There are template data languages s template.data.language.override.warning.title=Override Subdirectory Template Data Languages quickfix.change.template.data.language.text=Change {0} template data language to... incorrect.name=Incorrect name + +jrt.node.short=[JRT] +jrt.node.long=[Java Run-time Modules] +jrt.not.available.message=You need to run IDEA on Java 8 to be able to use modular JDK. Sorry. +jrt.not.available.title=Unsupported JDK ''{0}'' detected diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 8cc924382404..f7dff8a422d9 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -45,6 +45,9 @@ + + com.intellij.openapi.vfs.JrtFileSystem + com.intellij.util.xml.impl.JavaDomApplicationComponent From f501189a4f9da9dc6a8eaa8bccbc87db22d363d3 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 14 Jan 2015 13:28:10 +0300 Subject: [PATCH 13/55] fix commit message test for not utf8 encoding --- plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java index 009f90c9a58a..cfc649cd6913 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/HgEncodingTest.java @@ -24,7 +24,9 @@ import org.zmlx.hg4idea.command.HgLogCommand; import org.zmlx.hg4idea.execution.HgCommandException; import org.zmlx.hg4idea.repo.HgRepository; import org.zmlx.hg4idea.repo.HgRepositoryImpl; +import org.zmlx.hg4idea.util.HgEncodingUtil; +import java.nio.charset.Charset; import java.util.List; import static com.intellij.openapi.vcs.Executor.cd; @@ -49,6 +51,7 @@ public class HgEncodingTest extends HgPlatformTest { cd(myRepository); String fileName = "file.txt"; echo(fileName, "lalala"); + Charset charset = HgEncodingUtil.getDefaultCharset(myProject); String comment = "öäüß"; HgRepository hgRepo = HgRepositoryImpl.getInstance(myRepository, myProject, myProject); HgCommitCommand commitCommand = new HgCommitCommand(myProject, hgRepo, comment); @@ -59,6 +62,6 @@ public class HgEncodingTest extends HgPlatformTest { assert file != null; List revisions = logCommand.execute(new HgFile(myProject, file), 1, false); HgFileRevision rev = revisions.get(0); - assertEquals(comment, rev.getCommitMessage()); + assertEquals(new String(comment.getBytes(charset)), rev.getCommitMessage()); } } From 3419a30f6842ca755b559b9b29d110f17cdc40c8 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 14 Jan 2015 13:44:36 +0300 Subject: [PATCH 14/55] style: remove unnecessary field --- .../dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java index 2e811916c8e5..b2314fe9bee6 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java @@ -36,7 +36,6 @@ public class VcsPushDialog extends DialogWrapper { private static final String ID = "Vcs.Push.Dialog"; - @NotNull private final Project myProject; private final PushLog myListPanel; private final PushController myController; private final Map myAdditionalPanels; @@ -48,7 +47,6 @@ public class VcsPushDialog extends DialogWrapper { @NotNull List selectedRepositories, @Nullable Repository currentRepo) { super(project); - myProject = project; myController = new PushController(project, this, selectedRepositories, currentRepo); myAdditionalPanels = myController.createAdditionalPanels(); myListPanel = myController.getPushPanelLog(); From 518722db46ca15dee3ea35a0a80fa6f15a032d9f Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 14 Jan 2015 14:43:14 +0300 Subject: [PATCH 15/55] refactoring * separated disableOkActions created for start edit property change event; * clarifying comment added; * enableOkActions method renamed to updateOkActions with appropriate logic moved inside --- .../intellij/dvcs/push/PushController.java | 10 +++++++--- .../intellij/dvcs/push/ui/VcsPushDialog.java | 20 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index 78f22616b1bd..390f7588e3a4 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -88,8 +88,12 @@ public class PushController implements Disposable { myPushLog.getTree().addPropertyChangeListener(PushLogTreeUtil.EDIT_MODE_PROP, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { + // when user starts edit we need to force disable ok actions, because tree.isEditing() still false; + // after editing completed okActions will be enabled automatically by dialog validation Boolean isEditMode = (Boolean)evt.getNewValue(); - myDialog.enableOkActions(!isEditMode && isPushAllowed()); + if (isEditMode) { + myDialog.disableOkActions(); + } } }); startLoadingCommits(); @@ -234,7 +238,7 @@ public class PushController implements Disposable { @Override public void onSelectionChanged(boolean isSelected) { - myDialog.enableOkActions(isPushAllowed()); + myDialog.updateOkActions(); if (isSelected) { boolean forceLoad = myExcludedRepositoryRoots.remove(model.getRepository().getRoot().getPath()); if (!model.hasCommitInfo() && (forceLoad || !model.getSupport().shouldRequestIncomingChangesForNotCheckedRepositories())) { @@ -399,7 +403,7 @@ public class PushController implements Disposable { if (shouldBeSelected) { // never remove selection; initially all checkboxes are not selected node.setChecked(true); } - myDialog.enableOkActions(isPushAllowed()); + myDialog.updateOkActions(); } }); } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java index b2314fe9bee6..0dae18f857a1 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java @@ -52,7 +52,7 @@ public class VcsPushDialog extends DialogWrapper { myListPanel = myController.getPushPanelLog(); init(); - enableOkActions(myController.isPushAllowed()); + updateOkActions(); setOKButtonText("Push"); setOKButtonMnemonic('P'); setTitle("Push Commits"); @@ -78,7 +78,7 @@ public class VcsPushDialog extends DialogWrapper { @Nullable @Override protected ValidationInfo doValidate() { - enableOkActions(myController.isPushAllowed()); + updateOkActions(); return null; } @@ -101,6 +101,10 @@ public class VcsPushDialog extends DialogWrapper { return actions.toArray(new Action[actions.size()]); } + private boolean canPush() { + return myController.isPushAllowed(); + } + private boolean canForcePush() { return myController.isForcePushEnabled() && myController.getProhibitedTarget() == null; } @@ -121,11 +125,13 @@ public class VcsPushDialog extends DialogWrapper { protected String getHelpId() { return ID; } - public void enableOkActions(boolean isEnabled) { - myPushAction.setEnabled(isEnabled); + + public void updateOkActions() { + boolean canPush = canPush(); + myPushAction.setEnabled(canPush); if (myForcePushAction != null) { boolean canForcePush = canForcePush(); - myForcePushAction.setEnabled(isEnabled && canForcePush); + myForcePushAction.setEnabled(canPush && canForcePush); String tooltip = null; if (!canForcePush) { PushTarget target = myController.getProhibitedTarget(); @@ -137,6 +143,10 @@ public class VcsPushDialog extends DialogWrapper { } } + public void disableOkActions() { + myPushAction.setEnabled(false); + } + @Nullable public VcsPushOptionValue getAdditionalOptionValue(@NotNull PushSupport support) { VcsPushOptionsPanel panel = myAdditionalPanels.get(support); From 901b6f8c2a8c836a12a6a8556bfe89d15d6f033b Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 14 Jan 2015 14:49:11 +0300 Subject: [PATCH 16/55] IDEA-135126 Allow force push if there are no commits to push --- .../src/com/intellij/dvcs/push/PushController.java | 8 ++++---- .../src/com/intellij/dvcs/push/ui/VcsPushDialog.java | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index 390f7588e3a4..c35f94c047b6 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -281,21 +281,21 @@ public class PushController implements Disposable { return names; } - public boolean isPushAllowed() { + public boolean isPushAllowed(final boolean force) { JTree tree = myPushLog.getTree(); return !tree.isEditing() && ContainerUtil.exists(myPushSupports, new Condition>() { @Override public boolean value(PushSupport support) { - return isPushAllowed(support); + return isPushAllowed(support, force); } }); } - private boolean isPushAllowed(@NotNull PushSupport pushSupport) { + private boolean isPushAllowed(@NotNull PushSupport pushSupport, boolean force) { Collection nodes = getNodesForSupport(pushSupport); if (hasSomethingToPush(nodes)) return true; - if (hasCheckedNodesWithContent(nodes, myDialog.getAdditionalOptionValue(pushSupport) != null)) { + if (hasCheckedNodesWithContent(nodes, force || myDialog.getAdditionalOptionValue(pushSupport) != null)) { return !pushSupport.getRepositoryManager().isSyncEnabled() || allNodesAreLoaded(nodes); } return false; diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java index 0dae18f857a1..7dbe1b20096e 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java @@ -102,11 +102,11 @@ public class VcsPushDialog extends DialogWrapper { } private boolean canPush() { - return myController.isPushAllowed(); + return myController.isPushAllowed(false); } private boolean canForcePush() { - return myController.isForcePushEnabled() && myController.getProhibitedTarget() == null; + return myController.isForcePushEnabled() && myController.getProhibitedTarget() == null && myController.isPushAllowed(true); } @Nullable @@ -127,11 +127,10 @@ public class VcsPushDialog extends DialogWrapper { } public void updateOkActions() { - boolean canPush = canPush(); - myPushAction.setEnabled(canPush); + myPushAction.setEnabled(canPush()); if (myForcePushAction != null) { boolean canForcePush = canForcePush(); - myForcePushAction.setEnabled(canPush && canForcePush); + myForcePushAction.setEnabled(canForcePush); String tooltip = null; if (!canForcePush) { PushTarget target = myController.getProhibitedTarget(); From 0015f09cc1e17881c137da4d24efc332ca5203cc Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 14 Jan 2015 14:59:18 +0300 Subject: [PATCH 17/55] rich copy: make text pasted in target application have same size as original text in IDEA editor --- .../editor/richcopy/TextWithMarkupProcessor.java | 14 +++++++++++++- .../openapi/editor/richcopy/model/SyntaxInfo.java | 10 +++++----- .../editor/richcopy/view/HtmlTransferableData.java | 2 +- .../editor/richcopy/view/RtfTransferableData.java | 6 +++--- .../richcopy/SyntaxInfoConstructionTest.java | 2 +- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java index a70eed809667..cdabd8b98641 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.editorActions.CopyPastePostProcessor; import com.intellij.codeInsight.editorActions.CopyPastePreProcessor; import com.intellij.ide.highlighter.HighlighterFactory; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.EditorColorsScheme; @@ -45,6 +46,7 @@ import com.intellij.openapi.editor.richcopy.view.RtfTransferableData; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiFile; import com.intellij.psi.TokenType; @@ -271,7 +273,17 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor"); + myResultBuffer.append(String.format("font-size:%.1fpt;\">", mySyntaxInfo.getFontSize())); mySyntaxInfo.processOutputInfo(this); diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java index 9424a37dd64a..bce01e88853e 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/view/RtfTransferableData.java @@ -77,8 +77,8 @@ public class RtfTransferableData extends AbstractSyntaxAwareInputStreamTransfera return "US-ASCII"; } - private static void addFontSize(StringBuilder buffer, int fontSize) { - buffer.append("\\fs").append(fontSize * 2); + private static void addFontSize(StringBuilder buffer, float fontSize) { + buffer.append("\\fs").append(Math.round(fontSize * 2)); } private static class MyVisitor implements MarkupHandler { @@ -88,7 +88,7 @@ public class RtfTransferableData extends AbstractSyntaxAwareInputStreamTransfera private final int myMaxLength; private final int myDefaultBackgroundId; - private final int myFontSize; + private final float myFontSize; private int myForegroundId = -1; private int myFontNameId = -1; private int myFontStyle = -1; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/richcopy/SyntaxInfoConstructionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/richcopy/SyntaxInfoConstructionTest.java index b7811e0ae40d..bdeffd5a13db 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/richcopy/SyntaxInfoConstructionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/richcopy/SyntaxInfoConstructionTest.java @@ -305,7 +305,7 @@ public class SyntaxInfoConstructionTest extends LightPlatformCodeInsightFixtureT final ColorRegistry colorRegistry = syntaxInfo.getColorRegistry(); assertEquals(JBColor.BLACK, colorRegistry.dataById(syntaxInfo.getDefaultForeground())); assertEquals(JBColor.WHITE, colorRegistry.dataById(syntaxInfo.getDefaultBackground())); - assertEquals(getFontSize(), syntaxInfo.getFontSize()); + assertEquals((float)getFontSize(), syntaxInfo.getFontSize(), 0.01f); syntaxInfo.processOutputInfo(new MarkupHandler() { @Override public void handleText(int startOffset, int endOffset) throws Exception { From f90ba61bcfc47eb2b71a87c4b81e3daf4d6941d3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 11:30:02 +0100 Subject: [PATCH 18/55] code cleanup also for code generation on completion --- ...JavaGenerateMemberCompletionContributor.java | 17 +++++++++++++---- .../completion/NormalCompletionTest.groovy | 17 +++++++++++++++++ .../ex/GlobalInspectionContextBase.java | 2 +- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java index 8ae9622f3440..e636ab4fc9b4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.generation.*; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.codeInspection.ex.GlobalInspectionContextBase; import com.intellij.icons.AllIcons; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Key; @@ -30,10 +31,7 @@ import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.ContainerUtil; import javax.swing.*; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; import static com.intellij.patterns.PlatformPatterns.psiElement; @@ -137,6 +135,17 @@ public class JavaGenerateMemberCompletionContributor { List> newInfos = GenerateMembersUtil .insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos); if (!newInfos.isEmpty()) { + final List elements = new ArrayList(); + for (GenerationInfo member : newInfos) { + if (!(member instanceof TemplateGenerationInfo)) { + final PsiMember psiMember = member.getPsiMember(); + if (psiMember != null) { + elements.add(psiMember); + } + } + } + + GlobalInspectionContextBase.cleanupElements(context.getProject(), null, elements.toArray(new PsiElement[elements.size()])); newInfos.get(0).positionCaret(context.getEditor(), true); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 3bf3f6fbe428..dafb0ea9445b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -27,6 +27,7 @@ import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiMethod import com.intellij.psi.codeStyle.CodeStyleSettingsManager import com.intellij.psi.codeStyle.CommonCodeStyleSettings +import com.siyeh.ig.style.UnqualifiedFieldAccessInspection public class NormalCompletionTest extends LightFixtureCompletionTestCase { @Override @@ -1484,5 +1485,21 @@ class Bar { myFixture.assertPreferredCompletionItems(0, "xcreateZoo", "xcreateElephant"); } + public void "test code cleanup during completion generation"() { + myFixture.configureByText "a.java", "class Foo {int i; ge}" + def inspection = new UnqualifiedFieldAccessInspection() + try { + myFixture.enableInspections(inspection) + myFixture.complete(CompletionType.BASIC) + myFixture.checkResult '''class Foo {int i; + public int getI() { + return this.i; + } +}''' + } + finally { + myFixture.disableInspections(inspection) + } + } } diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java index 4372a5944a2f..b284780ae278 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java @@ -438,7 +438,7 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G }; Application application = ApplicationManager.getApplication(); - if (application.isWriteAccessAllowed()) { + if (application.isWriteAccessAllowed() && !application.isUnitTestMode()) { application.invokeLater(cleanupRunnable); } else { From 73239255ecc2c55da04b0c5d1d220a3d514991f0 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 12:35:44 +0100 Subject: [PATCH 19/55] disable add exception to catch/generalize catch inside functional interface inside try statement (IDEA-135171) --- .../impl/quickfix/AddExceptionToCatchFix.java | 4 +-- .../impl/quickfix/GeneralizeCatchFix.java | 2 +- .../afterInsideLambdaTryInside.java | 25 +++++++++++++++++++ .../addCatchBlock/beforeInsideLambda.java | 16 ++++++++++++ .../beforeInsideLambdaTryInside.java | 23 +++++++++++++++++ .../addCatchBlock/beforeInsideMethodRef.java | 16 ++++++++++++ .../generalizeCatch/beforeInsideLambda.java | 16 ++++++++++++ .../beforeInsideMethodRef.java | 16 ++++++++++++ .../quickFix/AddExceptionToCatchTest.java | 8 ++++++ .../daemon/quickFix/GeneralizeCatchTest.java | 8 ++++++ 10 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/afterInsideLambdaTryInside.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambda.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambdaTryInside.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideMethodRef.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideLambda.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideMethodRef.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java index 5d51949c1d6b..cc43f962fc19 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java @@ -171,8 +171,8 @@ public class AddExceptionToCatchFix extends BaseIntentionAction { if (element == null) return null; @SuppressWarnings({"unchecked"}) - final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, PsiMethod.class); - if (parent == null || parent instanceof PsiMethod) return null; + final PsiElement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, PsiMethod.class, PsiFunctionalExpression.class); + if (parent == null || parent instanceof PsiMethod || parent instanceof PsiFunctionalExpression) return null; final PsiTryStatement statement = (PsiTryStatement) parent; final PsiCodeBlock tryBlock = statement.getTryBlock(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java index 64ad43808b86..2f7c34e47886 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GeneralizeCatchFix.java @@ -63,7 +63,7 @@ public class GeneralizeCatchFix implements IntentionAction { myTryStatement = (PsiTryStatement)element.getParent(); break; } - if (element instanceof PsiMethod || (element instanceof PsiClass && !(element instanceof PsiAnonymousClass))) break; + if (element instanceof PsiMethod || element instanceof PsiFunctionalExpression || (element instanceof PsiClass && !(element instanceof PsiAnonymousClass))) break; element = element.getParent(); } if (myTryStatement == null) return false; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/afterInsideLambdaTryInside.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/afterInsideLambdaTryInside.java new file mode 100644 index 000000000000..0bad23e6f11a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/afterInsideLambdaTryInside.java @@ -0,0 +1,25 @@ +// "Add 'catch' clause(s)" "true" +import java.io.IOException; +import java.util.function.Supplier; + +class C { + static Object get() throws Exception { + return null; + } + + void method() { + try { + Supplier lambda1 = () -> { + try { + return C.get(); + } catch (IOException e) { + throw new RuntimeException(); + } catch (Exception e) { + e.printStackTrace(); + } + }; + } catch( Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambda.java new file mode 100644 index 000000000000..08b71cbd8571 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambda.java @@ -0,0 +1,16 @@ +// "Add 'catch' clause(s)" "false" +import java.util.function.Supplier; + +class C { + static Object get() throws Exception { + return null; + } + + void method() { + try { + Supplier lambda1 = () -> C.get(); + } catch( Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambdaTryInside.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambdaTryInside.java new file mode 100644 index 000000000000..857e16005aa8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideLambdaTryInside.java @@ -0,0 +1,23 @@ +// "Add 'catch' clause(s)" "true" +import java.io.IOException; +import java.util.function.Supplier; + +class C { + static Object get() throws Exception { + return null; + } + + void method() { + try { + Supplier lambda1 = () -> { + try { + return C.get(); + } catch (IOException e) { + throw new RuntimeException(); + } + }; + } catch( Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideMethodRef.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideMethodRef.java new file mode 100644 index 000000000000..300d6bdc806c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock/beforeInsideMethodRef.java @@ -0,0 +1,16 @@ +// "Add 'catch' clause(s)" "false" +import java.util.function.Supplier; + +class C { + static Object get() throws Exception { + return null; + } + + void method() { + try { + Supplier lambda1 = C::get; + } catch( Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideLambda.java new file mode 100644 index 000000000000..97db7ea2a88f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideLambda.java @@ -0,0 +1,16 @@ +// "Generalize catch for 'java.lang.Exception' to 'java.lang.Exception'" "false" +import java.util.function.Supplier; + +class C { + static Object get() throws Exception { + return null; + } + + void method() { + try { + Supplier lambda1 = () -> C.get(); + } catch( Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideMethodRef.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideMethodRef.java new file mode 100644 index 000000000000..1bc024dd7453 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch/beforeInsideMethodRef.java @@ -0,0 +1,16 @@ +// "Generalize catch for 'java.lang.Exception' to 'java.lang.Exception'" "false" +import java.util.function.Supplier; + +class C { + static Object get() throws Exception { + return null; + } + + void method() { + try { + Supplier lambda1 = C::get; + } catch( Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java index 4ef4c493e09d..e55cced09985 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java @@ -1,5 +1,8 @@ package com.intellij.codeInsight.daemon.quickFix; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.testFramework.IdeaTestUtil; + public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase { public void test() throws Exception { doAllTests(); @@ -9,4 +12,9 @@ public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase protected String getBasePath() { return "/codeInsight/daemonCodeAnalyzer/quickFix/addCatchBlock"; } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java index ac0c5b4ae09e..90299b35923c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java @@ -1,5 +1,8 @@ package com.intellij.codeInsight.daemon.quickFix; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.testFramework.IdeaTestUtil; + public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase { public void test() throws Exception { doAllTests(); @@ -9,4 +12,9 @@ public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase { protected String getBasePath() { return "/codeInsight/daemonCodeAnalyzer/quickFix/generalizeCatch"; } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } } From a1b44a53ac7ca01f9a642e0c9ba2ce24415ed685 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 13:20:34 +0100 Subject: [PATCH 20/55] redundant throws: find throws clauses inside functional expressions (IDEA-135181) --- .../reference/RefJavaUtilImpl.java | 27 +++++++++++++++++++ .../expected.xml | 9 +++++++ .../src/Foo.java | 23 ++++++++++++++++ .../codeInspection/RedundantThrowTest.java | 15 +++++++++++ 4 files changed, 74 insertions(+) create mode 100644 java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/expected.xml create mode 100644 java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/src/Foo.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java index e35aa3aa80a5..22d347ee1ecb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java @@ -20,6 +20,7 @@ */ package com.intellij.codeInspection.reference; +import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; @@ -30,6 +31,9 @@ import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; +import java.util.Collections; + public class RefJavaUtilImpl extends RefJavaUtil{ @Override @@ -114,6 +118,29 @@ public class RefJavaUtilImpl extends RefJavaUtil{ final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass); if (interfaceMethod != null) { refFrom.addReference(refFrom.getRefManager().getReference(interfaceMethod), interfaceMethod, psiFrom, false, true, null); + + PsiElement body = null; + PsiElement topElement = null; + if (expression instanceof PsiLambdaExpression) { + body = ((PsiLambdaExpression)expression).getBody(); + topElement = expression; + } + else { + final PsiElement resolve = ((PsiMethodReferenceExpression)expression).resolve(); + if (resolve instanceof PsiMethod) { + body = ((PsiMethod)resolve).getBody(); + topElement = resolve; + } + } + + final Collection exceptionTypes = body != null ? ExceptionUtil.collectUnhandledExceptions(body, topElement, false) + : Collections.emptyList(); + RefElement refResolved = refFrom.getRefManager().getReference(interfaceMethod); + if (refResolved instanceof RefMethodImpl) { + for (final PsiClassType exceptionType : exceptionTypes) { + ((RefMethodImpl)refResolved).updateThrowsList(exceptionType); + } + } } } } diff --git a/java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/expected.xml b/java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/expected.xml new file mode 100644 index 000000000000..d7687ccb6f07 --- /dev/null +++ b/java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/expected.xml @@ -0,0 +1,9 @@ + + + + Foo.java + 21 + ObjectStreamException + + + diff --git a/java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/src/Foo.java b/java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/src/Foo.java new file mode 100644 index 000000000000..78316c54cfb5 --- /dev/null +++ b/java/java-tests/testData/inspection/redundantThrow/ThrownClausesInFunctionalExpressions/src/Foo.java @@ -0,0 +1,23 @@ +import java.io.*; + +class ExceptionTest { + + MyFunction method() { + return () -> { + throw new EOFException(); + }; + } + + MyFunction method1() { + return this::e; + } + + private void e() throws FileNotFoundException { + throw new FileNotFoundException(); + } + + @FunctionalInterface + private interface MyFunction { + void call() throws FileNotFoundException, EOFException, ObjectStreamException; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java index c1017d242538..61dc1d9a5600 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantThrowTest.java @@ -17,6 +17,10 @@ package com.intellij.codeInspection; import com.intellij.JavaTestUtil; import com.intellij.codeInspection.unneededThrows.RedundantThrows; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.InspectionTestCase; public class RedundantThrowTest extends InspectionTestCase { @@ -60,4 +64,15 @@ public class RedundantThrowTest extends InspectionTestCase { public void testSelfCall() throws Exception { doTest(); } + + public void testThrownClausesInFunctionalExpressions() throws Exception { + doTest(); + } + + @Override + protected Sdk getTestProjectSdk() { + Sdk sdk = IdeaTestUtil.getMockJdk17(); + LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_8); + return sdk; + } } From a4575a6bddfec50eb127c154184d4c6a52732588 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 14 Jan 2015 13:41:31 +0100 Subject: [PATCH 21/55] common Y offset for IntelliJ and Darcula radio buttons --- .../intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java index 4b1d9dfafaf9..e3fe9f582393 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonUI.java @@ -117,7 +117,7 @@ public class DarculaRadioButtonUI extends MetalRadioButtonUI { if (b.isSelected()) { final boolean enabled = b.isEnabled(); g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor"));// ? Gray._30 : Gray._60); - final int yOff = UIUtil.isUnderDarcula() ? 2 : JBUI.scale(1); + final int yOff = 2; g.fillOval(w/2 - rad/2, h/2 - rad/2 + yOff , rad, rad); g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor")); //Gray._170 : Gray._120); g.fillOval(w/2 - rad/2, h/2 - rad/2 -1 + yOff, rad, rad); From 8a290943610f2a4d8412a843499757c80539f2c6 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 14 Jan 2015 16:02:26 +0300 Subject: [PATCH 22/55] IDEA-134811 After ctrl-w selects line, shift-down should contain current line in selection --- .../openapi/actionSystem/IdeActions.java | 2 ++ .../openapi/editor/impl/CaretImpl.java | 3 ++- .../editor/actions/EditorActionTest.java | 20 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index f81859417580..22f5eddf54c8 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -40,6 +40,8 @@ public interface IdeActions { @NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace"; @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection"; @NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection"; + @NonNls String ACTION_EDITOR_MOVE_CARET_UP_WITH_SELECTION = "EditorUpWithSelection"; + @NonNls String ACTION_EDITOR_MOVE_CARET_DOWN_WITH_SELECTION = "EditorDownWithSelection"; @NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp"; @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft"; @NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown"; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index fd49b3b5574d..233f0cc45621 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -248,6 +248,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { myEditor.getCaretModel().doWithCaretMerging(new Runnable() { @Override public void run() { + int oldOffset = myOffset; final int leadSelectionOffset = getLeadSelectionOffset(); final VisualPosition leadSelectionPosition = getLeadSelectionPosition(); EditorSettings editorSettings = myEditor.getSettings(); @@ -370,7 +371,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret { else { int selectionStartToUse = leadSelectionOffset; VisualPosition selectionStartPositionToUse = leadSelectionPosition; - if (isUnknownDirection()) { + if (isUnknownDirection() || oldOffset > getSelectionStart() && oldOffset < getSelectionEnd()) { if (getOffset() > leadSelectionOffset ^ getSelectionStart() < getSelectionEnd()) { selectionStartToUse = getSelectionEnd(); selectionStartPositionToUse = getSelectionEndPosition(); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java index a653da599d80..2545df56d20c 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java @@ -167,4 +167,24 @@ public class EditorActionTest extends AbstractEditorTest { executeAction(IdeActions.ACTION_EDITOR_DELETE_TO_WORD_END); checkResultByText("class Foo { String s = \"a\\b\"; }"); } + + public void testUpWithSelectionOnCaretInsideSelection() throws Exception { + initText("blah blah\n" + + "blah blah\n" + + "blah blah"); + executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP_WITH_SELECTION); + checkResultByText("blah blah\n" + + "blah blah\n" + + "blah blah"); + } + + public void testDownWithSelectionOnCaretInsideSelection() throws Exception { + initText("blah blah\n" + + "blah blah\n" + + "blah blah"); + executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN_WITH_SELECTION); + checkResultByText("blah blah\n" + + "blah blah\n" + + "blah blah"); + } } \ No newline at end of file From 2394bc283028017efd43f503c88db75d7bf4ad1f Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 14 Jan 2015 16:08:45 +0300 Subject: [PATCH 23/55] [vcs-log] show progress in find by hash popup while loading log IDEA-134749 --- .../api/src/com/intellij/vcs/log/VcsLog.java | 4 +- .../com/intellij/vcs/log/impl/VcsLogImpl.java | 7 +- .../vcs/log/ui/FindPopupWithProgress.java | 125 ++++++++++++++++++ .../intellij/vcs/log/ui/GoToRefAction.java | 20 +-- .../PopupWithTextFieldWithAutoCompletion.java | 85 ------------ .../vcs/log/ui/TextFieldWithProgress.java | 104 +++++++++++++++ .../com/intellij/vcs/log/ui/VcsLogUiImpl.java | 26 ++-- .../SelectRevisionInGitLogAction.java | 36 ++++- 8 files changed, 293 insertions(+), 114 deletions(-) create mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/ui/FindPopupWithProgress.java delete mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/ui/PopupWithTextFieldWithAutoCompletion.java create mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/ui/TextFieldWithProgress.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index 29f63e6cdeb3..9636218cd449 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.Collection; import java.util.List; +import java.util.concurrent.Future; /** * Use this interface to access information available in the VCS Log. @@ -55,7 +56,7 @@ public interface VcsLog { /** * Selects the commit node defined by the given reference (commit hash, branch or tag). */ - void jumpToReference(String reference); + Future jumpToReference(String reference); /** * Returns the VCS log toolbar component. @@ -68,5 +69,4 @@ public interface VcsLog { */ @NotNull Collection getLogProviders(); - } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index e80032bbd9ba..a36e871489bd 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.Collection; import java.util.List; +import java.util.concurrent.Future; /** * @@ -85,7 +86,7 @@ public class VcsLogImpl implements VcsLog { } @Override - public void jumpToReference(final String reference) { + public Future jumpToReference(final String reference) { Collection references = getAllReferences(); VcsRef ref = ContainerUtil.find(references, new Condition() { @Override @@ -94,10 +95,10 @@ public class VcsLogImpl implements VcsLog { } }); if (ref != null) { - myUi.jumpToCommit(ref.getCommitHash()); + return myUi.jumpToCommit(ref.getCommitHash()); } else { - myUi.jumpToCommitByPartOfHash(reference); + return myUi.jumpToCommitByPartOfHash(reference); } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/FindPopupWithProgress.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/FindPopupWithProgress.java new file mode 100644 index 000000000000..0b46160165ad --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/FindPopupWithProgress.java @@ -0,0 +1,125 @@ +/* + * Copyright 2000-2015 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.intellij.vcs.log.ui; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; +import com.intellij.ui.components.JBTextField; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.Collection; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class FindPopupWithProgress { + private static final Logger LOG = Logger.getInstance(FindPopupWithProgress.class); + + @NotNull private final TextFieldWithProgress myTextField; + @NotNull private final Function myFunction; + @NotNull private final JBPopup myPopup; + @Nullable private Future myFuture; + + public FindPopupWithProgress(@NotNull final Project project, + @NotNull Collection variants, + @NotNull Function function) { + myFunction = function; + myTextField = new TextFieldWithProgress(project, variants) { + @Override + public void onOk() { + if (myFuture == null) { + final Future future = myFunction.fun(getText().trim()); + myFuture = future; + showProgress(); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + try { + future.get(); + ok(); + } + catch (CancellationException ex) { + cancel(); + } + catch (InterruptedException ex) { + cancel(); + } + catch (ExecutionException ex) { + LOG.error(ex); + cancel(); + } + } + }); + } + } + }; + + myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myTextField, myTextField.getPreferableFocusComponent()) + .setCancelOnClickOutside(true).setCancelOnWindowDeactivation(true).setCancelKeyEnabled(true).setRequestFocus(true).createPopup(); + myPopup.addListener(new JBPopupListener.Adapter() { + @Override + public void onClosed(LightweightWindowEvent event) { + if (!event.isOk()) { + if (myFuture != null) { + myFuture.cancel(false); + myFuture = null; + } + } + } + }); + + final JBTextField field = new JBTextField(20); + final Dimension size = field.getPreferredSize(); + final Insets insets = myTextField.getBorder().getBorderInsets(myTextField); + size.height += 6 + insets.top + insets.bottom; + size.width += 4 + insets.left + insets.right; + myPopup.setSize(size); + } + + private void cancel() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (myFuture != null) myFuture = null; + myTextField.hideProgress(); + myPopup.cancel(); + } + }); + } + + private void ok() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (myFuture != null) myFuture = null; + myTextField.hideProgress(); + myPopup.closeOk(null); + } + }); + } + + public void showUnderneathOf(@NotNull Component anchor) { + myPopup.showUnderneathOf(anchor); + } +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/GoToRefAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/GoToRefAction.java index 8b117c72da26..12f6b65a0551 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/GoToRefAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/GoToRefAction.java @@ -18,9 +18,6 @@ package com.intellij.vcs.log.ui; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.JBPopupListener; -import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.VcsLog; @@ -28,6 +25,7 @@ import com.intellij.vcs.log.VcsLogDataKeys; import com.intellij.vcs.log.VcsRef; import java.util.Collection; +import java.util.concurrent.Future; public class GoToRefAction extends DumbAwareAction { @@ -45,16 +43,12 @@ public class GoToRefAction extends DumbAwareAction { return ref.getName(); } }); - final PopupWithTextFieldWithAutoCompletion textField = new PopupWithTextFieldWithAutoCompletion(project, refs); - JBPopup popup = textField.createPopup(); - popup.addListener(new JBPopupListener.Adapter() { - @Override - public void onClosed(LightweightWindowEvent event) { - if (event.isOk()) { - log.jumpToReference(textField.getText().trim()); - } - } - }); + FindPopupWithProgress popup = new FindPopupWithProgress(project, refs, new Function() { + @Override + public Future fun(String text) { + return log.jumpToReference(text); + } + }); popup.showUnderneathOf(log.getToolbar()); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/PopupWithTextFieldWithAutoCompletion.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/PopupWithTextFieldWithAutoCompletion.java deleted file mode 100644 index fbfb71de3c04..000000000000 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/PopupWithTextFieldWithAutoCompletion.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2000-2013 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.intellij.vcs.log.ui; - -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization; -import com.intellij.ui.TextFieldWithAutoCompletion; -import com.intellij.ui.components.JBTextField; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.util.Collection; - -public class PopupWithTextFieldWithAutoCompletion extends TextFieldWithAutoCompletion { - - @Nullable private JBPopup myPopup; - - public PopupWithTextFieldWithAutoCompletion(@NotNull Project project, @NotNull Collection variants) { - super(project, new StringsCompletionProvider(variants, null), false, null); - setBorder(new EmptyBorder(3, 3, 3, 3)); - } - - public JBPopup createPopup() { - myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(this, this) - .setCancelOnClickOutside(true) - .setCancelOnWindowDeactivation(true) - .setCancelKeyEnabled(true) - .setRequestFocus(true) - .createPopup(); - - final JBTextField field = new JBTextField(20); - final Dimension size = field.getPreferredSize(); - final Insets insets = getBorder().getBorderInsets(this); - size.height+=6 + insets.top + insets.bottom; - size.width +=4 + insets.left + insets.right; - myPopup.setSize(size); - - return myPopup; - } - - @Override - protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - if (myPopup != null) { - myPopup.closeOk(e); - } - return true; - } - else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - if (myPopup != null) { - myPopup.cancel(e); - } - return true; - } - return false; - } - - @Override - protected EditorEx createEditor() { - // spell check is not needed - EditorEx editor = super.createEditor(); - SpellCheckingEditorCustomization.getInstance(false).customize(editor); - return editor; - } -} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/TextFieldWithProgress.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/TextFieldWithProgress.java new file mode 100644 index 000000000000..70901fe4caaa --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/TextFieldWithProgress.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2015 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.intellij.vcs.log.ui; + +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.progress.PerformInBackgroundOption; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.util.ui.AsyncProcessIcon; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.util.Collection; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public abstract class TextFieldWithProgress extends JPanel { + @NotNull private final TextFieldWithAutoCompletion myTextField; + @NotNull private final AsyncProcessIcon myProgressIcon; + + public TextFieldWithProgress(@NotNull Project project, @NotNull Collection variants) { + super(new BorderLayout()); + setBorder(IdeBorderFactory.createEmptyBorder(3)); + + myProgressIcon = new AsyncProcessIcon("Loading commits"); + myTextField = + new TextFieldWithAutoCompletion(project, new TextFieldWithAutoCompletion.StringsCompletionProvider(variants, null), false, + null) { + @Override + public void setBackground(Color bg) { + super.setBackground(bg); + myProgressIcon.setBackground(bg); + } + + @Override + protected EditorEx createEditor() { + // spell check is not needed + EditorEx editor = super.createEditor(); + SpellCheckingEditorCustomization.getInstance(false).customize(editor); + return editor; + } + + @Override + protected boolean processKeyBinding(KeyStroke ks, final KeyEvent e, int condition, boolean pressed) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + onOk(); + return true; + } + return false; + } + }; + myTextField.setBorder(IdeBorderFactory.createEmptyBorder()); + + myProgressIcon.setOpaque(true); + myProgressIcon.setBackground(myTextField.getBackground()); + + add(myTextField, BorderLayout.CENTER); + add(myProgressIcon, BorderLayout.EAST); + + hideProgress(); + } + + public JComponent getPreferableFocusComponent() { + return myTextField; + } + + public void showProgress() { + myTextField.setEnabled(false); + myProgressIcon.setVisible(true); + } + + public void hideProgress() { + myTextField.setEnabled(true); + myProgressIcon.setVisible(false); + } + + public String getText() { + return myTextField.getText(); + } + + public abstract void onOk(); +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 78ce9caeb2a1..7e098af05ee9 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -1,5 +1,6 @@ package com.intellij.vcs.log.ui; +import com.google.common.util.concurrent.SettableFuture; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -32,6 +33,7 @@ import javax.swing.table.TableModel; import java.awt.*; import java.util.ArrayList; import java.util.Collection; +import java.util.concurrent.Future; public class VcsLogUiImpl implements VcsLogUi, Disposable { @@ -192,22 +194,26 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { return myUiProperties.isShowRootNames(); } - public void jumpToCommit(@NotNull Hash commitHash) { + public Future jumpToCommit(@NotNull Hash commitHash) { + SettableFuture future = SettableFuture.create(); jumpTo(commitHash, new PairFunction() { @Override public Integer fun(GraphTableModel model, Hash hash) { return model.getRowOfCommit(hash); } - }); + }, future); + return future; } - public void jumpToCommitByPartOfHash(@NotNull String commitHash) { + public Future jumpToCommitByPartOfHash(@NotNull String commitHash) { + SettableFuture future = SettableFuture.create(); jumpTo(commitHash, new PairFunction() { @Override public Integer fun(GraphTableModel model, String hash) { return model.getRowOfCommitByPartOfHash(hash); } - }); + }, future); + return future; } public void handleAnswer(@Nullable GraphAnswer answer, boolean dataCouldChange) { @@ -235,13 +241,15 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { } } - private void jumpTo(@NotNull final T commitId, @NotNull final PairFunction rowGetter) { + private void jumpTo(@NotNull final T commitId, @NotNull final PairFunction rowGetter, @NotNull final SettableFuture future) { + if (future.isCancelled()) return; + GraphTableModel model = getModel(); if (model == null) { invokeOnChange(new Runnable() { @Override public void run() { - jumpTo(commitId, rowGetter); + jumpTo(commitId, rowGetter, future); } }); return; @@ -250,12 +258,13 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { int row = rowGetter.fun(model, commitId); if (row >= 0) { myMainFrame.getGraphTable().jumpToRow(row); + future.set(true); } else if (model.canRequestMore()) { model.requestToLoadMore(new Runnable() { @Override public void run() { - jumpTo(commitId, rowGetter); + jumpTo(commitId, rowGetter, future); } }); } @@ -263,12 +272,13 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { invokeOnChange(new Runnable() { @Override public void run() { - jumpTo(commitId, rowGetter); + jumpTo(commitId, rowGetter, future); } }); } else { commitNotFound(commitId.toString()); + future.set(false); } } diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java b/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java index 1d7db804019b..0d4c66a44f8e 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java @@ -2,6 +2,11 @@ package git4idea.history.wholeTree; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.PerformInBackgroundOption; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; @@ -22,7 +27,12 @@ import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + public class SelectRevisionInGitLogAction extends DumbAwareAction { + private static final Logger LOG = Logger.getInstance(SelectRevisionInGitLogAction.class); public SelectRevisionInGitLogAction() { super(GitBundle.getString("vcs.history.action.gitlog"), GitBundle.getString("vcs.history.action.gitlog"), null); @@ -30,7 +40,7 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction { @Override public void actionPerformed(@NotNull AnActionEvent event) { - Project project = event.getRequiredData(CommonDataKeys.PROJECT); + final Project project = event.getRequiredData(CommonDataKeys.PROJECT); final VcsRevisionNumber revision = getRevisionNumber(event); if (revision == null) { return; @@ -60,7 +70,7 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction { Runnable selectCommit = new Runnable() { @Override public void run() { - log.jumpToReference(revision.asString()); + jumpToRevisionUnderProgress(project, log, revision); } }; @@ -128,5 +138,25 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction { return null; } - + private static void jumpToRevisionUnderProgress(@NotNull Project project, @NotNull VcsLog log, @NotNull VcsRevisionNumber revision) { + final Future future = log.jumpToReference(revision.asString()); + if (!future.isDone()) { + ProgressManager.getInstance().run(new Task.Backgroundable(project, "Searching for revision " + revision.asString(), false/*can not cancel*/, + PerformInBackgroundOption.ALWAYS_BACKGROUND) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + future.get(); + } + catch (CancellationException ignored) { + } + catch (InterruptedException ignored) { + } + catch (ExecutionException e) { + LOG.error(e); + } + } + }); + } + } } From f0ee490791db7d125016b123dae86ae60e49614e Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 14 Jan 2015 16:13:47 +0300 Subject: [PATCH 24/55] [vcs-log] add NotNull annotations --- platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java | 1 + .../vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java | 1 + .../vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java | 2 ++ 3 files changed, 4 insertions(+) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index 9636218cd449..73b0c3bfdb54 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -56,6 +56,7 @@ public interface VcsLog { /** * Selects the commit node defined by the given reference (commit hash, branch or tag). */ + @NotNull Future jumpToReference(String reference); /** diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index a36e871489bd..0b685dffc3f1 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -85,6 +85,7 @@ public class VcsLogImpl implements VcsLog { return myUi.getDataPack().getRefsModel().getAllRefs(); } + @NotNull @Override public Future jumpToReference(final String reference) { Collection references = getAllReferences(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 7e098af05ee9..440b3efd1a9a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -194,6 +194,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { return myUiProperties.isShowRootNames(); } + @NotNull public Future jumpToCommit(@NotNull Hash commitHash) { SettableFuture future = SettableFuture.create(); jumpTo(commitHash, new PairFunction() { @@ -205,6 +206,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { return future; } + @NotNull public Future jumpToCommitByPartOfHash(@NotNull String commitHash) { SettableFuture future = SettableFuture.create(); jumpTo(commitHash, new PairFunction() { From ba2dc0e0db889f2451af3e723900376491759a00 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 14 Jan 2015 16:08:44 +0300 Subject: [PATCH 25/55] IDEA-17307 Enum must not be local in JSP declaration block --- .../codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 76da573725a8..e1fdc3840f2a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -1173,7 +1173,7 @@ public class GenericsHighlightUtil { public static HighlightInfo checkEnumMustNotBeLocal(final PsiClass aClass) { if (!aClass.isEnum()) return null; PsiElement parent = aClass.getParent(); - if (!(parent instanceof PsiClass || parent instanceof PsiFile)) { + if (!(parent instanceof PsiClass || parent instanceof PsiFile || parent instanceof PsiClassLevelDeclarationStatement)) { String description = JavaErrorMessages.message("local.enum"); TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); From 2806b9890bd3078b2a27d4d6ce2e9d1f0d1eb8ac Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 14 Jan 2015 16:29:01 +0300 Subject: [PATCH 26/55] IDEA-135089 Search and replace multiline text allows to input only three lines --- .../intellij/find/EditorSearchComponent.java | 17 ++++++++++++++--- .../util/src/com/intellij/util/ui/UIUtil.java | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index 747cea82df93..f30da0b39b4b 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -450,6 +450,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data else { nothingToSearchFor(); } + if (mySearchField instanceof JTextArea) { + UIUtil.adjustRows((JTextArea)mySearchField, 2, 6); + } } public boolean isRegexp() { @@ -637,6 +640,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data private void replaceFieldDocumentChanged() { setMatchesLimit(LivePreviewController.MATCHES_LIMIT); myFindModel.setStringToReplace(myReplaceField.getText()); + if (myReplaceField instanceof JTextArea) { + UIUtil.adjustRows((JTextArea)myReplaceField, 2, 6); + } } private boolean canReplaceCurrent() { @@ -697,12 +703,17 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data super.paintBorder(g); paintBorderOfTextField(g); } + + @Override + public Dimension getPreferredSize() { + return super.getPreferredSize(); + } }; ((JTextArea)editorTextField).setColumns(25); - ((JTextArea)editorTextField).setRows(3); + ((JTextArea)editorTextField).setRows(2); final JScrollPane scrollPane = new JBScrollPane(editorTextField, - ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, - ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); myLeftComponent.add(scrollPane, constraint); componentRef.set(scrollPane); } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 02bed0eedf02..6af544af7755 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -3215,6 +3215,10 @@ public class UIUtil { textComponent.getActionMap().put("redoKeystroke", REDO_ACTION); } + public static void adjustRows(JTextArea area, int minRows, int maxRows) { + area.setRows(Math.max(minRows, Math.min(maxRows, area.getText().split("\n").length))); + } + public static void playSoundFromResource(final String resourceName) { final Class callerClass = ReflectionUtil.getGrandCallerClass(); if (callerClass == null) return; From 2300591f46220e96d094598e969b21bfb0cdc88d Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 14 Jan 2015 14:48:41 +0100 Subject: [PATCH 27/55] show usage in preview editor --- .../com/intellij/find/impl/FindDialog.java | 85 +++++++++++++------ 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java index d44e4a25cb17..6db6bfe0e4db 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java @@ -60,6 +60,7 @@ import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.JBTable; import com.intellij.usageView.UsageInfo; import com.intellij.usages.*; +import com.intellij.usages.impl.UsagePreviewPanel; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.Processor; @@ -70,14 +71,14 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.event.*; -import java.util.Arrays; -import java.util.HashMap; +import java.util.*; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -123,7 +124,9 @@ public class FindDialog extends DialogWrapper { private static boolean myPreviewResultsTabWasSelected; private static final int RESULTS_PREVIEW_TAB_INDEX = 1; + private Splitter myPreviewSplitter; private JBTable myResultsPreviewTable; + private UsagePreviewPanel myUsagePreviewPanel; private TabbedPane myContent; private volatile ProgressIndicatorBase myResultsPreviewSearchProgress; @@ -173,6 +176,7 @@ public class FindDialog extends DialogWrapper { @Override protected void dispose() { finishPreviousPreviewSearch(); + if (myUsagePreviewPanel != null) Disposer.dispose(myUsagePreviewPanel); for(Map.Entry e: myComboBoxListeners.entrySet()) { e.getKey().removeDocumentListener(e.getValue()); } @@ -489,8 +493,29 @@ public class FindDialog extends DialogWrapper { } }; table.setShowColumns(false); + table.setShowGrid(false); new NavigateToSourceListener().installOn(table); + + Splitter previewSplitter = new Splitter(true, 0.5f, 0.1f, 0.9f); + myUsagePreviewPanel = new UsagePreviewPanel(myProject, new UsageViewPresentation()); myResultsPreviewTable = table; + myResultsPreviewTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) return; + int index = myResultsPreviewTable.getSelectionModel().getLeadSelectionIndex(); + if (index != -1) { + UsageInfo usageInfo = ((UsageInfo2UsageAdapter)myResultsPreviewTable.getModel().getValueAt(index, 0)).getUsageInfo(); + myUsagePreviewPanel.updateLayout(Collections.singletonList(usageInfo)); + } + else { + myUsagePreviewPanel.updateLayout(null); + } + } + }); + previewSplitter.setFirstComponent(new JBScrollPane(myResultsPreviewTable)); + previewSplitter.setSecondComponent(myUsagePreviewPanel.createComponent()); + myPreviewSplitter = previewSplitter; } } else { @@ -513,10 +538,10 @@ public class FindDialog extends DialogWrapper { resultsOptionPanel.add(myCbToOpenInNewTab); } - if (myResultsPreviewTable != null) { + if (myPreviewSplitter != null) { TabbedPane pane = new TabbedPaneImpl(SwingConstants.TOP); pane.insertTab("Options", null, optionsPanel, null, 0); - pane.insertTab("Preview", null, new JBScrollPane(myResultsPreviewTable), null, RESULTS_PREVIEW_TAB_INDEX); + pane.insertTab("Preview", null, myPreviewSplitter, null, RESULTS_PREVIEW_TAB_INDEX); myContent = pane; if (myPreviewResultsTabWasSelected) myContent.setSelectedIndex(RESULTS_PREVIEW_TAB_INDEX); @@ -1389,36 +1414,46 @@ public class FindDialog extends DialogWrapper { } private static class UsageTableCellRenderer extends JPanel implements TableCellRenderer { - private SimpleColoredComponent myUsageRenderer = new SimpleColoredComponent(); - private SimpleColoredComponent myFileAndLineNumber = new SimpleColoredComponent(); + private ColoredTableCellRenderer myUsageRenderer = new ColoredTableCellRenderer() { + @Override + protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { + if (value instanceof UsageInfo2UsageAdapter) { + TextChunk[] text = ((UsageInfo2UsageAdapter)value).getPresentation().getText(); + + // skip line number / file info + for (int i = 1; i < text.length; ++i) { + TextChunk textChunk = text[i]; + myUsageRenderer.append(textChunk.getText(), textChunk.getSimpleAttributesIgnoreBackground()); + } + } + setBorder(null); + } + }; + private ColoredTableCellRenderer myFileAndLineNumber = new ColoredTableCellRenderer() { + @Override + protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { + if (value instanceof UsageInfo2UsageAdapter) { + TextChunk[] text = ((UsageInfo2UsageAdapter)value).getPresentation().getText(); + // line number / file info + append(((UsageInfo2UsageAdapter)value).getFile().getName() + " " + text[0].getText(), SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES); + } + setBorder(null); + } + }; UsageTableCellRenderer() { setLayout(new BorderLayout()); + add(myUsageRenderer, BorderLayout.WEST); add(myFileAndLineNumber, BorderLayout.EAST); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - myUsageRenderer.clear(); - myFileAndLineNumber.clear(); - setBackground(isSelected && hasFocus ? UIUtil.getTableSelectionBackground() : UIUtil.getTableBackground()); + setBackground(UIUtil.getTableBackground(isSelected)); + myUsageRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + myFileAndLineNumber.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if (value instanceof UsageInfo2UsageAdapter) { - UsageInfo2UsageAdapter usageAdapter = (UsageInfo2UsageAdapter)value; - UsagePresentation presentation = usageAdapter.getPresentation(); - TextChunk[] text = presentation.getText(); - - // put line number / file info at the right - for (int i = 1; i < text.length; ++i) { - TextChunk textChunk = text[i]; - SimpleTextAttributes simples = textChunk.getSimpleAttributesIgnoreBackground(); - myUsageRenderer.append(textChunk.getText(), simples); - } - - myFileAndLineNumber.append(usageAdapter.getFile().getName() + " " + text[0].getText(), - SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES); - } return this; } } From 5b2519635a36baaa0290fac6f0205a39249abfaf Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 14 Jan 2015 14:49:44 +0100 Subject: [PATCH 28/55] Platform: ListTable/ListTableModel fixes: 1) first cell was always selected when TAB was pressed during editing. Fix: event.consume() 2) editing, adding and removing elements should scroll to the effected element 3) pressing 'add' when last element is empty should focus it and edit, otherwise isn't not clear, why 'add' doesn't work. 4) a bit more compact view (interlaced spacing removed, stripes added) 5) ListTableModel should send notifications, when value in a cell has been changed --- .../execution/util/ListTableWithButtons.java | 23 +++++++++++++++---- .../com/intellij/util/ui/ListTableModel.java | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/util/ListTableWithButtons.java b/platform/lang-api/src/com/intellij/execution/util/ListTableWithButtons.java index 78f833591ebc..22cbf612d5fd 100644 --- a/platform/lang-api/src/com/intellij/execution/util/ListTableWithButtons.java +++ b/platform/lang-api/src/com/intellij/execution/util/ListTableWithButtons.java @@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; +import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.Collections; @@ -40,6 +41,7 @@ public abstract class ListTableWithButtons extends Observable { private final List myElements = ContainerUtil.newArrayList(); private final JPanel myPanel; private final TableView myTableView; + private final CommonActionsPanel myActionsPanel; private boolean myIsEnabled = true; protected ListTableWithButtons() { @@ -55,6 +57,7 @@ public abstract class ListTableWithButtons extends Observable { final int column = myTableView.getEditingColumn(); final int row = myTableView.getEditingRow(); if (e.getModifiers() == 0 && (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB)) { + e.consume(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -69,6 +72,7 @@ public abstract class ListTableWithButtons extends Observable { nextRow = 0; } } + myTableView.scrollRectToVisible(myTableView.getCellRect(nextRow, nextColumn, true)); myTableView.editCellAt(nextRow, nextColumn); } }); @@ -79,19 +83,24 @@ public abstract class ListTableWithButtons extends Observable { } }; myTableView.setRowHeight(new JTextField().getPreferredSize().height); + myTableView.setIntercellSpacing(new Dimension(0, 0)); + myTableView.setStriped(true); + myTableView.getTableViewModel().setSortable(false); - myPanel = ToolbarDecorator.createDecorator(myTableView) + ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTableView); + myPanel = decorator .setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { - if (!myElements.isEmpty() && isEmpty(myElements.get(myElements.size() - 1))) return; myTableView.stopEditing(); setModified(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - myElements.add(createElement()); - myTableView.getTableViewModel().setItems(myElements); + if (myElements.isEmpty() || !isEmpty(myElements.get(myElements.size() - 1))) { + myElements.add(createElement()); + myTableView.getTableViewModel().setItems(myElements); + } myTableView.scrollRectToVisible(myTableView.getCellRect(myElements.size() - 1, 0, true)); myTableView.getComponent().editCellAt(myElements.size() - 1, 0); } @@ -105,6 +114,7 @@ public abstract class ListTableWithButtons extends Observable { T selected = getSelection(); if (selected != null) { int selectedIndex = myElements.indexOf(selected); + myTableView.scrollRectToVisible(myTableView.getCellRect(selectedIndex, 0, true)); myElements.remove(selected); myTableView.getTableViewModel().setItems(myElements); @@ -133,6 +143,7 @@ public abstract class ListTableWithButtons extends Observable { } }); + myActionsPanel = decorator.getActionsPanel(); myTableView.getComponent().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } @@ -157,6 +168,10 @@ public abstract class ListTableWithButtons extends Observable { return myPanel; } + public CommonActionsPanel getActionsPanel() { + return myActionsPanel; + } + public void setEnabled() { myTableView.getComponent().setEnabled(true); myIsEnabled = true; diff --git a/platform/util/src/com/intellij/util/ui/ListTableModel.java b/platform/util/src/com/intellij/util/ui/ListTableModel.java index 8e01d89374cc..bdd04ec399ac 100644 --- a/platform/util/src/com/intellij/util/ui/ListTableModel.java +++ b/platform/util/src/com/intellij/util/ui/ListTableModel.java @@ -116,6 +116,7 @@ public class ListTableModel extends TableViewModel implements Editab if (rowIndex < myItems.size()) { myColumnInfos[columnIndex].setValue(getItem(rowIndex), aValue); } + fireTableCellUpdated(rowIndex, columnIndex); } /** From f1c1790bdda323e3ce38003d2d48f48eb833f8cb Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 14 Jan 2015 16:57:32 +0300 Subject: [PATCH 29/55] [vcs] EA-62261 don't modify the externally received collection --- .../vcs/changes/patch/ApplyPatchDifferentiatedDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index 80f78e885500..e32434c67177 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -947,12 +947,12 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { if (myPatches.isEmpty() || (! myContainBasedChanges)) return; final List changes = getAllChanges(); Collections.sort(changes, myMyChangeComparator); - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + List selectedChanges = myChangesTreeList.getSelectedChanges(); int selectedIdx = 0; final ArrayList diffRequestPresentables = new ArrayList(changes.size()); if (selectedChanges.isEmpty()) { - selectedChanges.addAll(changes); + selectedChanges = changes; } if (! selectedChanges.isEmpty()) { final FilePatchInProgress.PatchChange c = selectedChanges.get(0); From 2438a0711c37ab6aa39b246dbb4c0cb447535d57 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Jan 2015 15:02:46 +0100 Subject: [PATCH 30/55] BytecodeAnalysisTest: don't spam to stdout --- .../codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java index 4c42cdd0e448..f833aff3d48f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java @@ -194,10 +194,12 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase { } private void checkCompoundId(Method method, PsiMethod psiMethod, boolean noKey) throws IOException { + /* System.out.println(); System.out.println(method.internalClassName); System.out.println(method.methodName); System.out.println(method.methodDesc); + */ HKey psiKey = BytecodeAnalysisConverter.psiKey(psiMethod, Direction.Out, myMessageDigest); From 01c96de0b7530e3438005e24126d9178fd9fc660 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 14 Jan 2015 17:18:47 +0300 Subject: [PATCH 31/55] refactoring pycharm educational second iteration extracted interactive-learning (language independent) and interactive-learning-python modules --- .../learn-python/gen/icons/StudyIcons.java | 27 ---- python/edu/learn-python/learn-python.iml | 21 --- .../resources/META-INF/plugin.xml | 82 ----------- .../python/edu/StudyResourceManger.java | 5 - .../python/edu/actions/StudyRunAction.java | 96 ------------- python/edu/main_pycharm_edu.iml | 3 +- .../interactive-learning-python.iml | 18 +++ .../resources/META-INF/plugin.xml | 43 ++++++ .../com/jetbrains/python/edu/user_tester.py | 0 .../resources/courses/introduction_course.zip | Bin .../edu/learning}/EducationalProjectType.png | Bin .../learning}/EducationalProjectType@2x.png | Bin .../learning}/EducationalProjectType_dark.png | Bin .../EducationalProjectType_dark@2x.png | Bin .../PyStudyDirectoryProjectGenerator.java | 95 +++++++++++++ .../edu/learning/PyStudyTestRunner.java} | 40 +----- .../jetbrains/edu/learning/PyStudyUtils.java | 76 ++++++++++ .../PyStudyIntroductionCourseAction.java} | 18 +-- .../actions/PyStudyWatchTutorialAction.java} | 6 +- .../highlighting/PyStudyVisitorFilter.java} | 6 +- .../icons/InteractiveLearningPythonIcons.java | 17 +++ .../testData/course.json | 0 .../testData/helloworld.py | 0 .../tests/JsonParserTest.java | 23 +-- .../tests/StudyDocumentListenerTest.java | 6 +- .../tests/StudyTestCase.java | 0 .../coursecreator/CCProjectGeneratorUtil.java | 3 + .../interactive-learning.iml | 3 + .../resources/META-INF/plugin.xml | 74 ++++++++++ .../com/jetbrains/edu/learning}/Lesson.png | Bin .../com/jetbrains/edu/learning}/Lesson@2x.png | Bin .../jetbrains/edu/learning}/LessonComp@2x.png | Bin .../jetbrains/edu/learning}/LessonCompl.png | Bin .../com/jetbrains/edu/learning}/Sandbox.png | Bin .../jetbrains/edu/learning}/Sandbox@2x.png | Bin .../com/jetbrains/edu/learning}/Task.png | Bin .../com/jetbrains/edu/learning}/Task@2x.png | Bin .../jetbrains/edu/learning}/Task@2x_dark.png | Bin .../com/jetbrains/edu/learning}/TaskCompl.png | Bin .../jetbrains/edu/learning}/TaskCompl@2x.png | Bin .../edu/learning}/TaskCompl@2x_dark.png | Bin .../edu/learning}/TaskCompl_dark.png | Bin .../com/jetbrains/edu/learning}/TaskProbl.png | Bin .../jetbrains/edu/learning}/TaskProbl@2x.png | Bin .../edu/learning}/TaskProbl@2x_dark.png | Bin .../edu/learning}/TaskProbl_dark.png | Bin .../com/jetbrains/edu/learning}/Task_dark.png | Bin .../jetbrains/edu/learning}/WatchInput.png | Bin .../com/jetbrains/edu/learning}/prev.png | Bin .../com/jetbrains/edu/learning}/resolve.png | Bin .../jetbrains/edu/learning}/resolve_dark.png | Bin .../com/jetbrains/edu/learning}/showHint.png | Bin .../jetbrains/edu/learning}/showHint@2x.png | Bin .../edu/learning}/StudyDocumentListener.java | 6 +- .../learning}/StudyEditorFactoryListener.java | 8 +- .../learning}/StudyInitialConfigurator.java | 2 +- .../learning}/StudyInstructionPainter.java | 6 +- .../jetbrains/edu/learning}/StudyNames.java | 5 +- .../edu/learning/StudyProjectGenerator.java} | 132 ++++++------------ .../jetbrains/edu/learning}/StudyState.java | 8 +- .../edu/learning}/StudyTaskManager.java | 21 ++- .../edu/learning/StudyTestRunner.java | 38 +++++ .../jetbrains/edu/learning}/StudyUtils.java | 64 +++++++-- .../learning/StudyUtilsExtensionPoint.java | 46 ++++++ .../learning}/TaskWindowDeleteHandler.java | 2 +- .../learning}/actions/StudyCheckAction.java | 25 ++-- .../actions/StudyEditInputAction.java | 18 +-- .../actions/StudyNextStudyTaskAction.java | 6 +- .../actions/StudyNextWindowAction.java | 6 +- .../actions/StudyPrevWindowAction.java | 10 +- .../actions/StudyPreviousStudyTaskAction.java | 6 +- .../actions/StudyRefreshTaskFileAction.java | 12 +- .../edu/learning/actions/StudyRunAction.java | 82 +++++++++++ .../actions/StudyShowHintAction.java | 18 +-- .../actions/StudyTaskNavigationAction.java | 12 +- .../actions/StudyWindowNavigationAction.java | 12 +- .../edu/learning}/course/Course.java | 2 +- .../edu/learning}/course/CourseInfo.java | 2 +- .../edu/learning}/course/Lesson.java | 4 +- .../edu/learning}/course/LessonInfo.java | 2 +- .../edu/learning}/course/Stateful.java | 2 +- .../edu/learning}/course/StudyStatus.java | 2 +- .../jetbrains/edu/learning}/course/Task.java | 6 +- .../edu/learning}/course/TaskFile.java | 8 +- .../edu/learning}/course/TaskWindow.java | 8 +- .../edu/learning}/course/UserTest.java | 2 +- .../edu/learning}/editor/StudyEditor.java | 26 ++-- .../editor/StudyFileEditorProvider.java | 6 +- .../projectView/StudyDirectoryNode.java | 20 +-- .../StudyTreeStructureProvider.java | 10 +- .../edu/learning}/ui/StudyCondition.java | 4 +- .../learning}/ui/StudyNewProjectPanel.form | 2 +- .../learning}/ui/StudyNewProjectPanel.java | 17 +-- .../edu/learning}/ui/StudyProgressBar.java | 2 +- .../learning}/ui/StudyTestContentPanel.java | 4 +- .../learning}/ui/StudyToolWindowFactory.java | 12 +- 96 files changed, 796 insertions(+), 552 deletions(-) delete mode 100644 python/edu/learn-python/gen/icons/StudyIcons.java delete mode 100644 python/edu/learn-python/learn-python.iml delete mode 100644 python/edu/learn-python/resources/META-INF/plugin.xml delete mode 100644 python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java delete mode 100644 python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java create mode 100644 python/educational-python/interactive-learning-python/resources/META-INF/plugin.xml rename python/{edu/learn-python => educational-python/interactive-learning-python}/resources/com/jetbrains/python/edu/user_tester.py (100%) rename python/{edu/learn-python => educational-python/interactive-learning-python}/resources/courses/introduction_course.zip (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning}/EducationalProjectType.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning}/EducationalProjectType@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning}/EducationalProjectType_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning}/EducationalProjectType_dark@2x.png (100%) create mode 100644 python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java rename python/{edu/learn-python/src/com/jetbrains/python/edu/StudyTestRunner.java => educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java} (62%) create mode 100644 python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java rename python/{edu/learn-python/src/com/jetbrains/python/edu/actions/StudyIntroductionCourseAction.java => educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java} (81%) rename python/{edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWatchTutorialAction.java => educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java} (74%) rename python/{edu/learn-python/src/com/jetbrains/python/edu/highlighting/StudyVisitorFilter.java => educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java} (76%) create mode 100644 python/educational-python/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java rename python/{edu/learn-python => educational-python/interactive-learning-python}/testData/course.json (100%) rename python/{edu/learn-python => educational-python/interactive-learning-python}/testData/helloworld.py (100%) rename python/{edu/learn-python => educational-python/interactive-learning-python}/tests/JsonParserTest.java (63%) rename python/{edu/learn-python => educational-python/interactive-learning-python}/tests/StudyDocumentListenerTest.java (91%) rename python/{edu/learn-python => educational-python/interactive-learning-python}/tests/StudyTestCase.java (100%) create mode 100644 python/educational/interactive-learning/resources/META-INF/plugin.xml rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Lesson.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Lesson@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/LessonComp@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/LessonCompl.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Sandbox.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Sandbox@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Task.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Task@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Task@2x_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskCompl.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskCompl@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskCompl@2x_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskCompl_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskProbl.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskProbl@2x.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskProbl@2x_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/TaskProbl_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/Task_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/WatchInput.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/prev.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/resolve.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/resolve_dark.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/showHint.png (100%) rename python/{edu/learn-python/resources/icons/com/jetbrains/python/edu => educational/interactive-learning/resources/icons/com/jetbrains/edu/learning}/showHint@2x.png (100%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyDocumentListener.java (94%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyEditorFactoryListener.java (94%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyInitialConfigurator.java (98%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyInstructionPainter.java (95%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyNames.java (85%) rename python/{edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java => educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectGenerator.java} (87%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyState.java (88%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyTaskManager.java (95%) create mode 100644 python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTestRunner.java rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/StudyUtils.java (76%) create mode 100644 python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtilsExtensionPoint.java rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/TaskWindowDeleteHandler.java (95%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyCheckAction.java (96%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyEditInputAction.java (94%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyNextStudyTaskAction.java (81%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyNextWindowAction.java (87%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyPrevWindowAction.java (75%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyPreviousStudyTaskAction.java (81%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyRefreshTaskFileAction.java (95%) create mode 100644 python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyShowHintAction.java (89%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyTaskNavigationAction.java (92%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/actions/StudyWindowNavigationAction.java (87%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/Course.java (98%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/CourseInfo.java (96%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/Lesson.java (97%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/LessonInfo.java (96%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/Stateful.java (73%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/StudyStatus.java (70%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/Task.java (98%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/TaskFile.java (97%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/TaskWindow.java (97%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/course/UserTest.java (94%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/editor/StudyEditor.java (95%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/editor/StudyFileEditorProvider.java (93%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/projectView/StudyDirectoryNode.java (89%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/projectView/StudyTreeStructureProvider.java (91%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/ui/StudyCondition.java (86%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/ui/StudyNewProjectPanel.form (98%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/ui/StudyNewProjectPanel.java (93%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/ui/StudyProgressBar.java (98%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/ui/StudyTestContentPanel.java (96%) rename python/{edu/learn-python/src/com/jetbrains/python/edu => educational/interactive-learning/src/com/jetbrains/edu/learning}/ui/StudyToolWindowFactory.java (91%) diff --git a/python/edu/learn-python/gen/icons/StudyIcons.java b/python/edu/learn-python/gen/icons/StudyIcons.java deleted file mode 100644 index f1db45d83e73..000000000000 --- a/python/edu/learn-python/gen/icons/StudyIcons.java +++ /dev/null @@ -1,27 +0,0 @@ -package icons; - -import com.intellij.openapi.util.IconLoader; - -import javax.swing.*; - -/** - * NOTE THIS FILE IS AUTO-GENERATED - * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead - */ -public class StudyIcons { - private static Icon load(String path) { - return IconLoader.getIcon(path, StudyIcons.class); - } - - public static final Icon EducationalProjectType = load("/icons/com/jetbrains/python/edu/EducationalProjectType.png"); // 16x16 - public static final Icon Lesson = load("/icons/com/jetbrains/python/edu/Lesson.png"); // 16x16 - public static final Icon LessonCompl = load("/icons/com/jetbrains/python/edu/LessonCompl.png"); // 16x16 - public static final Icon Prev = load("/icons/com/jetbrains/python/edu/prev.png"); // 16x16 - public static final Icon Resolve = load("/icons/com/jetbrains/python/edu/resolve.png"); // 16x16 - public static final Icon Sandbox = load("/icons/com/jetbrains/python/edu/Sandbox.png"); // 16x16 - public static final Icon ShowHint = load("/icons/com/jetbrains/python/edu/showHint.png"); // 16x16 - public static final Icon Task = load("/icons/com/jetbrains/python/edu/Task.png"); // 16x16 - public static final Icon TaskCompl = load("/icons/com/jetbrains/python/edu/TaskCompl.png"); // 16x16 - public static final Icon TaskProbl = load("/icons/com/jetbrains/python/edu/TaskProbl.png"); // 16x16 - public static final Icon WatchInput = load("/icons/com/jetbrains/python/edu/WatchInput.png"); // 24x24 -} diff --git a/python/edu/learn-python/learn-python.iml b/python/edu/learn-python/learn-python.iml deleted file mode 100644 index f2b46e9e5479..000000000000 --- a/python/edu/learn-python/learn-python.iml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/python/edu/learn-python/resources/META-INF/plugin.xml b/python/edu/learn-python/resources/META-INF/plugin.xml deleted file mode 100644 index a8e99c9506ec..000000000000 --- a/python/edu/learn-python/resources/META-INF/plugin.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - com.jetbrains.python.edu.learn-python - Educational plugin for PyCharm - 1.2 - - - - - - - - - - - com.intellij.modules.lang - com.intellij.modules.python - - - - com.jetbrains.python.edu.StudyTaskManager - com.jetbrains.python.edu.StudyTaskManager - - - - - - com.jetbrains.python.edu.StudyInitialConfigurator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java deleted file mode 100644 index 38f1c2ff2cde..000000000000 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.jetbrains.python.edu; - -public interface StudyResourceManger { - String USER_TESTER = "user_tester.py"; -} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java deleted file mode 100644 index c1398a9a585a..000000000000 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.jetbrains.python.edu.actions; - -import com.intellij.execution.ExecutionException; -import com.intellij.execution.RunContentExecutor; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.OSProcessHandler; -import com.intellij.execution.process.ProcessHandler; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.python.edu.StudyResourceManger; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.Task; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.editor.StudyEditor; -import com.jetbrains.python.run.PythonTracebackFilter; -import org.jetbrains.annotations.NotNull; - -import java.io.File; - -public class StudyRunAction extends DumbAwareAction { - private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName()); - public static final String ACTION_ID = "StudyRunAction"; - private ProcessHandler myHandler; - - public void run(@NotNull final Project project, @NotNull final Sdk sdk) { - if (myHandler != null && !myHandler.isProcessTerminated()) return; - Editor selectedEditor = StudyEditor.getSelectedEditor(project); - FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); - assert selectedEditor != null; - VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument()); - StudyTaskManager taskManager = StudyTaskManager.getInstance(project); - if (openedFile != null && openedFile.getCanonicalPath() != null) { - String filePath = openedFile.getCanonicalPath(); - GeneralCommandLine cmd = new GeneralCommandLine(); - cmd.withWorkDirectory(openedFile.getParent().getCanonicalPath()); - String pythonPath = sdk.getHomePath(); - if (pythonPath != null) { - cmd.setExePath(pythonPath); - TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile); - assert selectedTaskFile != null; - Task currentTask = selectedTaskFile.getTask(); - if (!currentTask.getUserTests().isEmpty()) { - cmd.addParameter(new File(project.getBaseDir().getPath(), StudyResourceManger.USER_TESTER).getPath()); - cmd.addParameter(pythonPath); - cmd.addParameter(filePath); - Process process; - try { - process = cmd.createProcess(); - } - catch (ExecutionException e) { - LOG.error(e); - return; - } - myHandler = new OSProcessHandler(process); - RunContentExecutor executor = new RunContentExecutor(project, myHandler).withFilter(new PythonTracebackFilter(project)); - Disposer.register(project, executor); - executor.run(); - return; - } - try { - cmd.addParameter(filePath); - Process p = cmd.createProcess(); - myHandler = new OSProcessHandler(p); - - RunContentExecutor executor = new RunContentExecutor(project, myHandler).withFilter(new PythonTracebackFilter(project)); - Disposer.register(project, executor); - executor.run(); - } - - catch (ExecutionException e) { - LOG.error(e); - } - } - } - } - - public void actionPerformed(@NotNull AnActionEvent e) { - Project project = e.getProject(); - if (project == null) { - return; - } - Sdk sdk = StudyUtils.findPythonSdk(project); - if (sdk == null) { - return; - } - run(project, sdk); - } -} diff --git a/python/edu/main_pycharm_edu.iml b/python/edu/main_pycharm_edu.iml index c29ec159fc09..7dbfb712fc9c 100644 --- a/python/edu/main_pycharm_edu.iml +++ b/python/edu/main_pycharm_edu.iml @@ -15,9 +15,10 @@ - + + \ No newline at end of file diff --git a/python/educational-python/interactive-learning-python/interactive-learning-python.iml b/python/educational-python/interactive-learning-python/interactive-learning-python.iml index c90834f2d607..96fc1b873f54 100644 --- a/python/educational-python/interactive-learning-python/interactive-learning-python.iml +++ b/python/educational-python/interactive-learning-python/interactive-learning-python.iml @@ -4,8 +4,26 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/educational-python/interactive-learning-python/resources/META-INF/plugin.xml b/python/educational-python/interactive-learning-python/resources/META-INF/plugin.xml new file mode 100644 index 000000000000..be0490b7ba79 --- /dev/null +++ b/python/educational-python/interactive-learning-python/resources/META-INF/plugin.xml @@ -0,0 +1,43 @@ + + + com.jetbrains.python.edu.interactivelearning.python + Educational plugin for PyCharm + 2.0 + + + + + + + + + + + com.intellij.modules.lang + com.intellij.modules.python + com.jetbrains.edu.interactivelearning + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/edu/learn-python/resources/com/jetbrains/python/edu/user_tester.py b/python/educational-python/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py similarity index 100% rename from python/edu/learn-python/resources/com/jetbrains/python/edu/user_tester.py rename to python/educational-python/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py diff --git a/python/edu/learn-python/resources/courses/introduction_course.zip b/python/educational-python/interactive-learning-python/resources/courses/introduction_course.zip similarity index 100% rename from python/edu/learn-python/resources/courses/introduction_course.zip rename to python/educational-python/interactive-learning-python/resources/courses/introduction_course.zip diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType.png b/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType.png rename to python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType@2x.png b/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType@2x.png rename to python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType_dark.png b/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType_dark.png rename to python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType_dark@2x.png b/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/EducationalProjectType_dark@2x.png rename to python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java new file mode 100644 index 000000000000..293282be29e3 --- /dev/null +++ b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -0,0 +1,95 @@ +package com.jetbrains.edu.learning; + +import com.intellij.facet.ui.FacetEditorValidator; +import com.intellij.facet.ui.FacetValidatorsManager; +import com.intellij.facet.ui.ValidationResult; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.platform.DirectoryProjectGenerator; +import com.jetbrains.edu.learning.course.CourseInfo; +import com.jetbrains.edu.learning.ui.StudyNewProjectPanel; +import com.jetbrains.python.newProject.PythonProjectGenerator; +import icons.InteractiveLearningPythonIcons; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.File; +import java.util.Map; + + +public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator { + private final StudyProjectGenerator myGenerator; + public ValidationResult myValidationResult = new ValidationResult("selected course is not valid"); + + public PyStudyDirectoryProjectGenerator() { + myGenerator = new StudyProjectGenerator(); + myGenerator.addSettingsStateListener(new StudyProjectGenerator.SettingsListener() { + @Override + public void stateChanged(ValidationResult result) { + setValidationResult(result); + } + }); + } + + @Nls + @NotNull + @Override + public String getName() { + return "Educational"; + } + + @Nullable + @Override + public Object showGenerationSettings(VirtualFile baseDir) throws ProcessCanceledException { + return null; + } + + @Nullable + @Override + public Icon getLogo() { + return InteractiveLearningPythonIcons.EducationalProjectType; + } + + + @Override + public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, + @Nullable Object settings, @NotNull Module module) { + myGenerator.generateProject(project, baseDir); + } + @NotNull + @Override + public ValidationResult validate(@NotNull String s) { + return myValidationResult; + } + + public void setValidationResult(ValidationResult validationResult) { + myValidationResult = validationResult; + } + + @Nullable + @Override + public JPanel extendBasePanel() throws ProcessCanceledException { + StudyNewProjectPanel settingsPanel = new StudyNewProjectPanel(myGenerator); + settingsPanel.registerValidators(new FacetValidatorsManager() { + public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) { + throw new UnsupportedOperationException(); + } + public void validate() { + fireStateChanged(); + } + }); + return settingsPanel.getContentPanel(); + } + + public Map getCourses() { + return myGenerator.getCourses(); + } + + public void setSelectedCourse(CourseInfo course) { + myGenerator.setSelectedCourse(course); + } +} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTestRunner.java b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java similarity index 62% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyTestRunner.java rename to python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java index 78eadcbfe8b2..bc0e563d80c9 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTestRunner.java +++ b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java @@ -1,36 +1,26 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.ProcessOutput; -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.edu.learning.course.Course; +import com.jetbrains.edu.learning.course.Task; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; -import java.io.*; +import java.io.File; import java.util.Map; -public class StudyTestRunner { - public static final String STUDY_PREFIX="#educational_plugin"; - public static final String TEST_OK = "test OK"; - private static final String TEST_FAILED = "FAILED + "; +public class PyStudyTestRunner extends StudyTestRunner { 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; + PyStudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskfile) { + super(task, taskfile); } - public Process createCheckProcess(Project project, String executablePath) throws ExecutionException { Sdk sdk = PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]); File testRunner = new File(myTaskDir.getPath(), myTask.getTestFile()); @@ -61,20 +51,4 @@ public class StudyTestRunner { } return null; } - - - @NotNull - public String getTestsOutput(@NotNull final ProcessOutput processOutput) { - for (String line : processOutput.getStdoutLines()) { - if (line.contains(STUDY_PREFIX)) { - if (line.contains(TEST_OK)) { - continue; - } - int messageStart = line.indexOf(TEST_FAILED); - return line.substring(messageStart + TEST_FAILED.length()); - } - } - - return TEST_OK; - } } diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java new file mode 100644 index 000000000000..524510e97e6c --- /dev/null +++ b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java @@ -0,0 +1,76 @@ +/* + * 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.learning; + +import com.intellij.execution.RunContentExecutor; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.python.run.PythonTracebackFilter; +import com.jetbrains.python.sdk.PythonSdkType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; + +public class PyStudyUtils implements StudyUtilsExtensionPoint { + + @Override + public Sdk findSdk(@NotNull final Project project) { + return PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]); + } + + @Nullable + @Override + public String getLinkToTutorial() { + return "If you'd like to learn" + + " more about PyCharm " + + "Educational Edition, " + + "click here to watch a tutorial"; + } + + @Override + public StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) { + return new PyStudyTestRunner(task, taskDir); + } + + @Override + public RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler) { + return new RunContentExecutor(project, handler).withFilter(new PythonTracebackFilter(project)); + } + + @Override + public void setCommandLineParameters(@NotNull final GeneralCommandLine cmd, + @NotNull final Project project, + @NotNull final String filePath, + @NotNull final String pythonPath, + @NotNull final Task currentTask) { + if (!currentTask.getUserTests().isEmpty()) { + cmd.addParameter(new File(project.getBaseDir().getPath(), StudyNames.USER_TESTER).getPath()); + cmd.addParameter(pythonPath); + cmd.addParameter(filePath); + } + else { + cmd.addParameter(filePath); + } + } + + +} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyIntroductionCourseAction.java b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java similarity index 81% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyIntroductionCourseAction.java rename to python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java index a03dc6acec3b..a7785e16838c 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyIntroductionCourseAction.java +++ b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.actionSystem.AnAction; @@ -21,23 +21,23 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.Sdk; +import com.jetbrains.edu.learning.PyStudyDirectoryProjectGenerator; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.CourseInfo; import com.jetbrains.python.configuration.PyConfigurableInterpreterList; -import com.jetbrains.python.edu.StudyDirectoryProjectGenerator; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.CourseInfo; import com.jetbrains.python.newProject.actions.GenerateProjectCallback; import com.jetbrains.python.newProject.actions.ProjectSpecificSettingsStep; -import icons.StudyIcons; +import icons.InteractiveLearningPythonIcons; import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.List; import java.util.Map; -public class StudyIntroductionCourseAction extends AnAction { +public class PyStudyIntroductionCourseAction extends AnAction { - public StudyIntroductionCourseAction() { - super("Introduction to Python", "Introduction to Python", StudyIcons.EducationalProjectType); + public PyStudyIntroductionCourseAction() { + super("Introduction to Python", "Introduction to Python", InteractiveLearningPythonIcons.EducationalProjectType); } @Override @@ -48,7 +48,7 @@ public class StudyIntroductionCourseAction extends AnAction { } else { final GenerateProjectCallback callback = new GenerateProjectCallback(); - final StudyDirectoryProjectGenerator generator = new StudyDirectoryProjectGenerator(); + final PyStudyDirectoryProjectGenerator generator = new PyStudyDirectoryProjectGenerator(); final Map courses = generator.getCourses(); CourseInfo introCourse = null; for (CourseInfo info : courses.keySet()) { diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWatchTutorialAction.java b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java similarity index 74% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWatchTutorialAction.java rename to python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java index cae18e2457ad..e9e1b2b378bb 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWatchTutorialAction.java +++ b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java @@ -1,12 +1,12 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.DumbAwareAction; import org.jetbrains.annotations.NotNull; -public class StudyWatchTutorialAction extends DumbAwareAction { - public StudyWatchTutorialAction() { +public class PyStudyWatchTutorialAction extends DumbAwareAction { + public PyStudyWatchTutorialAction() { super("Learn more about PyCharm Educational Edition", null, null); } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/highlighting/StudyVisitorFilter.java b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java similarity index 76% rename from python/edu/learn-python/src/com/jetbrains/python/edu/highlighting/StudyVisitorFilter.java rename to python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java index dc7495adb16e..4b849da0bf7a 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/highlighting/StudyVisitorFilter.java +++ b/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java @@ -1,12 +1,12 @@ -package com.jetbrains.python.edu.highlighting; +package com.jetbrains.edu.learning.highlighting; import com.intellij.psi.PsiFile; -import com.jetbrains.python.edu.StudyTaskManager; +import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.python.inspections.PythonVisitorFilter; import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection; import org.jetbrains.annotations.NotNull; -public class StudyVisitorFilter implements PythonVisitorFilter { +public class PyStudyVisitorFilter implements PythonVisitorFilter { @Override public boolean isSupported(@NotNull final Class visitorClass, @NotNull final PsiFile file) { if (StudyTaskManager.getInstance(file.getProject()).getCourse() == null) return true; diff --git a/python/educational-python/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java b/python/educational-python/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java new file mode 100644 index 000000000000..08b0bdd2acd8 --- /dev/null +++ b/python/educational-python/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java @@ -0,0 +1,17 @@ +package icons; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; + +/** + * NOTE THIS FILE IS AUTO-GENERATED + * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead + */ +public class InteractiveLearningPythonIcons { + private static Icon load(String path) { + return IconLoader.getIcon(path, InteractiveLearningPythonIcons.class); + } + + public static final Icon EducationalProjectType = load("/icons/com/jetbrains/edu/learning/EducationalProjectType.png"); // 16x16 +} diff --git a/python/edu/learn-python/testData/course.json b/python/educational-python/interactive-learning-python/testData/course.json similarity index 100% rename from python/edu/learn-python/testData/course.json rename to python/educational-python/interactive-learning-python/testData/course.json diff --git a/python/edu/learn-python/testData/helloworld.py b/python/educational-python/interactive-learning-python/testData/helloworld.py similarity index 100% rename from python/edu/learn-python/testData/helloworld.py rename to python/educational-python/interactive-learning-python/testData/helloworld.py diff --git a/python/edu/learn-python/tests/JsonParserTest.java b/python/educational-python/interactive-learning-python/tests/JsonParserTest.java similarity index 63% rename from python/edu/learn-python/tests/JsonParserTest.java rename to python/educational-python/interactive-learning-python/tests/JsonParserTest.java index df8ee03a6c39..b9fd9654a90e 100644 --- a/python/edu/learn-python/tests/JsonParserTest.java +++ b/python/educational-python/interactive-learning-python/tests/JsonParserTest.java @@ -1,32 +1,30 @@ import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import org.junit.Before; -import org.junit.Test; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.Course; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.Course; +import com.jetbrains.python.PythonHelpersLocator; +import junit.framework.TestCase; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.io.Reader; -import static org.junit.Assert.assertEquals; /** * author: liana * data: 7/4/14. */ -public class JsonParserTest { +public class JsonParserTest extends TestCase { private Course myCourse = null; - @Before - public void setUp() throws FileNotFoundException { - Reader reader = new InputStreamReader(new FileInputStream("testData/course.json")); + + public void setUp() throws Exception { + super.setUp(); + Reader reader = new InputStreamReader(new FileInputStream(getTestDataPath() + "/course.json")); Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); myCourse = gson.fromJson(reader, Course.class); } - @Test public void testCourseLevel() { assertEquals(myCourse.getName(), "Python для начинающих"); assertEquals(StudyUtils.getFirst(myCourse.getLessons().get(1).getTaskList().get(0).getUserTests()).getInput(), "sum-input.txt"); @@ -34,4 +32,7 @@ public class JsonParserTest { assertEquals(myCourse.getLessons().get(0).getTaskList().size(), 2); assertEquals(myCourse.getLessons().get(1).getTaskList().size(), 1); } + protected String getTestDataPath() { + return PythonHelpersLocator.getPythonCommunityPath() + "/edu/learn-python/testData"; + } } diff --git a/python/edu/learn-python/tests/StudyDocumentListenerTest.java b/python/educational-python/interactive-learning-python/tests/StudyDocumentListenerTest.java similarity index 91% rename from python/edu/learn-python/tests/StudyDocumentListenerTest.java rename to python/educational-python/interactive-learning-python/tests/StudyDocumentListenerTest.java index 9a89d12d670a..1004bd643dd9 100644 --- a/python/edu/learn-python/tests/StudyDocumentListenerTest.java +++ b/python/educational-python/interactive-learning-python/tests/StudyDocumentListenerTest.java @@ -3,9 +3,9 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.psi.PsiFile; -import com.jetbrains.python.edu.StudyDocumentListener; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.course.TaskWindow; +import com.jetbrains.edu.learning.StudyDocumentListener; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.course.TaskWindow; import java.util.ArrayList; import java.util.List; diff --git a/python/edu/learn-python/tests/StudyTestCase.java b/python/educational-python/interactive-learning-python/tests/StudyTestCase.java similarity index 100% rename from python/edu/learn-python/tests/StudyTestCase.java rename to python/educational-python/interactive-learning-python/tests/StudyTestCase.java diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java index 7ccd9a8d7f6a..2d7d03f1dc9e 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectGeneratorUtil.java @@ -16,6 +16,9 @@ import org.jetbrains.annotations.NotNull; public class CCProjectGeneratorUtil { + private CCProjectGeneratorUtil() { + } + public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, @NotNull final String name, @NotNull final String author, @NotNull final String description) { diff --git a/python/educational/interactive-learning/interactive-learning.iml b/python/educational/interactive-learning/interactive-learning.iml index c90834f2d607..7413f5da4ba1 100644 --- a/python/educational/interactive-learning/interactive-learning.iml +++ b/python/educational/interactive-learning/interactive-learning.iml @@ -4,8 +4,11 @@ + + + \ No newline at end of file diff --git a/python/educational/interactive-learning/resources/META-INF/plugin.xml b/python/educational/interactive-learning/resources/META-INF/plugin.xml new file mode 100644 index 000000000000..8374db06e8ed --- /dev/null +++ b/python/educational/interactive-learning/resources/META-INF/plugin.xml @@ -0,0 +1,74 @@ + + + com.jetbrains.edu.interactivelearning + Educational plugin core + 2.0 + + + + + + + + + + + com.intellij.modules.lang + + + + com.jetbrains.edu.learning.StudyTaskManager + com.jetbrains.edu.learning.StudyTaskManager + + + + + + com.jetbrains.edu.learning.StudyInitialConfigurator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Lesson.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Lesson.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Lesson.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Lesson.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Lesson@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Lesson@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Lesson@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Lesson@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/LessonComp@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/LessonComp@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/LessonComp@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/LessonComp@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/LessonCompl.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/LessonCompl.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/LessonCompl.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/LessonCompl.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Sandbox.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Sandbox.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Sandbox.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Sandbox.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Sandbox@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Sandbox@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Sandbox@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Sandbox@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task@2x_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task@2x_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task@2x_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task@2x_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl@2x_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl@2x_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl@2x_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl@2x_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskCompl_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskCompl_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl@2x.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl@2x_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl@2x_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl@2x_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl@2x_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/TaskProbl_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/TaskProbl_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Task_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/Task_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/WatchInput.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/WatchInput.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/WatchInput.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/WatchInput.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/prev.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/prev.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/prev.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/prev.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/resolve.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/resolve.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve_dark.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/resolve_dark.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve_dark.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/resolve_dark.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/showHint.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/showHint.png diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint@2x.png b/python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/showHint@2x.png similarity index 100% rename from python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint@2x.png rename to python/educational/interactive-learning/resources/icons/com/jetbrains/edu/learning/showHint@2x.png diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyDocumentListener.java similarity index 94% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyDocumentListener.java index 848becfae1b1..9714472a5649 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyDocumentListener.java @@ -1,12 +1,12 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.course.TaskWindow; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.course.TaskWindow; import java.util.ArrayList; import java.util.List; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyEditorFactoryListener.java similarity index 94% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyEditorFactoryListener.java index 8d580923f6e4..78da60815e4a 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyEditorFactoryListener.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.openapi.application.ApplicationManager; @@ -12,9 +12,9 @@ import com.intellij.openapi.editor.event.EditorMouseEvent; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.course.TaskWindow; -import com.jetbrains.python.edu.editor.StudyEditor; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.course.TaskWindow; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import java.awt.*; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyInitialConfigurator.java similarity index 98% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyInitialConfigurator.java index 6078025e9492..fef9cc78bd8a 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyInitialConfigurator.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.ide.RecentProjectsManager; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyInstructionPainter.java similarity index 95% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyInstructionPainter.java index 95ecfb49651f..38266615e0cb 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyInstructionPainter.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; @@ -12,7 +12,7 @@ import com.intellij.ui.JBColor; import com.intellij.util.PairFunction; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.UIUtil; -import com.jetbrains.python.edu.actions.*; +import com.jetbrains.edu.learning.actions.*; import javax.swing.*; import java.awt.*; @@ -32,7 +32,7 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter { UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f); - painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180)); + painter.appendLine("Educational Edition").underlined(new JBColor(Gray._150, Gray._180)); addAction(painter, "Navigate to the next answer placeholder", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true); String shortcut1 = getShortcutText(StudyPrevWindowAction.ACTION_ID, StudyPrevWindowAction.SHORTCUT, false, false); String shortcut2 = getShortcutText(StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT, false, false); diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyNames.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyNames.java similarity index 85% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyNames.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyNames.java index 348ce36e6d9c..893f0d3b59ac 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyNames.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyNames.java @@ -13,18 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import org.jetbrains.annotations.NonNls; @NonNls public class StudyNames { - public static final String INTRODUCTION_COURSE = "introduction_course"; public static final String TASK_HTML = "task.html"; public static final String TASK_TESTS = "tests.py"; - public static final String COURSES = "courses"; public static final String LESSON = "lesson"; public static final String TEST_HELPER = "test_helper.py"; + public static final String USER_TESTER = "user_tester.py"; private StudyNames() { } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectGenerator.java similarity index 87% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectGenerator.java index cc2bc803f0ea..c6954c6e60d6 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectGenerator.java @@ -1,9 +1,7 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.google.gson.*; import com.google.gson.stream.JsonReader; -import com.intellij.facet.ui.FacetEditorValidator; -import com.intellij.facet.ui.FacetValidatorsManager; import com.intellij.facet.ui.ValidationResult; import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.projectView.impl.AbstractProjectViewPane; @@ -13,8 +11,6 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.LocalFileSystem; @@ -24,29 +20,26 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; -import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.platform.templates.github.GeneratorException; import com.intellij.platform.templates.github.ZipUtil; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.jetbrains.python.edu.course.*; -import com.jetbrains.python.edu.ui.StudyNewProjectPanel; -import com.jetbrains.python.newProject.PythonProjectGenerator; -import icons.StudyIcons; -import org.jetbrains.annotations.Nls; +import com.intellij.util.containers.ContainerUtil; +import com.jetbrains.edu.learning.course.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.*; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; - -public class StudyDirectoryProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator { - private static final Logger LOG = Logger.getInstance(StudyDirectoryProjectGenerator.class.getName()); +public class StudyProjectGenerator { + private static final Logger LOG = Logger.getInstance(StudyProjectGenerator.class.getName()); + private final List myListeners = ContainerUtil.newArrayList(); private static final String REPO_URL = "https://github.com/JetBrains/pycharm-courses/archive/master.zip"; private static final String USER_NAME = "PyCharm"; private static final String COURSE_META_FILE = "course.json"; @@ -59,15 +52,6 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple private Map myCourses = new HashMap(); private File mySelectedCourseFile; private Project myProject; - public ValidationResult myValidationResult = new ValidationResult("selected course is not valid"); - - @Nls - @NotNull - @Override - public String getName() { - return "Educational"; - } - public void setCourses(Map courses) { myCourses = courses; @@ -140,22 +124,7 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple return null; } - @Nullable - @Override - public Object showGenerationSettings(VirtualFile baseDir) throws ProcessCanceledException { - return null; - } - - @Nullable - @Override - public Icon getLogo() { - return StudyIcons.EducationalProjectType; - } - - - @Override - public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, - @Nullable Object settings, @NotNull Module module) { + public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir) { myProject = project; Reader reader = null; @@ -336,42 +305,6 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple return courseInfo; } - @NotNull - @Override - public ValidationResult validate(@NotNull String s) { - return myValidationResult; - } - - public void setValidationResult(ValidationResult validationResult) { - myValidationResult = validationResult; - } - - /** - * @return courses from memory or from cash file or parses course directory - */ - public Map getCourses() { - if (!myCourses.isEmpty()) { - return myCourses; - } - if (myCoursesDir.exists()) { - File cacheFile = new File(myCoursesDir, CACHE_NAME); - if (cacheFile.exists()) { - myCourses = getCoursesFromCache(cacheFile); - if (!myCourses.isEmpty()) { - return myCourses; - } - } - myCourses = loadCourses(); - if (!myCourses.isEmpty()) { - return myCourses; - } - } - downloadAndUnzip(false); - myCourses = loadCourses(); - flushCache(); - return myCourses; - } - /** * Writes courses to cash file {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#CACHE_NAME} */ @@ -417,7 +350,7 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple Map coursesFromCash = new HashMap(); BufferedReader reader = null; try { - reader = new BufferedReader(new InputStreamReader(new FileInputStream(cashFile))); + reader = new BufferedReader(new InputStreamReader(new FileInputStream(cashFile))); String line; while ((line = reader.readLine()) != null) { @@ -446,18 +379,43 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple return coursesFromCash; } - @Nullable - @Override - public JPanel extendBasePanel() throws ProcessCanceledException { - StudyNewProjectPanel settingsPanel = new StudyNewProjectPanel(this); - settingsPanel.registerValidators(new FacetValidatorsManager() { - public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) { - throw new UnsupportedOperationException(); + /** + * @return courses from memory or from cash file or parses course directory + */ + public Map getCourses() { + if (!myCourses.isEmpty()) { + return myCourses; + } + if (myCoursesDir.exists()) { + File cacheFile = new File(myCoursesDir, CACHE_NAME); + if (cacheFile.exists()) { + myCourses = getCoursesFromCache(cacheFile); + if (!myCourses.isEmpty()) { + return myCourses; + } } - public void validate() { - fireStateChanged(); + myCourses = loadCourses(); + if (!myCourses.isEmpty()) { + return myCourses; } - }); - return settingsPanel.getContentPanel(); + } + downloadAndUnzip(false); + myCourses = loadCourses(); + flushCache(); + return myCourses; + } + + public void addSettingsStateListener(@NotNull SettingsListener listener) { + myListeners.add(listener); + } + + public interface SettingsListener { + void stateChanged(ValidationResult result); + } + + public void fireStateChanged(ValidationResult result) { + for (SettingsListener listener : myListeners) { + listener.stateChanged(result); + } } } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyState.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyState.java similarity index 88% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyState.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyState.java index 96dc3d906472..4c382e0cc622 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyState.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyState.java @@ -1,11 +1,11 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; 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; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.editor.StudyEditor; public class StudyState { private final StudyEditor myStudyEditor; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java similarity index 95% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java index d44c251d5bb4..16996c0fb331 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.ide.BrowserUtil; import com.intellij.ide.ui.UISettings; @@ -32,13 +32,13 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.wm.*; import com.intellij.util.ui.update.UiNotifyConnector; import com.intellij.util.xmlb.XmlSerializer; -import com.jetbrains.python.edu.actions.*; -import com.jetbrains.python.edu.course.Course; -import com.jetbrains.python.edu.course.Lesson; -import com.jetbrains.python.edu.course.Task; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.ui.StudyCondition; -import com.jetbrains.python.edu.ui.StudyToolWindowFactory; +import com.jetbrains.edu.learning.actions.*; +import com.jetbrains.edu.learning.course.Course; +import com.jetbrains.edu.learning.course.Lesson; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.ui.StudyCondition; +import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -201,10 +201,7 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon @Override public void run() { if (PropertiesComponent.getInstance().getBoolean("StudyShowPopup", true)) { - String content = "If you'd like to learn" + - " more about PyCharm " + - "Educational Edition, " + - "click here to watch a tutorial"; + String content = StudyUtils.getLinkToTutorial(); final Notification notification = new Notification("Watch Tutorials!", "", content, NotificationType.INFORMATION, new UrlOpeningListener(true)); Notifications.Bus.notify(notification); diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTestRunner.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTestRunner.java new file mode 100644 index 000000000000..366a8df7faf4 --- /dev/null +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTestRunner.java @@ -0,0 +1,38 @@ +package com.jetbrains.edu.learning; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.ProcessOutput; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.course.Task; +import org.jetbrains.annotations.NotNull; + +public abstract class StudyTestRunner { + public static final String STUDY_PREFIX="#educational_plugin"; + public static final String TEST_OK = "test OK"; + private static final String TEST_FAILED = "FAILED + "; + protected final Task myTask; + protected final VirtualFile myTaskDir; + + public StudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) { + myTask = task; + myTaskDir = taskDir; + } + + public abstract Process createCheckProcess(Project project, String executablePath) throws ExecutionException; + + @NotNull + public String getTestsOutput(@NotNull final ProcessOutput processOutput) { + for (String line : processOutput.getStdoutLines()) { + if (line.contains(STUDY_PREFIX)) { + if (line.contains(TEST_OK)) { + continue; + } + int messageStart = line.indexOf(TEST_FAILED); + return line.substring(messageStart + TEST_FAILED.length()); + } + } + + return TEST_OK; + } +} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtils.java similarity index 76% rename from python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtils.java index 324e58aa4b4c..9262ac6c7041 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtils.java @@ -1,5 +1,8 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; +import com.intellij.execution.RunContentExecutor; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.ProcessHandler; import com.intellij.ide.SaveAndSyncHandlerImpl; import com.intellij.ide.projectView.actions.MarkRootActionBase; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -11,7 +14,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; @@ -24,10 +26,9 @@ 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.*; -import com.jetbrains.python.edu.editor.StudyEditor; -import com.jetbrains.python.edu.ui.StudyToolWindowFactory; -import com.jetbrains.python.sdk.PythonSdkType; +import com.jetbrains.edu.learning.course.*; +import com.jetbrains.edu.learning.editor.StudyEditor; +import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +36,9 @@ import java.io.*; import java.util.Collection; public class StudyUtils { + private StudyUtils() { + } + private static final Logger LOG = Logger.getInstance(StudyUtils.class.getName()); public static void closeSilently(Closeable stream) { @@ -199,8 +203,13 @@ public class StudyUtils { } @Nullable - public static Sdk findPythonSdk(@NotNull final Project project) { - return PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]); + public static Sdk findSdk(@NotNull final Project project) { + final StudyUtilsExtensionPoint[] extensions = + ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME); + if (extensions.length > 0) { + return extensions[0].findSdk(project); + } + return null; } public static void markDirAsSourceRoot(@NotNull final VirtualFile dir, @NotNull final Project project) { @@ -224,4 +233,43 @@ public class StudyUtils { } }); } + + public static StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) { + final StudyUtilsExtensionPoint[] extensions = + ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME); + if (extensions.length > 0) { + return extensions[0].getTestRunner(task, taskDir); + } + return null; + } + + public static String getLinkToTutorial() { + final StudyUtilsExtensionPoint[] extensions = + ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME); + if (extensions.length > 0) { + return extensions[0].getLinkToTutorial(); + } + return null; + } + + public static RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler) { + final StudyUtilsExtensionPoint[] extensions = + ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME); + if (extensions.length > 0) { + return extensions[0].getExecutor(project, handler); + } + return null; + } + + public static void setCommandLineParameters(@NotNull final GeneralCommandLine cmd, + @NotNull final Project project, + @NotNull final String filePath, + @NotNull final String pythonPath, + @NotNull final Task currentTask) { + final StudyUtilsExtensionPoint[] extensions = + ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME); + if (extensions.length > 0) { + extensions[0].setCommandLineParameters(cmd, project, filePath, pythonPath, currentTask); + } + } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtilsExtensionPoint.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtilsExtensionPoint.java new file mode 100644 index 000000000000..2342e5d28e15 --- /dev/null +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyUtilsExtensionPoint.java @@ -0,0 +1,46 @@ +/* + * 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.learning; + +import com.intellij.execution.RunContentExecutor; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.course.Task; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface StudyUtilsExtensionPoint { + ExtensionPointName EP_NAME = ExtensionPointName.create("Edu.StudyUtils"); + + @Nullable + abstract Sdk findSdk(@NotNull final Project project); + + abstract String getLinkToTutorial(); + + abstract StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir); + + public RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler); + + public void setCommandLineParameters(@NotNull final GeneralCommandLine cmd, + @NotNull final Project project, + @NotNull final String filePath, + @NotNull final String pythonPath, + @NotNull final Task currentTask); +} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/TaskWindowDeleteHandler.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/TaskWindowDeleteHandler.java similarity index 95% rename from python/edu/learn-python/src/com/jetbrains/python/edu/TaskWindowDeleteHandler.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/TaskWindowDeleteHandler.java index 334d78f550fb..3e3896d26c0c 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/TaskWindowDeleteHandler.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/TaskWindowDeleteHandler.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu; +package com.jetbrains.edu.learning; import com.intellij.codeInsight.hint.HintManager; import com.intellij.openapi.editor.Editor; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java similarity index 96% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java index 1b161278357b..4afe508dbc5a 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.CapturingProcessHandler; @@ -33,15 +33,15 @@ import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.StatusBarEx; import com.intellij.openapi.wm.ex.WindowManagerEx; -import com.jetbrains.python.edu.StudyDocumentListener; -import com.jetbrains.python.edu.StudyState; -import com.jetbrains.python.edu.StudyTestRunner; -import com.jetbrains.python.edu.StudyUtils; -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.edu.learning.StudyDocumentListener; +import com.jetbrains.edu.learning.StudyState; +import com.jetbrains.edu.learning.StudyTestRunner; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.StudyStatus; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.course.TaskWindow; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -133,7 +133,7 @@ public class StudyCheckAction extends DumbAwareAction { final Task task = studyState.getTask(); final VirtualFile taskDir = studyState.getTaskDir(); flushWindows(task, taskDir); - Sdk sdk = StudyUtils.findPythonSdk(project); + final Sdk sdk = StudyUtils.findSdk(project); if (sdk == null) { createNoPythonInterpreterPopUp(project); return; @@ -149,7 +149,8 @@ public class StudyCheckAction extends DumbAwareAction { IdeFocusManager.getInstance(project).requestFocus(studyState.getEditor().getComponent(), true); } }); - final StudyTestRunner testRunner = new StudyTestRunner(task, taskDir); + + final StudyTestRunner testRunner = StudyUtils.getTestRunner(task, taskDir); Process testProcess = null; try { final VirtualFile executablePath = getTaskVirtualFile(studyState, task, taskDir); diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java similarity index 94% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java index 50dcc3a2e69a..b026e18388cd 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.icons.AllIcons; import com.intellij.ide.ui.UISettings; @@ -20,13 +20,13 @@ import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.TabsListener; import com.intellij.ui.tabs.impl.JBEditorTabs; import com.intellij.util.PlatformIcons; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.Task; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.course.UserTest; -import com.jetbrains.python.edu.editor.StudyEditor; -import com.jetbrains.python.edu.ui.StudyTestContentPanel; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.course.UserTest; +import com.jetbrains.edu.learning.editor.StudyEditor; +import com.jetbrains.edu.learning.ui.StudyTestContentPanel; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -154,7 +154,7 @@ public class StudyEditInputAction extends DumbAwareAction { showInput(e.getProject()); } - private class HintClosedListener extends JBPopupAdapter { + private static class HintClosedListener extends JBPopupAdapter { private final Task myTask; private HintClosedListener(@NotNull final Task task) { myTask = task; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java similarity index 81% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java index 27edf22529cd..831208fcf5fa 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java @@ -1,7 +1,7 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; -import com.jetbrains.python.edu.editor.StudyEditor; -import com.jetbrains.python.edu.course.Task; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import javax.swing.*; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java similarity index 87% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java index e4d3bb79d7a3..6dbcc19cef15 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java @@ -1,8 +1,8 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.icons.AllIcons; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.TaskWindow; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.TaskWindow; import org.jetbrains.annotations.NotNull; import java.util.List; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPrevWindowAction.java similarity index 75% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPrevWindowAction.java index 01f6e1688b02..267944a33dc6 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPrevWindowAction.java @@ -1,8 +1,8 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.TaskWindow; -import icons.StudyIcons; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.TaskWindow; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,7 +17,7 @@ public class StudyPrevWindowAction extends StudyWindowNavigationAction { public static final String SHORTCUT = "ctrl shift pressed COMMA"; public StudyPrevWindowAction() { - super("Navigate to the Previous Answer Placeholder", "Navigate to the previous answer placeholder", StudyIcons.Prev); + super("Navigate to the Previous Answer Placeholder", "Navigate to the previous answer placeholder", InteractiveLearningIcons.Prev); } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java similarity index 81% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java index 02cc36355834..1c3dc5a95cb6 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java @@ -1,8 +1,8 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; -import com.jetbrains.python.edu.editor.StudyEditor; -import com.jetbrains.python.edu.course.Task; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import javax.swing.*; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskFileAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java similarity index 95% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskFileAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java index 9ec54b10569e..3458d252a15b 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskFileAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -18,11 +18,11 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; 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.StudyUtils; -import com.jetbrains.python.edu.course.*; -import com.jetbrains.python.edu.editor.StudyEditor; +import com.jetbrains.edu.learning.StudyDocumentListener; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.*; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import java.io.File; diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java new file mode 100644 index 000000000000..2cd453b0b870 --- /dev/null +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java @@ -0,0 +1,82 @@ +package com.jetbrains.edu.learning.actions; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.RunContentExecutor; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.OSProcessHandler; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.editor.StudyEditor; +import org.jetbrains.annotations.NotNull; + +public class StudyRunAction extends DumbAwareAction { + private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName()); + public static final String ACTION_ID = "StudyRunAction"; + private ProcessHandler myHandler; + + public void run(@NotNull final Project project, @NotNull final Sdk sdk) { + if (myHandler != null && !myHandler.isProcessTerminated()) return; + Editor selectedEditor = StudyEditor.getSelectedEditor(project); + FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); + assert selectedEditor != null; + VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument()); + + if (openedFile != null && openedFile.getCanonicalPath() != null) { + String filePath = openedFile.getCanonicalPath(); + executeFile(project, sdk, openedFile, filePath); + } + } + + private void executeFile(@NotNull final Project project, @NotNull final Sdk sdk, + @NotNull final VirtualFile openedFile, @NotNull final String filePath) { + StudyTaskManager taskManager = StudyTaskManager.getInstance(project); + GeneralCommandLine cmd = new GeneralCommandLine(); + cmd.withWorkDirectory(openedFile.getParent().getCanonicalPath()); + String sdkHomePath = sdk.getHomePath(); + if (sdkHomePath != null) { + cmd.setExePath(sdkHomePath); + TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile); + assert selectedTaskFile != null; + Task currentTask = selectedTaskFile.getTask(); + Process process; + StudyUtils.setCommandLineParameters(cmd, project, filePath, sdkHomePath, currentTask); + + try { + process = cmd.createProcess(); + } + catch (ExecutionException e) { + LOG.error(e); + return; + } + myHandler = new OSProcessHandler(process); + RunContentExecutor executor = StudyUtils.getExecutor(project, myHandler); + Disposer.register(project, executor); + executor.run(); + + } + } + + public void actionPerformed(@NotNull AnActionEvent e) { + Project project = e.getProject(); + if (project == null) { + return; + } + Sdk sdk = StudyUtils.findSdk(project); + if (sdk == null) { + return; + } + run(project, sdk); + } +} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java similarity index 89% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java index a5d37cbd2c2e..94e3cc4bd5ef 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.codeInsight.documentation.DocumentationComponent; import com.intellij.codeInsight.documentation.DocumentationManager; @@ -13,13 +13,13 @@ import com.intellij.openapi.util.Disposer; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.jetbrains.python.edu.StudyState; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.Course; -import com.jetbrains.python.edu.course.TaskWindow; -import com.jetbrains.python.edu.editor.StudyEditor; -import icons.StudyIcons; +import com.jetbrains.edu.learning.StudyState; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.Course; +import com.jetbrains.edu.learning.course.TaskWindow; +import com.jetbrains.edu.learning.editor.StudyEditor; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,7 +32,7 @@ public class StudyShowHintAction extends DumbAwareAction { public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder"; public StudyShowHintAction() { - super("Show hint", "Show hint", StudyIcons.ShowHint); + super("Show hint", "Show hint", InteractiveLearningIcons.ShowHint); } public void actionPerformed(@NotNull AnActionEvent e) { diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java similarity index 92% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java index b98bbd098776..721ff2f10ccb 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -14,11 +14,11 @@ import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.ui.tree.TreeUtil; -import com.jetbrains.python.edu.StudyState; -import com.jetbrains.python.edu.course.Lesson; -import com.jetbrains.python.edu.course.Task; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.editor.StudyEditor; +import com.jetbrains.edu.learning.StudyState; +import com.jetbrains.edu.learning.course.Lesson; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import javax.swing.*; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java similarity index 87% rename from python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java index e401fcee021f..cc5fea2dc9ec 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.actions; +package com.jetbrains.edu.learning.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.editor.Editor; @@ -6,11 +6,11 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.TaskFile; -import com.jetbrains.python.edu.course.TaskWindow; -import com.jetbrains.python.edu.editor.StudyEditor; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.TaskFile; +import com.jetbrains.edu.learning.course.TaskWindow; +import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Course.java similarity index 98% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Course.java index d461a4807151..94196dd45e26 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Course.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/CourseInfo.java similarity index 96% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/CourseInfo.java index 9f820c12c572..6cf9b18ea6d2 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/CourseInfo.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; /** * Implementation of class which contains information to be shawn in course description in tool window diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Lesson.java similarity index 97% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Lesson.java index b4a3286dfd94..34be407bf5ef 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Lesson.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; @@ -58,7 +58,7 @@ public class Lesson implements Stateful { * * @param courseDir project directory of course * @param resourceRoot directory where original lesson stored - * @throws java.io.IOException + * @throws IOException */ public void create(@NotNull final VirtualFile courseDir, @NotNull final File resourceRoot, @NotNull final Project project) throws IOException { diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/LessonInfo.java similarity index 96% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/LessonInfo.java index 85e2eb8be1a9..2de9bad0af6f 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/LessonInfo.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; /** * Implementation of class which contains information about student progress in current lesson diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Stateful.java similarity index 73% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Stateful.java index 3a163622f56d..4ba655e5066e 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Stateful.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; public interface Stateful { StudyStatus getStatus(); diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/StudyStatus.java similarity index 70% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/StudyStatus.java index d95b42b73866..cedcfd0fb01e 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/StudyStatus.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; /** * @see {@link TaskWindow#myStatus} diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Task.java similarity index 98% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Task.java index 0a106ff597ad..abdda07da02f 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/Task.java @@ -1,10 +1,10 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.xmlb.annotations.Transient; -import com.jetbrains.python.edu.StudyUtils; +import com.jetbrains.edu.learning.StudyUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -83,7 +83,7 @@ public class Task implements Stateful { * * @param lessonDir project directory of lesson which task belongs to * @param resourceRoot directory where original task file stored - * @throws java.io.IOException + * @throws IOException */ public void create(@NotNull final VirtualFile lessonDir, @NotNull final File resourceRoot, @NotNull final Project project) throws IOException { diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/TaskFile.java similarity index 97% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/TaskFile.java index b8908b606311..1f5f7ebbbb52 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/TaskFile.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -13,8 +13,8 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.xmlb.annotations.Transient; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.TaskWindowDeleteHandler; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.TaskWindowDeleteHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,7 +85,7 @@ public class TaskFile implements Stateful { * * @param taskDir project directory of task which task file belongs to * @param resourceRoot directory where original task file stored - * @throws java.io.IOException + * @throws IOException */ public void create(@NotNull final VirtualFile taskDir, @NotNull final File resourceRoot, @NotNull final String name) throws IOException { diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/TaskWindow.java similarity index 97% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/TaskWindow.java index 2229309092e7..2cd4c4ce7759 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/TaskWindow.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.CapturingProcessHandler; @@ -18,9 +18,9 @@ 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 com.jetbrains.edu.learning.StudyDocumentListener; +import com.jetbrains.edu.learning.StudyTestRunner; +import com.jetbrains.edu.learning.StudyUtils; import org.jetbrains.annotations.NotNull; import java.io.File; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/UserTest.java similarity index 94% rename from python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/UserTest.java index 8133e9102a14..fdaffc582fff 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/course/UserTest.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.course; +package com.jetbrains.edu.learning.course; public class UserTest { private String input; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java similarity index 95% rename from python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java index 14f932ede2f0..a5c7edb9291a 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.editor; +package com.jetbrains.edu.learning.editor; import com.intellij.codeHighlighting.BackgroundEditorHighlighter; import com.intellij.icons.AllIcons; @@ -34,13 +34,13 @@ import com.intellij.ui.HideableTitledPanel; import com.intellij.ui.JBColor; import com.intellij.util.ui.EmptyClipboardOwner; import com.intellij.util.ui.UIUtil; -import com.jetbrains.python.edu.StudyDocumentListener; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.actions.*; -import com.jetbrains.python.edu.course.Task; -import com.jetbrains.python.edu.course.TaskFile; -import icons.StudyIcons; +import com.jetbrains.edu.learning.StudyDocumentListener; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.actions.*; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -205,13 +205,13 @@ public class StudyEditor implements TextEditor { } private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) { - myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, StudyIcons.Resolve, StudyCheckAction.SHORTCUT); - myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, StudyIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT); + myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, InteractiveLearningIcons.Resolve, StudyCheckAction.SHORTCUT); + myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, InteractiveLearningIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT); myNextTaskButton = addButton(taskActionsPanel, StudyNextStudyTaskAction.ACTION_ID, AllIcons.Actions.Forward, StudyNextStudyTaskAction.SHORTCUT); myRefreshButton = addButton(taskActionsPanel, StudyRefreshTaskFileAction.ACTION_ID, AllIcons.Actions.Refresh, StudyRefreshTaskFileAction.SHORTCUT); - JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, StudyIcons.ShowHint, StudyShowHintAction.SHORTCUT); + JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, InteractiveLearningIcons.ShowHint, StudyShowHintAction.SHORTCUT); if (!taskFile.getTask().getUserTests().isEmpty()) { - final Sdk sdk = StudyUtils.findPythonSdk(myProject); + final Sdk sdk = StudyUtils.findSdk(myProject); if (sdk != null) { JButton runButton = addButton(taskActionsPanel, StudyRunAction.ACTION_ID, AllIcons.General.Run, null); runButton.addActionListener(new ActionListener() { @@ -221,7 +221,7 @@ public class StudyEditor implements TextEditor { studyRunAction.run(myProject, sdk); } }); - JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", StudyIcons.WatchInput, null); + JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", InteractiveLearningIcons.WatchInput, null); watchInputButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyFileEditorProvider.java similarity index 93% rename from python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyFileEditorProvider.java index 631b5a9eaf4c..ae8df1652681 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyFileEditorProvider.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.editor; +package com.jetbrains.edu.learning.editor; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorPolicy; @@ -8,10 +8,10 @@ import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.course.TaskFile; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.course.TaskFile; /** * User: lia diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java similarity index 89% rename from python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java index 4bd8df9baee7..a76e98ca50de 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.projectView; +package com.jetbrains.edu.learning.projectView; import com.intellij.ide.projectView.PresentationData; import com.intellij.ide.projectView.ProjectView; @@ -11,10 +11,10 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.ui.JBColor; import com.intellij.ui.SimpleTextAttributes; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.*; -import icons.StudyIcons; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.*; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -35,7 +35,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode { @Override protected void updateImpl(PresentationData data) { - data.setIcon(StudyIcons.Task); + data.setIcon(InteractiveLearningIcons.Task); String valueName = myValue.getName(); StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(myProject); Course course = studyTaskManager.getCourse(); @@ -72,7 +72,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode { if (myValue.getParent() != null) { if (!myValue.getParent().getName().contains(Course.SANDBOX_DIR)) { data.setPresentableText(Course.SANDBOX_DIR); - data.setIcon(StudyIcons.Sandbox); + data.setIcon(InteractiveLearningIcons.Sandbox); return; } } @@ -94,16 +94,16 @@ public class StudyDirectoryNode extends PsiDirectoryNode { StudyStatus taskStatus = stateful.getStatus(); switch (taskStatus) { case Unchecked: { - updatePresentation(data, additionalName, JBColor.BLACK, stateful instanceof Lesson ? StudyIcons.Lesson : StudyIcons.Task); + updatePresentation(data, additionalName, JBColor.BLACK, stateful instanceof Lesson ? InteractiveLearningIcons.Lesson : InteractiveLearningIcons.Task); break; } case Solved: { updatePresentation(data, additionalName, new JBColor(new Color(0, 134, 0), new Color(98, 150, 85)), - stateful instanceof Lesson ? StudyIcons.LessonCompl : StudyIcons.TaskCompl); + stateful instanceof Lesson ? InteractiveLearningIcons.LessonCompl : InteractiveLearningIcons.TaskCompl); break; } case Failed: { - updatePresentation(data, additionalName, JBColor.RED, stateful instanceof Lesson ? StudyIcons.Lesson : StudyIcons.TaskProbl); + updatePresentation(data, additionalName, JBColor.RED, stateful instanceof Lesson ? InteractiveLearningIcons.Lesson : InteractiveLearningIcons.TaskProbl); } } } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/projectView/StudyTreeStructureProvider.java similarity index 91% rename from python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/projectView/StudyTreeStructureProvider.java index 29b328a5da45..375a350f8bbb 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/projectView/StudyTreeStructureProvider.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.projectView; +package com.jetbrains.edu.learning.projectView; import com.intellij.ide.projectView.TreeStructureProvider; import com.intellij.ide.projectView.ViewSettings; @@ -8,10 +8,10 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.course.Course; -import com.jetbrains.python.edu.course.Task; -import com.jetbrains.python.edu.course.TaskFile; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.course.Course; +import com.jetbrains.edu.learning.course.Task; +import com.jetbrains.edu.learning.course.TaskFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java similarity index 86% rename from python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java index 5add6c934ecd..9d82fa4813a3 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java @@ -1,9 +1,9 @@ -package com.jetbrains.python.edu.ui; +package com.jetbrains.edu.learning.ui; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; -import com.jetbrains.python.edu.StudyTaskManager; +import com.jetbrains.edu.learning.StudyTaskManager; /** * author: liana diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.form similarity index 98% rename from python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.form index 8dd6506d710c..e6d745da6a7b 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.form @@ -1,5 +1,5 @@ - + diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java similarity index 93% rename from python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java index 6edad63586f0..b7064784e0bf 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.ui; +package com.jetbrains.edu.learning.ui; import com.intellij.facet.ui.FacetValidatorsManager; import com.intellij.facet.ui.ValidationResult; @@ -7,9 +7,9 @@ import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; -import com.jetbrains.python.edu.StudyDirectoryProjectGenerator; -import com.jetbrains.python.edu.StudyUtils; -import com.jetbrains.python.edu.course.CourseInfo; +import com.jetbrains.edu.learning.StudyProjectGenerator; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.course.CourseInfo; import javax.swing.*; import java.awt.event.ActionEvent; @@ -33,12 +33,12 @@ public class StudyNewProjectPanel{ private JLabel myAuthorLabel; private JLabel myDescriptionLabel; private JLabel myLabel; - private final StudyDirectoryProjectGenerator myGenerator; + private final StudyProjectGenerator myGenerator; private static final String CONNECTION_ERROR = "Failed to download courses.
Check your Internet connection."; private static final String INVALID_COURSE = "Selected course is invalid"; private FacetValidatorsManager myValidationManager; - public StudyNewProjectPanel(StudyDirectoryProjectGenerator generator) { + public StudyNewProjectPanel(StudyProjectGenerator generator) { myGenerator = generator; Map courses = myGenerator.getCourses(); if (courses.isEmpty()) { @@ -110,14 +110,14 @@ public class StudyNewProjectPanel{ } private void setError(String errorMessage) { - myGenerator.setValidationResult(new ValidationResult(errorMessage)); + myGenerator.fireStateChanged(new ValidationResult(errorMessage)); if (myValidationManager != null) { myValidationManager.validate(); } } private void setOK() { - myGenerator.setValidationResult(ValidationResult.OK); + myGenerator.fireStateChanged(ValidationResult.OK); if (myValidationManager != null) { myValidationManager.validate(); } @@ -196,4 +196,5 @@ public class StudyNewProjectPanel{ setOK(); } } + } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java similarity index 98% rename from python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java index a25c98b99e35..e7ae06b6e363 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.ui; +package com.jetbrains.edu.learning.ui; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.ui.GraphicsConfig; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyTestContentPanel.java similarity index 96% rename from python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyTestContentPanel.java index dee4fbaf9d01..6863ad597992 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyTestContentPanel.java @@ -1,9 +1,9 @@ -package com.jetbrains.python.edu.ui; +package com.jetbrains.edu.learning.ui; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.components.JBScrollPane; +import com.jetbrains.edu.learning.course.UserTest; import org.jetbrains.annotations.NotNull; -import com.jetbrains.python.edu.course.UserTest; import javax.swing.*; import javax.swing.event.DocumentEvent; diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java similarity index 91% rename from python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java rename to python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java index 1c312af6e5d9..73930ab662dd 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java @@ -1,4 +1,4 @@ -package com.jetbrains.python.edu.ui; +package com.jetbrains.edu.learning.ui; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; @@ -8,11 +8,11 @@ import com.intellij.ui.JBColor; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.intellij.util.ui.UIUtil; -import com.jetbrains.python.edu.StudyTaskManager; -import com.jetbrains.python.edu.course.Course; -import com.jetbrains.python.edu.course.Lesson; -import com.jetbrains.python.edu.course.LessonInfo; -import com.jetbrains.python.edu.course.StudyStatus; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.course.Course; +import com.jetbrains.edu.learning.course.Lesson; +import com.jetbrains.edu.learning.course.LessonInfo; +import com.jetbrains.edu.learning.course.StudyStatus; import org.jetbrains.annotations.NotNull; import javax.swing.*; From d04892da9a98fb079364f2200ea5f4567c1e5591 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 14 Jan 2015 17:24:30 +0300 Subject: [PATCH 32/55] refactoring pycharm educational third iteration moved interactive-learning-python and course-creator-python modules to the proper place added missing icons to the interactive-learning --- .../course-creator-python.iml | 0 .../resources/META-INF/plugin.xml | 0 .../fileTemplates/internal/task.answer.ft | 0 .../fileTemplates/internal/task.html.ft | 0 .../fileTemplates/internal/test_helper.py.ft | 0 .../fileTemplates/internal/tests.py.ft | 0 .../icons/CourseCreationProjectType.png | Bin .../icons/CourseCreationProjectType@2x.png | Bin .../CourseCreationProjectType@2x_dark.png | Bin .../icons/CourseCreationProjectType_dark.png | Bin .../PyCCAnswerFileTypeFactory.java | 0 .../coursecreator/PyCCProjectGenerator.java | 0 .../actions/PyCCRunTestsAction.java | 0 .../src/icons/CourseCreatorPythonIcons.java | 0 .../testData/helloworld.py | 0 .../testData/helloworld.xml | 0 .../tests/CCDocumentListenerTest.java | 0 .../tests/CCTestCase.java | 0 .../interactive-learning-python.iml | 0 .../resources/META-INF/plugin.xml | 0 .../com/jetbrains/python/edu/user_tester.py | 0 .../resources/courses/introduction_course.zip | Bin .../edu/learning/EducationalProjectType.png | Bin .../learning/EducationalProjectType@2x.png | Bin .../learning/EducationalProjectType_dark.png | Bin .../EducationalProjectType_dark@2x.png | Bin .../PyStudyDirectoryProjectGenerator.java | 0 .../edu/learning/PyStudyTestRunner.java | 0 .../jetbrains/edu/learning/PyStudyUtils.java | 0 .../PyStudyIntroductionCourseAction.java | 0 .../actions/PyStudyWatchTutorialAction.java | 0 .../highlighting/PyStudyVisitorFilter.java | 0 .../icons/InteractiveLearningPythonIcons.java | 0 .../testData/course.json | 0 .../testData/helloworld.py | 0 .../tests/JsonParserTest.java | 0 .../tests/StudyDocumentListenerTest.java | 0 .../tests/StudyTestCase.java | 0 .../educational-python/educational-python.iml | 11 -------- .../src/icons/InteractiveLearningIcons.java | 26 ++++++++++++++++++ 40 files changed, 26 insertions(+), 11 deletions(-) rename python/{educational-python => edu}/course-creator-python/course-creator-python.iml (100%) rename python/{educational-python => edu}/course-creator-python/resources/META-INF/plugin.xml (100%) rename python/{educational-python => edu}/course-creator-python/resources/fileTemplates/internal/task.answer.ft (100%) rename python/{educational-python => edu}/course-creator-python/resources/fileTemplates/internal/task.html.ft (100%) rename python/{educational-python => edu}/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft (100%) rename python/{educational-python => edu}/course-creator-python/resources/fileTemplates/internal/tests.py.ft (100%) rename python/{educational-python => edu}/course-creator-python/resources/icons/CourseCreationProjectType.png (100%) rename python/{educational-python => edu}/course-creator-python/resources/icons/CourseCreationProjectType@2x.png (100%) rename python/{educational-python => edu}/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png (100%) rename python/{educational-python => edu}/course-creator-python/resources/icons/CourseCreationProjectType_dark.png (100%) rename python/{educational-python => edu}/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java (100%) rename python/{educational-python => edu}/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java (100%) rename python/{educational-python => edu}/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java (100%) rename python/{educational-python => edu}/course-creator-python/src/icons/CourseCreatorPythonIcons.java (100%) rename python/{educational-python => edu}/course-creator-python/testData/helloworld.py (100%) rename python/{educational-python => edu}/course-creator-python/testData/helloworld.xml (100%) rename python/{educational-python => edu}/course-creator-python/tests/CCDocumentListenerTest.java (100%) rename python/{educational-python => edu}/course-creator-python/tests/CCTestCase.java (100%) rename python/{educational-python => edu}/interactive-learning-python/interactive-learning-python.iml (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/META-INF/plugin.xml (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/courses/introduction_course.zip (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png (100%) rename python/{educational-python => edu}/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png (100%) rename python/{educational-python => edu}/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java (100%) rename python/{educational-python => edu}/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java (100%) rename python/{educational-python => edu}/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java (100%) rename python/{educational-python => edu}/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java (100%) rename python/{educational-python => edu}/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java (100%) rename python/{educational-python => edu}/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java (100%) rename python/{educational-python => edu}/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java (100%) rename python/{educational-python => edu}/interactive-learning-python/testData/course.json (100%) rename python/{educational-python => edu}/interactive-learning-python/testData/helloworld.py (100%) rename python/{educational-python => edu}/interactive-learning-python/tests/JsonParserTest.java (100%) rename python/{educational-python => edu}/interactive-learning-python/tests/StudyDocumentListenerTest.java (100%) rename python/{educational-python => edu}/interactive-learning-python/tests/StudyTestCase.java (100%) delete mode 100644 python/educational-python/educational-python.iml create mode 100644 python/educational/interactive-learning/src/icons/InteractiveLearningIcons.java diff --git a/python/educational-python/course-creator-python/course-creator-python.iml b/python/edu/course-creator-python/course-creator-python.iml similarity index 100% rename from python/educational-python/course-creator-python/course-creator-python.iml rename to python/edu/course-creator-python/course-creator-python.iml diff --git a/python/educational-python/course-creator-python/resources/META-INF/plugin.xml b/python/edu/course-creator-python/resources/META-INF/plugin.xml similarity index 100% rename from python/educational-python/course-creator-python/resources/META-INF/plugin.xml rename to python/edu/course-creator-python/resources/META-INF/plugin.xml diff --git a/python/educational-python/course-creator-python/resources/fileTemplates/internal/task.answer.ft b/python/edu/course-creator-python/resources/fileTemplates/internal/task.answer.ft similarity index 100% rename from python/educational-python/course-creator-python/resources/fileTemplates/internal/task.answer.ft rename to python/edu/course-creator-python/resources/fileTemplates/internal/task.answer.ft diff --git a/python/educational-python/course-creator-python/resources/fileTemplates/internal/task.html.ft b/python/edu/course-creator-python/resources/fileTemplates/internal/task.html.ft similarity index 100% rename from python/educational-python/course-creator-python/resources/fileTemplates/internal/task.html.ft rename to python/edu/course-creator-python/resources/fileTemplates/internal/task.html.ft diff --git a/python/educational-python/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft b/python/edu/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft similarity index 100% rename from python/educational-python/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft rename to python/edu/course-creator-python/resources/fileTemplates/internal/test_helper.py.ft diff --git a/python/educational-python/course-creator-python/resources/fileTemplates/internal/tests.py.ft b/python/edu/course-creator-python/resources/fileTemplates/internal/tests.py.ft similarity index 100% rename from python/educational-python/course-creator-python/resources/fileTemplates/internal/tests.py.ft rename to python/edu/course-creator-python/resources/fileTemplates/internal/tests.py.ft diff --git a/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType.png b/python/edu/course-creator-python/resources/icons/CourseCreationProjectType.png similarity index 100% rename from python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType.png rename to python/edu/course-creator-python/resources/icons/CourseCreationProjectType.png diff --git a/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x.png b/python/edu/course-creator-python/resources/icons/CourseCreationProjectType@2x.png similarity index 100% rename from python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x.png rename to python/edu/course-creator-python/resources/icons/CourseCreationProjectType@2x.png diff --git a/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png b/python/edu/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png similarity index 100% rename from python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png rename to python/edu/course-creator-python/resources/icons/CourseCreationProjectType@2x_dark.png diff --git a/python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType_dark.png b/python/edu/course-creator-python/resources/icons/CourseCreationProjectType_dark.png similarity index 100% rename from python/educational-python/course-creator-python/resources/icons/CourseCreationProjectType_dark.png rename to python/edu/course-creator-python/resources/icons/CourseCreationProjectType_dark.png diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java similarity index 100% rename from python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java rename to python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java similarity index 100% rename from python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java rename to python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java similarity index 100% rename from python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java rename to python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/actions/PyCCRunTestsAction.java diff --git a/python/educational-python/course-creator-python/src/icons/CourseCreatorPythonIcons.java b/python/edu/course-creator-python/src/icons/CourseCreatorPythonIcons.java similarity index 100% rename from python/educational-python/course-creator-python/src/icons/CourseCreatorPythonIcons.java rename to python/edu/course-creator-python/src/icons/CourseCreatorPythonIcons.java diff --git a/python/educational-python/course-creator-python/testData/helloworld.py b/python/edu/course-creator-python/testData/helloworld.py similarity index 100% rename from python/educational-python/course-creator-python/testData/helloworld.py rename to python/edu/course-creator-python/testData/helloworld.py diff --git a/python/educational-python/course-creator-python/testData/helloworld.xml b/python/edu/course-creator-python/testData/helloworld.xml similarity index 100% rename from python/educational-python/course-creator-python/testData/helloworld.xml rename to python/edu/course-creator-python/testData/helloworld.xml diff --git a/python/educational-python/course-creator-python/tests/CCDocumentListenerTest.java b/python/edu/course-creator-python/tests/CCDocumentListenerTest.java similarity index 100% rename from python/educational-python/course-creator-python/tests/CCDocumentListenerTest.java rename to python/edu/course-creator-python/tests/CCDocumentListenerTest.java diff --git a/python/educational-python/course-creator-python/tests/CCTestCase.java b/python/edu/course-creator-python/tests/CCTestCase.java similarity index 100% rename from python/educational-python/course-creator-python/tests/CCTestCase.java rename to python/edu/course-creator-python/tests/CCTestCase.java diff --git a/python/educational-python/interactive-learning-python/interactive-learning-python.iml b/python/edu/interactive-learning-python/interactive-learning-python.iml similarity index 100% rename from python/educational-python/interactive-learning-python/interactive-learning-python.iml rename to python/edu/interactive-learning-python/interactive-learning-python.iml diff --git a/python/educational-python/interactive-learning-python/resources/META-INF/plugin.xml b/python/edu/interactive-learning-python/resources/META-INF/plugin.xml similarity index 100% rename from python/educational-python/interactive-learning-python/resources/META-INF/plugin.xml rename to python/edu/interactive-learning-python/resources/META-INF/plugin.xml diff --git a/python/educational-python/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py b/python/edu/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py similarity index 100% rename from python/educational-python/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py rename to python/edu/interactive-learning-python/resources/com/jetbrains/python/edu/user_tester.py diff --git a/python/educational-python/interactive-learning-python/resources/courses/introduction_course.zip b/python/edu/interactive-learning-python/resources/courses/introduction_course.zip similarity index 100% rename from python/educational-python/interactive-learning-python/resources/courses/introduction_course.zip rename to python/edu/interactive-learning-python/resources/courses/introduction_course.zip diff --git a/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png b/python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png similarity index 100% rename from python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png rename to python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType.png diff --git a/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png b/python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png similarity index 100% rename from python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png rename to python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType@2x.png diff --git a/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png b/python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png similarity index 100% rename from python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png rename to python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark.png diff --git a/python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png b/python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png similarity index 100% rename from python/educational-python/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png rename to python/edu/interactive-learning-python/resources/icons/com/jetbrains/edu/learning/EducationalProjectType_dark@2x.png diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java rename to python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java rename to python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java rename to python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyUtils.java diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java rename to python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyIntroductionCourseAction.java diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java rename to python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/actions/PyStudyWatchTutorialAction.java diff --git a/python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java rename to python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/highlighting/PyStudyVisitorFilter.java diff --git a/python/educational-python/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java b/python/edu/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java similarity index 100% rename from python/educational-python/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java rename to python/edu/interactive-learning-python/src/icons/InteractiveLearningPythonIcons.java diff --git a/python/educational-python/interactive-learning-python/testData/course.json b/python/edu/interactive-learning-python/testData/course.json similarity index 100% rename from python/educational-python/interactive-learning-python/testData/course.json rename to python/edu/interactive-learning-python/testData/course.json diff --git a/python/educational-python/interactive-learning-python/testData/helloworld.py b/python/edu/interactive-learning-python/testData/helloworld.py similarity index 100% rename from python/educational-python/interactive-learning-python/testData/helloworld.py rename to python/edu/interactive-learning-python/testData/helloworld.py diff --git a/python/educational-python/interactive-learning-python/tests/JsonParserTest.java b/python/edu/interactive-learning-python/tests/JsonParserTest.java similarity index 100% rename from python/educational-python/interactive-learning-python/tests/JsonParserTest.java rename to python/edu/interactive-learning-python/tests/JsonParserTest.java diff --git a/python/educational-python/interactive-learning-python/tests/StudyDocumentListenerTest.java b/python/edu/interactive-learning-python/tests/StudyDocumentListenerTest.java similarity index 100% rename from python/educational-python/interactive-learning-python/tests/StudyDocumentListenerTest.java rename to python/edu/interactive-learning-python/tests/StudyDocumentListenerTest.java diff --git a/python/educational-python/interactive-learning-python/tests/StudyTestCase.java b/python/edu/interactive-learning-python/tests/StudyTestCase.java similarity index 100% rename from python/educational-python/interactive-learning-python/tests/StudyTestCase.java rename to python/edu/interactive-learning-python/tests/StudyTestCase.java diff --git a/python/educational-python/educational-python.iml b/python/educational-python/educational-python.iml deleted file mode 100644 index c90834f2d607..000000000000 --- a/python/educational-python/educational-python.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/python/educational/interactive-learning/src/icons/InteractiveLearningIcons.java b/python/educational/interactive-learning/src/icons/InteractiveLearningIcons.java new file mode 100644 index 000000000000..a6151a684e3c --- /dev/null +++ b/python/educational/interactive-learning/src/icons/InteractiveLearningIcons.java @@ -0,0 +1,26 @@ +package icons; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; + +/** + * NOTE THIS FILE IS AUTO-GENERATED + * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead + */ +public class InteractiveLearningIcons { + private static Icon load(String path) { + return IconLoader.getIcon(path, InteractiveLearningIcons.class); + } + + public static final Icon Lesson = load("/icons/com/jetbrains/edu/learning/Lesson.png"); // 16x16 + public static final Icon LessonCompl = load("/icons/com/jetbrains/edu/learning/LessonCompl.png"); // 16x16 + public static final Icon Prev = load("/icons/com/jetbrains/edu/learning/prev.png"); // 16x16 + public static final Icon Resolve = load("/icons/com/jetbrains/edu/learning/resolve.png"); // 16x16 + public static final Icon Sandbox = load("/icons/com/jetbrains/edu/learning/Sandbox.png"); // 16x16 + public static final Icon ShowHint = load("/icons/com/jetbrains/edu/learning/showHint.png"); // 16x16 + public static final Icon Task = load("/icons/com/jetbrains/edu/learning/Task.png"); // 16x16 + public static final Icon TaskCompl = load("/icons/com/jetbrains/edu/learning/TaskCompl.png"); // 16x16 + public static final Icon TaskProbl = load("/icons/com/jetbrains/edu/learning/TaskProbl.png"); // 16x16 + public static final Icon WatchInput = load("/icons/com/jetbrains/edu/learning/WatchInput.png"); // 24x24 +} From 5a24769ec5d6339e875028d0f86b9b3933b78d72 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 14 Jan 2015 17:43:19 +0300 Subject: [PATCH 33/55] do not normalize "at breakpoint" thread state --- .../src/com/intellij/unscramble/UnscrambleDialog.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java index 4c60a453eafa..1245f04103cd 100644 --- a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java +++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -314,6 +314,10 @@ public class UnscrambleDialog extends DialogWrapper { builder.append(trimSuffix(line)).append("\n"); continue; } + if (line.startsWith("at breakpoint")) { // possible thread status mixed with "at ..." + builder.append(" ").append(trimSuffix(line)); + continue; + } if (!first && mustHaveNewLineBefore(line)) { builder.append("\n"); if (line.startsWith("\"")) builder.append("\n"); // Additional line break for thread names From 82f9db055916819edc3df85cf27e9c1880c72d00 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 14 Jan 2015 15:42:44 +0100 Subject: [PATCH 34/55] refactor to extract renderer from GotoActionModel --- .../ide/util/gotoByName/GotoActionModel.java | 248 ++++++++++-------- 1 file changed, 133 insertions(+), 115 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 3a9001e005ac..84fb10920923 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -41,6 +41,7 @@ import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.OnOffButton; import com.intellij.ui.speedSearch.SpeedSearchUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.ui.EmptyIcon; @@ -144,7 +145,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @NotNull public final Comparable value; @NotNull final String pattern; - MatchedValue(@NotNull Comparable value, @NotNull String pattern) { + public MatchedValue(@NotNull Comparable value, @NotNull String pattern) { this.value = value; this.pattern = pattern; } @@ -208,121 +209,12 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override public ListCellRenderer getListCellRenderer() { - return new DefaultListCellRenderer() { + return new GotoActionListCellRenderer(new Function() { @Override - public Component getListCellRendererComponent(@NotNull final JList list, - final Object matchedValue, - final int index, final boolean isSelected, final boolean cellHasFocus) { - final JPanel panel = new JPanel(new BorderLayout()); - panel.setBorder(IdeBorderFactory.createEmptyBorder(2)); - panel.setOpaque(true); - Color bg = UIUtil.getListBackground(isSelected); - panel.setBackground(bg); - - if (matchedValue instanceof String) { //... - final JBLabel label = new JBLabel((String)matchedValue); - label.setIcon(EMPTY_ICON); - panel.add(label, BorderLayout.WEST); - return panel; - } - - Color groupFg = isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getLabelDisabledForeground(); - - final Object value = ((MatchedValue) matchedValue).value; - String pattern = ((MatchedValue)matchedValue).pattern; - - SimpleColoredComponent nameComponent = new SimpleColoredComponent(); - nameComponent.setBackground(bg); - panel.add(nameComponent, BorderLayout.CENTER); - - if (value instanceof ActionWrapper) { - final ActionWrapper actionWithParentGroup = (ActionWrapper)value; - final AnAction anAction = actionWithParentGroup.getAction(); - final Presentation presentation = anAction.getTemplatePresentation(); - boolean toggle = anAction instanceof ToggleAction; - String groupName = actionWithParentGroup.getAction() instanceof ApplyIntentionAction ? null : actionWithParentGroup.getGroupName(); - final Color fg = defaultActionForeground(isSelected, actionWithParentGroup.getPresentation()); - panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST); - appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected); - - final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(getActionId(anAction))); - if (shortcut != null) { - nameComponent.append(" (" + KeymapUtil.getShortcutText(shortcut) + ")", new SimpleTextAttributes(STYLE_PLAIN, groupFg)); - } - - if (toggle) { - final OnOffButton button = new OnOffButton(); - AnActionEvent event = new AnActionEvent(null, ((ActionWrapper)value).myDataContext, - ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(), - 0); - button.setSelected(((ToggleAction)anAction).isSelected(event)); - panel.add(button, BorderLayout.EAST); - panel.setBorder(IdeBorderFactory.createEmptyBorder()); - } - else { - if (groupName != null) { - final JLabel groupLabel = new JLabel(groupName); - groupLabel.setBackground(bg); - groupLabel.setForeground(groupFg); - panel.add(groupLabel, BorderLayout.EAST); - } - } - } - else if (value instanceof OptionDescription) { - if (!isSelected && !(value instanceof BooleanOptionDescription)) { - Color descriptorBg = UIUtil.isUnderDarcula() ? ColorUtil.brighter(UIUtil.getListBackground(), 1) : LightColors.SLIGHTLY_GRAY; - panel.setBackground(descriptorBg); - nameComponent.setBackground(descriptorBg); - } - String hit = ((OptionDescription)value).getHit(); - if (hit == null) { - hit = ((OptionDescription)value).getOption(); - } - hit = StringUtil.unescapeXml(hit); - hit = hit.replace(" ", " "); // avoid extra spaces from mnemonics and xml conversion - String fullHit = hit; - hit = StringUtil.first(hit, 45, true); - - final Color fg = UIUtil.getListForeground(isSelected); - - appendWithColoredMatches(nameComponent, hit.trim(), pattern, fg, isSelected); - - panel.add(new JLabel(EMPTY_ICON), BorderLayout.WEST); - panel.setToolTipText(fullHit); - - if (value instanceof BooleanOptionDescription) { - final OnOffButton button = new OnOffButton(); - button.setSelected(((BooleanOptionDescription)value).isOptionEnabled()); - panel.add(button, BorderLayout.EAST); - panel.setBorder(IdeBorderFactory.createEmptyBorder()); - } - else { - final JLabel settingsLabel = new JLabel(getGroupName((OptionDescription)value)); - settingsLabel.setForeground(groupFg); - settingsLabel.setBackground(bg); - panel.add(settingsLabel, BorderLayout.EAST); - } - } - return panel; + public String fun(OptionDescription description) { + return getGroupName(description); } - - public String getName(String text, String groupName, boolean toggle) { - return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text; - } - - private void appendWithColoredMatches(SimpleColoredComponent nameComponent, String name, String pattern, Color fg, boolean selected) { - final SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg); - final SimpleTextAttributes highlighted = new SimpleTextAttributes(null, fg, null, STYLE_SEARCH_MATCH); - List fragments = ContainerUtil.newArrayList(); - if (selected) { - int matchStart = StringUtil.indexOfIgnoreCase(name, pattern, 0); - if (matchStart >= 0) { - fragments.add(TextRange.from(matchStart, pattern.length())); - } - } - SpeedSearchUtil.appendColoredFragments(nameComponent, name, fragments, plain, highlighted); - } - }; + }); } protected String getActionId(@NotNull final AnAction anAction) { @@ -721,4 +613,130 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return myAction.getTemplatePresentation().getText().hashCode(); } } + + public static class GotoActionListCellRenderer extends DefaultListCellRenderer { + private final Function myGroupNamer; + + public GotoActionListCellRenderer(Function groupNamer) { + myGroupNamer = groupNamer; + } + + @Override + public Component getListCellRendererComponent(@NotNull final JList list, + final Object matchedValue, + final int index, final boolean isSelected, final boolean cellHasFocus) { + final JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(IdeBorderFactory.createEmptyBorder(2)); + panel.setOpaque(true); + Color bg = UIUtil.getListBackground(isSelected); + panel.setBackground(bg); + + if (matchedValue instanceof String) { //... + final JBLabel label = new JBLabel((String)matchedValue); + label.setIcon(EMPTY_ICON); + panel.add(label, BorderLayout.WEST); + return panel; + } + + Color groupFg = isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getLabelDisabledForeground(); + + final Object value = ((MatchedValue) matchedValue).value; + String pattern = ((MatchedValue)matchedValue).pattern; + + SimpleColoredComponent nameComponent = new SimpleColoredComponent(); + nameComponent.setBackground(bg); + panel.add(nameComponent, BorderLayout.CENTER); + + if (value instanceof ActionWrapper) { + final ActionWrapper actionWithParentGroup = (ActionWrapper)value; + final AnAction anAction = actionWithParentGroup.getAction(); + final Presentation presentation = anAction.getTemplatePresentation(); + boolean toggle = anAction instanceof ToggleAction; + String groupName = actionWithParentGroup.getAction() instanceof ApplyIntentionAction ? null : actionWithParentGroup.getGroupName(); + final Color fg = defaultActionForeground(isSelected, actionWithParentGroup.getPresentation()); + panel.add(createIconLabel(presentation.getIcon()), BorderLayout.WEST); + appendWithColoredMatches(nameComponent, getName(presentation.getText(), groupName, toggle), pattern, fg, isSelected); + + final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(ActionManager.getInstance().getId(anAction))); + if (shortcut != null) { + nameComponent.append(" (" + KeymapUtil.getShortcutText(shortcut) + ")", new SimpleTextAttributes(STYLE_PLAIN, groupFg)); + } + + if (toggle) { + final OnOffButton button = new OnOffButton(); + AnActionEvent event = new AnActionEvent(null, ((ActionWrapper)value).myDataContext, + ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(), + 0); + button.setSelected(((ToggleAction)anAction).isSelected(event)); + panel.add(button, BorderLayout.EAST); + panel.setBorder(IdeBorderFactory.createEmptyBorder()); + } + else { + if (groupName != null) { + final JLabel groupLabel = new JLabel(groupName); + groupLabel.setBackground(bg); + groupLabel.setForeground(groupFg); + panel.add(groupLabel, BorderLayout.EAST); + } + } + } + else if (value instanceof OptionDescription) { + if (!isSelected && !(value instanceof BooleanOptionDescription)) { + Color descriptorBg = UIUtil.isUnderDarcula() ? ColorUtil.brighter(UIUtil.getListBackground(), 1) : LightColors.SLIGHTLY_GRAY; + panel.setBackground(descriptorBg); + nameComponent.setBackground(descriptorBg); + } + String hit = ((OptionDescription)value).getHit(); + if (hit == null) { + hit = ((OptionDescription)value).getOption(); + } + hit = StringUtil.unescapeXml(hit); + hit = hit.replace(" ", " "); // avoid extra spaces from mnemonics and xml conversion + String fullHit = hit; + hit = StringUtil.first(hit, 45, true); + + final Color fg = UIUtil.getListForeground(isSelected); + + appendWithColoredMatches(nameComponent, hit.trim(), pattern, fg, isSelected); + + panel.add(new JLabel(EMPTY_ICON), BorderLayout.WEST); + panel.setToolTipText(fullHit); + + if (value instanceof BooleanOptionDescription) { + final OnOffButton button = new OnOffButton(); + button.setSelected(((BooleanOptionDescription)value).isOptionEnabled()); + panel.add(button, BorderLayout.EAST); + panel.setBorder(IdeBorderFactory.createEmptyBorder()); + } + else { + final JLabel settingsLabel = new JLabel(myGroupNamer.fun((OptionDescription)value)); + settingsLabel.setForeground(groupFg); + settingsLabel.setBackground(bg); + panel.add(settingsLabel, BorderLayout.EAST); + } + } + return panel; + } + + public String getName(String text, String groupName, boolean toggle) { + return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text; + } + + private static void appendWithColoredMatches(SimpleColoredComponent nameComponent, + String name, + String pattern, + Color fg, + boolean selected) { + final SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg); + final SimpleTextAttributes highlighted = new SimpleTextAttributes(null, fg, null, STYLE_SEARCH_MATCH); + List fragments = ContainerUtil.newArrayList(); + if (selected) { + int matchStart = StringUtil.indexOfIgnoreCase(name, pattern, 0); + if (matchStart >= 0) { + fragments.add(TextRange.from(matchStart, pattern.length())); + } + } + SpeedSearchUtil.appendColoredFragments(nameComponent, name, fragments, plain, highlighted); + } + } } From e3b6f8adb31b67c2bb58def0a4e4ae47860fc231 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 14 Jan 2015 15:43:37 +0100 Subject: [PATCH 35/55] renderer with shortcuts for actions and cache for action updates --- .../ide/actions/SearchEverywhereAction.java | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index ee1e5dcf2695..60dcc2ea2d06 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -158,6 +158,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA private JBList myList; private JCheckBox myNonProjectCheckBox; private AnActionEvent myActionEvent; + private Set myDisabledActions = new HashSet(); private Component myContextComponent; private CalcThread myCalcThread; private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false); @@ -1040,6 +1041,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } }; SearchEverywherePsiRenderer myFileRenderer = new SearchEverywherePsiRenderer(myList); + ListCellRenderer myActionsRenderer = new GotoActionModel.GotoActionListCellRenderer(Function.TO_STRING); private String myLocationString; private DefaultPsiElementCellRenderer myPsiRenderer = new DefaultPsiElementCellRenderer() { @@ -1080,6 +1082,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } else if (value instanceof PsiElement) { myFileRenderer.setPatternMatcher(matcher); cmp = myFileRenderer.getListCellRendererComponent(list, value, index, isSelected, isSelected); + } else if (value instanceof GotoActionModel.ActionWrapper) { + cmp = myActionsRenderer.getListCellRendererComponent(list, new GotoActionModel.MatchedValue(((GotoActionModel.ActionWrapper)value), pattern), index, isSelected, isSelected); } else { cmp = super.getListCellRendererComponent(list, value, index, isSelected, isSelected); final JPanel p = new JPanel(new BorderLayout()); @@ -1464,7 +1468,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA result.add(object); } } else if (actions && !isToolWindowAction(object) && isActionValue(object)) { - result.add(object); + AnAction action = object instanceof AnAction ? ((AnAction)object) : ((GotoActionModel.ActionWrapper)object).getAction(); + if (isEnabled(action)) { + result.add(object); + } } return result.size() <= max; } @@ -1905,19 +1912,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA public void run() { if (isCanceled()) return; - for (Object element : new ArrayList(elements)) { if (element instanceof AnAction) { - final AnAction action = (AnAction)element; - final AnActionEvent e = new AnActionEvent(myActionEvent.getInputEvent(), - myActionEvent.getDataContext(), - myActionEvent.getPlace(), - action.getTemplatePresentation(), - myActionEvent.getActionManager(), - myActionEvent.getModifiers()); - ActionUtil.performDumbAwareUpdate(action, e, false); - final Presentation presentation = e.getPresentation(); - if (!presentation.isEnabled() || !presentation.isVisible() || StringUtil.isEmpty(presentation.getText())) { + if (!isEnabled((AnAction)element)) { elements.remove(element); } if (isCanceled()) return; @@ -1933,6 +1930,29 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } } + protected boolean isEnabled(final AnAction action) { + if (myDisabledActions.contains(action)) return false; + final AnActionEvent e = new AnActionEvent(myActionEvent.getInputEvent(), + myActionEvent.getDataContext(), + myActionEvent.getPlace(), + action.getTemplatePresentation(), + myActionEvent.getActionManager(), + myActionEvent.getModifiers()); + + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + ActionUtil.performDumbAwareUpdate(action, e, false); + } + }); + final Presentation presentation = e.getPresentation(); + final boolean enabled = presentation.isEnabled() && presentation.isVisible() && !StringUtil.isEmpty(presentation.getText()); + if (!enabled) { + myDisabledActions.add(action); + } + return enabled; + } + private synchronized void checkModelsUpToDate() { if (myClassModel == null) { myClassModel = new GotoClassModel2(project); @@ -2165,6 +2185,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA myEditor = null; myFileEditor = null; myStructureModel = null; + myDisabledActions.clear(); } } } From e485a2fc91662917391a2d6f6008bec5ed7a32c7 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Jan 2015 15:54:34 +0100 Subject: [PATCH 36/55] dfa: annotation inference suppression is different from honoring package-level defaults, so split them --- .../codeInsight/InferredAnnotationsManagerImpl.java | 8 ++------ .../codeInspection/dataFlow/HardcodedContracts.java | 12 ++++++++++++ .../codeInsight/NullableNotNullManagerImpl.java | 6 ++++++ .../codeInsight/InferredAnnotationsManager.java | 3 --- .../intellij/codeInsight/NullableNotNullManager.java | 10 ++++++---- .../dataFlow/fixture/CustomTypeQualifierDefault.java | 11 +++++++++++ 6 files changed, 37 insertions(+), 13 deletions(-) rename java/{openapi => java-impl}/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java (80%) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/InferredAnnotationsManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/InferredAnnotationsManagerImpl.java index c67d4c995b1f..f5d21fd70282 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/InferredAnnotationsManagerImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/InferredAnnotationsManagerImpl.java @@ -82,24 +82,20 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager { if (owner instanceof PsiMethod && PsiUtil.canBeOverriden((PsiMethod)owner)) { return true; } - if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && hasHardcodedContracts(owner)) { + if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && HardcodedContracts.hasHardcodedContracts(owner)) { return true; } if (AnnotationUtil.NOT_NULL.equals(annotationFQN) && owner instanceof PsiParameter && owner.getParent() != null) { if (AnnotationUtil.isAnnotated(owner, NullableNotNullManager.getInstance(owner.getProject()).getNullables(), false, false)) { return true; } - if (hasHardcodedContracts(owner.getParent().getParent())) { + if (HardcodedContracts.hasHardcodedContracts(owner)) { return true; } } return false; } - private static boolean hasHardcodedContracts(PsiElement owner) { - return owner instanceof PsiMethod && !HardcodedContracts.getHardcodedContracts((PsiMethod)owner, null).isEmpty(); - } - @Nullable private PsiAnnotation getInferredContractAnnotation(PsiMethod method) { if (method.getModifierList().findAnnotation(ORG_JETBRAINS_ANNOTATIONS_CONTRACT) != null) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java index f9e58134c860..05743b52c137 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java @@ -164,4 +164,16 @@ public class HardcodedContracts { return true; } + + public static boolean hasHardcodedContracts(@Nullable PsiElement element) { + if (element instanceof PsiMethod) { + return !getHardcodedContracts((PsiMethod)element, null).isEmpty(); + } + + if (element instanceof PsiParameter) { + return hasHardcodedContracts(element.getParent().getParent()); + } + + return false; + } } diff --git a/java/openapi/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java similarity index 80% rename from java/openapi/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java rename to java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java index c817c3019275..adb18e11b682 100644 --- a/java/openapi/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/NullableNotNullManagerImpl.java @@ -15,13 +15,19 @@ */ package com.intellij.codeInsight; +import com.intellij.codeInspection.dataFlow.HardcodedContracts; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.psi.PsiElement; @State( name = "NullableNotNullManager", storages = {@Storage(file = StoragePathMacros.PROJECT_FILE)} ) public class NullableNotNullManagerImpl extends NullableNotNullManager { + protected boolean hasHardcodedContracts(PsiElement element) { + return HardcodedContracts.hasHardcodedContracts(element); + } + } diff --git a/java/java-psi-api/src/com/intellij/codeInsight/InferredAnnotationsManager.java b/java/java-psi-api/src/com/intellij/codeInsight/InferredAnnotationsManager.java index 3696c4c666cc..97401bc6f725 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/InferredAnnotationsManager.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/InferredAnnotationsManager.java @@ -53,9 +53,6 @@ public abstract class InferredAnnotationsManager { * * {@link Contract} and {@link NotNull} annotations on methods are not necessarily applicable to the overridden implementations, so they're ignored, too.

* - * In addition, package-default annotations like @ParametersAreNonnullByDefault are not honored for parameters where - * {@link NotNull} inference is ignored. - * * @return whether inference is to be suppressed the given annotation on the given method or parameter */ public abstract boolean ignoreInference(@NotNull PsiModifierListOwner owner, @Nullable String annotationFQN); diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java index ea5322cdd44f..3ade181e074b 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java @@ -36,7 +36,7 @@ import java.util.*; * User: anna * Date: 1/25/11 */ -public class NullableNotNullManager implements PersistentStateComponent { +public abstract class NullableNotNullManager implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance("#" + NullableNotNullManager.class.getName()); public String myDefaultNullable = AnnotationUtil.NULLABLE; @@ -184,14 +184,16 @@ public class NullableNotNullManager implements PersistentStateComponent if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) { return null; } - - if (!nullable && InferredAnnotationsManager.getInstance(owner.getProject()).ignoreInference(owner, AnnotationUtil.NOT_NULL)) { + + if (!nullable && hasHardcodedContracts(owner)) { return null; } - + return findNullabilityDefaultInHierarchy(owner, nullable); } + protected abstract boolean hasHardcodedContracts(PsiElement element); + @Nullable private static PsiType getOwnerType(PsiModifierListOwner owner) { if (owner instanceof PsiVariable) return ((PsiVariable)owner).getType(); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java index e9ec6b1dbe11..47df47f35b44 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java @@ -1,5 +1,6 @@ import foo.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; class Some { void foo(@NotNull String s) { @@ -18,6 +19,16 @@ class Some { @bar.MethodsAreNotNullByDefault class NotNullClass { static native Object foo(String s); + + public Object foo() { + return null; + } + + @Nullable + public Object foo2() { + return null; + } + } class NullableClass { From e7990d49e729bcb1d69875cf11d61fa4db29a0f1 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 14 Jan 2015 16:10:36 +0100 Subject: [PATCH 37/55] IDEA-131639 (Inspection for public fields ignore static/final keywords) --- .../src/inspectionDescriptions/PublicField.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PublicField.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PublicField.html index 6915037d54c1..5de79e7e8920 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/PublicField.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PublicField.html @@ -1,6 +1,6 @@ -Reports public instance variables. +Reports public fields. Constants (i.e. variables marked static and final) are not reported.

From c616cf0f0eb487d5627e3413c1ce267113961c5d Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 13 Jan 2015 20:39:09 +0300 Subject: [PATCH 38/55] IDEA-66963 IDEA-84000 vcs: annotate from annotate allow to annotate both: previous and selected revisions --- .../openapi/vcs/annotate/FileAnnotation.java | 3 +- .../AnnotateCurrentRevisionAction.java | 40 ++++++++++++++++++ .../AnnotatePreviousRevisionAction.java | 42 +++++++++++++++++++ .../vcs/actions/AnnotateRevisionAction.java | 37 ++++++---------- .../vcs/actions/AnnotateToggleAction.java | 3 +- 5 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/FileAnnotation.java b/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/FileAnnotation.java index df3fb7e4f4ed..1f8bc063cc7a 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/FileAnnotation.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/FileAnnotation.java @@ -98,7 +98,8 @@ public abstract class FileAnnotation { public abstract VcsRevisionNumber getCurrentRevision(); /** - * Get all revisions that are mentioned in the annotations + * Get all revisions that are mentioned in the annotations. + * order: from newest to oldest * * @return the list of revisions that are mentioned in annotations. Or null * if before/after popups cannot be suported by the VCS system. diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java new file mode 100644 index 000000000000..edb73a89713b --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateCurrentRevisionAction.java @@ -0,0 +1,40 @@ +package com.intellij.openapi.vcs.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.annotate.FileAnnotation; +import com.intellij.openapi.vcs.history.VcsFileRevision; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +class AnnotateCurrentRevisionAction extends AnnotateRevisionAction { + @NotNull private final List myRevisions; + + public AnnotateCurrentRevisionAction(@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) { + super("Annotate Revision", "Annotate selected revision in new tab", AllIcons.Actions.Annotate, + annotation, vcs); + Map map = new HashMap(); + List revisions = annotation.getRevisions(); + if (revisions != null) { + for (VcsFileRevision revision : revisions) { + map.put(revision.getRevisionNumber(), revision); + } + } + + myRevisions = new ArrayList(annotation.getLineCount()); + for (int i = 0; i < annotation.getLineCount(); i++) { + myRevisions.add(map.get(annotation.getLineRevisionNumber(i))); + } + } + + @Override + @NotNull + public List getRevisions() { + return myRevisions; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java new file mode 100644 index 000000000000..8fc2c1258398 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotatePreviousRevisionAction.java @@ -0,0 +1,42 @@ +package com.intellij.openapi.vcs.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.annotate.FileAnnotation; +import com.intellij.openapi.vcs.history.VcsFileRevision; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +class AnnotatePreviousRevisionAction extends AnnotateRevisionAction { + @NotNull private final List myRevisions; + + public AnnotatePreviousRevisionAction(@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) { + super("Annotate Previous Revision", "Annotate successor of selected revision in new tab", AllIcons.Actions.Annotate, + annotation, vcs); + Map map = new HashMap(); + List revisions = annotation.getRevisions(); + if (revisions != null) { + for (int i = 0; i < revisions.size(); i++) { + VcsFileRevision revision = revisions.get(i); + VcsFileRevision previousRevision = i + 1 < revisions.size() ? revisions.get(i + 1) : null; + map.put(revision.getRevisionNumber(), previousRevision); + } + } + + myRevisions = new ArrayList(annotation.getLineCount()); + for (int i = 0; i < annotation.getLineCount(); i++) { + myRevisions.add(map.get(annotation.getLineRevisionNumber(i))); + } + } + + @Override + @NotNull + public List getRevisions() { + return myRevisions; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java index 3419713eddc5..ed9b07bf4e33 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionAction.java @@ -1,6 +1,5 @@ package com.intellij.openapi.vcs.actions; -import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.vcs.AbstractVcs; @@ -10,45 +9,31 @@ import com.intellij.openapi.vcs.annotate.FileAnnotation; import com.intellij.openapi.vcs.annotate.LineNumberListener; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsFileRevisionEx; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.vfs.VcsFileSystem; import com.intellij.openapi.vcs.vfs.VcsVirtualFile; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; +import javax.swing.*; import java.util.List; -import java.util.Map; -class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbAware, LineNumberListener { +abstract class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbAware, LineNumberListener { @NotNull private final FileAnnotation myAnnotation; @NotNull private final AbstractVcs myVcs; - @NotNull private final List myRevisions; - private int currentLine; - public AnnotateRevisionAction(@NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) { - super("Annotate revision", "Annotate selected revision in new tab", AllIcons.Actions.Annotate); + public AnnotateRevisionAction(@Nullable String text, @Nullable String description, @Nullable Icon icon, + @NotNull FileAnnotation annotation, @NotNull AbstractVcs vcs) { + super(text, description, icon); myAnnotation = annotation; myVcs = vcs; - - Map map = new HashMap(); - List revisions = myAnnotation.getRevisions(); - if (revisions != null) { - for (VcsFileRevision revision : revisions) { - map.put(revision.getRevisionNumber(), revision); - } - } - - myRevisions = new ArrayList(myAnnotation.getLineCount()); - for (int i = 0; i < myAnnotation.getLineCount(); i++) { - myRevisions.add(map.get(myAnnotation.getLineRevisionNumber(i))); - } } + @NotNull + protected abstract List getRevisions(); + @Nullable protected AbstractVcs getVcs(@NotNull AnActionEvent e) { return myVcs; @@ -68,8 +53,10 @@ class AnnotateRevisionAction extends AnnotateRevisionActionBase implements DumbA @Nullable @Override protected VcsFileRevision getFileRevision(@NotNull AnActionEvent e) { - if (currentLine < 0 || currentLine >= myRevisions.size()) return null; - return myRevisions.get(currentLine); + List revisions = getRevisions(); + + if (currentLine < 0 || currentLine >= revisions.size()) return null; + return revisions.get(currentLine); } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java index 193db657496a..bc401e2508a2 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java @@ -299,7 +299,8 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware, Ann gutters.add(new ExtraFieldGutter(fileAnnotation, editor, presentation, bgColorMap, actionGroup)); presentation.addAction(new ShowHideAdditionalInfoAction(gutters, editorGutter, actionGroup)); - presentation.addAction(new AnnotateRevisionAction(fileAnnotation, vcs)); + presentation.addAction(new AnnotateCurrentRevisionAction(fileAnnotation, vcs)); + presentation.addAction(new AnnotatePreviousRevisionAction(fileAnnotation, vcs)); addActionsFromExtensions(presentation, fileAnnotation); for (AnAction action : presentation.getActions()) { From 574c7349a1a93b88b369c3f8ca3c78fed2d8070a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 13:59:02 +0100 Subject: [PATCH 39/55] no need in paired inspection after unused symbol/declaration merged --- .../unusedSymbol/UnusedSymbolLocalInspectionBase.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java index 6c045fa4270b..293e23796148 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java @@ -24,7 +24,7 @@ import org.intellij.lang.annotations.Pattern; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool { +public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool { @NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME; @NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME; @NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters"; @@ -74,9 +74,4 @@ public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool return true; } - @NotNull - @Override - public String getInspectionForBatchShortName() { - return UnusedDeclarationInspectionBase.SHORT_NAME; - } } From 6e99326ee4924e56a9037006ee68cbae7e222741 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 15:06:17 +0100 Subject: [PATCH 40/55] cleanup IDEA-CR-1199 --- .../completion/NormalCompletionTest.groovy | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index dafb0ea9445b..ad932fc86735 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1487,19 +1487,13 @@ class Bar { public void "test code cleanup during completion generation"() { myFixture.configureByText "a.java", "class Foo {int i; ge}" - def inspection = new UnqualifiedFieldAccessInspection() - try { - myFixture.enableInspections(inspection) - myFixture.complete(CompletionType.BASIC) - myFixture.checkResult '''class Foo {int i; + myFixture.enableInspections(new UnqualifiedFieldAccessInspection()) + myFixture.complete(CompletionType.BASIC) + myFixture.checkResult '''class Foo {int i; public int getI() { return this.i; } }''' - } - finally { - myFixture.disableInspections(inspection) - } } } From ba85aa6a1ca8c754ef9eed264f5c2e2814895056 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 15:27:04 +0100 Subject: [PATCH 41/55] redundant cast: check that then/else branches of conditional expressions stay assignable to the conditional expression type (IDEA-135153) --- .../intellij/psi/util/RedundantCastUtil.java | 18 ++++++++++++++++++ .../lambda/Conditional/expected.xml | 2 ++ .../lambda/Conditional/src/Test.java | 5 +++++ .../codeInspection/RedundantCast18Test.java | 1 + 4 files changed, 26 insertions(+) create mode 100644 java/java-tests/testData/inspection/redundantCast/lambda/Conditional/expected.xml create mode 100644 java/java-tests/testData/inspection/redundantCast/lambda/Conditional/src/Test.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java index eca80b6ee824..02566166fa28 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java @@ -549,6 +549,14 @@ public class RedundantCastUtil { final PsiExpression initializer = ((PsiLocalVariable)declarationStatement.getDeclaredElements()[0]).getInitializer(); LOG.assertTrue(initializer != null, operand.getText()); opType = initializer.getType(); + + if (opType != null) { + final PsiExpression expr = PsiUtil.skipParenthesizedExprDown(operand); + if (expr instanceof PsiConditionalExpression) { + if (!isApplicableForConditionalBranch(opType, ((PsiConditionalExpression)expr).getThenExpression())) return; + if (!isApplicableForConditionalBranch(opType, ((PsiConditionalExpression)expr).getElseExpression())) return; + } + } } catch (IncorrectOperationException ignore) {} } @@ -631,6 +639,16 @@ public class RedundantCastUtil { } } + private static boolean isApplicableForConditionalBranch(PsiType opType, PsiExpression thenExpression) { + if (thenExpression != null) { + final PsiType thenType = thenExpression.getType(); + if (thenType != null && !TypeConversionUtil.isAssignable(opType, thenType)) { + return false; + } + } + return true; + } + private static boolean arrayAccessAtTheLeftSideOfAssignment(PsiElement element) { PsiAssignmentExpression assignment = PsiTreeUtil.getParentOfType(element, PsiAssignmentExpression.class, false, PsiMember.class); if (assignment == null) return false; diff --git a/java/java-tests/testData/inspection/redundantCast/lambda/Conditional/expected.xml b/java/java-tests/testData/inspection/redundantCast/lambda/Conditional/expected.xml new file mode 100644 index 000000000000..4704d91e891d --- /dev/null +++ b/java/java-tests/testData/inspection/redundantCast/lambda/Conditional/expected.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/redundantCast/lambda/Conditional/src/Test.java b/java/java-tests/testData/inspection/redundantCast/lambda/Conditional/src/Test.java new file mode 100644 index 000000000000..cfa128ec2f29 --- /dev/null +++ b/java/java-tests/testData/inspection/redundantCast/lambda/Conditional/src/Test.java @@ -0,0 +1,5 @@ +class Test { + public static void foo(Object[] objectArray, boolean check) { + String kv = (String)(check ? "N" : objectArray[0]) ; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast18Test.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast18Test.java index 6cb52914fe84..d3b13ec6ca54 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast18Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantCast18Test.java @@ -33,6 +33,7 @@ public class RedundantCast18Test extends InspectionTestCase { public void testMethodRefContext() throws Exception { doTest(); } public void testExpectedSupertype() throws Exception { doTest(); } public void testForeachValue() throws Exception { doTest(); } + public void testConditional() throws Exception { doTest(); } @Override protected Sdk getTestProjectSdk() { From f0c7fe99b57fd1591b28387a021bb7b23e8b1ca1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 15:29:38 +0100 Subject: [PATCH 42/55] enable $MODULE_DIR$ macro for testng (IDEA-135220) --- .../testng/configuration/TestNGConfigurationEditor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java index a7e498e6e18e..9f3dffb9e814 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java @@ -142,6 +142,7 @@ public class TestNGConfigurationEditor extends SettingsEditor Date: Wed, 14 Jan 2015 16:14:25 +0100 Subject: [PATCH 43/55] copyright: artificial blank lines added in groovy (IDEA-135228) --- .../idea/copyright/psi/UpdatePsiFileCopyright.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java index 338c8a73880e..f40b3245891d 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java @@ -159,8 +159,11 @@ public abstract class UpdatePsiFileCopyright extends AbstractUpdateCopyright { return; // Nothing to do since the comment is the same } PsiElement next = getNextSibling(range.getLast()); - if (next instanceof PsiWhiteSpace && countNewline(next.getText()) > 1) { - return; + if (next != null) { + final String text = next.getText(); + if (StringUtil.isEmptyOrSpaces(text) && countNewline(text) > 1) { + return; + } } point = range.getFirst(); } From 7205db4b582156675c801a71a86ef62119c1a69b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Jan 2015 16:40:28 +0100 Subject: [PATCH 44/55] anonym -> lambda: evaluate ground type for type, inferred by position (IDEA-135211) --- .../AnonymousCanBeLambdaInspection.java | 3 ++- ...GroundTypeForInferredTypeBeforeChecks.java | 21 +++++++++++++++ .../afterVoidValueTransformation.java | 5 ++-- ...GroundTypeForInferredTypeBeforeChecks.java | 26 +++++++++++++++++++ .../beforeVoidValueTransformation.java | 5 ++-- .../Anonymous2LambdaInspectionTest.java | 7 +++++ 6 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterGetGroundTypeForInferredTypeBeforeChecks.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeGetGroundTypeForInferredTypeBeforeChecks.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index f1a601117e62..cbb715cb12b1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -35,6 +35,7 @@ import com.intellij.psi.controlFlow.AnalysisCanceledException; import com.intellij.psi.controlFlow.ControlFlow; import com.intellij.psi.controlFlow.ControlFlowUtil; import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; +import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; @@ -439,7 +440,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection PsiAnonymousClass aClass) { myMethod = method; myAnonymClass = aClass; - final PsiType inferredType = getInferredType(aClass); + final PsiType inferredType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(getInferredType(aClass)); myEqualInference = !aClass.getBaseClassType().equals(inferredType); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterGetGroundTypeForInferredTypeBeforeChecks.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterGetGroundTypeForInferredTypeBeforeChecks.java new file mode 100644 index 000000000000..e2f8e7825584 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterGetGroundTypeForInferredTypeBeforeChecks.java @@ -0,0 +1,21 @@ +// "Replace with lambda" "true" +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +class Test { + + void f(List r){ + List l = r.stream().filter(status -> stringContainingSort(status)) + .map(Status::new) + .collect(Collectors.toList()); + } + + boolean stringContainingSort(Object text) { + return true; + } + + class Status { + public Status(Status s) {} + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterVoidValueTransformation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterVoidValueTransformation.java index 9cbf793206d4..b3bec72aa1e5 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterVoidValueTransformation.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterVoidValueTransformation.java @@ -1,9 +1,10 @@ // "Replace with lambda" "true" -import javax.swing.*; class Test { String c = null; public void main(String[] args){ - SwingUtilities.invokeLater(() -> c.substring(0).toString()); + invokeLater(() -> c.substring(0).toString()); } + + public void invokeLater(Runnable r) {} } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeGetGroundTypeForInferredTypeBeforeChecks.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeGetGroundTypeForInferredTypeBeforeChecks.java new file mode 100644 index 000000000000..5759c051f507 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeGetGroundTypeForInferredTypeBeforeChecks.java @@ -0,0 +1,26 @@ +// "Replace with lambda" "true" +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +class Test { + + void f(List r){ + List l = r.stream().filter(new Predicate() { + @Override + public boolean test(Status status) { + return stringContainingSort(status); + } + }) + .map(Status::new) + .collect(Collectors.toList()); + } + + boolean stringContainingSort(Object text) { + return true; + } + + class Status { + public Status(Status s) {} + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeVoidValueTransformation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeVoidValueTransformation.java index a676def55b15..bb0c9b6715e7 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeVoidValueTransformation.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeVoidValueTransformation.java @@ -1,13 +1,14 @@ // "Replace with lambda" "true" -import javax.swing.*; class Test { String c = null; public void main(String[] args){ - SwingUtilities.invokeLater(new Runnable() { + invokeLater(new Runnable() { public void run() { c.substring(0).toString(); } }); } + + public void invokeLater(Runnable r) {} } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java index 4689fe1b0079..fd88b4b3dbb8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java @@ -17,6 +17,9 @@ package com.intellij.codeInsight.daemon.quickFix; import com.intellij.codeInspection.AnonymousCanBeLambdaInspection; import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.testFramework.IdeaTestUtil; import org.jetbrains.annotations.NotNull; @@ -36,4 +39,8 @@ public class Anonymous2LambdaInspectionTest extends LightQuickFixParameterizedTe return "/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda"; } + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } } \ No newline at end of file From 0761efccfde0b24fd1274d92456ad3a36c5642fc Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 14 Jan 2015 19:09:48 +0300 Subject: [PATCH 45/55] updated pycharm edu build.gant according to new modules layout --- python/edu/build/pycharm_edu_build.gant | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index c3e837dacdef..5dd02039a32d 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -213,12 +213,14 @@ public layoutEducational(String classesPath, Set usedJars) { private layoutPlugins(layouts) { dir("plugins") { - layouts.layoutPlugin("learn-python") { + layouts.layoutPlugin("interactive-learning") + layouts.layoutPlugin("interactive-learning-python") { dir("courses") { - fileset(dir: "$pythonEduHome/learn-python/resources/courses") + fileset(dir: "$pythonEduHome/interactive-learning-python/resources/courses") } } layouts.layoutPlugin("course-creator") + layouts.layoutPlugin("course-creator-python") } layouts.layoutCommunityPlugins(ch) From bdacb837a047d422103df7cf508638d532d25747 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 14 Jan 2015 19:47:36 +0300 Subject: [PATCH 46/55] [vcs-log] restore selection after log refresh and reset myMoreRequested flag on model change IDEA-125279 --- .../com/intellij/vcs/log/ui/VcsLogUiImpl.java | 22 +++++++------------ .../vcs/log/ui/tables/GraphTableModel.java | 1 + 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 440b3efd1a9a..98478881d336 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -76,20 +76,21 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { public void setVisiblePack(@NotNull VisiblePack pack) { ApplicationManager.getApplication().assertIsDispatchThread(); + PermanentGraph previousPermGraph = myVisiblePack.getPermanentGraph(); TIntHashSet previouslySelected = getSelectedCommits(); - PermanentGraph previousPermGraph = myVisiblePack.getPermanentGraph(); myVisiblePack = pack; - boolean permGraphChanged = previousPermGraph != myVisiblePack.getPermanentGraph(); GraphTableModel currentModel = getModel(); if (currentModel == null) { - GraphTableModel newModel = new GraphTableModel(myVisiblePack, myLogDataHolder, this); - setModel(newModel, myVisiblePack.getVisibleGraph(), previouslySelected); + VcsLogGraphTable table = getTable(); + table.setModel(new GraphTableModel(myVisiblePack, myLogDataHolder, this)); + table.setPaintBusy(false); } else { currentModel.setVisiblePack(myVisiblePack); + restoreSelection(currentModel, myVisiblePack.getVisibleGraph(), previouslySelected, getTable()); } myMainFrame.updateDataPack(myVisiblePack); setLongEdgeVisibility(myUiProperties.areLongEdgesVisible()); @@ -102,15 +103,6 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { return myMainFrame; } - private void setModel(@NotNull GraphTableModel newModel, - @NotNull VisibleGraph newVisibleGraph, - @NotNull TIntHashSet previouslySelectedCommits) { - final VcsLogGraphTable table = getTable(); - table.setModel(newModel); - restoreSelection(newModel, newVisibleGraph, previouslySelectedCommits, table); - table.setPaintBusy(false); - } - private static void restoreSelection(@NotNull GraphTableModel newModel, @NotNull VisibleGraph newVisibleGraph, @NotNull TIntHashSet previouslySelectedCommits, @@ -243,7 +235,9 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { } } - private void jumpTo(@NotNull final T commitId, @NotNull final PairFunction rowGetter, @NotNull final SettableFuture future) { + private void jumpTo(@NotNull final T commitId, + @NotNull final PairFunction rowGetter, + @NotNull final SettableFuture future) { if (future.isCancelled()) return; GraphTableModel model = getModel(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index 5e83503e81d2..476bab69af06 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -246,6 +246,7 @@ public class GraphTableModel extends AbstractTableModel { public void setVisiblePack(@NotNull VisiblePack visiblePack) { myDataPack = visiblePack; + myMoreRequested = false; fireTableDataChanged(); } } From 3ad0612c6a15d2ddd4fdbdec78d4aed462025c4a Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Jan 2015 17:43:51 +0100 Subject: [PATCH 47/55] restore autopopup after typing # in javadoc (IDEA-135231) --- .../completion/JavadocCompletionConfidence.java | 15 ++++++++++----- .../completion/JavaAutoPopupTest.groovy | 11 +++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavadocCompletionConfidence.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavadocCompletionConfidence.java index 6d6bd29f01c7..3f09e08b2a2f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavadocCompletionConfidence.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavadocCompletionConfidence.java @@ -33,11 +33,16 @@ public class JavadocCompletionConfidence extends CompletionConfidence { @NotNull @Override public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) { - if (psiElement().inside(PsiDocTag.class).accepts(contextElement) && findJavaReference(psiFile, offset - 1) != null) { - return ThreeState.NO; - } - if (PlatformPatterns.psiElement(JavaDocTokenType.DOC_TAG_NAME).accepts(contextElement)) { - return ThreeState.NO; + if (psiElement().inside(PsiDocTag.class).accepts(contextElement)) { + if (findJavaReference(psiFile, offset - 1) != null) { + return ThreeState.NO; + } + if (PlatformPatterns.psiElement(JavaDocTokenType.DOC_TAG_NAME).accepts(contextElement)) { + return ThreeState.NO; + } + if (contextElement.textMatches("#")) { + return ThreeState.NO; + } } return super.shouldSkipAutopopup(contextElement, psiFile, offset); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 5635e5418ea0..4bd51ede33c3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -256,6 +256,17 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { assert lookup } + public void "test popup after hash in javadoc"() { + myFixture.configureByText("a.java", """ + /** + * {@link String} + */ + class Foo {} + """) + type '#' + assert lookup + } + public void "test popup in javadoc local reference"() { myFixture.configureByText("a.java", """ /** From 949bfe924e9fa2c068302663b108ce696268989d Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Wed, 14 Jan 2015 19:49:28 +0300 Subject: [PATCH 48/55] Do postponed operations/formatting in case of PSI modifications (fixes WI-26121 Format on paste throws exception after modification of injected fragment) --- .../intellij/codeInsight/intention/impl/QuickEditHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java index 7f3f4c47de7d..db6b405e50c8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java @@ -382,6 +382,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable { commitToOriginalInner(); } }); + PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myOrigDocument); } } finally { From 0eff1b1311c62cd611df731ba2d7eaf1eea23dc6 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 14 Jan 2015 20:15:16 +0300 Subject: [PATCH 49/55] [vcs-log] reset PaintBusy IDEA-125279 --- .../impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 98478881d336..9ee21d88617e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -84,14 +84,14 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { GraphTableModel currentModel = getModel(); if (currentModel == null) { - VcsLogGraphTable table = getTable(); - table.setModel(new GraphTableModel(myVisiblePack, myLogDataHolder, this)); - table.setPaintBusy(false); + getTable().setModel(new GraphTableModel(myVisiblePack, myLogDataHolder, this)); } else { currentModel.setVisiblePack(myVisiblePack); restoreSelection(currentModel, myVisiblePack.getVisibleGraph(), previouslySelected, getTable()); } + getTable().setPaintBusy(false); + myMainFrame.updateDataPack(myVisiblePack); setLongEdgeVisibility(myUiProperties.areLongEdgesVisible()); fireFilterChangeEvent(myVisiblePack, permGraphChanged); From 88779186a28b553cc3fda68ee2740c4774dbb5d2 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Wed, 14 Jan 2015 20:23:29 +0300 Subject: [PATCH 50/55] Fix assertions in Emmet --- .../codeInsight/template/emmet/nodes/GenerationNode.java | 2 +- .../codeInsight/template/emmet/tokens/TemplateToken.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java index 31695e10d832..f41f17261aa1 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java @@ -282,7 +282,7 @@ public class GenerationNode extends UserDataHolderBase { final XmlFile xmlFile = token.getFile(); PsiFileFactory fileFactory = PsiFileFactory.getInstance(xmlFile.getProject()); - XmlFile dummyFile = (XmlFile)fileFactory.createFileFromText(HTMLLanguage.INSTANCE, xmlFile.getText()); + XmlFile dummyFile = (XmlFile)fileFactory.createFileFromText("dummy.html", HTMLLanguage.INSTANCE, xmlFile.getText(), false, true); final XmlTag tag = dummyFile.getRootTag(); if (tag != null) { diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java index 10dec7c5f7a7..e4daa0421238 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java @@ -100,7 +100,7 @@ public class TemplateToken extends ZenCodingToken { String templateString = template.getString(); final PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(callback.getProject()); if (!containsAttrsVar(template)) { - XmlFile dummyFile = (XmlFile)psiFileFactory.createFileFromText(HTMLLanguage.INSTANCE, templateString); + XmlFile dummyFile = (XmlFile)psiFileFactory.createFileFromText("dummy.html", HTMLLanguage.INSTANCE, templateString, false, true); dummyRootTag = dummyFile.getRootTag(); if (dummyRootTag != null) { addMissingAttributes(dummyRootTag, attributes); From c800bb1a850294f869f72dcdcbab05110a3d16f6 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 14 Jan 2015 20:34:50 +0300 Subject: [PATCH 51/55] Added utility class to process mnemonics in one place --- .../com/intellij/openapi/MnemonicWrapper.java | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java b/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java new file mode 100644 index 000000000000..166559e8d38c --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java @@ -0,0 +1,289 @@ +/* + * Copyright 2000-2015 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.intellij.openapi; + +import com.intellij.ide.ui.UISettings; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.Component; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; + +/** + * @author Sergey.Malenkov + */ +abstract class MnemonicWrapper implements Runnable, PropertyChangeListener { + public static MnemonicWrapper getWrapper(Component component) { + for (PropertyChangeListener listener : component.getPropertyChangeListeners()) { + if (listener instanceof MnemonicWrapper) { + MnemonicWrapper wrapper = (MnemonicWrapper)listener; + wrapper.run(); // update mnemonics immediately + return wrapper; + } + } + if (component instanceof JMenuItem) { + return null; // TODO: new MenuWrapper((JMenuItem)component); + } + if (component instanceof AbstractButton) { + return new ButtonWrapper((AbstractButton)component); + } + if (component instanceof JLabel) { + return new LabelWrapper((JLabel)component); + } + return null; + } + + final T myComponent; // direct access from inner classes + private final String myTextProperty; + private final String myCodeProperty; + private final String myIndexProperty; + private int myCode; + private int myIndex; + private boolean myFocusable; + private boolean myEvent; + private Runnable myRunnable; + + private MnemonicWrapper(T component, String text, String code, String index) { + myComponent = component; + myTextProperty = text; + myCodeProperty = code; + myIndexProperty = index; + if (!updateText()) { + // assume that it is already set + myCode = getMnemonicCode(); + myIndex = getMnemonicIndex(); + } + myFocusable = isFocusable(); + myComponent.addPropertyChangeListener(this); + run(); // update mnemonics immediately + } + + @Override + public final void run() { + boolean disabled = isDisabled(); + try { + myEvent = true; + setMnemonicCode(disabled ? KeyEvent.VK_UNDEFINED : myCode); + setMnemonicIndex(disabled ? -1 : myIndex); + Component component = getFocusableComponent(); + if (component != null) { + component.setFocusable(disabled || myFocusable); + } + } + finally { + myEvent = false; + myRunnable = null; + } + } + + @Override + public final void propertyChange(PropertyChangeEvent event) { + if (!myEvent) { + String property = event.getPropertyName(); + if (myTextProperty.equals(property)) { + if (updateText()) { + updateRequest(); + } + } + else if (myCodeProperty.equals(property)) { + myCode = getMnemonicCode(); + updateRequest(); + } + else if (myIndexProperty.equals(property)) { + myIndex = getMnemonicIndex(); + updateRequest(); + } + else if ("focusable".equals(property) || "labelFor".equals(property)) { + myFocusable = isFocusable(); + updateRequest(); + } + } + } + + private boolean updateText() { + String text = getText(); + if (text != null) { + int code = KeyEvent.VK_UNDEFINED; + int index = -1; + int length = text.length(); + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + char ch = text.charAt(i); + if (ch != UIUtil.MNEMONIC) { + sb.append(ch); + } + else if (i + 1 < length) { + code = getExtendedKeyCodeForChar(text.charAt(i + 1)); + index = sb.length(); + } + } + if (code != KeyEvent.VK_UNDEFINED) { + try { + myEvent = true; + setText(sb.toString()); + } + finally { + myEvent = false; + } + myCode = code; + myIndex = index; + return true; + } + } + return false; + } + + private void updateRequest() { + if (myRunnable == null) { + myRunnable = this; // run once + SwingUtilities.invokeLater(this); + } + } + + private boolean isFocusable() { + Component component = getFocusableComponent(); + return component == null || component.isFocusable(); + } + + Component getFocusableComponent() { + return myComponent; + } + + boolean isDisabled() { + return UISettings.getShadowInstance().DISABLE_MNEMONICS_IN_CONTROLS; + } + + abstract String getText(); + + abstract void setText(String text); + + abstract int getMnemonicCode(); + + abstract void setMnemonicCode(int code); + + abstract int getMnemonicIndex(); + + abstract void setMnemonicIndex(int index); + + // TODO: HACK because of Java7 required: + // replace later with KeyEvent.getExtendedKeyCodeForChar(ch) + private static int getExtendedKeyCodeForChar(int ch) { + try { + Method method = KeyEvent.class.getMethod("getExtendedKeyCodeForChar", int.class); + if (!method.isAccessible()) { + method.setAccessible(true); + } + return (Integer)method.invoke(KeyEvent.class, ch); + } + catch (Exception exception) { + if (ch >= 'a' && ch <= 'z') { + ch -= ('a' - 'A'); + } + return ch; + } + } + + private static class MenuWrapper extends ButtonWrapper { + private MenuWrapper(AbstractButton component) { + super(component); + } + + @Override + boolean isDisabled() { + return UISettings.getShadowInstance().DISABLE_MNEMONICS; + } + } + + private static class ButtonWrapper extends MnemonicWrapper { + private ButtonWrapper(AbstractButton component) { + super(component, "text", "mnemonic", "displayedMnemonicIndex"); + } + + @Override + String getText() { + return myComponent.getText(); + } + + @Override + void setText(String text) { + myComponent.setText(text); + } + + @Override + int getMnemonicCode() { + return myComponent.getMnemonic(); + } + + @Override + void setMnemonicCode(int code) { + myComponent.setMnemonic(code); + } + + @Override + int getMnemonicIndex() { + return myComponent.getDisplayedMnemonicIndex(); + } + + @Override + void setMnemonicIndex(int index) { + myComponent.setDisplayedMnemonicIndex(index); + } + } + + private static class LabelWrapper extends MnemonicWrapper { + private LabelWrapper(JLabel component) { + super(component, "text", "displayedMnemonic", "displayedMnemonicIndex"); + } + + @Override + String getText() { + return myComponent.getText(); + } + + @Override + void setText(String text) { + myComponent.setText(text); + } + + @Override + int getMnemonicCode() { + return myComponent.getDisplayedMnemonic(); + } + + @Override + void setMnemonicCode(int code) { + myComponent.setDisplayedMnemonic(code); + } + + @Override + int getMnemonicIndex() { + return myComponent.getDisplayedMnemonicIndex(); + } + + @Override + void setMnemonicIndex(int index) { + myComponent.setDisplayedMnemonicIndex(index); + } + + @Override + Component getFocusableComponent() { + return myComponent.getLabelFor(); + } + } +} From 46dd0ba7920a9340bd7c4310618540bd0274ff5c Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 14 Jan 2015 20:46:16 +0300 Subject: [PATCH 52/55] Added registry key to disable alt-based mnemonics on Mac --- .../com/intellij/openapi/MnemonicHelper.java | 4 +-- .../com/intellij/openapi/MnemonicWrapper.java | 33 +++++++++++++++++++ .../util/resources/misc/registry.properties | 1 + 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java index a7cf3ea5241d..1e4577c58dac 100644 --- a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi; -import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; @@ -26,7 +25,6 @@ import com.intellij.util.ui.DialogUtil; import org.jetbrains.annotations.NonNls; import javax.swing.*; -import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; @@ -80,7 +78,7 @@ public class MnemonicHelper extends ComponentTreeWatcher { } private static void fixMacMnemonicKeyStroke(JComponent component, String type) { - if (SystemInfo.isMac) { + if (SystemInfo.isMac && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) { // hack to make component's mnemonic work for ALT+KEY_CODE on Macs. // Default implementation uses ALT+CTRL+KEY_CODE (see BasicLabelUI). InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java b/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java index 166559e8d38c..0fa5b7b0f6f5 100644 --- a/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicWrapper.java @@ -16,10 +16,13 @@ package com.intellij.openapi; import com.intellij.ide.ui.UISettings; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.awt.Component; +import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -181,6 +184,18 @@ abstract class MnemonicWrapper implements Runnable, Propert abstract void setMnemonicIndex(int index); + static KeyStroke fixMacKeyStroke(KeyStroke stroke, InputMap map, int code, boolean onKeyRelease, String action) { + if (stroke != null && code != stroke.getKeyCode()) { + map.remove(stroke); + stroke = null; + } + if (stroke == null && code != KeyEvent.VK_UNDEFINED) { + stroke = KeyStroke.getKeyStroke(code, InputEvent.ALT_MASK | InputEvent.ALT_DOWN_MASK, onKeyRelease); + map.put(stroke, action); + } + return stroke; + } + // TODO: HACK because of Java7 required: // replace later with KeyEvent.getExtendedKeyCodeForChar(ch) private static int getExtendedKeyCodeForChar(int ch) { @@ -211,6 +226,9 @@ abstract class MnemonicWrapper implements Runnable, Propert } private static class ButtonWrapper extends MnemonicWrapper { + private KeyStroke myStrokePressed; + private KeyStroke myStrokeReleased; + private ButtonWrapper(AbstractButton component) { super(component, "text", "mnemonic", "displayedMnemonicIndex"); } @@ -233,6 +251,13 @@ abstract class MnemonicWrapper implements Runnable, Propert @Override void setMnemonicCode(int code) { myComponent.setMnemonic(code); + if (SystemInfo.isMac && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) { + InputMap map = myComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + if (map != null) { + myStrokePressed = fixMacKeyStroke(myStrokePressed, map, code, false, "pressed"); + myStrokeReleased = fixMacKeyStroke(myStrokeReleased, map, code, true, "released"); + } + } } @Override @@ -247,6 +272,8 @@ abstract class MnemonicWrapper implements Runnable, Propert } private static class LabelWrapper extends MnemonicWrapper { + private KeyStroke myStrokeRelease; + private LabelWrapper(JLabel component) { super(component, "text", "displayedMnemonic", "displayedMnemonicIndex"); } @@ -269,6 +296,12 @@ abstract class MnemonicWrapper implements Runnable, Propert @Override void setMnemonicCode(int code) { myComponent.setDisplayedMnemonic(code); + if (SystemInfo.isMac && Registry.is("ide.mac.alt.mnemonic.without.ctrl")) { + InputMap map = myComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + if (map != null) { + myStrokeRelease = fixMacKeyStroke(myStrokeRelease, map, code, true, "release"); + } + } } @Override diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index dd03c96f747d..192d5eae3666 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -154,6 +154,7 @@ skip.untitled.windows.for.mac.messages=false skip.untitled.windows.for.mac.messages.description=Temporary key to test a fix for MacMessages ide.mac.mountain.lion.notifications.enabled=true ide.mac.inplaceDialogMnemonicsFix=false +ide.mac.alt.mnemonic.without.ctrl=true ide.mac.fix.dialog.showing=false ide.mac.hide.cursor.when.typing=true ide.mac.show.native.help=true From cccd245a5ff32b96f077064d2cac1a71bfbad765 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Jan 2015 18:48:39 +0100 Subject: [PATCH 53/55] IDEA-134518 Insert "instanceof" completion variant on typing "!" (exclamation mark) --- .../completion/JavaCharFilter.java | 4 ++- .../completion/JavaCompletionData.java | 29 +++++++++++++++---- .../keywords/instanceofNegation.java | 7 +++++ .../keywords/instanceofNegation_after.java | 7 +++++ .../completion/KeywordCompletionTest.java | 7 +++++ 5 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation.java create mode 100644 java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java index 5c2318bb8281..cb3543aecc94 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java @@ -27,7 +27,6 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.CharFilter; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.lang.java.JavaLanguage; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.pom.java.LanguageLevel; @@ -61,6 +60,9 @@ public class JavaCharFilter extends CharFilter { final PsiType type = ((PsiMethod)o).getReturnType(); if (type != null && PsiType.BOOLEAN.isAssignableFrom(type)) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } + if (o instanceof PsiKeyword && ((PsiKeyword)o).textMatches(PsiKeyword.INSTANCEOF)) { + return Result.SELECT_ITEM_AND_FINISH_LOOKUP; + } return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index f5e43aa7bcec..77c6eb0d17cc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -19,10 +19,7 @@ import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.TailTypes; import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupItem; -import com.intellij.codeInsight.lookup.PsiTypeLookupItem; -import com.intellij.codeInsight.lookup.TailTypeDecorator; +import com.intellij.codeInsight.lookup.*; import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PsiJavaElementPattern; import com.intellij.pom.java.LanguageLevel; @@ -491,7 +488,29 @@ public class JavaCompletionData extends JavaAwareCompletionData { } if (isInstanceofPlace(position)) { - result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.INSTANCEOF), TailType.HUMBLE_SPACE_BEFORE_WORD)); + result.addElement(LookupElementDecorator.withInsertHandler( + createKeyword(position, PsiKeyword.INSTANCEOF), + new InsertHandler>() { + @Override + public void handleInsert(InsertionContext context, LookupElementDecorator item) { + TailType tailType = TailType.HUMBLE_SPACE_BEFORE_WORD; + if (tailType.isApplicable(context)) { + tailType.processTail(context.getEditor(), context.getTailOffset()); + } + + if ('!' == context.getCompletionChar()) { + context.setAddCompletionChar(false); + context.commitDocument(); + PsiInstanceOfExpression expr = + PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiInstanceOfExpression.class, false); + if (expr != null) { + String space = context.getCodeStyleSettings().SPACE_WITHIN_PARENTHESES ? " " : ""; + context.getDocument().insertString(expr.getTextRange().getStartOffset(), "!(" + space); + context.getDocument().insertString(context.getTailOffset(), space + ")"); + } + } + } + })); } if (isSuitableForClass(position)) { diff --git a/java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation.java b/java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation.java new file mode 100644 index 000000000000..04a3af1d55b4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation.java @@ -0,0 +1,7 @@ +class Foo { + void test() { + if (o inx) { + + } + } +} diff --git a/java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation_after.java b/java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation_after.java new file mode 100644 index 000000000000..cb7f271338dd --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/keywords/instanceofNegation_after.java @@ -0,0 +1,7 @@ +class Foo { + void test() { + if (!(o instanceof )x) { + + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java index 59029a2fb05a..b9511edf4a20 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/KeywordCompletionTest.java @@ -101,6 +101,13 @@ public class KeywordCompletionTest extends LightCompletionTestCase { public void testSpaceAfterInstanceof() throws Exception { doTest(false); } public void testInstanceofAfterUnresolved() throws Exception { doTest(1, "instanceof"); } public void testInstanceofAfterStatementStart() throws Exception { doTest(1, "instanceof"); } + + public void testInstanceofNegation() { + configureByFile(BASE_PATH + "/" + getTestName(true) + ".java"); + selectItem(myItems[0], '!'); + checkResultByFile(BASE_PATH + "/" + getTestName(true) + "_after.java"); + } + public void testAbstractInInterface() throws Exception { doTest(1, "abstract"); } public void testCharInAnnotatedParameter() throws Exception { doTest(1, "char"); } public void testReturnInTernary() throws Exception { doTest(1, "return"); } From 30346e631a4225e936a87c0dd5d971ff227b5710 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Jan 2015 18:52:54 +0100 Subject: [PATCH 54/55] WEB-14407 Event Log: should cut passed data --- .../src/com/intellij/notification/EventLog.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index 2cc090f4d645..f99c4d67915c 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -106,8 +106,9 @@ public class EventLog { Map links = new LinkedHashMap(); List lineSeparators = new ArrayList(); - String title = notification.getTitle(); - String content = notification.getContent(); + String title = truncateLongString(showMore, notification.getTitle()); + String content = truncateLongString(showMore, notification.getContent()); + RangeMarker afterTitle = null; boolean hasHtml = parseHtmlContent(title, notification, logDoc, showMore, links, lineSeparators); if (StringUtil.isNotEmpty(title)) { @@ -144,6 +145,15 @@ public class EventLog { return new LogEntry(logDoc.getText(), status, list); } + @NotNull + private static String truncateLongString(AtomicBoolean showMore, String title) { + if (title.length() > 1000) { + showMore.set(true); + return title.substring(0, 1000) + "..."; + } + return title; + } + private static void indentNewLines(DocumentImpl logDoc, List lineSeparators, RangeMarker afterTitle, boolean hasHtml, String indent) { if (!hasHtml) { int i = -1; From 06a21fcd941ce4a182a86748fb9a6eb323b6b431 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 14 Jan 2015 20:55:30 +0300 Subject: [PATCH 55/55] IDEA-126885 Decompiler exception on jdk.nashorn.internal.objects.Global --- .../code/interpreter/InstructionImpact.java | 10 +++++++--- .../decompiler/modules/decompiler/ExprProcessor.java | 12 +++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java index 55d4f5d83819..553ad84c1fee 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,6 +19,7 @@ import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.Instruction; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.struct.consts.LinkConstant; +import org.jetbrains.java.decompiler.struct.consts.PooledConstant; import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; import org.jetbrains.java.decompiler.struct.gen.DataPoint; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; @@ -394,8 +395,8 @@ public class InstructionImpact { case CodeConstants.opc_ldc: case CodeConstants.opc_ldc_w: case CodeConstants.opc_ldc2_w: - cn = pool.getPrimitiveConstant(instr.getOperand(0)); - switch (cn.type) { + PooledConstant constant = pool.getConstant(instr.getOperand(0)); + switch (constant.type) { case CodeConstants.CONSTANT_Integer: stack.push(new VarType(CodeConstants.TYPE_INT)); break; @@ -416,6 +417,9 @@ public class InstructionImpact { case CodeConstants.CONSTANT_Class: stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class")); break; + case CodeConstants.CONSTANT_MethodHandle: + stack.push(new VarType(((LinkConstant)constant).descriptor)); + break; } break; case CodeConstants.opc_aload: diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index fbd579b4a480..292d865d44f7 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -362,8 +362,14 @@ public class ExprProcessor implements CodeConstants { case opc_ldc: case opc_ldc_w: case opc_ldc2_w: - PrimitiveConstant cn = pool.getPrimitiveConstant(instr.getOperand(0)); - pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], cn.value, bytecode_offsets)); + PooledConstant cn = pool.getConstant(instr.getOperand(0)); + if (cn instanceof PrimitiveConstant) { + pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], ((PrimitiveConstant)cn).value, bytecode_offsets)); + } + else if (cn instanceof LinkConstant) { + //TODO: for now treat Links as Strings + pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_STRING, ((LinkConstant)cn).elementname , bytecode_offsets)); + } break; case opc_iload: case opc_lload: