From 242869ff3bd41f7e04700157bfd73352545bb7ed Mon Sep 17 00:00:00 2001 From: Kiryl Chetyrbak Date: Tue, 28 Mar 2017 17:45:35 -0400 Subject: [PATCH 01/27] Guess project by file for line separator if document was modified outside of command --- .../openapi/fileEditor/impl/FileDocumentManagerImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index 42faec0d2b16..b42d099ed0ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -113,6 +113,8 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt } final Runnable currentCommand = CommandProcessor.getInstance().getCurrentCommand(); Project project = currentCommand == null ? null : CommandProcessor.getInstance().getCurrentCommandProject(); + if (project == null) + project = ProjectUtil.guessProjectForFile(getFile(document)); String lineSeparator = CodeStyleFacade.getInstance(project).getLineSeparator(); document.putUserData(LINE_SEPARATOR_KEY, lineSeparator); From 71b911eba386ec85894b121b91f34a17d349b68e Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Thu, 20 Apr 2017 18:58:26 +0300 Subject: [PATCH 02/27] IDEA-169388 Resources not copied to output folder if Gradle project name is 'test' --- .../data/ExternalProjectDataCache.java | 9 +++++--- .../GradleResourceProcessingTest.java | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataCache.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataCache.java index 576ae24ecee5..562e0bb9b31a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataCache.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataCache.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.DefaultExternalProject; import org.jetbrains.plugins.gradle.model.ExternalProject; import org.jetbrains.plugins.gradle.model.ExternalSourceSet; +import org.jetbrains.plugins.gradle.util.GradleConstants; import java.io.File; import java.util.Collections; @@ -101,13 +102,15 @@ public class ExternalProjectDataCache { @NotNull public Map findExternalProject(@NotNull ExternalProject parentProject, @NotNull Module module) { String externalProjectId = ExternalSystemApiUtil.getExternalProjectId(module); - return externalProjectId != null ? findExternalProject(parentProject, externalProjectId) + boolean isSourceSet = GradleConstants.GRADLE_SOURCE_SET_MODULE_TYPE_KEY.equals(ExternalSystemApiUtil.getExternalModuleType(module)); + return externalProjectId != null ? findExternalProject(parentProject, externalProjectId, isSourceSet) : Collections.emptyMap(); } @NotNull private static Map findExternalProject(@NotNull ExternalProject parentProject, - @NotNull String externalProjectId) { + @NotNull String externalProjectId, + boolean isSourceSet) { Queue queue = ContainerUtil.newLinkedList(); queue.add(parentProject); @@ -119,7 +122,7 @@ public class ExternalProjectDataCache { for (Map.Entry sourceSetEntry : externalProject.getSourceSets().entrySet()) { final String sourceSetName = sourceSetEntry.getKey(); final String sourceSetId = projectId + ":" + sourceSetName; - if (isRelatedProject || externalProjectId.equals(sourceSetId)) { + if (isRelatedProject || (isSourceSet && externalProjectId.equals(sourceSetId))) { result.put(sourceSetName, sourceSetEntry.getValue()); } } diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java index 34ad6589e86f..0cd1b08cdb79 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java @@ -302,6 +302,29 @@ public class GradleResourceProcessingTest extends GradleCompilingTestCase { assertCopiedResources(); } + @Test + public void testModuleWithNameTestResourceCopying() throws Exception { + createProjectSubFile("bar/foo/src/main/resources/dir/file.properties"); + createProjectSubFile("bar/foo/src/test/resources/dir/file-test.properties"); + createProjectSubFile("bar/test/src/main/resources/dir/file.properties"); + createProjectSubFile("bar/test/src/test/resources/dir/file-test.properties"); + createSettingsFile("include ':bar:foo'\n" + + "include ':bar:test'"); + + importProjectUsingSingeModulePerGradleProject( + "subprojects {\n" + + " apply plugin: 'java'\n" + + "}\n" + ); + assertModules("project", "bar", "foo", "test"); + compileModules("project", "bar", "foo", "test"); + + assertCopied("bar/foo/build/resources/main/dir/file.properties"); + assertCopied("bar/foo/build/resources/test/dir/file-test.properties"); + assertCopied("bar/test/build/resources/main/dir/file.properties"); + assertCopied("bar/test/build/resources/test/dir/file-test.properties"); + } + private void createFilesForIncludesAndExcludesTest() throws IOException { createProjectSubFile("src/main/resources/dir/file.xxx"); createProjectSubFile("src/main/resources/dir/file.yyy"); From 8d750d328afda1b39571e102fce948ba8573104e Mon Sep 17 00:00:00 2001 From: "Liana.Bakradze" Date: Thu, 20 Apr 2017 19:18:35 +0300 Subject: [PATCH 03/27] move smart checker to Edu Python --- .../edu/learning/checker/StudyCheckUtils.java | 69 ------------------- .../edu/learning/PyEduPluginConfigurator.java | 1 + .../checker/PyStudySmartChecker.java} | 67 +++++++++++++++++- .../{ => checker}/PyStudyTaskChecker.java | 8 ++- .../{ => checker}/PyStudyTestRunner.java | 4 +- 5 files changed, 72 insertions(+), 77 deletions(-) rename python/{educational-core/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java => educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java} (57%) rename python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/{ => checker}/PyStudyTaskChecker.java (94%) rename python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/{ => checker}/PyStudyTestRunner.java (96%) diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java index 3b74d33b4fb8..bd0772416b07 100644 --- a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java +++ b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java @@ -6,9 +6,7 @@ import com.intellij.execution.process.ProcessOutput; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.progress.ProgressManager; @@ -16,7 +14,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.BalloonBuilder; import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindow; @@ -26,10 +23,7 @@ import com.intellij.ui.content.Content; import com.jetbrains.edu.learning.StudyState; import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; -import com.jetbrains.edu.learning.core.EduDocumentListener; -import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; -import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder; import com.jetbrains.edu.learning.courseFormat.TaskFile; import com.jetbrains.edu.learning.courseFormat.tasks.Task; import com.jetbrains.edu.learning.editor.StudyEditor; @@ -40,7 +34,6 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.io.IOException; import java.util.Map; public class StudyCheckUtils { @@ -117,68 +110,6 @@ public class StudyCheckUtils { } - public static void runSmartTestProcess(@NotNull final VirtualFile taskDir, - @NotNull final StudyTestRunner testRunner, - @NotNull final String taskFileName, - @NotNull final TaskFile taskFile, - @NotNull final Project project) { - final VirtualFile virtualFile = taskDir.findFileByRelativePath(taskFileName); - if (virtualFile == null) { - return; - } - Pair pair = getCopyWithAnswers(taskDir, virtualFile, taskFile); - if (pair == null) { - return; - } - VirtualFile answerFile = pair.getFirst(); - TaskFile answerTaskFile = pair.getSecond(); - try { - for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) { - final Document document = FileDocumentManager.getInstance().getDocument(virtualFile); - if (document == null) { - continue; - } - StudySmartChecker.smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner, - virtualFile, document); - } - } - finally { - StudyUtils.deleteFile(answerFile); - } - } - - - private static Pair getCopyWithAnswers(@NotNull final VirtualFile taskDir, - @NotNull final VirtualFile file, - @NotNull final TaskFile source) { - try { - VirtualFile answerFile = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension()); - final FileDocumentManager documentManager = FileDocumentManager.getInstance(); - final Document document = documentManager.getDocument(answerFile); - if (document != null) { - TaskFile answerTaskFile = source.getTask().copy().getTaskFile(StudyUtils.pathRelativeToTask(file)); - if (answerTaskFile == null) { - return null; - } - EduDocumentListener listener = new EduDocumentListener(answerTaskFile); - document.addDocumentListener(listener); - for (AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) { - final int start = answerPlaceholder.getOffset(); - final int end = start + answerPlaceholder.getRealLength(); - final String text = answerPlaceholder.getPossibleAnswer(); - document.replaceString(start, end, text); - } - ApplicationManager.getApplication().runWriteAction(() -> documentManager.saveDocument(document)); - return Pair.create(answerFile, answerTaskFile); - } - } - catch (IOException e) { - LOG.error(e); - } - return null; - } - - public static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) { for (Map.Entry entry : task.getTaskFiles().entrySet()) { String name = entry.getKey(); diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java index bd224e42f31c..758dd36fe94e 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java @@ -19,6 +19,7 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; import com.intellij.util.PathUtil; import com.jetbrains.edu.coursecreator.settings.CCSettings; +import com.jetbrains.edu.learning.checker.PyStudyTaskChecker; import com.jetbrains.edu.learning.checker.StudyTaskChecker; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.courseFormat.Course; diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java similarity index 57% rename from python/educational-core/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java rename to python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java index daa1d3491eb5..59c850b661e6 100644 --- a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java @@ -8,6 +8,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.jetbrains.edu.learning.StudyTaskManager; @@ -23,12 +24,12 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; -public class StudySmartChecker { - private StudySmartChecker() { +public class PyStudySmartChecker { + private PyStudySmartChecker() { } - private static final Logger LOG = Logger.getInstance(StudySmartChecker.class); + private static final Logger LOG = Logger.getInstance(PyStudySmartChecker.class); public static void smartCheck(@NotNull final AnswerPlaceholder placeholder, @NotNull final Project project, @@ -80,4 +81,64 @@ public class StudySmartChecker { StudyUtils.deleteFile(fileWindows); } } + + public static void runSmartTestProcess(@NotNull final VirtualFile taskDir, + @NotNull final StudyTestRunner testRunner, + @NotNull final String taskFileName, + @NotNull final TaskFile taskFile, + @NotNull final Project project) { + final VirtualFile virtualFile = taskDir.findFileByRelativePath(taskFileName); + if (virtualFile == null) { + return; + } + Pair pair = getCopyWithAnswers(taskDir, virtualFile, taskFile); + if (pair == null) { + return; + } + VirtualFile answerFile = pair.getFirst(); + TaskFile answerTaskFile = pair.getSecond(); + try { + for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) { + final Document document = FileDocumentManager.getInstance().getDocument(virtualFile); + if (document == null) { + continue; + } + smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner, + virtualFile, document); + } + } + finally { + StudyUtils.deleteFile(answerFile); + } + } + + private static Pair getCopyWithAnswers(@NotNull final VirtualFile taskDir, + @NotNull final VirtualFile file, + @NotNull final TaskFile source) { + try { + VirtualFile answerFile = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension()); + final FileDocumentManager documentManager = FileDocumentManager.getInstance(); + final Document document = documentManager.getDocument(answerFile); + if (document != null) { + TaskFile answerTaskFile = source.getTask().copy().getTaskFile(StudyUtils.pathRelativeToTask(file)); + if (answerTaskFile == null) { + return null; + } + EduDocumentListener listener = new EduDocumentListener(answerTaskFile); + document.addDocumentListener(listener); + for (AnswerPlaceholder answerPlaceholder : answerTaskFile.getActivePlaceholders()) { + final int start = answerPlaceholder.getOffset(); + final int end = start + answerPlaceholder.getRealLength(); + final String text = answerPlaceholder.getPossibleAnswer(); + document.replaceString(start, end, text); + } + ApplicationManager.getApplication().runWriteAction(() -> documentManager.saveDocument(document)); + return Pair.create(answerFile, answerTaskFile); + } + } + catch (IOException e) { + LOG.error(e); + } + return null; + } } diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyTaskChecker.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java similarity index 94% rename from python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyTaskChecker.java rename to python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java index f50016c2fe89..909a3ecb4f90 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyTaskChecker.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java @@ -1,4 +1,4 @@ -package com.jetbrains.edu.learning; +package com.jetbrains.edu.learning.checker; import com.intellij.execution.ExecutionException; import com.intellij.openapi.application.ApplicationManager; @@ -6,8 +6,10 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.StudyState; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.actions.StudyCheckAction; -import com.jetbrains.edu.learning.checker.*; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.Course; @@ -90,7 +92,7 @@ public class PyStudyTaskChecker extends StudyTaskChecker { if (course != null && EduNames.STUDY.equals(course.getCourseMode())) { CommandProcessor.getInstance().runUndoTransparentAction( () -> ApplicationManager.getApplication().runWriteAction( - () -> StudyCheckUtils.runSmartTestProcess(taskDir, new PyStudyTestRunner(myTask, taskDir), name, taskFile, myProject))); + () -> PyStudySmartChecker.runSmartTestProcess(taskDir, new PyStudyTestRunner(myTask, taskDir), name, taskFile, myProject))); } } StudyCheckUtils.navigateToFailedPlaceholder(new StudyState(StudyUtils.getSelectedStudyEditor(myProject)), myTask, taskDir, myProject); diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java similarity index 96% rename from python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java rename to python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java index e8c506d64025..b111077d23f4 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyTestRunner.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java @@ -1,4 +1,4 @@ -package com.jetbrains.edu.learning; +package com.jetbrains.edu.learning.checker; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; @@ -8,7 +8,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.edu.learning.checker.StudyTestRunner; +import com.jetbrains.edu.learning.PyEduPluginConfigurator; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.courseFormat.tasks.Task; import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks; From 237c90e318ecb862bfd53d55d7958587a6d81059 Mon Sep 17 00:00:00 2001 From: "Liana.Bakradze" Date: Thu, 20 Apr 2017 19:22:28 +0300 Subject: [PATCH 04/27] remove redundant interface --- .../edu/learning/checker/StudyTestRunner.java | 22 ------------------- .../learning/checker/PyStudySmartChecker.java | 4 ++-- .../learning/checker/PyStudyTaskChecker.java | 2 +- .../learning/checker/PyStudyTestRunner.java | 8 ++++--- 4 files changed, 8 insertions(+), 28 deletions(-) delete mode 100644 python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java deleted file mode 100644 index 9fd0b70a232a..000000000000 --- a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTestRunner.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.jetbrains.edu.learning.checker; - -import com.intellij.execution.ExecutionException; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.edu.learning.courseFormat.tasks.Task; -import org.jetbrains.annotations.NotNull; - -public abstract class StudyTestRunner {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(@NotNull final Project project, @NotNull final String executablePath) throws ExecutionException; - - public abstract GeneralCommandLine getCommandLine(); - -} diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java index 59c850b661e6..0848d459bebe 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java @@ -36,7 +36,7 @@ public class PyStudySmartChecker { @NotNull final VirtualFile answerFile, @NotNull final TaskFile answerTaskFile, @NotNull final TaskFile usersTaskFile, - @NotNull final StudyTestRunner testRunner, + @NotNull final PyStudyTestRunner testRunner, @NotNull final VirtualFile virtualFile, @NotNull final Document usersDocument) { VirtualFile fileWindows = null; @@ -83,7 +83,7 @@ public class PyStudySmartChecker { } public static void runSmartTestProcess(@NotNull final VirtualFile taskDir, - @NotNull final StudyTestRunner testRunner, + @NotNull final PyStudyTestRunner testRunner, @NotNull final String taskFileName, @NotNull final TaskFile taskFile, @NotNull final Project project) { diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java index 909a3ecb4f90..6b2f117354e8 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTaskChecker.java @@ -46,7 +46,7 @@ public class PyStudyTaskChecker extends StudyTaskChecker { StudyCheckUtils.flushWindows(myTask, taskDir); latch.countDown(); })); - final StudyTestRunner testRunner = new PyStudyTestRunner(myTask, taskDir); + final PyStudyTestRunner testRunner = new PyStudyTestRunner(myTask, taskDir); try { final VirtualFile fileToCheck = getTaskVirtualFile(myTask, taskDir); if (fileToCheck != null) { diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java index b111077d23f4..ea3bcb7a511c 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java @@ -18,12 +18,15 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.Map; -public class PyStudyTestRunner extends StudyTestRunner { +public class PyStudyTestRunner { private static final String PYTHONPATH = "PYTHONPATH"; + @NotNull private final Task myTask; + @NotNull private final VirtualFile myTaskDir; private GeneralCommandLine myCommandLine; PyStudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) { - super(task, taskDir); + myTask = task; + myTaskDir = taskDir; } public Process createCheckProcess(@NotNull final Project project, @NotNull final String executablePath) throws ExecutionException { @@ -56,7 +59,6 @@ public class PyStudyTestRunner extends StudyTestRunner { return null; } - @Override public GeneralCommandLine getCommandLine() { return myCommandLine; } From b4bf5c63ddf78f1c1a6fd4d305b6dfcda42bd192 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 20 Apr 2017 19:23:46 +0300 Subject: [PATCH 05/27] Find in Path: better wording for error message in case of empty search text --- platform/lang-impl/src/com/intellij/find/impl/FindDialog.java | 2 +- .../lang-impl/src/com/intellij/find/impl/FindPopupPanel.java | 2 +- .../platform-resources-en/src/messages/FindBundle.properties | 1 + 3 files changed, 3 insertions(+), 2 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 d24cd4b17486..dd807c292b17 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java @@ -820,7 +820,7 @@ public class FindDialog extends DialogWrapper implements FindUI { } if (!myHelper.canSearchThisString()) { - return new ValidationInfo("String to find is empty", myInputComboBox); + return new ValidationInfo(FindBundle.message("find.empty.search.text.error"), myInputComboBox); } if (myCbRegularExpressions != null && myCbRegularExpressions.isSelected() && myCbRegularExpressions.isEnabled()) { diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java b/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java index d0edd3d747cb..db900b681a2a 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java @@ -896,7 +896,7 @@ public class FindPopupPanel extends JBPanel implements FindUI, DataProvider { } if (!myHelper.canSearchThisString()) { - return new ValidationInfo("String to find is empty", mySearchComponent); + return new ValidationInfo(FindBundle.message("find.empty.search.text.error"), mySearchComponent); } if (myCbRegularExpressions != null && myCbRegularExpressions.isSelected() && myCbRegularExpressions.isEnabled()) { diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties index 341d047cc743..2b2c613ee639 100644 --- a/platform/platform-resources-en/src/messages/FindBundle.properties +++ b/platform/platform-resources-en/src/messages/FindBundle.properties @@ -84,6 +84,7 @@ find.context.presentation.scope.label=\u0020({0}) find.directory.not.found.error=Directory \"{0}\" is not found find.invalid.regular.expression.error=Bad pattern \"{0}\": {1} find.empty.match.regular.expression.error=Regular expression matches empty string +find.empty.search.text.error=No search text entered find.filter.invalid.file.mask.error=Bad file mask \"{0}\" find.filter.empty.file.mask.error=Empty file mask find.options.case.sensitive=&Case sensitive From 6701f2562e1a270481d13d3922f2d6140c834167 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Thu, 20 Apr 2017 19:34:36 +0300 Subject: [PATCH 06/27] method chain completion: suggest arrays/collections on 2nd invocation --- .../compiler/chainsSearch/ChainsSearcher.java | 11 +++++++++- .../MethodsChainsCompletionContributor.java | 16 ++++++++------ .../context/ChainCompletionContext.java | 5 ++++- .../chainsSearch/context/TargetType.java | 22 ++++++++++++------- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/ChainsSearcher.java b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/ChainsSearcher.java index 6de36488de64..6815804f36b5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/ChainsSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/ChainsSearcher.java @@ -57,7 +57,16 @@ public class ChainsSearcher { private static SearchInitializer createInitializer(TargetType target, CompilerReferenceServiceEx compilerReferenceServiceEx, ChainCompletionContext context) { - SortedSet> methods = compilerReferenceServiceEx.findMethodReferenceOccurrences(target.getClassQName(), target.getArrayKind()); + SortedSet> methods = null; + for (byte kind : target.getArrayKind()) { + SortedSet> currentMethods = + compilerReferenceServiceEx.findMethodReferenceOccurrences(target.getClassQName(), kind); + if (methods == null) { + methods = currentMethods; + } else { + methods.addAll(currentMethods); + } + } return new SearchInitializer(methods, context); } diff --git a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/completion/MethodsChainsCompletionContributor.java b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/completion/MethodsChainsCompletionContributor.java index a7865ca539dd..89c114230817 100644 --- a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/completion/MethodsChainsCompletionContributor.java +++ b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/completion/MethodsChainsCompletionContributor.java @@ -116,10 +116,10 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { LOG.assertTrue(parent != null, "A completion position should match to a pattern"); if (parent instanceof PsiAssignmentExpression) { - return extractContextFromAssignment((PsiAssignmentExpression)parent); + return extractContextFromAssignment((PsiAssignmentExpression)parent, parameters); } if (parent instanceof PsiLocalVariable) { - return extractContextFromVariable((PsiLocalVariable)parent); + return extractContextFromVariable((PsiLocalVariable)parent, parameters); } PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod(); if (method == null) return null; @@ -130,23 +130,25 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { PsiParameter[] methodParameters = method.getParameterList().getParameters(); if (exprPosition < methodParameters.length) { PsiParameter methodParameter = methodParameters[exprPosition]; - return ChainCompletionContext.createContext(methodParameter.getType(), PsiTreeUtil.getParentOfType(expression, PsiDeclarationStatement.class)); + return ChainCompletionContext.createContext(methodParameter.getType(), PsiTreeUtil.getParentOfType(expression, PsiDeclarationStatement.class), suggestIterators(parameters)); } return null; } @Nullable - private static ChainCompletionContext extractContextFromVariable(PsiLocalVariable localVariable) { + private static ChainCompletionContext extractContextFromVariable(PsiLocalVariable localVariable, + CompletionParameters parameters) { PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(localVariable, PsiDeclarationStatement.class); - return ChainCompletionContext.createContext(localVariable.getType(), declaration); + return ChainCompletionContext.createContext(localVariable.getType(), declaration, suggestIterators(parameters)); } @Nullable - private static ChainCompletionContext extractContextFromAssignment(PsiAssignmentExpression assignmentExpression) { + private static ChainCompletionContext extractContextFromAssignment(PsiAssignmentExpression assignmentExpression, + CompletionParameters parameters) { if (!(assignmentExpression instanceof PsiReferenceExpression)) return null; PsiElement resolved = ((PsiReferenceExpression)assignmentExpression).resolve(); return resolved instanceof PsiVariable - ? ChainCompletionContext.createContext(((PsiVariable)resolved).getType(), assignmentExpression) + ? ChainCompletionContext.createContext(((PsiVariable)resolved).getType(), assignmentExpression, suggestIterators(parameters)) : null; } diff --git a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/ChainCompletionContext.java b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/ChainCompletionContext.java index 665cc6726abf..f2bfd944f882 100644 --- a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/ChainCompletionContext.java +++ b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/ChainCompletionContext.java @@ -161,10 +161,13 @@ public class ChainCompletionContext { @Nullable public static ChainCompletionContext createContext(@Nullable PsiType targetType, - @Nullable PsiElement containingElement) { + @Nullable PsiElement containingElement, boolean suggestIterators) { if (containingElement == null) return null; TargetType target = TargetType.create(targetType); if (target == null) return null; + if (suggestIterators) { + target = target.toIterators(); + } ContextProcessor processor = new ContextProcessor(null, containingElement.getProject(), containingElement); PsiScopesUtil.treeWalkUp(processor, containingElement, containingElement.getContainingFile()); diff --git a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/TargetType.java b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/TargetType.java index b3ee0f1d2e13..37ff8525c3b8 100644 --- a/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/TargetType.java +++ b/java/compiler/impl/src/com/intellij/compiler/chainsSearch/context/TargetType.java @@ -26,14 +26,14 @@ import org.jetbrains.jps.backwardRefs.SignatureData; */ public class TargetType { private final String myClassQName; - private final byte myArrayKind; + private final byte[] myAcceptedArrayKinds; private final PsiType myPsiType; public TargetType(String classQName, - byte arrayKind, + byte[] arrayKinds, PsiType targetType) { myClassQName = classQName; - myArrayKind = arrayKind; + myAcceptedArrayKinds = arrayKinds; myPsiType = targetType; } @@ -41,15 +41,21 @@ public class TargetType { return myClassQName; } - @SignatureData.IteratorKind - public byte getArrayKind() { - return myArrayKind; + //@SignatureData.IteratorKind + public byte[] getArrayKind() { + return myAcceptedArrayKinds; } public PsiClass getTargetClass() { return PsiUtil.resolveClassInType(myPsiType); } + public TargetType toIterators() { + return myAcceptedArrayKinds.length == 1 && myAcceptedArrayKinds[0] == SignatureData.ZERO_DIM ? + new TargetType(myClassQName, new byte[]{SignatureData.ARRAY_ONE_DIM, SignatureData.ITERATOR_ONE_DIM}, myPsiType) : + this; + } + @Nullable public static TargetType create(PsiType type) { if (type instanceof PsiArrayType) { @@ -69,7 +75,7 @@ public class TargetType { if (aClass == null) return null; String targetQName = aClass.getQualifiedName(); if (targetQName == null) return null; - return new TargetType(targetQName, SignatureData.ARRAY_ONE_DIM, arrayType); + return new TargetType(targetQName, new byte[] {SignatureData.ARRAY_ONE_DIM}, arrayType); } @Nullable @@ -90,7 +96,7 @@ public class TargetType { if (classQName == null) { return null; } - return new TargetType(classQName, iteratorKind, classType); + return new TargetType(classQName, new byte[] {iteratorKind}, classType); } public static String getIteratorKind(PsiClass resolvedClass) { From c40c52e08d0d30031b465a1030280ac4057c54b9 Mon Sep 17 00:00:00 2001 From: "Liana.Bakradze" Date: Thu, 20 Apr 2017 19:39:57 +0300 Subject: [PATCH 07/27] cleanup --- .../edu/learning/checker/PyStudySmartChecker.java | 8 ++++---- .../jetbrains/edu/learning/checker/PyStudyTestRunner.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java index 0848d459bebe..dd7ad5143b2c 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudySmartChecker.java @@ -24,14 +24,14 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; -public class PyStudySmartChecker { +class PyStudySmartChecker { private PyStudySmartChecker() { } private static final Logger LOG = Logger.getInstance(PyStudySmartChecker.class); - public static void smartCheck(@NotNull final AnswerPlaceholder placeholder, + private static void smartCheck(@NotNull final AnswerPlaceholder placeholder, @NotNull final Project project, @NotNull final VirtualFile answerFile, @NotNull final TaskFile answerTaskFile, @@ -82,7 +82,7 @@ public class PyStudySmartChecker { } } - public static void runSmartTestProcess(@NotNull final VirtualFile taskDir, + static void runSmartTestProcess(@NotNull final VirtualFile taskDir, @NotNull final PyStudyTestRunner testRunner, @NotNull final String taskFileName, @NotNull final TaskFile taskFile, @@ -112,7 +112,7 @@ public class PyStudySmartChecker { } } - private static Pair getCopyWithAnswers(@NotNull final VirtualFile taskDir, + static Pair getCopyWithAnswers(@NotNull final VirtualFile taskDir, @NotNull final VirtualFile file, @NotNull final TaskFile source) { try { diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java index ea3bcb7a511c..cbcb35c145ae 100644 --- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java +++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/checker/PyStudyTestRunner.java @@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.Map; -public class PyStudyTestRunner { +class PyStudyTestRunner { private static final String PYTHONPATH = "PYTHONPATH"; @NotNull private final Task myTask; @NotNull private final VirtualFile myTaskDir; @@ -29,7 +29,7 @@ public class PyStudyTestRunner { myTaskDir = taskDir; } - public Process createCheckProcess(@NotNull final Project project, @NotNull final String executablePath) throws ExecutionException { + Process createCheckProcess(@NotNull final Project project, @NotNull final String executablePath) throws ExecutionException { final Sdk sdk = PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]); PyEduPluginConfigurator configurator = new PyEduPluginConfigurator(); String testsFileName = configurator.getTestFileName(); @@ -59,7 +59,7 @@ public class PyStudyTestRunner { return null; } - public GeneralCommandLine getCommandLine() { + GeneralCommandLine getCommandLine() { return myCommandLine; } } From f0c14961057cd0dca2b756f49b0ea4444ef33dd7 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 20 Apr 2017 19:41:01 +0300 Subject: [PATCH 08/27] fix blinking JavaFileEditorManagerTest.testFoldingIsNotBlinkingOnNavigationToSingleLineMethod test --- .../openapi/fileEditor/FileEditorManager.java | 9 +++- .../fileEditor/OpenFileDescriptor.java | 50 ++++++++++--------- .../fileEditor/ex/FileEditorManagerEx.java | 7 ++- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java index 010c6c5df242..7fae225f1993 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -198,4 +198,11 @@ public abstract class FileEditorManager { * {@link FileEditorProvider#getEditorTypeId()} */ public abstract void setSelectedEditor(@NotNull VirtualFile file, @NotNull String fileEditorProviderId); + + /** + * {@link FileEditorManager} supports asynchronous opening of text editors, i.e. when one of 'openFile' methods returns, returned + * editor might not be fully initialized yet. This method allows to delay (if needed) execution of given runnable until editor is + * fully loaded. + */ + public abstract void runWhenLoaded(@NotNull Editor editor, @NotNull Runnable runnable); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java index 7f1d0d8e62fa..e4f64cfda5d9 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -146,10 +146,12 @@ public class OpenFileDescriptor implements Navigatable, Comparable { + unfoldCurrentLine(e); + if (focusEditor) { + IdeFocusManager.getInstance(myProject).requestFocus(e.getContentComponent(), true); + } + }); } } return !editors.isEmpty(); @@ -166,28 +168,30 @@ public class OpenFileDescriptor implements Navigatable, Comparable= 0) { - LogicalPosition pos = new LogicalPosition(myLogicalLine, Math.max(myLogicalColumn, 0)); - if (offset < 0 || offset == e.logicalPositionToOffset(pos)) { + FileEditorManager.getInstance(myProject).runWhenLoaded(e, () -> { + final int offset = getOffset(); + CaretModel caretModel = e.getCaretModel(); + boolean caretMoved = false; + if (myLogicalLine >= 0) { + LogicalPosition pos = new LogicalPosition(myLogicalLine, Math.max(myLogicalColumn, 0)); + if (offset < 0 || offset == e.logicalPositionToOffset(pos)) { + caretModel.removeSecondaryCarets(); + caretModel.moveToLogicalPosition(pos); + caretMoved = true; + } + } + if (!caretMoved && offset >= 0) { caretModel.removeSecondaryCarets(); - caretModel.moveToLogicalPosition(pos); + caretModel.moveToOffset(Math.min(offset, e.getDocument().getTextLength())); caretMoved = true; } - } - if (!caretMoved && offset >= 0) { - caretModel.removeSecondaryCarets(); - caretModel.moveToOffset(Math.min(offset, e.getDocument().getTextLength())); - caretMoved = true; - } - if (caretMoved) { - e.getSelectionModel().removeSelection(); - scrollToCaret(e); - unfoldCurrentLine(e); - } + if (caretMoved) { + e.getSelectionModel().removeSelection(); + scrollToCaret(e); + unfoldCurrentLine(e); + } + }); } protected static void unfoldCurrentLine(@NotNull final Editor editor) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java index 95117ded2f16..23dd6c6b9365 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2017 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,6 +26,7 @@ import com.intellij.openapi.fileEditor.impl.EditorComposite; import com.intellij.openapi.fileEditor.impl.EditorWindow; import com.intellij.openapi.fileEditor.impl.EditorsSplitters; import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; +import com.intellij.openapi.fileEditor.impl.text.AsyncEditorLoader; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; @@ -208,4 +209,8 @@ public abstract class FileEditorManagerEx extends FileEditorManager implements B @NotNull public abstract ActionCallback notifyPublisher(@NotNull Runnable runnable); + @Override + public void runWhenLoaded(@NotNull Editor editor, @NotNull Runnable runnable) { + AsyncEditorLoader.performWhenLoaded(editor, runnable); + } } From 31f8809024c38f68f160ff0e7e95dfc16d3f06ec Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Thu, 20 Apr 2017 19:52:22 +0300 Subject: [PATCH 09/27] ImplicitSubclassInspection-related typo and style-fixes --- .../ImplementedAtRuntimeConditionImpl.java | 3 ++- .../inheritance/ImplicitSubclassInspection.kt | 6 ++--- .../inheritance/ImplicitSubclassProvider.java | 22 ++++++++-------- .../codeInsight/MetaAnnotationUtil.java | 26 +++++++++++-------- .../src/messages/InspectionsBundle.properties | 10 +++---- .../idea/devkit/DevKitBundle.properties | 2 +- .../DevKitImplicitSubclassProvider.java | 2 +- resources/src/META-INF/IdeaPlugin.xml | 2 +- 8 files changed, 39 insertions(+), 34 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplementedAtRuntimeConditionImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplementedAtRuntimeConditionImpl.java index 78520d6835be..8456bd228770 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplementedAtRuntimeConditionImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplementedAtRuntimeConditionImpl.java @@ -23,8 +23,9 @@ public class ImplementedAtRuntimeConditionImpl extends ImplementedAtRuntimeCondi @Override public boolean isImplementedAtRuntime(@NotNull PsiClass psiClass) { for (ImplicitSubclassProvider provider : ImplicitSubclassProvider.EP_NAME.getExtensions()) { - if(provider.providesSubclassFor(psiClass)) + if (provider.providesSubclassFor(psiClass)) { return true; + } } return false; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt index 8880ae4cf8a5..a537975a67f5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassInspection.kt @@ -56,7 +56,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() { problemTargets(aClass).forEach { problems.add(manager.createProblemDescriptor( - it, classReasonToBeSubclassed ?: InspectionsBundle.message("inspection.implicitsubclass.display.forClass", aClass.name), isOnTheFly, + it, classReasonToBeSubclassed ?: InspectionsBundle.message("inspection.implicit.subclass.display.forClass", aClass.name), isOnTheFly, classFixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING) ) @@ -114,9 +114,9 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() { override fun getFamilyName(): String = QuickFixBundle.message("fix.modifiers.family") override fun getText() = if (uDeclaration is UClass) - InspectionsBundle.message("inspection.implicitsubclass.make.class.extendable") + InspectionsBundle.message("inspection.implicit.subclass.make.class.extendable") else - InspectionsBundle.message("inspection.implicitsubclass.extendable", hintName) + InspectionsBundle.message("inspection.implicit.subclass.extendable", hintName) override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassProvider.java b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassProvider.java index b8d384596a2c..69cbea4cce60 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassProvider.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/inheritance/ImplicitSubclassProvider.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable; /** - * Provides information about classes/interfaces that will be implicitly subclassed/implemented by runtime, + * Provides information about classes/interfaces that will be implicitly subclassed/implemented at runtime, * e.g. by some framework (CGLIB Proxy in Spring). * * @author Nicolay Mitropolsky @@ -38,7 +38,7 @@ public abstract class ImplicitSubclassProvider { * Checks if this provider could probably provide a subclass for passed psiClass. * Note: this check is expected to be cheap. If it requires long computations then it is better just to return true. * - * @param psiClass a class to check for possible subclass + * @param psiClass a class to check for possible subclass. * @return {@code false} if definitely no subclass will be created for the psiClass and all further checks could be skipped; * {@code true} if a subclass for the psiClass will probably be created, * and then you should check {@link #findOverridingReason(PsiMethod)} and {@link #findOverridingReason(PsiMethod)} @@ -47,14 +47,14 @@ public abstract class ImplicitSubclassProvider { public abstract boolean isApplicableTo(@NotNull PsiClass psiClass); /** - * Checks if this provider will implicitly subclass passed class + * Checks if this provider will implicitly subclass passed class. * Note: this method could be computationally costly because in some cases it could require deep annotations checks * not only for class but also for all it's methods. - * default implementations doesn't check methods, so implementors should override this methods if target framework - * makes decision about overriding basing on methods annotations + * Default implementations don't check methods, so implementors should override this methods if target framework + * makes decision about overriding basing on methods annotations. * - * @param psiClass a class to check for possible subclass - * @return true if class will be subclassed, false - otherwise + * @param psiClass a class to check for possible subclass. + * @return true if class will be subclassed, false - otherwise. */ public boolean providesSubclassFor(@NotNull PsiClass psiClass) { return isApplicableTo(psiClass) && findSubclassingReason(psiClass) != null; @@ -64,8 +64,8 @@ public abstract class ImplicitSubclassProvider { * Note: assumes that you have called {@link #isApplicableTo(PsiClass)} and will not check it again. * So you can get wrong results if you haven't check. * - * @param psiClass a class to check for possible subclass - * @return explanation why this class will be implicitly subclassed, or {@code null} if it will not be subclassed + * @param psiClass a class to check for possible subclass. + * @return explanation why this class will be implicitly subclassed, or {@code null} if it will not be subclassed. */ @Nls @Nullable @@ -75,8 +75,8 @@ public abstract class ImplicitSubclassProvider { * Note: assumes that you have called {@link #isApplicableTo(PsiClass)} and will not check it again. * So you can get wrong results if you haven't check. * - * @param psiMethod a method to check for implicit override - * @return explanation why this method will be implicitly overridden, or {@code null} if it will not be overridden + * @param psiMethod a method to check for implicit override. + * @return explanation why this method will be implicitly overridden, or {@code null} if it will not be overridden. */ @Nls @Nullable diff --git a/java/openapi/src/com/intellij/codeInsight/MetaAnnotationUtil.java b/java/openapi/src/com/intellij/codeInsight/MetaAnnotationUtil.java index 911a7d2695be..33d0d17847b6 100644 --- a/java/openapi/src/com/intellij/codeInsight/MetaAnnotationUtil.java +++ b/java/openapi/src/com/intellij/codeInsight/MetaAnnotationUtil.java @@ -159,8 +159,8 @@ public class MetaAnnotationUtil { final List resolvedAnnotations = getResolvedClassesInAnnotationsList(listOwner); for (String annotationFQN : annotations) { - for (PsiClass psiClass : resolvedAnnotations) { - if (metaAnnotationCached(annotationFQN, psiClass) != null) return true; + for (PsiClass resolvedAnnotation : resolvedAnnotations) { + if (metaAnnotationCached(resolvedAnnotation, annotationFQN) != null) return true; } } @@ -168,11 +168,12 @@ public class MetaAnnotationUtil { } @Nullable - private static PsiAnnotation metaAnnotationCached(String annotationFQN, PsiClass psiClass) { - ConcurrentFactoryMap cachedValue = CachedValuesManager.getCachedValue(psiClass, () -> - new CachedValueProvider.Result<>(ConcurrentFactoryMap.createConcurrentMap(anno -> findMetaAnnotation(psiClass, anno, new HashSet<>())), - PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT)); - return cachedValue.get(annotationFQN); + private static PsiAnnotation metaAnnotationCached(PsiClass subjectAnnotation, String annotationToFind) { + ConcurrentFactoryMap cachedValue = CachedValuesManager.getCachedValue(subjectAnnotation, () -> { + ConcurrentFactoryMap metaAnnotationsMap = ConcurrentFactoryMap.createConcurrentMap(anno -> findMetaAnnotation(subjectAnnotation, anno, new HashSet<>())); + return new CachedValueProvider.Result<>(metaAnnotationsMap, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); + }); + return cachedValue.get(annotationToFind); } @Nullable @@ -201,14 +202,17 @@ public class MetaAnnotationUtil { Stream directAnnotations = Stream.of(AnnotationUtil.findAnnotations(listOwner, annotations)); - Stream metannotations = + Stream lazyResolvedAnnotations = Stream.generate(() -> getResolvedClassesInAnnotationsList(listOwner)).limit(1) - .flatMap(e -> e.stream()) + .flatMap(e -> e.stream()); + + Stream metaAnnotations = + lazyResolvedAnnotations .flatMap(psiClass -> annotations.stream() - .map(annotationFQN -> metaAnnotationCached(annotationFQN, psiClass))) + .map(annotationFQN -> metaAnnotationCached(psiClass, annotationFQN))) .filter(Objects::nonNull); - return Stream.concat(directAnnotations, metannotations); + return Stream.concat(directAnnotations, metaAnnotations); } diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 4710fd0d8657..807517bfb3ad 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -825,10 +825,10 @@ inspection.reflection.invocation.argument.not.assignable=Argument is not assigna inspection.reflection.invocation.item.not.assignable=Array item is not assignable to ''{0}'' inspection.reflection.invocation.array.not.assignable=Array {0,choice,1#item has|1 Date: Thu, 20 Apr 2017 20:02:36 +0300 Subject: [PATCH 10/27] properties: cleanup --- .../psi/PropertiesElementFactory.java | 1 - .../PropertiesCodeStyleSettingsProvider.java | 1 - ...AlphaUnsortedPropertiesFileInspection.java | 13 +++++----- .../properties/CustomResourceBundleState.java | 4 +-- .../lang/properties/PropertiesAnnotator.java | 2 +- .../editor/ResourceBundleAsVirtualFile.java | 2 +- .../ResourceBundleEditorRenderer.java | 9 ++----- .../parsing/PropertiesElementTypes.java | 1 - .../parsing/PropertiesParserDefinition.java | 1 - .../properties/psi/impl/PropertyImpl.java | 26 ++++++++----------- .../psi/impl/PropertyValueImpl.java | 2 +- .../PropertiesFileStructureViewElement.java | 4 +-- .../PropertiesStructureViewElement.java | 5 ---- .../properties/xml/XmlPropertiesFileImpl.java | 3 +-- .../properties/xml/XmlPropertiesIndex.java | 6 ++--- .../lang/properties/xml/XmlProperty.java | 1 - 16 files changed, 27 insertions(+), 54 deletions(-) diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java index b9368659e476..ebf1fd7f03b5 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java @@ -16,7 +16,6 @@ package com.intellij.lang.properties.psi; -import com.intellij.lang.ASTNode; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.PropertiesFileType; import com.intellij.lang.properties.psi.codeStyle.PropertiesCodeStyleSettings; diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java index 7746d66f670d..4fc365e81cc4 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java @@ -33,7 +33,6 @@ public class PropertiesCodeStyleSettingsProvider extends CodeStyleSettingsProvid @Override public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { return new CodeStyleAbstractConfigurable(settings, originalSettings, "Properties Files") { - @Nullable @Override public String getHelpTopic() { return "reference.settingsdialog.codestyle.properties"; diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java b/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java index a52477db4574..385a7fa4bd44 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java @@ -63,12 +63,13 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool { if (!isResourceBundleAlphaSortedExceptOneFile(resourceBundle, propertiesFile)) { final List allFiles = resourceBundle.getPropertiesFiles(); holder.registerProblem(file, String.format(MESSAGE_TEMPLATE_WHOLE_RESOURCE_BUNDLE, resourceBundleBaseName), - ProblemHighlightType.INFO, - new PropertiesSorterQuickFix(true, allFiles.toArray(new PropertiesFile[allFiles.size()]))); + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + new PropertiesSorterQuickFix(allFiles.toArray(new PropertiesFile[allFiles.size()]))); return; } if (!propertiesFile.isAlphaSorted()) { - holder.registerProblem(file, "Properties file is alphabetically unsorted", ProblemHighlightType.INFO, new PropertiesSorterQuickFix(true, propertiesFile)); + holder.registerProblem(file, "Properties file is alphabetically unsorted", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new PropertiesSorterQuickFix( + propertiesFile)); } } }; @@ -88,18 +89,16 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool { } private static class PropertiesSorterQuickFix implements LocalQuickFix { - private final boolean myWholeResourceBundle; private final PropertiesFile[] myFilesToSort; - private PropertiesSorterQuickFix(final boolean wholeResourceBundle, PropertiesFile... toSort) { - myWholeResourceBundle = wholeResourceBundle; + private PropertiesSorterQuickFix(PropertiesFile... toSort) { myFilesToSort = toSort; } @NotNull @Override public String getFamilyName() { - return myWholeResourceBundle ? "Sort resource bundle files" : "Sort properties file"; + return "Sort resource bundle files"; } @Override diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java index a44e569ff820..56ac8cf76af4 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/CustomResourceBundleState.java @@ -15,10 +15,8 @@ */ package com.intellij.lang.properties; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; import com.intellij.util.xmlb.annotations.AbstractCollection; @@ -39,7 +37,7 @@ import java.util.Set; public class CustomResourceBundleState { @Property(surroundWithTag = false) - @AbstractCollection(surroundWithTag = false, elementTag = "file", elementValueAttribute = "value") + @AbstractCollection(surroundWithTag = false, elementTag = "file") public Set myFileUrls = new HashSet<>(); @Tag("base-name") diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesAnnotator.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesAnnotator.java index a862ca0c2459..f0ee873ae71c 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesAnnotator.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesAnnotator.java @@ -46,7 +46,7 @@ import java.util.Collection; public class PropertiesAnnotator implements Annotator { public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { - if (!(element instanceof IProperty)) return; + if (!(element instanceof Property)) return; final Property property = (Property)element; PropertiesFile propertiesFile = property.getPropertiesFile(); Collection others = propertiesFile.findPropertiesByKey(property.getUnescapedKey()); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java index 26f83ecd2f76..8afce3dcf1f1 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java @@ -98,7 +98,7 @@ public class ResourceBundleAsVirtualFile extends VirtualFile implements VirtualF @Override public boolean isValid() { - if (myResourceBundle instanceof ResourceBundleImpl && !((ResourceBundleImpl)myResourceBundle).isValid()) { + if (myResourceBundle instanceof ResourceBundleImpl && !myResourceBundle.isValid()) { return false; } for (PropertiesFile propertiesFile : myResourceBundle.getPropertiesFiles()) { diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/inspections/ResourceBundleEditorRenderer.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/inspections/ResourceBundleEditorRenderer.java index 643efc566be4..450d10e020e9 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/inspections/ResourceBundleEditorRenderer.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/inspections/ResourceBundleEditorRenderer.java @@ -15,22 +15,17 @@ */ package com.intellij.lang.properties.editor.inspections; -import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.ide.util.treeView.NodeRenderer; import com.intellij.ide.util.treeView.smartTree.TreeElement; import com.intellij.ide.util.treeView.smartTree.TreeElementWrapper; -import com.intellij.lang.properties.editor.ResourceBundlePropertyStructureViewElement; import com.intellij.navigation.ItemPresentation; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.ui.SimpleTextAttributes; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; -import java.awt.*; /** * @author Dmitry Batkovich @@ -38,7 +33,7 @@ import java.awt.*; public class ResourceBundleEditorRenderer extends NodeRenderer { @Override - public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { if (customize(value)) { return; } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesElementTypes.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesElementTypes.java index 74e182084aa3..acdebb164c5e 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesElementTypes.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesElementTypes.java @@ -22,7 +22,6 @@ import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilderFactory; import com.intellij.lang.properties.PropertiesLanguage; -import com.intellij.lang.properties.PropertiesFileType; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.stubs.IStubElementType; diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParserDefinition.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParserDefinition.java index 23c9a8d43fb0..dceab81adb39 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParserDefinition.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParserDefinition.java @@ -22,7 +22,6 @@ import com.intellij.lang.properties.psi.impl.PropertiesFileImpl; import com.intellij.lang.properties.psi.impl.PropertiesListImpl; import com.intellij.lang.properties.psi.impl.PropertyImpl; import com.intellij.lexer.Lexer; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java index 4e2d7f73c673..fc504092dd05 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java @@ -316,26 +316,22 @@ public class PropertyImpl extends PropertiesStubElementImpl implem off++; } } - else if (aChar == 't') { - if (startSpaces == -1) startSpaces = off; - } - else if (aChar == 'r') { - if (startSpaces == -1) startSpaces = off; - } - else if (aChar == 'n') { - if (startSpaces == -1) startSpaces = off; - } - else if (aChar == 'f') { + else if (aChar == 't' || aChar == 'r') { if (startSpaces == -1) startSpaces = off; } else { - if (Character.isWhitespace(aChar)) { - if (startSpaces == -1) { - startSpaces = off-1; - } + if (aChar == 'n' || aChar == 'f') { + if (startSpaces == -1) startSpaces = off; } else { - startSpaces = -1; + if (Character.isWhitespace(aChar)) { + if (startSpaces == -1) { + startSpaces = off-1; + } + } + else { + startSpaces = -1; + } } } } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyValueImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyValueImpl.java index 079cb86cba26..61f354168d33 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyValueImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyValueImpl.java @@ -33,7 +33,7 @@ public class PropertyValueImpl extends LeafPsiElement { @Override @NotNull public PsiReference[] getReferences() { - return ReferenceProvidersRegistry.getReferencesFromProviders(this, PropertyValueImpl.class); + return ReferenceProvidersRegistry.getReferencesFromProviders(this); } @Override diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesFileStructureViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesFileStructureViewElement.java index d390b838b218..8c0f4611cc4a 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesFileStructureViewElement.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesFileStructureViewElement.java @@ -19,10 +19,8 @@ import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.structureView.impl.common.PsiTreeElementBase; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.editor.ResourceBundleEditorViewElement; -import com.intellij.lang.properties.psi.Property; import com.intellij.lang.properties.psi.impl.PropertiesFileImpl; import com.intellij.navigation.ItemPresentation; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,7 +45,7 @@ public class PropertiesFileStructureViewElement extends PsiTreeElementBase elements = new ArrayList<>(properties.size()); for (IProperty property : properties) { - elements.add(new PropertiesStructureViewElement((Property)property)); + elements.add(new PropertiesStructureViewElement(property)); } return elements; } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesStructureViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesStructureViewElement.java index a27cc54146e1..9c5ad34172e5 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesStructureViewElement.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesStructureViewElement.java @@ -17,18 +17,13 @@ package com.intellij.lang.properties.structureView; import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.lang.properties.IProperty; -import com.intellij.lang.properties.PropertiesHighlighter; import com.intellij.lang.properties.editor.ResourceBundleEditorViewElement; import com.intellij.lang.properties.editor.ResourceBundlePropertyStructureViewElement; -import com.intellij.lang.properties.psi.Property; import com.intellij.navigation.ColoredItemPresentation; import com.intellij.navigation.ItemPresentation; -import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.ui.JBColor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java index 4a7901d7d5ea..0de1485e5248 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java @@ -152,8 +152,7 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { final XmlTag rootTag = myFile.getRootTag(); final XmlTag entry = createPropertyTag(key, value); final XmlTag addedEntry = (XmlTag) (anchorTag == null ? myFile.getRootTag().addSubTag(entry, !addToEnd) : rootTag.addAfter(entry, anchorTag)); - final XmlProperty property = new XmlProperty(addedEntry, this); - return property; + return new XmlProperty(addedEntry, this); } @NotNull diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java index 61787da9a70c..1b559382edb6 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java @@ -34,7 +34,6 @@ import com.intellij.util.text.CharArrayUtil; import com.intellij.util.xml.NanoXmlUtil; import net.n3.nanoxml.StdXMLReader; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.*; import java.util.Collections; @@ -135,11 +134,10 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension Date: Thu, 20 Apr 2017 20:43:10 +0300 Subject: [PATCH 11/27] [gui-test] make editor be a function with a lambda receiver --- .../src/com/intellij/testGuiFramework/impl/GuiTestCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt index a076d82e0345..c8d9f3cd4b89 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestCase.kt @@ -205,7 +205,7 @@ open class GuiTestCase : GuiTestBase() { "Sorry, unable to find PluginTable component with ${target().toString()} as a Container") //*********FIXTURES METHODS FOR IDEFRAME WITHOUT ROBOT and TARGET; KOTLIN ONLY - fun IdeFrameFixture.editor(func: EditorFixture.() -> Unit, /*timeout in seconds*/ timeout: Long = defaultTimeout) { + fun IdeFrameFixture.editor(/*timeout in seconds*/ timeout: Long = defaultTimeout, func: EditorFixture.() -> Unit) { func.invoke(this.editor) } From b7fa03c1cedabc95b342078d0ca6300b4dfd506c Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Thu, 20 Apr 2017 20:58:28 +0300 Subject: [PATCH 12/27] PY-23217: Support django-nose When django nose runner is used we need to: * Use it instead of old TeamCityRunner * Add new (Leonid's) nose plugin to NOSE_PLUGINS so it could report tests in TC protocol --- python/helpers/pycharm/django_test_manage.py | 25 ++++++++++++++++++- python/helpers/pycharm/django_test_runner.py | 8 +++--- python/setup-test-environment/build.gradle | 4 +-- .../universalTests/PyUniversalTests.kt | 2 +- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/python/helpers/pycharm/django_test_manage.py b/python/helpers/pycharm/django_test_manage.py index f06280a909a6..b03a2461cd11 100644 --- a/python/helpers/pycharm/django_test_manage.py +++ b/python/helpers/pycharm/django_test_manage.py @@ -5,7 +5,9 @@ import sys from django.core.management import ManagementUtility +from django_test_runner import is_nosetest from pycharm_run_utils import import_system_module +from teamcity import teamcity_presence_env_var inspect = import_system_module("inspect") @@ -106,7 +108,28 @@ class PycharmTestManagementUtility(ManagementUtility): ManagementUtility.__init__(self, argv) def execute(self): - PycharmTestCommand().run_from_argv(self.argv) + if is_nosetest(settings) and "_JB_USE_OLD_RUNNERS" not in os.environ: + # New way to run django-nose is to install teamcity-runners plugin + # there is no easy way to get qname in 2.7 so string is used + name = "teamcity.nose_report.TeamcityReport" + + # emulate TC to enable plugin + os.environ.update({teamcity_presence_env_var: "1"}) + + # NOSE_PLUGINS could be list or tuple. Adding teamcity plugin to it + try: + settings.NOSE_PLUGINS += [name] + except TypeError: + settings.NOSE_PLUGINS += (name, ) + except AttributeError: + settings.NOSE_PLUGINS = [name] + + # This file is required to init and monkeypatch new runners + # noinspection PyUnresolvedReferences + import _jb_runner_tools + super(PycharmTestManagementUtility, self).execute() + else: + PycharmTestCommand().run_from_argv(self.argv) if __name__ == "__main__": diff --git a/python/helpers/pycharm/django_test_runner.py b/python/helpers/pycharm/django_test_runner.py index 7ee43c4113f0..092d93d75b1e 100644 --- a/python/helpers/pycharm/django_test_runner.py +++ b/python/helpers/pycharm/django_test_runner.py @@ -8,7 +8,7 @@ adjust_django_sys_path() from django.conf import settings -def _is_nosetest(settings): +def is_nosetest(settings): """ Checks if Django configured to work with nosetest @@ -28,7 +28,7 @@ def _is_nosetest(settings): from django.test.testcases import TestCase from django import VERSION -if _is_nosetest(settings): +if is_nosetest(settings): from nose_utils import TeamcityNoseRunner # See: https://docs.djangoproject.com/en/1.8/releases/1.7/#django-utils-unittest @@ -128,7 +128,7 @@ class DjangoTeamcityTestRunner(BaseRunner): return suite def run_suite(self, suite, **kwargs): - if _is_nosetest(settings): + if is_nosetest(settings): from django_nose.plugin import DjangoSetUpPlugin, ResultPlugin from django_nose.runner import _get_plugins_from_settings from nose.config import Config @@ -151,7 +151,7 @@ class DjangoTeamcityTestRunner(BaseRunner): return TeamcityTestRunner.run(self, suite, **self.options) def run_tests(self, test_labels, extra_tests=None, **kwargs): - if _is_nosetest(settings): + if is_nosetest(settings): return super(DjangoTeamcityTestRunner, self).run_tests(test_labels, extra_tests) return super(DjangoTeamcityTestRunner, self).run_tests(test_labels, extra_tests, **kwargs) diff --git a/python/setup-test-environment/build.gradle b/python/setup-test-environment/build.gradle index 719eee4a7040..b432bd7a21b3 100644 --- a/python/setup-test-environment/build.gradle +++ b/python/setup-test-environment/build.gradle @@ -15,8 +15,8 @@ envs { conda "django19", "2.7", ["django==1.9", "tox", "nose", "pytest", "behave", "lettuce>=0.2.22"], true textfile "django19/tags.txt", "python2.7\ndjango\nnose\npytest\nbehave\nlettuce\npackaging\ntox" - conda "django110", "3.4", ["django==1.10"], false - textfile "django110/tags.txt", "python3.4\ndjango\nskeletons" + conda "django110", "3.4", ["django==1.10", "django-nose"], false + textfile "django110/tags.txt", "python3.4\ndjango\nskeletons\ndjango-nose" conda "django111", "3.4", ["django==1.11"], true textfile "django111/tags.txt", "python3.4\ndjango" diff --git a/python/src/com/jetbrains/python/testing/universalTests/PyUniversalTests.kt b/python/src/com/jetbrains/python/testing/universalTests/PyUniversalTests.kt index 84b89bf624bb..0206438bbe36 100644 --- a/python/src/com/jetbrains/python/testing/universalTests/PyUniversalTests.kt +++ b/python/src/com/jetbrains/python/testing/universalTests/PyUniversalTests.kt @@ -115,7 +115,7 @@ private fun findConfigurationFactoryFromSettings(module: Module): ConfigurationF // folder provided by python side. Resolve test names versus it private val PATH_URL = Pattern.compile("^python<([^<>]+)>$") -private object PyUniversalTestsLocator : SMTestLocator { +object PyUniversalTestsLocator : SMTestLocator { override fun getLocation(protocol: String, path: String, project: Project, scope: GlobalSearchScope): List> { if (scope !is ModuleWithDependenciesScope) { return listOf() From 3d66278a2590de6d82b21ea692c1b744086e71d5 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Thu, 20 Apr 2017 21:46:42 +0300 Subject: [PATCH 13/27] Correctly dispose editor instance in AppEditorFontConfigurable --- .../fonts/AppEditorFontConfigurable.java | 28 ++++++++++++++---- .../editor/fonts/AppEditorFontPanel.java | 29 ++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java index ccde0bc19ea6..9f6262d5d0d6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java @@ -23,6 +23,8 @@ import com.intellij.openapi.editor.colors.impl.AppEditorFontOptions; import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.LazyInstance; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +33,12 @@ import javax.swing.*; public class AppEditorFontConfigurable implements SearchableConfigurable { - private AppEditorFontPanel myFontPanel; + private LazyInstance myFontPanelInstance = new LazyInstance() { + @Override + protected Class getInstanceClass() throws ClassNotFoundException { + return AppEditorFontPanel.class; + } + }; @NotNull @Override @@ -42,8 +49,7 @@ public class AppEditorFontConfigurable implements SearchableConfigurable { @Nullable @Override public JComponent createComponent() { - myFontPanel = new AppEditorFontPanel(); - return myFontPanel; + return getFontPanel().getComponent(); } @Override @@ -62,13 +68,13 @@ public class AppEditorFontConfigurable implements SearchableConfigurable { @NotNull private FontPreferences getUIFontPreferences() { - return myFontPanel.getOptionsPanel().getFontPreferences(); + return getFontPanel().getOptionsPanel().getFontPreferences(); } @Override public void reset() { getStoredPreferences().copyTo(getUIFontPreferences()); - myFontPanel.getOptionsPanel().updateOptionsList(); + getFontPanel().getOptionsPanel().updateOptionsList(); } @NotNull @@ -76,9 +82,21 @@ public class AppEditorFontConfigurable implements SearchableConfigurable { return AppEditorFontOptions.getInstance().getFontPreferences(); } + @NotNull + private AppEditorFontPanel getFontPanel() { + return myFontPanelInstance.getValue(); + } + @Nls @Override public String getDisplayName() { return "Default Font"; } + + @Override + public void disposeUIResources() { + if (myFontPanelInstance.isComputed()) { + Disposer.dispose(getFontPanel()); + } + } } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontPanel.java b/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontPanel.java index a172a4894892..942dcf811cd2 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontPanel.java @@ -17,26 +17,29 @@ package com.intellij.application.options.editor.fonts; import com.intellij.application.options.colors.ColorAndFontSettingsListener; import com.intellij.application.options.colors.FontEditorPreview; +import com.intellij.openapi.Disposable; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -public class AppEditorFontPanel extends JPanel { +public class AppEditorFontPanel implements Disposable { - private final AppEditorFontOptionsPanel myOptionsPanel; - private final FontEditorPreview myPreview; - private final EditorColorsScheme myPreviewScheme; + @NotNull private final AppEditorFontOptionsPanel myOptionsPanel; + @NotNull private final FontEditorPreview myPreview; + @NotNull private final EditorColorsScheme myPreviewScheme; + @NotNull private final JPanel myTopPanel; public AppEditorFontPanel() { - super(new BorderLayout(0,10)); + myTopPanel = new JPanel(new BorderLayout(0,10)); myPreviewScheme = createPreviewScheme(); myOptionsPanel = new AppEditorFontOptionsPanel(myPreviewScheme); - add(myOptionsPanel, BorderLayout.NORTH); + myTopPanel.add(myOptionsPanel, BorderLayout.NORTH); myPreview = new FontEditorPreview(()-> myPreviewScheme, true); - add(myPreview.getPanel(), BorderLayout.CENTER); + myTopPanel.add(myPreview.getPanel(), BorderLayout.CENTER); myOptionsPanel.addListener( new ColorAndFontSettingsListener.Abstract() { @Override @@ -47,12 +50,24 @@ public class AppEditorFontPanel extends JPanel { ); } + @Override + public void dispose() { + myPreview.disposeUIResources(); + } + + @NotNull private static EditorColorsScheme createPreviewScheme() { EditorColorsScheme scheme = (EditorColorsScheme)EditorColorsManager.getInstance().getSchemeForCurrentUITheme().clone(); scheme.setFontPreferences(new FontPreferencesImpl()); return scheme; } + @NotNull + public JPanel getComponent() { + return myTopPanel; + } + + @NotNull public AppEditorFontOptionsPanel getOptionsPanel() { return myOptionsPanel; } From b9d17e211db977822e11ab2905a9044c6b28dc16 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Thu, 20 Apr 2017 22:04:04 +0300 Subject: [PATCH 14/27] PY-23785: support unittest2, PY-23846: support dots in subtest names Leonid's runners updated to support unittest2 and dots in subtests --- python/helpers/pycharm/teamcity/unittestpy.py | 25 ++++-- python/setup-test-environment/build.gradle | 4 +- .../env/unit/subtestDots/test_test.py | 9 +++ .../env/unit/unittest2/test_test.py | 10 +++ .../python/testing/PythonUnitTestingTest.java | 76 +++++++++++++++++++ 5 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 python/testData/testRunner/env/unit/subtestDots/test_test.py create mode 100644 python/testData/testRunner/env/unit/unittest2/test_test.py diff --git a/python/helpers/pycharm/teamcity/unittestpy.py b/python/helpers/pycharm/teamcity/unittestpy.py index 90f56e944769..b4176776f3b9 100644 --- a/python/helpers/pycharm/teamcity/unittestpy.py +++ b/python/helpers/pycharm/teamcity/unittestpy.py @@ -17,6 +17,9 @@ class TeamcityTestResult(TestResult): def __init__(self, stream=_real_stdout, descriptions=None, verbosity=None): super(TeamcityTestResult, self).__init__() + # Some code may ask for self.failfast, see unittest2.case.TestCase.subTest + self.failfast = getattr(self, "failfast", False) + self.test_started_datetime_map = {} self.failed_tests = set() self.subtest_failures = {} @@ -40,7 +43,9 @@ class TeamcityTestResult(TestResult): super(TeamcityTestResult, self).addSuccess(test) def addExpectedFailure(self, test, err): - super(TeamcityTestResult, self).addExpectedFailure(test, err) + _super = super(TeamcityTestResult, self) + if hasattr(_super, "addExpectedFailure"): + _super.addExpectedFailure(test, err) err = convert_error_to_string(err) test_id = self.get_test_id(test) @@ -68,7 +73,8 @@ class TeamcityTestResult(TestResult): else: reason_str = "" - if get_class_fullname(test) == "unittest.case._SubTest": + test_class_name = get_class_fullname(test) + if test_class_name == "unittest.case._SubTest" or test_class_name == "unittest2.case._SubTest": parent_test = test.test_case parent_test_id = self.get_test_id(parent_test) subtest = test @@ -83,7 +89,9 @@ class TeamcityTestResult(TestResult): self.messages.testIgnored(test_id, message="Skipped" + reason_str, flowId=test_id) def addUnexpectedSuccess(self, test): - super(TeamcityTestResult, self).addUnexpectedSuccess(test) + _super = super(TeamcityTestResult, self) + if hasattr(_super, "addUnexpectedSuccess"): + _super.addUnexpectedSuccess(test) test_id = self.get_test_id(test) self.messages.testFailed(test_id, message='Failure', @@ -93,7 +101,8 @@ class TeamcityTestResult(TestResult): def addError(self, test, err, *k): super(TeamcityTestResult, self).addError(test, err) - if get_class_fullname(test) == "unittest.suite._ErrorHolder": + test_class = get_class_fullname(test) + if test_class == "unittest.suite._ErrorHolder" or test_class == "unittest2.suite._ErrorHolder": # This is a standalone error test_name = test.id() @@ -120,13 +129,17 @@ class TeamcityTestResult(TestResult): self.report_fail(test, 'Failure', err) def addSubTest(self, test, subtest, err): - super(TeamcityTestResult, self).addSubTest(test, subtest, err) + _super = super(TeamcityTestResult, self) + if hasattr(_super, "addSubTest"): + _super.addSubTest(test, subtest, err) test_id = self.get_test_id(test) subtest_id = self.get_test_id(subtest) if subtest_id.startswith(test_id): - block_id = subtest_id[len(test_id):].strip() + # Replace "." -> "_" since '.' is a test hierarchy separator + # See i.e. https://github.com/JetBrains/teamcity-messages/issues/134 (https://youtrack.jetbrains.com/issue/PY-23846) + block_id = subtest_id[len(test_id):].strip().replace(".", "_") else: block_id = subtest_id if len(block_id) == 0: diff --git a/python/setup-test-environment/build.gradle b/python/setup-test-environment/build.gradle index b432bd7a21b3..9dfed8f2c777 100644 --- a/python/setup-test-environment/build.gradle +++ b/python/setup-test-environment/build.gradle @@ -12,8 +12,8 @@ envs { packages = ["pip", "setuptools"] _64Bits = true - conda "django19", "2.7", ["django==1.9", "tox", "nose", "pytest", "behave", "lettuce>=0.2.22"], true - textfile "django19/tags.txt", "python2.7\ndjango\nnose\npytest\nbehave\nlettuce\npackaging\ntox" + conda "django19", "2.7", ["django==1.9", "tox", "nose", "pytest", "behave", "lettuce>=0.2.22", "unittest2"], true + textfile "django19/tags.txt", "python2.7\ndjango\nnose\npytest\nbehave\nlettuce\npackaging\ntox\nunittest2" conda "django110", "3.4", ["django==1.10", "django-nose"], false textfile "django110/tags.txt", "python3.4\ndjango\nskeletons\ndjango-nose" diff --git a/python/testData/testRunner/env/unit/subtestDots/test_test.py b/python/testData/testRunner/env/unit/subtestDots/test_test.py new file mode 100644 index 000000000000..7f49f0587bde --- /dev/null +++ b/python/testData/testRunner/env/unit/subtestDots/test_test.py @@ -0,0 +1,9 @@ +import unittest + + +class SampleTest(unittest.TestCase): + + def test_sample(self): + for i in range(10): + with self.subTest(i=str(i)+'.'+str(i)): + self.assertTrue(i > 1) \ No newline at end of file diff --git a/python/testData/testRunner/env/unit/unittest2/test_test.py b/python/testData/testRunner/env/unit/unittest2/test_test.py new file mode 100644 index 000000000000..061c4e82e909 --- /dev/null +++ b/python/testData/testRunner/env/unit/unittest2/test_test.py @@ -0,0 +1,10 @@ + +from unittest2 import TestCase + + +class SampleTest(TestCase): + + def test_sample(self): + for i in range(10): + with self.subTest(i=i): + self.assertTrue(i > 3) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java b/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java index e093598086e3..4a3d2438aa71 100644 --- a/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java +++ b/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java @@ -51,6 +51,82 @@ import static org.junit.Assert.assertEquals; */ public final class PythonUnitTestingTest extends PyEnvTestCase { + + /** + * subtest names may have dots and shall not break test tree + */ + @EnvTestTagsRequired(tags = "python3") + @Test + public void testDotsInSubtest() throws Exception { + runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/subtestDots", "test_test.py") { + + @NotNull + @Override + protected PyUnitTestProcessRunner createProcessRunner() throws Exception { + return new PyUnitTestProcessRunner(toFullPath(myScriptName), 1); + } + + @Override + protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner, + @NotNull final String stdout, + @NotNull final String stderr, + @NotNull final String all) { + runner.getFormattedTestTree(); + assertEquals("dots in subtest names broke output", "Test tree:\n" + + "[root]\n" + + ".test_test\n" + + "..SampleTest\n" + + "...test_sample\n" + + "....(i='0_0')(-)\n" + + "....(i='1_1')(-)\n" + + "....(i='2_2')(+)\n" + + "....(i='3_3')(+)\n" + + "....(i='4_4')(+)\n" + + "....(i='5_5')(+)\n" + + "....(i='6_6')(+)\n" + + "....(i='7_7')(+)\n" + + "....(i='8_8')(+)\n" + + "....(i='9_9')(+)\n", runner.getFormattedTestTree()); + } + }); + } + + @EnvTestTagsRequired(tags = "unittest2") + @Test + public void testUnitTest2() throws Exception { + runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/unittest2", "test_test.py") { + + @NotNull + @Override + protected PyUnitTestProcessRunner createProcessRunner() throws Exception { + return new PyUnitTestProcessRunner(toFullPath(myScriptName), 1); + } + + @Override + protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner, + @NotNull final String stdout, + @NotNull final String stderr, + @NotNull final String all) { + runner.getFormattedTestTree(); + assertEquals("unittest2 produced wrong tree", "Test tree:\n" + + "[root]\n" + + ".test_test\n" + + "..SampleTest\n" + + "...test_sample\n" + + "....(i=0)(-)\n" + + "....(i=1)(-)\n" + + "....(i=2)(-)\n" + + "....(i=3)(-)\n" + + "....(i=4)(+)\n" + + "....(i=5)(+)\n" + + "....(i=6)(+)\n" + + "....(i=7)(+)\n" + + "....(i=8)(+)\n" + + "....(i=9)(+)\n", runner.getFormattedTestTree()); + } + }); + } + // Ensures setup/teardown does not break anything @Test public void testSetupTearDown() throws Exception { From da5f6412712f95b8c8b41f84917e7a31ba8d724e Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 21 Apr 2017 09:51:35 +0700 Subject: [PATCH 15/27] StateMerger#mergeIndependentRanges refactoring; fix NPE (EA-100503) --- .../codeInspection/dataFlow/StateMerger.java | 80 ++++++++++--------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java index 6df7b7a89b33..e36fc897cdc7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java @@ -24,6 +24,7 @@ import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MultiMap; +import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -271,43 +272,8 @@ class StateMerger { // For every variable with more than one range, try to union range info and see if some states could be merged after that for (Map.Entry> entry : ranges.entrySet()) { if (entry.getValue().size() > 1) { - class Record { - final DfaMemoryStateImpl myState; - final LongRangeSet myRange; - final boolean myMerged; - - Record(DfaMemoryStateImpl state, LongRangeSet range, boolean merged) { - myState = state; - myRange = range; - myMerged = merged; - } - - Record union(Record other) { - return new Record(myState, myRange.union(other.myRange), true); - } - } - - ProgressManager.checkCanceled(); - Map merged = new LinkedHashMap<>(); - DfaVariableValue var = entry.getKey(); - for (DfaMemoryStateImpl state : states) { - DfaVariableState variableState = state.getVariableState(var); - LongRangeSet range = variableState.getRange(); - if (range == null) { - range = Objects.requireNonNull(LongRangeSet.fromType(var.getVariableType())); - } - merged.merge(copyWithoutVar(state, var), new Record(state, range, false), Record::union); - } - if(merged.size() < states.size()) { - List updated = new ArrayList<>(merged.size()); - for (Record record : merged.values()) { - DfaMemoryStateImpl state = record.myState; - if(record.myMerged) { - state.flushVariable(var); - state.setRange(var, record.myRange); - } - updated.add(state); - } + List updated = mergeIndependentRanges(states, entry.getKey()); + if (updated != null) { states = updated; changed = true; } @@ -316,6 +282,46 @@ class StateMerger { return changed ? states : null; } + @Nullable + private List mergeIndependentRanges(List states, DfaVariableValue var) { + class Record { + final DfaMemoryStateImpl myState; + final LongRangeSet myRange; + final boolean myMerged; + + Record(DfaMemoryStateImpl state, LongRangeSet range, boolean merged) { + myState = state; + myRange = range; + myMerged = merged; + } + + Record union(Record other) { + return new Record(myState, myRange.union(other.myRange), true); + } + + DfaMemoryStateImpl getState() { + if(myMerged) { + myState.flushVariable(var); + myState.setRange(var, myRange); + } + return myState; + } + } + + ProgressManager.checkCanceled(); + Map merged = new LinkedHashMap<>(); + for (DfaMemoryStateImpl state : states) { + DfaVariableState variableState = state.getVariableState(var); + LongRangeSet range = variableState.getRange(); + if (range == null) { + range = LongRangeSet.fromType(var.getVariableType()); + if (range == null) return null; + } + merged.merge(copyWithoutVar(state, var), new Record(state, range, false), Record::union); + } + return merged.size() == states.size() ? null : StreamEx.ofValues(merged).map(Record::getState).toList(); + } + @Nullable private static List dropExcessRangeInfo(List states, Set rangeVariables) { if (states.size() <= MAX_RANGE_STATES || rangeVariables.isEmpty()) return null; From c235edf33661a8b1f9b93e4148d7e7b5b35376fb Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 21 Apr 2017 14:26:25 +0700 Subject: [PATCH 16/27] IDEA-171770 "Equals between inconvertible types" does not work for method reference --- ...lsBetweenInconvertibleTypesInspection.java | 102 ++++++++---------- .../com/siyeh/ig/callMatcher/CallMatcher.java | 52 +++++++-- ...tweenInconvertibleTypesInspectionTest.java | 27 +++-- 3 files changed, 109 insertions(+), 72 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java index 84092c06dc95..e94a42c03445 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java @@ -16,16 +16,22 @@ package com.siyeh.ig.bugs; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ObjectUtils; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.psiutils.MethodCallUtils; +import com.siyeh.ig.callMatcher.CallMatcher; +import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NotNull; -public class EqualsBetweenInconvertibleTypesInspection - extends BaseInspection { +public class EqualsBetweenInconvertibleTypesInspection extends BaseInspection { + private static final CallMatcher OBJECT_EQUALS = + CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, "equals").parameterTypes(CommonClassNames.JAVA_LANG_OBJECT); + private static final CallMatcher STATIC_EQUALS = + CallMatcher.anyOf( + CallMatcher.staticCall("java.util.Objects", "equals").parameterCount(2), + CallMatcher.staticCall("com.google.common.base.Objects", "equal").parameterCount(2)); @Override @NotNull @@ -58,73 +64,57 @@ public class EqualsBetweenInconvertibleTypesInspection private static class EqualsBetweenInconvertibleTypesVisitor extends BaseInspectionVisitor { + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + super.visitMethodReferenceExpression(expression); + if (!OBJECT_EQUALS.methodReferenceMatches(expression) && !STATIC_EQUALS.methodReferenceMatches(expression)) return; + PsiMethod method = ObjectUtils.tryCast(expression.resolve(), PsiMethod.class); + if (method == null) return; + PsiType functionalInterfaceType = expression.getFunctionalInterfaceType(); + if (functionalInterfaceType == null) return; + PsiType type1, type2; + PsiExpression qualifier = expression.getQualifierExpression(); + type1 = LambdaUtil.getLambdaParameterFromType(functionalInterfaceType, 0); + if (qualifier == null || + qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifier).isReferenceTo(method.getContainingClass())) { + type2 = LambdaUtil.getLambdaParameterFromType(functionalInterfaceType, 1); + } else { + type2 = qualifier.getType(); + } + checkTypes(expression, type1, type2); + } + @Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - final PsiReferenceExpression methodExpression = expression.getMethodExpression(); - final boolean staticEqualsCall; - if (MethodCallUtils.isEqualsCall(expression)) { + boolean staticEqualsCall; + if (OBJECT_EQUALS.test(expression)) { staticEqualsCall = false; } - else { - final String name = methodExpression.getReferenceName(); - if (!"equals".equals(name) && !"equal".equals(name)) { - return; - } - final PsiMethod method = expression.resolveMethod(); - if (method == null) { - return; - } - final PsiClass aClass = method.getContainingClass(); - if (aClass == null) { - return; - } - final String qualifiedName = aClass.getQualifiedName(); - if (!"java.util.Objects".equals(qualifiedName) && !"com.google.common.base.Objects".equals(qualifiedName)) { - return; - } + else if (STATIC_EQUALS.test(expression)) { staticEqualsCall = true; } - final PsiExpressionList argumentList = expression.getArgumentList(); - final PsiExpression[] arguments = argumentList.getExpressions(); - final PsiExpression expression1; + else { + return; + } + final PsiExpression[] arguments = expression.getArgumentList().getExpressions(); + final PsiExpression expression1 = arguments[0]; final PsiExpression expression2; if (staticEqualsCall) { - if (arguments.length != 2) { - return; - } - expression1 = arguments[0]; expression2 = arguments[1]; } else { - if (arguments.length != 1) { - return; - } - expression1 = arguments[0]; - expression2 = methodExpression.getQualifierExpression(); + expression2 = ExpressionUtils.getQualifierOrThis(expression.getMethodExpression()); } - final PsiType comparisonType; - if (expression2 == null) { - final PsiClass aClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class); - if (aClass == null) { - return; - } - comparisonType = TypeUtils.getType(aClass); - } else { - comparisonType = expression2.getType(); + checkTypes(expression.getMethodExpression(), expression1.getType(), expression2.getType()); + } + + void checkTypes(PsiReferenceExpression expression, PsiType type1, PsiType type2) { + if (type1 != null && type2 != null && !TypeUtils.areConvertible(type1, type2)) { + PsiElement name = expression.getReferenceNameElement(); + registerError(name == null ? expression : name, type1, type2); } - if (comparisonType == null) { - return; - } - final PsiType comparedType = expression1.getType(); - if (comparedType == null) { - return; - } - if (TypeUtils.areConvertible(comparedType, comparisonType)) { - return; - } - registerMethodCallError(expression, comparedType, comparisonType); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/callMatcher/CallMatcher.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/callMatcher/CallMatcher.java index cfa2b4cca03f..9cb645036b2b 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/callMatcher/CallMatcher.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/callMatcher/CallMatcher.java @@ -19,6 +19,7 @@ import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.MethodCallUtils; import one.util.streamex.StreamEx; @@ -42,6 +43,8 @@ public interface CallMatcher extends Predicate { */ Stream names(); + boolean methodReferenceMatches(PsiMethodReferenceExpression methodRef); + @Contract("null -> false") boolean test(@Nullable PsiMethodCallExpression call); @@ -70,6 +73,16 @@ public interface CallMatcher extends Predicate { return Stream.of(matchers).flatMap(CallMatcher::names); } + @Override + public boolean methodReferenceMatches(PsiMethodReferenceExpression methodRef) { + for (CallMatcher m : matchers) { + if (m.methodReferenceMatches(methodRef)) { + return true; + } + } + return false; + } + @Override public boolean test(PsiMethodCallExpression call) { for (CallMatcher m : matchers) { @@ -163,6 +176,17 @@ public interface CallMatcher extends Predicate { psiType instanceof PsiClassType && ((PsiClassType)psiType).rawType().equalsToText(type); } + @Override + public boolean methodReferenceMatches(PsiMethodReferenceExpression methodRef) { + if (methodRef == null) return false; + String name = methodRef.getReferenceName(); + if (!myNames.contains(name)) return false; + PsiMethod method = ObjectUtils.tryCast(methodRef.resolve(), PsiMethod.class); + if (!methodMatches(method)) return false; + PsiParameterList parameterList = method.getParameterList(); + return parametersMatch(parameterList); + } + @Override public boolean test(PsiMethodCallExpression call) { if (call == null) return false; @@ -173,6 +197,24 @@ public interface CallMatcher extends Predicate { if (args.length < myParameters.length) return false; } PsiMethod method = call.resolveMethod(); + if (!methodMatches(method)) return false; + PsiParameterList parameterList = method.getParameterList(); + if (parameterList.getParametersCount() > args.length || + (!MethodCallUtils.isVarArgCall(call) && parameterList.getParametersCount() < args.length)) { + return false; + } + return parametersMatch(parameterList); + } + + private boolean parametersMatch(@NotNull PsiParameterList parameterList) { + if (myParameters == null) return true; + if (myParameters.length != parameterList.getParametersCount()) return false; + return StreamEx.zip(myParameters, parameterList.getParameters(), + Simple::parameterTypeMatches).allMatch(Boolean.TRUE::equals); + } + + @Contract("null -> false") + private boolean methodMatches(PsiMethod method) { if (method == null) return false; PsiClass aClass = method.getContainingClass(); if (aClass == null) return false; @@ -181,16 +223,6 @@ public interface CallMatcher extends Predicate { (!myStatic && !InheritanceUtil.isInheritor(aClass, myClassName))) { return false; } - PsiParameterList parameterList = method.getParameterList(); - if (parameterList.getParametersCount() > args.length || - (!MethodCallUtils.isVarArgCall(call) && parameterList.getParametersCount() < args.length)) { - return false; - } - if (myParameters != null) { - if (myParameters.length != parameterList.getParametersCount()) return false; - return StreamEx.zip(myParameters, parameterList.getParameters(), - Simple::parameterTypeMatches).allMatch(Boolean.TRUE::equals); - } return true; } diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java index d24751c6ff8a..b9accdb240bb 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java @@ -16,7 +16,9 @@ package com.siyeh.ig.bugs; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.NotNull; /** * @author Bas Leijdekkers @@ -75,15 +77,22 @@ public class EqualsBetweenInconvertibleTypesInspectionTest extends LightInspecti "}"); } + public void testMethodReference() { + doTest("import java.util.Objects;\n" + + "import java.util.function.*;\n" + + "\n" + + "class Test {\n" + + " Predicate p = \"123\"::/*'equals()' between objects of inconvertible types 'Integer' and 'String'*/equals/**/;\n" + + " Predicate pOk = \"456\"::equals;\n" + + " BiPredicate bp = Objects::/*'equals()' between objects of inconvertible types 'String' and 'Integer'*/equals/**/;\n" + + " BiPredicate bp2 = Object::/*'equals()' between objects of inconvertible types 'Long' and 'Double'*/equals/**/;\n" + + " BiPredicate bpOk = Object::equals;\n" + + "}\n"); + } + @Override protected String[] getEnvironmentClasses() { return new String[] { - "package java.util;" + - "public final class Objects {" + - " public static boolean equals(Object a, Object b) {" + - " return (a == b) || (a != null && a.equals(b));" + - " }" + - "}", "package com.google.common.base;" + "public final class Objects {" + " public static boolean equal(Object a, Object b) {" + @@ -97,4 +106,10 @@ public class EqualsBetweenInconvertibleTypesInspectionTest extends LightInspecti protected InspectionProfileEntry getInspection() { return new EqualsBetweenInconvertibleTypesInspection(); } + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_8; + } } From 6317f2b916c9dcfe4628f5b107384dfb098f486a Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 21 Apr 2017 10:14:17 +0200 Subject: [PATCH 17/27] [tests] one more test case for module-info formatting --- .../intellij/psi/formatter/java/JavaModuleFormatterTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaModuleFormatterTest.kt b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaModuleFormatterTest.kt index 7cae4b3b9b98..92266fba923f 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaModuleFormatterTest.kt +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaModuleFormatterTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -36,4 +36,8 @@ class JavaModuleFormatterTest : AbstractJavaFormatterTest() { fun testStatements() { doTextTest("module m { requires java.base; exports a.b; }", "module m {\n requires java.base;\n exports a.b;\n}") } + + fun testQualifiedExports() { + doTextTest("module m { exports a.b to m1,m2,m3; }", "module m {\n exports a.b to m1, m2, m3;\n}") + } } \ No newline at end of file From ebb520451ceddfd42794ddc98c316db42c4b4c67 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 21 Apr 2017 11:27:49 +0300 Subject: [PATCH 18/27] Gradle: 4.0 compatibility fix, handle removed method - ProjectDependency.getProjectConfiguration --- .../util/DependencyResolverImpl.groovy | 35 ++++++++++--------- .../builder/AbstractModelBuilderTest.java | 5 +-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy index 4a9117d61e93..b8ad27a361c3 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy @@ -21,17 +21,8 @@ import com.google.common.collect.ArrayListMultimap import com.google.common.collect.Lists import com.google.common.collect.Multimap import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.Dependency -import org.gradle.api.artifacts.ModuleVersionIdentifier -import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.artifacts.ResolvedArtifact -import org.gradle.api.artifacts.SelfResolvingDependency -import org.gradle.api.artifacts.component.ComponentIdentifier -import org.gradle.api.artifacts.component.ModuleComponentIdentifier -import org.gradle.api.artifacts.component.ModuleComponentSelector -import org.gradle.api.artifacts.component.ProjectComponentIdentifier -import org.gradle.api.artifacts.component.ProjectComponentSelector +import org.gradle.api.artifacts.* +import org.gradle.api.artifacts.component.* import org.gradle.api.artifacts.result.* import org.gradle.api.plugins.WarPlugin import org.gradle.api.specs.Specs @@ -57,8 +48,11 @@ import java.util.regex.Pattern */ class DependencyResolverImpl implements DependencyResolver { - private static isArtifactResolutionQuerySupported = GradleVersion.current() >= GradleVersion.version("2.0") - private static isDependencySubstitutionsSupported = GradleVersion.current() > GradleVersion.version("2.5") + private static is4OrBetter = GradleVersion.current().baseVersion >= GradleVersion.version("4.0") + private static isDependencySubstitutionsSupported = is4OrBetter || + (GradleVersion.current() > GradleVersion.version("2.5")) + private static isArtifactResolutionQuerySupported = isDependencySubstitutionsSupported || + (GradleVersion.current() >= GradleVersion.version("2.0")) @NotNull private final Project myProject @@ -151,7 +145,7 @@ class DependencyResolverImpl implements DependencyResolver { if(!processedConfigurations.add(conf)) return map conf.incoming.dependencies.findAll { it instanceof ProjectDependency }.each { it -> map.put(toComponentIdentifier(it.group, it.name, it.version), it as ProjectDependency) - projectDeps((it as ProjectDependency).projectConfiguration, map) + projectDeps(getTargetConfiguration(it as ProjectDependency), map) } map } @@ -721,15 +715,17 @@ class DependencyResolverImpl implements DependencyResolver { try { if (it instanceof ProjectDependency) { def project = it.getDependencyProject() + Configuration targetConfiguration = getTargetConfiguration(it) + final projectDependency = new DefaultExternalProjectDependency( name: project.name, group: project.group, version: project.version, scope: scope, projectPath: project.path, - configurationName: it.projectConfiguration.name + configurationName: targetConfiguration.name ) - projectDependency.projectDependencyArtifacts = it.projectConfiguration.allArtifacts.files.files + projectDependency.projectDependencyArtifacts = targetConfiguration.allArtifacts.files.files result.add(projectDependency) } else if (it instanceof Dependency) { @@ -772,6 +768,11 @@ class DependencyResolverImpl implements DependencyResolver { return result } + private static Configuration getTargetConfiguration(ProjectDependency projectDependency) { + return !is4OrBetter ? projectDependency.projectConfiguration : + projectDependency.dependencyProject.configurations.getByName(projectDependency.targetConfiguration ?: 'default') + } + class DependencyResultsTransformer { Collection handledDependencyResults Multimap artifactMap @@ -824,7 +825,7 @@ class DependencyResolverImpl implements DependencyResolver { selectionReason = "composite build substitution" } } else { - dependencyConfigurations = projectDependencies.collect {it.projectConfiguration} + dependencyConfigurations = projectDependencies.collect { getTargetConfiguration(it) } } dependencyConfigurations.each { diff --git a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java index 2f8d4e074a06..db6f6130da73 100644 --- a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java +++ b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java @@ -76,7 +76,8 @@ public abstract class AbstractModelBuilderTest { //{"1.9"}, /*{"1.10"}, {"1.11"},*/ {"1.12"}, // {"2.0"}, /*{"2.1"}, {"2.2"} , {"2.3"}, {"2.4"}, */{"2.5"}, /*{"2.6"}, {"2.7"}, {"2.8"},*/ {"2.9"}, /*{"2.10"}, {"2.11"}, {"2.12"}, {"2.13"}, */{"2.14.1"}, - {"3.0"}, /*{"3.1"}, {"3.2"},*/ {"3.3"}, {"3.4"}, {"3.5-rc-2"} + {"3.0"}, /*{"3.1"}, {"3.2"},*/ {"3.3"}, {"3.4"}, {"3.5"}/*, + {"4.0-20170421000013+0000"}*/ }; public static final String BASE_GRADLE_VERSION = String.valueOf(SUPPORTED_GRADLE_VERSIONS[SUPPORTED_GRADLE_VERSIONS.length - 1][0]); @@ -177,7 +178,7 @@ public abstract class AbstractModelBuilderTest { @NotNull private Set getToolingExtensionClasses() { - final Set classes = ContainerUtil.set( + final Set classes = ContainerUtil.set( ExternalProject.class, // gradle-tooling-extension-api jar ProjectImportAction.class, From 4dac349ac56b80b705c2799a3a37d8fce13e1f47 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 21 Apr 2017 11:33:11 +0300 Subject: [PATCH 19/27] Gradle: revert the result of wrong optimize imports --- .../tooling/util/DependencyResolverImpl.groovy | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy index b8ad27a361c3..d40c04a0fb3b 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.groovy @@ -21,8 +21,17 @@ import com.google.common.collect.ArrayListMultimap import com.google.common.collect.Lists import com.google.common.collect.Multimap import org.gradle.api.Project -import org.gradle.api.artifacts.* -import org.gradle.api.artifacts.component.* +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ModuleVersionIdentifier +import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.artifacts.ResolvedArtifact +import org.gradle.api.artifacts.SelfResolvingDependency +import org.gradle.api.artifacts.component.ComponentIdentifier +import org.gradle.api.artifacts.component.ModuleComponentIdentifier +import org.gradle.api.artifacts.component.ModuleComponentSelector +import org.gradle.api.artifacts.component.ProjectComponentIdentifier +import org.gradle.api.artifacts.component.ProjectComponentSelector import org.gradle.api.artifacts.result.* import org.gradle.api.plugins.WarPlugin import org.gradle.api.specs.Specs From ccffbf026fde0ff7430bfacf6dc0735e7db649fc Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 21 Apr 2017 11:53:34 +0300 Subject: [PATCH 20/27] inspection view: fix NPE when inspection has no description EA-100514 --- .../com/intellij/codeInspection/ui/InspectionNodeInfo.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java index 0928ff4b3290..2c90e5dfbaaf 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java @@ -21,6 +21,7 @@ import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionsConfigTreeTable; @@ -75,7 +76,10 @@ public class InspectionNodeInfo extends JPanel { description.setOpaque(false); description.setBackground(UIUtil.getLabelBackground()); description.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE); - final String toolDescription = DefaultInspectionToolPresentation.stripUIRefsFromInspectionDescription(toolWrapper.loadDescription()); + String descriptionText = toolWrapper.loadDescription(); + LOG.assertTrue(descriptionText != null, "Inspection '" + toolWrapper.getShortName() + "' has no description"); + final String toolDescription = + DefaultInspectionToolPresentation.stripUIRefsFromInspectionDescription(StringUtil.notNullize(descriptionText)); SingleInspectionProfilePanel.readHTML(description, SingleInspectionProfilePanel.toHTML(description, toolDescription == null ? "" : toolDescription, false)); JScrollPane pane = ScrollPaneFactory.createScrollPane(description, true); int maxWidth = getFontMetrics(UIUtil.getLabelFont()).charWidth('f') * 110 - pane.getMinimumSize().width; From e2fa2d81cb0f54e17b349001ff8b7ad95881e07e Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 20 Apr 2017 16:29:55 +0300 Subject: [PATCH 21/27] speedup descriptors parsing, avoid using regexp split --- .../struct/consts/LinkConstant.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java index 71bf14615558..5d37f0fc57c5 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -135,31 +135,32 @@ public class LinkConstant extends PooledConstant { } private void resolveDescriptor(String descr) { + int parenth = descr.indexOf(')'); + if (descr.length() < 2 || parenth < 0 || descr.charAt(0) != '(') { + throw new IllegalArgumentException("Invalid descriptor: " + descr); + } - String[] arr = descr.split("[()]"); - String par = arr[1]; - - int index = 0, counter = 0; - int len = par.length(); - - while (index < len) { - - char c = par.charAt(index); - if (c == 'L') { - index = par.indexOf(";", index); - } - else if (c == '[') { + int counter = 0; + if (parenth > 1) { // params + int index = 1; + while (index < parenth) { + char c = descr.charAt(index); + if (c == 'L') { + index = descr.indexOf(";", index); + } + else if (c == '[') { + index++; + continue; + } + counter++; index++; - continue; } - - counter++; - index++; } paramCount = counter; - isVoid = "V".equals(arr[2]); - returnCategory2 = ("D".equals(arr[2]) || "J".equals(arr[2])); - } + char retChar = descr.charAt(parenth + 1); + isVoid = retChar == 'V'; + returnCategory2 = (retChar == 'D') || (retChar == 'J'); + } } From 78a21bd9b2d551f354322ab7b905ed001b13ce44 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 20 Apr 2017 19:11:52 +0300 Subject: [PATCH 22/27] specify the exact collection size when we know --- .../org/jetbrains/java/decompiler/struct/StructClass.java | 6 +++--- .../org/jetbrains/java/decompiler/struct/StructMember.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java index 33dc178fba72..fafd5f878fc5 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -93,7 +93,7 @@ public class StructClass extends StructMember { // fields length = in.readUnsignedShort(); - fields = new VBStyleCollection<>(); + fields = new VBStyleCollection<>(length); for (int i = 0; i < length; i++) { StructField field = new StructField(in, this); fields.addWithKey(field, InterpreterUtil.makeUniqueKey(field.getName(), field.getDescriptor())); @@ -101,7 +101,7 @@ public class StructClass extends StructMember { // methods length = in.readUnsignedShort(); - methods = new VBStyleCollection<>(); + methods = new VBStyleCollection<>(length); for (int i = 0; i < length; i++) { StructMethod method = new StructMethod(in, this); methods.addWithKey(method, InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor())); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java index 86f79b4a683f..bfe22706ba0f 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java @@ -48,9 +48,9 @@ public class StructMember { } protected VBStyleCollection readAttributes(DataInputFullStream in, ConstantPool pool) throws IOException { - VBStyleCollection attributes = new VBStyleCollection<>(); - int length = in.readUnsignedShort(); + + VBStyleCollection attributes = new VBStyleCollection<>(length); for (int i = 0; i < length; i++) { int nameIndex = in.readUnsignedShort(); String name = pool.getPrimitiveConstant(nameIndex).getString(); From f70a1b7e639fdc982440a44158061b78f43d31d1 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 20 Apr 2017 19:27:41 +0300 Subject: [PATCH 23/27] reduced memory usage - use HashMap for attributes --- .../java/decompiler/main/ClassWriter.java | 30 +++++++++---------- .../decompiler/main/ClassesProcessor.java | 6 ++-- .../decompiler/main/rels/LambdaProcessor.java | 4 +-- .../main/rels/NestedClassProcessor.java | 2 +- .../modules/decompiler/ExprProcessor.java | 2 +- .../modules/decompiler/IdeaNotNullHelper.java | 12 +++----- .../modules/decompiler/exps/ExitExprent.java | 4 +-- .../modules/decompiler/exps/VarExprent.java | 4 +-- .../java/decompiler/struct/StructMember.java | 25 +++++++++------- .../java/decompiler/struct/StructMethod.java | 9 +++--- 10 files changed, 50 insertions(+), 48 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 0986a22a1553..6233efef02cf 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -271,7 +271,7 @@ public class ClassWriter { private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) { StructLineNumberTableAttribute table = - (StructLineNumberTableAttribute)method.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); + (StructLineNumberTableAttribute)method.getAttribute(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); tracer.setLineNumberTable(table); String key = InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor()); DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, key, tracer); @@ -287,8 +287,8 @@ public class ClassWriter { StructClass cl = wrapper.getClassStruct(); int flags = node.type == ClassNode.CLASS_ROOT ? cl.getAccessFlags() : node.access; - boolean isDeprecated = cl.getAttributes().containsKey("Deprecated"); - boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || cl.getAttributes().containsKey("Synthetic"); + boolean isDeprecated = cl.hasAttribute("Deprecated"); + boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || cl.hasAttribute("Synthetic"); boolean isEnum = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM) && (flags & CodeConstants.ACC_ENUM) != 0; boolean isInterface = (flags & CodeConstants.ACC_INTERFACE) != 0; boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0; @@ -379,7 +379,7 @@ public class ClassWriter { private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { int start = buffer.length(); boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); - boolean isDeprecated = fd.getAttributes().containsKey("Deprecated"); + boolean isDeprecated = fd.hasAttribute("Deprecated"); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); if (isDeprecated) { @@ -407,7 +407,7 @@ public class ClassWriter { GenericFieldDescriptor descriptor = null; if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) { - StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)fd.getAttributes().getWithKey("Signature"); + StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)fd.getAttribute("Signature"); if (attr != null) { descriptor = GenericMain.parseFieldSignature(attr.getSignature()); } @@ -448,7 +448,7 @@ public class ClassWriter { } else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) { StructConstantValueAttribute attr = - (StructConstantValueAttribute)fd.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE); + (StructConstantValueAttribute)fd.getAttribute(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE); if (attr != null) { PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex()); buffer.append(" = "); @@ -587,7 +587,7 @@ public class ClassWriter { boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); boolean isAnnotation = cl.hasModifier(CodeConstants.ACC_ANNOTATION); boolean isEnum = cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); - boolean isDeprecated = mt.getAttributes().containsKey("Deprecated"); + boolean isDeprecated = mt.hasAttribute("Deprecated"); boolean clinit = false, init = false, dinit = false; MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); @@ -609,7 +609,7 @@ public class ClassWriter { appendRenameComment(buffer, oldName, MType.METHOD, indent); } - boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic"); + boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.hasAttribute("Synthetic"); boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0; if (isSynthetic) { appendComment(buffer, "synthetic method", indent); @@ -647,7 +647,7 @@ public class ClassWriter { GenericMethodDescriptor descriptor = null; if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) { - StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)mt.getAttributes().getWithKey("Signature"); + StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)mt.getAttribute("Signature"); if (attr != null) { descriptor = GenericMain.parseMethodSignature(attr.getSignature()); if (descriptor != null) { @@ -771,7 +771,7 @@ public class ClassWriter { buffer.append(')'); - StructExceptionsAttribute attr = (StructExceptionsAttribute)mt.getAttributes().getWithKey("Exceptions"); + StructExceptionsAttribute attr = (StructExceptionsAttribute)mt.getAttribute("Exceptions"); if ((descriptor != null && !descriptor.exceptions.isEmpty()) || attr != null) { throwsExceptions = true; buffer.append(" throws "); @@ -796,7 +796,7 @@ public class ClassWriter { if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { // native or abstract method (explicit or interface) if (isAnnotation) { - StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault"); + StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttribute("AnnotationDefault"); if (attr != null) { buffer.append(" default "); buffer.append(attr.getDefaultValue().toJava(0, BytecodeMappingTracer.DUMMY)); @@ -943,7 +943,7 @@ public class ClassWriter { Set filter = new HashSet<>(); for (String name : ANNOTATION_ATTRIBUTES) { - StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name); + StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttribute(name); if (attribute != null) { for (AnnotationExprent annotation : attribute.getAnnotations()) { String text = annotation.toJava(indent, BytecodeMappingTracer.DUMMY).toString(); @@ -960,7 +960,7 @@ public class ClassWriter { Set filter = new HashSet<>(); for (String name : PARAMETER_ANNOTATION_ATTRIBUTES) { - StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttributes().getWithKey(name); + StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttribute(name); if (attribute != null) { List> annotations = attribute.getParamAnnotations(); if (param < annotations.size()) { @@ -978,7 +978,7 @@ public class ClassWriter { private static void appendTypeAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType, int index, Set filter) { for (String name : TYPE_ANNOTATION_ATTRIBUTES) { - StructTypeAnnotationAttribute attribute = (StructTypeAnnotationAttribute)mb.getAttributes().getWithKey(name); + StructTypeAnnotationAttribute attribute = (StructTypeAnnotationAttribute)mb.getAttribute(name); if (attribute != null) { for (TypeAnnotation annotation : attribute.getAnnotations()) { if (annotation.isTopLevel() && annotation.getTargetType() == targetType && (index < 0 || annotation.getIndex() == index)) { @@ -1041,7 +1041,7 @@ public class ClassWriter { public static GenericClassDescriptor getGenericClassDescriptor(StructClass cl) { if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) { - StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)cl.getAttributes().getWithKey("Signature"); + StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)cl.getAttribute("Signature"); if (attr != null) { return GenericMain.parseClassSignature(attr.getSignature()); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index 4afeddfaedb7..a743f985878d 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -66,7 +66,7 @@ public class ClassesProcessor { for (StructClass cl : context.getClasses().values()) { if (cl.isOwn() && !mapRootClasses.containsKey(cl.qualifiedName)) { if (bDecompileInner) { - StructInnerClassesAttribute inner = (StructInnerClassesAttribute)cl.getAttributes().getWithKey("InnerClasses"); + StructInnerClassesAttribute inner = (StructInnerClassesAttribute)cl.getAttribute("InnerClasses"); if (inner != null) { for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) { @@ -157,7 +157,7 @@ public class ClassesProcessor { if (setNestedClasses != null) { StructClass scl = superNode.classStruct; - StructInnerClassesAttribute inner = (StructInnerClassesAttribute)scl.getAttributes().getWithKey("InnerClasses"); + StructInnerClassesAttribute inner = (StructInnerClassesAttribute)scl.getAttribute("InnerClasses"); if (inner == null || inner.getEntries().isEmpty()) { DecompilerContext.getLogger().writeMessage(superClass + " does not contain inner classes!", IFernflowerLogger.Severity.WARN); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java index 0063a15ef65d..3b2e74d42ec1 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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,7 +56,7 @@ public class LambdaProcessor { } StructBootstrapMethodsAttribute bootstrap = - (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS); + (StructBootstrapMethodsAttribute)cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS); if (bootstrap == null || bootstrap.getMethodsNumber() == 0) { return false; // no bootstrap constants in pool } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java index 897b3944951d..974c05796151 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java @@ -192,7 +192,7 @@ public class NestedClassProcessor { if (!setEnclosing.isEmpty()) { StructEnclosingMethodAttribute attr = - (StructEnclosingMethodAttribute)child.classStruct.getAttributes().getWithKey("EnclosingMethod"); + (StructEnclosingMethodAttribute)child.classStruct.getAttribute("EnclosingMethod"); if (attr != null && attr.getMethodName() != null && node.classStruct.qualifiedName.equals(attr.getClassName()) && 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 930b1ee051e6..f6005ba54268 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 @@ -288,7 +288,7 @@ public class ExprProcessor implements CodeConstants { ConstantPool pool = cl.getPool(); StructBootstrapMethodsAttribute bootstrap = - (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS); + (StructBootstrapMethodsAttribute)cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS); BasicBlock block = stat.getBlock(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java index 40d94fd0a08e..d6f917d8ed12 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -25,7 +25,6 @@ import org.jetbrains.java.decompiler.struct.attr.StructAnnotationAttribute; import org.jetbrains.java.decompiler.struct.attr.StructAnnotationParameterAttribute; import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; -import org.jetbrains.java.decompiler.util.VBStyleCollection; import java.util.List; @@ -85,11 +84,10 @@ public class IdeaNotNullHelper { boolean thisvar = !mt.hasModifier(CodeConstants.ACC_STATIC); MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); - VBStyleCollection attributes = mt.getAttributes(); // parameter annotations - StructAnnotationParameterAttribute param_annotations = (StructAnnotationParameterAttribute)attributes - .getWithKey(StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS); + StructAnnotationParameterAttribute param_annotations = + (StructAnnotationParameterAttribute)mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS); if (param_annotations != null) { List> param_annotations_lists = param_annotations.getParamAnnotations(); @@ -172,13 +170,11 @@ public class IdeaNotNullHelper { private static boolean findAndRemoveReturnCheck(Statement stat, StructMethod mt) { - VBStyleCollection attributes = mt.getAttributes(); - boolean is_notnull_check = false; // method annotation, refers to the return value StructAnnotationAttribute attr = - (StructAnnotationAttribute)attributes.getWithKey(StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS); + (StructAnnotationAttribute)mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS); if (attr != null) { List annotations = attr.getAnnotations(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java index abfc4ab04532..0f16b667f258 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -96,7 +96,7 @@ public class ExitExprent extends Exprent { ClassNode node = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)); if (method != null && node != null) { - StructExceptionsAttribute attr = (StructExceptionsAttribute)method.methodStruct.getAttributes().getWithKey("Exceptions"); + StructExceptionsAttribute attr = (StructExceptionsAttribute)method.methodStruct.getAttribute("Exceptions"); if (attr != null) { String classname = null; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java index 0cb7fd1dec4f..d31f809b7b59 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java @@ -155,8 +155,8 @@ public class VarExprent extends Exprent { if (originalIndex != null) { // first try from signature if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) { - StructLocalVariableTypeTableAttribute attr = (StructLocalVariableTypeTableAttribute)method.methodStruct.getAttributes() - .getWithKey(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE); + StructLocalVariableTypeTableAttribute attr = (StructLocalVariableTypeTableAttribute)method.methodStruct + .getAttribute(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE); if (attr != null) { String signature = attr.getSignature(originalIndex, visibleOffset); if (signature != null) { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java index bfe22706ba0f..585fcb203110 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMember.java @@ -21,22 +21,27 @@ import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribu import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTypeTableAttribute; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.util.DataInputFullStream; -import org.jetbrains.java.decompiler.util.VBStyleCollection; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; public class StructMember { protected int accessFlags; - protected VBStyleCollection attributes; + protected Map attributes; public int getAccessFlags() { return accessFlags; } - public VBStyleCollection getAttributes() { - return attributes; + public StructGeneralAttribute getAttribute(String name) { + return attributes.get(name); + } + + public boolean hasAttribute(String name) { + return attributes.containsKey(name); } public boolean hasModifier(int modifier) { @@ -44,13 +49,13 @@ public class StructMember { } public boolean isSynthetic() { - return hasModifier(CodeConstants.ACC_SYNTHETIC) || attributes.containsKey(StructGeneralAttribute.ATTRIBUTE_SYNTHETIC); + return hasModifier(CodeConstants.ACC_SYNTHETIC) || hasAttribute(StructGeneralAttribute.ATTRIBUTE_SYNTHETIC); } - protected VBStyleCollection readAttributes(DataInputFullStream in, ConstantPool pool) throws IOException { + protected Map readAttributes(DataInputFullStream in, ConstantPool pool) throws IOException { int length = in.readUnsignedShort(); - VBStyleCollection attributes = new VBStyleCollection<>(length); + Map attributes = new HashMap<>(length); for (int i = 0; i < length; i++) { int nameIndex = in.readUnsignedShort(); String name = pool.getPrimitiveConstant(nameIndex).getString(); @@ -60,16 +65,16 @@ public class StructMember { if (attribute != null) { if (StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(name) && attributes.containsKey(name)) { // merge all variable tables - StructLocalVariableTableAttribute table = (StructLocalVariableTableAttribute)attributes.getWithKey(name); + StructLocalVariableTableAttribute table = (StructLocalVariableTableAttribute)attributes.get(name); table.add((StructLocalVariableTableAttribute)attribute); } else if (StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE.equals(name) && attributes.containsKey(name)) { // merge all variable tables - StructLocalVariableTypeTableAttribute table = (StructLocalVariableTypeTableAttribute)attributes.getWithKey(name); + StructLocalVariableTypeTableAttribute table = (StructLocalVariableTypeTableAttribute)attributes.get(name); table.add((StructLocalVariableTypeTableAttribute)attribute); } else { - attributes.addWithKey(attribute, attribute.getName()); + attributes.put(attribute.getName(), attribute); } } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMethod.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMethod.java index d398c5ea2a27..64ee869d5b42 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMethod.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -25,6 +25,7 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static org.jetbrains.java.decompiler.code.CodeConstants.*; @@ -53,7 +54,7 @@ public class StructMethod extends StructMember { private int codeFullLength = 0; private InstructionSequence seq; private boolean expanded = false; - private VBStyleCollection codeAttributes; + private Map codeAttributes; public StructMethod(DataInputFullStream in, StructClass clStruct) throws IOException { classStruct = clStruct; @@ -69,7 +70,7 @@ public class StructMethod extends StructMember { attributes = readAttributes(in, pool); if (codeAttributes != null) { - attributes.addAllWithKey(codeAttributes); + attributes.putAll(codeAttributes); codeAttributes = null; } } @@ -391,7 +392,7 @@ public class StructMethod extends StructMember { } public StructLocalVariableTableAttribute getLocalVariableAttr() { - return (StructLocalVariableTableAttribute)getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); + return (StructLocalVariableTableAttribute)getAttribute(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); } @Override From 0537285e2d86d65ac2b23236f86c8e807586d039 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 21 Apr 2017 12:08:24 +0300 Subject: [PATCH 24/27] IDEA-153597 [followup] Settings > Appearance > "Override default fonts" should display current font when unchecked --- .../ide/ui/AppearanceConfigurable.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index fdef6fcde7cd..bea0fd807eb8 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -199,11 +199,9 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab settings.setAllowMergeButtons(myComponent.myAllowMergeButtons.isSelected()); update |= settings.getCycleScrolling() != myComponent.myCycleScrollingCheckBox.isSelected(); settings.setCycleScrolling(myComponent.myCycleScrollingCheckBox.isSelected()); - boolean shouldResetLafFonts = false; if (settings.getOverrideLafFonts() != myComponent.myOverrideLAFFonts.isSelected()) { shouldUpdateUI = true; update = true; - shouldResetLafFonts = !myComponent.myOverrideLAFFonts.isSelected(); } settings.setOverrideLafFonts(myComponent.myOverrideLAFFonts.isSelected()); settings.setMoveMouseOnDefaultButton(myComponent.myMoveMouseOnDefaultButtonCheckBox.isSelected()); @@ -256,14 +254,17 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab if (shouldUpdateUI) { lafManager.updateUI(); - if (shouldResetLafFonts) { - int defSize = JBUI.Fonts.label().getSize(); - settings.setFontSize(defSize); - myComponent.myFontSizeCombo.getModel().setSelectedItem(String.valueOf(defSize)); - String defName = JBUI.Fonts.label().getFontName(); - settings.setFontFace(defName); - myComponent.myFontCombo.setFontName(defName); - } + shouldUpdateUI = false; + } + // reset to default when unchecked + if (!myComponent.myOverrideLAFFonts.isSelected()) { + assert !shouldUpdateUI; + int defSize = JBUI.Fonts.label().getSize(); + settings.setFontSize(defSize); + myComponent.myFontSizeCombo.getModel().setSelectedItem(String.valueOf(defSize)); + String defName = JBUI.Fonts.label().getFontName(); + settings.setFontFace(defName); + myComponent.myFontCombo.setFontName(defName); } if (WindowManagerEx.getInstanceEx().isAlphaModeSupported()) { From 42656ceaae8dba42186725bed34979abb7cab5c7 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 21 Apr 2017 12:20:13 +0300 Subject: [PATCH 25/27] javac ast indices: request index rebuild on every io exception --- .../backwardRefs/CompilerReferenceServiceImpl.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java index 2e1cc8598e48..6823341793ed 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java @@ -57,7 +57,6 @@ import com.intellij.util.indexing.StorageException; import com.intellij.util.io.PersistentEnumeratorBase; import gnu.trove.THashSet; import gnu.trove.TIntHashSet; -import org.iq80.snappy.CorruptionException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -686,12 +685,8 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp } private static boolean requireIndexRebuild(@Nullable Throwable exception) { - if (exception instanceof PersistentEnumeratorBase.CorruptedException || exception instanceof StorageException) { - return true; - } - if (exception instanceof IOException && exception.getCause() instanceof CorruptionException) { - return true; - } - return false; + return exception instanceof PersistentEnumeratorBase.CorruptedException || + exception instanceof StorageException || + exception instanceof IOException; } } From 0dccec9d103390e1767a1a05626314894370529f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 21 Apr 2017 11:33:56 +0200 Subject: [PATCH 26/27] cleanup (name, type) --- .../com/intellij/ide/browsers/BrowserLauncherAppless.java | 6 +++--- .../src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java index aeb901b507da..4326378c6f57 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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,7 +56,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { (SystemInfo.isUnix && SystemInfo.hasXdgOpen()); } - private static GeneralSettings getGeneralSettingsInstance() { + private static GeneralSettings getGeneralSettings() { if (ApplicationManager.getApplication() != null) { GeneralSettings settings = GeneralSettings.getInstance(); if (settings != null) { @@ -101,7 +101,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { public void browse(@NotNull URI uri, @Nullable Project project) { LOG.debug("Launch browser: [" + uri + "]"); - GeneralSettings settings = getGeneralSettingsInstance(); + GeneralSettings settings = getGeneralSettings(); if (settings.isUseDefaultBrowser()) { boolean tryToUseCli = true; if (isDesktopActionSupported(Desktop.Action.BROWSE)) { diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java index b634fd2fc8b1..ed11f096a835 100644 --- a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java +++ b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -37,11 +37,11 @@ public final class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo { private final Condition browserCondition; public OpenUrlHyperlinkInfo(@NotNull String url) { - this(url, Conditions.alwaysTrue(), null); + this(url, Conditions.alwaysTrue(), null); } public OpenUrlHyperlinkInfo(@NotNull String url, @Nullable final WebBrowser browser) { - this(url, browser == null ? Conditions.alwaysTrue() : Conditions.is(browser)); + this(url, browser == null ? Conditions.alwaysTrue() : Conditions.is(browser)); } public OpenUrlHyperlinkInfo(@NotNull String url, @NotNull Condition browserCondition) { From 833deed552695c47c8f8dc327646cdbca54a81ff Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 21 Apr 2017 11:35:11 +0200 Subject: [PATCH 27/27] WEB-26547 attempt to use smart url opener if no browser specified, but first listed specified in the settings --- .../com/intellij/ide/browsers/BrowserLauncherImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java index 7d2a1e3ce92b..278ef3be2548 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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,6 +53,14 @@ public final class BrowserLauncherImpl extends BrowserLauncherAppless { url = serverManager.addAuthToken(parsedUrl).toExternalForm(); } + if (browser == null) { + // https://youtrack.jetbrains.com/issue/WEB-26547 + WebBrowserManager browserManager = WebBrowserManager.getInstance(); + if (browserManager.getDefaultBrowserPolicy() == DefaultBrowserPolicy.FIRST) { + browser = browserManager.getFirstActiveBrowser(); + } + } + super.browse(url, browser, project); }