From 3d2373ae285749bb98cf0360487b0d77e6f5b2b6 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Mon, 17 Aug 2015 17:12:24 +0300 Subject: [PATCH 01/12] IDEA-97324 Maven support cannot handle skinny wars for EAR deployments --- ...enManifestGenerationBuildTaskProvider.java | 94 +++++++++++++++++++ .../MavenModuleResourceConfiguration.java | 5 + .../maven/importing/ManifestImporter.java | 2 +- .../idea/maven/importing/MavenImporter.java | 6 ++ .../maven/importing/MavenModuleImporter.java | 25 +++++ .../maven/importing/MavenProjectImporter.java | 8 +- ...esourceCompilerConfigurationGenerator.java | 9 ++ .../idea/maven/utils/ManifestBuilder.java | 39 +++++--- 8 files changed, 173 insertions(+), 15 deletions(-) diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenManifestGenerationBuildTaskProvider.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenManifestGenerationBuildTaskProvider.java index e5aa3003c36e..f65ee59c26c2 100644 --- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenManifestGenerationBuildTaskProvider.java +++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenManifestGenerationBuildTaskProvider.java @@ -16,26 +16,43 @@ package org.jetbrains.jps.maven.compiler; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Base64; +import com.intellij.util.Function; +import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider; import org.jetbrains.jps.builders.storage.BuildDataPaths; +import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.BuildTask; import org.jetbrains.jps.incremental.CompileContext; import org.jetbrains.jps.incremental.ProjectBuildException; +import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactUtil; import org.jetbrains.jps.maven.model.JpsMavenExtensionService; import org.jetbrains.jps.maven.model.impl.MavenModuleResourceConfiguration; import org.jetbrains.jps.maven.model.impl.MavenProjectConfiguration; import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.artifact.elements.JpsArtifactRootElement; +import org.jetbrains.jps.model.artifact.elements.JpsFileCopyPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.jar.Attributes; import java.util.jar.JarFile; +import java.util.jar.Manifest; /** * @author nik @@ -72,6 +89,7 @@ public class MavenManifestGenerationBuildTaskProvider extends ArtifactBuildTaskP try { File output = new File(myArtifact.getOutputPath(), JarFile.MANIFEST_NAME); FileUtil.writeToFile(output, Base64.decode(moduleResourceConfiguration.manifest)); + handleSkinnyWars(context, projectConfiguration, moduleResourceConfiguration); } // do not fail the whole 'Make' if there is an invalid manifest cached (e.g. non encoded string generated by previous IDEA version) catch (Exception e) { @@ -80,6 +98,82 @@ public class MavenManifestGenerationBuildTaskProvider extends ArtifactBuildTaskP } } + private void handleSkinnyWars(final CompileContext context, + final MavenProjectConfiguration projectConfiguration, + MavenModuleResourceConfiguration moduleResourceConfiguration) { + if (!"ear".equals(moduleResourceConfiguration.modelMap.get("packaging"))) return; + if (!Boolean.parseBoolean(moduleResourceConfiguration.modelMap.get("build.plugin.maven-ear-plugin.skinnyWars"))) return; + + final String earClasspath = moduleResourceConfiguration.classpath; + if (earClasspath == null) return; + + final Map earClasspathMap = ContainerUtil.map2Map( + StringUtil.split(earClasspath, " "), new Function>() { + @Override + public Pair fun(String s) { + final int idx = s.lastIndexOf("/"); + return Pair.create(s.substring(idx == -1 ? 0 : idx + 1), s); + } + }); + + JpsArtifactUtil.processPackagingElements(myArtifact.getRootElement(), new Processor() { + @Override + public boolean process(JpsPackagingElement element) { + if (!(element instanceof JpsFileCopyPackagingElement)) return true; + + final String filePath = ((JpsFileCopyPackagingElement)element).getFilePath(); + final File skinnyManifest = new File(filePath); + if (!"SKINNY_MANIFEST.MF".equals(skinnyManifest.getName())) return true; + + final String skinnyWarModuleName = skinnyManifest.getParentFile().getParentFile().getName(); + final MavenModuleResourceConfiguration warConfiguration = projectConfiguration.moduleConfigurations.get(skinnyWarModuleName); + if (warConfiguration == null || warConfiguration.classpath == null) return true; + + try { + final byte[] warManifestData = Base64.decode(warConfiguration.manifest); + Manifest warManifest = new Manifest(new ByteArrayInputStream(warManifestData)); + + List skinnyWarClasspath = ContainerUtil.newArrayList(); + for (String entry : StringUtil.split(warConfiguration.classpath, " ")) { + final int idx = entry.lastIndexOf("/"); + final String entryName = entry.substring(idx == -1 ? 0 : idx + 1); + final String earEntryPath = earClasspathMap.get(entryName); + skinnyWarClasspath.add(earEntryPath == null ? entry : earEntryPath); + } + + final Attributes warManifestMainAttributes = warManifest.getMainAttributes(); + warManifestMainAttributes.putValue("Class-Path", StringUtil.join(skinnyWarClasspath, " ")); + + FileUtil.createParentDirs(skinnyManifest); + FileOutputStream outputStream = new FileOutputStream(skinnyManifest); + try { + warManifest.write(outputStream); + + final ProjectDescriptor projectDescriptor = context.getProjectDescriptor(); + final Collection descriptors = + projectDescriptor.getBuildRootIndex().findAllParentDescriptors(skinnyManifest, context); + for (BuildRootDescriptor descriptor : descriptors) { + try { + projectDescriptor.fsState.markDirty(context, skinnyManifest, descriptor, projectDescriptor.timestamps.getStorage()); + } + catch (IOException e) { + LOG.debug(e); + } + } + } + finally { + StreamUtil.closeStream(outputStream); + } + } + catch (IOException e) { + LOG.debug(e); + } + + return true; + } + }); + } + @Nullable private static String getModuleName(@NotNull String artifactName) { return StringUtil.substringBefore(artifactName, ":"); diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java index a6bf8b1e1e91..20cc5ed17b44 100644 --- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java +++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java @@ -45,6 +45,10 @@ public class MavenModuleResourceConfiguration { @Tag("manifest") public String manifest; + @Nullable + @Tag("classpath") + public String classpath; + @NotNull @Tag("delimiters-pattern") public String delimitersPattern; @@ -110,6 +114,7 @@ public class MavenModuleResourceConfiguration { result = 31 * result + (parentId != null ? parentId.hashCode() : 0); result = 31 * result + directory.hashCode(); result = 31 * result + (manifest != null ? manifest.hashCode() : 0); + result = 31 * result + (classpath != null ? classpath.hashCode() : 0); result = 31 * result + delimitersPattern.hashCode(); result = 31 * result + modelMap.hashCode(); result = 31 * result + properties.hashCode(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/ManifestImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/ManifestImporter.java index 65fb06cebfce..210f8013ee7e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/ManifestImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/ManifestImporter.java @@ -50,7 +50,7 @@ public abstract class ManifestImporter { String classpathPrefix = getClasspathPrefix(manifestConfiguration); for (MavenArtifact mavenArtifact : mavenProject.getDependencies()) { final DependencyScope scope = MavenModuleImporter.selectScope(mavenArtifact.getScope()); - if (scope.isForProductionRuntime()) { + if (scope.isForProductionCompile() || scope.isForProductionRuntime()) { if (classpath.length() > 0) { classpath.append(" "); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java index f2e55d189ad1..7732bd15d3a7 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java @@ -149,6 +149,12 @@ public abstract class MavenImporter { Map mavenProjectToModuleName, List postTasks); + public void postProcess(Module module, + MavenProject mavenProject, + MavenProjectChanges changes, + MavenModifiableModelsProvider modifiableModelsProvider) { + } + public boolean processChangedModulesOnly() { return true; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index cb7396dfb85b..954706999ba3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -159,6 +159,31 @@ public class MavenModuleImporter { }); } + public void postConfigFacets() { + MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { + public void run() { + if (myModule.isDisposed()) return; + + final ModuleType moduleType = ModuleType.get(myModule); + + for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + + if (importer.getModuleType() == moduleType) { + importer.postProcess(myModule, myMavenProject, changes, myModifiableModelsProvider); + } + } + } + }); + } + private List getSuitableImporters() { return myMavenProject.getSuitableImporters(); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java index 9ee85b83fcc5..a7b5a600516d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java @@ -431,7 +431,7 @@ public class MavenProjectImporter { javacOptions.ADDITIONAL_OPTIONS_STRING = options; } - private void importModules(final List postTasks) { + private void importModules(final List tasks) { Map projectsWithChanges = myProjectsToImportWithChanges; Set projectsWithNewlyCreatedModules = new THashSet(); @@ -471,7 +471,11 @@ public class MavenProjectImporter { } for (MavenModuleImporter importer : importers) { - importer.configFacets(postTasks); + importer.configFacets(tasks); + } + + for (MavenModuleImporter importer : importers) { + importer.postConfigFacets(); } setMavenizedModules(modulesToMavenize, true); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java index 274ee5a16193..5c4ad86a84c9 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java @@ -129,6 +129,8 @@ public class MavenResourceCompilerConfigurationGenerator { } } + addEarModelMapEntries(mavenProject, resourceConfig.modelMap); + Element pluginConfiguration = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-resources-plugin"); resourceConfig.outputDirectory = getResourcesPluginGoalOutputDirectory(mavenProject, pluginConfiguration, "resources"); @@ -190,6 +192,12 @@ public class MavenResourceCompilerConfigurationGenerator { }); } + private static void addEarModelMapEntries(@NotNull MavenProject mavenProject, @NotNull Map modelMap) { + Element pluginConfiguration = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-ear-plugin"); + final String skinnyWars = MavenJDOMUtil.findChildValueByPath(pluginConfiguration, "skinnyWars", "false"); + modelMap.put("build.plugin.maven-ear-plugin.skinnyWars", skinnyWars); + } + @Nullable private static String getResourcesPluginGoalOutputDirectory(@NotNull MavenProject mavenProject, @Nullable Element pluginConfiguration, @@ -234,6 +242,7 @@ public class MavenResourceCompilerConfigurationGenerator { finally { StreamUtil.closeStream(outputStream); } + resourceConfig.classpath = ManifestBuilder.getClasspath(mavenProject); } catch (ManifestBuilder.ManifestBuilderException e) { LOG.warn("Unable to generate artifact manifest", e); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/ManifestBuilder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/ManifestBuilder.java index dbedc4a88675..bf6bf48abe1b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/ManifestBuilder.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/ManifestBuilder.java @@ -67,18 +67,7 @@ public class ManifestBuilder { @NotNull public java.util.jar.Manifest build() throws ManifestBuilderException { try { - Element mavenPackagingPluginConfiguration = null; - final String packaging = myMavenProject.getPackaging(); - if (StringUtil.isEmpty(packaging)) { - mavenPackagingPluginConfiguration = myMavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-jar-plugin"); - } - else { - final String pluginArtifactId = PACKAGING_PLUGINS.get(StringUtil.toLowerCase(packaging)); - if (pluginArtifactId != null) { - mavenPackagingPluginConfiguration = myMavenProject.getPluginConfiguration("org.apache.maven.plugins", pluginArtifactId); - } - } - + Element mavenPackagingPluginConfiguration = getMavenPackagingPluginConfiguration(myMavenProject); final Element mavenArchiveConfiguration = mavenPackagingPluginConfiguration != null ? mavenPackagingPluginConfiguration.getChild("archive") : null; @@ -110,6 +99,16 @@ public class ManifestBuilder { } } + @NotNull + public static String getClasspath(@NotNull MavenProject mavenProject) { + Element mavenPackagingPluginConfiguration = getMavenPackagingPluginConfiguration(mavenProject); + final Element mavenArchiveConfiguration = + mavenPackagingPluginConfiguration != null ? mavenPackagingPluginConfiguration.getChild("archive") : null; + final Element manifestConfiguration = mavenArchiveConfiguration != null ? mavenArchiveConfiguration.getChild("manifest") : null; + final ManifestImporter manifestImporter = ManifestImporter.getManifestImporter(mavenProject.getPackaging()); + return manifestImporter.getClasspath(mavenProject, manifestConfiguration); + } + @NotNull public static String getClasspathPrefix(@Nullable Element manifestConfiguration) { String classpathPrefix = MavenJDOMUtil.findChildValueByPath(manifestConfiguration, "classpathPrefix", "").replaceAll("\\\\", "/"); @@ -119,6 +118,22 @@ public class ManifestBuilder { return classpathPrefix; } + @Nullable + private static Element getMavenPackagingPluginConfiguration(@NotNull MavenProject mavenProject) { + Element mavenPackagingPluginConfiguration = null; + final String packaging = mavenProject.getPackaging(); + if (StringUtil.isEmpty(packaging)) { + mavenPackagingPluginConfiguration = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-jar-plugin"); + } + else { + final String pluginArtifactId = PACKAGING_PLUGINS.get(StringUtil.toLowerCase(packaging)); + if (pluginArtifactId != null) { + mavenPackagingPluginConfiguration = mavenProject.getPluginConfiguration("org.apache.maven.plugins", pluginArtifactId); + } + } + return mavenPackagingPluginConfiguration; + } + private static Map getManifestEntries(Element manifestEntries) { boolean hasManifestEntries = manifestEntries != null && manifestEntries.getContentSize() > 0; From f4672e27777c82b7e751c8154b3218d68b1ef805 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Mon, 17 Aug 2015 17:30:20 +0300 Subject: [PATCH 02/12] OC-11982 Navigate from Objective-C to Swift derived methods and classes (review 2) --- .../com/intellij/codeInsight/navigation/GotoTargetHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java index 562b6ad544a8..f2069874326f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java @@ -242,7 +242,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { }; } - protected static PsiElementListCellRenderer createRenderer(GotoData gotoData, PsiElement eachTarget) { + public static PsiElementListCellRenderer createRenderer(GotoData gotoData, PsiElement eachTarget) { PsiElementListCellRenderer renderer = null; for (GotoTargetRendererProvider eachProvider : Extensions.getExtensions(GotoTargetRendererProvider.EP_NAME)) { renderer = eachProvider.getRenderer(eachTarget, gotoData); From b00e5ea35e03484a2c8cd82677fa8050d7fd2e76 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 17 Aug 2015 16:59:29 +0200 Subject: [PATCH 03/12] To avoid memory leak from AWT implementation, unregister action with custom shortcut attached to root pane (IDEA-143990) --- .../src/com/intellij/find/impl/FindDialog.java | 14 ++++++++++++-- 1 file changed, 12 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 1b55e7771da8..4fb51e73df83 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java @@ -24,6 +24,7 @@ import com.intellij.find.FindSettings; import com.intellij.find.actions.ShowUsagesAction; import com.intellij.ide.util.scopeChooser.ScopeChooserCombo; import com.intellij.lang.Language; +import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -647,7 +648,7 @@ public class FindDialog extends DialogWrapper { pane.insertTab("Options", null, optionsPanel, null, 0); pane.insertTab(PREVIEW_TITLE, null, myPreviewSplitter, null, RESULTS_PREVIEW_TAB_INDEX); myContent = pane; - AnAction anAction = new AnAction() { + final AnAction anAction = new AnAction() { @Override public void actionPerformed(AnActionEvent e) { int selectedIndex = myContent.getSelectedIndex(); @@ -656,7 +657,16 @@ public class FindDialog extends DialogWrapper { }; final ShortcutSet shortcutSet = ActionManager.getInstance().getAction(IdeActions.ACTION_SWITCHER).getShortcutSet(); - anAction.registerCustomShortcutSet(shortcutSet, getRootPane()); + final JRootPane rootPane = getRootPane(); + + anAction.registerCustomShortcutSet(shortcutSet, rootPane); + Disposer.register(myDisposable, new Disposable() { + @Override + public void dispose() { + anAction.unregisterCustomShortcutSet(rootPane); + } + }); + if (myPreviewResultsTabWasSelected) myContent.setSelectedIndex(RESULTS_PREVIEW_TAB_INDEX); return pane.getComponent(); From 1a9e331018ae9a919cf8a2bcc9aa45e8863d3b33 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 17 Aug 2015 17:34:38 +0200 Subject: [PATCH 04/12] IDEA-143911 (quick fix produces uncompilable code (StringBuffer can be replaced with String)) --- .../StringBufferReplaceableByStringInspection.java | 2 +- .../style/replace_with_string/Linebreaks.after.java | 9 +++++++++ .../igfixes/style/replace_with_string/Linebreaks.java | 10 ++++++++++ .../style/StringBufferReplaceableByStringFixTest.java | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java index db90214433e8..589d8d8b50d1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java @@ -209,7 +209,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { } if (element instanceof PsiWhiteSpace) { - if (element.getText().contains("\n")) { + if (element.getText().contains("\n") && result.length() > 0) { result.append('\n'); // keep line break structure } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.after.java new file mode 100644 index 000000000000..748f16c6b43d --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.after.java @@ -0,0 +1,9 @@ +class Linebreaks { + + void m(String code) { + String controlDigit = String.valueOf(code.charAt(5)) + + code.charAt(7) + + code.charAt(9) + + code.charAt(11); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.java new file mode 100644 index 000000000000..29bc796680e8 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/Linebreaks.java @@ -0,0 +1,10 @@ +class Linebreaks { + + void m(String code) { + String controlDigit = new StringBuilder() + .append(code.charAt(5)) + .append(code.charAt(7)) + .append(code.charAt(9)) + .append(code.charAt(11)).toString(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java index bf5ffba39ae1..7ce51e5e5860 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java @@ -35,4 +35,5 @@ public class StringBufferReplaceableByStringFixTest extends IGQuickFixesTestCase public void testMethodCallOnString() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); } public void testComplex1() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); } public void testComplex2() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); } + public void testLinebreaks() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); } } From cc772f3242295e5fbfe308adb42ab7896dae5122 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 17 Aug 2015 18:55:40 +0300 Subject: [PATCH 05/12] test history fixed --- .../testframework/sm/runner/ui/SMTestRunnerResultsForm.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java index 0ab67c1325d5..671255c19b78 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java @@ -41,6 +41,7 @@ import com.intellij.openapi.progress.util.ColorProgressBar; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pass; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; @@ -808,6 +809,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel new SimpleDateFormat(HISTORY_DATE_FORMAT).format(new Date()); myOutputFile = new File(AbstractImportTestsAction.getTestHistoryRoot(myProject), configurationNameIncludedDate + ".xml"); + FileUtilRt.createParentDirs(myOutputFile); handler.setResult(new StreamResult(new FileWriter(myOutputFile))); final SMTestProxy.SMRootTestProxy root = myRoot; final RunConfiguration configuration = myConfiguration; From 1e0891dac5ffe45de476e7ad29e27df730f0f42f Mon Sep 17 00:00:00 2001 From: Pavel Fatin Date: Mon, 17 Aug 2015 18:43:37 +0200 Subject: [PATCH 06/12] Zero-latency typing: skip undo / redo and PSI synchronization changes --- .../com/intellij/openapi/editor/impl/DocumentImpl.java | 7 +++++++ .../com/intellij/openapi/editor/impl/EditorImpl.java | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index a92586c8e110..ea5974deb2fb 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -624,6 +624,13 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { myGuardsSuppressed = true; } + // This data is used during the immediate editor painting to detect whether PSI synchronization is in progress. + // PsiToDocumentSynchronizer.doCommitTransaction should probably perform bulk document updates. + // TODO Remove this getter later + public boolean isGuardsSuppressed() { + return myGuardsSuppressed; + } + @Override public void unSuppressGuardedExceptions() { myGuardsSuppressed = false; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index fe17f8680acf..a327c8c10af6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -37,6 +37,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.*; @@ -2174,8 +2175,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi print(g, newText, point, ascent, font, color); } - private static boolean canPaintImmediately(@NotNull DocumentEvent e) { - return !contains(e.getOldFragment(), '\n') && + private boolean canPaintImmediately(@NotNull DocumentEvent e) { + UndoManager undoManager = UndoManager.getInstance(myProject); + return !undoManager.isUndoInProgress() && // Undo / Redo actions might start multiple write actions and make multiple document changes. + !undoManager.isRedoInProgress() && // Can we optimize the subsystem to start only one write action and do a single update? + myDocument instanceof DocumentImpl && + !((DocumentImpl)myDocument).isGuardsSuppressed() && // Heuristics. Can PsiToDocumentSynchronizer perform bulk document updates? + !contains(e.getOldFragment(), '\n') && !contains(e.getNewFragment(), '\n') && !(e.getNewLength() == 1 && DOCUMENT_CHARS_TO_SKIP.contains(e.getNewFragment().charAt(0))); } From 26042023ca1af258c5d80550162cfb2660827794 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 17 Aug 2015 18:54:25 +0200 Subject: [PATCH 07/12] cleanup. Use ScrollingUtil --- .../documentation/DocumentationManager.java | 4 ++-- .../codeInsight/lookup/impl/EndHandler.java | 6 +++--- .../codeInsight/lookup/impl/HomeHandler.java | 6 +++--- .../com/intellij/ide/util/FileStructureDialog.java | 6 +++--- .../fileTypes/impl/FileTypeConfigurable.java | 13 ++++++------- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 8e67d354fa38..f45bad48d7e5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -58,7 +58,7 @@ import com.intellij.psi.*; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilCore; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.ui.content.Content; import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.PopupPositionManager; @@ -185,7 +185,7 @@ public class DocumentationManager extends DockablePopupManager= 0) { - ListScrollingUtil.ensureIndexIsVisible(myList, selectedIndex, 0); + ScrollingUtil.ensureIndexIsVisible(myList, selectedIndex, 0); } } } diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java index 9cf3f3e46c3c..8d979438000d 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.options.*; import com.intellij.openapi.project.DumbModePermission; import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; @@ -309,7 +308,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable updateExtensionList(); final int index = myPatterns.getListModel().indexOf(matcher.getPresentableString()); if (index >= 0) { - ListScrollingUtil.selectItem(myPatterns.myPatternsList, index); + ScrollingUtil.selectItem(myPatterns.myPatternsList, index); } myPatterns.myPatternsList.requestFocus(); } @@ -512,7 +511,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable listModel.addElement(type); } } - ListScrollingUtil.ensureSelectionExists(myFileTypesList); + ScrollingUtil.ensureSelectionExists(myFileTypesList); } public int getSelectedIndex() { @@ -579,12 +578,12 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable } public void ensureSelectionExists() { - ListScrollingUtil.ensureSelectionExists(myPatternsList); + ScrollingUtil.ensureSelectionExists(myPatternsList); } public void addPatternAndSelect(String pattern) { addPattern(pattern); - ListScrollingUtil.selectItem(myPatternsList, getListModel().getSize() - 1); + ScrollingUtil.selectItem(myPatternsList, getListModel().getSize() - 1); } public void select(final String pattern) { @@ -593,7 +592,7 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable if (at instanceof String) { final FileNameMatcher matcher = FileTypeManager.parseFromString((String)at); if (FileNameMatcherEx.acceptsCharSequence(matcher, pattern)) { - ListScrollingUtil.selectItem(myPatternsList, i); + ScrollingUtil.selectItem(myPatternsList, i); return; } } From d2b8b9c292ab1f72b7541e7362f5e570aeecb504 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 17 Aug 2015 18:57:08 +0200 Subject: [PATCH 08/12] cleanup. Use ScrollingUtil --- .../codeInsight/lookup/impl/LookupActionHandler.java | 12 ++++++------ .../intellij/codeInsight/lookup/impl/LookupImpl.java | 8 ++++---- .../codeInspection/ex/SeverityEditorDialog.java | 4 ++-- .../intellij/ide/actions/SearchEverywhereAction.java | 8 ++++---- .../ide/navigationToolbar/NavBarListWrapper.java | 6 +++--- .../ide/navigationToolbar/NavBarListener.java | 6 +++--- .../intellij/ide/navigationToolbar/NavBarPopup.java | 4 ++-- .../src/com/intellij/tools/OutputFiltersDialog.java | 4 ++-- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java index 1ea0f9862af3..3216ee19c87d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import org.jetbrains.annotations.Nullable; /** @@ -84,9 +84,9 @@ public abstract class LookupActionHandler extends EditorActionHandler { } } if (up) { - ListScrollingUtil.moveUp(lookup.getList(), 0); + ScrollingUtil.moveUp(lookup.getList(), 0); } else { - ListScrollingUtil.moveDown(lookup.getList(), 0); + ScrollingUtil.moveDown(lookup.getList(), 0); } lookup.markSelectionTouched(); lookup.refreshUi(false, true); @@ -166,7 +166,7 @@ public abstract class LookupActionHandler extends EditorActionHandler { @Override protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) { lookup.setFocusDegree(LookupImpl.FocusDegree.FOCUSED); - ListScrollingUtil.movePageDown(lookup.getList()); + ScrollingUtil.movePageDown(lookup.getList()); } } @@ -178,7 +178,7 @@ public abstract class LookupActionHandler extends EditorActionHandler { @Override protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) { lookup.setFocusDegree(LookupImpl.FocusDegree.FOCUSED); - ListScrollingUtil.movePageUp(lookup.getList()); + ScrollingUtil.movePageUp(lookup.getList()); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index fb6c7c026ade..84ed80e0c3ea 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -323,7 +323,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, } if (!forceTopSelection) { - ListScrollingUtil.ensureIndexIsVisible(myList, myList.getSelectedIndex(), 1); + ScrollingUtil.ensureIndexIsVisible(myList, myList.getSelectedIndex(), 1); return; } @@ -338,7 +338,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, return; } - ListScrollingUtil.ensureRangeIsVisible(myList, top, top + myList.getLastVisibleIndex() - firstVisibleIndex); + ScrollingUtil.ensureRangeIsVisible(myList, top, top + myList.getLastVisibleIndex() - firstVisibleIndex); } boolean truncatePrefix(boolean preserveSelection) { @@ -402,7 +402,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, } private boolean isSelectionVisible() { - return ListScrollingUtil.isIndexFullyVisible(myList, myList.getSelectedIndex()); + return ScrollingUtil.isIndexFullyVisible(myList, myList.getSelectedIndex()); } private boolean checkReused() { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java index 058b4e8747c4..c39f2b35b040 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -144,7 +144,7 @@ public class SeverityEditorDialog extends DialogWrapper { ((DefaultListModel)myOptionsList.getModel()).addElement(newSeverityBasedTextAttributes); myOptionsList.clearSelection(); - ListScrollingUtil.selectItem(myOptionsList, newSeverityBasedTextAttributes); + ScrollingUtil.selectItem(myOptionsList, newSeverityBasedTextAttributes); } }).setMoveUpAction(new AnActionButtonRunnable() { @Override diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 08e51e1f9efe..15a5115fa59b 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -433,8 +433,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA if (more < newIndex) { more = myList.getItemsCount() - 1; } - ListScrollingUtil.ensureIndexIsVisible(myList, more, forward ? 1 : -1); - ListScrollingUtil.ensureIndexIsVisible(myList, newIndex, forward ? 1 : -1); + ScrollingUtil.ensureIndexIsVisible(myList, more, forward ? 1 : -1); + ScrollingUtil.ensureIndexIsVisible(myList, newIndex, forward ? 1 : -1); } } @@ -2136,7 +2136,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA myList.revalidate(); myList.repaint(); } - ListScrollingUtil.ensureSelectionExists(myList); + ScrollingUtil.ensureSelectionExists(myList); if (myList.getModel().getSize() > 0) { updatePopupBounds(); } @@ -2193,7 +2193,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA case RUN_CONFIGURATIONS: moreIndex.runConfigurations = -1; break; } } - ListScrollingUtil.selectItem(myList, index); + ScrollingUtil.selectItem(myList, index); myDone.setDone(); } catch (Exception e) { diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListWrapper.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListWrapper.java index 84777150b77c..bbf70c4e483c 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListWrapper.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package com.intellij.ide.navigationToolbar; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; @@ -53,7 +53,7 @@ class NavBarListWrapper extends JBScrollPane implements DataProvider { } }); - ListScrollingUtil.installActions(list); + ScrollingUtil.installActions(list); final int modelSize = list.getModel().getSize(); setBorder(BorderFactory.createEmptyBorder()); diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java index e0a0d946c9c5..572767e70ec9 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,7 +43,7 @@ import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiTreeChangeEvent; import com.intellij.psi.PsiTreeChangeListener; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; @@ -311,7 +311,7 @@ public class NavBarListener extends WolfTheProblemSolver.ProblemListener return action instanceof PopupAction || action instanceof CopyAction || action instanceof CutAction - || action instanceof ListScrollingUtil.ListScrollAction; + || action instanceof ScrollingUtil.ListScrollAction; } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java index 6c0374a5d744..74417627abd1 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPopup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,7 +130,7 @@ public class NavBarPopup extends LightweightHint implements Disposable{ show(myPanel, p.x - offset, p.y, myPanel, new HintHint(myPanel, p)); final JBList list = getList(); if (0 <= myIndex && myIndex < list.getItemsCount()) { - ListScrollingUtil.selectItem(list, myIndex); + ScrollingUtil.selectItem(list, myIndex); } } if (myPanel.isInFloatingMode()) { diff --git a/platform/lang-impl/src/com/intellij/tools/OutputFiltersDialog.java b/platform/lang-impl/src/com/intellij/tools/OutputFiltersDialog.java index ce2552a460ca..5f6ebe1f611c 100644 --- a/platform/lang-impl/src/com/intellij/tools/OutputFiltersDialog.java +++ b/platform/lang-impl/src/com/intellij/tools/OutputFiltersDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,7 +63,7 @@ public class OutputFiltersDialog extends DialogWrapper { append(info.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); } }); - ListScrollingUtil.ensureSelectionExists(myFiltersList); + ScrollingUtil.ensureSelectionExists(myFiltersList); } private String suggestFilterName() { From dba24e7f24d16d8ec7cf122020f8e1d5b2af07ff Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 17 Aug 2015 19:01:02 +0200 Subject: [PATCH 09/12] cleanup. Use ScrollingUtil --- .../openapi/ui/popup/PopupChooserBuilder.java | 4 +-- .../ui/ReorderableListController.java | 4 +-- .../com/intellij/util/ui/tree/TreeUtil.java | 4 +-- .../ActionMacroConfigurationPanel.java | 6 ++-- .../com/intellij/ide/actions/Switcher.java | 10 +++---- .../editor/actions/ContentChooser.java | 6 ++-- .../fileChooser/ex/FileTextFieldImpl.java | 12 ++++---- .../openapi/fileTypes/ex/FileTypeChooser.java | 4 +-- .../welcomeScreen/EditProjectGroupAction.java | 4 +-- .../impl/welcomeScreen/FlatWelcomeFrame.java | 2 +- .../RemoveSelectedProjectsAction.java | 4 +-- .../com/intellij/ui/FinderRecursivePanel.java | 2 +- .../src/com/intellij/ui/ListSpeedSearch.java | 4 +-- .../ui/MultipleTraitsListSpeedSearch.java | 4 +-- .../intellij/ui/popup/list/ListPopupImpl.java | 12 ++++---- .../com/intellij/util/ui/ListModelEditor.java | 4 +-- .../intellij/tasks/actions/SearchSupport.java | 30 +++++++++---------- .../configuration/browser/GroupList.java | 6 ++-- 18 files changed, 61 insertions(+), 61 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java index 6f108c5f4224..c7f616c90fe4 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -538,7 +538,7 @@ public class PopupChooserBuilder { ListUtil.installAutoSelectOnMouseMove(list); } - ListScrollingUtil.installActions(list); + ScrollingUtil.installActions(list); setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); myList = list; diff --git a/platform/platform-api/src/com/intellij/ui/ReorderableListController.java b/platform/platform-api/src/com/intellij/ui/ReorderableListController.java index f0c541508668..f90a9c1a8687 100644 --- a/platform/platform-api/src/com/intellij/ui/ReorderableListController.java +++ b/platform/platform-api/src/com/intellij/ui/ReorderableListController.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,7 +106,7 @@ public abstract class ReorderableListController { ((DefaultListModel)listModel).addElement(element); } myList.clearSelection(); - ListScrollingUtil.selectItem(myList, element); + ScrollingUtil.selectItem(myList, element); } public static ReorderableListController create(final JList list, final DefaultActionGroup actionGroup) { diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index 0d947d45c440..29f22ff89639 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -23,7 +23,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.treeStructure.Tree; @@ -383,7 +383,7 @@ public final class TreeUtil { return showRowCentred(tree, tree.getRowForPath(path)); } else { final int row = tree.getRowForPath(path); - return showAndSelect(tree, row - ListScrollingUtil.ROW_PADDING, row + ListScrollingUtil.ROW_PADDING, row, -1); + return showAndSelect(tree, row - ScrollingUtil.ROW_PADDING, row + ScrollingUtil.ROW_PADDING, row, -1); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java index d945e63dff53..a0d15c5b0578 100644 --- a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,7 +76,7 @@ public class ActionMacroConfigurationPanel implements Disposable { myMacrosModel.addElement(macro.clone()); } myMacrosList.setModel(myMacrosModel); - ListScrollingUtil.ensureSelectionExists(myMacrosList); + ScrollingUtil.ensureSelectionExists(myMacrosList); } public void apply() { @@ -136,7 +136,7 @@ public class ActionMacroConfigurationPanel implements Disposable { actionModel.addElement(action); } myMacroActionsList.setModel(actionModel); - ListScrollingUtil.ensureSelectionExists(myMacroActionsList); + ScrollingUtil.ensureSelectionExists(myMacroActionsList); } public JPanel getPanel() { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index f2f6dd5b9f9b..f60166870af4 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -321,10 +321,10 @@ public class Switcher extends AnAction implements DumbAware { } }); toolWindows.addKeyListener(this); - ListScrollingUtil.installActions(toolWindows); + ScrollingUtil.installActions(toolWindows); toolWindows.addMouseListener(this); toolWindows.addMouseMotionListener(this); - ListScrollingUtil.ensureSelectionExists(toolWindows); + ScrollingUtil.ensureSelectionExists(toolWindows); myClickListener.installOn(toolWindows); toolWindows.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(@NotNull ListSelectionEvent e) { @@ -512,11 +512,11 @@ public class Switcher extends AnAction implements DumbAware { files.setCellRenderer(filesRenderer); files.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); files.addKeyListener(this); - ListScrollingUtil.installActions(files); + ScrollingUtil.installActions(files); files.addMouseListener(this); files.addMouseMotionListener(this); myClickListener.installOn(files); - ListScrollingUtil.ensureSelectionExists(files); + ScrollingUtil.ensureSelectionExists(files); this.add(toolWindows, BorderLayout.WEST); if (filesModel.size() > 0) { @@ -1066,7 +1066,7 @@ public class Switcher extends AnAction implements DumbAware { files.repaint(); toolWindows.repaint(); if (value != null) { - ListScrollingUtil.ensureSelectionExists(getSelectedList(list)); + ScrollingUtil.ensureSelectionExists(getSelectedList(list)); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java index 7764bcfa51a5..125b49c95a6d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java @@ -168,8 +168,8 @@ public abstract class ContentChooser extends DialogWrapper { mySplitter.setSecondComponent(new JPanel()); rebuildListContent(); - ListScrollingUtil.installActions(myList); - ListScrollingUtil.ensureSelectionExists(myList); + ScrollingUtil.installActions(myList); + ScrollingUtil.ensureSelectionExists(myList); updateViewerForSelection(); myList.addListSelectionListener(new ListSelectionListener() { @Override @@ -309,7 +309,7 @@ public abstract class ContentChooser extends DialogWrapper { public void setSelectedIndex(int index) { myList.setSelectedIndex(index); - ListScrollingUtil.ensureIndexIsVisible(myList, index, 0); + ScrollingUtil.ensureIndexIsVisible(myList, index, 0); updateViewerForSelection(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java index 64f56eb750eb..cda2aa936254 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.codeStyle.MinusculeMatcher; import com.intellij.psi.codeStyle.NameUtil; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.ui.components.JBList; import com.intellij.ui.popup.list.GroupedItemsListRenderer; import com.intellij.util.ui.update.LazyUiDisposable; @@ -778,20 +778,20 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT if ("selectNextRow".equals(action)) { if (ensureSelectionExists()) { - ListScrollingUtil.moveDown(myList, e.getModifiersEx()); + ScrollingUtil.moveDown(myList, e.getModifiersEx()); e.consume(); } } else if ("selectPreviousRow".equals(action)) { - ListScrollingUtil.moveUp(myList, e.getModifiersEx()); + ScrollingUtil.moveUp(myList, e.getModifiersEx()); e.consume(); } else if ("scrollDown".equals(action)) { - ListScrollingUtil.movePageDown(myList); + ScrollingUtil.movePageDown(myList); e.consume(); } else if ("scrollUp".equals(action)) { - ListScrollingUtil.movePageUp(myList); + ScrollingUtil.movePageUp(myList); e.consume(); } else if (getSelectedFileFromCompletionPopup() != null && (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) && e.getModifiers() == 0) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java index 6118ebab35fd..91d50d80b69a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java @@ -29,7 +29,7 @@ import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.DoubleClickListener; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.util.FunctionUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -109,7 +109,7 @@ public class FileTypeChooser extends DialogWrapper { } ); - ListScrollingUtil.selectItem(myList, FileTypes.PLAIN_TEXT); + ScrollingUtil.selectItem(myList, FileTypes.PLAIN_TEXT); return myPanel; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/EditProjectGroupAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/EditProjectGroupAction.java index f2eea817d9ba..c7e71b8c5c3e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/EditProjectGroupAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/EditProjectGroupAction.java @@ -22,7 +22,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ui.InputValidatorEx; import com.intellij.openapi.ui.Messages; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -77,7 +77,7 @@ public class EditProjectGroupAction extends RecentProjectsWelcomeScreenActionBas Object element = model.get(i); if (element instanceof ProjectGroupActionGroup) { if (((ProjectGroupActionGroup)element).getGroup().equals(group)) { - ListScrollingUtil.selectItem(list, i); + ScrollingUtil.selectItem(list, i); break; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java index 3482fa604c0b..90eb177e4c57 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java @@ -350,7 +350,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { @Override public void run() { final JBList list = panel.second; - ListScrollingUtil.ensureSelectionExists(list); + ScrollingUtil.ensureSelectionExists(list); final ListSelectionListener[] listeners = ((DefaultListSelectionModel)list.getSelectionModel()).getListeners(ListSelectionListener.class); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RemoveSelectedProjectsAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RemoveSelectedProjectsAction.java index 866079e26cd2..1411cc5b026b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RemoveSelectedProjectsAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RemoveSelectedProjectsAction.java @@ -20,7 +20,7 @@ import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.ReopenProjectAction; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import javax.swing.*; @@ -47,7 +47,7 @@ public class RemoveSelectedProjectsAction extends RecentProjectsWelcomeScreenAct JList list = getList(e); if (list != null) { - ListScrollingUtil.ensureSelectionExists(list); + ScrollingUtil.ensureSelectionExists(list); } } diff --git a/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java b/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java index 4331a877ffbd..654ecfc3e656 100644 --- a/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java +++ b/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java @@ -217,7 +217,7 @@ public abstract class FinderRecursivePanel extends JBSplitter implements Data updateRightComponent(true); } }); - ListScrollingUtil.installActions(list); + ScrollingUtil.installActions(list); // installSpeedSearch(list); // TODO diff --git a/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java index a72b455ee340..e4fb2bf1899e 100644 --- a/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java +++ b/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,7 +43,7 @@ public class ListSpeedSearch extends SpeedSearchBase { } protected void selectElement(Object element, String selectedText) { - ListScrollingUtil.selectItem(myComponent, element); + ScrollingUtil.selectItem(myComponent, element); } protected int getSelectedIndex() { diff --git a/platform/platform-impl/src/com/intellij/ui/MultipleTraitsListSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/MultipleTraitsListSpeedSearch.java index 43545dd038a6..833cf783560b 100644 --- a/platform/platform-impl/src/com/intellij/ui/MultipleTraitsListSpeedSearch.java +++ b/platform/platform-impl/src/com/intellij/ui/MultipleTraitsListSpeedSearch.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,6 @@ public class MultipleTraitsListSpeedSearch extends MultipleTraitsSpeedSearch) { int[] indices = ((MultiSelectionListPopupStep)listStep).getDefaultOptionIndices(); if (indices.length > 0) { - ListScrollingUtil.ensureIndexIsVisible(myList, indices[0], 0); + ScrollingUtil.ensureIndexIsVisible(myList, indices[0], 0); myList.setSelectedIndices(indices); selected = true; } @@ -132,7 +132,7 @@ public class ListPopupImpl extends WizardPopup implements ListPopup { else { final int defaultIndex = listStep.getDefaultOptionIndex(); if (defaultIndex >= 0 && defaultIndex < myList.getModel().getSize()) { - ListScrollingUtil.selectItem(myList, defaultIndex); + ScrollingUtil.selectItem(myList, defaultIndex); selected = true; } } @@ -170,7 +170,7 @@ public class ListPopupImpl extends WizardPopup implements ListPopup { } if (mostUsedValue > 0) { - ListScrollingUtil.selectItem(myList, mostUsedValue); + ScrollingUtil.selectItem(myList, mostUsedValue); return true; } } @@ -237,7 +237,7 @@ public class ListPopupImpl extends WizardPopup implements ListPopup { Insets padding = UIUtil.getListViewportPadding(); myList.setBorder(new EmptyBorder(padding)); - ListScrollingUtil.installActions(myList); + ScrollingUtil.installActions(myList); myList.setCellRenderer(getListElementRenderer()); diff --git a/platform/platform-impl/src/com/intellij/util/ui/ListModelEditor.java b/platform/platform-impl/src/com/intellij/util/ui/ListModelEditor.java index a93d61051905..67005649dcb7 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/ListModelEditor.java +++ b/platform/platform-impl/src/com/intellij/util/ui/ListModelEditor.java @@ -43,14 +43,14 @@ public class ListModelEditor extends ListModelEditorBase { if (!model.isEmpty()) { T lastItem = model.getElementAt(model.getSize() - 1); if (ListModelEditor.this.itemEditor.isEmpty(lastItem)) { - ListScrollingUtil.selectItem(list, ContainerUtil.indexOfIdentity(model.getItems(), lastItem)); + ScrollingUtil.selectItem(list, ContainerUtil.indexOfIdentity(model.getItems(), lastItem)); return; } } T item = createElement(); model.add(item); - ListScrollingUtil.selectItem(list, ContainerUtil.indexOfIdentity(model.getItems(), item)); + ScrollingUtil.selectItem(list, ContainerUtil.indexOfIdentity(model.getItems(), item)); } }) .setRemoveActionUpdater(new AnActionButtonUpdater() { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SearchSupport.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SearchSupport.java index 13e38cc72a83..8b99213f41f8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SearchSupport.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SearchSupport.java @@ -1,17 +1,17 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.intellij.tasks.actions; @@ -29,7 +29,7 @@ import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.util.Computable; import com.intellij.tasks.Task; import com.intellij.ui.EditorTextField; -import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScrollingUtil; import com.intellij.ui.SortedListModel; import com.intellij.ui.components.JBList; import org.jetbrains.annotations.Nullable; @@ -141,17 +141,17 @@ public abstract class SearchSupport { if ("selectNextRow".equals(action)) { if (ensureSelectionExists()) { - ListScrollingUtil.moveDown(myList, e.getModifiersEx()); + ScrollingUtil.moveDown(myList, e.getModifiersEx()); } } else if ("selectPreviousRow".equals(action)) { - ListScrollingUtil.moveUp(myList, e.getModifiersEx()); + ScrollingUtil.moveUp(myList, e.getModifiersEx()); } else if ("scrollDown".equals(action)) { - ListScrollingUtil.movePageDown(myList); + ScrollingUtil.movePageDown(myList); } else if ("scrollUp".equals(action)) { - ListScrollingUtil.movePageUp(myList); + ScrollingUtil.movePageUp(myList); } else if ((e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) && e.getModifiers() == 0) { hideCurrentPopup(); diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/browser/GroupList.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/browser/GroupList.java index 7f14866d0cfe..c0be62ab92a6 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/browser/GroupList.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/browser/GroupList.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,8 @@ package com.theoryinpractice.testng.configuration.browser; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.psi.PsiClass; -import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.ScrollingUtil; import com.intellij.ui.SortedListModel; import com.intellij.ui.components.JBList; import com.intellij.util.ArrayUtil; @@ -50,7 +50,7 @@ public class GroupList extends JPanel model.addAll(array); add(ScrollPaneFactory.createScrollPane(list)); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - ListScrollingUtil.ensureSelectionExists(list); + ScrollingUtil.ensureSelectionExists(list); } public String getSelected() From 95072fb6f241e1df8fa9d7d9b85b0fac23135d7c Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 17 Aug 2015 19:25:45 +0200 Subject: [PATCH 10/12] IDEA-143772 IDEA shows deleted files in command line diff between two folders --- .../src/com/intellij/diff/applications/DiffApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java index 9e2f84f0b1ca..5e67bdb39b68 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java @@ -58,7 +58,7 @@ public class DiffApplication extends ApplicationStarterBase { if (file1 == null) throw new Exception("Can't find file " + path1); if (file2 == null) throw new Exception("Can't find file " + path2); - VfsUtil.markDirtyAndRefresh(false, false, false, file1, file2); + VfsUtil.markDirtyAndRefresh(false, true, true, file1, file2); DiffRequest request = DiffRequestFactory.getInstance().createFromFiles(null, file1, file2); Project project = DefaultProjectFactory.getInstance().getDefaultProject(); From adb87edba73131617c8cd93c8b4b972371d60fd3 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 17 Aug 2015 19:35:37 +0200 Subject: [PATCH 11/12] javadoc for AutomaticRenamerFactory --- .../naming/AutomaticRenamerFactory.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamerFactory.java b/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamerFactory.java index dc747b921247..9500a8896b13 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamerFactory.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamerFactory.java @@ -19,24 +19,62 @@ package com.intellij.refactoring.rename.naming; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiElement; import com.intellij.usageView.UsageInfo; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; /** + * When an element is renamed, allows to prompt the user to rename other elements with names derived from the name of the + * element being renamed (for example, when a class is renamed, allows to prompt the user to rename variables of this class + * that have names similar to the name of the class). + * * @author yole */ public interface AutomaticRenamerFactory { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.automaticRenamerFactory"); + /** + * Checks if this factory can provide additional elements to be renamed for the given element being renamed. + * + * @param element the element being renamed. + * @return + */ boolean isApplicable(@NotNull PsiElement element); + /** + * Returns the title of the checkbox shown in the rename dialog which enables or disables this renamer factory, + * or null if the renamer factory does not require showing a checkbox in the rename dialog. + * + * @return the checkbox title. + */ @Nullable + @Nls String getOptionName(); + /** + * Returns true if this renamer factory is enabled (and the checkbox representing its state should be checked.) + * Normally, the implementation of this method needs to load the persisted state of the checkbox. + * @return + */ boolean isEnabled(); + + /** + * Persists the state of the checkbox which enables or disables the renamer factory. + * + * @param enabled true if the checkbox is checked, false otherwise. + */ void setEnabled(boolean enabled); + /** + * Creates an automatic renamer for the given rename operation. + * + * @param element the primary element being renamed. + * @param newName the new name of the element + * @param usages the list of usages of the primary element. + * @return the renamer instance. + */ + @NotNull AutomaticRenamer createRenamer(final PsiElement element, final String newName, final Collection usages); } From bc1d2b78da6cb64db34e65a40172fb5350b2d32e Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Mon, 17 Aug 2015 18:42:28 +0300 Subject: [PATCH 12/12] TreeTraversal: make iterator() lazy and simplify FilteredTraverser: add forceExpandAndSkip --- .../src/com/intellij/psi/SyntaxTraverser.java | 7 +- .../util/containers/TreeTraverserTest.java | 89 +++++++++++-- .../containers/FilteredTraverserBase.java | 89 ++++++++----- .../util/containers/TreeTraversal.java | 121 +++++++++++------- 4 files changed, 210 insertions(+), 96 deletions(-) diff --git a/platform/core-api/src/com/intellij/psi/SyntaxTraverser.java b/platform/core-api/src/com/intellij/psi/SyntaxTraverser.java index 9aa092e1c392..785de7e4b5ad 100644 --- a/platform/core-api/src/com/intellij/psi/SyntaxTraverser.java +++ b/platform/core-api/src/com/intellij/psi/SyntaxTraverser.java @@ -15,6 +15,8 @@ import org.jetbrains.annotations.Nullable; import java.util.Iterator; import java.util.LinkedList; +import static com.intellij.openapi.util.Conditions.compose; + /** * @author gregsh */ @@ -96,12 +98,12 @@ public class SyntaxTraverser extends FilteredTraverserBase expandTypes(@NotNull Condition condition) { - return super.expand(Conditions.compose(api.TO_TYPE(), condition)); + return super.expand(compose(api.TO_TYPE(), condition)); } @NotNull public SyntaxTraverser filterTypes(@NotNull Condition condition) { - return super.filter(Conditions.compose(api.TO_TYPE(), condition)); + return super.filter(compose(api.TO_TYPE(), condition)); } @Nullable @@ -125,7 +127,6 @@ public class SyntaxTraverser extends FilteredTraverserBase implements Function> { @NotNull public abstract IElementType typeOf(@NotNull T node); diff --git a/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java b/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java index 0911b7c74fbb..fe4baed38dad 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java @@ -16,15 +16,14 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.util.Function; import com.intellij.util.Functions; import com.intellij.util.PairFunction; import junit.framework.TestCase; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; +import java.util.*; /** * @author gregsh @@ -40,6 +39,23 @@ public class TreeTraverserTest extends TestCase { build(); } + private static Map> numbers2() { + return ContainerUtil.>immutableMapBuilder(). + put(1, Arrays.asList(2, 3, 4)). + put(2, Arrays.asList(5, 6, 7)). + put(3, Arrays.asList(8, 9, 10)). + put(4, Arrays.asList(11, 12, 13)). + put(5, Arrays.asList(14, 15, 16)). + put(6, Arrays.asList(17, 18, 19)). + put(7, Arrays.asList(20, 21, 22)). + put(8, Arrays.asList(23, 24, 25)). + put(9, Arrays.asList(26, 27, 28)). + put(10, Arrays.asList(29, 30, 31)). + put(11, Arrays.asList(32, 33, 34)). + put(12, Arrays.asList(35, 36, 37)). + build(); + } + private static final Condition IS_ODD = new Condition() { @Override public boolean value(Integer integer) { @@ -47,6 +63,15 @@ public class TreeTraverserTest extends TestCase { } }; + private static Condition inRange(final int s, final int e) { + return new Condition() { + @Override + public boolean value(Integer integer) { + return s <= integer && integer <= e; + } + }; + } + private static final Function INCREMENT = new Function() { @Override public Integer fun(Integer k) { @@ -177,20 +202,37 @@ public class TreeTraverserTest extends TestCase { // TreeTraversal ---------------------------------------------- @NotNull - private static Function> traverser(TreeTraversal t) { + private static Function> numTraverser(TreeTraversal t) { return t.traversal(Functions.fromMap(numbers())); } + @NotNull + private static Function> numTraverser2(TreeTraversal t) { + return t.traversal(Functions.fromMap(numbers2())); + } public void testSimplePreOrderDfs() { - assertEquals(Arrays.asList(1, 2, 5, 6, 7, 3, 8, 9, 10, 4, 11, 12, 13), traverser(TreeTraversal.PRE_ORDER_DFS).fun(1).toList()); + assertEquals(Arrays.asList(1, 2, 5, 6, 7, 3, 8, 9, 10, 4, 11, 12, 13), numTraverser(TreeTraversal.PRE_ORDER_DFS).fun(1).toList()); + } + + public void testSimplePreOrderDfsBacktrace() { + List backDfs = Collections.emptyList(); + for (TreeTraversal.TracingIt it = numTraverser2(TreeTraversal.PRE_ORDER_DFS).fun(1).typedIterator(); it.hasNext(); ) { + if (it.next().equals(37)) backDfs = it.backtrace().toList(); + } + List backBfs = Collections.emptyList(); + for (TreeTraversal.TracingIt it = numTraverser2(TreeTraversal.TRACING_BFS).fun(1).typedIterator(); it.hasNext(); ) { + if (it.next().equals(37)) backBfs = it.backtrace().toList(); + } + assertEquals(Arrays.asList(37, 12, 4, 1), backDfs); + assertEquals(Arrays.asList(37, 12, 4, 1), backBfs); } public void testSimplePostOrderDfs() { - assertEquals(Arrays.asList(5, 6, 7, 2, 8, 9, 10, 3, 11, 12, 13, 4, 1), traverser(TreeTraversal.POST_ORDER_DFS).fun(1).toList()); + assertEquals(Arrays.asList(5, 6, 7, 2, 8, 9, 10, 3, 11, 12, 13, 4, 1), numTraverser(TreeTraversal.POST_ORDER_DFS).fun(1).toList()); } public void testSimpleBfs() { - assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), traverser(TreeTraversal.PLAIN_BFS).fun(1).toList()); + assertEquals(JBIterable.generate(1, INCREMENT).take(37).toList(), numTraverser2(TreeTraversal.PLAIN_BFS).fun(1).toList()); } // FilteredTraverser ---------------------------------------------- @@ -217,18 +259,43 @@ public class TreeTraverserTest extends TestCase { public void testSkipExpandedDfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(2, 8, 9, 10, 4), t.withRoot(1).expand(IS_ODD).leavesOnly(true).leavesOnlyDfsTraversal().toList()); + assertEquals(Arrays.asList(2, 8, 9, 10, 4), t.withRoot(1).expand(IS_ODD).leavesOnlyDfsTraversal().toList()); + } + + public void testRangeChildrenLeavesDfs() { + FilteredTraverser t = filteredTraverser(); + assertEquals(Arrays.asList(5, 6, 3, 11, 12, 13), t.withRoot(1).children(Conditions.not(inRange(7, 10))).leavesOnlyDfsTraversal().toList()); + } + + public void testRangeChildrenLeavesBfs() { + FilteredTraverser t = filteredTraverser(); + assertEquals(Arrays.asList(5, 6, 3, 11, 12, 13), t.withRoot(1).children(Conditions.not(inRange(7, 10))).leavesOnlyDfsTraversal().toList()); } public void testSkipExpandedBfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(2, 4, 8, 9, 10), t.withRoot(1).expand(IS_ODD).leavesOnly(true).leavesOnlyBfsTraversal().toList()); + assertEquals(Arrays.asList(2, 4, 8, 9, 10), t.withRoot(1).expand(IS_ODD).leavesOnlyBfsTraversal().toList()); } public void testExpandSkipFilterReset() { FilteredTraverser t = filteredTraverser(); assertEquals(Arrays.asList(1, 5, 7, 3, 9, 11, 13), t.withRoot(1).expand(IS_ODD). - leavesOnly(true).reset().filter(IS_ODD).toList()); + withTraversal(TreeTraversal.LEAVES_ONLY_DFS).reset().filter(IS_ODD).toList()); + } + + public void testForceExlcudeReset() { + FilteredTraverser t = filteredTraverser(); + assertEquals(Arrays.asList(1, 2, 6, 4, 12), t.withRoot(1).forceExclude(IS_ODD).reset().toList()); + } + + public void testForceSkipReset() { + FilteredTraverser t = filteredTraverser(); + assertEquals(Arrays.asList(1, 2, 6, 8, 10, 4, 12), t.withRoot(1).forceExpandAndSkip(IS_ODD).reset().toList()); + } + + public void testForceSkipLeavesDfs() { + FilteredTraverser t = filteredTraverser(); + assertEquals(Arrays.asList(6, 8, 10, 12), t.withRoot(1).forceExpandAndSkip(IS_ODD).leavesOnlyDfsTraversal().toList()); } public void testFilterChildren() { @@ -257,7 +324,7 @@ public class TreeTraverserTest extends TestCase { TreeTraversal.TracingIt cursor = JBIterator.cursor(it).first(); assertNotNull(cursor); assertSame(cursor, it); - assertEquals(Arrays.asList(20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1), cursor.backtrace().toList()); + assertEquals(Arrays.asList(21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1), cursor.backtrace().toList()); } } diff --git a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java index fa2e6770027e..b2bdab21aba1 100644 --- a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java +++ b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java @@ -16,7 +16,6 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Conditions; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,6 +24,8 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import static com.intellij.openapi.util.Conditions.*; + public abstract class FilteredTraverserBase> implements Iterable { protected final Meta meta; @@ -66,7 +67,7 @@ public abstract class FilteredTraverserBase traverse() { - return meta.skipExpanded ? leavesOnlyDfsTraversal() : preOrderDfsTraversal(); + return traverse(meta.traversal); } @NotNull @@ -101,7 +102,7 @@ public abstract class FilteredTraverserBaseempty().exclude(meta.excludeFilter).withRoots(meta.roots)); + return newInstance(Meta.empty().forceExclude(meta.forceExclude).forceExpandAndSkip(meta.forceExpandAndSkip).withRoots(meta.roots)); } @NotNull @@ -115,8 +116,8 @@ public abstract class FilteredTraverserBase filter) { - return newInstance(meta.expand(filter).filter(Conditions.not(filter))); + return newInstance(meta.expand(filter).filter(not(filter))); } @NotNull @@ -150,15 +151,22 @@ public abstract class FilteredTraverserBase filter) { - return newInstance(meta.exclude(filter)); + public Self forceExclude(@NotNull Condition filter) { + return newInstance(meta.forceExclude(filter)); + } + + @NotNull + public Self forceExpandAndSkip(@NotNull Condition filter) { + return newInstance(meta.forceExpandAndSkip(filter)); } @NotNull public JBIterable children(@NotNull T node) { if (isAlwaysLeaf(node)) return JBIterable.empty(); JBIterable children = JBIterable.from(tree.fun(node)); - if (meta.childFilter == Conditions.TRUE) return children.filter(Conditions.not(meta.excludeFilter)); + if (meta.childFilter == TRUE && meta.forceExpandAndSkip == Condition.FALSE) { + return children.filter(not(meta.forceExclude)); + } // traverse subtree to select accepted children return newInstance(meta.forChildren(children)).traverse(); } @@ -179,61 +187,76 @@ public abstract class FilteredTraverserBase { - final Iterable roots; - final boolean skipExpanded; - final Condition expandFilter; - final Condition childFilter; - final Condition resultFilter; - final Condition excludeFilter; + public final Iterable roots; + public final TreeTraversal traversal; + public final Condition expandFilter; + public final Condition childFilter; + public final Condition resultFilter; + + public final Condition forceExclude; + public final Condition forceExpandAndSkip; public Meta(@NotNull Iterable roots, - boolean skipExpanded, + @NotNull TreeTraversal traversal, @NotNull Condition expandFilter, @NotNull Condition childFilter, @NotNull Condition resultFilter, - @NotNull Condition excludeFilter) { + @NotNull Condition forceExclude, + @NotNull Condition forceExpandAndSkip) { this.roots = roots; - this.skipExpanded = skipExpanded; + this.traversal = traversal; this.expandFilter = expandFilter; this.childFilter = childFilter; this.resultFilter = resultFilter; - this.excludeFilter = excludeFilter; + this.forceExclude = forceExclude; + this.forceExpandAndSkip = forceExpandAndSkip; } public Meta withRoots(@NotNull Iterable roots) { - return new Meta(roots, skipExpanded, expandFilter, childFilter, resultFilter, excludeFilter); + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude, forceExpandAndSkip); } - public Meta skipExpanded(boolean flag) { - return new Meta(roots, flag, expandFilter, childFilter, resultFilter, excludeFilter); + public Meta withTraversal(TreeTraversal traversal) { + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude, forceExpandAndSkip); } public Meta expand(@NotNull Condition filter) { - return new Meta(roots, skipExpanded, Conditions.and2(expandFilter, filter), childFilter, resultFilter, excludeFilter); + return new Meta(roots, traversal, and2(expandFilter, filter), childFilter, resultFilter, forceExclude, + forceExpandAndSkip); } public Meta children(@NotNull Condition filter) { - return new Meta(roots, skipExpanded, expandFilter, Conditions.and2(childFilter, filter), resultFilter, excludeFilter); + return new Meta(roots, traversal, expandFilter, and2(childFilter, filter), resultFilter, forceExclude, + forceExpandAndSkip); } public Meta filter(@NotNull Condition filter) { - return new Meta(roots, skipExpanded, expandFilter, childFilter, Conditions.and2(resultFilter, filter), excludeFilter); + return new Meta(roots, traversal, expandFilter, childFilter, and2(resultFilter, filter), forceExclude, + forceExpandAndSkip); } - public Meta exclude(Condition filter) { - // exclude filter is always accumulated - return new Meta(roots, skipExpanded, expandFilter, childFilter, resultFilter, Conditions.or2(excludeFilter, filter)); + // forceExclude and forceSkip filter is always accumulated + public Meta forceExclude(Condition filter) { + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, or2(forceExclude, filter), + forceExpandAndSkip); + } + + public Meta forceExpandAndSkip(Condition filter) { + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude, or2(forceExpandAndSkip, filter)); + } + + public Meta forChildren(JBIterable children) { + Condition expand = or2(forceExpandAndSkip, not(childFilter)); + return new Meta(children, TreeTraversal.LEAVES_ONLY_DFS, expand, TRUE, not(or2(expand, forceExclude)), FALSE, FALSE); } private static final Meta EMPTY = new Meta( - JBIterable.empty(), false, Conditions.TRUE, Conditions.TRUE, Conditions.TRUE, Conditions.FALSE); + JBIterable.empty(), TreeTraversal.PRE_ORDER_DFS, + TRUE, TRUE, TRUE, + FALSE, FALSE); public static Meta empty() { return (Meta)EMPTY; } - - public Meta forChildren(Iterable children) { - return new Meta(children, false, Conditions.not(childFilter), Conditions.TRUE, childFilter, excludeFilter); - } } } diff --git a/platform/util/src/com/intellij/util/containers/TreeTraversal.java b/platform/util/src/com/intellij/util/containers/TreeTraversal.java index fc0e98006519..87258b7c75a2 100644 --- a/platform/util/src/com/intellij/util/containers/TreeTraversal.java +++ b/platform/util/src/com/intellij/util/containers/TreeTraversal.java @@ -16,15 +16,14 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Pair; import com.intellij.util.Function; -import com.intellij.util.Functions; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayDeque; import java.util.Iterator; import java.util.Map; +import java.util.NoSuchElementException; /** * A redesigned version of com.google.common.collect.TreeTraversal. @@ -203,55 +202,51 @@ public abstract class TreeTraversal { // ----------------------------------------------------------------------------- private abstract static class DfsIt extends TracingIt { - final ArrayDeque>> stack = new ArrayDeque>>(); + final ArrayDeque> stack = new ArrayDeque>(); @Nullable public T parent() { - Iterator>> it = stack.descendingIterator(); + if (stack.isEmpty()) throw new NoSuchElementException(); + Iterator> it = stack.descendingIterator(); it.next(); - return it.hasNext() ? it.next().first : null; + return it.hasNext() ? it.next().node : null; } @NotNull public JBIterable backtrace() { - return new JBIterable>>() { + if (stack.isEmpty()) throw new NoSuchElementException(); + return new JBIterable>() { @Override - public Iterator>> iterator() { - Iterator>> iterator = stack.descendingIterator(); - iterator.next(); - return iterator; + public Iterator> iterator() { + return stack.descendingIterator(); } - }.transform(Functions.pairFirst()).filter(Condition.NOT_NULL); + }.transform(P.toNode()).filter(Condition.NOT_NULL); } } private final static class PreOrderIt extends DfsIt { final Function> tree; - int doneCount; PreOrderIt(@NotNull Iterable roots, Function> tree) { this.tree = tree; - Iterator iterator = roots.iterator(); - if (iterator.hasNext()) { - stack.addLast(Pair.>create(null, iterator)); - } + stack.addLast(P.create(roots)); } @Override public T nextImpl() { - if (stack.size() <= doneCount) return stop(); - Pair> top; - while (!(top = stack.getLast()).second.hasNext()) { - stack.removeLast(); - doneCount--; + while (!stack.isEmpty()) { + Iterator it = stack.getLast().iterator(tree); + if (it.hasNext()) { + T result = it.next(); + stack.addLast(P.create(result)); + return result; + } + else { + stack.removeLast(); + } } - T result = top.second.next(); - if (!top.second.hasNext()) doneCount++; - Iterator childItr = children(result, tree).iterator(); - stack.addLast(Pair.>create(result, childItr)); - if (!childItr.hasNext()) doneCount++; - return result; + return stop(); } } @@ -262,21 +257,20 @@ public abstract class TreeTraversal { PostOrderIt(@NotNull Iterable roots, Function> tree) { this.tree = tree; for (T root : roots) { - stack.addLast(Pair.>create(root, children(root, tree).iterator())); + stack.addLast(P.create(root)); } } @Override public T nextImpl() { while (!stack.isEmpty()) { - Pair> top = stack.getLast(); - if (top.second.hasNext()) { - T child = top.second.next(); - stack.addLast(Pair.>create(child, children(child, tree).iterator())); + Iterator it = stack.getLast().iterator(tree); + if (it.hasNext()) { + T result = it.next(); + stack.addLast(P.create(result)); } else { - stack.removeLast(); - return top.first; + return stack.removeLast().node; } } return stop(); @@ -289,29 +283,20 @@ public abstract class TreeTraversal { LeavesDfsIt(@NotNull Iterable roots, Function> tree) { this.tree = tree; - for (T root : roots) { - Iterator childrenIt = children(root, tree).iterator(); - stack.addLast(Pair.>create(root, childrenIt.hasNext() ? childrenIt : null)); - } + stack.addLast(P.create(roots)); } @Override public T nextImpl() { while (!stack.isEmpty()) { - Pair> top = stack.getLast(); - if (top.second != null && top.second.hasNext()) { - T child = top.second.next(); - Iterator childrenIt = children(child, tree).iterator(); - if (childrenIt.hasNext()) { - stack.addLast(Pair.>create(child, childrenIt)); - } - else { - return child; - } + P top = stack.getLast(); + if (top.iterator(tree).hasNext() && !top.empty) { + T child = top.iterator(tree).next(); + stack.addLast(P.create(child)); } else { stack.removeLast(); - if (top.second == null) return top.first; + if (top.empty) return stack.isEmpty() ? stop() : top.node; } } return stop(); @@ -410,4 +395,42 @@ public abstract class TreeTraversal { }; } } + + private static class P { + T node; + Iterable itle; + Iterator it; + boolean empty; + + Iterator iterator(@NotNull Function> tree) { + if (it != null) return it; + it = (itle != null ? itle : (itle = children(node, tree))).iterator(); + empty = !it.hasNext(); + return it; + } + + static P create(T node) { + P p = new P(); + p.node = node; + return p; + } + + static P create(Iterable it) { + P p = new P(); + p.itle = it; + return p; + } + + static Function, T> toNode() { + //noinspection unchecked + return TO_NODE; + } + + static final Function TO_NODE = new Function, Object>() { + @Override + public Object fun(P tp) { + return tp.node; + } + }; + } }