From a40c2d2035f6db2f68313bcfa5bdfcf14d6e384f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 7 Oct 2014 18:17:46 +0400 Subject: [PATCH 01/16] [vcs] VcsManagerPerModuleConfiguration: remove usages --- .../openapi/vcs/impl/VcsManagerPerModuleConfiguration.java | 1 + resources/src/componentSets/IdeaComponents.xml | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsManagerPerModuleConfiguration.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsManagerPerModuleConfiguration.java index c97c8cef3968..d7597921a2f6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsManagerPerModuleConfiguration.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsManagerPerModuleConfiguration.java @@ -36,6 +36,7 @@ import org.jetbrains.annotations.Nullable; * @deprecated to remove in IDEA 15 */ @Deprecated +@SuppressWarnings("UnusedDeclaration") @State( name = "VcsManagerConfiguration", storages = @Storage(file = StoragePathMacros.MODULE_FILE) diff --git a/resources/src/componentSets/IdeaComponents.xml b/resources/src/componentSets/IdeaComponents.xml index 265d81babdf1..7a1c7f048668 100644 --- a/resources/src/componentSets/IdeaComponents.xml +++ b/resources/src/componentSets/IdeaComponents.xml @@ -50,10 +50,5 @@ - - - com.intellij.openapi.vcs.impl.VcsManagerPerModuleConfiguration - - From 3deef87307ba8240288bce8de1bf35f0bb74fe9a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 7 Oct 2014 18:25:46 +0400 Subject: [PATCH 02/16] [git] IDEA-130898 Fields must be final --- plugins/git4idea/src/git4idea/push/GitPushTagMode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/push/GitPushTagMode.java b/plugins/git4idea/src/git4idea/push/GitPushTagMode.java index 6c28cc109f67..f0a05d355ae0 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushTagMode.java +++ b/plugins/git4idea/src/git4idea/push/GitPushTagMode.java @@ -25,8 +25,8 @@ public final class GitPushTagMode implements VcsPushOptionValue { public static GitPushTagMode ALL = new GitPushTagMode("All", "--tags"); public static GitPushTagMode FOLLOW = new GitPushTagMode("Current Branch", "--follow-tags"); - @NotNull private final String myTitle; - @NotNull private final String myArgument; + @NotNull public final String myTitle; + @NotNull public final String myArgument; // for deserialization @SuppressWarnings("UnusedDeclaration") From 1067d708f8b48509c01546641daa183af83ca371 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 7 Oct 2014 16:39:23 +0200 Subject: [PATCH 03/16] IDEA-130766 (Bogus floating point equality inspection for infinity constants) --- .../FloatingPointEqualityInspection.java | 19 +++++++++- .../FloatingPointEquality.html | 4 +- .../bugs/FloatingPointEqualityInspection.java | 36 ------------------ .../FloatingPointEquality.java | 38 +++++++++++++++++++ .../FloatingPointEqualityInspectionTest.java | 35 +++++++++++++++++ 5 files changed, 92 insertions(+), 40 deletions(-) delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/FloatingPointEqualityInspection.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/floating_point_equality/FloatingPointEquality.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/FloatingPointEqualityInspectionTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java index 6e0d8e81b0c2..4f3b272e4522 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,10 +60,25 @@ public class FloatingPointEqualityInspection extends BaseInspection { if (!TypeUtils.hasFloatingPointType(lhs) && !TypeUtils.hasFloatingPointType(rhs)) { return; } - if (ExpressionUtils.isZero(lhs) || ExpressionUtils.isZero(rhs)) { + if (isInfinityOrZero(lhs) || isInfinityOrZero(rhs)) { return; } registerError(expression); } + + private static boolean isInfinityOrZero(PsiExpression expression) { + final Object value = ExpressionUtils.computeConstantExpression(expression); + if (value instanceof Double) { + final Double aDouble = (Double)value; + final double v = aDouble.doubleValue(); + return v == Double.NEGATIVE_INFINITY || v == Double.POSITIVE_INFINITY || v == 0.0; + } + else if (value instanceof Float) { + final Float aFloat = (Float)value; + final float f = aFloat.floatValue(); + return f == Float.NEGATIVE_INFINITY || f == Float.POSITIVE_INFINITY || f == 0.0f; + } + return false; + } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/FloatingPointEquality.html b/plugins/InspectionGadgets/src/inspectionDescriptions/FloatingPointEquality.html index 82b9dc0d0838..88405aca7bf6 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/FloatingPointEquality.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/FloatingPointEquality.html @@ -1,10 +1,10 @@ Reports floating-point values -being compared with == or !=. +being compared with an == or != operator. Floating point values are inherently inaccurate, and comparing them for exact equality is almost never the desired semantics. This inspection ignores comparisons -with zero literals. +with zero and infinity literals.

diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/FloatingPointEqualityInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/FloatingPointEqualityInspection.java deleted file mode 100644 index 5801819af572..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/FloatingPointEqualityInspection.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.siyeh.igtest.bugs; - -public class FloatingPointEqualityInspection -{ - private double m_bar; - private double m_baz; - private float m_barf; - private float m_bazf; - - public static final float TENTH = 0.1f; - public static final float fifth = 0.2f; - - public FloatingPointEqualityInspection() - { - m_bar = 0.0; - m_baz = 1.0; - m_barf = TENTH; - m_bazf = fifth; - } - - public void foo() - { - if (m_bar == m_baz) { - System.out.println("m_bar = " + m_bar); - } - if (m_barf == m_bazf) { - System.out.println("m_barf = " + m_barf); - } - if (m_barf != m_bar) { - System.out.println("m_barf = " + m_barf); - } - - } - - -} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/floating_point_equality/FloatingPointEquality.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/floating_point_equality/FloatingPointEquality.java new file mode 100644 index 000000000000..0d436471570d --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/floating_point_equality/FloatingPointEquality.java @@ -0,0 +1,38 @@ + +public class FloatingPointEquality +{ + private double m_bar; + private double m_baz; + private float m_barf; + private float m_bazf; + + public static final float TENTH = 0.1f; + public static final float fifth = 0.2f; + + public FloatingPointEquality() + { + m_bar = 0.0; + m_baz = 1.0; + m_barf = TENTH; + m_bazf = fifth; + } + + public void foo() + { + if (m_bar == m_baz) { + System.out.println("m_bar = " + m_bar); + } + if (m_barf == m_bazf) { + System.out.println("m_barf = " + m_barf); + } + if (m_barf != m_bar) { + System.out.println("m_barf = " + m_barf); + } + + boolean infinity = m_bar == Double.POSITIVE_INFINITY; + boolean zero = m_barf == 0.0f; + + } + + +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/FloatingPointEqualityInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/FloatingPointEqualityInspectionTest.java new file mode 100644 index 000000000000..794373696149 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/FloatingPointEqualityInspectionTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ig.numeric; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import junit.framework.TestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class FloatingPointEqualityInspectionTest extends LightInspectionTestCase { + + public void testFloatingPointEquality() { doTest(); } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new FloatingPointEqualityInspection(); + } +} \ No newline at end of file From 7355361cdc207acc15f6f0903e6b31179f05ceae Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 7 Oct 2014 18:57:14 +0400 Subject: [PATCH 04/16] [git] IDEA-130898 fields must be not-final even when public --- .../src/git4idea/push/GitPushTagMode.java | 20 +++++++++++++++---- .../src/git4idea/push/GitPushTagPanel.java | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/push/GitPushTagMode.java b/plugins/git4idea/src/git4idea/push/GitPushTagMode.java index f0a05d355ae0..1283dc4a9911 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushTagMode.java +++ b/plugins/git4idea/src/git4idea/push/GitPushTagMode.java @@ -22,11 +22,11 @@ import org.jetbrains.annotations.NotNull; */ public final class GitPushTagMode implements VcsPushOptionValue { - public static GitPushTagMode ALL = new GitPushTagMode("All", "--tags"); - public static GitPushTagMode FOLLOW = new GitPushTagMode("Current Branch", "--follow-tags"); + public static final GitPushTagMode ALL = new GitPushTagMode("All", "--tags"); + public static final GitPushTagMode FOLLOW = new GitPushTagMode("Current Branch", "--follow-tags"); - @NotNull public final String myTitle; - @NotNull public final String myArgument; + @NotNull private String myTitle; + @NotNull private String myArgument; // for deserialization @SuppressWarnings("UnusedDeclaration") @@ -54,6 +54,18 @@ public final class GitPushTagMode implements VcsPushOptionValue { return myArgument; } + // for deserialization + @SuppressWarnings("UnusedDeclaration") + public void setTitle(@NotNull String title) { + myTitle = title; + } + + // for deserialization + @SuppressWarnings("UnusedDeclaration") + public void setArgument(@NotNull String argument) { + myArgument = argument; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/plugins/git4idea/src/git4idea/push/GitPushTagPanel.java b/plugins/git4idea/src/git4idea/push/GitPushTagPanel.java index 21a86a63ac41..7201067d5c6f 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushTagPanel.java +++ b/plugins/git4idea/src/git4idea/push/GitPushTagPanel.java @@ -33,7 +33,7 @@ class GitPushTagPanel extends VcsPushOptionsPanel { private final ComboBox myCombobox; private final JBCheckBox myCheckBox; - GitPushTagPanel(@Nullable GitPushTagMode defaultMode, boolean followTagsSupported) { + GitPushTagPanel(@NotNull GitPushTagMode defaultMode, boolean followTagsSupported) { String checkboxText = "Push Tags"; if (followTagsSupported) { checkboxText += ": "; From 80d8b7f994a74f0aa9b6bcda60fbfe7e55cb725a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 7 Oct 2014 17:11:33 +0200 Subject: [PATCH 05/16] IDEA-129372 Draw outline of the auto-hideable scrollbar in the editor's right gutter --- .../intellij/util/ui/ButtonlessScrollBarUI.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index b11ca7f3222f..093407542c74 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -569,17 +569,23 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { } private void paintMacThumb(Graphics g, Rectangle thumbBounds) { - if (myMacScrollbarHidden) return; - thumbBounds = getMacScrollBarBounds(thumbBounds, true); Graphics2D g2d = (Graphics2D)g; RenderingHints oldHints = g2d.getRenderingHints(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setColor(adjustColor(new JBColor(Gray._0, Gray._128))); - + JBColor baseColor = new JBColor(Gray._0, Gray._128); int arc = Math.min(thumbBounds.width, thumbBounds.height); - g2d.fillRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, arc, arc); + + if (alwaysShowTrack()) { + g2d.setColor(new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), UIUtil.isUnderDarcula() ? 100 : 40)); + g2d.drawRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, arc, arc); + } + + if (!myMacScrollbarHidden) { + g2d.setColor(adjustColor(baseColor)); + g2d.fillRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, arc, arc); + } g2d.setRenderingHints(oldHints); } From 8864e87030b92610131fd6fd19d4720f22381c48 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 7 Oct 2014 18:06:39 +0200 Subject: [PATCH 06/16] IDEA-128849 Plugin downloader can't handle HTTP redirect Ensure that we use progress indicator --- .../intellij/ide/plugins/PluginInstaller.java | 50 +++--- .../ide/plugins/PluginManagerMain.java | 2 +- .../ide/plugins/RepositoryHelper.java | 142 ++++++++++++------ .../updateSettings/impl/PluginDownloader.java | 42 +----- .../updateSettings/impl/UpdateChecker.java | 97 ++++++------ 5 files changed, 178 insertions(+), 155 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 366e4e1cf4ef..294bda988328 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -22,15 +22,21 @@ import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.updateSettings.impl.PluginDownloader; import com.intellij.openapi.updateSettings.impl.UpdateChecker; import com.intellij.ui.GuiUtils; import com.intellij.util.ArrayUtil; +import com.intellij.util.SmartList; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author stathik @@ -41,9 +47,9 @@ public class PluginInstaller { private PluginInstaller() { } - public static boolean prepareToInstall(List pluginsToInstall, List allPlugins) { - HashSet dependant = new HashSet(); - boolean install = prepareToInstall(pluginsToInstall, allPlugins, dependant); + public static boolean prepareToInstall(List pluginsToInstall, List allPlugins, @NotNull ProgressIndicator indicator) { + Set dependant = new THashSet(); + boolean install = prepareToInstall(pluginsToInstall, allPlugins, dependant, indicator); for (PluginNode node : dependant) { if (!pluginsToInstall.contains(node)) { pluginsToInstall.add(node); @@ -54,21 +60,18 @@ public class PluginInstaller { private static boolean prepareToInstall(List pluginsToInstall, List allPlugins, - Set installedDependant) { - ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator(); - - final List pluginIds = new ArrayList(); + Set installedDependant, + @NotNull ProgressIndicator progressIndicator) { + List pluginIds = new SmartList(); for (PluginNode pluginNode : pluginsToInstall) { pluginIds.add(pluginNode.getPluginId()); } boolean result = false; - - for (final PluginNode pluginNode : pluginsToInstall) { - if (pi != null) pi.setText(pluginNode.getName()); - + for (PluginNode pluginNode : pluginsToInstall) { + progressIndicator.setText(pluginNode.getName()); try { - result |= prepareToInstall(pluginNode, pluginIds, allPlugins, installedDependant); + result |= prepareToInstall(pluginNode, pluginIds, allPlugins, installedDependant, progressIndicator); } catch (IOException e) { String title = IdeBundle.message("title.plugin.error"); @@ -83,7 +86,8 @@ public class PluginInstaller { private static boolean prepareToInstall(final PluginNode pluginNode, final List pluginIds, List allPlugins, - Set installedDependant) throws IOException { + Set installedDependant, + @NotNull ProgressIndicator progressIndicator) throws IOException { installedDependant.add(pluginNode); // check for dependent plugins at first. if (pluginNode.getDepends() != null && pluginNode.getDepends().size() > 0) { @@ -93,7 +97,6 @@ public class PluginInstaller { final List optionalDeps = new ArrayList(); for (int i = 0; i < pluginNode.getDepends().size(); i++) { PluginId depPluginId = pluginNode.getDepends().get(i); - if (PluginManager.isPluginInstalled(depPluginId) || PluginManagerCore.isModuleDependency(depPluginId) || PluginManagerUISettings.getInstance().getInstalledPlugins().contains(depPluginId.getIdString()) || (pluginIds != null && pluginIds.contains(depPluginId))) { @@ -123,6 +126,7 @@ public class PluginInstaller { } try { GuiUtils.runOrInvokeAndWait(new Runnable() { + @Override public void run() { String title = IdeBundle.message("plugin.manager.dependencies.detected.title"); String message = IdeBundle.message("plugin.manager.dependencies.detected.message", depends.size(), buf.substring(0, buf.length() - 1)); @@ -134,7 +138,7 @@ public class PluginInstaller { return false; } if (proceed[0]) { - if (!prepareToInstall(depends, allPlugins, installedDependant)) { + if (!prepareToInstall(depends, allPlugins, installedDependant, progressIndicator)) { return false; } } @@ -151,6 +155,7 @@ public class PluginInstaller { final boolean[] proceed = new boolean[1]; try { GuiUtils.runOrInvokeAndWait(new Runnable() { + @Override public void run() { proceed[0] = Messages.showYesNoDialog(IdeBundle.message("plugin.manager.optional.dependencies.detected.message", optionalDeps.size(), @@ -164,19 +169,19 @@ public class PluginInstaller { return false; } if (proceed[0]) { - if (!prepareToInstall(optionalDeps, allPlugins, installedDependant)) { + if (!prepareToInstall(optionalDeps, allPlugins, installedDependant, progressIndicator)) { return false; } } } } - PluginDownloader downloader = null; + PluginDownloader downloader; final String repositoryName = pluginNode.getRepositoryName(); if (repositoryName != null) { try { - final Map downloaders = new HashMap(); - if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders)) { + Map downloaders = new THashMap(); + if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders, progressIndicator)) { return false; } downloader = downloaders.get(pluginNode.getPluginId()); @@ -190,7 +195,7 @@ public class PluginInstaller { downloader = PluginDownloader.createDownloader(pluginNode); } - if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { + if (downloader.prepareToInstall(progressIndicator)) { synchronized (myLock) { downloader.install(); } @@ -199,7 +204,6 @@ public class PluginInstaller { else { return false; } - return true; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index a58e3fd7d628..ded719147d3b 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -415,7 +415,7 @@ public abstract class PluginManagerMain implements Disposable { @Override public void run(@NotNull ProgressIndicator indicator) { try { - if (PluginInstaller.prepareToInstall(plugins, allPlugins)) { + if (PluginInstaller.prepareToInstall(plugins, allPlugins, indicator)) { ApplicationManager.getApplication().invokeLater(onSuccess); result[0] = true; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java index c03eca88ade3..2c2925fcb62e 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java @@ -24,10 +24,14 @@ import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.BuildNumber; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.util.PathUtil; import com.intellij.util.net.HttpConfigurable; +import com.intellij.util.net.NetUtils; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.xml.parsers.SAXParser; @@ -35,6 +39,7 @@ import javax.xml.parsers.SAXParserFactory; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; +import java.net.URLConnection; import java.util.List; import java.util.zip.GZIPInputStream; @@ -49,8 +54,70 @@ public class RepositoryHelper { return loadPluginsFromRepository(indicator, null); } - public static List loadPluginsFromRepository(@Nullable ProgressIndicator indicator, - BuildNumber buildnumber) throws Exception { + @NotNull + public static Pair openConnection(@NotNull String initialUrl, boolean supportGzip) throws IOException { + int i = 0; + String url = initialUrl; + while (i++ < 99) { + URLConnection connection; + if (ApplicationManager.getApplication() != null) { + connection = HttpConfigurable.getInstance().openConnection(url); + } + else { + connection = new URL(url).openConnection(); + connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + } + + if (supportGzip) { + connection.setRequestProperty("Accept-Encoding", "gzip"); + } + connection.setUseCaches(false); + + if (connection instanceof HttpURLConnection) { + int responseCode = ((HttpURLConnection)connection).getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK && responseCode != HttpURLConnection.HTTP_NOT_MODIFIED) { + if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { + url = connection.getHeaderField("Location"); + } + else { + url = null; + } + + if (url == null) { + throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode)); + } + else { + ((HttpURLConnection)connection).disconnect(); + continue; + } + } + } + return Pair.create(connection, url == initialUrl ? null : url); + } + throw new IOException("Infinite redirection"); + } + + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") + @NotNull + public static InputStream getConnectionInputStream(@NotNull URLConnection connection) throws IOException { + InputStream inputStream = connection.getInputStream(); + if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) { + try { + return new GZIPInputStream(inputStream); + } + catch (IOException e) { + inputStream.close(); + throw e; + } + } + else { + return inputStream; + } + } + + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") + public static List loadPluginsFromRepository(@Nullable ProgressIndicator indicator, @Nullable BuildNumber buildnumber) throws Exception { ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance(); String url = appInfo.getPluginsListUrl() + "?build=" + (buildnumber != null ? buildnumber.asString() : appInfo.getApiVersion()); @@ -70,17 +137,10 @@ public class RepositoryHelper { } } - HttpURLConnection connection = ApplicationManager.getApplication() != null ? - HttpConfigurable.getInstance().openHttpConnection(url) : - (HttpURLConnection)new URL(url).openConnection(); - connection.setRequestProperty("Accept-Encoding", "gzip"); - connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - + HttpURLConnection connection = (HttpURLConnection)openConnection(url, true).first; if (indicator != null) { indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl())); } - connection.connect(); try { if (indicator != null) { @@ -91,49 +151,35 @@ public class RepositoryHelper { return loadPluginList(pluginListFile); } - String encoding = connection.getContentEncoding(); - InputStream is = connection.getInputStream(); - try { - if ("gzip".equalsIgnoreCase(encoding)) { - is = new GZIPInputStream(is); - } - - if (indicator != null) { - indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins")); - } - - return readPluginsStream(is, indicator, PLUGIN_LIST_FILE); - } - finally { - is.close(); + if (indicator != null) { + indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins")); } + return readPluginsStream(connection, indicator, PLUGIN_LIST_FILE); } finally { connection.disconnect(); } } - private synchronized static List readPluginsStream(InputStream is, + private synchronized static List readPluginsStream(@NotNull URLConnection connection, ProgressIndicator indicator, - String file) throws Exception { - File temp = createLocalPluginsDescriptions(file); - - OutputStream os = new FileOutputStream(temp, false); + @NotNull String file) throws Exception { + File localFile; + InputStream input = getConnectionInputStream(connection); try { - byte[] buffer = new byte[1024]; - int size; - while ((size = is.read(buffer)) > 0) { - os.write(buffer, 0, size); - if (indicator != null) { - indicator.checkCanceled(); - } + localFile = createLocalPluginsDescriptions(file); + OutputStream output = new FileOutputStream(localFile); + try { + NetUtils.copyStreamContent(indicator, input, output, connection.getContentLength()); + } + finally { + output.close(); } } finally { - os.close(); + input.close(); } - - return loadPluginList(temp); + return loadPluginList(localFile); } private static List loadPluginList(File file) throws Exception { @@ -143,7 +189,8 @@ public class RepositoryHelper { return handler.getPluginsList(); } - private static File createLocalPluginsDescriptions(String file) throws IOException { + @NotNull + private static File createLocalPluginsDescriptions(@NotNull String file) throws IOException { File basePath = new File(PathManager.getPluginsPath()); if (!basePath.isDirectory() && !basePath.mkdirs()) { throw new IOException("Cannot create directory: " + basePath); @@ -153,17 +200,14 @@ public class RepositoryHelper { if (temp.exists()) { FileUtil.delete(temp); } - FileUtil.createIfDoesntExist(temp); + else { + FileUtilRt.createParentDirs(temp); + } return temp; } - public static List loadPluginsFromDescription(InputStream is, ProgressIndicator indicator) throws Exception { - try { - return readPluginsStream(is, indicator, "host.xml"); - } - finally { - is.close(); - } + public static List loadPluginsFromDescription(@NotNull URLConnection connection, @Nullable ProgressIndicator indicator) throws Exception { + return readPluginsStream(connection, indicator, "host.xml"); } public static String getDownloadUrl() { diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index c93e69438766..2d1069e26eb1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -26,6 +26,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.BuildNumber; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -34,7 +35,6 @@ import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.util.PathUtil; import com.intellij.util.io.UrlConnectionUtil; import com.intellij.util.io.ZipUtil; -import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.NetUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -42,7 +42,6 @@ import org.jetbrains.annotations.Nullable; import java.io.*; import java.net.HttpURLConnection; -import java.net.URL; import java.net.URLConnection; import java.util.List; @@ -262,15 +261,10 @@ public class PluginDownloader { if (ApplicationManager.getApplication() != null && pi != null) { pi.setText(IdeBundle.message("progress.downloading.plugin", getPluginName())); } - final int contentLength = connection.getContentLength(); - if (pi != null) { - pi.setIndeterminate(contentLength == -1); - } - try { final OutputStream fos = new BufferedOutputStream(new FileOutputStream(file, false)); try { - NetUtils.copyStreamContent(pi, is, fos, contentLength); + NetUtils.copyStreamContent(pi, is, fos, connection.getContentLength()); } finally { fos.close(); @@ -295,34 +289,12 @@ public class PluginDownloader { } } - private URLConnection openConnection(final String url) throws IOException { - final URLConnection connection; - if (ApplicationManager.getApplication() != null) { - connection = HttpConfigurable.getInstance().openConnection(url); + private URLConnection openConnection(@NotNull String url) throws IOException { + Pair result = RepositoryHelper.openConnection(url, false); + if (result.second != null) { + myPluginUrl = result.second; } - else { - connection = new URL(url).openConnection(); - connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - } - if (connection instanceof HttpURLConnection) { - final int responseCode = ((HttpURLConnection)connection).getResponseCode(); - if (responseCode != HttpURLConnection.HTTP_OK) { - String location = null; - if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { - location = connection.getHeaderField("Location"); - } - if (location == null) { - throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode)); - } - else { - myPluginUrl = location; - ((HttpURLConnection)connection).disconnect(); - return openConnection(location); - } - } - } - return connection; + return result.first; } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index bae6a17b8522..4cf122146c62 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -334,9 +334,9 @@ public final class UpdateChecker { return hosts; } - public static boolean checkPluginsHost(final String host, final Map downloaded) throws Exception { + public static boolean checkPluginsHost(final String host, final Map downloaded, @NotNull ProgressIndicator progressIndicator) throws Exception { try { - return checkPluginsHost(host, downloaded, null, true, null, null); + return checkPluginsHost(host, downloaded, null, true, progressIndicator, null); } catch (ProcessCanceledException e) { return false; @@ -356,19 +356,15 @@ public final class UpdateChecker { final boolean collectToUpdate, final @Nullable ProgressIndicator indicator, final BuildNumber buildNumber) throws Exception { - InputStream inputStream = loadVersionInfo(host); - if (inputStream == null) return false; final Document document; try { - document = JDOMUtil.loadDocument(inputStream); + document = JDOMUtil.loadDocument(RepositoryHelper.getConnectionInputStream(loadVersionInfo(host))); } catch (JDOMException e) { return false; } - inputStream = loadVersionInfo(host); - if (inputStream == null) return false; - final List descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream, indicator); + final List descriptors = RepositoryHelper.loadPluginsFromDescription(loadVersionInfo(host), indicator); for (IdeaPluginDescriptor descriptor : descriptors) { ((PluginNode)descriptor).setRepositoryName(host); prepareToInstall(PluginDownloader.createDownloader(descriptor, buildNumber), buildNumber, downloaded, incompatiblePlugins, collectToUpdate, @@ -412,29 +408,19 @@ public final class UpdateChecker { if (collectToUpdate) { final String finalPluginUrl = getPluginUrl(pluginFile); - final Runnable updatePluginRunnable = new Runnable() { - public void run() { - try { - final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); - if (progressIndicator != null) { - progressIndicator.setText2(finalPluginUrl); - } - final PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null, buildNumber); - prepareToInstall(downloader, buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator); - } - catch (IOException e) { - LOG.info(e); - } - } - }; if (ApplicationManager.getApplication().isDispatchThread()) { - String title = IdeBundle.message("update.uploading.plugin.progress.title"); - ProgressManager.getInstance().runProcessWithProgressSynchronously(updatePluginRunnable, title, true, null); + ProgressManager.getInstance().run(new Task.Modal(null, IdeBundle.message("update.uploading.plugin.progress.title"), true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + updatePlugins(finalPluginUrl, pluginId, pluginVersion, buildNumber, downloaded, incompatiblePlugins, true, indicator); + } + }); } else { - updatePluginRunnable.run(); + updatePlugins(finalPluginUrl, pluginId, pluginVersion, buildNumber, downloaded, incompatiblePlugins, true, indicator); } - } else { + } + else { final PluginDownloader downloader = new PluginDownloader(pluginId, pluginUrl, pluginVersion); downloader.setDescription(description); downloader.setDepends(dependsPlugins); @@ -444,6 +430,24 @@ public final class UpdateChecker { return success; } + private static void updatePlugins(String finalPluginUrl, + String pluginId, + String pluginVersion, + BuildNumber buildNumber, + Map downloaded, + Collection incompatiblePlugins, boolean collectToUpdate, ProgressIndicator indicator) { + try { + if (indicator != null) { + indicator.setText2(finalPluginUrl); + } + PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null, buildNumber); + prepareToInstall(downloader, buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator); + } + catch (IOException e) { + LOG.info(e); + } + } + @NotNull private static String getPluginUrl(@NotNull VirtualFile pluginFile) { String protocol = pluginFile.getFileSystem().getProtocol(); @@ -502,6 +506,7 @@ public final class UpdateChecker { if (newChannelReady(channelToPropose)) { Runnable runnable = new Runnable() { + @Override public void run() { new NewChannelDialog(channelToPropose).show(); } @@ -606,34 +611,28 @@ public final class UpdateChecker { } } - private static InputStream loadVersionInfo(final String url) throws Exception { - final InputStream[] inputStreams = new InputStream[]{null}; - final Exception[] exception = new Exception[]{null}; + @NotNull + private static URLConnection loadVersionInfo(@NotNull final String url) throws Exception { + final Ref connectionRef = Ref.create(); + final Ref exception = Ref.create(); Future downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override public void run() { try { - final String urlToCheck; + String urlToCheck; if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) { urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString(); - } else { + } + else { urlToCheck = url; } - URLConnection connection; - if (ApplicationManager.getApplication() != null) { - connection = HttpConfigurable.getInstance().openConnection(urlToCheck); - } - else { - connection = new URL(urlToCheck).openConnection(); - connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - } + URLConnection connection = RepositoryHelper.openConnection(urlToCheck, true).first; connection.connect(); - - inputStreams[0] = connection.getInputStream(); + connectionRef.set(connection); } catch (IOException e) { - exception[0] = e; + exception.set(e); } } }); @@ -641,15 +640,18 @@ public final class UpdateChecker { try { downloadThreadFuture.get(5, TimeUnit.SECONDS); } - catch (TimeoutException ignored) { } + catch (TimeoutException ignored) { + } if (!downloadThreadFuture.isDone()) { downloadThreadFuture.cancel(true); throw new ConnectionException(IdeBundle.message("updates.timeout.error")); } - if (exception[0] != null) throw exception[0]; - return inputStreams[0]; + if (!exception.isNull()) { + throw exception.get(); + } + return connectionRef.get(); } public static String getInstallationUID(final PropertiesComponent propertiesComponent) { @@ -734,6 +736,7 @@ public final class UpdateChecker { final DownloadPatchResult[] result = new DownloadPatchResult[]{DownloadPatchResult.CANCELED}; if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override public void run() { try { doDownloadAndInstallPatch(newVersion, ProgressManager.getInstance().getProgressIndicator()); From a5ac8ea1d2a6f820fa2cf9ad9de977e2d556d031 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Tue, 7 Oct 2014 18:01:26 +0200 Subject: [PATCH 07/16] cleanup --- .../ide/scratch/NewScratchFileAction.java | 19 +++++-------------- .../ide/scratch/ScratchpadManagerImpl.java | 5 +++-- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java b/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java index 8e15a6ce5a36..be74f8ca6588 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java @@ -44,7 +44,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -65,25 +64,17 @@ public class NewScratchFileAction extends AnAction implements DumbAware { public static List getLastUsedLanguagesIds(Project project) { String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName()); - if (values == null) { - return ContainerUtil.emptyList(); - } - return ContainerUtil.list(values); + return values == null ? ContainerUtil.emptyList() : ContainerUtil.list(values); } - @Override public void actionPerformed(@NotNull AnActionEvent e) { final Project project = e.getProject(); if (project == null) return; - Language context = null; PsiFile file = e.getData(CommonDataKeys.PSI_FILE); - - if (file != null) { - context = file.getLanguage(); - } - + Language context = file != null ? file.getLanguage() : null; + ListPopup popup = buildLanguagePopup(project, context, new Consumer() { @Override public void consume(Language language) { @@ -98,7 +89,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware { @NotNull static ListPopup buildLanguagePopup(@NotNull Project project, @Nullable Language context, final Consumer onChoosen) { List languages = LanguageUtil.getFileLanguages(); - final List ids = new ArrayList(getLastUsedLanguagesIds(project)); + final List ids = ContainerUtil.newArrayList(getLastUsedLanguagesIds(project)); if (context != null) { ids.add(context.getID()); } @@ -108,7 +99,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware { ContainerUtil.sort(languages, new Comparator() { @Override - public int compare(Language o1, Language o2) { + public int compare(@NotNull Language o1, @NotNull Language o2) { int ind1 = ids.indexOf(o1.getID()); int ind2 = ids.indexOf(o2.getID()); if (ind1 == -1) ind1 = 666; diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java index 6cc2e81cecc8..c7dc4462475a 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java @@ -26,9 +26,10 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.WindowManager; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; +import java.util.List; public class ScratchpadManagerImpl extends ScratchpadManager implements Disposable { private final Project myProject; @@ -61,7 +62,7 @@ public class ScratchpadManagerImpl extends ScratchpadManager implements Disposab private static void updateHistory(Project project, Language language) { String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName()); - ArrayList lastUsed = new ArrayList(5); + List lastUsed = ContainerUtil.newArrayListWithCapacity(5); lastUsed.add(language.getID()); if (values != null) { for (String value : values) { From 02c3e4395d4618aa379781e182cb8f4ce0aeca80 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 7 Oct 2014 14:25:26 +0200 Subject: [PATCH 08/16] testdata for IDEA-127767 --- .../genericsHighlighting/IDEA127767.java | 21 +++++++++++++++++++ .../daemon/GenericsHighlightingTest.java | 4 ++++ 2 files changed, 25 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA127767.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA127767.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA127767.java new file mode 100644 index 000000000000..42d6ecec1803 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA127767.java @@ -0,0 +1,21 @@ +class Scratch +{ + public static class PredicatedProposal + { + private final Discriminator pred = null; + + public Discriminator get() + { + return this.pred; + } + } + + public static interface Discriminator extends Predicate + { + + } + + interface Predicate { + boolean val(T t); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index fde013dca76d..944e0756a3b0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -380,6 +380,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { //jdk should propagate LL 1.4 but actually it provides LL 1.7?! public void testCastObjectToIntJdk14() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_4, false); } + public void testIDEA127767() { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testHiddenMethodsOfAnonymousClass() throws Exception { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } From bcdb87573e49bd6de42d983406104819a9a95929 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 7 Oct 2014 18:15:46 +0200 Subject: [PATCH 09/16] new inference: do not cache control flow during conflict resolution (IDEA-130226) --- .../tree/java/PsiLambdaExpressionImpl.java | 22 ++++++++-- ...idValueCompatibilityCachedControlFlow.java | 41 +++++++++++++++++++ .../daemon/lambda/OverloadResolutionTest.java | 4 ++ 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/VoidValueCompatibilityCachedControlFlow.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java index 9d35ace98cf4..f1f310615050 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java @@ -37,6 +37,24 @@ import javax.swing.*; public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements PsiLambdaExpression { + private static final ControlFlowPolicy ourPolicy = new ControlFlowPolicy() { + @Nullable + @Override + public PsiVariable getUsedVariable(@NotNull PsiReferenceExpression refExpr) { + return null; + } + + @Override + public boolean isParameterAccepted(@NotNull PsiParameter psiParameter) { + return true; + } + + @Override + public boolean isLocalVariableAccepted(@NotNull PsiLocalVariable psiVariable) { + return true; + } + }; + public PsiLambdaExpressionImpl() { super(JavaElementType.LAMBDA_EXPRESSION); } @@ -92,9 +110,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi final PsiElement body = getBody(); if (body instanceof PsiCodeBlock) { try { - ControlFlow controlFlow = - ControlFlowFactory.getInstance(getProject()).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy - .getInstance()); + ControlFlow controlFlow = ControlFlowFactory.getInstance(getProject()).getControlFlow(body, ourPolicy); int startOffset = controlFlow.getStartOffset(body); int endOffset = controlFlow.getEndOffset(body); if (startOffset != -1 && endOffset != -1 && ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset)) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/VoidValueCompatibilityCachedControlFlow.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/VoidValueCompatibilityCachedControlFlow.java new file mode 100644 index 000000000000..d04c0694219d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/VoidValueCompatibilityCachedControlFlow.java @@ -0,0 +1,41 @@ + +import java.io.IOException; + +class Test { + { + queryForObject( + (rs) -> { + try { + return readValue(rs); + } catch (IOException e) { + return new UserOptions(); + } + } + ); + } + + UserOptions readValue(String content) throws IOException { + System.out.println(content); + return null; + } + + UserOptions readValue(Integer i) throws IOException { + System.out.println(i); + return null; + } + + void queryForObject(Mapper rowMapper) { + System.out.println(rowMapper); + } + + void queryForObject(String requiredType) { + System.out.println(requiredType); + } + + interface Mapper { + UserOptions mapRow(String rs) throws IOException; + } + + class UserOptions {} + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java index d28b5ca8b048..327d54d04260 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java @@ -42,6 +42,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase { public void testVoidValueCompatibilityOfImplicitlyTypedLambda() throws Exception { doTest(); } + + public void testVoidValueCompatibilityCachedControlFlow() throws Exception { + doTest(); + } public void testIDEA102800() throws Exception { doTest(); From d78b3d6a7b2ca1c137763517ccc76286bd88883a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 7 Oct 2014 18:21:31 +0200 Subject: [PATCH 10/16] IDEA-130928 "Quick Documentation" eliminates comma for field --- .../intellij/codeInsight/javadoc/JavaDocInfoGenerator.java | 2 +- .../codeInsight/javadocIG/commaInsideArgsList.html | 1 + .../codeInsight/javadocIG/commaInsideArgsList.java | 7 +++++++ .../codeInsight/javadoc/JavaDocInfoGeneratorTest.java | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.java diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 3c9e76151e1d..c0742de3c7f6 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -2054,7 +2054,7 @@ public class JavaDocInfoGenerator { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { myBuffer.append(expression.getMethodExpression().getText()).append("("); - expression.getArgumentList().acceptChildren(this); + expression.getArgumentList().accept(this); myBuffer.append(")"); } diff --git a/java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.html b/java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.html new file mode 100644 index 000000000000..4fb3721930dd --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.html @@ -0,0 +1 @@ + Test

public String field = foo("", "")
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.java b/java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.java new file mode 100644 index 000000000000..52c368532dc4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/commaInsideArgsList.java @@ -0,0 +1,7 @@ +class Test { + public String field = foo("", ""); + + String foo(String s, String s1) { + return s; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java index 409ebcc681c1..871c758d08fd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -96,6 +96,10 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase { doTestField(); } + public void testCommaInsideArgsList() throws Exception { + doTestField(); + } + public void testEnumConstantOrdinal() throws Exception { PsiClass psiClass = getTestClass(); PsiField field = psiClass.getFields() [0]; From b1923a185f2f6fde2ef478146f16687cbd9e06c5 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 7 Oct 2014 20:28:45 +0400 Subject: [PATCH 11/16] IDEA-130875 Settings: misaligned elements in Copyright Profiles --- .../openapi/ui/MasterDetailsComponent.java | 16 ++++++++++------ .../openapi/options/newEditor/OptionsEditor.java | 13 ++++--------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java index 068546a24b1e..92c7f0f09db9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java @@ -132,7 +132,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom protected MasterDetailsComponent(MasterDetailsState state) { myState = state; - mySplitter = isNewProjectSettings() ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f); + mySplitter = isNewProjectSettings() || isNewSettingsView() ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f); mySplitter.setSplitterProportionKey("ProjectStructure.SecondLevelElements"); mySplitter.setHonorComponentsMinimumSize(true); @@ -141,9 +141,6 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom } private boolean isNewProjectSettings() { - if (ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.settings.view")) { - return true; - } if (!Registry.is("ide.new.project.settings")) { return false; } @@ -157,6 +154,10 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom } } + private boolean isNewSettingsView() { + return ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.settings.view"); + } + protected void reInitWholePanelIfNeeded() { if (!myToReInitWholePanel) return; @@ -188,7 +189,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom } }; - if (isNewProjectSettings()) { + if (isNewProjectSettings() || isNewSettingsView()) { ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTree); DefaultActionGroup group = createToolbarActionGroup(); if (group != null) { @@ -206,6 +207,9 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom final JPanel right = new JPanel(new BorderLayout()); right.add(myDetails.getComponent(), BorderLayout.CENTER); + if (!isNewProjectSettings() && isNewSettingsView()) { + right.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + } mySplitter.setSecondComponent(right); @@ -299,7 +303,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom } private void initToolbar() { - if (isNewProjectSettings()) return; + if (isNewProjectSettings() || isNewSettingsView()) return; DefaultActionGroup group = createToolbarActionGroup(); if (group != null) { final JComponent component = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java index 62b32b39bad4..a86c1dd012aa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java @@ -498,14 +498,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat private ActionCallback initConfigurable(@NotNull final Configurable configurable) { final ActionCallback result = new ActionCallback(); - final ConfigurableContent content; - - if (configurable instanceof MasterDetails) { - content = new Details((MasterDetails)configurable); - } - else { - content = new Simple(configurable); - } + final ConfigurableContent content = new Simple(configurable); if (!myConfigurable2Content.containsKey(configurable)) { if (configurable instanceof Place.Navigator) { @@ -1068,7 +1061,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat @Override void set(final ContentWrapper wrapper) { myOwnDetails.setDetailsModeEnabled(true); - wrapper.setContent(myComponent, getContext().getErrors().get(myConfigurable), !ConfigurableWrapper.isNoScroll(myConfigurable)); + boolean noScroll = ConfigurableWrapper.isNoScroll(myConfigurable) || + ConfigurableWrapper.cast(MasterDetails.class, myConfigurable) != null; + wrapper.setContent(myComponent, getContext().getErrors().get(myConfigurable), !noScroll); } @Override From 5e7876308516082534c4671e73b20ce51a999eb1 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 7 Oct 2014 20:37:21 +0400 Subject: [PATCH 12/16] decompiler: move generated lines as it is stated in debug line table (disabled for now) --- .../util/resources/misc/registry.properties | 2 + .../java/decompiler/main/ClassWriter.java | 37 ++-- .../decompiler/main/ClassesProcessor.java | 4 +- .../java/decompiler/main/Fernflower.java | 6 +- .../java/decompiler/main/TextBuffer.java | 163 ++++++++++++++++++ .../main/collectors/BytecodeSourceMapper.java | 3 +- .../main/collectors/ImportCollector.java | 3 +- .../main/decompiler/ConsoleDecompiler.java | 5 +- .../main/extern/IFernflowerPreferences.java | 2 + .../decompiler/main/extern/IResultSaver.java | 4 +- .../modules/decompiler/ExprProcessor.java | 5 +- .../modules/decompiler/exps/ExitExprent.java | 5 +- .../modules/decompiler/exps/FieldExprent.java | 3 +- .../decompiler/exps/InvocationExprent.java | 3 +- .../modules/decompiler/exps/NewExprent.java | 9 +- .../modules/decompiler/exps/VarExprent.java | 3 +- .../java/decompiler/struct/ContextUnit.java | 7 +- .../decompiler/struct/IDecompiledData.java | 4 +- .../java/decompiler/util/InterpreterUtil.java | 5 +- .../java/decompiler/IdeaDecompiler.java | 13 +- 20 files changed, 242 insertions(+), 44 deletions(-) create mode 100644 plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index abeaacb3338e..7fc9cf6fc0a8 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -448,3 +448,5 @@ new.css.schema.enabled=true editor.disable.rtl=false editor.disable.rtl.description=Disables RTL support in editor (which is broken now anyway) + +decompiler.use.line.table=false 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 0383dd410e47..61507fb8a92b 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 @@ -76,7 +76,7 @@ public class ClassWriter { } } - public void classLambdaToJava(ClassNode node, StringBuilder buffer, Exprent method_object, int indent) { + public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_object, int indent) { // get the class node with the content method ClassNode classNode = node; while (classNode != null && classNode.type == ClassNode.CLASS_LAMBDA) { @@ -160,7 +160,7 @@ public class ClassWriter { DecompilerContext.getLogger().endWriteClass(); } - public void classToJava(ClassNode node, StringBuilder buffer, int indent) { + public void classToJava(ClassNode node, TextBuffer buffer, int indent) { ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); @@ -279,7 +279,7 @@ public class ClassWriter { DecompilerContext.getLogger().endWriteClass(); } - private void writeClassDefinition(ClassNode node, StringBuilder buffer, int indent) { + private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { String lineSeparator = DecompilerContext.getNewLineSeparator(); String indentString = InterpreterUtil.getIndentString(indent); @@ -390,7 +390,7 @@ public class ClassWriter { buffer.append(lineSeparator); } - private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, StringBuilder buffer, int indent, BytecodeMappingTracer tracer) { + private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { String indentString = InterpreterUtil.getIndentString(indent); String lineSeparator = DecompilerContext.getNewLineSeparator(); @@ -479,7 +479,7 @@ public class ClassWriter { private static void methodLambdaToJava(ClassNode lambdaNode, ClassNode classNode, StructMethod mt, - StringBuilder buffer, + TextBuffer buffer, int indent, boolean codeOnly, BytecodeMappingTracer tracer) { ClassWrapper classWrapper = classNode.wrapper; @@ -565,7 +565,7 @@ public class ClassWriter { } } - private boolean methodToJava(ClassNode node, StructMethod mt, StringBuilder buffer, int indent, BytecodeMappingTracer tracer) { + private boolean methodToJava(ClassNode node, StructMethod mt, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { ClassWrapper wrapper = node.wrapper; StructClass cl = wrapper.getClassStruct(); MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()); @@ -586,6 +586,15 @@ public class ClassWriter { boolean isDeprecated = mt.getAttributes().containsKey("Deprecated"); boolean clinit = false, init = false, dinit = false; + int startLine = -1; + if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) { + StructLineNumberTableAttribute lineNumberTable = + (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE); + if (lineNumberTable != null) { + startLine = lineNumberTable.getFirstLine(); + } + } + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); int flags = mt.getAccessFlags(); @@ -800,6 +809,8 @@ public class ClassWriter { buffer.append(' '); } + //TODO: for now only start line set + buffer.setCurrentLine(startLine); buffer.append('{'); buffer.append(lineSeparator); @@ -861,13 +872,13 @@ public class ClassWriter { return true; } - private static void appendDeprecation(StringBuilder buffer, String indentString, String lineSeparator) { + private static void appendDeprecation(TextBuffer buffer, String indentString, String lineSeparator) { buffer.append(indentString).append("/** @deprecated */").append(lineSeparator); } private enum MType {CLASS, FIELD, METHOD} - private static void appendRenameComment(StringBuilder buffer, String oldName, MType type, int indent, String lineSeparator) { + private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent, String lineSeparator) { if (oldName == null) return; InterpreterUtil.appendIndent(buffer, indent); @@ -915,14 +926,14 @@ public class ClassWriter { return typeText; } - private static void appendComment(StringBuilder buffer, String comment, String indentString, String lineSeparator) { + private static void appendComment(TextBuffer buffer, String comment, String indentString, String lineSeparator) { buffer.append(indentString).append("// $FF: ").append(comment).append(lineSeparator); } private static final String[] ANNOTATION_ATTRIBUTES = { StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS}; - private static void appendAnnotations(StringBuilder buffer, StructMember mb, int indent, String lineSeparator) { + private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent, String lineSeparator) { BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one @@ -939,7 +950,7 @@ public class ClassWriter { private static final String[] PARAMETER_ANNOTATION_ATTRIBUTES = { StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS}; - private static void appendParameterAnnotations(StringBuilder buffer, StructMethod mt, int param) { + private static void appendParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) { BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one @@ -984,7 +995,7 @@ public class ClassWriter { private static final int FIELD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL; private static final int METHOD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_ABSTRACT; - private static void appendModifiers(StringBuilder buffer, int flags, int allowed, boolean isInterface, int excluded) { + private static void appendModifiers(TextBuffer buffer, int flags, int allowed, boolean isInterface, int excluded) { flags &= allowed; if (!isInterface) excluded = 0; for (int modifier : MODIFIERS.keySet()) { @@ -994,7 +1005,7 @@ public class ClassWriter { } } - private static void appendTypeParameters(StringBuilder buffer, List parameters, List> bounds) { + private static void appendTypeParameters(TextBuffer buffer, List parameters, List> bounds) { buffer.append('<'); for (int i = 0; i < parameters.size(); i++) { 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 c79e3555daba..42f47193c495 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 @@ -236,7 +236,7 @@ public class ClassesProcessor { } } - public void writeClass(StructClass cl, StringBuilder buffer) throws IOException { + public void writeClass(StructClass cl, TextBuffer buffer) throws IOException { ClassNode root = mapRootClasses.get(cl.qualifiedName); if (root.type != ClassNode.CLASS_ROOT) { return; @@ -260,7 +260,7 @@ public class ClassesProcessor { new NestedMemberAccess().propagateMemberAccess(root); - StringBuilder classBuffer = new StringBuilder(AVERAGE_CLASS_SIZE); + TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE); new ClassWriter().classToJava(root, classBuffer, 0); String lineSeparator = DecompilerContext.getNewLineSeparator(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java index 324a39449794..4988bc0cdf03 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java @@ -80,11 +80,11 @@ public class Fernflower implements IDecompiledData { } @Override - public String getClassContent(StructClass cl) { + public TextBuffer getClassContent(StructClass cl) { try { - StringBuilder buffer = new StringBuilder(ClassesProcessor.AVERAGE_CLASS_SIZE); + TextBuffer buffer = new TextBuffer(ClassesProcessor.AVERAGE_CLASS_SIZE); classesProcessor.writeClass(cl, buffer); - return buffer.toString(); + return buffer; } catch (Throwable ex) { DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", ex); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java new file mode 100644 index 000000000000..6d279bfe1863 --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java @@ -0,0 +1,163 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.java.decompiler.main; + +import java.util.*; + +/** + * Allows to connect text with resulting lines + * + * @author egor + */ +public class TextBuffer { + private final String myLineSeparator = DecompilerContext.getNewLineSeparator(); + private final StringBuilder myStringBuilder; + private Map myLineToOffsetMapping = null; + + public TextBuffer() { + myStringBuilder = new StringBuilder(); + } + + public TextBuffer(int size) { + myStringBuilder = new StringBuilder(size); + } + + public void setCurrentLine(int line) { + if (line >= 0) { + checkMapCreated(); + myLineToOffsetMapping.put(line, myStringBuilder.length()+1); + } + } + + public TextBuffer append(String str) { + myStringBuilder.append(str); + return this; + } + + public TextBuffer append(char ch) { + myStringBuilder.append(ch); + return this; + } + + public TextBuffer appendLineSeparator() { + myStringBuilder.append(myLineSeparator); + return this; + } + + public void addBanner(String banner) { + myStringBuilder.insert(0, banner); + if (myLineToOffsetMapping != null) { + for (Integer line : myLineToOffsetMapping.keySet()) { + myLineToOffsetMapping.put(line, myLineToOffsetMapping.get(line) + banner.length()); + } + } + } + + @Override + public String toString() { + String original = myStringBuilder.toString(); + if (myLineToOffsetMapping == null || myLineToOffsetMapping.isEmpty()) { + return original; + } + else { + StringBuilder res = new StringBuilder(); + String[] srcLines = original.split(myLineSeparator); + int currentLineStartOffset = 0; + int currentLine = 0; + int previousMarkLine = 0; + int dumpedLines = 0; + ArrayList linesWithMarks = new ArrayList(myLineToOffsetMapping.keySet()); + Collections.sort(linesWithMarks); + for (Integer markLine : linesWithMarks) { + Integer markOffset = myLineToOffsetMapping.get(markLine); + while (currentLine < srcLines.length) { + String line = srcLines[currentLine]; + int lineEnd = currentLineStartOffset + line.length() + myLineSeparator.length(); + if (markOffset >= currentLineStartOffset && markOffset <= lineEnd) { + int requiredLinesNumber = markLine - dumpedLines; + dumpedLines = markLine; + appendLines(res, srcLines, previousMarkLine, currentLine, requiredLinesNumber); + previousMarkLine = currentLine; + break; + } + currentLineStartOffset = lineEnd; + currentLine++; + } + } + if (previousMarkLine < srcLines.length) { + appendLines(res, srcLines, previousMarkLine, srcLines.length, srcLines.length - previousMarkLine); + } + + return res.toString(); + } + } + + private void appendLines(StringBuilder res, String[] srcLines, int from, int to, int requiredLineNumber) { + if (to - from > requiredLineNumber) { + int separatorsRequired = to - from - requiredLineNumber - 1; + for (int i = from; i < to; i++) { + res.append(srcLines[i]); + if (separatorsRequired-- > 0) { + res.append(myLineSeparator); + } + } + res.append(myLineSeparator); + } + else if (to - from <= requiredLineNumber) { + for (int i = from; i < to; i++) { + res.append(srcLines[i]).append(myLineSeparator); + } + for (int i = 0; i < requiredLineNumber - to + from; i++) { + res.append(myLineSeparator); + } + } + } + + public int length() { + return myStringBuilder.length(); + } + + public String substring(int start) { + return myStringBuilder.substring(start); + } + + public void setLength(int position) { + myStringBuilder.setLength(position); + } + + public void append(TextBuffer buffer) { + if (buffer.myLineToOffsetMapping != null && !buffer.myLineToOffsetMapping.isEmpty()) { + checkMapCreated(); + for (Map.Entry entry : buffer.myLineToOffsetMapping.entrySet()) { + myLineToOffsetMapping.put(entry.getKey(), entry.getValue() + myStringBuilder.length()); + } + } + myStringBuilder.append(buffer.myStringBuilder); + } + + private void checkMapCreated() { + if (myLineToOffsetMapping == null) { + myLineToOffsetMapping = new HashMap(); + } + } + + public void insert(int offset, String s) { + if (myLineToOffsetMapping != null) { + throw new IllegalStateException("insert not yet supported with Line mapping"); + } + myStringBuilder.insert(offset, s); + } +} diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java index 53f92b2bb2e8..36c8ac8f5c28 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map.Entry; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.util.InterpreterUtil; public class BytecodeSourceMapper { @@ -37,7 +38,7 @@ public class BytecodeSourceMapper { } } - public void dumpMapping(StringBuilder buffer) { + public void dumpMapping(TextBuffer buffer) { String lineSeparator = DecompilerContext.getNewLineSeparator(); String indentstr1 = InterpreterUtil.getIndentString(1); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java index bd5e01117794..c66a3e053bb6 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.main.collectors; import org.jetbrains.java.decompiler.main.ClassesProcessor; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.struct.StructContext; import java.util.*; @@ -107,7 +108,7 @@ public class ImportCollector { return retname == null ? nshort : retname; } - public int writeImports(StringBuilder buffer) { + public int writeImports(TextBuffer buffer) { int importlines_written = 0; String new_line_separator = DecompilerContext.getNewLineSeparator(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java index a486d9f83ee1..43cfafb6ba92 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.main.decompiler; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.Fernflower; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; import org.jetbrains.java.decompiler.main.extern.IResultSaver; @@ -181,12 +182,12 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver { } @Override - public void saveClassFile(String path, String qualifiedName, String entryName, String content) { + public void saveClassFile(String path, String qualifiedName, String entryName, TextBuffer content) { File file = new File(getAbsolutePath(path), entryName); try { Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF8"); try { - out.write(content); + out.write(content.toString()); } finally { out.close(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java index ce81e3c83585..b5f6ac06fca3 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java @@ -45,6 +45,7 @@ public interface IFernflowerPreferences { String LAMBDA_TO_ANONYMOUS_CLASS = "lac"; String BYTECODE_SOURCE_MAPPING = "bsm"; + String USE_DEBUG_LINE_NUMBERS = "udl"; String LOG_LEVEL = "log"; String MAX_PROCESSING_METHOD = "mpm"; @@ -80,6 +81,7 @@ public interface IFernflowerPreferences { put(LAMBDA_TO_ANONYMOUS_CLASS, "0"); put(BYTECODE_SOURCE_MAPPING, "0"); + put(USE_DEBUG_LINE_NUMBERS, "0"); put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name()); put(MAX_PROCESSING_METHOD, "0"); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java index 1e6a7d4262a5..5b4b7e06ec86 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IResultSaver.java @@ -15,6 +15,8 @@ */ package org.jetbrains.java.decompiler.main.extern; +import org.jetbrains.java.decompiler.main.TextBuffer; + import java.util.jar.Manifest; public interface IResultSaver { @@ -22,7 +24,7 @@ public interface IResultSaver { void copyFile(String source, String path, String entryName); - void saveClassFile(String path, String qualifiedName, String entryName, String content); + void saveClassFile(String path, String qualifiedName, String entryName, TextBuffer content); void createArchive(String path, String archiveName, Manifest manifest); 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 dc284856a475..e283fdfb9aca 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 @@ -20,6 +20,7 @@ import org.jetbrains.java.decompiler.code.Instruction; import org.jetbrains.java.decompiler.code.InstructionSequence; import org.jetbrains.java.decompiler.code.cfg.BasicBlock; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph; @@ -857,14 +858,14 @@ public class ExprProcessor implements CodeConstants { return defaultval; } - public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent, + public static boolean getCastedExprent(Exprent exprent, VarType leftType, TextBuffer buffer, int indent, boolean castNull, BytecodeMappingTracer tracer) { return getCastedExprent(exprent, leftType, buffer, indent, castNull, false, tracer); } public static boolean getCastedExprent(Exprent exprent, VarType leftType, - StringBuilder buffer, + TextBuffer buffer, int indent, boolean castNull, boolean castAlways, BytecodeMappingTracer tracer) { 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 e03bc8d24a76..e54b3653ac9c 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 @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -81,7 +82,7 @@ public class ExitExprent extends Exprent { tracer.addMapping(bytecode); if (exittype == EXIT_RETURN) { - StringBuilder buffer = new StringBuilder(); + TextBuffer buffer = new TextBuffer(); if (rettype.type != CodeConstants.TYPE_VOID) { buffer.append(" "); @@ -115,7 +116,7 @@ public class ExitExprent extends Exprent { if (classname != null) { VarType exctype = new VarType(classname, true); - StringBuilder buffer = new StringBuilder(); + TextBuffer buffer = new TextBuffer(); ExprProcessor.getCastedExprent(value, exctype, buffer, indent, false, tracer); return "throw " + buffer.toString(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java index ce7d72fef8b2..e51615d10570 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -137,7 +138,7 @@ public class FieldExprent extends Exprent { buf.append("super"); } else { - StringBuilder buff = new StringBuilder(); + TextBuffer buff = new TextBuffer(); boolean casted = ExprProcessor.getCastedExprent(instance, new VarType(CodeConstants.TYPE_OBJECT, 0, classname), buff, indent, true, tracer); String res = buff.toString(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index e782b235c4b6..92d549e01c7b 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.rels.MethodWrapper; @@ -360,7 +361,7 @@ public class InvocationExprent extends Exprent { buf.append(", "); } - StringBuilder buff = new StringBuilder(); + TextBuffer buff = new TextBuffer(); ExprProcessor.getCastedExprent(lstParameters.get(i), descriptor.params[i], buff, indent, true, setAmbiguousParameters.contains(i), tracer); buf.append(buff); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java index 8395a3d60c86..5006d30e6494 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java @@ -19,6 +19,7 @@ import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -172,7 +173,7 @@ public class NewExprent extends Exprent { @Override public String toJava(int indent, BytecodeMappingTracer tracer) { - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); if (anonymous) { @@ -220,7 +221,7 @@ public class NewExprent extends Exprent { } } - StringBuilder buff = new StringBuilder(); + TextBuffer buff = new TextBuffer(); ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true, tracer); buf.append(buff); @@ -317,7 +318,7 @@ public class NewExprent extends Exprent { buf.append(", "); } - StringBuilder buff = new StringBuilder(); + TextBuffer buff = new TextBuffer(); ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buff, indent, true, tracer); buf.append(buff); @@ -373,7 +374,7 @@ public class NewExprent extends Exprent { if (i > 0) { buf.append(", "); } - StringBuilder buff = new StringBuilder(); + TextBuffer buff = new TextBuffer(); ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false, tracer); buf.append(buff); 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 16eba3a465aa..16e6c64fe53c 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 @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -83,7 +84,7 @@ public class VarExprent extends Exprent { @Override public String toJava(int indent, BytecodeMappingTracer tracer) { - StringBuilder buffer = new StringBuilder(); + TextBuffer buffer = new TextBuffer(); tracer.addMapping(bytecode); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/ContextUnit.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/ContextUnit.java index 819ae6446d07..dd6854439fce 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/ContextUnit.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/ContextUnit.java @@ -15,6 +15,7 @@ */ package org.jetbrains.java.decompiler.struct; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.extern.IResultSaver; import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; import org.jetbrains.java.decompiler.struct.lazy.LazyLoader.Link; @@ -110,7 +111,7 @@ public class ContextUnit { StructClass cl = classes.get(i); String entryName = decompiledData.getClassEntryName(cl, classEntries.get(i)); if (entryName != null) { - String content = decompiledData.getClassContent(cl); + TextBuffer content = decompiledData.getClassContent(cl); if (content != null) { resultSaver.saveClassFile(filename, cl.qualifiedName, entryName, content); } @@ -142,8 +143,8 @@ public class ContextUnit { StructClass cl = classes.get(i); String entryName = decompiledData.getClassEntryName(cl, classEntries.get(i)); if (entryName != null) { - String content = decompiledData.getClassContent(cl); - resultSaver.saveClassEntry(archivePath, filename, cl.qualifiedName, entryName, content); + TextBuffer content = decompiledData.getClassContent(cl); + resultSaver.saveClassEntry(archivePath, filename, cl.qualifiedName, entryName, content.toString()); } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java index f309b0e17bc9..25f1f88f2e04 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java @@ -15,9 +15,11 @@ */ package org.jetbrains.java.decompiler.struct; +import org.jetbrains.java.decompiler.main.TextBuffer; + public interface IDecompiledData { String getClassEntryName(StructClass cl, String entryname); - String getClassContent(StructClass cl); + TextBuffer getClassContent(StructClass cl); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java index eaada902b03d..50411bc8a565 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.util; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import java.io.*; @@ -91,12 +92,12 @@ public class InterpreterUtil { public static String getIndentString(int length) { if (length == 0) return ""; - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); appendIndent(buf, length); return buf.toString(); } - public static void appendIndent(StringBuilder buffer, int length) { + public static void appendIndent(TextBuffer buffer, int length) { if (length == 0) return; String indent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING); while (length-- > 0) { diff --git a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java index b13584a4b0b1..6181f3b2b734 100644 --- a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java +++ b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java @@ -32,6 +32,7 @@ import com.intellij.openapi.project.DefaultProjectFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.codeStyle.CodeStyleSettings; @@ -47,6 +48,7 @@ import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler; import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; @@ -82,6 +84,7 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light { myOptions.put(IFernflowerPreferences.REMOVE_BRIDGE, "1"); myOptions.put(IFernflowerPreferences.LITERALS_AS_IS, "1"); myOptions.put(IFernflowerPreferences.NEW_LINE_SEPARATOR, "1"); + //myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, "1"); Project project = DefaultProjectFactory.getInstance().getDefaultProject(); CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); @@ -141,13 +144,15 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light { MyBytecodeProvider provider = new MyBytecodeProvider(files); MyResultSaver saver = new MyResultSaver(); + myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, Registry.is("decompiler.use.line.table") ? "1" : "0"); BaseDecompiler decompiler = new BaseDecompiler(provider, saver, myOptions, myLogger); for (String path : files.keySet()) { decompiler.addSpace(new File(path), true); } decompiler.decompileContext(); - return BANNER + saver.myResult; + saver.myResult.addBanner(BANNER); + return saver.myResult.toString(); } catch (Exception e) { if (ApplicationManager.getApplication().isUnitTestMode()) { @@ -183,11 +188,11 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light { } private static class MyResultSaver implements IResultSaver { - private String myResult = ""; + private TextBuffer myResult = null; @Override - public void saveClassFile(String path, String qualifiedName, String entryName, String content) { - if (myResult.isEmpty()) { + public void saveClassFile(String path, String qualifiedName, String entryName, TextBuffer content) { + if (myResult == null || myResult.length() == 0) { myResult = content; } } From 675f89908bc9965aaf4dac79810fcac515fe5eb1 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 7 Oct 2014 20:38:13 +0400 Subject: [PATCH 13/16] check method name when searching for debugger position in compiled class --- .../intellij/debugger/engine/PositionManagerImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 016b01ed6f96..c6c20ff587e8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -152,7 +152,7 @@ public class PositionManagerImpl implements PositionManager { return SourcePosition.createFromLine(psiFile, -1); } - final MethodFinder finder = new MethodFinder(location.declaringType().name(), methodSignature); + final MethodFinder finder = new MethodFinder(location.declaringType().name(), methodName, methodSignature); psiFile.accept(finder); final PsiMethod compiledMethod = finder.getCompiledMethod(); @@ -382,11 +382,13 @@ public class PositionManagerImpl implements PositionManager { private class MethodFinder extends JavaRecursiveElementVisitor { private final String myClassName; private PsiClass myCompiledClass; + private final String myMethodName; private final String myMethodSignature; private PsiMethod myCompiledMethod; - public MethodFinder(final String className, final String methodSignature) { + public MethodFinder(final String className, final String methodName, final String methodSignature) { myClassName = className; + myMethodName = methodName; myMethodSignature = methodSignature; } @@ -409,9 +411,8 @@ public class PositionManagerImpl implements PositionManager { if(containingClass != null && containingClass.equals(myCompiledClass) && - methodName.equals(methodName) && + methodName.equals(myMethodName) && JVMNameUtil.getJVMSignature(method).getName(myDebugProcess).equals(myMethodSignature)) { - myCompiledMethod = method; } } From 03c31c5b11249a3dc29bf60ed42130ce83c7f5ea Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 7 Oct 2014 21:03:09 +0400 Subject: [PATCH 14/16] calculate less indent buffers --- .../java/decompiler/main/ClassWriter.java | 54 ++++++++----------- .../java/decompiler/main/TextBuffer.java | 16 +++++- .../main/collectors/BytecodeSourceMapper.java | 20 +++---- .../java/decompiler/util/InterpreterUtil.java | 11 ++-- .../java/decompiler/IdeaDecompiler.java | 3 +- 5 files changed, 49 insertions(+), 55 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 61507fb8a92b..bdc2afa9d752 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 @@ -149,8 +149,7 @@ public class ClassWriter { methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer); - InterpreterUtil.appendIndent(buffer, indent); - buffer.append("}"); + buffer.appendIndent(indent).append("}"); } } finally { @@ -265,8 +264,7 @@ public class ClassWriter { } } - InterpreterUtil.appendIndent(buffer, indent); - buffer.append('}'); + buffer.appendIndent(indent).append('}'); if (node.type != ClassNode.CLASS_ANONYMOUS) { buffer.append(lineSeparator); @@ -281,7 +279,6 @@ public class ClassWriter { private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { String lineSeparator = DecompilerContext.getNewLineSeparator(); - String indentString = InterpreterUtil.getIndentString(indent); if (node.type == ClassNode.CLASS_ANONYMOUS) { buffer.append(" {"); @@ -300,7 +297,7 @@ public class ClassWriter { boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0; if (isDeprecated) { - appendDeprecation(buffer, indentString, lineSeparator); + appendDeprecation(buffer, indent, lineSeparator); } if (interceptor != null) { @@ -309,12 +306,12 @@ public class ClassWriter { } if (isSynthetic) { - appendComment(buffer, "synthetic class", indentString, lineSeparator); + appendComment(buffer, "synthetic class", indent, lineSeparator); } appendAnnotations(buffer, cl, indent, lineSeparator); - buffer.append(indentString); + buffer.appendIndent(indent); if (isEnum) { // remove abstract and final flags (JLS 8.9 Enums) @@ -391,7 +388,6 @@ public class ClassWriter { } private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { - String indentString = InterpreterUtil.getIndentString(indent); String lineSeparator = DecompilerContext.getNewLineSeparator(); boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); @@ -399,7 +395,7 @@ public class ClassWriter { boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); if (isDeprecated) { - appendDeprecation(buffer, indentString, lineSeparator); + appendDeprecation(buffer, indent, lineSeparator); } if (interceptor != null) { @@ -408,12 +404,12 @@ public class ClassWriter { } if (fd.isSynthetic()) { - appendComment(buffer, "synthetic field", indentString, lineSeparator); + appendComment(buffer, "synthetic field", indent, lineSeparator); } appendAnnotations(buffer, fd, indent, lineSeparator); - buffer.append(indentString); + buffer.appendIndent(indent); if (!isEnum) { appendModifiers(buffer, fd.getAccessFlags(), FIELD_ALLOWED, isInterface, FIELD_EXCLUDED); @@ -494,7 +490,7 @@ public class ClassWriter { MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(lambdaNode.lambda_information.method_descriptor); if (!codeOnly) { - InterpreterUtil.appendIndent(buffer, indent); + buffer.appendIndent(indent); buffer.append("public "); buffer.append(method_name); buffer.append("("); @@ -547,7 +543,7 @@ public class ClassWriter { } if (methodWrapper.decompiledWithErrors) { - InterpreterUtil.appendIndent(buffer, indent); + buffer.appendIndent(indent); buffer.append("// $FF: Couldn't be decompiled"); buffer.append(DecompilerContext.getNewLineSeparator()); } @@ -555,7 +551,7 @@ public class ClassWriter { if (!codeOnly) { indent -= 1; - InterpreterUtil.appendIndent(buffer, indent); + buffer.appendIndent(indent); buffer.append('}'); buffer.append(DecompilerContext.getNewLineSeparator()); } @@ -573,7 +569,6 @@ public class ClassWriter { boolean hideMethod = false; int start_index_method = buffer.length(); - String indentString = InterpreterUtil.getIndentString(indent); String lineSeparator = DecompilerContext.getNewLineSeparator(); MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); @@ -606,7 +601,7 @@ public class ClassWriter { } if (isDeprecated) { - appendDeprecation(buffer, indentString, lineSeparator); + appendDeprecation(buffer, indent, lineSeparator); } if (interceptor != null) { @@ -617,15 +612,15 @@ public class ClassWriter { boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic"); boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0; if (isSynthetic) { - appendComment(buffer, "synthetic method", indentString, lineSeparator); + appendComment(buffer, "synthetic method", indent, lineSeparator); } if (isBridge) { - appendComment(buffer, "bridge method", indentString, lineSeparator); + appendComment(buffer, "bridge method", indent, lineSeparator); } appendAnnotations(buffer, mt, indent, lineSeparator); - buffer.append(indentString); + buffer.appendIndent(indent); appendModifiers(buffer, flags, METHOD_ALLOWED, isInterface, METHOD_EXCLUDED); @@ -811,8 +806,7 @@ public class ClassWriter { //TODO: for now only start line set buffer.setCurrentLine(startLine); - buffer.append('{'); - buffer.append(lineSeparator); + buffer.append('{').appendLineSeparator(); RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root; @@ -834,14 +828,12 @@ public class ClassWriter { } if (methodWrapper.decompiledWithErrors) { - buffer.append(InterpreterUtil.getIndentString(indent + 1)); + buffer.appendIndent(indent + 1); buffer.append("// $FF: Couldn't be decompiled"); buffer.append(lineSeparator); } - buffer.append(indentString); - buffer.append('}'); - buffer.append(lineSeparator); + buffer.appendIndent(indent).append('}').appendLineSeparator(); } } finally { @@ -872,8 +864,8 @@ public class ClassWriter { return true; } - private static void appendDeprecation(TextBuffer buffer, String indentString, String lineSeparator) { - buffer.append(indentString).append("/** @deprecated */").append(lineSeparator); + private static void appendDeprecation(TextBuffer buffer, int indent, String lineSeparator) { + buffer.appendIndent(indent).append("/** @deprecated */").append(lineSeparator); } private enum MType {CLASS, FIELD, METHOD} @@ -881,7 +873,7 @@ public class ClassWriter { private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent, String lineSeparator) { if (oldName == null) return; - InterpreterUtil.appendIndent(buffer, indent); + buffer.appendIndent(indent); buffer.append("// $FF: renamed from: "); switch (type) { @@ -926,8 +918,8 @@ public class ClassWriter { return typeText; } - private static void appendComment(TextBuffer buffer, String comment, String indentString, String lineSeparator) { - buffer.append(indentString).append("// $FF: ").append(comment).append(lineSeparator); + private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) { + buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator); } private static final String[] ANNOTATION_ATTRIBUTES = { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java index 6d279bfe1863..32766ca030c2 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java @@ -15,6 +15,8 @@ */ package org.jetbrains.java.decompiler.main; +import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; + import java.util.*; /** @@ -24,6 +26,7 @@ import java.util.*; */ public class TextBuffer { private final String myLineSeparator = DecompilerContext.getNewLineSeparator(); + private final String myIndent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING); private final StringBuilder myStringBuilder; private Map myLineToOffsetMapping = null; @@ -57,13 +60,21 @@ public class TextBuffer { return this; } - public void addBanner(String banner) { + public TextBuffer appendIndent(int length) { + while (length-- > 0) { + append(myIndent); + } + return this; + } + + public TextBuffer addBanner(String banner) { myStringBuilder.insert(0, banner); if (myLineToOffsetMapping != null) { for (Integer line : myLineToOffsetMapping.keySet()) { myLineToOffsetMapping.put(line, myLineToOffsetMapping.get(line) + banner.length()); } } + return this; } @Override @@ -138,7 +149,7 @@ public class TextBuffer { myStringBuilder.setLength(position); } - public void append(TextBuffer buffer) { + public TextBuffer append(TextBuffer buffer) { if (buffer.myLineToOffsetMapping != null && !buffer.myLineToOffsetMapping.isEmpty()) { checkMapCreated(); for (Map.Entry entry : buffer.myLineToOffsetMapping.entrySet()) { @@ -146,6 +157,7 @@ public class TextBuffer { } } myStringBuilder.append(buffer.myStringBuilder); + return this; } private void checkMapCreated() { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java index 36c8ac8f5c28..7bf4f08ee31d 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java @@ -1,11 +1,10 @@ package org.jetbrains.java.decompiler.main.collectors; -import java.util.HashMap; -import java.util.Map.Entry; - import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.TextBuffer; -import org.jetbrains.java.decompiler.util.InterpreterUtil; + +import java.util.HashMap; +import java.util.Map.Entry; public class BytecodeSourceMapper { @@ -41,9 +40,6 @@ public class BytecodeSourceMapper { public void dumpMapping(TextBuffer buffer) { String lineSeparator = DecompilerContext.getNewLineSeparator(); - String indentstr1 = InterpreterUtil.getIndentString(1); - String indentstr2 = InterpreterUtil.getIndentString(2); - for(Entry>> class_entry : mapping.entrySet()) { HashMap> class_mapping = class_entry.getValue(); @@ -55,17 +51,17 @@ public class BytecodeSourceMapper { HashMap method_mapping = method_entry.getValue(); if(!is_first_method) { - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } - buffer.append(indentstr1 + "method " + method_entry.getKey() + "{" + lineSeparator); + buffer.appendIndent(1).append("method " + method_entry.getKey() + "{" + lineSeparator); for(Entry line : method_mapping.entrySet()) { - buffer.append(indentstr2 + line.getKey() + indentstr2 + (line.getValue() +offset_total) + lineSeparator); + buffer.appendIndent(2).append(line.getKey().toString()).appendIndent(2).append((line.getValue() + offset_total) + lineSeparator); } - buffer.append(indentstr1 + "}" + lineSeparator); + buffer.appendIndent(1).append("}").appendLineSeparator(); is_first_method = false; } - buffer.append("}" + lineSeparator); + buffer.append("}").appendLineSeparator(); } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java index 50411bc8a565..67af3ad57dc4 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java @@ -92,17 +92,12 @@ public class InterpreterUtil { public static String getIndentString(int length) { if (length == 0) return ""; - TextBuffer buf = new TextBuffer(); - appendIndent(buf, length); - return buf.toString(); - } - - public static void appendIndent(TextBuffer buffer, int length) { - if (length == 0) return; + StringBuilder buf = new StringBuilder(); String indent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING); while (length-- > 0) { - buffer.append(indent); + buf.append(indent); } + return buf.toString(); } public static boolean equalSets(Collection c1, Collection c2) { diff --git a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java index 6181f3b2b734..1cba4baa22c5 100644 --- a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java +++ b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java @@ -151,8 +151,7 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light { } decompiler.decompileContext(); - saver.myResult.addBanner(BANNER); - return saver.myResult.toString(); + return saver.myResult.addBanner(BANNER).toString(); } catch (Exception e) { if (ApplicationManager.getApplication().isUnitTestMode()) { From 871d2fb5ab91938ab00498fb519171a385da514d Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Oct 2014 19:25:28 +0200 Subject: [PATCH 15/16] IDEA-130774 Cyclic expand word overwrites following characters --- .../codeInsight/completion/HippieCompletionTest.groovy | 8 ++++++++ .../completion/actions/HippieWordCompletionHandler.java | 7 +++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy index b5f3afcb6501..186f420b51a4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy @@ -211,6 +211,14 @@ foo->bar ''' } + public void "test inside word"() { + myFixture.configureByText "a.c", 'foo fox fbar' + complete() + myFixture.checkResult 'foo fox foxbar' + complete() + myFixture.checkResult 'foo fox foobar' + } + private void complete() { myFixture.performEditorAction(IdeActions.ACTION_HIPPIE_COMPLETION) } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java index a07e5c1f0b06..d56a5a0a762a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java @@ -55,8 +55,8 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler { public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file) { if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; - int offset = editor.getCaretModel().getOffset(); - if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) { + int caretOffset = editor.getCaretModel().getOffset(); + if (editor.isViewer() || editor.getDocument().getRangeGuard(caretOffset, caretOffset) != null) { editor.getDocument().fireReadOnlyModificationAttempt(); CodeInsightUtilBase.showReadOnlyViewWarning(editor); return; @@ -87,8 +87,7 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler { CompletionVariant nextVariant = computeNextVariant(editor, oldPrefix, lastProposedVariant, data, file, fromOtherFiles, false); if (nextVariant == null) return; - int replacementEnd = data.startOffset + data.myWordUnderCursor.length(); - editor.getDocument().replaceString(data.startOffset, replacementEnd, nextVariant.variant); + editor.getDocument().replaceString(data.startOffset, caretOffset, nextVariant.variant); editor.getCaretModel().moveToOffset(data.startOffset + nextVariant.variant.length()); completionState.lastProposedVariant = nextVariant; completionState.fromOtherFiles = nextVariant.editor != editor; From 83f912fb12ff1cfb95c1b37bc117d6aabbfa1e03 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 7 Oct 2014 21:50:08 +0400 Subject: [PATCH 16/16] IDEA-130888 "Find action" don't navigate to selected option --- .../ide/actions/ShowSettingsUtilImpl.java | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java index d8237874e1c0..a8b9809cf65e 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java @@ -164,7 +164,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { ConfigurableGroup[] group = getConfigurableGroups(project, true); group = filterEmptyGroups(group); - final Configurable configurable2Select = findConfigurable2Select(id2Select, group); + final Configurable configurable2Select = id2Select == null ? null : new ConfigurableVisitor.ByID(id2Select).find(group); if (ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.settings.view")) { new SettingsDialog(getProject(project), group, configurable2Select, filter).show(); @@ -183,31 +183,6 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { dialog.show(); } - @Nullable - private static Configurable findConfigurable2Select(String id2Select, ConfigurableGroup[] group) { - for (ConfigurableGroup configurableGroup : group) { - for (Configurable configurable : configurableGroup.getConfigurables()) { - final Configurable conf = containsId(id2Select, configurable); - if (conf != null) return conf; - } - } - return null; - } - - @Nullable - private static Configurable containsId(String id2Select, Configurable configurable) { - if (configurable instanceof SearchableConfigurable && id2Select.equals(((SearchableConfigurable)configurable).getId())) { - return configurable; - } - if (configurable instanceof SearchableConfigurable.Parent) { - for (Configurable subConfigurable : ((SearchableConfigurable.Parent)configurable).getConfigurables()) { - final Configurable config = containsId(id2Select, subConfigurable); - if (config != null) return config; - } - } - return null; - } - @Override public void showSettingsDialog(@NotNull final Project project, final Configurable toSelect) { getDialog(project, getConfigurableGroups(project, true), toSelect).show();