From 5054ae058e5f981e702d3457b454bd17ee533463 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 10:00:09 +0100 Subject: [PATCH 01/53] =?UTF-8?q?show=20message=20=E2=80=94=20pass=20proje?= =?UTF-8?q?ct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../testng/src/com/theoryinpractice/testng/TestNGFramework.java | 2 +- .../src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java b/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java index f9808bd06f54..f23e4f4246b2 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java +++ b/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java @@ -103,7 +103,7 @@ public class TestNGFramework extends JavaTestFramework { if (inClass != null) { int exit = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : - Messages.showYesNoDialog("Method \'" + setUpName + "\' already exist but is not annotated as @BeforeMethod.", + Messages.showYesNoDialog(manager.getProject(), "Method \'" + setUpName + "\' already exist but is not annotated as @BeforeMethod.", CommonBundle.getWarningTitle(), "Annotate", "Create new method", diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java index c9c1eb98e1a6..a58395d257c0 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java @@ -119,7 +119,7 @@ public class DefaultUrlOpener extends UrlOpener { AppUIUtil.invokeOnEdt(new Runnable() { @Override public void run() { - if (Messages.showYesNoDialog(StringUtil.notNullize(error, "Unknown error"), XmlBundle.message("browser.error"), Messages.OK_BUTTON, "Fix\u2026", null) == Messages.NO) { + if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), XmlBundle.message("browser.error"), Messages.OK_BUTTON, "Fix\u2026", null) == Messages.NO) { final BrowserSettings browserSettings = new BrowserSettings(); ShowSettingsUtil.getInstance().editConfigurable(project, browserSettings, browser == null ? null : new Runnable() { @Override From a7753550834c48f62f9365ffa8b3edd6d5412fb1 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 10:05:51 +0100 Subject: [PATCH 02/53] extract button.fix resource --- .../facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java | 2 +- .../facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java | 2 +- .../roots/ui/configuration/artifacts/ArtifactErrorPanel.java | 3 ++- .../platform-resources-en/src/messages/IdeBundle.properties | 2 +- .../src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java index 0bb6900789c8..63ba7def99d5 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java @@ -117,7 +117,7 @@ public class FacetLibrariesValidatorImpl extends FacetLibrariesValidator { private CustomLibraryDescription myDescription; public LibrariesQuickFix(CustomLibraryDescription description) { - super(IdeBundle.message("missing.libraries.fix.button")); + super(IdeBundle.message("button.fix")); myDescription = description; } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java index 95f012e6bf70..be22534d2754 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java @@ -73,7 +73,7 @@ public class FrameworkLibraryValidatorImpl extends FrameworkLibraryValidator { private CustomLibraryDescription myDescription; public LibrariesQuickFix(CustomLibraryDescription description) { - super(IdeBundle.message("missing.libraries.fix.button")); + super(IdeBundle.message("button.fix")); myDescription = description; } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java index 4d0da3eb903c..f55955929d21 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java @@ -16,6 +16,7 @@ package com.intellij.openapi.roots.ui.configuration.artifacts; import com.intellij.icons.AllIcons; +import com.intellij.ide.IdeBundle; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ConfigurationErrorQuickFix; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; @@ -96,7 +97,7 @@ public class ArtifactErrorPanel { myCurrentQuickFixes = quickFixes; myFixButton.setVisible(!quickFixes.isEmpty()); if (!quickFixes.isEmpty()) { - myFixButton.setText(quickFixes.size() == 1 ? ContainerUtil.getFirstItem(quickFixes, null).getActionName() : "Fix..."); + myFixButton.setText(quickFixes.size() == 1 ? ContainerUtil.getFirstItem(quickFixes, null).getActionName() : IdeBundle.message("button.fix")); } } diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 2ec314a77652..bd9acb3305c4 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1006,7 +1006,7 @@ error.file.download.failed=Failed to download ''{0}'': {1} maven.repository.presentable.name=Maven repository label.missed.libraries.prefix=The following libraries are missing: label.missed.libraries.text=''{0}'' library not found in the module dependencies list -missing.libraries.fix.button=Fix... +button.fix=Fix\u2026 setup.library.dialog.title=Setup Library label.library.will.be.created.description.text={0} level library {1} with {2} {2, choice, 1#file|2#files} will be created new.library.file.chooser.title=New Library Files diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java index a58395d257c0..a28505ed9465 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java @@ -119,7 +119,7 @@ public class DefaultUrlOpener extends UrlOpener { AppUIUtil.invokeOnEdt(new Runnable() { @Override public void run() { - if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), XmlBundle.message("browser.error"), Messages.OK_BUTTON, "Fix\u2026", null) == Messages.NO) { + if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), XmlBundle.message("browser.error"), Messages.OK_BUTTON, IdeBundle.message("button.fix"), null) == Messages.NO) { final BrowserSettings browserSettings = new BrowserSettings(); ShowSettingsUtil.getInstance().editConfigurable(project, browserSettings, browser == null ? null : new Runnable() { @Override From 4c2d519369515dcc18f763cdeaea1d0619373165 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 10:48:09 +0100 Subject: [PATCH 03/53] =?UTF-8?q?continue:=20add=20"Fix"=20button=20?= =?UTF-8?q?=E2=80=94=20open=20web=20browser=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/intellij/ide/BrowserUtil.java | 2 +- .../src/messages/IdeBundle.properties | 3 +- .../src/messages/XmlBundle.properties | 3 ++ .../com/intellij/ide/browsers/WebBrowser.java | 5 ++- .../ide/browsers/impl/DefaultUrlOpener.java | 34 +++++++------------ 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 16a250b98024..a882fac3017d 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -226,7 +226,7 @@ public class BrowserUtil { return null; } - private static void launchBrowserByCommand(@NotNull final URI uri, @NotNull final List command) { + private static void launchBrowserByCommand(@NotNull URI uri, @NotNull List command) { try { GeneralCommandLine commandLine = new GeneralCommandLine(command); commandLine.addParameter(uri.toString()); diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index bd9acb3305c4..b3a4669f5a5a 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1,10 +1,9 @@ -title.cannot.start.browser=Cannot start browser error.malformed.url=Malformed url: {0} error.cannot.start.browser=Cannot start browser: {0} error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers -error.0.browser.path.not.specified={0} browser path is not specified in {1} | Web Browsers title.browser.not.found=Browser Not Found title.browser.path.not.found=Browser Path Not Found + action.sort.alphabetically=Sort Alphabetically button.finish=&Finish button.ok=&OK diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties index 4cc0e41824bc..5f38fff182cf 100644 --- a/platform/platform-resources-en/src/messages/XmlBundle.properties +++ b/platform/platform-resources-en/src/messages/XmlBundle.properties @@ -154,7 +154,10 @@ browsers.opera=Opera browsers.firefox=Firefox browsers.chrome=Chrome browser.description=Open file in {0} + browser.error=Browser Error +error.0.browser.path.not.specified={0} browser path is not specified. + web.editor.configuration.title=Web browser.select.in.default.name=Web Browser diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java index e9ead7c9994d..82a56623ec31 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java @@ -15,10 +15,9 @@ */ package com.intellij.ide.browsers; -import com.intellij.CommonBundle; -import com.intellij.ide.IdeBundle; import com.intellij.openapi.util.NullableComputable; import com.intellij.util.xmlb.Converter; +import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,7 +60,7 @@ public abstract class WebBrowser { @NotNull public String getBrowserNotFoundMessage() { - return IdeBundle.message("error.0.browser.path.not.specified", getFamily().getName(), CommonBundle.settingsActionPath()); + return XmlBundle.message("error.0.browser.path.not.specified", getName()); } @Nullable diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java index a28505ed9465..e85420eef9d4 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -56,33 +56,23 @@ public class DefaultUrlOpener extends UrlOpener { boolean newWindowIfPossible, @Nullable final Project project, @NotNull String... additionalParameters) { - final String browserPath = browser.getPath(); + String browserPath = browser.getPath(); if (StringUtil.isEmpty(browserPath)) { - AppUIUtil.invokeOnEdt(new Runnable() { - @Override - public void run() { - Messages.showErrorDialog(project, browser.getBrowserNotFoundMessage(), IdeBundle.message("title.browser.not.found")); - } - }); + showError(browser.getBrowserNotFoundMessage(), browser, project, IdeBundle.message("title.browser.not.found")); return false; } - - return doLaunchBrowser(browserPath, browser.getSpecificSettings(), url, newWindowIfPossible, project, browser, additionalParameters); + else { + return doLaunchBrowser(browser, browserPath, url, newWindowIfPossible, project, additionalParameters); + } } - private static boolean doLaunchBrowser(final String browserPath, - @Nullable BrowserSpecificSettings browserSpecificSettings, - final String url, - final boolean newWindowIfPossible, - @Nullable final Project project, - @NotNull final WebBrowser browser, - final String[] additionalParameters) { + private static boolean doLaunchBrowser(@NotNull final WebBrowser browser, String browserPath, String url, boolean newWindowIfPossible, @Nullable final Project project, String[] additionalParameters) { GeneralCommandLine commandLine = new GeneralCommandLine(BrowserUtil.getOpenBrowserCommand(browserPath, newWindowIfPossible)); if (url != null) { commandLine.addParameter(url); } - addArgs(commandLine, browserSpecificSettings, additionalParameters); + addArgs(commandLine, browser.getSpecificSettings(), additionalParameters); try { final Process process = commandLine.createProcess(); @@ -92,7 +82,7 @@ public class DefaultUrlOpener extends UrlOpener { public void run() { try { if (process.waitFor() == 1) { - showError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project); + showError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project, null); } } catch (InterruptedException ignored) { @@ -110,16 +100,16 @@ public class DefaultUrlOpener extends UrlOpener { return true; } catch (ExecutionException e) { - showError(e.getMessage(), browser, project); + showError(e.getMessage(), browser, project, null); return false; } } - private static void showError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project) { + private static void showError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, @Nullable final String title) { AppUIUtil.invokeOnEdt(new Runnable() { @Override public void run() { - if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), XmlBundle.message("browser.error"), Messages.OK_BUTTON, IdeBundle.message("button.fix"), null) == Messages.NO) { + if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), title == null ? XmlBundle.message("browser.error") : title, Messages.OK_BUTTON, IdeBundle.message("button.fix"), null) == Messages.NO) { final BrowserSettings browserSettings = new BrowserSettings(); ShowSettingsUtil.getInstance().editConfigurable(project, browserSettings, browser == null ? null : new Runnable() { @Override From 3395850d7ab8fe7ae7124a03bea82368076766c4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 10:53:50 +0100 Subject: [PATCH 04/53] =?UTF-8?q?continue:=20add=20"Fix"=20button=20?= =?UTF-8?q?=E2=80=94=20open=20web=20browser=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xml/impl/src/com/intellij/ide/browsers/UrlOpener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java index 16250913d306..747b855f6709 100644 --- a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java @@ -39,7 +39,7 @@ public abstract class UrlOpener { } else { for (UrlOpener urlOpener : EP_NAME.getExtensions()) { - if (urlOpener.openUrl(browser, url, null)) { + if (urlOpener.openUrl(browser, url, project)) { return; } } From e7200d54c76f05ad9f1b54371e58bf3ba3560196 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 10:57:38 +0100 Subject: [PATCH 05/53] cleanup --- xml/impl/src/com/intellij/ide/browsers/UrlOpener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java index 747b855f6709..cb3e27086d59 100644 --- a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. From 4389b6606ea8189d1003a9bb34dbfd4963281908 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 11:09:59 +0100 Subject: [PATCH 06/53] move BrowserFamily to upper level --- .../intellij/ide/browsers/BrowserFamily.java | 84 +++++++++++++++++++ .../ide/browsers/BrowserSelector.java | 4 +- .../ide/browsers/BrowserSettingsPanel.java | 1 - .../ide/browsers/BrowsersConfiguration.java | 79 ----------------- .../ide/browsers/ConfigurableWebBrowser.java | 2 - .../ide/browsers/CustomWebBrowser.java | 2 +- .../com/intellij/ide/browsers/UrlOpener.java | 4 - .../com/intellij/ide/browsers/WebBrowser.java | 2 - .../ide/browsers/WebBrowserManager.java | 2 - .../impl/BrowserConfigurationHelper.java | 14 ++-- 10 files changed, 94 insertions(+), 100 deletions(-) create mode 100644 xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java b/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java new file mode 100644 index 000000000000..63169b7c827f --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java @@ -0,0 +1,84 @@ +package com.intellij.ide.browsers; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.browsers.chrome.ChromeSettings; +import com.intellij.ide.browsers.firefox.FirefoxSettings; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.xml.XmlBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public enum BrowserFamily implements Iconable { + CHROME(XmlBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) { + @Override + public BrowserSpecificSettings createBrowserSpecificSettings() { + return new ChromeSettings(); + } + }, + EXPLORER(XmlBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16), + FIREFOX(XmlBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) { + @Override + public BrowserSpecificSettings createBrowserSpecificSettings() { + return new FirefoxSettings(); + } + }, + OPERA(XmlBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16), + SAFARI(XmlBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16); + + private final String myName; + private final String myWindowsPath; + private final String myUnixPath; + private final String myMacPath; + private final Icon myIcon; + + BrowserFamily(@NotNull String name, + @NotNull final String windowsPath, + @Nullable final String unixPath, + @Nullable final String macPath, + @NotNull Icon icon) { + myName = name; + myWindowsPath = windowsPath; + myUnixPath = unixPath; + myMacPath = macPath; + myIcon = icon; + } + + @Nullable + public BrowserSpecificSettings createBrowserSpecificSettings() { + return null; + } + + @Nullable + public String getExecutionPath() { + if (SystemInfo.isWindows) { + return myWindowsPath; + } + else if (SystemInfo.isMac) { + return myMacPath; + } + else { + return myUnixPath; + } + } + + public String getName() { + return myName; + } + + public Icon getIcon() { + return myIcon; + } + + @Override + public String toString() { + return myName; + } + + @Override + public Icon getIcon(@IconFlags int flags) { + return getIcon(); + } +} \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java index 5a144fbd4f32..9bbadf3be254 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java @@ -88,7 +88,7 @@ public class BrowserSelector { /** * @deprecated to remove in IDEA 14 */ - public BrowsersConfiguration.BrowserFamily getSelectedBrowser() { + public BrowserFamily getSelectedBrowser() { WebBrowser selected = getSelected(); return selected == null ? null : selected.getFamily(); } @@ -109,7 +109,7 @@ public class BrowserSelector { /** * @deprecated to remove in IDEA 14 */ - public void setSelectedBrowser(@SuppressWarnings("deprecation") @Nullable BrowsersConfiguration.BrowserFamily selectedItem) { + public void setSelectedBrowser(@SuppressWarnings("deprecation") @Nullable BrowserFamily selectedItem) { setSelected(selectedItem == null ? null : WebBrowserManager.getInstance().findBrowser(selectedItem)); } diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java index 97fae1571977..8b5439aed03c 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java @@ -49,7 +49,6 @@ import java.awt.event.ItemListener; import java.util.Collections; import java.util.UUID; -import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; import static com.intellij.ide.browsers.WebBrowserManager.DefaultBrowser; import static com.intellij.util.ui.table.TableModelEditor.EditableColumnInfo; diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java b/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java index 2def85b9c953..73e2f2286ede 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java @@ -15,93 +15,14 @@ */ package com.intellij.ide.browsers; -import com.intellij.icons.AllIcons; -import com.intellij.ide.browsers.chrome.ChromeSettings; -import com.intellij.ide.browsers.firefox.FirefoxSettings; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.util.Iconable; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.xml.XmlBundle; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.io.File; public class BrowsersConfiguration { - public enum BrowserFamily implements Iconable { - CHROME(XmlBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) { - @Override - public BrowserSpecificSettings createBrowserSpecificSettings() { - return new ChromeSettings(); - } - }, - EXPLORER(XmlBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16), - FIREFOX(XmlBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) { - @Override - public BrowserSpecificSettings createBrowserSpecificSettings() { - return new FirefoxSettings(); - } - }, - OPERA(XmlBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16), - SAFARI(XmlBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16); - - private final String myName; - private final String myWindowsPath; - private final String myUnixPath; - private final String myMacPath; - private final Icon myIcon; - - BrowserFamily(@NotNull String name, - @NotNull final String windowsPath, - @Nullable final String unixPath, - @Nullable final String macPath, - @NotNull Icon icon) { - myName = name; - myWindowsPath = windowsPath; - myUnixPath = unixPath; - myMacPath = macPath; - myIcon = icon; - } - - @Nullable - public BrowserSpecificSettings createBrowserSpecificSettings() { - return null; - } - - @Nullable - public String getExecutionPath() { - if (SystemInfo.isWindows) { - return myWindowsPath; - } - else if (SystemInfo.isMac) { - return myMacPath; - } - else { - return myUnixPath; - } - } - - public String getName() { - return myName; - } - - public Icon getIcon() { - return myIcon; - } - - @Override - public String toString() { - return myName; - } - - @Override - public Icon getIcon(@IconFlags int flags) { - return getIcon(); - } - } @SuppressWarnings({"UnusedDeclaration"}) @Nullable diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java index c48e8c5bdfa2..a6b44ca3a1dd 100644 --- a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java @@ -9,8 +9,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.UUID; -import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; - final class ConfigurableWebBrowser extends WebBrowser { private boolean active; private String path; diff --git a/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java index c55d1a10ac74..190731fbbc29 100644 --- a/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java @@ -13,7 +13,7 @@ final class CustomWebBrowser extends WebBrowser { private final String browserNotFoundMessage; CustomWebBrowser(@NotNull UUID id, - @NotNull BrowsersConfiguration.BrowserFamily family, + @NotNull BrowserFamily family, @NotNull String name, @NotNull Icon icon, @NotNull Computable pathComputable, diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java index cb3e27086d59..536e065476fd 100644 --- a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java @@ -24,10 +24,6 @@ import org.jetbrains.annotations.Nullable; public abstract class UrlOpener { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.jetbrains.urlOpener"); - public static void launchBrowser(final @Nullable BrowsersConfiguration.BrowserFamily family, final @NotNull String url) { - launchBrowser(url, family == null ? null : WebBrowserManager.getInstance().findBrowser(family)); - } - public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser) { launchBrowser(url, browser, null); } diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java index 82a56623ec31..a64b4c174381 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java @@ -24,8 +24,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.UUID; -import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; - public abstract class WebBrowser { protected @NotNull BrowserFamily family; protected @NotNull String name; diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java index 91e7607e401c..8072c8185111 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java @@ -32,8 +32,6 @@ import java.util.Collections; import java.util.List; import java.util.UUID; -import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; - @State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/web-browsers.xml")}) public class WebBrowserManager implements PersistentStateComponent, ModificationTracker { private static final Logger LOG = Logger.getInstance(WebBrowserManager.class); diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java index c534910d003e..dc08f2c357cd 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java @@ -15,7 +15,7 @@ */ package com.intellij.ide.browsers.impl; -import com.intellij.ide.browsers.BrowsersConfiguration; +import com.intellij.ide.browsers.BrowserFamily; import com.intellij.openapi.util.io.WindowsRegistryUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,13 +32,13 @@ public class BrowserConfigurationHelper { * Read data from Windows registry (may take some time to run). */ @NotNull - public static Map getBrowserPathsFromRegistry() { - Map map = - new EnumMap(BrowsersConfiguration.BrowserFamily.class); + public static Map getBrowserPathsFromRegistry() { + Map map = + new EnumMap(BrowserFamily.class); List sections = WindowsRegistryUtil.readRegistryBranch(START_MENU_KEY); for (String section : sections) { - BrowsersConfiguration.BrowserFamily family = getFamily(section); + BrowserFamily family = getFamily(section); if (family != null) { String pathToExe = WindowsRegistryUtil.readRegistryDefault(START_MENU_KEY + "\\" + section + "\\shell\\open\\command"); if (pathToExe != null) { @@ -51,9 +51,9 @@ public class BrowserConfigurationHelper { } @Nullable - private static BrowsersConfiguration.BrowserFamily getFamily(String registryName) { + private static BrowserFamily getFamily(String registryName) { registryName = registryName.toLowerCase(); - for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) { + for (BrowserFamily family : BrowserFamily.values()) { if (registryName.contains(family.getName().toLowerCase(Locale.US))) { return family; } From ab3c2925a425c9f42bfbd963051ebe60f684d665 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 11:11:03 +0100 Subject: [PATCH 07/53] remove deprecated BrowsersConfiguration --- .../src/META-INF/XmlPlugin.xml | 3 - .../ide/browsers/BrowsersConfiguration.java | 70 ------------------- 2 files changed, 73 deletions(-) delete mode 100644 xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 6f4d4318cf28..b5ca72c2d384 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -194,9 +194,6 @@ serviceImplementation="com.intellij.application.options.XmlSettings"/> - - diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java b/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java deleted file mode 100644 index 73e2f2286ede..000000000000 --- a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.ide.browsers; - -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import org.jetbrains.annotations.Nullable; - -import java.io.File; - -public class BrowsersConfiguration { - - @SuppressWarnings({"UnusedDeclaration"}) - @Nullable - @Deprecated - /** - * @deprecated to remove in IDEA 14 - */ - public static BrowsersConfiguration getInstance() { - return ServiceManager.getService(BrowsersConfiguration.class); - } - - @SuppressWarnings({"UnusedDeclaration"}) - @Nullable - @Deprecated - /** - * @deprecated to remove in IDEA 14 - */ - public BrowserFamily findFamilyByName(@Nullable String name) { - for (BrowserFamily family : BrowserFamily.values()) { - if (family.getName().equals(name)) { - return family; - } - } - return null; - } - - @SuppressWarnings({"UnusedDeclaration"}) - @Nullable - @Deprecated - /** - * @deprecated to remove in IDEA 14 - */ - public BrowserFamily findFamilyByPath(@Nullable String path) { - if (!StringUtil.isEmptyOrSpaces(path)) { - String name = FileUtil.getNameWithoutExtension(new File(path).getName()); - for (BrowserFamily family : BrowserFamily.values()) { - if (name.equalsIgnoreCase(family.getExecutionPath())) { - return family; - } - } - } - - return null; - } -} \ No newline at end of file From a6892528d352a73c670c4669758abdfab3676a20 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 11:27:37 +0100 Subject: [PATCH 08/53] update since-build --- platform/platform-resources-en/src/messages/IdeBundle.properties | 1 - xml/impl/src/com/intellij/ide/browsers/UrlOpener.java | 1 - 2 files changed, 2 deletions(-) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index b3a4669f5a5a..46efb01bfb8b 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -2,7 +2,6 @@ error.malformed.url=Malformed url: {0} error.cannot.start.browser=Cannot start browser: {0} error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers title.browser.not.found=Browser Not Found -title.browser.path.not.found=Browser Path Not Found action.sort.alphabetically=Sort Alphabetically button.finish=&Finish diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java index 536e065476fd..f4a573d57d01 100644 --- a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java @@ -28,7 +28,6 @@ public abstract class UrlOpener { launchBrowser(url, browser, null); } - // different params order in order not to break compilation for launchBrowser(null, url) public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) { if (browser == null) { BrowserUtil.launchBrowser(url); From ddd555fd16234756db88c38b2c365781cfc404c3 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 11:45:32 +0100 Subject: [PATCH 09/53] extract WebBrowserBase --- .../ide/browsers/ConfigurableWebBrowser.java | 2 +- .../ide/browsers/CustomWebBrowser.java | 2 +- .../ide/browsers/StartBrowserSettings.java | 2 +- .../com/intellij/ide/browsers/WebBrowser.java | 79 ++------------- .../intellij/ide/browsers/WebBrowserBase.java | 96 +++++++++++++++++++ .../OpenFileInDefaultBrowserAction.java | 5 +- .../ide/browsers/impl/DefaultUrlOpener.java | 5 +- 7 files changed, 107 insertions(+), 84 deletions(-) create mode 100644 xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java index a6b44ca3a1dd..a74c1b702831 100644 --- a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.UUID; -final class ConfigurableWebBrowser extends WebBrowser { +final class ConfigurableWebBrowser extends WebBrowserBase { private boolean active; private String path; diff --git a/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java index 190731fbbc29..d3f296631ae2 100644 --- a/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/CustomWebBrowser.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.UUID; -final class CustomWebBrowser extends WebBrowser { +final class CustomWebBrowser extends WebBrowserBase { private final Computable pathComputable; private final Icon icon; private final String browserNotFoundMessage; diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java index b87fd057f191..db6045ad24f4 100644 --- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java +++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java @@ -27,7 +27,7 @@ public class StartBrowserSettings { } @Nullable - @Attribute(value = "name", converter = WebBrowser.ReferenceConverter.class) + @Attribute(value = "name", converter = WebBrowserBase.ReferenceConverter.class) public WebBrowser getBrowser() { return myBrowser; } diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java index a64b4c174381..04eaa34123e9 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java @@ -1,23 +1,5 @@ -/* - * 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.intellij.ide.browsers; -import com.intellij.openapi.util.NullableComputable; -import com.intellij.util.xmlb.Converter; -import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,30 +7,14 @@ import javax.swing.*; import java.util.UUID; public abstract class WebBrowser { - protected @NotNull BrowserFamily family; - protected @NotNull String name; - private final UUID id; - - protected WebBrowser(@NotNull UUID id, @NotNull BrowserFamily family, @NotNull String name) { - this.id = id; - this.family = family; - this.name = name; - } + @NotNull + public abstract String getName(); @NotNull - public String getName() { - return name; - } + public abstract UUID getId(); @NotNull - public final UUID getId() { - return id; - } - - @NotNull - public BrowserFamily getFamily() { - return family; - } + public abstract BrowserFamily getFamily(); @NotNull public abstract Icon getIcon(); @@ -57,41 +23,8 @@ public abstract class WebBrowser { public abstract String getPath(); @NotNull - public String getBrowserNotFoundMessage() { - return XmlBundle.message("error.0.browser.path.not.specified", getName()); - } + public abstract String getBrowserNotFoundMessage(); @Nullable - public BrowserSpecificSettings getSpecificSettings() { - return null; - } - - @NotNull - public static WebBrowser createCustomBrowser(@NotNull BrowserFamily family, - @NotNull String name, - @NotNull UUID id, - @NotNull Icon icon, - @NotNull NullableComputable pathComputable, - @Nullable String browserNotFoundMessage) { - return new CustomWebBrowser(id, family, name, icon, pathComputable, browserNotFoundMessage); - } - - @Override - public String toString() { - return getName() + " (" + getPath() + ")"; - } - - public static final class ReferenceConverter extends Converter { - @Nullable - @Override - public WebBrowser fromString(@NotNull String value) { - return WebBrowserManager.getInstance().findBrowserById(value); - } - - @NotNull - @Override - public String toString(@NotNull WebBrowser browser) { - return browser.getId().toString(); - } - } + public abstract BrowserSpecificSettings getSpecificSettings(); } \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java new file mode 100644 index 000000000000..bc6af2b71e71 --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java @@ -0,0 +1,96 @@ +/* + * 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.intellij.ide.browsers; + +import com.intellij.openapi.util.NullableComputable; +import com.intellij.util.xmlb.Converter; +import com.intellij.xml.XmlBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.UUID; + +public abstract class WebBrowserBase extends WebBrowser { + protected @NotNull BrowserFamily family; + protected @NotNull String name; + private final UUID id; + + protected WebBrowserBase(@NotNull UUID id, @NotNull BrowserFamily family, @NotNull String name) { + this.id = id; + this.family = family; + this.name = name; + } + + @Override + @NotNull + public String getName() { + return name; + } + + @Override + @NotNull + public final UUID getId() { + return id; + } + + @Override + @NotNull + public BrowserFamily getFamily() { + return family; + } + + @Override + @NotNull + public String getBrowserNotFoundMessage() { + return XmlBundle.message("error.0.browser.path.not.specified", getName()); + } + + @Override + @Nullable + public BrowserSpecificSettings getSpecificSettings() { + return null; + } + + @NotNull + public static WebBrowser createCustomBrowser(@NotNull BrowserFamily family, + @NotNull String name, + @NotNull UUID id, + @NotNull Icon icon, + @NotNull NullableComputable pathComputable, + @Nullable String browserNotFoundMessage) { + return new CustomWebBrowser(id, family, name, icon, pathComputable, browserNotFoundMessage); + } + + @Override + public String toString() { + return getName() + " (" + getPath() + ")"; + } + + public static final class ReferenceConverter extends Converter { + @Nullable + @Override + public WebBrowser fromString(@NotNull String value) { + return WebBrowserManager.getInstance().findBrowserById(value); + } + + @NotNull + @Override + public String toString(@NotNull WebBrowser browser) { + return browser.getId().toString(); + } + } +} \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java index 48dc7bb2deb5..80ddd286fe5c 100644 --- a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java +++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java @@ -16,10 +16,7 @@ package com.intellij.ide.browsers.actions; import com.intellij.ide.GeneralSettings; -import com.intellij.ide.browsers.OpenInBrowserRequest; -import com.intellij.ide.browsers.WebBrowser; -import com.intellij.ide.browsers.WebBrowserManager; -import com.intellij.ide.browsers.WebBrowserUrlProvider; +import com.intellij.ide.browsers.*; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java index e85420eef9d4..bc760156e229 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java @@ -21,10 +21,7 @@ import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeBundle; -import com.intellij.ide.browsers.BrowserSettings; -import com.intellij.ide.browsers.BrowserSpecificSettings; -import com.intellij.ide.browsers.UrlOpener; -import com.intellij.ide.browsers.WebBrowser; +import com.intellij.ide.browsers.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ShowSettingsUtil; From 1bce66590a5105b82ce18c9e8ace53e0b834728a Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 11:46:37 +0100 Subject: [PATCH 10/53] extract WebBrowserBase --- .../ide/browsers/StartBrowserSettings.java | 2 +- .../intellij/ide/browsers/WebBrowserBase.java | 15 --------------- .../WebBrowserReferenceConverter.java | 19 +++++++++++++++++++ 3 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java index db6045ad24f4..5495b20e17fd 100644 --- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java +++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java @@ -27,7 +27,7 @@ public class StartBrowserSettings { } @Nullable - @Attribute(value = "name", converter = WebBrowserBase.ReferenceConverter.class) + @Attribute(value = "name", converter = WebBrowserReferenceConverter.class) public WebBrowser getBrowser() { return myBrowser; } diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java index bc6af2b71e71..56b4d5bf8904 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java @@ -16,7 +16,6 @@ package com.intellij.ide.browsers; import com.intellij.openapi.util.NullableComputable; -import com.intellij.util.xmlb.Converter; import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -79,18 +78,4 @@ public abstract class WebBrowserBase extends WebBrowser { public String toString() { return getName() + " (" + getPath() + ")"; } - - public static final class ReferenceConverter extends Converter { - @Nullable - @Override - public WebBrowser fromString(@NotNull String value) { - return WebBrowserManager.getInstance().findBrowserById(value); - } - - @NotNull - @Override - public String toString(@NotNull WebBrowser browser) { - return browser.getId().toString(); - } - } } \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java new file mode 100644 index 000000000000..d65f179241f7 --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java @@ -0,0 +1,19 @@ +package com.intellij.ide.browsers; + +import com.intellij.util.xmlb.Converter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class WebBrowserReferenceConverter extends Converter { + @Nullable + @Override + public WebBrowser fromString(@NotNull String value) { + return WebBrowserManager.getInstance().findBrowserById(value); + } + + @NotNull + @Override + public String toString(@NotNull WebBrowser browser) { + return browser.getId().toString(); + } +} \ No newline at end of file From aecf185bba87196c910af428fb421da45b04a1d2 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 11:54:12 +0100 Subject: [PATCH 11/53] prepare to move UrlOpener to platform-api --- .../src/messages/IdeBundle.properties | 6 ++++++ .../src/messages/XmlBundle.properties | 5 ----- .../src/com/intellij/ide/browsers/BrowserFamily.java | 12 ++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 46efb01bfb8b..39fd5a3d3238 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -3,6 +3,12 @@ error.cannot.start.browser=Cannot start browser: {0} error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers title.browser.not.found=Browser Not Found +browsers.explorer=Internet Explorer +browsers.safari=Safari +browsers.opera=Opera +browsers.firefox=Firefox +browsers.chrome=Chrome + action.sort.alphabetically=Sort Alphabetically button.finish=&Finish button.ok=&OK diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties index 5f38fff182cf..82c72e9b0662 100644 --- a/platform/platform-resources-en/src/messages/XmlBundle.properties +++ b/platform/platform-resources-en/src/messages/XmlBundle.properties @@ -148,11 +148,6 @@ cannot.resolve.anchor.in.file=Cannot resolve anchor #{0} in file {1} # web browsers browsers.configuration.name=Web Browsers -browsers.explorer=Internet Explorer -browsers.safari=Safari -browsers.opera=Opera -browsers.firefox=Firefox -browsers.chrome=Chrome browser.description=Open file in {0} browser.error=Browser Error diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java b/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java index 63169b7c827f..7a3a1dde9986 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java @@ -1,32 +1,32 @@ package com.intellij.ide.browsers; import com.intellij.icons.AllIcons; +import com.intellij.ide.IdeBundle; import com.intellij.ide.browsers.chrome.ChromeSettings; import com.intellij.ide.browsers.firefox.FirefoxSettings; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.SystemInfo; -import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; public enum BrowserFamily implements Iconable { - CHROME(XmlBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) { + CHROME(IdeBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) { @Override public BrowserSpecificSettings createBrowserSpecificSettings() { return new ChromeSettings(); } }, - EXPLORER(XmlBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16), - FIREFOX(XmlBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) { + EXPLORER(IdeBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16), + FIREFOX(IdeBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) { @Override public BrowserSpecificSettings createBrowserSpecificSettings() { return new FirefoxSettings(); } }, - OPERA(XmlBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16), - SAFARI(XmlBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16); + OPERA(IdeBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16), + SAFARI(IdeBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16); private final String myName; private final String myWindowsPath; From 982376729fd996b3d656b170f526a1e83017e55e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 12:00:33 +0100 Subject: [PATCH 12/53] prepare to move UrlOpener to platform-api --- .../intellij/ide/browsers/BrowserFamily.java | 0 .../ide/browsers/BrowserSpecificSettings.java | 0 .../ide/browsers/chrome/ChromeSettings.java | 0 .../chrome/ChromeSettingsConfigurable.form | 0 .../chrome/ChromeSettingsConfigurable.java | 0 .../ide/browsers/firefox/FirefoxProfile.java | 0 .../ide/browsers/firefox/FirefoxSettings.java | 0 .../firefox/FirefoxSettingsConfigurable.form | 18 +++++++++--------- .../firefox/FirefoxSettingsConfigurable.java | 6 +++--- .../ide/browsers/firefox/FirefoxUtil.java | 0 .../src/messages/IdeBundle.properties | 6 ++++++ .../src/messages/XmlBundle.properties | 6 ------ 12 files changed, 18 insertions(+), 18 deletions(-) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/BrowserFamily.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/BrowserSpecificSettings.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/chrome/ChromeSettings.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form (97%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java (97%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java (100%) diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/BrowserFamily.java rename to platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java rename to platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java rename to platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form rename to platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java rename to platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java rename to platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java rename to platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form similarity index 97% rename from xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form rename to platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form index bd1e753ec59b..27890c577f2f 100644 --- a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form +++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form @@ -29,19 +29,19 @@ - - - - - - - - + + + + + + + + @@ -66,7 +66,7 @@ - + diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java similarity index 97% rename from xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java rename to platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java index 9aedd893b31d..effd129eeb55 100644 --- a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java @@ -15,6 +15,7 @@ */ package com.intellij.ide.browsers.firefox; +import com.intellij.ide.IdeBundle; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.PathChooserDialog; import com.intellij.openapi.options.Configurable; @@ -25,7 +26,6 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; -import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.Nullable; @@ -50,7 +50,7 @@ public class FirefoxSettingsConfigurable implements Configurable { public FirefoxSettingsConfigurable(FirefoxSettings settings) { mySettings = settings; - myProfilesIniPathField.addBrowseFolderListener(XmlBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR); + myProfilesIniPathField.addBrowseFolderListener(IdeBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR); myProfilesIniPathField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { @@ -144,7 +144,7 @@ public class FirefoxSettingsConfigurable implements Configurable { @Override @Nls public String getDisplayName() { - return XmlBundle.message("display.name.firefox.settings"); + return IdeBundle.message("display.name.firefox.settings"); } @Override diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java rename to platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 39fd5a3d3238..7e82df4f4f1b 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -3,6 +3,12 @@ error.cannot.start.browser=Cannot start browser: {0} error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers title.browser.not.found=Browser Not Found +chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File +label.text.path.to.profiles.ini=Path to \"profiles.ini\": +label.text.profile=&Profile: +button.text.settings=Settings... +display.name.firefox.settings=Firefox Settings + browsers.explorer=Internet Explorer browsers.safari=Safari browsers.opera=Opera diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties index 82c72e9b0662..ee7468c273d7 100644 --- a/platform/platform-resources-en/src/messages/XmlBundle.properties +++ b/platform/platform-resources-en/src/messages/XmlBundle.properties @@ -222,12 +222,6 @@ cant.rename.file=Can't rename {0} to {1} cant.delete.file=Can't delete file {0} select.xsd.schema.dialog.title=Select XSD Schema -chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File -label.text.path.to.profiles.ini=Path to \"profiles.ini\": -label.text.profile=&Profile: -button.text.settings=Settings... -display.name.firefox.settings=Firefox Settings - emmet.title=Emmet emmet.configuration.title=Emmet (Zen Coding) emmet.enable.label=&Enable XML Emmet From ac8d9f560435434393e4e791fb386b02e82e262b Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 12:06:25 +0100 Subject: [PATCH 13/53] move UrlOpener to platform-api --- .../platform-api}/src/com/intellij/ide/browsers/UrlOpener.java | 0 .../platform-api}/src/com/intellij/ide/browsers/WebBrowser.java | 0 .../platform-resources/src/META-INF/PlatformExtensionPoints.xml | 2 ++ platform/platform-resources/src/META-INF/XmlPlugin.xml | 1 - 4 files changed, 2 insertions(+), 1 deletion(-) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/UrlOpener.java (100%) rename {xml/impl => platform/platform-api}/src/com/intellij/ide/browsers/WebBrowser.java (100%) diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/UrlOpener.java rename to platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java b/platform/platform-api/src/com/intellij/ide/browsers/WebBrowser.java similarity index 100% rename from xml/impl/src/com/intellij/ide/browsers/WebBrowser.java rename to platform/platform-api/src/com/intellij/ide/browsers/WebBrowser.java diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index 1b6b48f25ef0..4ab86f41ee1b 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -213,5 +213,7 @@ + + diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index b5ca72c2d384..9ee00e1f73e2 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -70,7 +70,6 @@ - From 613c3be0820ee54c905b6ae289b83982fdd6b126 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 16:40:28 +0100 Subject: [PATCH 14/53] move impl to BrowserLauncher --- .../src/com/intellij/ide/BrowserUtil.java | 365 +------------ .../ide/browsers/BrowserLauncher.java | 47 ++ .../com/intellij/ide/browsers/UrlOpener.java | 23 +- .../src/messages/IdeBundle.properties | 3 +- .../src/messages/XmlBundle.properties | 8 - .../src/META-INF/XmlPlugin.xml | 2 + .../ide/browsers/BrowserLauncherImpl.java | 496 ++++++++++++++++++ .../ide/browsers/BrowserSettingsPanel.java | 5 +- .../browsers/JavaScriptDebuggerStarter.java | 2 +- .../ide/browsers/OpenUrlHyperlinkInfo.java | 4 +- .../intellij/ide/browsers/WebBrowserBase.java | 4 +- .../actions/BaseOpenInBrowserAction.java | 6 +- .../ide/browsers/impl/DefaultUrlOpener.java | 126 +---- 13 files changed, 584 insertions(+), 507 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java create mode 100644 xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index a882fac3017d..bbd30f098a74 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -15,55 +15,29 @@ */ package com.intellij.ide; -import com.intellij.CommonBundle; -import com.intellij.Patches; -import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Ref; +import com.intellij.ide.browsers.BrowserLauncher; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.*; -import com.intellij.ui.GuiUtils; -import com.intellij.util.io.ZipUtil; -import com.intellij.util.ui.OptionsDialog; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.awt.*; import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import static com.intellij.util.containers.ContainerUtil.newSmartList; import static com.intellij.util.containers.ContainerUtilRt.newArrayList; public class BrowserUtil { - private static final Logger LOG = Logger.getInstance(BrowserUtil.class); - // The pattern for 'scheme' mainly according to RFC1738. // We have to violate the RFC since we need to distinguish // real schemes from local Windows paths; The only difference @@ -106,142 +80,23 @@ public class BrowserUtil { } public static void browse(@NotNull @NonNls String url) { - openOrBrowse(url, true); + BrowserLauncher.getInstance().openOrBrowse(url, true); } public static void open(@NotNull @NonNls String url) { - openOrBrowse(url, false); - } - - private static void openOrBrowse(@NotNull @NonNls String url, boolean browse) { - url = url.trim(); - - if (url.startsWith("jar:")) { - String files = extractFiles(url); - if (files == null) { - return; - } - url = files; - } - - URI uri; - if (isAbsoluteURL(url)) { - uri = VfsUtil.toUri(url); - } - else { - File file = new File(url); - if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) { - try { - Desktop.getDesktop().open(file); - return; - } - catch (IOException e) { - LOG.debug(e); - } - } - - browse(file); - return; - } - - if (uri == null) { - showErrorMessage(IdeBundle.message("error.malformed.url", url), CommonBundle.getErrorTitle()); - } - else { - browse(uri); - } + BrowserLauncher.getInstance().openOrBrowse(url, false); } /** * Main method: tries to launch a browser using every possible way */ public static void browse(@NotNull URI uri) { - LOG.debug("Launch browser: [" + uri + "]"); - - GeneralSettings settings = getGeneralSettingsInstance(); - if (settings.isUseDefaultBrowser()) { - if (isDesktopActionSupported(Desktop.Action.BROWSE)) { - try { - Desktop.getDesktop().browse(uri); - LOG.debug("Browser launched using JDK 1.6 API"); - return; - } - catch (Exception e) { - LOG.warn("Error while using Desktop API, fallback to CLI", e); - } - } - - List command = getDefaultBrowserCommand(); - if (command != null) { - launchBrowserByCommand(uri, command); - return; - } - } - - String browserPath = settings.getBrowserPath(); - if (StringUtil.isEmptyOrSpaces(browserPath)) { - String message = IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath()); - showErrorMessage(message, IdeBundle.message("title.browser.not.found")); - return; - } - - launchBrowserByCommand(uri, getOpenBrowserCommand(browserPath)); - } - - private static boolean isDesktopActionSupported(Desktop.Action action) { - return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 && - Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action); - } - - private static GeneralSettings getGeneralSettingsInstance() { - if (ApplicationManager.getApplication() != null) { - GeneralSettings settings = GeneralSettings.getInstance(); - if (settings != null) { - return settings; - } - } - - return new GeneralSettings(); - } - - public static boolean canStartDefaultBrowser() { - return isDesktopActionSupported(Desktop.Action.BROWSE) || - SystemInfo.isMac || SystemInfo.isWindows || - SystemInfo.isUnix && SystemInfo.hasXdgOpen(); - } - - @Nullable - @NonNls - private static List getDefaultBrowserCommand() { - if (SystemInfo.isWindows) { - return newArrayList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote("")); - } - else if (SystemInfo.isMac) { - return newSmartList(ExecUtil.getOpenCommandPath()); - } - else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { - return newSmartList("xdg-open"); - } - - return null; - } - - private static void launchBrowserByCommand(@NotNull URI uri, @NotNull List command) { - try { - GeneralCommandLine commandLine = new GeneralCommandLine(command); - commandLine.addParameter(uri.toString()); - commandLine.createProcess(); - - if (LOG.isDebugEnabled()) { - LOG.debug("Browser launched with command line: " + commandLine); - } - } - catch (ExecutionException e) { - showErrorMessage(IdeBundle.message("error.cannot.start.browser", e.getMessage()), CommonBundle.getErrorTitle()); - } + BrowserLauncher.getInstance().browse(uri); } + @SuppressWarnings("UnusedDeclaration") @NotNull + @Deprecated public static List getOpenBrowserCommand(@NonNls @NotNull String browserPathOrName) { return getOpenBrowserCommand(browserPathOrName, false); } @@ -266,210 +121,10 @@ public class BrowserUtil { } } - private static void showErrorMessage(final String message, final String title) { - final Application app = ApplicationManager.getApplication(); - if (app == null) { - return; // Not started yet. Not able to show message up. (Could happen in License panel under Linux). - } - - Runnable runnable = new Runnable() { - @Override - public void run() { - Messages.showMessageDialog(message, title, Messages.getErrorIcon()); - } - }; - - if (app.isDispatchThread()) { - runnable.run(); - } - else { - app.invokeLater(runnable, ModalityState.NON_MODAL); - } - } - - @Nullable - private static String extractFiles(String url) { - try { - int sharpPos = url.indexOf('#'); - String anchor = ""; - if (sharpPos != -1) { - anchor = url.substring(sharpPos); - url = url.substring(0, sharpPos); - } - - VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); - if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null; - - JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem(); - VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file); - if (jarVirtualFile == null) return null; - - String targetFilePath = file.getPath(); - String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR); - LOG.assertTrue(targetFileRelativePath != null); - - String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode()); - final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash); - - final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified()); - final File timestampFile = new File(outputDir, ".idea.timestamp"); - - String previousTimestamp = null; - if (timestampFile.exists()) { - previousTimestamp = FileUtil.loadFile(timestampFile); - } - - if (!currentTimestamp.equals(previousTimestamp)) { - final Ref extract = new Ref(); - Runnable r = new Runnable() { - @Override - public void run() { - final ConfirmExtractDialog dialog = new ConfirmExtractDialog(); - if (dialog.isToBeShown()) { - dialog.show(); - extract.set(dialog.isOK()); - } - else { - dialog.close(DialogWrapper.OK_EXIT_CODE); - extract.set(true); - } - } - }; - - try { - GuiUtils.runOrInvokeAndWait(r); - } - catch (InvocationTargetException ignored) { - extract.set(false); - } - catch (InterruptedException ignored) { - extract.set(false); - } - - if (!extract.get()) return null; - - @SuppressWarnings("ConstantConditions") - final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile(); - if (zipFile == null) return null; - ZipEntry entry = zipFile.getEntry(targetFileRelativePath); - if (entry == null) return null; - InputStream is = zipFile.getInputStream(entry); - try { - ZipUtil.extractEntry(entry, is, outputDir); - } - finally { - is.close(); - } - - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - new Task.Backgroundable(null, "Extracting files...", true) { - @Override - public void run(@NotNull final ProgressIndicator indicator) { - final int size = zipFile.size(); - final int[] counter = new int[]{0}; - - class MyFilter implements FilenameFilter { - private final Set myImportantDirs = new HashSet( - Arrays.asList(outputDir, new File(outputDir, "resources"))); - private final boolean myImportantOnly; - - private MyFilter(boolean importantOnly) { - myImportantOnly = importantOnly; - } - - @Override - public boolean accept(@NotNull File dir, @NotNull String name) { - indicator.checkCanceled(); - boolean result = myImportantOnly == myImportantDirs.contains(dir); - if (result) { - indicator.setFraction(((double)counter[0]) / size); - counter[0]++; - } - return result; - } - } - - try { - ZipUtil.extract(zipFile, outputDir, new MyFilter(true)); - ZipUtil.extract(zipFile, outputDir, new MyFilter(false)); - FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes()); - } - catch (IOException ignore) { - } - } - }.queue(); - } - }); - } - - return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor; - } - catch (IOException e) { - LOG.warn(e); - Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error"); - return null; - } - } - - public static void clearExtractedFiles() { - FileUtil.delete(getExtractedFilesDir()); - } - - private static File getExtractedFilesDir() { - return new File(PathManager.getSystemPath(), "ExtractedFiles"); - } - public static boolean isOpenCommandSupportArgs() { return SystemInfo.isMacOSSnowLeopard; } - private static class ConfirmExtractDialog extends OptionsDialog { - private ConfirmExtractDialog() { - super(null); - setTitle("Confirmation"); - init(); - } - - @Override - protected boolean isToBeShown() { - return getGeneralSettingsInstance().isConfirmExtractFiles(); - } - - @Override - protected void setToBeShown(boolean value, boolean onOk) { - getGeneralSettingsInstance().setConfirmExtractFiles(value); - } - - @Override - protected boolean shouldSaveOptionsOnCancel() { - return true; - } - - @Override - @NotNull - protected Action[] createActions() { - setOKButtonText(CommonBundle.getYesButtonText()); - return new Action[]{getOKAction(), getCancelAction()}; - } - - @Override - protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new BorderLayout()); - String message = "The files are inside an archive, do you want them to be extracted?"; - JLabel label = new JLabel(message); - - label.setIconTextGap(10); - label.setIcon(Messages.getQuestionIcon()); - - panel.add(label, BorderLayout.CENTER); - panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); - - return panel; - } - } - @NotNull public static String getDefaultAlternativeBrowserPath() { if (SystemInfo.isWindows) { diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java new file mode 100644 index 000000000000..dc3385f11c88 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java @@ -0,0 +1,47 @@ +/* + * 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.intellij.ide.browsers; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.net.URI; + +public abstract class BrowserLauncher { + public static BrowserLauncher getInstance() { + return ServiceManager.getService(BrowserLauncher.class); + } + + public abstract void browse(@NotNull URI uri); + + public abstract void openOrBrowse(@NotNull String url, boolean browse); + + public abstract void browse(@NotNull String url, @Nullable WebBrowser browser); + + public abstract void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project); + + public abstract boolean browse(@Nullable String url, + @NotNull WebBrowser browser, + @Nullable Project project, + @NotNull String... additionalParameters); + + public abstract boolean browse(@Nullable String url, + @Nullable String browserPath, + @Nullable WebBrowser browser, + @Nullable Project project); +} \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java b/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java index f4a573d57d01..1119f722e1c8 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java @@ -15,30 +15,29 @@ */ package com.intellij.ide.browsers; -import com.intellij.ide.BrowserUtil; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +@SuppressWarnings("deprecation") public abstract class UrlOpener { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.jetbrains.urlOpener"); + @Deprecated + /** + * @deprecated Use {@link com.intellij.ide.browsers.BrowserLauncher#browse(String, WebBrowser)} + */ public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser) { - launchBrowser(url, browser, null); + BrowserLauncher.getInstance().browse(url, browser); } + @Deprecated + /** + * @deprecated Use {@link com.intellij.ide.browsers.BrowserLauncher#browse(String, WebBrowser, com.intellij.openapi.project.Project)} + */ public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) { - if (browser == null) { - BrowserUtil.launchBrowser(url); - } - else { - for (UrlOpener urlOpener : EP_NAME.getExtensions()) { - if (urlOpener.openUrl(browser, url, project)) { - return; - } - } - } + BrowserLauncher.getInstance().browse(url, browser, project); } public abstract boolean openUrl(@NotNull WebBrowser browser, @NotNull String url, @Nullable Project project); diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 7e82df4f4f1b..9263d4f083ea 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1,7 +1,8 @@ error.malformed.url=Malformed url: {0} -error.cannot.start.browser=Cannot start browser: {0} error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers title.browser.not.found=Browser Not Found +browser.error=Browser Error +error.0.browser.path.not.specified={0} browser path is not specified. chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File label.text.path.to.profiles.ini=Path to \"profiles.ini\": diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties index ee7468c273d7..e761b3c9a92b 100644 --- a/platform/platform-resources-en/src/messages/XmlBundle.properties +++ b/platform/platform-resources-en/src/messages/XmlBundle.properties @@ -145,14 +145,6 @@ xml.folding.settings=Code Folding Settings cannot.resolve.anchor=Cannot resolve anchor #{0} cannot.resolve.anchor.in.file=Cannot resolve anchor #{0} in file {1} - -# web browsers -browsers.configuration.name=Web Browsers -browser.description=Open file in {0} - -browser.error=Browser Error -error.0.browser.path.not.specified={0} browser path is not specified. - web.editor.configuration.title=Web browser.select.in.default.name=Web Browser diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 9ee00e1f73e2..d8889636d101 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -361,6 +361,8 @@ + + diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java new file mode 100644 index 000000000000..bcc86da4070d --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java @@ -0,0 +1,496 @@ +/* + * 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.intellij.ide.browsers; + +import com.intellij.CommonBundle; +import com.intellij.Patches; +import com.intellij.concurrency.JobScheduler; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.util.ExecUtil; +import com.intellij.ide.BrowserUtil; +import com.intellij.ide.GeneralSettings; +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.*; +import com.intellij.ui.AppUIUtil; +import com.intellij.ui.GuiUtils; +import com.intellij.util.ArrayUtil; +import com.intellij.util.io.ZipUtil; +import com.intellij.util.ui.OptionsDialog; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.*; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +final class BrowserLauncherImpl extends BrowserLauncher { + private static final Logger LOG = Logger.getInstance(BrowserLauncherImpl.class); + + private static boolean isDesktopActionSupported(Desktop.Action action) { + return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 && + Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action); + } + + public static boolean canStartDefaultBrowser() { + return isDesktopActionSupported(Desktop.Action.BROWSE) || + SystemInfo.isMac || SystemInfo.isWindows || + SystemInfo.isUnix && SystemInfo.hasXdgOpen(); + } + + private static GeneralSettings getGeneralSettingsInstance() { + if (ApplicationManager.getApplication() != null) { + GeneralSettings settings = GeneralSettings.getInstance(); + if (settings != null) { + return settings; + } + } + + return new GeneralSettings(); + } + + @Nullable + private static List getDefaultBrowserCommand() { + if (SystemInfo.isWindows) { + return Arrays.asList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote("")); + } + else if (SystemInfo.isMac) { + return Collections.singletonList(ExecUtil.getOpenCommandPath()); + } + else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { + return Collections.singletonList("xdg-open"); + } + else { + return null; + } + } + + @Override + public void browse(@NotNull URI uri) { + LOG.debug("Launch browser: [" + uri + "]"); + + GeneralSettings settings = getGeneralSettingsInstance(); + if (settings.isUseDefaultBrowser()) { + if (isDesktopActionSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(uri); + LOG.debug("Browser launched using JDK 1.6 API"); + return; + } + catch (Exception e) { + LOG.warn("Error while using Desktop API, fallback to CLI", e); + } + } + + List command = getDefaultBrowserCommand(); + if (command != null) { + doLaunch(uri.toString(), command, null, null, ArrayUtil.EMPTY_STRING_ARRAY); + return; + } + } + + browse(uri.toString(), settings.getBrowserPath(), null, null); + } + + @Override + public void openOrBrowse(@NotNull String url, boolean browse) { + url = url.trim(); + + if (url.startsWith("jar:")) { + String files = extractFiles(url); + if (files == null) { + return; + } + url = files; + } + + URI uri; + if (BrowserUtil.isAbsoluteURL(url)) { + uri = VfsUtil.toUri(url); + } + else { + File file = new File(url); + if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) { + try { + Desktop.getDesktop().open(file); + return; + } + catch (IOException e) { + LOG.debug(e); + } + } + + BrowserUtil.browse(file); + return; + } + + if (uri == null) { + showError(IdeBundle.message("error.malformed.url", url), null, null, null); + } + else { + browse(uri); + } + } + + @Nullable + private static String extractFiles(String url) { + try { + int sharpPos = url.indexOf('#'); + String anchor = ""; + if (sharpPos != -1) { + anchor = url.substring(sharpPos); + url = url.substring(0, sharpPos); + } + + VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); + if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null; + + JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem(); + VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file); + if (jarVirtualFile == null) return null; + + String targetFilePath = file.getPath(); + String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR); + LOG.assertTrue(targetFileRelativePath != null); + + String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode()); + final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash); + + final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified()); + final File timestampFile = new File(outputDir, ".idea.timestamp"); + + String previousTimestamp = null; + if (timestampFile.exists()) { + previousTimestamp = FileUtil.loadFile(timestampFile); + } + + if (!currentTimestamp.equals(previousTimestamp)) { + final Ref extract = new Ref(); + Runnable r = new Runnable() { + @Override + public void run() { + final ConfirmExtractDialog dialog = new ConfirmExtractDialog(); + if (dialog.isToBeShown()) { + dialog.show(); + extract.set(dialog.isOK()); + } + else { + dialog.close(DialogWrapper.OK_EXIT_CODE); + extract.set(true); + } + } + }; + + try { + GuiUtils.runOrInvokeAndWait(r); + } + catch (InvocationTargetException ignored) { + extract.set(false); + } + catch (InterruptedException ignored) { + extract.set(false); + } + + if (!extract.get()) { + return null; + } + + @SuppressWarnings("ConstantConditions") + final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile(); + if (zipFile == null) { + return null; + } + ZipEntry entry = zipFile.getEntry(targetFileRelativePath); + if (entry == null) { + return null; + } + InputStream is = zipFile.getInputStream(entry); + try { + ZipUtil.extractEntry(entry, is, outputDir); + } + finally { + is.close(); + } + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + new Task.Backgroundable(null, "Extracting files...", true) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + final int size = zipFile.size(); + final int[] counter = new int[]{0}; + + class MyFilter implements FilenameFilter { + private final Set myImportantDirs = new HashSet( + Arrays.asList(outputDir, new File(outputDir, "resources"))); + private final boolean myImportantOnly; + + private MyFilter(boolean importantOnly) { + myImportantOnly = importantOnly; + } + + @Override + public boolean accept(@NotNull File dir, @NotNull String name) { + indicator.checkCanceled(); + boolean result = myImportantOnly == myImportantDirs.contains(dir); + if (result) { + indicator.setFraction(((double)counter[0]) / size); + counter[0]++; + } + return result; + } + } + + try { + ZipUtil.extract(zipFile, outputDir, new MyFilter(true)); + ZipUtil.extract(zipFile, outputDir, new MyFilter(false)); + FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes()); + } + catch (IOException ignore) { + } + } + }.queue(); + } + }); + } + + return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor; + } + catch (IOException e) { + LOG.warn(e); + Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error"); + return null; + } + } + + private static File getExtractedFilesDir() { + return new File(PathManager.getSystemPath(), "ExtractedFiles"); + } + + public static void clearExtractedFiles() { + FileUtil.delete(getExtractedFilesDir()); + } + + private static class ConfirmExtractDialog extends OptionsDialog { + private ConfirmExtractDialog() { + super(null); + setTitle("Confirmation"); + init(); + } + + @Override + protected boolean isToBeShown() { + return getGeneralSettingsInstance().isConfirmExtractFiles(); + } + + @Override + protected void setToBeShown(boolean value, boolean onOk) { + getGeneralSettingsInstance().setConfirmExtractFiles(value); + } + + @Override + protected boolean shouldSaveOptionsOnCancel() { + return true; + } + + @Override + @NotNull + protected Action[] createActions() { + setOKButtonText(CommonBundle.getYesButtonText()); + return new Action[]{getOKAction(), getCancelAction()}; + } + + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(new BorderLayout()); + String message = "The files are inside an archive, do you want them to be extracted?"; + JLabel label = new JLabel(message); + + label.setIconTextGap(10); + label.setIcon(Messages.getQuestionIcon()); + + panel.add(label, BorderLayout.CENTER); + panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); + + return panel; + } + } + + @Override + public void browse(@NotNull String url, @Nullable WebBrowser browser) { + browse(url, browser, null); + } + + @Override + public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) { + if (browser == null) { + BrowserUtil.launchBrowser(url); + } + else { + for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) { + if (urlOpener.openUrl(browser, url, project)) { + return; + } + } + } + } + + @Override + public boolean browse(@Nullable String url, + @NotNull WebBrowser browser, + @Nullable Project project, + @NotNull String... additionalParameters) { + return doLaunch(url, browser.getPath(), browser, project, additionalParameters); + } + + @Override + public boolean browse(@Nullable String url, + @Nullable String browserPath, + @Nullable WebBrowser browser, + @Nullable Project project) { + return doLaunch(url, browserPath, browser, project, ArrayUtil.EMPTY_STRING_ARRAY); + } + + private static boolean doLaunch(@Nullable String url, + @Nullable String browserPath, + @Nullable WebBrowser browser, + @Nullable Project project, + @NotNull String[] additionalParameters) { + if (StringUtil.isEmptyOrSpaces(browserPath)) { + showError(browser == null ? IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath()) : browser + .getBrowserNotFoundMessage(), browser, project, IdeBundle.message("title.browser.not.found")); + return false; + } + + return doLaunch(url, BrowserUtil.getOpenBrowserCommand(browserPath, false), browser, project, additionalParameters); + } + + private static boolean doLaunch(@Nullable String url, + @NotNull List command, + @Nullable final WebBrowser browser, + @Nullable final Project project, + String[] additionalParameters) { + GeneralCommandLine commandLine = new GeneralCommandLine(command); + if (url != null) { + commandLine.addParameter(url); + } + + addArgs(commandLine, browser == null ? null : browser.getSpecificSettings(), additionalParameters); + + try { + final Process process = commandLine.createProcess(); + if (isOpenCommandUsed(commandLine)) { + final Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + try { + if (process.waitFor() == 1) { + showError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project, null); + } + } + catch (InterruptedException ignored) { + } + } + }); + // 30 seconds is enough to start + JobScheduler.getScheduler().schedule(new Runnable() { + @Override + public void run() { + future.cancel(true); + } + }, 30, TimeUnit.MILLISECONDS); + } + return true; + } + catch (ExecutionException e) { + showError(e.getMessage(), browser, project, null); + return false; + } + } + + public static void showError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, @Nullable final String title) { + if (ApplicationManager.getApplication() == null) { + LOG.warn(error); + // Not started yet. Not able to show message up. (Could happen in License panel under Linux). + return; + } + + AppUIUtil.invokeOnEdt(new Runnable() { + @Override + public void run() { + if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), + title == null ? IdeBundle.message("browser.error") : title, Messages.OK_BUTTON, + IdeBundle.message("button.fix"), null) == Messages.NO) { + final BrowserSettings browserSettings = new BrowserSettings(); + ShowSettingsUtil.getInstance().editConfigurable(project, browserSettings, browser == null ? null : new Runnable() { + @Override + public void run() { + browserSettings.selectBrowser(browser); + } + }); + } + } + }); + } + + private static void addArgs(@NotNull GeneralCommandLine command, @Nullable BrowserSpecificSettings settings, @NotNull String[] additional) { + List specific = settings == null ? Collections.emptyList() : settings.getAdditionalParameters(); + if (specific.size() + additional.length > 0) { + if (isOpenCommandUsed(command)) { + if (BrowserUtil.isOpenCommandSupportArgs()) { + command.addParameter("--args"); + } + else { + LOG.warn("'open' command doesn't allow to pass command line arguments so they will be ignored: " + + StringUtil.join(specific, ", ") + " " + Arrays.toString(additional)); + return; + } + } + + command.addParameters(specific); + command.addParameters(additional); + } + } + + private static boolean isOpenCommandUsed(@NotNull GeneralCommandLine command) { + return SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.getExePath()); + } +} \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java index 8b5439aed03c..f4e2245b0f54 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java @@ -15,7 +15,6 @@ */ package com.intellij.ide.browsers; -import com.intellij.ide.BrowserUtil; import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; import com.intellij.openapi.fileChooser.FileChooserDescriptor; @@ -152,7 +151,7 @@ final class BrowserSettingsPanel { //noinspection unchecked defaultBrowserComboBox.setModel(new EnumComboBoxModel(DefaultBrowser.class)); - if (BrowserUtil.canStartDefaultBrowser()) { + if (BrowserLauncherImpl.canStartDefaultBrowser()) { defaultBrowserComboBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { @@ -202,7 +201,7 @@ final class BrowserSettingsPanel { clearExtractedFiles.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - BrowserUtil.clearExtractedFiles(); + BrowserLauncherImpl.clearExtractedFiles(); } }); } diff --git a/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java b/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java index ff5182abd92f..00e1ceb73440 100644 --- a/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java +++ b/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java @@ -48,7 +48,7 @@ public interface JavaScriptDebuggerStarter { @Nullable WebBrowser browser, boolean startDebugger) { if (!startDebugger || !start(runConfiguration, url)) { - UrlOpener.launchBrowser(url, browser, runConfiguration.getProject()); + BrowserLauncher.getInstance().browse(url, browser, runConfiguration.getProject()); } } } diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java index 70cacb054de6..7ba40265ecf7 100644 --- a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java +++ b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java @@ -62,7 +62,7 @@ public final class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo { group.add(new AnAction("Open in " + browser.getName(), "Open URL in " + browser.getName(), browser.getIcon()) { @Override public void actionPerformed(AnActionEvent e) { - UrlOpener.launchBrowser(url, browser, e.getProject()); + BrowserLauncher.getInstance().browse(url, browser, e.getProject()); } }); } @@ -79,6 +79,6 @@ public final class OpenUrlHyperlinkInfo implements HyperlinkWithPopupMenuInfo { @Override public void navigate(Project project) { - UrlOpener.launchBrowser(url, browser, project); + BrowserLauncher.getInstance().browse(url, browser, project); } } diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java index 56b4d5bf8904..fc02f965b6c8 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java @@ -15,8 +15,8 @@ */ package com.intellij.ide.browsers; +import com.intellij.ide.IdeBundle; import com.intellij.openapi.util.NullableComputable; -import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -55,7 +55,7 @@ public abstract class WebBrowserBase extends WebBrowser { @Override @NotNull public String getBrowserNotFoundMessage() { - return XmlBundle.message("error.0.browser.path.not.specified", getName()); + return IdeBundle.message("error.0.browser.path.not.specified", getName()); } @Override diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java index 8ab0c13b5d2d..ac6b476cb97e 100644 --- a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java +++ b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java @@ -16,6 +16,7 @@ package com.intellij.ide.browsers.actions; import com.intellij.icons.AllIcons; +import com.intellij.ide.IdeBundle; import com.intellij.ide.browsers.*; import com.intellij.ide.browsers.impl.WebBrowserServiceImpl; import com.intellij.openapi.actionSystem.*; @@ -42,7 +43,6 @@ import com.intellij.util.Consumer; import com.intellij.util.ObjectUtils; import com.intellij.util.Url; import com.intellij.util.containers.ContainerUtil; -import com.intellij.xml.XmlBundle; import com.intellij.xml.util.HtmlUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -207,13 +207,13 @@ public abstract class BaseOpenInBrowserAction extends DumbAwareAction { @Override public void consume(Url url) { ApplicationManager.getApplication().saveAll(); - UrlOpener.launchBrowser(url.toExternalForm(), browser, request.getProject()); + BrowserLauncher.getInstance().browse(url.toExternalForm(), browser, request.getProject()); } }); } } catch (WebBrowserUrlProvider.BrowserException e1) { - Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error")); + Messages.showErrorDialog(e1.getMessage(), IdeBundle.message("browser.error")); } catch (Exception e1) { LOG.error(e1); diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java index bc760156e229..0788a6b335c2 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java @@ -15,130 +15,16 @@ */ package com.intellij.ide.browsers.impl; -import com.intellij.concurrency.JobScheduler; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.util.ExecUtil; -import com.intellij.ide.BrowserUtil; -import com.intellij.ide.IdeBundle; -import com.intellij.ide.browsers.*; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.ide.browsers.BrowserLauncher; +import com.intellij.ide.browsers.UrlOpener; +import com.intellij.ide.browsers.WebBrowser; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.AppUIUtil; -import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class DefaultUrlOpener extends UrlOpener { - private static final Logger LOG = Logger.getInstance(DefaultUrlOpener.class); - +final class DefaultUrlOpener extends UrlOpener { @Override public boolean openUrl(@NotNull WebBrowser browser, @NotNull String url, @Nullable Project project) { - return launchBrowser(browser, url, false, project); + return BrowserLauncher.getInstance().browse(url, browser.getPath(), browser, project); } - - public static boolean launchBrowser(@NotNull final WebBrowser browser, - @Nullable String url, - boolean newWindowIfPossible, - @Nullable final Project project, - @NotNull String... additionalParameters) { - String browserPath = browser.getPath(); - if (StringUtil.isEmpty(browserPath)) { - showError(browser.getBrowserNotFoundMessage(), browser, project, IdeBundle.message("title.browser.not.found")); - return false; - } - else { - return doLaunchBrowser(browser, browserPath, url, newWindowIfPossible, project, additionalParameters); - } - } - - private static boolean doLaunchBrowser(@NotNull final WebBrowser browser, String browserPath, String url, boolean newWindowIfPossible, @Nullable final Project project, String[] additionalParameters) { - GeneralCommandLine commandLine = new GeneralCommandLine(BrowserUtil.getOpenBrowserCommand(browserPath, newWindowIfPossible)); - if (url != null) { - commandLine.addParameter(url); - } - - addArgs(commandLine, browser.getSpecificSettings(), additionalParameters); - - try { - final Process process = commandLine.createProcess(); - if (isOpenCommandUsed(commandLine)) { - final Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - try { - if (process.waitFor() == 1) { - showError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project, null); - } - } - catch (InterruptedException ignored) { - } - } - }); - // 30 seconds is enough to start - JobScheduler.getScheduler().schedule(new Runnable() { - @Override - public void run() { - future.cancel(true); - } - }, 30, TimeUnit.MILLISECONDS); - } - return true; - } - catch (ExecutionException e) { - showError(e.getMessage(), browser, project, null); - return false; - } - } - - private static void showError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, @Nullable final String title) { - AppUIUtil.invokeOnEdt(new Runnable() { - @Override - public void run() { - if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"), title == null ? XmlBundle.message("browser.error") : title, Messages.OK_BUTTON, IdeBundle.message("button.fix"), null) == Messages.NO) { - final BrowserSettings browserSettings = new BrowserSettings(); - ShowSettingsUtil.getInstance().editConfigurable(project, browserSettings, browser == null ? null : new Runnable() { - @Override - public void run() { - browserSettings.selectBrowser(browser); - } - }); - } - } - }); - } - - private static void addArgs(@NotNull GeneralCommandLine command, @Nullable BrowserSpecificSettings settings, @NotNull String[] additional) { - List specific = settings == null ? Collections.emptyList() : settings.getAdditionalParameters(); - if (specific.size() + additional.length > 0) { - if (isOpenCommandUsed(command)) { - if (BrowserUtil.isOpenCommandSupportArgs()) { - command.addParameter("--args"); - } - else { - LOG.warn("'open' command doesn't allow to pass command line arguments so they will be ignored: " + - StringUtil.join(specific, ", ") + " " + Arrays.toString(additional)); - return; - } - } - - command.addParameters(specific); - command.addParameters(additional); - } - } - - private static boolean isOpenCommandUsed(@NotNull GeneralCommandLine command) { - return SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.getExePath()); - } -} +} \ No newline at end of file From 708466048e13f63c86b85c7f484152c8732d89f1 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 16:44:29 +0100 Subject: [PATCH 15/53] It is safe now to deprecate launchBrowser --- .../impl/src/com/intellij/debugger/ui/GetJPDADialog.java | 2 +- .../openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java | 4 ++-- .../intellij/codeEditor/printing/ExportToHTMLManager.java | 6 ++---- .../codeInsight/documentation/DocumentationManager.java | 5 +++-- .../src/com/intellij/ide/actions/ExternalJavaDocAction.java | 4 ++-- .../src/com/intellij/openapi/paths/WebReference.java | 4 ++-- .../com/intellij/history/core/ChangeListStorageImpl.java | 2 +- .../intellij/execution/filters/BrowserHyperlinkInfo.java | 2 +- platform/platform-api/src/com/intellij/ide/BrowserUtil.java | 4 ++++ .../platform-api/src/com/intellij/ui/HyperlinkLabel.java | 2 +- .../src/com/intellij/ui/SimpleColoredComponent.java | 2 +- .../src/com/intellij/diagnostic/JetBrainsAccountDialog.java | 2 +- .../src/com/intellij/help/impl/HelpManagerImpl.java | 2 +- .../src/com/intellij/help/impl/IdeaHelpContentViewUI.java | 2 +- .../src/com/intellij/ide/actions/AboutDialog.java | 2 +- .../src/com/intellij/ide/actions/OnlineDocAction.java | 2 +- .../src/com/intellij/ide/actions/RefCardAction.java | 2 +- .../src/com/intellij/ide/actions/SearchWebAction.java | 2 +- .../src/com/intellij/ide/actions/SendFeedbackAction.java | 2 +- .../com/intellij/ide/actions/TechnicalSupportAction.java | 2 +- .../src/com/intellij/ide/actions/WhatsNewAction.java | 2 +- .../openapi/updateSettings/impl/NewChannelDialog.java | 4 ++-- .../openapi/updateSettings/impl/UpdateInfoDialog.java | 4 ++-- .../openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java | 2 +- .../src/com/intellij/psi/impl/UrlPsiReference.java | 2 +- .../changes/issueLinks/AbstractBaseTagMouseListener.java | 2 +- plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java | 2 +- plugins/git4idea/src/git4idea/push/GitPushResult.java | 2 +- .../jetbrains/plugins/github/GithubCreateGistAction.java | 2 +- .../jetbrains/plugins/github/GithubOpenInBrowserAction.java | 2 +- .../plugins/github/GithubShowCommitInBrowserAction.java | 2 +- .../com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java | 2 +- .../com/intellij/tasks/actions/OpenTaskInBrowserAction.java | 3 +-- .../intellij/lang/xpath/xslt/run/XsltCommandLineState.java | 2 +- .../src/com/intellij/ide/browsers/BrowserLauncherImpl.java | 2 +- 35 files changed, 46 insertions(+), 44 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java b/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java index 468dd1c246e4..00701785c9ec 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java @@ -60,7 +60,7 @@ public class GetJPDADialog extends DialogWrapper { new DoubleClickListener() { @Override protected boolean onDoubleClick(MouseEvent e) { - BrowserUtil.launchBrowser(JPDA_URL); + BrowserUtil.browse(JPDA_URL); return true; } }.installOn(label2); diff --git a/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java b/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java index 390238950c4c..5e37d69ebcc4 100644 --- a/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java +++ b/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java @@ -35,10 +35,10 @@ public class DevelopPluginsAction extends AnAction implements DumbAware { public void actionPerformed(final AnActionEvent e) { try { if (new File(PLUGIN_URL).isFile()) { - BrowserUtil.launchBrowser(PLUGIN_URL); + BrowserUtil.browse(PLUGIN_URL); } else { - BrowserUtil.launchBrowser(PLUGIN_WEBSITE); + BrowserUtil.browse(PLUGIN_WEBSITE); } } catch(IllegalStateException ex) { diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java index d293a79471c8..bc8830c1c193 100644 --- a/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java +++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java @@ -20,8 +20,6 @@ import com.intellij.CommonBundle; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; @@ -117,7 +115,7 @@ class ExportToHTMLManager { } textPainter.paint(null, psiFile.getFileType()); if (exportToHTMLSettings.OPEN_IN_BROWSER) { - BrowserUtil.launchBrowser(textPainter.getHTMLFileName()); + BrowserUtil.browse(textPainter.getHTMLFileName()); } } else { @@ -269,7 +267,7 @@ class ExportToHTMLManager { dirToShow += File.separatorChar; } dirToShow += PsiDirectoryFactory.getInstance(myProject).getQualifiedName(myPsiDirectory, false).replace('.', File.separatorChar); - BrowserUtil.launchBrowser(dirToShow); + BrowserUtil.browse(dirToShow); } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index a0abbbc9175b..273777e42ace 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -970,10 +970,11 @@ public class DocumentationManager extends DockablePopupManager("Choose external documentation root", ArrayUtil.toStringArray(set)) { @Override public PopupStep onChosen(final String selectedValue, final boolean finalChoice) { - BrowserUtil.launchBrowser(selectedValue); + BrowserUtil.browse(selectedValue); return FINAL_CHOICE; } }).showInBestPositionFor(DataManager.getInstance().getDataContext()); } else if (set.size() == 1) { - BrowserUtil.launchBrowser(urls.get(0)); + BrowserUtil.browse(urls.get(0)); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java b/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java index 2a2a6c714406..74e80f046aa4 100644 --- a/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java +++ b/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java @@ -49,8 +49,8 @@ public class WebReference extends PsiReferenceBase { @Override public void navigate(boolean requestFocus) { - BrowserUtil.launchBrowser(getValue()); - } + BrowserUtil.browse(getValue()); + } @Override public String getPresentableText() { diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java index c833f810eb9f..836a6c95d4eb 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java @@ -138,7 +138,7 @@ public class ChangeListStorageImpl implements ChangeListStorage { @NotNull HyperlinkEvent event) { if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if ("url".equals(event.getDescription())) { - BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270"); + BrowserUtil.browse("http://youtrack.jetbrains.net/issue/IDEA-71270"); } else { File file = new File(logFile); diff --git a/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java b/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java index 8c279902b81f..cf1129ae9219 100644 --- a/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java +++ b/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java @@ -33,6 +33,6 @@ public class BrowserHyperlinkInfo implements HyperlinkInfo { } public static void openUrl(String url) { - BrowserUtil.launchBrowser(url); + BrowserUtil.browse(url); } } diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index bbd30f098a74..d628307472d0 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -75,6 +75,10 @@ public class BrowserUtil { browse(url.toExternalForm()); } + @Deprecated + /** + * @deprecated Use {@link #browse(String)} + */ public static void launchBrowser(@NotNull @NonNls String url) { browse(url); } diff --git a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java index 564b097c6bc0..27324c9d9781 100644 --- a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java @@ -147,7 +147,7 @@ public class HyperlinkLabel extends HighlightableComponent { myHyperlinkListener = new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent e) { - BrowserUtil.launchBrowser(url); + BrowserUtil.browse(url); } }; addHyperlinkListener(myHyperlinkListener); diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index f9c5738100b7..9d8e1de807ef 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -933,7 +933,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co @Override public void run() { - BrowserUtil.launchBrowser(myUrl); + BrowserUtil.browse(myUrl); } } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java index a1dc63622130..092c346d40b7 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java @@ -94,7 +94,7 @@ public class JetBrainsAccountDialog extends DialogWrapper { new ClickListener() { @Override public boolean onClick(@NotNull MouseEvent e, int clickCount) { - BrowserUtil.launchBrowser("http://account.jetbrains.com"); + BrowserUtil.browse("http://account.jetbrains.com"); return true; } }.installOn(myCreateAccountLabel); diff --git a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java index dbfd012f4ff2..ac197b192284 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java @@ -64,7 +64,7 @@ public class HelpManagerImpl extends HelpManager { } if (myHelpSet == null) { - BrowserUtil.launchBrowser(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id); + BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id); return; } diff --git a/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java b/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java index 53ef59036659..976da513e7e5 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java +++ b/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java @@ -45,7 +45,7 @@ class IdeaHelpContentViewUI extends BasicContentViewerUI{ protected void linkActivated(URL u){ String url=u.toExternalForm(); if(url.startsWith("http") || url.startsWith("ftp")){ - BrowserUtil.launchBrowser(url); + BrowserUtil.browse(url); } else{ super.linkActivated(u); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java index 24f21faa881d..544c4899ca41 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java @@ -219,7 +219,7 @@ public class AboutDialog extends JDialog { public void mousePressed(MouseEvent event) { if (myActiveLink != null) { event.consume(); - BrowserUtil.launchBrowser(myActiveLink.url); + BrowserUtil.browse(myActiveLink.url); } } }); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java b/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java index ea1d3790e746..08aa03744d4c 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java @@ -26,7 +26,7 @@ import com.intellij.openapi.project.DumbAware; */ public class OnlineDocAction extends AnAction implements DumbAware { public void actionPerformed(AnActionEvent e) { - BrowserUtil.launchBrowser(ApplicationInfoImpl.getShadowInstance().getDocumentationUrl()); + BrowserUtil.browse(ApplicationInfoImpl.getShadowInstance().getDocumentationUrl()); } public void update(final AnActionEvent e) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java index 09792104f3f7..df50bb85e8fa 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java @@ -44,7 +44,7 @@ public class RefCardAction extends AnAction implements DumbAware { final ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx(); String webUrl = SystemInfo.isMac ? appInfo.getMacKeymapUrl() : appInfo.getWinKeymapUrl(); if (webUrl != null) { - BrowserUtil.launchBrowser(webUrl); + BrowserUtil.browse(webUrl); } } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java index 88868fcf53d5..af387e88b8a7 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java @@ -35,7 +35,7 @@ public class SearchWebAction extends AnAction implements DumbAware { provider.performCopy(dataContext); String string = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor); if (StringUtil.isNotEmpty(string)) { - BrowserUtil.launchBrowser("http://www.google.com/search?q="+ URLEncoder.encode(string)); + BrowserUtil.browse("http://www.google.com/search?q=" + URLEncoder.encode(string)); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java index 4f7e826db29f..c70009157d61 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java @@ -46,7 +46,7 @@ public class SendFeedbackAction extends AnAction implements DumbAware { .replace("$TIMEZONE", System.getProperty("user.timezone")) .replace("$EVAL", isEvaluationLicense() ? "true" : "false") .replace("$DESCR", getDescription()); - BrowserUtil.launchBrowser(urlTemplate); + BrowserUtil.browse(urlTemplate); } private static String getDescription() { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java b/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java index 99d3089b8e74..78fd65ce9d2d 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java @@ -30,7 +30,7 @@ import com.intellij.openapi.project.DumbAware; public class TechnicalSupportAction extends AnAction implements DumbAware { public void actionPerformed(AnActionEvent e) { - BrowserUtil.launchBrowser(ApplicationInfoImpl.getShadowInstance().getSupportUrl()); + BrowserUtil.browse(ApplicationInfoImpl.getShadowInstance().getSupportUrl()); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java index 9065452abedf..1ca06493badd 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java @@ -28,7 +28,7 @@ import com.intellij.openapi.project.DumbAware; */ public class WhatsNewAction extends AnAction implements DumbAware { public void actionPerformed(AnActionEvent e) { - BrowserUtil.launchBrowser(ApplicationInfoEx.getInstanceEx().getWhatsNewUrl()); + BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWhatsNewUrl()); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java index 7e3a63c84636..65cdf2826723 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java @@ -77,7 +77,7 @@ class NewChannelDialog extends AbstractUpdateDialog { public void actionPerformed(ActionEvent e) { LicensingFacade facade = LicensingFacade.getInstance(); assert facade != null; - BrowserUtil.launchBrowser(facade.getUpgradeUrl()); + BrowserUtil.browse(facade.getUpgradeUrl()); doCancelAction(); } }); @@ -108,7 +108,7 @@ class NewChannelDialog extends AbstractUpdateDialog { @Override protected void doOKAction() { - BrowserUtil.launchBrowser(myChannel.getHomePageUrl()); + BrowserUtil.browse(myChannel.getHomePageUrl()); super.doOKAction(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java index 66ed35aa50eb..17d4fbe890eb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java @@ -123,7 +123,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog { } private void openDownloadPage() { - BrowserUtil.launchBrowser(myUpdatedChannel.getHomePageUrl()); + BrowserUtil.browse(myUpdatedChannel.getHomePageUrl()); } private static class ButtonAction extends AbstractAction { @@ -136,7 +136,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog { @Override public void actionPerformed(ActionEvent e) { - BrowserUtil.launchBrowser(myUrl); + BrowserUtil.browse(myUrl); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java index 68ad6d127978..184f3444175e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java @@ -42,6 +42,6 @@ public class JetBrainsTvAction extends AnAction implements DumbAware { @Override public void actionPerformed(AnActionEvent e) { - BrowserUtil.launchBrowser(myUrl); + BrowserUtil.browse(myUrl); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java index 9a52a5691815..2367e4dbe599 100644 --- a/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java +++ b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java @@ -38,7 +38,7 @@ public class UrlPsiReference extends PsiReferenceBase { @Override public void navigate(boolean requestFocus) { - BrowserUtil.launchBrowser(getValue()); + BrowserUtil.browse(getValue()); } }; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java index 675a1f40482b..f86be35a040a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java @@ -31,7 +31,7 @@ public abstract class AbstractBaseTagMouseListener extends LinkMouseListenerBase } if (tag != null && !Object.class.getName().equals(tag.getClass().getName())) { - BrowserUtil.launchBrowser(tag.toString()); + BrowserUtil.browse(tag.toString()); return true; } } diff --git a/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java b/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java index aeb7f949e3a3..229d8b083f50 100644 --- a/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java +++ b/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java @@ -79,7 +79,7 @@ public class GitCrlfDialog extends DialogWrapper { JLabel readMore = new LinkLabel("Read more", null, new LinkListener() { @Override public void linkSelected(LinkLabel aSource, Object aLinkData) { - BrowserUtil.launchBrowser("https://help.github.com/articles/dealing-with-line-endings"); + BrowserUtil.browse("https://help.github.com/articles/dealing-with-line-endings"); } }); diff --git a/plugins/git4idea/src/git4idea/push/GitPushResult.java b/plugins/git4idea/src/git4idea/push/GitPushResult.java index c82b5ea816cb..995a3a4b7058 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushResult.java +++ b/plugins/git4idea/src/git4idea/push/GitPushResult.java @@ -378,7 +378,7 @@ class GitPushResult { tree.setAfter(LocalHistory.getInstance().putSystemLabel(myProject, "After push")); } else { - BrowserUtil.launchBrowser(event.getDescription()); + BrowserUtil.browse(event.getDescription()); } } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java index 995c22400377..fd378e7b5689 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java @@ -140,7 +140,7 @@ public class GithubCreateGistAction extends DumbAwareAction { return; } if (dialog.isOpenInBrowser()) { - BrowserUtil.launchBrowser(url.get()); + BrowserUtil.browse(url.get()); } else { GithubNotifications.showInfoURL(project, "Gist Created Successfully", "Your gist url", url.get()); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index 3763e5f41038..f587d44c8cb6 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -99,7 +99,7 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { String urlToOpen = getGithubUrl(project, virtualFile, editor); if (urlToOpen != null) { - BrowserUtil.launchBrowser(urlToOpen); + BrowserUtil.browse(urlToOpen); } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java index 70bc45037e47..36e5bc4b99ec 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java @@ -51,7 +51,7 @@ abstract class GithubShowCommitInBrowserAction extends DumbAwareAction { String githubUrl = GithubUrlUtil.getGithubHost() + '/' + userAndRepository.getUser() + '/' + userAndRepository.getRepository() + "/commit/" + revisionHash; - BrowserUtil.launchBrowser(githubUrl); + BrowserUtil.browse(githubUrl); } } diff --git a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java index 36b5c86b499c..9edece0c0527 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java @@ -42,7 +42,7 @@ public class AppEngineSdkUtil { private static final FacetConfigurationQuickFix DOWNLOAD_SDK_QUICK_FIX = new FacetConfigurationQuickFix("Download...") { @Override public void run(JComponent place) { - BrowserUtil.launchBrowser(APP_ENGINE_DOWNLOAD_URL); + BrowserUtil.browse(APP_ENGINE_DOWNLOAD_URL); } }; diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java index 9ec20128e9f6..670f651cc990 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java @@ -19,7 +19,6 @@ package com.intellij.tasks.actions; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.project.Project; import com.intellij.tasks.TaskManager; @@ -33,7 +32,7 @@ public class OpenTaskInBrowserAction extends BaseTaskAction { public void actionPerformed(AnActionEvent e) { String url = getIssueUrl(e); if (url != null) { - BrowserUtil.launchBrowser(url); + BrowserUtil.browse(url); } } diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java index e2886b345356..6406db9f23b8 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java @@ -213,7 +213,7 @@ public class XsltCommandLineState extends CommandLineState { public void run() { if (event.getExitCode() == 0) { if (myXsltRunConfiguration.myOpenInBrowser) { - BrowserUtil.launchBrowser(myXsltRunConfiguration.myOutputFile); + BrowserUtil.browse(myXsltRunConfiguration.myOutputFile); } if (myXsltRunConfiguration.myOpenOutputFile) { final String url = VfsUtilCore.pathToUrl(myXsltRunConfiguration.myOutputFile); diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java index bcc86da4070d..46f45bbb375e 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java @@ -362,7 +362,7 @@ final class BrowserLauncherImpl extends BrowserLauncher { @Override public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) { if (browser == null) { - BrowserUtil.launchBrowser(url); + BrowserUtil.browse(url); } else { for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) { From 94f05f9d776782174ea3925685cb42e440e7f4e4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 7 Feb 2014 18:03:14 +0100 Subject: [PATCH 16/53] gwt code server run on module A. A inherits module B. Our current file belongs to module B. So, actual: http://localhost:9876/sourcemaps/A/com/jetbrains/upsource/frontend/application/client/views/feedView/FeedView.java expected: http://localhost:9876/sourcemaps/B/com/jetbrains/upsource/frontend/application/client/views/feedView/FeedView.java So, we must handle this case, not only library classes --- platform/platform-impl/src/com/intellij/util/Urls.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/util/Urls.java b/platform/platform-impl/src/com/intellij/util/Urls.java index f9cb97d20dca..64e577d1138c 100644 --- a/platform/platform-impl/src/com/intellij/util/Urls.java +++ b/platform/platform-impl/src/com/intellij/util/Urls.java @@ -132,7 +132,6 @@ public final class Urls { Matcher matcher = URI_PATTERN.matcher(urlToParse); if (!matcher.matches()) { - LOG.warn("Cannot parse url " + url); return null; } String scheme = matcher.group(1); From 5c8aa9588f91e3cec0589396a12acfd689033087 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 7 Feb 2014 16:34:13 +0100 Subject: [PATCH 17/53] Cleanup (test) --- .../util/containers/WeakListTest.java | 105 ++++++++++-------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java b/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java index 9fe0140cbea3..db86e637f281 100644 --- a/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java +++ b/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.containers; -import junit.framework.TestCase; +import org.junit.Test; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -24,20 +23,17 @@ import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; -public class WeakListTest extends TestCase { - private final WeakList myWeakList = new WeakList(); - protected final List myHolder = new ArrayList(); - - private void addElement(Object element) { - myWeakList.add(element); - myHolder.add(element); - } +import static org.junit.Assert.*; +public class WeakListTest { private static final String HARD_REFERENCED = "xxx"; + + private final WeakList myWeakList = new WeakList(); + private final List myHolder = new ArrayList(); + + @Test public void testCompresses() { - for (int i = 0; i < 20; i++) { - addElement(new Object()); - } + fillWithObjects(20); assertEquals(20, myWeakList.listSize()); addElement(HARD_REFERENCED); assertEquals(21, myWeakList.listSize()); @@ -55,37 +51,26 @@ public class WeakListTest extends TestCase { assertEquals(1, myWeakList.listSize()); } - private static void gc() { - ConcurrentMapsTest.tryGcSoftlyReachableObjects(); - WeakReference weakReference = new WeakReference(new Object()); - do { - System.gc(); - } - while (weakReference.get() != null); - } - + @Test public void testClear() { - for (int i = 0; i < 20; i++) { - addElement(new Object()); - } + fillWithObjects(20); assertEquals(20, myWeakList.listSize()); myHolder.clear(); gc(); myWeakList.clear(); assertFalse(myWeakList.iterator().hasNext()); } - + + @Test public void testIterator() { int N = 10; - for (int i=0; i< N;i++) { - addElement(i); - } + fillWithInts(N); gc(); - Iterator iterator = (Iterator)myWeakList.iterator(); - for (int i=0; i< N;i++) { + Iterator iterator = myWeakList.iterator(); + for (int i = 0; i < N; i++) { assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); - int element = iterator.next(); + int element = (Integer)iterator.next(); assertEquals(i, element); } assertFalse(iterator.hasNext()); @@ -97,7 +82,8 @@ public class WeakListTest extends TestCase { } assertEquals(N, elementCount); } - + + @Test public void testRemoveViaIterator() { addElement(new Object()); addElement(new Object()); @@ -115,14 +101,13 @@ public class WeakListTest extends TestCase { myHolder.remove(1); } + @Test public void testRemoveAllViaIterator() { int N = 10; - for (int i=0; i< N;i++) { - addElement(i); - } + fillWithInts(N); gc(); Iterator iterator = myWeakList.iterator(); - for (int i=0; i< N;i++) { + for (int i = 0; i < N; i++) { assertTrue(iterator.hasNext()); int element = (Integer)iterator.next(); assertEquals(i, element); @@ -132,6 +117,7 @@ public class WeakListTest extends TestCase { assertTrue(myWeakList.toStrongList().isEmpty()); } + @Test public void testRemoveLastViaIterator() { addElement(new Object()); addElement(new Object()); @@ -143,6 +129,7 @@ public class WeakListTest extends TestCase { iterator.remove(); } + @Test public void testIteratorKeepsFirstElement() { addElement(new Object()); addElement(new Object()); @@ -153,7 +140,8 @@ public class WeakListTest extends TestCase { assertNotNull(iterator.next()); assertFalse(iterator.hasNext()); } - + + @Test public void testIteratorKeepsNextElement() { addElement(new Object()); addElement(new Object()); @@ -167,6 +155,7 @@ public class WeakListTest extends TestCase { assertFalse(iterator.hasNext()); } + @Test public void testIteratorRemoveEmpty() { Iterator iterator = myWeakList.iterator(); assertFalse(iterator.hasNext()); @@ -184,16 +173,13 @@ public class WeakListTest extends TestCase { } } - public void testElementGetsGcedInTheMiddleAndListRebuildsItself() { + @Test + public void testElementGetsCollectedInTheMiddleAndListRebuildsItself() { int N = 200; - for (int i = 0; i < N; i++) { - addElement(new Object()); - } + fillWithObjects(N); String x = new String("xxx"); addElement(x); - for (int i = 0; i < N; i++) { - addElement(new Object()); - } + fillWithObjects(N); gc(); assertEquals(N + 1 + N, myWeakList.listSize()); myHolder.clear(); @@ -209,6 +195,7 @@ public class WeakListTest extends TestCase { assertSame(x, element); } + @Test public void testIsEmpty() { assertTrue(myWeakList.isEmpty()); addElement(new Object()); @@ -218,4 +205,30 @@ public class WeakListTest extends TestCase { assertEquals(1, myWeakList.listSize()); assertTrue(myWeakList.isEmpty()); } + + private void addElement(Object element) { + myWeakList.add(element); + myHolder.add(element); + } + + private void fillWithObjects(int n) { + for (int i = n - 1; i >= 0; i--) { + addElement(new Object()); + } + } + + private void fillWithInts(int n) { + for (int i = 0; i < n; i++) { + addElement(i); + } + } + + private static void gc() { + ConcurrentMapsTest.tryGcSoftlyReachableObjects(); + WeakReference weakReference = new WeakReference(new Object()); + do { + System.gc(); + } + while (weakReference.get() != null); + } } From 8ab67db6c535c862e25c2f4761e6e2e8ab593aa4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 13:19:03 +0100 Subject: [PATCH 18/53] new inference: method reference inference --- .../intellij/psi/PsiMethodReferenceUtil.java | 8 +- ...nctionalInterfaceParameterizationUtil.java | 4 +- .../graphInference/InferenceSession.java | 4 +- .../PsiMethodReferenceExpressionImpl.java | 132 ++++++++---------- 4 files changed, 63 insertions(+), 85 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index ac05d7c94f61..924f51f3524c 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -48,9 +48,7 @@ public class PsiMethodReferenceUtil { final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(expression); final PsiElement resolve = result.getElement(); if (resolve instanceof PsiMethod) { - PsiSubstitutor subst = PsiSubstitutor.EMPTY; - subst = subst.putAll(qualifierResolveResult.getSubstitutor()); - subst = subst.putAll(result.getSubstitutor()); + PsiSubstitutor subst = result.getSubstitutor(); final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); @@ -197,9 +195,7 @@ public class PsiMethodReferenceUtil { final PsiElement resolve = result.getElement(); if (resolve instanceof PsiMethod) { final MethodSignature signature1 = method.getSignature(LambdaUtil.getSubstitutor(method, resolveResult)); - PsiSubstitutor subst = PsiSubstitutor.EMPTY; - subst = subst.putAll(TypeConversionUtil.getSuperClassSubstitutor(((PsiMethod)resolve).getContainingClass(), qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor())); - subst = subst.putAll(result.getSubstitutor()); + PsiSubstitutor subst = result.getSubstitutor(); final MethodSignature signature2 = ((PsiMethod)resolve).getSignature(subst); if (methodReferenceExpression.isExact()) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java index 486d5af7e285..309ba98ff7b1 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java @@ -173,9 +173,9 @@ public class FunctionalInterfaceParameterizationUtil { if (bound == null) { parameters[i] = Bi; } else if (((PsiWildcardType)paramType).isExtends()){ - parameters[i] = GenericsUtil.getGreatestLowerBound(Bi, bound); + parameters[i] = GenericsUtil.getGreatestLowerBound(Bi, GenericsUtil.eliminateWildcards(bound, false)); } else { - parameters[i] = bound; + parameters[i] = GenericsUtil.eliminateWildcards(bound, false); } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index 1bc135c6df37..259e4809648f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -330,7 +330,7 @@ public class InferenceSession { } } - private void registerConstraints(PsiType returnType, PsiType targetType) { + public void registerConstraints(PsiType returnType, PsiType targetType) { final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType); if (inferenceVariable != null) { resolveBounds(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true); @@ -574,7 +574,7 @@ public class InferenceSession { return dependencies != null ? !dependencies.isEmpty() : isProper; } - protected boolean repeatInferencePhases(boolean incorporate) { + public boolean repeatInferencePhases(boolean incorporate) { do { if (!reduceConstraints()) { //inference error occurred diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 3cdb4a5b5721..2bf0a4562c3f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -26,6 +26,8 @@ import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; +import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; +import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeCompatibilityConstraint; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.FileElement; import com.intellij.psi.impl.source.tree.JavaElementType; @@ -328,7 +330,8 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase @NotNull @Override public ResolveResult[] resolve(@NotNull PsiJavaReference reference, boolean incompleteCode) { - final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(PsiMethodReferenceExpressionImpl.this); + final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult( + PsiMethodReferenceExpressionImpl.this); final PsiClass containingClass = qualifierResolveResult.getContainingClass(); PsiSubstitutor substitutor = qualifierResolveResult.getSubstitutor(); @@ -343,14 +346,15 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase PsiType functionalInterfaceType = null; final Map map = PsiMethodReferenceUtil.ourRefs.get(); if (map != null) { - functionalInterfaceType = map.get(PsiMethodReferenceExpressionImpl.this); + functionalInterfaceType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(map.get(PsiMethodReferenceExpressionImpl.this)); } if (functionalInterfaceType == null) { functionalInterfaceType = getFunctionalInterfaceType(); } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); - final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null; + final PsiSubstitutor functionalInterfaceSubstitutor = interfaceMethod != null ? LambdaUtil.getSubstitutor(interfaceMethod, resolveResult) : null; + final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(functionalInterfaceSubstitutor) : null; final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); PsiFile containingFile = getContainingFile(); final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(containingFile); @@ -399,7 +403,56 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase @NotNull @Override public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) { - return inferTypeArgumentsFromInterfaceMethod(signature, interfaceMethodReturnType, method, substitutor, languageLevel, qualifierResolveResult); + if (functionalInterfaceSubstitutor == null) return PsiSubstitutor.EMPTY; + final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, getManager(), PsiMethodReferenceExpressionImpl.this); + final PsiParameter[] functionalMethodParameters = interfaceMethod.getParameterList().getParameters(); + final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (parameters.length == functionalMethodParameters.length) {//static methods + for (int i = 0; i < functionalMethodParameters.length; i++) { + final PsiType pType = functionalInterfaceSubstitutor.substitute(functionalMethodParameters[i].getType()); + session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), pType)); + } + } + else if (parameters.length + 1 == functionalMethodParameters.length) { //instance methods + final PsiClass aClass = qualifierResolveResult.getContainingClass(); + session.initBounds(aClass.getTypeParameters()); + final PsiSubstitutor qualifierResultSubstitutor = qualifierResolveResult.getSubstitutor(); + + final PsiType pType = functionalInterfaceSubstitutor.substitute(functionalMethodParameters[0].getType()); + + PsiSubstitutor psiSubstitutor = qualifierResultSubstitutor; + //15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1, + // the type to search is the result of capture conversion (5.1.10) applied to T; + // otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference. + if (PsiUtil.isRawSubstitutor(aClass, qualifierResultSubstitutor)) { + final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(pType); + final PsiClass pClass = pResult.getElement(); + final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(aClass, pClass, pResult.getSubstitutor()) : null; + if (receiverSubstitutor != null) { + psiSubstitutor = receiverSubstitutor; + } + } + + final PsiType qType = JavaPsiFacade.getElementFactory(getProject()).createType(aClass, psiSubstitutor); + + session.addConstraint(new TypeCompatibilityConstraint(qType, pType)); + + for (int i = 0; i < parameters.length; i++) { + final PsiType interfaceParamType = functionalInterfaceSubstitutor.substitute(functionalMethodParameters[i + 1].getType()); + session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), interfaceParamType)); + } + } + else { + return substitutor; + } + + boolean success = session.repeatInferencePhases(false); + + final PsiType returnType = method.getReturnType(); + if (returnType != null) { + session.registerConstraints(returnType, interfaceMethodReturnType); + } + return session.infer(parameters, null, null); } }; } @@ -424,77 +477,6 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase return JavaResolveResult.EMPTY_ARRAY; } - @NotNull - private PsiSubstitutor inferTypeArgumentsFromInterfaceMethod(@Nullable MethodSignature signature, - @Nullable PsiType interfaceMethodReturnType, - PsiMethod method, - PsiSubstitutor substitutor, - LanguageLevel languageLevel, - PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult) { - if (signature == null) return PsiSubstitutor.EMPTY; - PsiType[] types = method.getSignature(PsiUtil.isRawSubstitutor(method, substitutor) ? PsiSubstitutor.EMPTY : substitutor).getParameterTypes(); - - final PsiClass qualifierClass = qualifierResolveResult.getContainingClass(); - if (qualifierClass != null) { - substitutor = TypeConversionUtil.getSuperClassSubstitutor(method.getContainingClass(), - qualifierClass, - substitutor).putAll(substitutor); - } - - PsiType[] rightTypes = signature.getParameterTypes(); - if (!method.isVarArgs() || types.length == 0) { - PsiSubstitutor psiSubstitutor = null; - if (types.length < rightTypes.length) { - psiSubstitutor = getSubstitutor(rightTypes[0]); - } else if (types.length > rightTypes.length) { - psiSubstitutor = getSubstitutor(types[0]); - } - if (psiSubstitutor != null) { - return substitutor.putAll(psiSubstitutor); - } - } else { - if (rightTypes.length != types.length || rightTypes[rightTypes.length - 1].getArrayDimensions() != types[types.length-1].getArrayDimensions()) { - boolean expandTypeArray = types.length < rightTypes.length; - int min = Math.min(types.length, rightTypes.length); - types = Arrays.copyOf(types, min); - if (expandTypeArray) { - types[types.length - 1] = ((PsiArrayType)types[types.length - 1]).getComponentType(); - } - rightTypes = Arrays.copyOf(rightTypes, min); - } - } - - for (int i = 0; i < rightTypes.length; i++) { - rightTypes[i] = GenericsUtil.eliminateWildcards(rightTypes[i]); - } - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(getProject()).getResolveHelper(); - if (method.isConstructor()) { - return substitutor.putAll(resolveHelper.inferTypeArguments(method.getTypeParameters(), types, rightTypes, languageLevel)); - } - - return LambdaUtil.inferFromReturnType(method.getTypeParameters(), - method.getReturnType(), - GenericsUtil.eliminateWildcards(interfaceMethodReturnType), - substitutor.putAll( - resolveHelper.inferTypeArguments(method.getTypeParameters(), types, rightTypes, languageLevel)), - languageLevel, getProject()); - } - - @NotNull - private PsiSubstitutor getSubstitutor(@NotNull PsiType type) { - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(type)); - PsiSubstitutor psiSubstitutor = resolveResult.getSubstitutor(); - if (type instanceof PsiClassType) { - final PsiClass psiClass = resolveResult.getElement(); - if (psiClass instanceof PsiTypeParameter) { - for (PsiClass aClass : psiClass.getSupers()) { - psiSubstitutor = psiSubstitutor.putAll(TypeConversionUtil.getSuperClassSubstitutor(aClass, (PsiClassType)type)); - } - } - } - return psiSubstitutor; - } - private class MethodReferenceConflictResolver implements PsiConflictResolver { private final MethodSignature mySignature; private final PsiMethodReferenceUtil.QualifierResolveResult myQualifierResolveResult; From c0cbeb959bf6335b69f8fa0e7561512ce3eaae52 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 14:13:26 +0100 Subject: [PATCH 19/53] new inference: method constructor inference --- .../src/com/intellij/psi/LambdaUtil.java | 20 ------------------- .../PsiMethodReferenceExpressionImpl.java | 12 ++++++----- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index ff21fcc0fef8..c289cf4b5987 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -583,26 +583,6 @@ public class LambdaUtil { return null; } - @NotNull - public static PsiSubstitutor inferFromReturnType(@NotNull PsiTypeParameter[] typeParameters, - final PsiType returnType, - @Nullable final PsiType interfaceMethodReturnType, - @NotNull PsiSubstitutor psiSubstitutor, - final LanguageLevel languageLevel, - final Project project) { - if (returnType == PsiType.VOID || interfaceMethodReturnType == PsiType.VOID) return psiSubstitutor; - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper(); - final PsiSubstitutor substitutor = - resolveHelper.inferTypeArguments(typeParameters, new PsiType[]{interfaceMethodReturnType}, new PsiType[]{returnType}, languageLevel); - for (PsiTypeParameter typeParameter : typeParameters) { - final PsiType inferredType = substitutor.substitute(typeParameter); - if (PsiUtil.resolveClassInType(inferredType) != typeParameter) { - psiSubstitutor = psiSubstitutor.put(typeParameter, inferredType); - } - } - return psiSubstitutor; - } - public static boolean notInferredType(PsiType typeByExpression) { return typeByExpression instanceof PsiMethodReferenceType || typeByExpression instanceof PsiLambdaExpressionType || typeByExpression instanceof PsiLambdaParameterType; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 2bf0a4562c3f..078a6d2df770 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -361,12 +361,14 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase if (isConstructor && interfaceMethod != null) { final PsiTypeParameter[] typeParameters = containingClass.getTypeParameters(); final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor); - Project project = containingClass.getProject(); - final PsiClassType returnType = JavaPsiFacade.getElementFactory(project).createType(containingClass, - isRawSubst ? PsiSubstitutor.EMPTY : substitutor); + final PsiClassType returnType = JavaPsiFacade.getElementFactory(containingClass.getProject()) + .createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : substitutor); - substitutor = LambdaUtil.inferFromReturnType(typeParameters, returnType, GenericsUtil.eliminateWildcards(interfaceMethodReturnType), substitutor, languageLevel, - project); + final InferenceSession session = new InferenceSession(typeParameters, substitutor, getManager(), null); + if (!(session.isProperType(returnType) && session.isProperType(interfaceMethodReturnType))) { + session.registerConstraints(returnType, interfaceMethodReturnType); + substitutor = session.infer(); + } if (containingClass.getConstructors().length == 0) { ClassCandidateInfo candidateInfo = null; From 3bda220da49f9c6f5798b734b0d1fc228d9e3556 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 14:20:51 +0100 Subject: [PATCH 20/53] new inference: method ref inference cleanup --- .../PsiMethodReferenceExpressionImpl.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 078a6d2df770..5b5758d016c8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -353,11 +353,8 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); - final PsiSubstitutor functionalInterfaceSubstitutor = interfaceMethod != null ? LambdaUtil.getSubstitutor(interfaceMethod, resolveResult) : null; - final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(functionalInterfaceSubstitutor) : null; + final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null; final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); - PsiFile containingFile = getContainingFile(); - final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(containingFile); if (isConstructor && interfaceMethod != null) { final PsiTypeParameter[] typeParameters = containingClass.getTypeParameters(); final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor); @@ -385,13 +382,13 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase final PsiConflictResolver[] resolvers; if (signature != null) { final PsiType[] parameterTypes = signature.getParameterTypes(); - resolvers = new PsiConflictResolver[]{conflictResolver, new MethodRefsSpecificResolver(parameterTypes, languageLevel)}; + resolvers = new PsiConflictResolver[]{conflictResolver, new MethodRefsSpecificResolver(parameterTypes, PsiUtil.getLanguageLevel(PsiMethodReferenceExpressionImpl.this))}; } else { resolvers = new PsiConflictResolver[]{conflictResolver}; } final MethodCandidatesProcessor processor = - new MethodCandidatesProcessor(PsiMethodReferenceExpressionImpl.this, containingFile, resolvers, new SmartList()) { + new MethodCandidatesProcessor(PsiMethodReferenceExpressionImpl.this, getContainingFile(), resolvers, new SmartList()) { @Override protected MethodCandidateInfo createCandidateInfo(final PsiMethod method, final PsiSubstitutor substitutor, @@ -405,13 +402,13 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase @NotNull @Override public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) { - if (functionalInterfaceSubstitutor == null) return PsiSubstitutor.EMPTY; + if (interfaceMethod == null) return substitutor; final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, getManager(), PsiMethodReferenceExpressionImpl.this); final PsiParameter[] functionalMethodParameters = interfaceMethod.getParameterList().getParameters(); final PsiParameter[] parameters = method.getParameterList().getParameters(); if (parameters.length == functionalMethodParameters.length) {//static methods for (int i = 0; i < functionalMethodParameters.length; i++) { - final PsiType pType = functionalInterfaceSubstitutor.substitute(functionalMethodParameters[i].getType()); + final PsiType pType = signature.getParameterTypes()[i]; session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), pType)); } } @@ -420,10 +417,10 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase session.initBounds(aClass.getTypeParameters()); final PsiSubstitutor qualifierResultSubstitutor = qualifierResolveResult.getSubstitutor(); - final PsiType pType = functionalInterfaceSubstitutor.substitute(functionalMethodParameters[0].getType()); + final PsiType pType = signature.getParameterTypes()[0]; PsiSubstitutor psiSubstitutor = qualifierResultSubstitutor; - //15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1, + // 15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1, // the type to search is the result of capture conversion (5.1.10) applied to T; // otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference. if (PsiUtil.isRawSubstitutor(aClass, qualifierResultSubstitutor)) { @@ -440,7 +437,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase session.addConstraint(new TypeCompatibilityConstraint(qType, pType)); for (int i = 0; i < parameters.length; i++) { - final PsiType interfaceParamType = functionalInterfaceSubstitutor.substitute(functionalMethodParameters[i + 1].getType()); + final PsiType interfaceParamType = signature.getParameterTypes()[i + 1]; session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), interfaceParamType)); } } From 5fb1dbb2ce2ea6444a8806b11dc0e8ec3ee54ed5 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 17:18:29 +0100 Subject: [PATCH 21/53] new inference: check containing class type params if they are in bounds --- .../daemon/impl/analysis/GenericsHighlightUtil.java | 10 ++++++++-- .../daemon/impl/analysis/HighlightVisitorImpl.java | 9 ++++++++- ...hlightReferenceWhenContradictBoundsAreInferred.java | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index a14e9992ef87..05208e889727 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -62,8 +62,14 @@ public class GenericsHighlightUtil { public static HighlightInfo checkInferredTypeArguments(PsiTypeParameterListOwner listOwner, PsiElement call, PsiSubstitutor substitutor) { - final Pair inferredTypeArgument = - GenericsUtil.findTypeParameterWithBoundError(listOwner.getTypeParameters(), substitutor, call, false); + return checkInferredTypeArguments(listOwner.getTypeParameters(), call, substitutor); + } + + @Nullable + public static HighlightInfo checkInferredTypeArguments(PsiTypeParameter[] typeParameters, + PsiElement call, + PsiSubstitutor substitutor) { + final Pair inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(typeParameters, substitutor, call, false); if (inferredTypeArgument != null) { final PsiType extendsType = inferredTypeArgument.second; final PsiTypeParameter typeParameter = inferredTypeArgument.first; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index db3cbfb35f6b..f0e982ead75a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -40,6 +40,7 @@ import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.util.*; +import com.intellij.util.ArrayUtil; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.MostlySingularMultiMap; import gnu.trove.THashMap; @@ -1250,7 +1251,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } if (!myHolder.hasErrorResults() && method instanceof PsiTypeParameterListOwner) { - myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments((PsiTypeParameterListOwner)method, expression, result.getSubstitutor())); + PsiTypeParameter[] typeParameters = ((PsiTypeParameterListOwner)method).getTypeParameters(); + if (method instanceof PsiMethod) { + final PsiClass containingClass = ((PsiMethod)method).getContainingClass(); + assert containingClass != null : method; + typeParameters = ArrayUtil.mergeArrays(typeParameters, containingClass.getTypeParameters()); + } + myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments(typeParameters, expression, result.getSubstitutor())); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java index bc3b75c1be94..0d1e79863b9d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java @@ -29,10 +29,10 @@ class Test { static void meth4(I3 s) { } static { - meth1(Foo::new); + meth1(Foo::new); meth2(Foo::new); - meth3(Foo::new); - meth4(Foo::new); + meth3(Foo::new); + meth4(Foo::new); meth1(Test::foo); meth2(Test::foo); From 6efef684ce275612e86e89fb9849ba8ebdac3347 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 18:12:06 +0100 Subject: [PATCH 22/53] new inference: method ref inference: postpone return type inference in case of constructor refs --- .../PsiMethodReferenceExpressionImpl.java | 46 ++++++++++--------- .../lambda/methodRef/RawQualifier.java | 2 +- .../lambda/methodRef/ReturnTypeSpecific.java | 4 +- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 5b5758d016c8..36566e9b1d05 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -17,7 +17,6 @@ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; @@ -355,26 +354,20 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null; final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); - if (isConstructor && interfaceMethod != null) { - final PsiTypeParameter[] typeParameters = containingClass.getTypeParameters(); - final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor); - final PsiClassType returnType = JavaPsiFacade.getElementFactory(containingClass.getProject()) - .createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : substitutor); - - final InferenceSession session = new InferenceSession(typeParameters, substitutor, getManager(), null); + if (isConstructor && interfaceMethod != null && containingClass.getConstructors().length == 0) { + final PsiClassType returnType = composeReturnType(containingClass, substitutor); + final InferenceSession session = new InferenceSession(containingClass.getTypeParameters(), substitutor, getManager(), null); if (!(session.isProperType(returnType) && session.isProperType(interfaceMethodReturnType))) { session.registerConstraints(returnType, interfaceMethodReturnType); substitutor = session.infer(); } - - if (containingClass.getConstructors().length == 0) { - ClassCandidateInfo candidateInfo = null; - if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && signature.getParameterTypes().length == 0 || - PsiMethodReferenceUtil.onArrayType(containingClass, signature)) { - candidateInfo = new ClassCandidateInfo(containingClass, substitutor); - } - return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo}; + ClassCandidateInfo candidateInfo = null; + if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && + signature.getParameterTypes().length == 0 || + PsiMethodReferenceUtil.onArrayType(containingClass, signature)) { + candidateInfo = new ClassCandidateInfo(containingClass, substitutor); } + return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo}; } final MethodReferenceConflictResolver conflictResolver = @@ -403,10 +396,16 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase @Override public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) { if (interfaceMethod == null) return substitutor; + final PsiSubstitutor qualifierResultSubstitutor = qualifierResolveResult.getSubstitutor(); final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, getManager(), PsiMethodReferenceExpressionImpl.this); final PsiParameter[] functionalMethodParameters = interfaceMethod.getParameterList().getParameters(); final PsiParameter[] parameters = method.getParameterList().getParameters(); if (parameters.length == functionalMethodParameters.length) {//static methods + + if (method.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, qualifierResultSubstitutor)) { + session.initBounds(containingClass.getTypeParameters()); + } + for (int i = 0; i < functionalMethodParameters.length; i++) { final PsiType pType = signature.getParameterTypes()[i]; session.addConstraint(new TypeCompatibilityConstraint(parameters[i].getType(), pType)); @@ -415,7 +414,6 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase else if (parameters.length + 1 == functionalMethodParameters.length) { //instance methods final PsiClass aClass = qualifierResolveResult.getContainingClass(); session.initBounds(aClass.getTypeParameters()); - final PsiSubstitutor qualifierResultSubstitutor = qualifierResolveResult.getSubstitutor(); final PsiType pType = signature.getParameterTypes()[0]; @@ -423,16 +421,16 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase // 15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1, // the type to search is the result of capture conversion (5.1.10) applied to T; // otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference. - if (PsiUtil.isRawSubstitutor(aClass, qualifierResultSubstitutor)) { + if (PsiUtil.isRawSubstitutor(containingClass, qualifierResultSubstitutor)) { final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(pType); final PsiClass pClass = pResult.getElement(); - final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(aClass, pClass, pResult.getSubstitutor()) : null; + final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null; if (receiverSubstitutor != null) { psiSubstitutor = receiverSubstitutor; } } - final PsiType qType = JavaPsiFacade.getElementFactory(getProject()).createType(aClass, psiSubstitutor); + final PsiType qType = JavaPsiFacade.getElementFactory(getProject()).createType(containingClass, psiSubstitutor); session.addConstraint(new TypeCompatibilityConstraint(qType, pType)); @@ -447,7 +445,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase boolean success = session.repeatInferencePhases(false); - final PsiType returnType = method.getReturnType(); + final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType(); if (returnType != null) { session.registerConstraints(returnType, interfaceMethodReturnType); } @@ -476,6 +474,12 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase return JavaResolveResult.EMPTY_ARRAY; } + private PsiClassType composeReturnType(PsiClass containingClass, PsiSubstitutor substitutor) { + final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor); + return JavaPsiFacade.getElementFactory(containingClass.getProject()) + .createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : substitutor); + } + private class MethodReferenceConflictResolver implements PsiConflictResolver { private final MethodSignature mySignature; private final PsiMethodReferenceUtil.QualifierResolveResult myQualifierResolveResult; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java index 67bbac28af1e..69fd19863ad2 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java @@ -39,6 +39,6 @@ class MyTest1 { static void foo(I3 i) {} static { - foo(Foo::new); + foo(Foo::new); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java index 93ca7899c7e5..848c423302c6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java @@ -67,7 +67,7 @@ class MyTest1 { } public static void main(String[] args) { - m(Foo::new); + m(Foo::new); } } class MyTest2 { @@ -104,6 +104,6 @@ class MyTest2 { } public static void main(String[] args) { - m(Foo::new); + m(Foo::new); } } From a8237f5eb18f610f0f0a115400e7539f43ff002b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 18:40:44 +0100 Subject: [PATCH 23/53] hide embedded scene builder under "embed.scene.builder" property [https://javafx-jira.kenai.com/browse/RT-35745] --- platform/platform-resources-en/src/misc/registry.properties | 1 + .../javaFX/sceneBuilder/SceneBuilderEditorProvider.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index bdf697d8b637..3f909b7be2b9 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -361,3 +361,4 @@ ide.open.file.in.temp.project.dir=true ide.open.file.in.temp.project.dir.description=Enables opening file in temp project directory editor.allow.multiple.carets=false +embed.scene.builder=false diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java index 08e05daf3def..de123d1ee1bb 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java @@ -1,6 +1,5 @@ package org.jetbrains.plugins.javaFX.sceneBuilder; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorPolicy; @@ -10,6 +9,7 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -27,7 +27,7 @@ public class SceneBuilderEditorProvider implements FileEditorProvider, DumbAware public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { return JavaFxFileTypeFactory.FXML_EXTENSION.equalsIgnoreCase(file.getExtension()) && SystemInfo.isJavaVersionAtLeast("1.8") && - ApplicationManager.getApplication().isInternal(); + Registry.is("embed.scene.builder", false); } @NotNull From e54fc5bde0b99a85d4d7a6dea125431501569772 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 7 Feb 2014 22:07:37 +0400 Subject: [PATCH 24/53] JavaFX Scene Builder integration --- .../javaFX/FxBuilderEmbedder/lib/embedder.jar | Bin 6608 -> 6644 bytes .../javaFX/sceneBuilder/SceneBuilderImpl.java | 2 ++ 2 files changed, 2 insertions(+) diff --git a/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar b/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar index 9400a2955c5b8b65c08eb093e1f493856573d031..10561a4d95e14dff3cdc5b492375cd88c3b0a340 100644 GIT binary patch delta 4384 zcmZvgcQD*-*T*fQg|N!9IuSjHx>~g8yZWj@lqDp@>ivgkQNyx{nyAsEtk^_}RYR00 zi5kHwQ4&@p^3Of>?kC&Z&QpK0aDT@Di?*chtEw40NmB1nGZN z+M%m`XlsvC|*f`KTpgqFPomn5OSZq$@ibwqT`t3>Nk$%oI?bLe}R*o*EM16p; zw4OUJRD87>HQ_Pqo2HEm9#{@)Zn*V0qXLq&juIT9HDyI@qp|)$1L-)D%+?&WOnij> z#VK>O@e2uGz=^hw&yK9%)kBKAngq0UzSXYL!o442zgpJI(IJ5~%{RA~VnxSV8Ztu! zYHVp&+3qwu4YX$ zJW{#DYc-DxN!2(gTj0Nx06D3)VsMFj3pf)Q%b=~XGb36gO0qu*tpMMD*9vim??s||iki>eD4DuGIx1f-h4!r67@#rJs9sUuSlF$1YFkgvdd42;>w%e~=uk zw(Z8_ckRE*r7Y?f_L@)670YL7*hqQ~O@qB=eQ2*T3xNxle88u^joJk9veWGnOp^W_ z=%9vmAHf7J5l6AnxLtrqwHPzw&oNx9v1 z2?(e_?pRD|vYtW2W0{}&TXtB~+Yeu%sk-S67Kf$jM(4P27n!$h*^>*nWV23q?$btI z^kkLR;08|2GCbQ>ob<~vLtp1wBD%g6VFDCiM+4`eTa=mkOuFJJ9*6o_eKFir>oTkf zu`3>n1IdXKqD7oje)_$R3`YP5XB_gaDZN~IK!c6!hZ|=5`1Rv~N=K=ou=IPRpU)ES z(dmz1ueOV-T?TG7H8y#ff=%ZA>-c+Ris~*@-AfS24oZzHx$3FBY8Y0=-+^*!G@L39 zK=?lQ8_(V`gJywbK3~kZ+)+0g<@`?8lHx(1Xn$E=?V{KN!Cs=fiG3%qq(~RX(g$gK z+hZ$!+_R9)YP}Y2RCMib^EL6p+S~4a<{{$`1<=gyiFz|q;&zqG9O7S8R}uJ6Q83+m zN+DD7XmXpaGva4x&%Gh)#hcD+1p?NVOXA9Eq7g!`RSbh`D4xip&QC#Dx;s7eHMfQ4 zdz>%v#*WvFKWX_DlhSJp*qFlQ_ps`gBM!0>j`};d4d%^w#+56-{DZZ$XC>4)Ov^O5 zkz-Ws-_?{Mj4Tay@R?~DUTW`T%G@A!42(e|F2w@D)9o1nFjI90<1D_odiOYivvDgK zc=3{iP7p#fiB%^7VR;K=;Uh*+DuzW6wPp@HG6M%pHjV!a%0=euxWJHI-L zw=8?Goipt5*Tj|ZMO*?nS{!9gbM-@gH&aTt6ypr7+RTghy4S+O?<8(y(`>XU?V_3x z36puds_$5Sc9;Dl%t(AT%Cd42X>3JzUuwT$4Sn3jcBp-}^7$2YYQHa+1%K(%z$i9xLjZfaK3GiLMi)24QRx*{PhL+11eoqF8}<{kA>a6Ylx z^p>;vIY^yN%pz}W_vs23PQ`#7yk3f&2-EVDejsVnV8QlK-3EQQ99PObsC(1m#ws3e zq2BPYE-6ACZ)EYDF6(=?_5k{-q7MD@q=^g`9OXU4cg9~gG>H72s<&%+(HCAQl!IwW z%=nUx0(=F|@UX;q{l2)(L_go38lvCFjIsT$ANSwC*?)JuIvOh=kjsYcY`}hiH?ydJ zE{6$IuN90%Gb7iu-r%X4J;zKKuPrlOqxgEZFggo*PO)*vtcI#J31Vzk(c&W zk)Zj;9P$dyxr?j@vCTZue#?9sutg1c^ZNEPkk>fs3JMZqVymB74m0Nz^4QTL2tW6I+YI|^8cs{Ao;*C01 z>*9A&i)(h=%26D*YWWD*QV!a1) zhI;yqApnZdsZ=O0y!9id!dp-K!OoDtQo!hoG9$qr`e2#rEprdCgjew*1Ct+X2!WtG zJeK#x68foZtqjw=2Oj$4zf{Q~vW-Qq79{%Qy&97QrI#c_E#b!LpW*25JohOY2$=kO z8GS@v1LCoTB+n$X;tMkTz{W|Y-lRIopEqH`-JhzU`JK+)qXg~e*t2Zp!EyX#qXnzqWH?RFi`_u9vu1pQF#wd9?5L-R_QPL?KHH+$u+X4=AAhf+k| z0C`BW-PKA0efx~-;g1YuO1ZHXZRm%`74}&xI9HaQ{0otHM;EtyNKl#6`k>EK+* zth%QIxJRJIDBwlNWHVX2pl=@9W6oI0gve1JklEOE{|Z-3__?{L%+lP4yzL?^r_K z9xQdMl5?G!K1}kirBh%Pdd3Y&>(IK}!ywenJ~2wElw~8y1Mfd{!ZwFNHkE8=U%cVB z0~>h!%z3cn@|JsDk@NHMWoB=o9_9y#pr9b~OO)){J8GH67C~VnJVBPc!A=wuz~F&j zJ8ZG&;(dqZ*e%)WO}NEH_vV;8I&=kw5TUdsmUzZd8_X{!6)NQD4pq4l=3+Z4gT~z;)Z|mBg#Oh zg_4adjfK%i|m7-y!zUhx~*=l_k^CjKdLS79XCe}W89zv?EFet z(f!J5OGA?YA4G|tgjb>moVk`Qex{dszNoMdJjy$Ez-Gom4~))EGU)Q-=eF}yUk)`Y zAZMm2KZ>o*+((pDj%|FvLKWWAyR1$#NpAOGv2Hd~L9PZ8{vN{LaApK>&C@C#MQRl* z9iCNarwHs(4gYh)yE~g@`l|D#1)^FjJHf^tAk~AHnA7}Wkf`}VcVLys{?)!BzD)Pr5Y*R;RTqQDKEtg;!rJsJjHDbsBdl8^KBJ)=cb^2YgY5QbC)Zaeca0i3! z)Dp7+TFI^FQRG*MhYYf@;vpS%Zsc!2l2XQK>jDRBe}q2}IcI?1QqZcK+qrl=wt|G# zF&xWQ{ZLP^If@`(qW_R^(&->;%hwgda0SM^|5GaEv=}uzJGHm&Lp6gQ9o;15`#>pM z%DAgEmPKR$$cVmygIpEu(FxxD(z`wK4=OQ$gED`XWI^|jvlsx%`p=$v5)W}UkI>NJ zz-TE1y0Bi=YqZ;~w_E0_WBMveE z{IbT@ZP?02y0$uFS*G+B$?zb0bKPaIv5?J=;UX+ARj#69Ft2u1D*}?sQnk4i)LG!f zOITnoucuG(OUckiGq; zUG>feOiN!ZV2)MpJ!T}`@X%>;H6Rv{{Dzu}<$CsQCi$GUPOu?tSySK~8SiCcAG-AM z;fZ&r+dflGAn%Fx;uz%YA>quP5uujmeP%K14^qnQjzTW2(7$j}F=o2n+`>y;*i}q6 zGli{t;@(ztaMAq(^+mQEeNftDoTU(IO3@^HS9IMeMP5%#ViHsEGVTM@AXhT5OEq5y z@j77pQqWxLA8G{-W;{(vHKz4;*BegjeZ;7#h_YrY9}(5Ryl!QV+S|>U!nYVShw~QY z9&nK=1&6Op$#von3P@PN;U38xuQRDTWLX`iq5u){%hY*9m)L=)_{fEyHV zGE|AN7{uTRb&52jzeFEReu{>>3T4?nkdS0>?by>YFXi?Uy;C-;$B~*|5KE*PS>7b& zh(B;Jn__cAeqe4dyJukB>_bjzQvbPRS$!t%;7^adgfOb@jb-Ml#c?NcS!MgwmeL#_ zO2K3Kr7F=@L;ZHD44dXB5&?V!pr&L%#xJ3l-8&vqab%XA|0f7Xc*mw}B9Xjt7J@yy za`QN*zRxIIJd<$P^Lr$|tfJ3na3&zVtN3O~EOFJuYuUz^4B?d&B4>G68oV4sqg))k zDb95{5r=TENcIOw_Ccx4pX*Qu7kIcGe!{3O|607~QW*h)JsA+NT&$c_EHB-h>fsA~ zZ_}Np+3{Xwj{7M3G20#OtLv>xv}T6n6lM`$qF)gc5jld0i2j+(NJK$FLG*tPS_8(0 zIQ46>e#LdtGj^SwOwl8hrO||!78>T)D&b6ft;X4{9&>#{djL3jxtnJ(mELO%zC20~ zgLy_Cc+PvOcFwC2?YKzLk~eUZNw2%IA3&KMAg#9dSPgdF9cpfHjth*@DDnHSLnAm< z${PcI&;Z}c-fD1CN~Bm+*!5gN0nXjizaPyA7l0}}EZh_vek6LYBy=mL*ujg;vh5s7 zj*VSwqAblztx|8-1h%Bf?Fw><$9JoZ**$l|uh^Q|Zo47(X*T{BZQmS_=`C}fM*N-_eelWXoW4K=W*9Y^hknf(-QVvmMF`B!H{ezWn z%1hJgP8}UmB@&aU6q7_-xkR>ZKDuqAeU=`9lmBOyOW+VT`L9`=|HCXJKnCjO?-~~N z%6i*kOr7zfxmwErl9{`l={sQot%x6ZWm5;o*&gY#>2Pt)mHL4Z2z?8!!fs)LM4mbJ zJox;(reeXI&Z>oO3A%rGx*?|HARiqjw*WjirF5aXKSQT0mqJ5@PwTGb)cGdGp7_v# z9O`C-i_9}I_HMx}RVDy_Q~}-ft7TzSr|H`hPnqbfR00({>H;VILYqQ|Pq-bO2(vs#w>K&ZKXA@opFKTdCT#k#a=ErI~)#;B}hZ+Y; zh76}~o3WvZr8cgn2w*XvVx33oM@W(m74XG5gR>P$Vz@aYeLJ9iN>&Wc@Sg1Lc2A_) z-s87?qLBWhr%G;9?ryRQ@}qr=%ez6E35Rjd*l5~d*8Mj~W6XRO=p=E!JMu-Nn=ZtS zEzg28d1jtC@tzB;#^+WYpF|@koSJ=UXt%ighmX{Cq^ZF3;dy!vZQe2FRtAIYEAraPBd%j-!PZ51m ztqtPk=^}vEWjYm!Ew;YmDBC>Bwn*3Nv*VX{n^xZ}UCZsz%x|>deY9rS(>1G~x2A-( z7BHQBc=oX(iN@Fj=7-^QmQecSAqIGifqS9oooTYZpgW?6D+o+_kA9womW6_`1*4bV z7hHQ>o}iEV<32Jyz7>V+Ji&x@oVPI84lZ1;iPKmJjzr8$G|H#85a&|(yuXc=g_fW4 zLq!9~9&K2kz8tU)-(&b!MQc+p8d?5Uko(`)?7y$P*A!MjB!@0r++=-Y9TrBfoK1gk zSxB^=!7E=GHCK|t#ZXqiVo<{%_$pii_1)N}ZEJTxw=DR0~d zXHJP$+~sD6s4D2|DTl3gei&p4XW?S8>HeA}KleA;b%m~Xp%2&#!8-uk5RWrZ zPF09sKiN3o+~@37W0?Zpd29kT9WTH;e|i~G=Kx?UlZ?)p!r`=R&?X^q56{a^5Ue@N z)>ff^56h$5^S-7Wl90Q{RP)nK;{lWN)#Z=}`SPY$_NZ0*S%#jpn56_Qi_*FA*YkfM z)#GX%`eCD&^E2u>4hx~I2a<4%2QQStA&92R2FTRvrHvvy^ zNCO{ze8EH>QC{}xrMGh-|P3^aVZ|x&)ZteHoZ_}@w~Id!76TotmZnUZc6TH@1zF#c&XXtr0kg%%xPBdlOP==J4_Bvy%9v`S}9U`uw zP*OR&_0z>J?iyLJ<}L;R-NP={HeADsj`B(NXz(w)A29BpHee77}M)nT*2H` z^(gWhkxh8_R7mMU4=kAGlGRjHS7+XJLAV{7zaG-B=f)l8w~~<S!fZ*eZ7&8Yy<-~X&FlF zR}(U)r+}aV2Po+2E}aL=)@BY4AX`M1=nG1#LNA6`f{*_khkvUyq1b4xTgSw2pwvj$ zi&mRVRl)40NiX~gBl)3*kz~NIK?^)c|3t1sz{Q8ykj1fyzT?Td)&tX?gOd&f&tf9K z(=&nqR%EI71e|Y63NaZ%o>U+Tm)2FtI-d~?&wX8^-Uhhtd==Ch5nY-*K_M3mBEg*u zdof_3%Nh*4x26Nq30_#p64UwPl<)lH)yPhR6Aq_Wd4-+)R)K3pKNh2#FTr>lYRBC#jBN{2mf^3Sv)#Il2h-J1nZ8rPusPljq>1}HX5JCMf)@Ce!Rn%u zJe~1O*C-Q)Dy9}4jggue8=axgv7lioE@7zsd=Ezaqm^(|u_ZW8|Naz2`)F9_N4n7d zl}TuK5+t-9|B)|H66gfI>P+Qf?;`lKKw& zl;j<6-km6=srWV!h_m2gtt9FZo@u!-JWwI0(k#a0ewnf7msTpR5|ClmuVO;5cw|Mt z5D&3xB6o}>9e*q!0}HgIqkuMht|bJF23U_;;W74)&ZA!n0-rxmMAruBOvpZZ9_~xY z65(q9b#Hr5N&5Peyv%+T3HM;6n22v8s>4M44q2qm5Ag8n{BT%$v+^2Fmt(TzYA=Qm z5u;rfUwt|ovXC8mRL|*Qu#c=k!A7WW&nhyf&r1oD5wB*ro(}A-5g<;REuCVU_O$|zlV_N3^*eu> z4QN+YK|f&UW~=q;XkvW#bT(~#N@Gm6k6^uo@d$I2^bO&#<6R^oDPMj?r+#a~*2MIP z{zwoz8yelJhHM^WTt>-c zD{CZiK>ZGQiI3oH5f7kAGE2Iar8A6N^syJB8Bg7O+)1qGTUx_N2C;klHQ?8T58}sJ z=|IYPn=c6;+_rs^XWzN&1;mMA->dG+A1dGF4l^I-Hz>TJyhj}r25u5mVBbHJd=kRL zb`6!iFZYBxFKk77cJ>*5d)Ayr_8R3i+b+@rhRPWTs7|pe+eT3z>zJ zk02TvfARiYa>YcZ+*lE8Tz1y#*9`89s9=F-wj|3h28NzQi-pc3WArMGR49LmSbbvE zCDEt!66Pk>R69pRk&}5d@)l^6J9YGpA4vUrr*CQ^#uF?=s|Xj&?qYx}xKEkSqpVC^lufI-oP19?%MFAhl=RP_`+7eZ`+RBlGc?7m()SjXJJ%~FIi@#GpyK8iLpRrIH?j@9<6G`Cv!OB# zT%)Y-=H*s0@M)Mg9G}J5m)Tm;6!P~Zf4<{TPa#KaWSSFlazGqx>1l1EF+dd}dygAB z;Gm?uM)#Ci-)3Q@;hri=p2-!OQ?QB8S$O)E(UsY=+h{u|V&?5A&0232t@506uFr8B zuo`%*_OHeA}qi{2&OSggT+W2e?- zAVqhxcwNpe6AxONm5GEKgx+IjMZ2&nTnd*>9J=VQz)E^4jIb(D|6Bk6TcerS01`F& TOOe3BiymU*C6i<(`aAvuixLQX diff --git a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java index fba7e4de778a..6748c0738622 100644 --- a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java +++ b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java @@ -33,6 +33,8 @@ public class SceneBuilderImpl implements SceneBuilder { myFileURL = url; myEditorCallback = editorCallback; + Platform.setImplicitExit(false); + Platform.runLater(new Runnable() { @Override public void run() { From 6cf7b4ab8930c6f5a8f8b16070e0495ca987ba5f Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 7 Feb 2014 22:23:54 +0400 Subject: [PATCH 25/53] JavaFX Scene Builder integration --- .../plugins/javaFX/sceneBuilder/SceneBuilderEditor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java index d102654d5a6d..ae36f912a177 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java @@ -170,6 +170,8 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor removeSceneBuilder(); try { + FileDocumentManager.getInstance().saveDocument(myDocument); + if (myFileURL == null) { myFileURL = new File(myFile.getPath()).toURI().toURL(); } @@ -188,6 +190,7 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor private void updateSceneBuilder() { if (mySceneBuilder != null) { + FileDocumentManager.getInstance().saveDocument(myDocument); mySceneBuilder.reloadFile(); } } From 5358bd270eb5a963c11167ca6365523d7a8d72b2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 19:09:29 +0100 Subject: [PATCH 26/53] new inference: testdata for IDEA-120376 --- .../lambda/newMethodRef/IDEA120376.java | 9 +++++++++ .../daemon/lambda/NewMethodRefHighlightingTest.java | 4 ++++ 2 files changed, 13 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java new file mode 100644 index 000000000000..822402fd0f64 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java @@ -0,0 +1,9 @@ +import java.util.Comparator; + +public class Test> { + Comparator> bySize = Comparator.comparingInt(Test::size); + + public int size() { + return 0; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 0a35bc2dbf4d..a716ed3f4b8e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -149,6 +149,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIDEA120376() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From a80cc8ea707b3857e34f6a60a7ef7419ae3449f6 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 19:36:05 +0100 Subject: [PATCH 27/53] spi files: do not override std file types (IDEA-120291) --- java/java-impl/src/com/intellij/spi/SPIFileType.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/spi/SPIFileType.java b/java/java-impl/src/com/intellij/spi/SPIFileType.java index 0d4a3bd8e474..507540460353 100644 --- a/java/java-impl/src/com/intellij/spi/SPIFileType.java +++ b/java/java-impl/src/com/intellij/spi/SPIFileType.java @@ -18,12 +18,13 @@ package com.intellij.spi; import com.intellij.icons.AllIcons; import com.intellij.lang.spi.SPILanguage; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.LanguageFileType; +import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -49,7 +50,7 @@ public class SPIFileType extends LanguageFileType implements FileTypeIdentifiabl for (Object condition : Extensions.getExtensions("com.intellij.vetoSPICondition")) { if (((Condition)condition).value(fileName)) return false; } - return true; + return FileTypeRegistry.getInstance().getFileTypeByFileName(fileName) == FileTypes.UNKNOWN; } } return false; From 91b0fd735521700a82edd5edd1ea8c5bde09ad74 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 19:45:32 +0100 Subject: [PATCH 28/53] invalid assertion for red code removed --- .../intellij/refactoring/typeMigration/TypeMigrationLabeler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java index 95b2f6bff69c..0542ff298dc6 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java @@ -475,7 +475,6 @@ public class TypeMigrationLabeler { return JavaPsiFacade.getElementFactory(resolved.getProject()).createType((PsiClass)resolved, PsiSubstitutor.EMPTY); } } - LOG.error("should not happen: " + resolved.getClass()); return null; } From f22cff3bfb04a6f81370eeed862852f2225249fd Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 19:50:52 +0100 Subject: [PATCH 29/53] presentation (IDEA-120353) --- .../refactoring/typeMigration/ui/TypeMigrationDialog.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java index 6ffaf333001d..3ba66bb0590e 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java @@ -257,6 +257,10 @@ public class TypeMigrationDialog extends RefactoringDialog { return "type of variable " + ((PsiLocalVariable)element).getName(); } + if (element instanceof PsiReferenceParameterList) { + return "class type arguments "; + } + if (element instanceof PsiParameter) { final PsiParameter param = (PsiParameter)element; String result = "type of parameter " + param.getName(); From 29b6eefac6f3819e1d97868fc3ca7877801d5156 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 21:14:26 +0100 Subject: [PATCH 30/53] static methods in interfaces should not have abstract by default --- .../src/com/intellij/psi/impl/source/PsiModifierListImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java index 7378569f99f0..925c0ee46543 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java @@ -130,7 +130,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement return false; } if (type == JavaTokenType.ABSTRACT_KEYWORD) { - return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null; + return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null && getNode().findChildByType(JavaTokenType.STATIC_KEYWORD) == null; } } } From d516dd3b1ce6a5d0db53e375c2f758cb7760fec2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 7 Feb 2014 21:16:38 +0100 Subject: [PATCH 31/53] pull up: support static methods and interfaces for java 8 --- .../memberPullUp/PullUpDialog.java | 22 +++++++++---------- .../refactoring/util/RefactoringUtil.java | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java index 0110c55d74bc..b92c5f52bfa9 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java @@ -180,11 +180,12 @@ public class PullUpDialog extends PullUpDialogBase Date: Fri, 7 Feb 2014 21:34:07 +0100 Subject: [PATCH 32/53] fix regress: invalidateIndices shouldn't schedule indexing for nonindexed files, many thanks for Peter.Gromov for help of finding the problem in review sessions --- .../util/indexing/FileBasedIndexImpl.java | 73 ++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 77cbac3719da..048c7599408b 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1698,8 +1698,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { //noinspection ForLoopReplaceableByForEach for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) { final ID indexId = affectedIndexCandidates.get(i); - if (myRequiringContentIndices.contains(indexId) && shouldIndexFile(file, indexId)) { - + if (shouldIndexFile(file, indexId)) { if (fc == null) { byte[] currentBytes; try { @@ -2066,9 +2065,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { IndexingStamp.removeAllIndexedState(file); } }); + // the file is for sure not a dir and it was previously indexed by at least one index + if (!isTooLarge(file)) scheduleForUpdate(file); } - // the file is for sure not a dir and it was previously indexed by at least one index - if (!isTooLarge(file)) scheduleForUpdate(file); } else { myFilesToUpdate.remove(file); @@ -2170,7 +2169,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } - public List getAllFilesToUpdate() { + public Collection getAllFilesToUpdate() { if (myFilesToUpdate.isEmpty()) { return Collections.emptyList(); } @@ -2200,50 +2199,34 @@ public class FileBasedIndexImpl extends FileBasedIndex { myUpdateSemaphoreRef.compareAndSet(semaphore, null); } - private static final int MAX_FILES_TO_PROCESS_OUTSIDE_SCOPE = 5; - private void forceUpdate(@Nullable Project project, @Nullable GlobalSearchScope filter, @Nullable VirtualFile restrictedTo, boolean onlyRemoveOutdatedData) { myChangedFilesCollector.ensureAllInvalidateTasksCompleted(); ProjectIndexableFilesFilter indexableFilesFilter = projectIndexableFiles(project); - int filesProcessedOutsideScope = 0; UpdateSemaphore updateSemaphore; do{ updateSemaphore = obtainForceUpdateSemaphore(); try { - List filesToUpdate = getAllFilesToUpdate(); - - //noinspection ForLoopReplaceableByForEach - for (int i = 0, size = filesToUpdate.size(); i < size; ++i) { - VirtualFile file = filesToUpdate.get(i); - - if ((indexableFilesFilter != null && // project files filtering - file instanceof VirtualFileWithId && - !indexableFilesFilter.containsFileId(((VirtualFileWithId)file).getId()) - ) || - filter != null && !filter.accept(file) || - restrictedTo != null && restrictedTo != file - ) { - if (filesProcessedOutsideScope >= MAX_FILES_TO_PROCESS_OUTSIDE_SCOPE) continue; - - // In order to have myFilesToUpdate empty for avoiding contention on scanning large concurrent set - // we need eventually to process all files in it including the ones that do not belong to any project or current scope - // e.g. the files that have vfs built but avoided due to project / scope exclusion: workspace.xml / files under .git / user home / etc - ++filesProcessedOutsideScope; + for (VirtualFile file : getAllFilesToUpdate()) { + if (indexableFilesFilter != null && file instanceof VirtualFileWithId && !indexableFilesFilter.containsFileId( + ((VirtualFileWithId)file).getId())) { + continue; } - - try { - updateSemaphore.down(); - // process only files that can affect result - processFileImpl(project, new com.intellij.ide.caches.FileContent(file), onlyRemoveOutdatedData); + + if (filter == null || filter.accept(file) || Comparing.equal(file, restrictedTo)) { + try { + updateSemaphore.down(); + // process only files that can affect result + processFileImpl(project, new com.intellij.ide.caches.FileContent(file), onlyRemoveOutdatedData); + } + catch (ProcessCanceledException e) { + updateSemaphore.reportUpdateCanceled(); + throw e; + } + finally { + updateSemaphore.up(); + } } - catch (ProcessCanceledException e) { - updateSemaphore.reportUpdateCanceled(); - throw e; - } - finally { - updateSemaphore.up(); - } } // If several threads entered the method at the same time and there were files to update, @@ -2464,11 +2447,17 @@ public class FileBasedIndexImpl extends FileBasedIndex { if (file != null) { VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile instanceof VirtualFileWithId) { + boolean wasIndexed = false; for(ID psiBackedIndex:myPsiDependentIndices) { - IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2); + if (isFileIndexed(virtualFile, psiBackedIndex)) { + IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2); + wasIndexed = true; + } + } + if (wasIndexed) { + myChangedFilesCollector.scheduleForUpdate(virtualFile); + IndexingStamp.flushCache(virtualFile); } - myChangedFilesCollector.scheduleForUpdate(virtualFile); - IndexingStamp.flushCache(virtualFile); } } } From db734f342561f4256e4a1966e48e6978e1e8baf1 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 7 Feb 2014 22:48:29 +0100 Subject: [PATCH 33/53] this is mostly revert of my last year commit 101e4e4 from 27.03.13 because the change introduced deadlock (IDEA-118827) since clearing stub index needs write lock and we can have read lock already from processingStubs. The reverted change introduced better handling of index corruption: do clearIndex at checkRebuild directly. In current code we only advance index version from checkRebuild and proceed with clear index later on edt (with progress) as it was before. --- .../util/indexing/FileBasedIndexImpl.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 048c7599408b..fa8116701846 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1322,20 +1322,21 @@ public class FileBasedIndexImpl extends FileBasedIndex { if (status.compareAndSet(REQUIRES_REBUILD, REBUILD_IN_PROGRESS)) { cleanupProcessedFlag(); - try { - clearIndex(indexId); - } catch (StorageException ex) { - requestRebuild(indexId, new Throwable(ex)); - } - + advanceIndexVersion(indexId); + final Runnable rebuildRunnable = new Runnable() { @Override public void run() { try { + doClearIndex(indexId); if (!cleanupOnly) { scheduleIndexRebuild(false); } } + catch (StorageException e) { + requestRebuild(indexId); + LOG.info(e); + } finally { status.compareAndSet(REBUILD_IN_PROGRESS, OK); } @@ -1381,9 +1382,17 @@ public class FileBasedIndexImpl extends FileBasedIndex { } private void clearIndex(@NotNull final ID indexId) throws StorageException { + advanceIndexVersion(indexId); + doClearIndex(indexId); + } + + private void doClearIndex(ID indexId) throws StorageException { final UpdatableIndex index = getIndex(indexId); assert index != null : "Index with key " + indexId + " not found or not registered properly"; index.clear(); + } + + private void advanceIndexVersion(ID indexId) { try { IndexInfrastructure.rewriteVersion(IndexInfrastructure.getVersionFile(indexId), myIndexIdToVersionMap.get(indexId)); } From 05bb24eb443905e5fe7f54e94a9383b2a9f36a3c Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Sat, 8 Feb 2014 11:29:21 +0400 Subject: [PATCH 34/53] WEB-10858 File Watchers plugin doesn't work http://youtrack.jetbrains.com/issue/WEB-10858#comment=27-672181 --- .../configurations/EncodingEnvironmentUtil.java | 4 +--- .../configurations/GeneralCommandLine.java | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java b/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java index 79fff54a9a7f..9983a6c216e5 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java @@ -22,7 +22,6 @@ import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.util.EnvironmentUtil; -import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -73,8 +72,7 @@ public class EncodingEnvironmentUtil { } if (commandLine.isPassParentEnvironment()) { // 'parentEnv' calculation logic should be kept in sync with GeneralCommandLine.setupEnvironment - Map parentEnv = PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606 - : EnvironmentUtil.getEnvironmentMap(); + Map parentEnv = commandLine.isPassShellEnvironmentAsParent() ? EnvironmentUtil.getEnvironmentMap() : System.getenv(); if (isLocaleDefined(parentEnv)) { return true; } diff --git a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java index a42a1bfab18a..893a548d262d 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java @@ -58,6 +58,7 @@ public class GeneralCommandLine implements UserDataHolder { private File myWorkDirectory = null; private final Map myEnvParams = new MyTHashMap(); private boolean myPassParentEnvironment = true; + private boolean myPassShellEnvironmentAsParent = !PlatformUtils.isAppCode(); private final ParametersList myProgramParams = new ParametersList(); private Charset myCharset = CharsetToolkit.getDefaultSystemCharset(); private boolean myRedirectErrorStream = false; @@ -142,6 +143,19 @@ public class GeneralCommandLine implements UserDataHolder { return myPassParentEnvironment; } + /** + * @param passShellEnvironmentAsParent if true, a shell (Terminal.app) environment will be used as parent (see {@link EnvironmentUtil#getEnvironmentMap}). + * Otherwise, {@link System#getenv()} will be used. + */ + public void setPassShellEnvironmentAsParent(boolean passShellEnvironmentAsParent) { + // Temporarily fix for OC-8606 + myPassShellEnvironmentAsParent = passShellEnvironmentAsParent; + } + + public boolean isPassShellEnvironmentAsParent() { + return myPassShellEnvironmentAsParent; + } + public void addParameters(final String... parameters) { for (String parameter : parameters) { addParameter(parameter); @@ -278,8 +292,7 @@ public class GeneralCommandLine implements UserDataHolder { environment.clear(); if (myPassParentEnvironment) { - environment.putAll(PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606 - : EnvironmentUtil.getEnvironmentMap()); + environment.putAll(myPassShellEnvironmentAsParent ? EnvironmentUtil.getEnvironmentMap() : System.getenv()); } if (!myEnvParams.isEmpty()) { From aac150d6168e9b1e7850378128234b7332dd7278 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Sun, 9 Feb 2014 11:19:52 +0100 Subject: [PATCH 35/53] Fix a typo (PY-12077). --- .../ImportFromToImportIntention/description.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html b/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html index 96be99018b8f..63818e399ca3 100644 --- a/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html +++ b/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html @@ -1,7 +1,7 @@ -This instenton transforms from module_name import ... into import module_name +This intention transforms from module_name import ... into import module_name and qualifies any names imported from that module by module name. From 7318d5d0a6ae44dfd979caaf595340ad83dc202d Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Mon, 10 Feb 2014 01:08:33 +0400 Subject: [PATCH 36/53] load installed packages in a background thread --- .../packaging/ManagePackagesDialog.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java index 07f5477b6d15..184b2331f1d0 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java @@ -275,16 +275,26 @@ public class ManagePackagesDialog extends DialogWrapper { } private void updateInstalledPackages() { - try { - Collection installedPackages = myController.getInstalledPackages(); - myInstalledPackages.clear(); - for (InstalledPackage pkg : installedPackages) { - myInstalledPackages.add(pkg.getName()); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + try { + final Collection installedPackages = myController.getInstalledPackages(); + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + myInstalledPackages.clear(); + for (InstalledPackage pkg : installedPackages) { + myInstalledPackages.add(pkg.getName()); + } + } + }); + } + catch(IOException e) { + LOG.info("Error updating list of installed packages:" + e); + } } - } - catch(IOException e) { - LOG.info("Error updating list of installed packages:" + e); - } + }); } public void initModel() { From a4a7cd5af7e16e2a0338a94a15aa7dcbf7528900 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 7 Feb 2014 13:00:16 +0400 Subject: [PATCH 37/53] cleanup default option searching --- .../groovy/console/GroovyShellActionBase.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java index 8a80bb209d69..560f299f8795 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -45,8 +45,10 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.ContainerUtil; import icons.JetgroovyIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl; @@ -157,13 +159,19 @@ public abstract class GroovyShellActionBase extends DumbAwareAction { } }; - for (int i = 0; i < modules.size(); i++) { - Module module = modules.get(i); - if (module.getName().equals(PropertiesComponent.getInstance(project).getValue(GROOVY_SHELL_LAST_MODULE))) { - step.setDefaultOptionIndex(i); - break; + final String lastModuleName = PropertiesComponent.getInstance(project).getValue(GROOVY_SHELL_LAST_MODULE); + if (lastModuleName != null) { + int defaultOption = ContainerUtil.indexOf(modules, new Condition() { + @Override + public boolean value(Module module) { + return module.getName().equals(lastModuleName); + } + }); + if (defaultOption >= 0) { + step.setDefaultOptionIndex(defaultOption); } } + JBPopupFactory.getInstance().createListPopup(step).showCenteredInCurrentWindow(project); } From d9c547ac6391590e6004c5bd511f2e960f9da51b Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 7 Feb 2014 13:08:39 +0400 Subject: [PATCH 38/53] Groovy ControlFlowBuilder: make some fields final --- .../controlFlow/impl/ControlFlowBuilder.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index ba021f44354f..498d753cf352 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -60,9 +60,10 @@ import static org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariabl */ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { private static final Logger LOG = Logger.getInstance(ControlFlowBuilder.class); - private List myInstructions; - private Deque myProcessingStack; + private final List myInstructions = new ArrayList(); + + private final Deque myProcessingStack = new ArrayDeque(); private final PsiConstantEvaluationHelper myConstantEvaluator; private GroovyPsiElement myScope; @@ -70,12 +71,12 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { /** * stack of current catch blocks */ - private Deque myCaughtExceptionInfos; + private final Deque myCaughtExceptionInfos = new ArrayDeque(); /** * stack of current conditions */ - private Deque myConditions; + private final Deque myConditions = new ArrayDeque(); /** @@ -91,7 +92,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { /** * list of pending nodes and corresponding scopes sorted by scopes from the biggest to smallest. */ - private List> myPending; + private List> myPending = new ArrayList>(); private int myInstructionNumber; private final GrControlFlowPolicy myPolicy; @@ -144,13 +145,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { } public Instruction[] buildControlFlow(GroovyPsiElement scope) { - myInstructions = new ArrayList(); - myProcessingStack = new ArrayDeque(); - myCaughtExceptionInfos = new ArrayDeque(); - myConditions = new ArrayDeque(); - myFinallyCount = 0; - myPending = new ArrayList>(); myInstructionNumber = 0; myScope = scope; From c2e137a60c118d4c1a46164f63e7ff378febf356 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 7 Feb 2014 13:14:33 +0400 Subject: [PATCH 39/53] Groovy ControlFlowBuilder: additional logging --- .../groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 498d753cf352..2934d093bfa3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -1120,7 +1120,9 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { private void finishNode(InstructionImpl instruction) { final InstructionImpl popped = myProcessingStack.pop(); if (!instruction.equals(popped)) { - String description = "popped: " + popped.toString() + " : " + popped.hashCode() + " , expected: " + instruction.toString() + " : " + instruction.hashCode(); + String description = "popped: " + popped.toString() + " : " + popped.hashCode() + + " , expected: " + instruction.toString() + " : " + instruction.hashCode() + + "same objects:" + (popped == instruction); error(description); } } From 48f76aeaa7aca185dfeed02e86ce161532750374 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 7 Feb 2014 14:33:57 +0400 Subject: [PATCH 40/53] EA-49782 - assert: TextRange. --- .../groovy/intentions/base/Intention.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java index 7f3b107db3df..103546f82e63 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -90,12 +90,16 @@ public abstract class Intention implements IntentionAction { SelectionModel selectionModel = editor.getSelectionModel(); if (selectionModel.hasSelection() && !selectionModel.hasBlockSelection()) { - TextRange selectionRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - PsiElement element = GroovyRefactoringUtil - .findElementInRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), PsiElement.class); - while (element != null && element.getTextRange() != null && selectionRange.contains(element.getTextRange())) { - if (predicate.satisfiedBy(element)) return element; - element = element.getParent(); + int start = selectionModel.getSelectionStart(); + int end = selectionModel.getSelectionEnd(); + + if (0 <= start && start <= end) { + TextRange selectionRange = new TextRange(start, end); + PsiElement element = GroovyRefactoringUtil.findElementInRange(file, start, end, PsiElement.class); + while (element != null && element.getTextRange() != null && selectionRange.contains(element.getTextRange())) { + if (predicate.satisfiedBy(element)) return element; + element = element.getParent(); + } } } From f3a4b5f7ee464ba20ddcb17a777f001ac596ae6f Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 7 Feb 2014 17:29:06 +0400 Subject: [PATCH 41/53] Groovy: in-place introduce field from local var --- .../field/GrIntroduceFieldProcessor.java | 41 +++++++++++-------- .../field/GrIntroduceFieldTest.groovy | 19 ++++++++- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java index 742c7cde76a7..d48ad50d2bbf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java @@ -125,26 +125,35 @@ public class GrIntroduceFieldProcessor { updateCaretPosition(occurrence); return Collections.singletonList(occurrence); } - else { - if (mySettings.replaceAllOccurrences()) { - GroovyRefactoringUtil.sortOccurrences(myContext.getOccurrences()); - ArrayList result = ContainerUtil.newArrayList(); - for (PsiElement occurrence : myContext.getOccurrences()) { - result.add(replaceOccurrence(field, occurrence, targetClass)); - } - return result; + + if (mySettings.replaceAllOccurrences()) { + GroovyRefactoringUtil.sortOccurrences(myContext.getOccurrences()); + ArrayList result = ContainerUtil.newArrayList(); + for (PsiElement occurrence : myContext.getOccurrences()) { + result.add(replaceOccurrence(field, occurrence, targetClass)); + } + return result; + } + + GrVariable var = myContext.getVar(); + if (var != null) { + GrExpression initializer = var.getInitializerGroovy(); + if (initializer != null) { + return Collections.singletonList(replaceOccurrence(field, initializer, targetClass)); } else { - final GrExpression expression = myContext.getExpression(); - assert expression != null; - if (PsiUtil.isExpressionStatement(expression)) { - return Collections.singletonList(expression); - } - else { - return Collections.singletonList(replaceOccurrence(field, expression, targetClass)); - } + return Collections.emptyList(); } } + + final GrExpression expression = myContext.getExpression(); + assert expression != null; + if (PsiUtil.isExpressionStatement(expression)) { + return Collections.singletonList(expression); + } + else { + return Collections.singletonList(replaceOccurrence(field, expression, targetClass)); + } } private void updateCaretPosition(@NotNull PsiElement occurrence) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy index 911f3a4118ab..945eb1fd6287 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -328,6 +328,23 @@ class A { ''', false, false, false, CUR_METHOD, false, null) } + void testFromVar() { + doTest('''\ +class A { + def foo() { + def a = 5 + print a + } +}''', '''\ +class A { + def f = 5 + + def foo() { + print f + } +}''', false, true, false, FIELD_DECLARATION, true, null) + } + private void doTest(final boolean isStatic, final boolean removeLocal, From edfbd5e99fd049a00bfd49d67ff6938e5997865d Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Sat, 8 Feb 2014 19:30:21 +0400 Subject: [PATCH 42/53] Groovy: in-place introduce from variable always process all occurrences --- .../refactoring/introduce/GrAbstractInplaceIntroducer.java | 4 ++-- .../groovy/refactoring/introduce/GrIntroduceHandlerBase.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java index 9d9fe9e3595d..92b036892266 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -262,7 +262,7 @@ public abstract class GrAbstractInplaceIntroducersingletonList(context.getStringPart())); + return map; } else if (context.getVar() != null) { - map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(context.getVar())); + map.put(OccurrencesChooser.ReplaceChoice.ALL, Collections.singletonList(context.getVar())); + return map; } PsiElement[] occurrences = context.getOccurrences(); From ec8c847972f36a0c59eb30d87cd62b6b8b014ff5 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Sun, 9 Feb 2014 15:27:17 +0400 Subject: [PATCH 43/53] Groovy: introduce parameter from local variable (both in-place and via dialog) --- .../extract/ExtractInfoHelper.java | 6 +- .../extract/ExtractInfoHelperBase.java | 9 +- .../extract/GroovyExtractChooser.java | 39 ++- .../refactoring/extract/InitialInfo.java | 13 +- .../closure/ExtractClosureHelperImpl.java | 4 +- .../closure/ExtractClosureProcessorBase.java | 5 +- .../introduce/GrIntroduceHandlerBase.java | 28 ++- .../refactoring/introduce/StringPartInfo.java | 1 + .../field/GrIntroduceFieldHandler.java | 2 +- .../parameter/GrExpressionWrapper.java | 4 +- .../GrInplaceParameterIntroducer.java | 227 ++++++++---------- .../GrIntroduceClosureParameterProcessor.java | 2 +- .../GrIntroduceExpressionSettingsImpl.java | 9 +- .../parameter/GrIntroduceParameterDialog.java | 25 +- .../GrIntroduceParameterHandler.java | 146 +++-------- .../GrIntroduceParameterProcessor.java | 21 +- .../GroovyIntroduceParameterUtil.java | 5 +- .../GrIntroduceParameterTest.groovy | 79 +++--- 18 files changed, 299 insertions(+), 326 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java index fde920e2f6f0..85c40082b977 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -21,6 +21,7 @@ import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; @@ -52,6 +53,9 @@ public interface ExtractInfoHelper { @Nullable StringPartInfo getStringPartInfo(); + @Nullable + GrVariable getVar(); + boolean hasReturnValue(); String getName(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java index 24a8cd889b88..67f548774a07 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -21,6 +21,7 @@ import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; @@ -113,6 +114,12 @@ public abstract class ExtractInfoHelperBase implements ExtractInfoHelper { return myInitialInfo.getStringPartInfo(); } + @Nullable + @Override + public GrVariable getVar() { + return myInitialInfo.getVar(); + } + public boolean hasReturnValue() { return myInitialInfo.hasReturnValue(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java index 6e61c36b3d23..237562151bf7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -19,18 +19,22 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; @@ -78,18 +82,35 @@ public class GroovyExtractChooser { SelectionModel selectionModel = editor.getSelectionModel(); PsiDocumentManager.getInstance(project).commitAllDocuments(); - final StringPartInfo stringPart = - StringPartInfo.findStringPart(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - + final StringPartInfo stringPart = StringPartInfo.findStringPart(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); if (stringPart != null) { - return new InitialInfo(new VariableInfo[0], new VariableInfo[0], PsiElement.EMPTY_ARRAY, GrStatement.EMPTY_ARRAY, new ArrayList(), stringPart, project); + return new InitialInfo(new VariableInfo[0], new VariableInfo[0], PsiElement.EMPTY_ARRAY, GrStatement.EMPTY_ARRAY, new ArrayList(), stringPart, project, null); } + GrVariable variable = GrIntroduceHandlerBase.findVariable(file, start, end); + if (variable != null) { + GrExpression initializer = variable.getInitializerGroovy(); + if (initializer != null) { + TextRange range = initializer.getTextRange(); + return buildInfo(project, file, range.getStartOffset(), range.getEndOffset(), forceStatements, selectionModel, variable); + } + } + return buildInfo(project, file, start, end, forceStatements, selectionModel, null); + } + + @NotNull + private static InitialInfo buildInfo(@NotNull Project project, + @NotNull PsiFile file, + int start, + int end, + boolean forceStatements, + @NotNull SelectionModel selectionModel, + @Nullable GrVariable variable) throws GrRefactoringError { PsiElement[] elements = getElementsInOffset(file, start, end, forceStatements); - if (elements.length == 1 && elements[0] instanceof GrExpression) { - selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset()); - } + //if (elements.length == 1 && elements[0] instanceof GrExpression) { + // selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset()); + //} GrStatement[] statements = getStatementsByElements(elements); @@ -171,7 +192,7 @@ public class GroovyExtractChooser { GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow")); } - return new InitialInfo(inputInfos, outputInfos, elements, statements, returnStatements, null, project); + return new InitialInfo(inputInfos, outputInfos, elements, statements, returnStatements, null, project, variable); } private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java index e50e6d5ed0d1..896f1e2eb0cc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -25,6 +25,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; @@ -47,6 +48,7 @@ public class InitialInfo implements ExtractInfoHelper { private final boolean myHasReturnValue; private final String[] myArgumentNames; private final StringPartInfo myStringPartInfo; + private final GrVariable myVariable; public InitialInfo(VariableInfo[] inputInfos, VariableInfo[] outputInfos, @@ -54,11 +56,12 @@ public class InitialInfo implements ExtractInfoHelper { GrStatement[] statements, ArrayList returnStatements, StringPartInfo stringPartInfo, - Project project) { + Project project, GrVariable variable) { myInnerElements = innerElements; myStatements = statements; myOutputNames = outputInfos; myStringPartInfo = stringPartInfo; + myVariable = variable; myHasReturnValue = ContainerUtil.find(returnStatements, new Condition() { @Override @@ -194,4 +197,10 @@ public class InitialInfo implements ExtractInfoHelper { public StringPartInfo getStringPartInfo() { return myStringPartInfo; } + + @Nullable + @Override + public GrVariable getVar() { + return myVariable; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java index d417859edf3a..7b7f9eacf3a5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; @@ -135,6 +136,7 @@ public class ExtractClosureHelperImpl extends ExtractInfoHelperBase implements G return myForceReturn; } + @Nullable @Override public GrVariable getVar() { return null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java index 7359fc08fd15..07ed028704f7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -60,7 +60,8 @@ public abstract class ExtractClosureProcessorBase extends BaseRefactoringProcess return EXTRACT_CLOSURE; } - public static GrClosableBlock generateClosure(GrIntroduceParameterSettings helper) { + @NotNull + public static GrClosableBlock generateClosure(@NotNull GrIntroduceParameterSettings helper) { StringBuilder buffer = new StringBuilder(); buffer.append("{ "); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index c80c447ceddd..be5c2d61bfb4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -439,18 +439,7 @@ public abstract class GrIntroduceHandlerBase list = Collections.synchronizedList(new ArrayList()); - ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { - @Override - public boolean process(PsiReference psiReference) { - final PsiElement element = psiReference.getElement(); - if (element != null) { - list.add(element); - } - return true; - } - }); - final PsiElement[] occurrences = list.toArray(new PsiElement[list.size()]); + final PsiElement[] occurrences = collectVariableUsages(variable, scope); return new GrIntroduceContextImpl(project, editor, null, variable, stringPart, occurrences, scope); } else if (expression != null ) { @@ -463,6 +452,21 @@ public abstract class GrIntroduceHandlerBase list = Collections.synchronizedList(new ArrayList()); + ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { + @Override + public boolean process(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + if (element != null) { + list.add(element); + } + return true; + } + }); + return list.toArray(new PsiElement[list.size()]); + } + private boolean invokeImpl(final Project project, final GrIntroduceContext context, final Editor editor) { try { if (!CommonRefactoringUtil.checkReadOnlyStatus(project, context.getOccurrences())) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java index 36ff8b45280d..d37f5bad5a5a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java @@ -282,6 +282,7 @@ public class StringPartInfo { return myInjections; } + @NotNull public GrLiteral createLiteralFromSelected() { return (GrLiteral)GroovyPsiElementFactory.getInstance(myLiteral.getProject()).createExpressionFromText(prepareSelected()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index f100448e4255..849cac3ae08a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java index 4bb4ee85ffd3..99ea5a7f84ac 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -34,7 +34,7 @@ public class GrExpressionWrapper implements IntroduceParameterData.ExpressionWra private final RangeMarker myMarker; private final PsiFile myFile; - public GrExpressionWrapper(GrExpression expression) { + public GrExpressionWrapper(@NotNull GrExpression expression) { assert expression.isValid(); myExpression = expression; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java index 26c00354833e..b9595d04a59d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -18,132 +18,85 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; import com.intellij.codeInsight.template.TextResult; import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.codeInsight.template.impl.TemplateState; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.EditorSettings; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.MarkupModel; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.PsiType; import com.intellij.refactoring.IntroduceParameterRefactoring; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.rename.inplace.InplaceRefactoring; -import com.intellij.ui.DottedBorder; import com.intellij.ui.JBColor; import com.intellij.ui.components.JBCheckBox; +import com.intellij.usageView.UsageInfo; import com.intellij.util.ArrayUtil; import gnu.trove.TIntArrayList; -import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import javax.swing.*; import javax.swing.border.EmptyBorder; -import javax.swing.border.LineBorder; import java.awt.*; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; +import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.findParametersToRemove; + /** * Created by Max Medvedev on 9/1/13 */ -public class GrInplaceParameterIntroducer extends GrInplaceIntroducer { - private final JPanel myPanel; - private EditorEx myPreview; +public class GrInplaceParameterIntroducer extends GrAbstractInplaceIntroducer { + private final IntroduceParameterInfo myInfo; + private final TIntArrayList myParametersToRemove; - private JComponent myPreviewComponent; private JBCheckBox myDelegateCB; - private GrIntroduceParameterSettings mySettings; - private final GrExpressionWrapper myExpr; + private LinkedHashSet mySuggestedNames; - public GrInplaceParameterIntroducer(@NotNull GrVariable elementToRename, - @NotNull Editor editor, - @NotNull Project project, - @NotNull String title, - @NotNull List occurrences, - @Nullable PsiElement elementToIntroduce, - GrIntroduceParameterSettings settings, - GrExpressionWrapper expr) { - super(elementToRename, editor, project, title, occurrences, elementToIntroduce); + public GrInplaceParameterIntroducer(IntroduceParameterInfo info, GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + super(GrIntroduceParameterHandler.REFACTORING_NAME, choice, context); + myInfo = info; - mySettings = settings; - - initPreview(project); - - myDelegateCB = new JBCheckBox("Delegate via overloading method"); - myDelegateCB.setMnemonic('l'); - myDelegateCB.setFocusable(false); - - myPanel = new JPanel(new BorderLayout()); - myPanel.add(myPreviewComponent, BorderLayout.CENTER); - myPanel.add(myDelegateCB, BorderLayout.SOUTH); - - myExpr = expr; + GrVariable localVar = GrIntroduceHandlerBase.resolveLocalVar(context); + mySuggestedNames = GroovyIntroduceParameterUtil.suggestNames(localVar, context.getExpression(), context.getStringPart(), info.getToReplaceIn(), context.getProject()); + myParametersToRemove = new TIntArrayList(findParametersToRemove(info).getValues()); } - protected final void setPreviewText(final String text) { - if (myPreview == null) return; //already disposed - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - myPreview.getDocument().replaceString(0, myPreview.getDocument().getTextLength(), text); - } - }); + @Override + protected String getActionName() { + return GrIntroduceParameterHandler.REFACTORING_NAME; } + @Override + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return ArrayUtil.toStringArray(mySuggestedNames); + } - private void initPreview(Project project) { - myPreview = (EditorEx)EditorFactory.getInstance() - .createEditor(EditorFactory.getInstance().createDocument(""), project, GroovyFileType.GROOVY_FILE_TYPE, true); - myPreview.setOneLineMode(true); - final EditorSettings settings = myPreview.getSettings(); - settings.setAdditionalLinesCount(0); - settings.setAdditionalColumnsCount(1); - settings.setRightMarginShown(false); - settings.setFoldingOutlineShown(false); - settings.setLineNumbersShown(false); - settings.setLineMarkerAreaShown(false); - settings.setIndentGuidesShown(false); - settings.setVirtualSpace(false); - myPreview.setHorizontalScrollbarVisible(false); - myPreview.setVerticalScrollbarVisible(false); - myPreview.setCaretEnabled(false); - settings.setLineCursorWidth(1); + @Override + protected JComponent getComponent() { - final Color bg = myPreview.getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); - myPreview.setBackgroundColor(bg); - myPreview.setBorder(BorderFactory.createCompoundBorder(new DottedBorder(JBColor.GRAY), new LineBorder(bg, 2))); - - myPreviewComponent = new JPanel(new BorderLayout()); - myPreviewComponent.add(myPreview.getComponent(), BorderLayout.CENTER); - myPreviewComponent.setBorder(new EmptyBorder(2, 2, 6, 2)); + JPanel previewPanel = new JPanel(new BorderLayout()); + previewPanel.add(getPreviewEditor().getComponent(), BorderLayout.CENTER); + previewPanel.setBorder(new EmptyBorder(2, 2, 6, 2)); DocumentAdapter documentAdapter = new DocumentAdapter() { @Override public void documentChanged(DocumentEvent e) { - if (myPreview == null) return; final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor); if (templateState != null) { final TextResult value = templateState.getVariableValue(InplaceRefactoring.PRIMARY_VARIABLE_NAME); @@ -155,59 +108,29 @@ public class GrInplaceParameterIntroducer extends GrInplaceIntroducer { }; myEditor.getDocument().addDocumentListener(documentAdapter); - updateTitle(getVariable(), getVariable().getName()); + myDelegateCB = new JBCheckBox("Delegate via overloading method"); + myDelegateCB.setMnemonic('l'); + myDelegateCB.setFocusable(false); + + JPanel panel = new JPanel(new BorderLayout()); + panel.add(previewPanel, BorderLayout.CENTER); + panel.add(myDelegateCB, BorderLayout.SOUTH); + return panel; } @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return GroovyIntroduceParameterUtil.suggestNames(null, myExpr.getExpression(), null, (GrParametersOwner)context.getScope(), context.getProject()); + protected void saveSettings(@NotNull GrVariable variable) { + } - static LinkedHashSet suggestNames(GrIntroduceContext context, GrParametersOwner scope) { - return GroovyIntroduceParameterUtil.suggestNames(context.getVar(), context.getExpression(), context.getStringPart(), scope, context.getProject()); - } - - @Override - protected void moveOffsetAfter(boolean success) { - if (success) { - final GrVariable parameter = getVariable(); - GrIntroduceParameterSettings settings = generateSettings((GrParameter)parameter, mySettings, myDelegateCB.isSelected()); - assert parameter != null; - parameter.delete(); - GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(settings, myExpr); - processor.run(); - } - - - super.moveOffsetAfter(success); - } - - public GrIntroduceParameterSettings generateSettings(GrParameter parameter, IntroduceParameterInfo info, boolean delegate) { - - TObjectIntHashMap toRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info); - TIntArrayList removeList = new TIntArrayList(delegate ? ArrayUtil.EMPTY_INT_ARRAY: toRemove.getValues()); - - GrExpression _expr = myExpr.getExpression(); - GrVariable _var = GroovyIntroduceParameterUtil.findVar(info); - return new GrIntroduceExpressionSettingsImpl(info, parameter.getName(), false, removeList, myDelegateCB.isSelected(), - IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, _expr, _var, - parameter.getType(), false, false); - } - - @Override - protected JComponent getComponent() { - updateTitle(getVariable()); - return myPanel; - } - - - protected void updateTitle(@Nullable PsiVariable variable) { + protected void updateTitle(@Nullable GrVariable variable) { if (variable == null) return; updateTitle(variable, variable.getName()); } - protected void updateTitle(@Nullable final PsiVariable variable, final String value) { - final PsiElement declarationScope = variable != null ? ((PsiParameter)variable).getDeclarationScope() : null; + protected void updateTitle(@Nullable GrVariable variable, String value) { + if (getPreviewEditor() == null || variable == null) return; + final PsiElement declarationScope = ((PsiParameter)variable).getDeclarationScope(); if (declarationScope instanceof PsiMethod) { final PsiMethod psiMethod = (PsiMethod)declarationScope; final StringBuilder buf = new StringBuilder(); @@ -233,15 +156,17 @@ public class GrInplaceParameterIntroducer extends GrInplaceIntroducer { if (variable == parameter) { addedRange = new TextRange(startOffset, endOffset); } - else if (mySettings.parametersToRemove().contains(i)) { + else if (myParametersToRemove.contains(i)) { ranges2Remove.add(new TextRange(startOffset, endOffset)); } i++; } + assert addedRange != null; + buf.append(")"); setPreviewText(buf.toString()); - final MarkupModel markupModel = DocumentMarkupModel.forDocument(myPreview.getDocument(), myProject, true); + final MarkupModel markupModel = DocumentMarkupModel.forDocument(getPreviewEditor().getDocument(), myProject, true); markupModel.removeAllHighlighters(); for (TextRange textRange : ranges2Remove) { markupModel.addRangeHighlighter(textRange.getStartOffset(), textRange.getEndOffset(), 0, getTestAttributesForRemoval(), HighlighterTargetArea.EXACT_RANGE); @@ -261,7 +186,61 @@ public class GrInplaceParameterIntroducer extends GrInplaceIntroducer { private static TextAttributes getTestAttributesForRemoval() { final TextAttributes textAttributes = new TextAttributes(); textAttributes.setEffectType(EffectType.STRIKEOUT); - textAttributes.setEffectColor(Color.BLACK); + textAttributes.setEffectColor(JBColor.BLACK); return textAttributes; } + + @Override + protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceParameterSettings settings, boolean processUsages) { + GrExpressionWrapper wrapper = createExpressionWrapper(context); + if (processUsages) { + GrIntroduceExpressionSettingsImpl patchedSettings = + new GrIntroduceExpressionSettingsImpl(settings, settings.getName(), settings.declareFinal(), settings.parametersToRemove(), + settings.generateDelegate(), settings.replaceFieldsWithGetters(), context.getExpression(), + context.getVar(), settings.getSelectedType(), context.getVar() != null || settings.replaceAllOccurrences(), + context.getVar() != null, settings.isForceReturn()); + GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(patchedSettings, wrapper); + processor.run(); + } + else { + GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(settings, wrapper); + processor.performRefactoring(UsageInfo.EMPTY_ARRAY); + } + GrParametersOwner owner = settings.getToReplaceIn(); + return ArrayUtil.getLastElement(owner.getParameters()); + } + + @NotNull + private static GrExpressionWrapper createExpressionWrapper(@NotNull GrIntroduceContext context) { + GrExpression expression = context.getExpression(); + GrVariable var = context.getVar(); + assert expression != null || var != null ; + + GrExpression initializer = expression != null ? expression : var.getInitializerGroovy(); + return new GrExpressionWrapper(initializer); + } + + @Nullable + @Override + protected GrIntroduceParameterSettings getInitialSettingsForInplace(@NotNull GrIntroduceContext context, + @NotNull OccurrencesChooser.ReplaceChoice choice, + String[] names) { + GrExpression expression = context.getExpression(); + GrVariable var = context.getVar(); + PsiType type = var != null ? var.getDeclaredType() : + expression != null ? expression.getType() : + null; + + return new GrIntroduceExpressionSettingsImpl(myInfo, names[0], false, myParametersToRemove, false, + IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, expression, + var, type, false, false, false); + + } + + @Override + protected GrIntroduceParameterSettings getSettings() { + return new GrIntroduceExpressionSettingsImpl(myInfo, getInputName(), false, myParametersToRemove, myDelegateCB.isSelected(), + IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, null, + null, getSelectedType(), isReplaceAllOccurrences(), false, false); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java index 70c5ac6d7f9e..84389a632249 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java @@ -92,7 +92,7 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess private GrExpressionWrapper myParameterInitializer; private GroovyPsiElementFactory myFactory = GroovyPsiElementFactory.getInstance(myProject); - public GrIntroduceClosureParameterProcessor(GrIntroduceParameterSettings settings) { + public GrIntroduceClosureParameterProcessor(@NotNull GrIntroduceParameterSettings settings) { super(settings.getProject(), null); mySettings = settings; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java index e0c42410caf7..3113473a7d95 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -31,6 +31,7 @@ public class GrIntroduceExpressionSettingsImpl extends ExtractClosureHelperImpl private final GrExpression myExpr; private final GrVariable myVar; private final PsiType mySelectedType; + private final boolean myRemoveLocalVar; public GrIntroduceExpressionSettingsImpl(IntroduceParameterInfo info, String name, @@ -44,11 +45,13 @@ public class GrIntroduceExpressionSettingsImpl extends ExtractClosureHelperImpl GrVariable var, PsiType selectedType, boolean replaceAllOccurrences, + boolean removeLocalVar, boolean forceReturn) { super(info, name, declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, forceReturn, replaceAllOccurrences, false); myExpr = expr; myVar = var; mySelectedType = selectedType; + myRemoveLocalVar = removeLocalVar; } @Override @@ -67,4 +70,8 @@ public class GrIntroduceExpressionSettingsImpl extends ExtractClosureHelperImpl } + @Override + public boolean removeLocalVariable() { + return myRemoveLocalVar; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java index 2bb3636243eb..bd63f95de532 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -75,6 +75,7 @@ import java.util.LinkedHashSet; import java.util.List; import static com.intellij.refactoring.IntroduceParameterRefactoring.*; +import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.*; public class GrIntroduceParameterDialog extends DialogWrapper { private GrTypeComboBox myTypeComboBox; @@ -100,9 +101,11 @@ public class GrIntroduceParameterDialog extends DialogWrapper { super(info.getProject(), true); myInfo = info; myProject = info.getProject(); - myCanIntroduceSimpleParameter = GroovyIntroduceParameterUtil.findExpr(myInfo) != null || GroovyIntroduceParameterUtil.findVar(myInfo) != null || findStringPart() != null; + myCanIntroduceSimpleParameter = findExpr(myInfo) != null || + findVar(myInfo) != null || + findStringPart() != null; - TObjectIntHashMap parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info); + TObjectIntHashMap parametersToRemove = findParametersToRemove(info); toRemoveCBs = new TObjectIntHashMap(parametersToRemove.size()); for (Object p : parametersToRemove.keys()) { JCheckBox cb = new JCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName())); @@ -274,7 +277,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper { c.nextLine().next().weightx(0).fillCellNone(); namePanel.add(typeLabel, c); - myTypeComboBox = createTypeComboBox(GroovyIntroduceParameterUtil.findVar(myInfo), GroovyIntroduceParameterUtil.findExpr(myInfo), findStringPart()); + myTypeComboBox = createTypeComboBox(findVar(myInfo), findExpr(myInfo), findStringPart()); c.next().weightx(1).fillCellHorizontally(); namePanel.add(myTypeComboBox, c); typeLabel.setLabelFor(myTypeComboBox); @@ -283,7 +286,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper { c.nextLine().next().weightx(0).fillCellNone(); namePanel.add(nameLabel, c); - myNameSuggestionsField = createNameField(GroovyIntroduceParameterUtil.findVar(myInfo)); + myNameSuggestionsField = createNameField(findVar(myInfo)); c.next().weightx(1).fillCellHorizontally(); namePanel.add(myNameSuggestionsField, c); nameLabel.setLabelFor(myNameSuggestionsField); @@ -358,7 +361,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper { } private void initReplaceFieldsWithGetters(JavaRefactoringSettings settings) { - final PsiField[] usedFields = GroovyIntroduceParameterUtil.findUsedFieldsWithGetters(myInfo.getStatements(), getContainingClass()); + final PsiField[] usedFields = findUsedFieldsWithGetters(myInfo.getStatements(), getContainingClass()); myGetterPanel.setVisible(usedFields.length > 0); switch (settings.INTRODUCE_PARAMETER_REPLACE_FIELDS_WITH_GETTERS) { case REPLACE_FIELDS_WITH_GETTERS_ALL: @@ -452,8 +455,8 @@ public class GrIntroduceParameterDialog extends DialogWrapper { final GrParametersOwner toReplaceIn = myInfo.getToReplaceIn(); - final GrExpression expr = GroovyIntroduceParameterUtil.findExpr(myInfo); - final GrVariable var = GroovyIntroduceParameterUtil.findVar(myInfo); + final GrExpression expr = findExpr(myInfo); + final GrVariable var = findVar(myInfo); final StringPartInfo stringPart = findStringPart(); if (myTypeComboBox.isClosureSelected() || expr == null && var == null && stringPart == null) { @@ -484,7 +487,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper { expr, var, myTypeComboBox.getSelectedType(), - false, myForceReturnCheckBox.isSelected()); + var != null, true, myForceReturnCheckBox.isSelected()); if (toReplaceIn instanceof GrMethod) { invokeRefactoring(new GrIntroduceParameterProcessor(settings)); } @@ -522,8 +525,8 @@ public class GrIntroduceParameterDialog extends DialogWrapper { @NotNull public LinkedHashSet suggestNames() { - GrVariable var = GroovyIntroduceParameterUtil.findVar(myInfo); - GrExpression expr = GroovyIntroduceParameterUtil.findExpr(myInfo); + GrVariable var = findVar(myInfo); + GrExpression expr = findExpr(myInfo); StringPartInfo stringPart = findStringPart(); return GroovyIntroduceParameterUtil.suggestNames(var, expr, stringPart, myInfo.getToReplaceIn(), myProject); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java index 6e2ba790997c..9f1a9848476f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java @@ -18,19 +18,16 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; import com.intellij.ide.util.SuperMethodWarningUtil; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiMethod; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.IntroduceParameterRefactoring; import com.intellij.refactoring.IntroduceTargetChooser; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; @@ -38,34 +35,31 @@ import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.Function; import com.intellij.util.PairFunction; -import com.intellij.util.containers.ContainerUtil; -import gnu.trove.TIntArrayList; -import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.extract.GroovyExtractChooser; import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; -import org.jetbrains.plugins.groovy.refactoring.introduce.*; -import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.java2groovy.GroovyIntroduceParameterMethodUsagesProcessor; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; +import org.jetbrains.plugins.groovy.refactoring.introduce.IntroduceOccurrencesChooser; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GrIntroduceVariableHandler; import org.jetbrains.plugins.groovy.refactoring.ui.MethodOrClosureScopeChooser; import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import static org.jetbrains.plugins.groovy.refactoring.HelpID.GROOVY_INTRODUCE_PARAMETER; -import static org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase.createRange; +import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.findExpr; +import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.findVar; /** * @author Maxim.Medvedev @@ -74,7 +68,7 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me static final String REFACTORING_NAME = RefactoringBundle.message("introduce.parameter.title"); private JBPopup myEnclosingMethodsPopup; - public void invoke(final @NotNull Project project, final Editor editor, final PsiFile file, final @Nullable DataContext dataContext) { + public void invoke(final @NotNull Project project, @NotNull final Editor editor, @NotNull final PsiFile file, final @Nullable DataContext dataContext) { final SelectionModel selectionModel = editor.getSelectionModel(); if (!selectionModel.hasSelection()) { final int offset = editor.getCaretModel().getOffset(); @@ -105,7 +99,7 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); } - private void invoke(final Project project, final Editor editor, PsiFile file, int startOffset, int endOffset) { + private void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file, int startOffset, int endOffset) { try { final InitialInfo initialInfo = GroovyExtractChooser.invoke(project, editor, file, startOffset, endOffset, false); chooseScopeAndRun(initialInfo, editor); @@ -146,7 +140,8 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me } } - private List findScopes(InitialInfo initialInfo) { + @NotNull + private static List findScopes(@NotNull InitialInfo initialInfo) { PsiElement place = initialInfo.getContext(); final List scopes = new ArrayList(); while (true) { @@ -165,14 +160,14 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me //method to hack in tests - protected void showDialogOrStartInplace(final IntroduceParameterInfo info, final Editor editor) { + protected void showDialogOrStartInplace(@NotNull final IntroduceParameterInfo info, @NotNull final Editor editor) { if (isInplace(info, editor)) { final GrIntroduceContext context = createContext(info, editor); Map> occurrencesMap = GrIntroduceHandlerBase.fillChoice(context); new IntroduceOccurrencesChooser(editor).showChooser(new Pass() { @Override public void pass(OccurrencesChooser.ReplaceChoice choice) { - startInplace(info, context, choice == OccurrencesChooser.ReplaceChoice.ALL); + startInplace(info, context, choice); } }, occurrencesMap); } @@ -185,112 +180,27 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me new GrIntroduceParameterDialog(info).show(); } - private void startInplace(final IntroduceParameterInfo info, final GrIntroduceContext context, boolean replaceAll) { - final GrIntroduceParameterSettings settings = getSettingsForInplace(info, context, replaceAll); - if (settings == null) return; - - CommandProcessor.getInstance().executeCommand(info.getProject(), new Runnable() { - public void run() { - Document document = context.getEditor().getDocument(); - - List occurrences = ContainerUtil.newArrayList(); - if (settings.replaceAllOccurrences()) { - for (PsiElement element : context.getOccurrences()) { - occurrences.add(createRange(document, element)); - } - } - else if (context.getExpression() != null) { - occurrences.add(createRange(document, context.getExpression())); - } - - GrExpressionWrapper expr = new GrExpressionWrapper(GroovyIntroduceParameterUtil.findExpr(settings)); - - SmartPsiElementPointer pointer = - ApplicationManager.getApplication().runWriteAction(new Computable>() { - @Override - public SmartPsiElementPointer compute() { - Project project = context.getProject(); - GrParametersOwner toReplaceIn = info.getToReplaceIn(); - String name = GrInplaceParameterIntroducer.suggestNames(context, toReplaceIn).iterator().next(); - PsiType type = getType(context.getExpression(), context.getVar(), context.getStringPart()); - GrParameter parameter = GroovyIntroduceParameterMethodUsagesProcessor.addParameter( - toReplaceIn, null, - type != null ? type : PsiType.getJavaLangObject(PsiManager.getInstance(project), toReplaceIn.getResolveScope()), name, - false, project); - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); - - if (settings.replaceAllOccurrences()) { - for (PsiElement element : context.getOccurrences()) { - element.replace(factory.createReferenceExpressionFromText(name)); - } - } - else { - context.getExpression().replace(factory.createReferenceExpressionFromText(name)); - } - return SmartPointerManager.getInstance(project).createSmartPsiElementPointer(parameter); - } - }); - GrVariable parameter = pointer != null ? pointer.getElement() : null; - - if (parameter != null) { - GrInplaceIntroducer introducer = getIntroducer(parameter, context, settings, occurrences, expr); - PsiDocumentManager.getInstance(info.getProject()).doPostponedOperationsAndUnblockDocument(context.getEditor().getDocument()); - introducer.performInplaceRefactoring(introducer.suggestNames(context)); - } - } - }, REFACTORING_NAME, REFACTORING_NAME); - + private static void startInplace(@NotNull final IntroduceParameterInfo info, + @NotNull final GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice replaceChoice) { + new GrInplaceParameterIntroducer(info, context, replaceChoice).startInplaceIntroduceTemplate(); } - private static GrInplaceIntroducer getIntroducer(GrVariable parameter, - GrIntroduceContext context, - GrIntroduceParameterSettings settings, - List occurrences, - GrExpressionWrapper expr) { - return new GrInplaceParameterIntroducer(parameter, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrences, context.getPlace(), settings, expr); + private static boolean isInplace(@NotNull IntroduceParameterInfo info, + @NotNull Editor editor) { + return findExpr(info) != null && GrIntroduceHandlerBase.isInplace(editor, info.getContext()); } - private static GrIntroduceParameterSettings getSettingsForInplace(@NotNull IntroduceParameterInfo info, - @NotNull GrIntroduceContext context, - boolean replaceAll) { - GrExpression expr = context.getExpression(); - GrVariable var = context.getVar(); - - TObjectIntHashMap toRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info); - LinkedHashSet names = - GroovyIntroduceParameterUtil.suggestNames(var, expr, info.getStringPartInfo(), info.getToReplaceIn(), info.getProject()); - return new GrIntroduceExpressionSettingsImpl(info, names.iterator().next(), false, new TIntArrayList(toRemove.getValues()), false, - IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, expr, var, - getType(expr, var, info.getStringPartInfo()), replaceAll, false); - } - - @Nullable - private static PsiType getType(GrExpression expr, GrVariable var, StringPartInfo info) { - if (expr != null) { - return expr.getType(); - } - else if (var != null) { - return var.getDeclaredType(); - } - else if (info != null) { - return info.getLiteral().getType(); - } - return null; - } - - private static boolean isInplace(IntroduceParameterInfo info, Editor editor) { - return GroovyIntroduceParameterUtil.findExpr(info) != null && GrIntroduceHandlerBase.isInplace(editor, info.getContext()); - } - - @Override public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { // Does nothing } - private static GrIntroduceContext createContext(IntroduceParameterInfo info, Editor editor) { - GrExpression expr = GroovyIntroduceParameterUtil.findExpr(info); - GrVariable var = GroovyIntroduceParameterUtil.findVar(info); - return new GrIntroduceVariableHandler().getContext(info.getProject(), editor, expr, var, info.getStringPartInfo(), info.getToReplaceIn()); + private static GrIntroduceContext createContext(@NotNull IntroduceParameterInfo info, + @NotNull Editor editor) { + GrExpression expr = findExpr(info); + GrVariable var = findVar(info); + StringPartInfo stringPart = info.getStringPartInfo(); + return new GrIntroduceVariableHandler().getContext(info.getProject(), editor, expr, var, stringPart, info.getToReplaceIn()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java index a27b2ceaf0b8..9a5ccb002647 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java @@ -46,6 +46,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import org.jetbrains.plugins.groovy.refactoring.util.AnySupers; @@ -77,9 +78,10 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl LOG.assertTrue(settings.getToSearchFor() instanceof PsiMethod); final StringPartInfo stringPartInfo = settings.getStringPartInfo(); - final GrExpression expression = stringPartInfo != null - ? stringPartInfo.createLiteralFromSelected() - : settings.getExpression(); + GrVariable var = settings.getVar(); + final GrExpression expression = stringPartInfo != null ? stringPartInfo.createLiteralFromSelected() : + var != null ? var.getInitializerGroovy() + : settings.getExpression(); return new GrExpressionWrapper(expression); } @@ -176,9 +178,16 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl } if (mySettings.replaceAllOccurrences()) { - PsiElement[] exprs = GroovyIntroduceParameterUtil.getOccurrences(mySettings); - for (PsiElement expr : exprs) { - result.add(new InternalUsageInfo(expr)); + if (mySettings.getVar() != null) { + for (PsiElement element : GrIntroduceHandlerBase.collectVariableUsages(mySettings.getVar(), mySettings.getToReplaceIn())) { + result.add(new InternalUsageInfo(element)); + } + } + else { + PsiElement[] exprs = GroovyIntroduceParameterUtil.getOccurrences(mySettings); + for (PsiElement expr : exprs) { + result.add(new InternalUsageInfo(expr)); + } } } else { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java index 5391a68df73b..ef1e8f73ea58 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -379,6 +379,9 @@ public class GroovyIntroduceParameterUtil { @Nullable static GrVariable findVar(IntroduceParameterInfo info) { + GrVariable variable = info.getVar(); + if (variable != null) return variable; + final GrStatement[] statements = info.getStatements(); if (statements.length != 1) return null; return GrIntroduceHandlerBase.findVariable(statements[0]); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy index 3956cf8da7be..550c5a1e3144 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy @@ -25,7 +25,6 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect import com.intellij.refactoring.IntroduceParameterRefactoring import gnu.trove.TIntArrayList import gnu.trove.TObjectIntHashMap -import junit.framework.Assert import org.jetbrains.annotations.Nullable import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement @@ -37,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.* import org.jetbrains.plugins.groovy.util.TestUtils +import org.junit.Assert /** * @author Maxim.Medvedev @@ -123,37 +123,32 @@ public class GrIntroduceParameterTest extends LightGroovyTestCase { final Project project, final Editor editor, final PsiFile file) { - CommandProcessor.getInstance().executeCommand(project, new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - try { - final GrIntroduceParameterHandler hackedHandler = new GrIntroduceParameterHandler() { - @Override - protected void showDialog(IntroduceParameterInfo info) { - final GrIntroduceParameterSettings hackedSettings = GrIntroduceParameterTest.getSettings(info, removeUnusedParameters, replaceFieldsWithGetters, declareFinal, generateDelegate); - if (info.getToReplaceIn() instanceof GrMethod) { - new GrIntroduceParameterProcessor(hackedSettings).run(); - } - else { - new GrIntroduceClosureParameterProcessor(hackedSettings).run(); - } - } - }; - hackedHandler.invoke(project, editor, file, null); - if (conflicts != null) fail("Conflicts were expected"); - } - catch (Exception e) { - if (conflicts == null) { - e.printStackTrace(); - fail("Conflicts were not expected"); + CommandProcessor.instance.executeCommand(project, { + ApplicationManager.application.runWriteAction { + try { + final GrIntroduceParameterHandler hackedHandler = new GrIntroduceParameterHandler() { + @Override + protected void showDialog(IntroduceParameterInfo info) { + final GrIntroduceParameterSettings hackedSettings = + getSettings(info, removeUnusedParameters, replaceFieldsWithGetters, declareFinal, generateDelegate); + if (info.getToReplaceIn() instanceof GrMethod) { + new GrIntroduceParameterProcessor(hackedSettings).run(); + } + else { + new GrIntroduceClosureParameterProcessor(hackedSettings).run(); } - Assert.assertEquals(conflicts, e.getMessage()); } + }; + hackedHandler.invoke(project, editor, file, null); + if (conflicts != null) fail("Conflicts were expected"); + } + catch (Exception e) { + if (conflicts == null) { + e.printStackTrace(); + fail("Conflicts were not expected"); } - }); + Assert.assertEquals(conflicts, e.getMessage()); + } } }, "introduce Parameter", null); } @@ -174,11 +169,10 @@ public class GrIntroduceParameterTest extends LightGroovyTestCase { final GrStatement[] statements = context.getStatements() GrExpression expr = statements.length == 1 ? GrIntroduceHandlerBase.findExpression(statements[0]) : null; - GrVariable var = statements.length == 1 ? GrIntroduceHandlerBase.findVariable(context.getStatements()[0]) : null; - final PsiType type = TypesUtil. - unboxPrimitiveTypeWrapper(var != null ? var.getType() : expr != null ? expr.getType() : context.stringPartInfo.literal.type); + GrVariable var = context.var + final PsiType type = TypesUtil.unboxPrimitiveTypeWrapper(var != null ? var.getType() : expr != null ? expr.getType() : context.stringPartInfo.literal.type); return new GrIntroduceExpressionSettingsImpl(context, "anObject", declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, - expr, var, type, false, true); + expr, var, type, var !=null, var != null, true); } @@ -375,6 +369,25 @@ def foo(anObject) { } foo(print(a)) +''') + } + + void testIntroduceFromLocalVar() { + doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, null, false, '''\ +def foo() { + def var = 5 + + print var + var +} + +foo() +''', '''\ +def foo(anObject) { + + print anObject + anObject +} + +foo(5) ''') } } From 37b45f030326f228713794f4853c3029710eab50 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Sun, 9 Feb 2014 23:50:13 +0400 Subject: [PATCH 44/53] Groovy: in-place introduce parameter: show parameters to remove in preview --- .../introduce/parameter/GrInplaceParameterIntroducer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java index b9595d04a59d..5a841f9e17a5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java @@ -231,7 +231,7 @@ public class GrInplaceParameterIntroducer extends GrAbstractInplaceIntroducer Date: Mon, 10 Feb 2014 10:58:36 +0400 Subject: [PATCH 45/53] EA-52671 - assert: AbstractMappingStrategy.processFoldRegion --- .../folding/FoldingExceptionTest.java | 9 ++++ .../editor/impl/FoldingExceptionTest.java | 48 +++++++++++++++++ .../editor/impl/SoftWrapModelImpl.java | 40 +++++++-------- .../softwrap/SoftWrapFoldingListener.java | 51 ------------------- .../mapping/SoftWrapApplianceManager.java | 6 +-- 5 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java create mode 100644 java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.java delete mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java diff --git a/java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java b/java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java new file mode 100644 index 000000000000..5d02f2a248a7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java @@ -0,0 +1,9 @@ +class Test { + int b; + java.util.List values = new java.util.ArrayList(); + + int getB() { + java.util.List values = new java.util.ArrayList(); + return b; + } +} diff --git a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.java b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.java new file mode 100644 index 000000000000..329288c8ff4f --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.java @@ -0,0 +1,48 @@ +/* + * 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.intellij.openapi.editor.impl; + +import com.intellij.codeHighlighting.TextEditorHighlightingPass; +import com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory; +import com.intellij.mock.MockProgressIndicator; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.EditorTestUtil; +import com.intellij.testFramework.LightCodeInsightTestCase; + +public class FoldingExceptionTest extends LightCodeInsightTestCase { + + public void test() { + configureByFile("/codeInsight/folding/FoldingExceptionTest.java"); + EditorTestUtil.configureSoftWraps(myEditor, 120); + runFoldingPass(); + deleteLine(); + runFoldingPass(); + // we just verify here that the operation completes normally - it was known to fail previously + } + + private static void runFoldingPass() { + PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(getProject()); + psiDocumentManager.commitAllDocuments(); + PsiFile psiFile = psiDocumentManager.getPsiFile(myEditor.getDocument()); + assertNotNull(psiFile); + + CodeFoldingPassFactory factory = getProject().getComponent(CodeFoldingPassFactory.class); + TextEditorHighlightingPass highlightingPass = factory.createHighlightingPass(psiFile, myEditor); + highlightingPass.collectInformation(new MockProgressIndicator()); + highlightingPass.doApplyInformationToEditor(); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index 57978a8c0af4..819a05779300 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -70,7 +70,6 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi private final FoldProcessingEndTask myFoldProcessingEndTask = new FoldProcessingEndTask(); private final List myDocumentListeners = new ArrayList(); - private final List myFoldListeners = new ArrayList(); private final List mySoftWrapListeners = new ArrayList(); /** @@ -160,7 +159,6 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myVisualSizeManager = new SoftWrapAwareVisualSizeManager(painter); myDocumentListeners.add(myApplianceManager); - myFoldListeners.add(myApplianceManager); applianceManager.addListener(myVisualSizeManager); applianceManager.addListener(new SoftWrapAwareDocumentParsingListenerAdapter() { @Override @@ -624,7 +622,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myDirty = true; return; } - + + // We delay processing of changed fold regions till the invocation of onFoldProcessingEnd(), as + // FoldingModel can return inconsistent data before that moment. myDeferredFoldRegions.add(new FoldRegionInfo(region)); } @@ -689,7 +689,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi try { task.run(true); } catch (Throwable e) { - if (Boolean.getBoolean(DEBUG_PROPERTY_NAME)) { + if (Boolean.getBoolean(DEBUG_PROPERTY_NAME) || ApplicationManager.getApplication().isUnitTestMode()) { String info = ""; if (myEditor instanceof EditorImpl) { info = ((EditorImpl)myEditor).dumpState(); @@ -813,28 +813,26 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi } try { - for (FoldRegionInfo info : myDeferredFoldRegions) { - // There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process - // such nested region then. - FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start); - if (outerRegion != null && outerRegion != info.region && outerRegion.getStartOffset() <= info.start - && outerRegion.getEndOffset() >= info.end) - { - continue; - } - - for (SoftWrapFoldingListener listener : myFoldListeners) { - listener.onFoldRegionStateChange(info.start, info.end); + if (!myDirty) { // no need to recalculate specific areas if the whole document will be reprocessed + for (FoldRegionInfo info : myDeferredFoldRegions) { + // There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process + // such nested region then. + FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start); + if (outerRegion != null && outerRegion != info.region && outerRegion.getStartOffset() <= info.start + && outerRegion.getEndOffset() >= info.end) + { + continue; + } + + myApplianceManager.onFoldRegionStateChange(info.start, info.end); } } } finally { myDeferredFoldRegions.clear(); } - - for (SoftWrapFoldingListener listener : myFoldListeners) { - listener.onFoldProcessingEnd(); - } + + myApplianceManager.onFoldProcessingEnd(); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java deleted file mode 100644 index 0291cdbf3227..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2011 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.editor.impl.softwrap; - -import com.intellij.openapi.editor.FoldRegion; -import com.intellij.openapi.editor.ex.FoldingListener; - -/** - * Adapts {@link FoldingListener} to soft wraps specific. - *

- * Generally, replaces {@link FoldingListener#onFoldRegionStateChange(FoldRegion)} by {@link #onFoldRegionStateChange(int, int)}. - * The reason is that soft wraps are assumed to be processed after fold regions, i.e. every time the document is changed, folding - * is processed at first place (notifying soft wraps via {@link FoldingListener}) and soft wraps are assumed to be processed - * only on {@link #onFoldProcessingEnd()}. Hence, there is a possible case that changed {@link FoldRegion} object - * is out-of-date (e.g. its offsets info is dropped if the region is removed), so, we can't use - * {@link FoldingListener#onFoldRegionStateChange(FoldRegion)}. - * - * @author Denis Zhdanov - * @since 5/4/11 3:48 PM - */ -public interface SoftWrapFoldingListener { - - /** - * Informs that 'collapsed' state of fold region that is/was located at the target range is just changed. - *

- * Note: listener should delay fold region state processing until {@link #onFoldProcessingEnd()} is called. - * I.e. folding model may return inconsistent data between current moment and {@link #onFoldProcessingEnd()}. - * - * @param startOffset start offset of the target fold region (inclusive) - * @param endOffset end offset of the target fold region (exclusive) - */ - void onFoldRegionStateChange(int startOffset, int endOffset); - - /** - * Informs that fold processing is done. - */ - void onFoldProcessingEnd(); -} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index ddcfa870e4b5..3b596c6bfca8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -56,7 +56,7 @@ import java.util.List; * @author Denis Zhdanov * @since Jul 5, 2010 10:01:27 AM */ -public class SoftWrapApplianceManager implements SoftWrapFoldingListener, DocumentListener, Dumpable { +public class SoftWrapApplianceManager implements DocumentListener, Dumpable { private static final Logger LOG = Logger.getInstance("#" + SoftWrapApplianceManager.class.getName()); @@ -986,7 +986,6 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume } } - @Override public void onFoldRegionStateChange(int startOffset, int endOffset) { assert ApplicationManagerEx.getApplicationEx().isDispatchThread(); @@ -1002,7 +1001,6 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume myEventsStorage.add(document, new IncrementalCacheUpdateEvent(document, recalculationStartOffset, recalculationEndOffset)); } - @Override public void onFoldProcessingEnd() { //CachingSoftWrapDataMapper.log("xxxxxxxxxxx On fold region processing end"); recalculateSoftWraps(); From 9c3260d17bd0f7d46af5980c0588170b2ffc5e60 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 10 Feb 2014 11:48:12 +0400 Subject: [PATCH 46/53] fix NPE --- .../src/com/intellij/ui/popup/AbstractPopup.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 0c2d7bec1c1a..be934bd5fa4f 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1650,8 +1650,14 @@ public class AbstractPopup implements JBPopup { if (size == null) { myMinSize = myHeaderPanel.getPreferredSize(); } else { - myMinSize.setSize(Math.min(size.width, myHeaderPanel.getPreferredSize().width), - Math.min(size.height, myHeaderPanel.getPreferredSize().height)); + final int width = Math.min(size.width, myHeaderPanel.getPreferredSize().width); + final int height = Math.min(size.height, myHeaderPanel.getPreferredSize().height); + if (myMinSize == null) { + myMinSize = new Dimension(width, height); + } + else { + myMinSize.setSize(width, height); + } } if (myWindow != null) { From 46fce02e4b9a103bed2401754a27303e98cbe7cd Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 10 Feb 2014 12:00:52 +0400 Subject: [PATCH 47/53] IDEA-120265 Incorrect whitespaces (tab) painting when cursor change position --- .../openapi/editor/impl/ArrowPainter.java | 15 ++++++++++++--- .../intellij/openapi/editor/impl/EditorImpl.java | 1 + .../impl/softwrap/ArrowSoftWrapPainter.java | 11 +++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java index b5b9e6945d61..38b00078596d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -30,10 +30,19 @@ import java.awt.*; public class ArrowPainter { private final ColorProvider myColorHolder; + private final Computable myWidthProvider; private final Computable myHeightProvider; - public ArrowPainter(@NotNull ColorProvider colorHolder, @NotNull Computable heightProvider) { + /** + * Creates an ArrowPainter with specified parameters. + * + * @param colorHolder defines arrow color + * @param widthProvider defines character width, it is used to calculate an inset for the arrow's tip + * @param heightProvider defines character height, it's used to calculate an arrow's width and height + */ + public ArrowPainter(@NotNull ColorProvider colorHolder, @NotNull Computable widthProvider, @NotNull Computable heightProvider) { myColorHolder = colorHolder; + myWidthProvider = widthProvider; myHeightProvider = heightProvider; } @@ -46,7 +55,7 @@ public class ArrowPainter { * @param stop ending 'x' position to use during drawing */ public void paint(Graphics g, int y, int start, int stop) { - stop -= g.getFontMetrics().charWidth(' ') / 2; + stop -= myWidthProvider.compute() / 2; Color oldColor = g.getColor(); g.setColor(myColorHolder.getColor()); final int height = myHeightProvider.compute(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index b9c391a0c545..ef49b827c7dc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -729,6 +729,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private void initTabPainter() { myTabPainter = new ArrowPainter( ColorProvider.byColorsScheme(myScheme, EditorColors.WHITESPACES_COLOR), + new Computable.PredefinedValueComputable(EditorUtil.getSpaceWidth(Font.PLAIN, this)), new Computable() { @Override public Integer compute() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java index ccd241e977ef..d00eb487a627 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -43,7 +43,7 @@ public class ArrowSoftWrapPainter implements SoftWrapPainter { public ArrowSoftWrapPainter(Editor editor) { myEditor = editor; - myArrowPainter = new ArrowPainter(ColorProvider.byColor(myEditor.getColorsScheme().getDefaultForeground()), myHeightProvider); + myArrowPainter = new ArrowPainter(ColorProvider.byColor(myEditor.getColorsScheme().getDefaultForeground()), new WidthProvider(), myHeightProvider); } @Override @@ -102,4 +102,11 @@ public class ArrowSoftWrapPainter implements SoftWrapPainter { return myHeight; } } + + private class WidthProvider implements Computable { + @Override + public Integer compute() { + return EditorUtil.getSpaceWidth(Font.PLAIN, myEditor); + } + } } From 539ccf88b13ff54340c2f037240b08a31e381b9c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Feb 2014 13:10:28 +0400 Subject: [PATCH 48/53] don't rely on SmartPOinterManager to load document --- .../testSrc/com/intellij/psi/StubAstSwitchTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy index 936bb1c84203..c9153983344a 100644 --- a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -89,7 +89,7 @@ class StubAstSwitchTest extends LightCodeInsightFixtureTestCase { def oldClass = JavaPsiFacade.getInstance(project).findClass("A", GlobalSearchScope.allScope(project)) def pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(oldClass) - def document = FileDocumentManager.instance.getCachedDocument(file.virtualFile) + def document = FileDocumentManager.instance.getDocument(file.virtualFile) assert document assert file == PsiDocumentManager.getInstance(project).getCachedPsiFile(document) assert document == PsiDocumentManager.getInstance(project).getCachedDocument(file) From 9d46ee9c3f9209192fc4003f39068418ee9d210d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Feb 2014 13:37:38 +0400 Subject: [PATCH 49/53] cleanup --- .../codeInsight/daemon/impl/GlobalUsageHelper.java | 2 +- .../daemon/impl/quickfix/CreateGetterOrSetterFix.java | 4 ++-- .../intellij/refactoring/ChangeSignatureGestureTest.java | 8 ++++---- .../com/intellij/find/findUsages/FindUsagesManager.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) rename java/{java-impl => java-analysis-impl}/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java (96%) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java similarity index 96% rename from java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java rename to java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java index cf2b86fd242f..469d03a98b5f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java index dba7da867302..209dde6cf4ea 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -40,7 +40,7 @@ public class CreateGetterOrSetterFix implements IntentionAction, LowPriorityActi private final PsiField myField; private final String myPropertyName; - public CreateGetterOrSetterFix(boolean createGetter, boolean createSetter, PsiField field) { + public CreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) { myCreateGetter = createGetter; myCreateSetter = createSetter; myField = field; diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java index 61f3b18f5bc8..36d7d3974108 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -30,7 +30,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.changeSignature.ChangeSignatureDetectorAction; import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import junit.framework.Assert; import java.util.List; @@ -62,9 +61,10 @@ public class ChangeSignatureGestureTest extends LightCodeInsightFixtureTestCase final IntentionAction intention = myFixture.findSingleIntention(hint); myFixture.launchAction(intention); myFixture.checkResultByFile("/refactoring/changeSignatureGesture/" + getTestName(false) + "_after.java"); - } else { + } + else { final List intentionActions = myFixture.filterAvailableIntentions(hint); - Assert.assertEquals(true, intentionActions.isEmpty()); + assertEmpty(intentionActions); } } finally { diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index df180eb4261d..ba9870a05941 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -298,7 +298,7 @@ public class FindUsagesManager implements JDOMExternalizable { return used.get(); } - private static boolean isInComment(Usage usage) { + private static boolean isInComment(@NotNull Usage usage) { if (!(usage instanceof UsageInfo2UsageAdapter)) return false; UsageInfo usageInfo = ((UsageInfo2UsageAdapter)usage).getUsageInfo(); if (!usageInfo.isNonCodeUsage()) return false; From 1cf0b70a2101a37509d78b0cde07319bf4672c9c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Feb 2014 13:38:30 +0400 Subject: [PATCH 50/53] moved PostHighlightingPass to analysis --- .../intention/QuickFixFactory.java | 25 +- .../daemon/impl/PostHighlightingPass.java | 410 ++++++++---------- .../UnusedSymbolLocalInspectionBase.java | 53 +++ .../impl/PostHighlightingPassFactory.java | 44 +- .../impl/config/QuickFixFactoryImpl.java | 210 ++++++++- .../UnusedParametersInspection.java | 7 +- .../UnusedSymbolLocalInspection.java | 35 +- .../intellij/psi/PsiImportStatementBase.java | 4 +- .../source/PsiImportStatementBaseImpl.java | 7 +- .../jsp/jspJava/JspxImportStatement.java | 3 +- .../UnusedDeclarationFixProvider.java | 2 +- .../local/GroovyPostHighlightingPass.java | 55 ++- 12 files changed, 565 insertions(+), 290 deletions(-) rename java/{java-impl => java-analysis-impl}/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java (65%) create mode 100644 java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java rename platform/{lang-api => analysis-api}/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java (96%) diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java index f14f9ec0c4ac..edd7adbe0c71 100644 --- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java +++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.codeInspection.LocalQuickFixOnPsiElement; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; @@ -222,6 +223,26 @@ public abstract class QuickFixFactory { public abstract void registerPullAsAbstractUpFixes(@NotNull PsiMethod method, @NotNull QuickFixActionRegistrar registrar); - public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair); + @NotNull + public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair); + @NotNull + public abstract IntentionAction createOptimizeImportsFix(); + + public abstract void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo); + + @NotNull + public abstract IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project, @NotNull String qualifiedName, @NotNull String element); + + @NotNull + public abstract IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field); + + @NotNull + public abstract IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement); + + @NotNull + public abstract IntentionAction createEnableOptimizeImportsOnTheFlyFix(); + + @NotNull + public abstract IntentionAction createSafeDeleteFix(@NotNull PsiElement element); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java similarity index 65% rename from java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java rename to java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 9252436053f6..ab6aa9129f6c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -16,32 +16,27 @@ package com.intellij.codeInsight.daemon.impl; import com.intellij.codeHighlighting.Pass; -import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.codeInsight.daemon.JavaErrorMessages; +import com.intellij.codeInsight.daemon.ProblemHighlightFilter; import com.intellij.codeInsight.daemon.impl.analysis.*; -import com.intellij.codeInsight.daemon.impl.quickfix.*; +import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; import com.intellij.codeInsight.intention.EmptyIntentionAction; import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInsight.intention.IntentionManager; -import com.intellij.codeInspection.*; +import com.intellij.codeInsight.intention.QuickFixFactory; +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.InspectionsBundle; +import com.intellij.codeInspection.SuppressionUtil; +import com.intellij.codeInspection.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.codeInspection.ex.EntryPointsManagerBase; import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider; import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; -import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection; -import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase; -import com.intellij.diagnostic.AttachmentFactory; -import com.intellij.diagnostic.LogMessageEx; -import com.intellij.find.FindManager; -import com.intellij.find.findUsages.*; -import com.intellij.find.impl.FindManagerImpl; import com.intellij.lang.Language; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -51,8 +46,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.PomNamedTarget; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; @@ -60,34 +54,35 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.source.PsiClassImpl; -import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement; -import com.intellij.psi.jsp.JspFile; -import com.intellij.psi.jsp.JspSpiUtil; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.PropertyUtil; +import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtilCore; -import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector; import com.intellij.util.Processor; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.PropertyKey; -import java.util.*; - -import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES; -import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass"); + private static final Key LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP"); private RefCountHolder myRefCountHolder; private final PsiFile myFile; @Nullable private final Editor myEditor; + private final boolean myUnusedImportEnabled; private final int myStartOffset; private final int myEndOffset; @@ -98,22 +93,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass private boolean myHasMissortedImports; private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME); private UnusedDeclarationInspection myDeadCodeInspection; - private UnusedSymbolLocalInspection myUnusedSymbolInspection; + private UnusedSymbolLocalInspectionBase myUnusedSymbolInspection; private HighlightDisplayKey myUnusedSymbolKey; private boolean myDeadCodeEnabled; private boolean myInLibrary; private HighlightDisplayKey myDeadCodeKey; private HighlightInfoType myDeadCodeInfoType; - private UnusedParametersInspection myUnusedParametersInspection; - PostHighlightingPass(@NotNull Project project, - @NotNull PsiFile file, - @Nullable Editor editor, - @NotNull Document document, - @NotNull HighlightInfoProcessor highlightInfoProcessor) { + public PostHighlightingPass(@NotNull Project project, + @NotNull PsiFile file, + @Nullable Editor editor, + @NotNull Document document, + @NotNull HighlightInfoProcessor highlightInfoProcessor, + boolean unusedImportEnabled) { super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor); myFile = file; myEditor = editor; + myUnusedImportEnabled = unusedImportEnabled; myStartOffset = 0; myEndOffset = file.getTextLength(); @@ -121,6 +117,21 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass myCurrentEntryIndex = -1; } + static boolean isUpToDate(@NotNull PsiFile file) { + Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP); + long currentStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount(); + return lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file); + } + + private static void markFileUpToDate(@NotNull PsiFile file) { + long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount(); + file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp); + } + + private static boolean isInjected(@NotNull Project project, @NotNull PsiModifierListOwner modifierListOwner) { + return EntryPointsManagerBase.getInstance(project).isEntryPoint(modifierListOwner); + } + @Override protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) { DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject); @@ -166,59 +177,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass protected void applyInformationWithProgress() { if (myHighlights == null) return; UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL); - PostHighlightingPassFactory.markFileUpToDate(myFile); + markFileUpToDate(myFile); Editor editor = myEditor; - if (editor != null && timeToOptimizeImports()) { + if (editor != null) { optimizeImportsOnTheFly(editor); } } private void optimizeImportsOnTheFly(@NotNull final Editor editor) { if (myHasRedundantImports || myHasMissortedImports) { - final OptimizeImportsFix optimizeImportsFix = new OptimizeImportsFix(); + IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix(); if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) { - invokeOnTheFlyImportOptimizer(new Runnable() { - @Override - public void run() { - optimizeImportsFix.invoke(myProject, editor, myFile); - } - }, myFile, editor); + optimizeImportsFix.invoke(myProject, editor, myFile); } } } - public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable, - @NotNull final PsiFile file, - @NotNull final Editor editor) { - final long stamp = editor.getDocument().getModificationStamp(); - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return; - //no need to optimize imports on the fly during undo/redo - final UndoManager undoManager = UndoManager.getInstance(editor.getProject()); - if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return; - PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); - String beforeText = file.getText(); - final long oldStamp = editor.getDocument().getModificationStamp(); - CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(runnable); - } - }); - if (oldStamp != editor.getDocument().getModificationStamp()) { - String afterText = file.getText(); - if (Comparing.strEqual(beforeText, afterText)) { - LOG.error(LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(), - AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile()))); - } - } - } - }); - } - // returns true if error highlight was created private boolean collectHighlights(@NotNull Collection elements, @NotNull final List result, @@ -226,25 +201,16 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass ApplicationManager.getApplication().assertReadAccessAllowed(); InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); - myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME); + myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspectionBase.SHORT_NAME); boolean unusedSymbolEnabled = profile.isToolEnabled(myUnusedSymbolKey, myFile); - HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME); - boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, myFile); - myUnusedSymbolInspection = (UnusedSymbolLocalInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspection.SHORT_NAME, myFile); + myUnusedSymbolInspection = (UnusedSymbolLocalInspectionBase)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.SHORT_NAME, myFile); LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null); myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME); myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile); myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, myFile); - myUnusedParametersInspection = (UnusedParametersInspection)profile.getUnwrappedTool(UnusedParametersInspection.SHORT_NAME, myFile); - LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedParametersInspection != null); - if (unusedImportEnabled && JspPsiUtil.isInJspFile(myFile)) { - final JspFile jspFile = JspPsiUtil.getJspFile(myFile); - if (jspFile != null) { - unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile); - } - } + HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME); myDeadCodeInfoType = myDeadCodeKey == null ? null @@ -282,7 +248,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } } } - if (unusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) { + if (myUnusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) { PsiImportList importList = ((PsiJavaFile)myFile).getImportList(); if (importList != null) { final PsiImportStatementBase[] imports = importList.getAllImportStatements(); @@ -301,7 +267,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } @Nullable - private HighlightInfo processIdentifier(PsiIdentifier identifier, ProgressIndicator progress, GlobalUsageHelper helper) { + private HighlightInfo processIdentifier(@NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) { if (SuppressionUtil.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null; PsiElement parent = identifier.getParent(); if (PsiUtilCore.hasErrorElementChild(parent)) return null; @@ -310,17 +276,17 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return processLocalVariable((PsiLocalVariable)parent, identifier, progress); } if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) { - return processField((PsiField)parent, identifier, progress, helper); + return processField(myProject, (PsiField)parent, identifier, progress, helper); } if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) { - if (SuppressionUtil.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null; - return processParameter((PsiParameter)parent, identifier, progress); + if (SuppressionUtil.isSuppressed(identifier, UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME)) return null; + return processParameter(myProject, (PsiParameter)parent, identifier, progress); } if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) { - return processMethod((PsiMethod)parent, identifier, progress, helper); + return processMethod(myProject, (PsiMethod)parent, identifier, progress, helper); } if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) { - return processClass((PsiClass)parent, identifier, progress, helper); + return processClass(myProject, (PsiClass)parent, identifier, progress, helper); } return null; } @@ -330,30 +296,30 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass @NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress) { if (variable instanceof PsiResourceVariable && PsiUtil.isIgnoredName(variable.getName())) return null; - if (isImplicitUsage(variable, progress)) return null; + if (isImplicitUsage(myProject, variable, progress)) return null; if (!myRefCountHolder.isReferenced(variable)) { String message = JavaErrorMessages.message("local.variable.is.never.used", identifier.getText()); HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL); - IntentionAction fix = variable instanceof PsiResourceVariable ? new RenameToIgnoredFix(variable) : new RemoveUnusedVariableFix(variable); + IntentionAction fix = variable instanceof PsiResourceVariable ? QuickFixFactory.getInstance().createRenameToIgnoredFix(variable) : QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable); QuickFixAction.registerQuickFixAction(highlightInfo, fix, myUnusedSymbolKey); return highlightInfo; } boolean referenced = myRefCountHolder.isReferencedForRead(variable); - if (!referenced && !isImplicitRead(variable, progress)) { + if (!referenced && !isImplicitRead(myProject, variable, progress)) { String message = JavaErrorMessages.message("local.variable.is.not.used.for.reading", identifier.getText()); HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(variable), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable), myUnusedSymbolKey); return highlightInfo; } if (!variable.hasInitializer()) { referenced = myRefCountHolder.isReferencedForWrite(variable); - if (!referenced && !isImplicitWrite(variable, progress)) { + if (!referenced && !isImplicitWrite(myProject, variable, progress)) { String message = JavaErrorMessages.message("local.variable.is.not.assigned", identifier.getText()); final HighlightInfo unusedSymbolInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspection.DISPLAY_NAME), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspectionBase.DISPLAY_NAME), myUnusedSymbolKey); return unusedSymbolInfo; } } @@ -361,8 +327,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return null; } - public static boolean isImplicitUsage(final PsiModifierListOwner element, ProgressIndicator progress) { - if (UnusedSymbolLocalInspection.isInjected(element)) return true; + public static boolean isImplicitUsage(@NotNull Project project, + @NotNull PsiModifierListOwner element, + @NotNull ProgressIndicator progress) { + if (isInjected(project, element)) return true; for (ImplicitUsageProvider provider : ourImplicitUsageProviders) { progress.checkCanceled(); if (provider.isImplicitUsage(element)) { @@ -373,24 +341,26 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return false; } - private static boolean isImplicitRead(final PsiVariable element, ProgressIndicator progress) { + private static boolean isImplicitRead(@NotNull Project project, @NotNull PsiVariable element, @NotNull ProgressIndicator progress) { for(ImplicitUsageProvider provider: ourImplicitUsageProviders) { progress.checkCanceled(); if (provider.isImplicitRead(element)) { return true; } } - return UnusedSymbolLocalInspection.isInjected(element); + return isInjected(project, element); } - private static boolean isImplicitWrite(final PsiVariable element, ProgressIndicator progress) { + private static boolean isImplicitWrite(@NotNull Project project, + @NotNull PsiVariable element, + @NotNull ProgressIndicator progress) { for(ImplicitUsageProvider provider: ourImplicitUsageProviders) { progress.checkCanceled(); if (provider.isImplicitWrite(element)) { return true; } } - return UnusedSymbolLocalInspection.isInjected(element); + return isInjected(project, element); } @Nullable @@ -411,7 +381,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } @Nullable - private HighlightInfo processField(@NotNull final PsiField field, + private HighlightInfo processField(@NotNull final Project project, + @NotNull final PsiField field, @NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) { @@ -419,18 +390,18 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return null; } if (field.hasModifierProperty(PsiModifier.PRIVATE)) { - if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(field, progress)) { + if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(myProject, field, progress)) { String message = JavaErrorMessages.message("private.field.is.not.used", identifier.getText()); HighlightInfo highlightInfo = suggestionsToMakeFieldUsed(field, identifier, message); if (!field.hasInitializer()) { - QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field)); + QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(field)); } return highlightInfo; } final boolean readReferenced = myRefCountHolder.isReferencedForRead(field); - if (!readReferenced && !isImplicitRead(field, progress)) { + if (!readReferenced && !isImplicitRead(project, field, progress)) { String message = JavaErrorMessages.message("private.field.is.not.used.for.reading", identifier.getText()); return suggestionsToMakeFieldUsed(field, identifier, message); } @@ -439,44 +410,52 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return null; } final boolean writeReferenced = myRefCountHolder.isReferencedForWrite(field); - if (!writeReferenced && !isImplicitWrite(field, progress)) { + if (!writeReferenced && !isImplicitWrite(project, field, progress)) { String message = JavaErrorMessages.message("private.field.is.not.assigned", identifier.getText()); final HighlightInfo info = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(info, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey); - QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field)); + QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix( + field)); SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor() { @Override public boolean process(final String annoName) { - QuickFixAction.registerQuickFixAction(info, UnusedSymbolLocalInspection.createQuickFix(annoName, "fields", field.getProject())); + QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance() + .createAddToDependencyInjectionAnnotationsFix(project, annoName, "fields")); return true; } }); return info; } } - else if (isImplicitUsage(field, progress)) { + else if (isImplicitUsage(myProject, field, progress)) { return null; } - else if (isFieldUnused(field, progress, helper)) { - return formatUnusedSymbolHighlightInfo("field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier); + else if (isFieldUnused(myProject, myFile, field, progress, helper)) { + return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier + ); } return null; } - public static boolean isFieldUnused(PsiField field, ProgressIndicator progress, GlobalUsageHelper helper) { - if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(field, progress, helper)) { + public static boolean isFieldUnused(@NotNull Project project, + @NotNull PsiFile containingFile, + @NotNull PsiField field, + @NotNull ProgressIndicator progress, + @NotNull GlobalUsageHelper helper) { + if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(project, containingFile, field, progress, helper)) { return false; } - return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(field, progress, helper); + return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper + ); } - private HighlightInfo suggestionsToMakeFieldUsed(final PsiField field, final PsiIdentifier identifier, final String message) { + private HighlightInfo suggestionsToMakeFieldUsed(@NotNull PsiField field, @NotNull PsiIdentifier identifier, @NotNull String message) { HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(field), myUnusedSymbolKey); - QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey); - QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey); - QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(field), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey); return highlightInfo; } @@ -486,7 +465,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } @Nullable - private HighlightInfo processParameter(@NotNull PsiParameter parameter, + private HighlightInfo processParameter(@NotNull Project project, + @NotNull PsiParameter parameter, @NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress) { PsiElement declarationScope = parameter.getDeclarationScope(); @@ -502,18 +482,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass !method.hasModifierProperty(PsiModifier.NATIVE) && !JavaHighlightUtil.isSerializationRelatedMethod(method, method.getContainingClass()) && !PsiClassImplUtil.isMainOrPremainMethod(method)) { - if (UnusedSymbolLocalInspection.isInjected(method)) return null; + if (isInjected(project, method)) return null; HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress); if (highlightInfo != null) { - List options = new ArrayList(); - options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, myFile)); - if (myUnusedParametersInspection != null) { - SuppressQuickFix[] batchSuppressActions = myUnusedParametersInspection.getBatchSuppressActions(parameter); - Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions)); - } - //need suppress from Unused Parameters but settings from Unused Symbol - QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter), - options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey)); + QuickFixFactory.getInstance().registerFixesForUnusedParameter(parameter, highlightInfo); return highlightInfo; } } @@ -521,7 +493,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass else if (declarationScope instanceof PsiForeachStatement && !PsiUtil.isIgnoredName(parameter.getName())) { HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress); if (highlightInfo != null) { - QuickFixAction.registerQuickFixAction(highlightInfo, new RenameToIgnoredFix(parameter), myUnusedSymbolKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRenameToIgnoredFix(parameter), myUnusedSymbolKey); return highlightInfo; } } @@ -533,7 +505,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass private HighlightInfo checkUnusedParameter(@NotNull PsiParameter parameter, @NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress) { - if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(parameter, progress)) { + if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(myProject, parameter, progress)) { String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText()); return createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL); } @@ -541,11 +513,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } @Nullable - private HighlightInfo processMethod(@NotNull final PsiMethod method, + private HighlightInfo processMethod(@NotNull final Project project, + @NotNull final PsiMethod method, @NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) { - if (isMethodReferenced(method, progress, helper)) return null; + if (isMethodReferenced(myProject, myFile, method, progress, helper)) return null; HighlightInfoType highlightInfoType; HighlightDisplayKey highlightDisplayKey; String key; @@ -562,26 +535,23 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY); String message = JavaErrorMessages.message(key, symbolName); final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType); - QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), highlightDisplayKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), highlightDisplayKey); SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(method, new Processor() { @Override public boolean process(final String annoName) { - QuickFixAction - .registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, "methods", method.getProject())); + IntentionAction fix = QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, "methods"); + QuickFixAction.registerQuickFixAction(highlightInfo, fix); return true; } }); - PsiClass containingClass = method.getContainingClass(); - if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) { - //ignore methods with deleted return types as they are always marked as unused without any reason - ChangeSignatureGestureDetector.getInstance(myProject).dismissForElement(method); - } return highlightInfo; } - public static boolean isMethodReferenced(PsiMethod method, - ProgressIndicator progress, - GlobalUsageHelper helper) { + public static boolean isMethodReferenced(@NotNull Project project, + @NotNull PsiFile containingFile, + @NotNull PsiMethod method, + @NotNull ProgressIndicator progress, + @NotNull GlobalUsageHelper helper) { if (helper.isLocallyUsed(method)) return true; boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE); @@ -591,39 +561,42 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass if (isIntentionalPrivateConstructor(method, containingClass)) { return true; } - if (isImplicitUsage(method, progress)) { + if (isImplicitUsage(project, method, progress)) { return true; } if (!helper.isCurrentFileAlreadyChecked()) { - return !weAreSureThereAreNoUsages(method, progress, helper); + return !weAreSureThereAreNoUsages(project, containingFile, method, progress, helper); } } else { //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too if (containingClass != null && method.isConstructor() && containingClass.getConstructors().length == 1 - && isClassUsed(containingClass, progress, helper)) { + && isClassUsed(project, containingFile, containingClass, progress, helper)) { return true; } - if (isImplicitUsage(method, progress)) return true; + if (isImplicitUsage(project, method, progress)) return true; if (method.findSuperMethods().length != 0) { return true; } - if (!weAreSureThereAreNoUsages(method, progress, helper)) { + if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) { return true; } } return false; } - private static boolean weAreSureThereAreNoUsages(@NotNull PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) { + private static boolean weAreSureThereAreNoUsages(@NotNull Project project, + @NotNull PsiFile containingFile, + @NotNull PsiMember member, + @NotNull ProgressIndicator progress, + @NotNull GlobalUsageHelper helper) { if (!helper.shouldCheckUsages(member)) return false; String name = member.getName(); if (name == null) return false; SearchScope useScope = member.getUseScope(); - Project project = member.getProject(); if (useScope instanceof GlobalSearchScope) { // some classes may have references from within XML outside dependent modules, e.g. our actions if (member instanceof PsiClass) { @@ -631,46 +604,67 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project); - PsiFile file = member.getContainingFile(); - PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? file : null; + PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null; PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress); - if (cheapEnough == TOO_MANY_OCCURRENCES) return false; + if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false; //search usages if it cheap //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before - if (cheapEnough == ZERO_OCCURRENCES) { - if (!canBeReferencedViaWeirdNames(member)) return true; + if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES && !canBeReferencedViaWeirdNames(member, containingFile)) { + return true; } if (member instanceof PsiMethod) { String propertyName = PropertyUtil.getPropertyName(member); - if (propertyName != null && file != null) { - SearchScope fileScope = file.getUseScope(); + if (propertyName != null) { + SearchScope fileScope = containingFile.getUseScope(); if (fileScope instanceof GlobalSearchScope && - searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == TOO_MANY_OCCURRENCES) { + searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == + PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) { return false; } } } } - FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); - FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project)); - FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone(); - findUsagesOptions.searchScope = useScope; - findUsagesOptions.isSearchForTextOccurrences = true; - return !findUsagesManager.isUsed(member, findUsagesOptions); + + //FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); + //FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project)); + //FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone(); + //findUsagesOptions.searchScope = useScope; + //findUsagesOptions.isSearchForTextOccurrences = true; + //boolean old = !findUsagesManager.isUsed(member, findUsagesOptions); + + //if (true) { + if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false; + return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope); + //} + //return old; } - private static boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) { + private static boolean foundUsageInText(PsiMember member, GlobalSearchScope scope) { + PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(member.getProject()); + + return !helper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() { + @Override + public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) { + return false; + } + }, scope); + } + + private static boolean isEnumValuesMethodUsed(@NotNull Project project, + @NotNull PsiFile containingFile, + @NotNull PsiMember member, + @NotNull ProgressIndicator progress, + @NotNull GlobalUsageHelper helper) { final PsiClass containingClass = member.getContainingClass(); if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true; final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod(); - return valuesMethod == null || isMethodReferenced(valuesMethod, progress, helper); + return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper); } - private static boolean canBeReferencedViaWeirdNames(PsiMember member) { + private static boolean canBeReferencedViaWeirdNames(@NotNull PsiMember member, @NotNull PsiFile containingFile) { if (member instanceof PsiClass) return false; - PsiFile containingFile = member.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) return true; // Groovy field can be referenced from Java by getter if (member instanceof PsiField) return false; //Java field cannot be referenced by anything but its name if (member instanceof PsiMethod) { @@ -680,11 +674,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } @Nullable - private HighlightInfo processClass(@NotNull PsiClass aClass, + private HighlightInfo processClass(@NotNull Project project, + @NotNull PsiClass aClass, @NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) { - if (isClassUsed(aClass, progress, helper)) return null; + if (isClassUsed(project, myFile, aClass, progress, helper)) return null; String pattern; HighlightDisplayKey highlightDisplayKey; @@ -711,30 +706,39 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass highlightDisplayKey = myDeadCodeKey; highlightInfoType = myDeadCodeInfoType; } - return formatUnusedSymbolHighlightInfo(pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier); + return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier + ); } - public static boolean isClassUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) { - if (aClass == null) return true; + public static boolean isClassUsed(@NotNull Project project, + @NotNull PsiFile containingFile, + @NotNull PsiClass aClass, + @NotNull ProgressIndicator progress, + @NotNull GlobalUsageHelper helper) { Boolean result = helper.unusedClassCache.get(aClass); if (result == null) { - result = isReallyUsed(aClass, progress, helper); + result = isReallyUsed(project, containingFile, aClass, progress, helper); helper.unusedClassCache.put(aClass, result); } return result; } - private static boolean isReallyUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) { - if (isImplicitUsage(aClass, progress) || helper.isLocallyUsed(aClass)) return true; + private static boolean isReallyUsed(@NotNull Project project, + @NotNull PsiFile containingFile, + @NotNull PsiClass aClass, + @NotNull ProgressIndicator progress, + @NotNull GlobalUsageHelper helper) { + if (isImplicitUsage(project, aClass, progress) || helper.isLocallyUsed(aClass)) return true; if (helper.isCurrentFileAlreadyChecked()) { if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) || aClass.getParent() instanceof PsiDeclarationStatement || aClass instanceof PsiTypeParameter) return false; } - return !weAreSureThereAreNoUsages(aClass, progress, helper); + return !weAreSureThereAreNoUsages(project, containingFile, aClass, progress, helper); } - private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern, + private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull final Project project, + @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern, @NotNull final PsiNameIdentifierOwner aClass, @NotNull final String element, @NotNull HighlightDisplayKey highlightDisplayKey, @@ -743,12 +747,13 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass String symbolName = aClass.getName(); String message = JavaErrorMessages.message(pattern, symbolName); final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType); - QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(aClass), highlightDisplayKey); + QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(aClass), highlightDisplayKey); SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes((PsiModifierListOwner)aClass, new Processor() { @Override public boolean process(final String annoName) { QuickFixAction - .registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, element, aClass.getProject())); + .registerQuickFixAction(highlightInfo, + QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, element)); return true; } }); @@ -758,7 +763,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass @Nullable private HighlightInfo processImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) { // jsp include directive hack - if (importStatement instanceof JspxImportStatement && ((JspxImportStatement)importStatement).isForeignFileImport()) return null; + if (importStatement.isForeignFileImport()) return null; if (PsiUtilCore.hasErrorElementChild(importStatement)) return null; @@ -799,43 +804,12 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description) .create(); - QuickFixAction.registerQuickFixAction(info, new OptimizeImportsFix(), unusedImportKey); - QuickFixAction.registerQuickFixAction(info, new EnableOptimizeImportsOnTheFlyFix(), unusedImportKey); + QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(), unusedImportKey); + QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey); myHasRedundantImports = true; return info; } - private boolean timeToOptimizeImports() { - if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false; - - DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject); - PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument); - // dont optimize out imports in JSP since it can be included in other JSP - if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false; - - if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false; - boolean errors = containsErrorsPreventingOptimize(file); - - return !errors && DaemonListeners.canChangeFileSilently(myFile); - } - - private boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) { - // ignore unresolved imports errors - PsiImportList importList = ((PsiJavaFile)file).getImportList(); - final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange(); - boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx - .processHighlights(myDocument, myProject, HighlightSeverity.ERROR, 0, myDocument.getTextLength(), new Processor() { - @Override - public boolean process(HighlightInfo error) { - int infoStart = error.getActualStartOffset(); - int infoEnd = error.getActualEndOffset(); - - return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF); - } - }); - - return hasErrorsExceptUnresolvedImports; - } private static boolean isIntentionalPrivateConstructor(@NotNull PsiMethod method, PsiClass containingClass) { return method.isConstructor() && diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java new file mode 100644 index 000000000000..af20033cc42d --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java @@ -0,0 +1,53 @@ +/* + * 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.intellij.codeInspection; + +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class UnusedSymbolLocalInspectionBase extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool { + @NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME; + @NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME; + @NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters"; + + public boolean LOCAL_VARIABLE = true; + public boolean FIELD = true; + public boolean METHOD = true; + public boolean CLASS = true; + public boolean PARAMETER = true; + public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true; + + @Override + public boolean isSuppressedFor(@NotNull PsiElement element) { + return isSuppressedFor(element, this); + } + public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) { + return BaseJavaBatchLocalInspectionTool.isSuppressedFor(element, tool); + } + @Override + public SuppressIntentionAction[] getSuppressActions(final PsiElement element) { + String shortName = getShortName(); + HighlightDisplayKey key = HighlightDisplayKey.find(shortName); + if (key == null) { + throw new AssertionError("HighlightDisplayKey.find(" + shortName + ") is null. Inspection: "+getClass()); + } + SuppressQuickFix[] batchSuppressActions = BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(key); + return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java index 6bd5a3b7f4b1..d9424beb743b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java @@ -19,18 +19,22 @@ import com.intellij.codeHighlighting.MainHighlightingPassFactory; import com.intellij.codeHighlighting.Pass; import com.intellij.codeHighlighting.TextEditorHighlightingPass; import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar; -import com.intellij.codeInsight.daemon.ProblemHighlightFilter; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl; +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.JspPsiUtil; import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiModificationTracker; +import com.intellij.psi.jsp.JspFile; +import com.intellij.psi.jsp.JspSpiUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,7 +46,7 @@ import java.util.Arrays; */ public class PostHighlightingPassFactory extends AbstractProjectComponent implements MainHighlightingPassFactory { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPassFactory"); - private static final Key LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP"); + public PostHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar, HighlightVisitorImpl hvi) { super(project); highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL,}, null, true, Pass.POST_UPDATE_ALL); @@ -65,26 +69,34 @@ public class PostHighlightingPassFactory extends AbstractProjectComponent implem @Nullable public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) { TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL); - if (textRange == null) { - Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP); - long currentStamp = PsiModificationTracker.SERVICE.getInstance(myProject).getModificationCount(); - if (lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file)) { - return null; - } - } + if (textRange == null && PostHighlightingPass.isUpToDate(file)) return null; - return new PostHighlightingPass(myProject, file, editor, editor.getDocument(), new DefaultHighlightInfoProcessor()); + return create(file, editor.getDocument(), editor, new DefaultHighlightInfoProcessor()); } @Override public TextEditorHighlightingPass createMainHighlightingPass(@NotNull PsiFile file, @NotNull Document document, @NotNull HighlightInfoProcessor highlightInfoProcessor) { - return new PostHighlightingPass(myProject, file, null, document, highlightInfoProcessor); + return create(file, document, null, highlightInfoProcessor); } - public static void markFileUpToDate(@NotNull PsiFile file) { - long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount(); - file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp); + private PostHighlightingPass create(@NotNull PsiFile file, + @NotNull Document document, Editor editor, + @NotNull HighlightInfoProcessor highlightInfoProcessor) { + HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME); + return new PostHighlightingPass(myProject, file, editor, document, highlightInfoProcessor, isUnusedImportEnabled(unusedImportKey, file)); + } + + private static boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey, @NotNull PsiFile file) { + InspectionProfile profile = InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile(); + boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, file); + if (unusedImportEnabled && JspPsiUtil.isInJspFile(file)) { + final JspFile jspFile = JspPsiUtil.getJspFile(file); + if (jspFile != null) { + unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile); + } + } + return unusedImportEnabled; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index dcbf1a7bd045..ddd5e65f74f3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -15,30 +15,60 @@ */ package com.intellij.codeInsight.intention.impl.config; +import com.intellij.codeInsight.CodeInsightSettings; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx; +import com.intellij.codeInsight.daemon.impl.DaemonListeners; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix; -import com.intellij.codeInsight.daemon.impl.quickfix.ReplacePrimitiveWithBoxedTypeAction; import com.intellij.codeInsight.daemon.impl.quickfix.*; import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix; import com.intellij.codeInsight.daemon.quickFix.CreateFieldOrPropertyFix; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.IntentionManager; import com.intellij.codeInsight.intention.QuickFixFactory; -import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; -import com.intellij.codeInspection.LocalQuickFixOnPsiElement; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ex.EntryPointsManagerBase; +import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.codeInspection.util.SpecialAnnotationsUtil; +import com.intellij.diagnostic.AttachmentFactory; +import com.intellij.diagnostic.LogMessageEx; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.undo.UndoManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.PropertyMemberType; import com.intellij.psi.util.ClassKind; +import com.intellij.psi.util.PropertyMemberType; +import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** * @author cdr */ public class QuickFixFactoryImpl extends QuickFixFactory { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.QuickFixFactoryImpl"); + @NotNull @Override public LocalQuickFixAndIntentionActionOnPsiElement createModifierListFix(@NotNull PsiModifierList modifierList, @@ -561,9 +591,177 @@ public class QuickFixFactoryImpl extends QuickFixFactory { PullAsAbstractUpFix.registerQuickFix(method, registrar); } + @NotNull @Override - public IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair) { + public IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair) { return new CreateAnnotationMethodFromUsageFix(pair); } + @NotNull + @Override + public IntentionAction createOptimizeImportsFix() { + final OptimizeImportsFix fix = new OptimizeImportsFix(); + + return new IntentionAction() { + @NotNull + @Override + public String getText() { + return fix.getText(); + } + + @NotNull + @Override + public String getFamilyName() { + return fix.getFamilyName(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return timeToOptimizeImports(file) && fix.isAvailable(project, editor, file); + } + + @Override + public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { + invokeOnTheFlyImportOptimizer(new Runnable() { + @Override + public void run() { + fix.invoke(project, editor, file); + } + }, file, editor); + } + + @Override + public boolean startInWriteAction() { + return fix.startInWriteAction(); + } + }; + } + + @Override + public void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo) { + Project myProject = parameter.getProject(); + InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); + UnusedParametersInspection unusedParametersInspection = + (UnusedParametersInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME, parameter); + LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || unusedParametersInspection != null); + List options = new ArrayList(); + HighlightDisplayKey myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME); + options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, parameter)); + if (unusedParametersInspection != null) { + SuppressQuickFix[] batchSuppressActions = unusedParametersInspection.getBatchSuppressActions(parameter); + Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions)); + } + //need suppress from Unused Parameters but settings from Unused Symbol + QuickFixAction.registerQuickFixAction((HighlightInfo)highlightInfo, new RemoveUnusedParameterFix(parameter), + options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey)); + } + + @NotNull + @Override + public IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project, + @NotNull String qualifiedName, + @NotNull String element) { + final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project); + return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction( + QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName), + QuickFixBundle.message("fix.unused.symbol.injection.family"), + entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName); + } + + @NotNull + @Override + public IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) { + return new CreateGetterOrSetterFix(createGetter, createSetter, field); + } + + @NotNull + @Override + public IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement) { + return new RenameToIgnoredFix(namedElement); + } + + @NotNull + @Override + public IntentionAction createEnableOptimizeImportsOnTheFlyFix() { + return new EnableOptimizeImportsOnTheFlyFix(); + } + + @NotNull + @Override + public IntentionAction createSafeDeleteFix(@NotNull PsiElement element) { + if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod)element; + PsiClass containingClass = method.getContainingClass(); + if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) { + //ignore methods with deleted return types as they are always marked as unused without any reason + ChangeSignatureGestureDetector.getInstance(method.getProject()).dismissForElement(method); + } + } + return new SafeDeleteFix(element); + } + + public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable, + @NotNull final PsiFile file, + @NotNull final Editor editor) { + final long stamp = editor.getDocument().getModificationStamp(); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return; + //no need to optimize imports on the fly during undo/redo + final UndoManager undoManager = UndoManager.getInstance(editor.getProject()); + if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return; + PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); + String beforeText = file.getText(); + final long oldStamp = editor.getDocument().getModificationStamp(); + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(runnable); + } + }); + if (oldStamp != editor.getDocument().getModificationStamp()) { + String afterText = file.getText(); + if (Comparing.strEqual(beforeText, afterText)) { + LOG.error( + LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(), + AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile()))); + } + } + } + }); + } + + private static boolean timeToOptimizeImports(@NotNull PsiFile file) { + if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false; + + DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject()); + // dont optimize out imports in JSP since it can be included in other JSP + if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false; + + if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false; + boolean errors = containsErrorsPreventingOptimize(file); + + return !errors && DaemonListeners.canChangeFileSilently(file); + } + + private static boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) { + Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + if (document == null) return true; + // ignore unresolved imports errors + PsiImportList importList = ((PsiJavaFile)file).getImportList(); + final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange(); + boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx + .processHighlights(document, file.getProject(), HighlightSeverity.ERROR, 0, document.getTextLength(), new Processor() { + @Override + public boolean process(HighlightInfo error) { + int infoStart = error.getActualStartOffset(); + int infoEnd = error.getActualEndOffset(); + + return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF); + } + }); + + return hasErrorsExceptUnresolvedImports; + } } diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java index 9750838e9c0c..fba3dcda7e66 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -43,7 +43,6 @@ import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,8 +53,6 @@ import java.util.Collection; import java.util.List; public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool { - @NonNls public static final String SHORT_NAME = "UnusedParameters"; - @Override @Nullable public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity, @@ -229,7 +226,7 @@ public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool { @Override @NotNull public String getShortName() { - return SHORT_NAME; + return UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME; } @Override diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java index f24fcd7cd2c6..d28c34b35c54 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -17,20 +17,14 @@ package com.intellij.codeInspection.unusedSymbol; import com.intellij.codeInsight.daemon.GroupNames; -import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.BaseJavaLocalInspectionTool; +import com.intellij.codeInspection.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.ex.EntryPointsManager; -import com.intellij.codeInspection.ex.EntryPointsManagerBase; import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool; -import com.intellij.codeInspection.util.SpecialAnnotationsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectUtil; -import com.intellij.psi.PsiModifierListOwner; import org.intellij.lang.annotations.Pattern; -import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,18 +38,7 @@ import java.awt.event.ActionListener; * User: anna * Date: 17-Feb-2006 */ -public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool { - @NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME; - @NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME; - - public boolean LOCAL_VARIABLE = true; - public boolean FIELD = true; - public boolean METHOD = true; - public boolean CLASS = true; - public boolean PARAMETER = true; - public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true; - - +public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase implements PairedUnfairLocalInspectionTool { @Override @NotNull public String getGroupDisplayName() { @@ -154,16 +137,4 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp public JComponent createOptionsPanel() { return new OptionsPanel().getPanel(); } - - public static IntentionAction createQuickFix(@NonNls String qualifiedName, @Nls String element, Project project) { - final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project); - return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction( - QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName), - QuickFixBundle.message("fix.unused.symbol.injection.family"), - entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName); - } - - public static boolean isInjected(final PsiModifierListOwner modifierListOwner) { - return EntryPointsManagerBase.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner); - } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java b/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java index 582f51d1bf8e..6b7354a57171 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -61,4 +61,6 @@ public interface PsiImportStatementBase extends PsiElement { */ @Nullable PsiElement resolve(); + + boolean isForeignFileImport(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java index b252f1f5d6a2..c5af2ad5b312 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -63,4 +63,9 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement myUnusedImports; @@ -133,19 +141,21 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { if (deadCodeEnabled && element instanceof GrNamedElement && element instanceof PsiModifierListOwner && - !PostHighlightingPass.isImplicitUsage((PsiModifierListOwner)element, progress) && + !PostHighlightingPass.isImplicitUsage(((PsiModifierListOwner)element).getProject(), (PsiModifierListOwner)element, progress) && !GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, GroovyUnusedDeclarationInspection.SHORT_NAME)) { PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy(); if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) { String name = ((GrNamedElement)element).getName(); - if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) { + if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed(myProject, + ((GrTypeDefinition)element).getContainingFile(), (GrTypeDefinition)element, progress, usageHelper + )) { HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL); QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey); ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo); } else if (element instanceof GrMethod) { GrMethod method = (GrMethod)element; - if (!PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) { + if (!PostHighlightingPass.isMethodReferenced(method.getProject(), method.getContainingFile(), method, progress, usageHelper)) { String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused"; HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL); QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), unusedDefKey); @@ -222,7 +232,7 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { } private static boolean isFieldUnused(GrField field, ProgressIndicator progress, GlobalUsageHelper usageHelper) { - if (!PostHighlightingPass.isFieldUnused(field, progress, usageHelper)) return false; + if (!PostHighlightingPass.isFieldUnused(field.getProject(), field.getContainingFile(), field, progress, usageHelper)) return false; final GrAccessorMethod[] getters = field.getGetters(); final GrAccessorMethod setter = field.getSetter(); @@ -300,7 +310,7 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { final Runnable optimize = myOptimizeRunnable; if (optimize != null && timeToOptimizeImports()) { - PostHighlightingPass.invokeOnTheFlyImportOptimizer(new Runnable() { + invokeOnTheFlyImportOptimizer(new Runnable() { @Override public void run() { optimize.run(); @@ -309,6 +319,39 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { } } + public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable, + @NotNull final PsiFile file, + @NotNull final Editor editor) { + final long stamp = editor.getDocument().getModificationStamp(); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return; + //no need to optimize imports on the fly during undo/redo + final UndoManager undoManager = UndoManager.getInstance(editor.getProject()); + if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return; + PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); + String beforeText = file.getText(); + final long oldStamp = editor.getDocument().getModificationStamp(); + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(runnable); + } + }); + if (oldStamp != editor.getDocument().getModificationStamp()) { + String afterText = file.getText(); + if (Comparing.strEqual(beforeText, afterText)) { + LOG.error( + LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(), + AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile()))); + } + } + } + }); + } + + private static TextRange calculateRangeToUse(GrImportStatement unusedImport) { final TextRange range = unusedImport.getTextRange(); From 261824e6137bd971262e97bb8ea6b8df51c4a22f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Feb 2014 14:03:08 +0400 Subject: [PATCH 51/53] moved to right package --- .../intellij/codeInsight/daemon/impl/PostHighlightingPass.java | 2 +- .../{ => unusedSymbol}/UnusedSymbolLocalInspectionBase.java | 3 ++- .../codeInsight/intention/impl/config/QuickFixFactoryImpl.java | 1 + .../unusedParameters/UnusedParametersInspection.java | 1 + .../unusedSymbol/UnusedSymbolLocalInspection.java | 1 - 5 files changed, 5 insertions(+), 3 deletions(-) rename java/java-analysis-impl/src/com/intellij/codeInspection/{ => unusedSymbol}/UnusedSymbolLocalInspectionBase.java (96%) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index ab6aa9129f6c..36610e65fca9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -28,7 +28,7 @@ import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.SuppressionUtil; -import com.intellij.codeInspection.UnusedSymbolLocalInspectionBase; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.ex.EntryPointsManagerBase; import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java similarity index 96% rename from java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java rename to java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java index af20033cc42d..dc28a7b340c0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/UnusedSymbolLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInspection; +package com.intellij.codeInspection.unusedSymbol; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.codeInspection.*; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index ddd5e65f74f3..147cf33bd8a7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -34,6 +34,7 @@ import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.EntryPointsManagerBase; import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection; import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.util.SpecialAnnotationsUtil; import com.intellij.diagnostic.AttachmentFactory; import com.intellij.diagnostic.LogMessageEx; diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java index fba3dcda7e66..e1fa136fb1d1 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java @@ -30,6 +30,7 @@ import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.EntryPointsManager; import com.intellij.codeInspection.reference.*; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.util.Comparing; diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java index d28c34b35c54..961427ff372a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java @@ -18,7 +18,6 @@ package com.intellij.codeInspection.unusedSymbol; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; -import com.intellij.codeInspection.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.ex.EntryPointsManager; import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool; From 42f69a2a2ff92a1f3e5191d3f3cf07b895b3f53c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Feb 2014 15:05:25 +0400 Subject: [PATCH 52/53] notnull --- .../deadCode/UnusedDeclarationInspection.java | 14 ++++++++------ .../daemon/LightAdvHighlightingJdk7Test.java | 6 +++--- .../daemon/LightAdvHighlightingTest.java | 4 ++-- .../intellij/testFramework/InspectionTestCase.java | 6 +++--- .../codeInspection/reference/EntryPoint.java | 6 +++--- .../junit2/inspection/JUnitEntryPoint.java | 6 +++--- .../testng/inspection/TestNGEntryPoint.java | 6 +++--- 7 files changed, 25 insertions(+), 23 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java index 51a311194080..bbeb09e06f92 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -435,7 +435,7 @@ public class UnusedDeclarationInspection extends GlobalInspectionTool { myPhase = 1; } - public boolean isEntryPoint(final RefElement owner) { + public boolean isEntryPoint(@NotNull RefElement owner) { final PsiElement element = owner.getElement(); if (RefUtil.isImplicitUsage(element)) return true; if (element instanceof PsiModifierListOwner) { @@ -444,9 +444,11 @@ public class UnusedDeclarationInspection extends GlobalInspectionTool { return true; } } - for (EntryPoint extension : myExtensions) { - if (extension.isEntryPoint(owner, element)) { - return true; + if (element != null) { + for (EntryPoint extension : myExtensions) { + if (extension.isEntryPoint(owner, element)) { + return true; + } } } return false; @@ -482,7 +484,7 @@ public class UnusedDeclarationInspection extends GlobalInspectionTool { } if (element instanceof PsiModifierListOwner) { final EntryPointsManager entryPointsManager = EntryPointsManager.getInstance(project); - if (entryPointsManager.isEntryPoint((PsiModifierListOwner)element)) return true; + if (entryPointsManager.isEntryPoint(element)) return true; //if (AnnotationUtil // .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.ADDITIONAL_ANNOTATIONS) || // AnnotationUtil diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index 03e81dd85c5a..ec160610ed7a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -109,8 +109,8 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { ExtensionPoint point = Extensions.getRootArea().getExtensionPoint(ToolExtensionPoints.DEAD_CODE_TOOL); EntryPoint extension = new EntryPoint() { @NotNull @Override public String getDisplayName() { return "duh"; } - @Override public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { return false; } - @Override public boolean isEntryPoint(PsiElement psiElement) { return false; } + @Override public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return false; } + @Override public boolean isEntryPoint(@NotNull PsiElement psiElement) { return false; } @Override public boolean isSelected() { return false; } @Override public void setSelected(boolean selected) { } @Override public void readExternal(Element element) { } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java index 2ae666ffe803..974a3222f119 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java @@ -234,12 +234,12 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase { } @Override - public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { + public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return false; } @Override - public boolean isEntryPoint(PsiElement psiElement) { + public boolean isEntryPoint(@NotNull PsiElement psiElement) { return psiElement instanceof PsiMethod && ((PsiMethod)psiElement).getName().equals("myTestMethod"); } diff --git a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java index c9d5c6742a68..5962675dcbb0 100644 --- a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -188,12 +188,12 @@ public abstract class InspectionTestCase extends PsiTestCase { } @Override - public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { + public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return isEntryPoint(psiElement); } @Override - public boolean isEntryPoint(PsiElement psiElement) { + public boolean isEntryPoint(@NotNull PsiElement psiElement) { return ext_src != null && VfsUtilCore.isAncestor(ext_src, PsiUtilCore.getVirtualFile(psiElement), false); } diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java index 464ab9add995..e24167444c0c 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -28,8 +28,8 @@ public abstract class EntryPoint implements JDOMExternalizable , Cloneable { @NotNull public abstract String getDisplayName(); - public abstract boolean isEntryPoint(RefElement refElement, PsiElement psiElement); - public abstract boolean isEntryPoint(PsiElement psiElement); + public abstract boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement); + public abstract boolean isEntryPoint(@NotNull PsiElement psiElement); public abstract boolean isSelected(); public abstract void setSelected(boolean selected); diff --git a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java index 54f0bc6e1ba9..b59854e320e6 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java +++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -45,12 +45,12 @@ public class JUnitEntryPoint extends EntryPoint { return InspectionsBundle.message("inspection.dead.code.option2"); } - public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { + public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return isEntryPoint(psiElement); } @Override - public boolean isEntryPoint(PsiElement psiElement) { + public boolean isEntryPoint(@NotNull PsiElement psiElement) { if (ADD_JUNIT_TO_ENTRIES) { if (psiElement instanceof PsiClass) { final PsiClass aClass = (PsiClass)psiElement; diff --git a/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java b/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java index 36395bcb510c..784da489907d 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java +++ b/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -48,12 +48,12 @@ public class TestNGEntryPoint extends EntryPoint { return "Automatically add all TestNG classes/methods/etc. to entry points"; } - public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { + public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return isEntryPoint(psiElement); } @Override - public boolean isEntryPoint(PsiElement psiElement) { + public boolean isEntryPoint(@NotNull PsiElement psiElement) { if (ADD_TESTNG_TO_ENTRIES) { if (psiElement instanceof PsiModifierListOwner) { if (TestNGUtil.hasTest((PsiModifierListOwner)psiElement, false, false, TestNGUtil.hasDocTagsSupport)) return true; From ec61769b7e6019a5dba5a7044d95224febddff91 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Feb 2014 16:04:48 +0400 Subject: [PATCH 53/53] less dependent on UnusedDeclarationInspection --- .../daemon/impl/PostHighlightingPass.java | 65 ++++++++----------- .../impl/PostHighlightingPassFactory.java | 19 +++++- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 36610e65fca9..f6effbe9f637 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -28,11 +28,11 @@ import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.SuppressionUtil; -import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.ex.EntryPointsManagerBase; import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider; import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; +import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase; import com.intellij.lang.Language; import com.intellij.lang.annotation.HighlightSeverity; @@ -66,6 +66,7 @@ import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.Processor; +import com.intellij.util.containers.Predicate; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -83,6 +84,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass private final PsiFile myFile; @Nullable private final Editor myEditor; private final boolean myUnusedImportEnabled; + @NotNull private final Predicate myIsEntryPointPredicate; private final int myStartOffset; private final int myEndOffset; @@ -92,10 +94,8 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass private int myCurrentEntryIndex; private boolean myHasMissortedImports; private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME); - private UnusedDeclarationInspection myDeadCodeInspection; private UnusedSymbolLocalInspectionBase myUnusedSymbolInspection; private HighlightDisplayKey myUnusedSymbolKey; - private boolean myDeadCodeEnabled; private boolean myInLibrary; private HighlightDisplayKey myDeadCodeKey; private HighlightInfoType myDeadCodeInfoType; @@ -105,11 +105,13 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass @Nullable Editor editor, @NotNull Document document, @NotNull HighlightInfoProcessor highlightInfoProcessor, - boolean unusedImportEnabled) { + boolean unusedImportEnabled, + @NotNull Predicate isEntryPoint) { super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor); myFile = file; myEditor = editor; myUnusedImportEnabled = unusedImportEnabled; + myIsEntryPointPredicate = isEntryPoint; myStartOffset = 0; myEndOffset = file.getTextLength(); @@ -207,20 +209,18 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null); myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME); - myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile); - myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, myFile); HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME); myDeadCodeInfoType = myDeadCodeKey == null - ? null + ? HighlightInfoType.UNUSED_SYMBOL : new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(), HighlightInfoType.UNUSED_SYMBOL.getAttributesKey()); GlobalUsageHelper helper = new GlobalUsageHelper() { @Override public boolean shouldCheckUsages(@NotNull PsiMember member) { - return !myInLibrary && myDeadCodeEnabled && !myDeadCodeInspection.isEntryPoint(member); + return !myInLibrary && !myIsEntryPointPredicate.apply(member); } @Override @@ -363,8 +363,10 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return isInjected(project, element); } - @Nullable - public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @NotNull String message, @NotNull final HighlightInfoType highlightInfoType) { + @Nullable + public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, + @NotNull String message, + @NotNull final HighlightInfoType highlightInfoType) { HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create(); if (info == null) { return null; //filtered out @@ -432,8 +434,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass return null; } else if (isFieldUnused(myProject, myFile, field, progress, helper)) { - return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier - ); + return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier); } return null; } @@ -446,8 +447,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(project, containingFile, field, progress, helper)) { return false; } - return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper - ); + return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper); } private HighlightInfo suggestionsToMakeFieldUsed(@NotNull PsiField field, @NotNull PsiIdentifier identifier, @NotNull String message) { @@ -597,14 +597,14 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass String name = member.getName(); if (name == null) return false; SearchScope useScope = member.getUseScope(); + PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project); + PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null; if (useScope instanceof GlobalSearchScope) { // some classes may have references from within XML outside dependent modules, e.g. our actions if (member instanceof PsiClass) { useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope); } - PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project); - PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null; PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress); if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false; @@ -626,28 +626,20 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass } } } - - //FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); - //FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project)); - //FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone(); - //findUsagesOptions.searchScope = useScope; - //findUsagesOptions.isSearchForTextOccurrences = true; - //boolean old = !findUsagesManager.isUsed(member, findUsagesOptions); - - //if (true) { - if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false; - return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope); - //} - //return old; + if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false; + return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope, searchHelper, ignoreFile); } - private static boolean foundUsageInText(PsiMember member, GlobalSearchScope scope) { - PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(member.getProject()); - - return !helper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() { + private static boolean foundUsageInText(@NotNull PsiMember member, + @NotNull GlobalSearchScope scope, + @NotNull PsiSearchHelper searchHelper, + final PsiFile ignoreFile) { + return !searchHelper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() { @Override public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) { - return false; + if (psiFile == ignoreFile) return true; // ignore usages in containingFile because isLocallyUsed() method would have caught that + PsiElement element = psiFile.findElementAt(startOffset); + return element instanceof PsiComment; // ignore comments } }, scope); } @@ -706,8 +698,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass highlightDisplayKey = myDeadCodeKey; highlightInfoType = myDeadCodeInfoType; } - return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier - ); + return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier); } public static boolean isClassUsed(@NotNull Project project, @@ -741,7 +732,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern, @NotNull final PsiNameIdentifierOwner aClass, @NotNull final String element, - @NotNull HighlightDisplayKey highlightDisplayKey, + HighlightDisplayKey highlightDisplayKey, @NotNull HighlightInfoType highlightInfoType, @NotNull PsiElement identifier) { String symbolName = aClass.getName(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java index d9424beb743b..54a9bc293478 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java @@ -22,6 +22,7 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl; import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.diagnostic.Logger; @@ -32,9 +33,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.JspPsiUtil; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.jsp.JspFile; import com.intellij.psi.jsp.JspSpiUtil; +import com.intellij.util.containers.Predicate; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,11 +88,21 @@ public class PostHighlightingPassFactory extends AbstractProjectComponent implem @NotNull Document document, Editor editor, @NotNull HighlightInfoProcessor highlightInfoProcessor) { HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME); - return new PostHighlightingPass(myProject, file, editor, document, highlightInfoProcessor, isUnusedImportEnabled(unusedImportKey, file)); + InspectionProfile profile = InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile(); + boolean importEnabled = isUnusedImportEnabled(unusedImportKey, file, profile); + final UnusedDeclarationInspection myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, file); + HighlightDisplayKey myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME); + final boolean myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, file); + + return new PostHighlightingPass(myProject, file, editor, document, highlightInfoProcessor, importEnabled, new Predicate() { + @Override + public boolean apply(PsiElement member) { + return !myDeadCodeEnabled || myDeadCodeInspection.isEntryPoint(member); + } + }); } - private static boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey, @NotNull PsiFile file) { - InspectionProfile profile = InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile(); + private static boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey, @NotNull PsiFile file, InspectionProfile profile) { boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, file); if (unusedImportEnabled && JspPsiUtil.isInJspFile(file)) { final JspFile jspFile = JspPsiUtil.getJspFile(file);