From 041dd688093a160e864abe5b047f43aab2ffe080 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 27 Mar 2012 17:22:52 +0400 Subject: [PATCH 01/84] IDEA-83362: Plugin run configuration compiles whole project instead of plugin module --- .../ui/configuration/ModulesCombobox.java | 8 ++++- .../devkit/src/module/PluginModuleType.java | 12 ++++++++ .../src/run/PluginConfigurationType.java | 3 +- .../src/run/PluginRunConfiguration.java | 14 ++------- .../src/run/PluginRunConfigurationEditor.java | 29 ++++++------------- 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java index ea28984c6757..4b4ca429d416 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesCombobox.java @@ -67,9 +67,15 @@ public class ModulesCombobox extends ComboBox { } public void fillModules(@NotNull Project project) { + fillModules(project, null); + } + + public void fillModules(@NotNull Project project, final @Nullable ModuleType moduleType) { myModel.clear(); for (Module module : ModuleManager.getInstance(project).getModules()) { - myModel.add(module); + if (moduleType == null || moduleType.equals(ModuleType.get(module))) { + myModel.add(module); + } } } diff --git a/plugins/devkit/src/module/PluginModuleType.java b/plugins/devkit/src/module/PluginModuleType.java index 1336a52594c5..59b4f93aad08 100644 --- a/plugins/devkit/src/module/PluginModuleType.java +++ b/plugins/devkit/src/module/PluginModuleType.java @@ -19,6 +19,7 @@ import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.module.*; +import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; @@ -153,4 +154,15 @@ public class PluginModuleType extends ModuleType { public boolean isValidSdk(final Module module, final Sdk projectSdk) { return JavaModuleType.isValidJavaSdk(module); } + + public static Module[] getAllPluginModules(final Project project) { + List modules = new ArrayList(); + Module[] allModules = ModuleManager.getInstance(project).getModules(); + for (Module module : allModules) { + if (get(module) == getInstance()) { + modules.add(module); + } + } + return modules.toArray(new Module[modules.size()]); + } } \ No newline at end of file diff --git a/plugins/devkit/src/run/PluginConfigurationType.java b/plugins/devkit/src/run/PluginConfigurationType.java index 7d1641fc5614..a40431a6604b 100644 --- a/plugins/devkit/src/run/PluginConfigurationType.java +++ b/plugins/devkit/src/run/PluginConfigurationType.java @@ -26,6 +26,7 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.module.PluginModuleType; import javax.swing.*; import java.io.File; @@ -50,7 +51,7 @@ public class PluginConfigurationType implements ConfigurationType { public RunConfiguration createConfiguration(String name, RunConfiguration template) { final PluginRunConfiguration pluginRunConfiguration = (PluginRunConfiguration)template; if (pluginRunConfiguration.getModule() == null) { - final Module[] modules = pluginRunConfiguration.getModules(); + final Module[] modules = PluginModuleType.getAllPluginModules(pluginRunConfiguration.getProject()); if (modules.length > 0){ pluginRunConfiguration.setModule(modules[0]); } diff --git a/plugins/devkit/src/run/PluginRunConfiguration.java b/plugins/devkit/src/run/PluginRunConfiguration.java index 1a0f22c0bad3..f8fe6a24f2e7 100644 --- a/plugins/devkit/src/run/PluginRunConfiguration.java +++ b/plugins/devkit/src/run/PluginRunConfiguration.java @@ -25,7 +25,6 @@ import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdkType; @@ -39,14 +38,11 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; -import org.jetbrains.idea.devkit.module.PluginModuleType; import org.jetbrains.idea.devkit.projectRoots.IdeaJdk; import org.jetbrains.idea.devkit.projectRoots.Sandbox; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; public class PluginRunConfiguration extends RunConfigurationBase implements ModuleRunConfiguration { private Module myModule; @@ -246,14 +242,8 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu @NotNull public Module[] getModules() { - List modules = new ArrayList(); - Module[] allModules = ModuleManager.getInstance(getProject()).getModules(); - for (Module module : allModules) { - if (ModuleType.get(module) == PluginModuleType.getInstance()) { - modules.add(module); - } - } - return modules.toArray(new Module[modules.size()]); + final Module module = getModule(); + return module != null ? new Module[]{module} : Module.EMPTY_ARRAY; } public void readExternal(Element element) throws InvalidDataException { diff --git a/plugins/devkit/src/run/PluginRunConfigurationEditor.java b/plugins/devkit/src/run/PluginRunConfigurationEditor.java index 6abca2f12397..8b4ae5bdf778 100644 --- a/plugins/devkit/src/run/PluginRunConfigurationEditor.java +++ b/plugins/devkit/src/run/PluginRunConfigurationEditor.java @@ -18,14 +18,13 @@ package org.jetbrains.idea.devkit.run; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.LogFileOptions; import com.intellij.execution.ui.AlternativeJREPanel; -import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ui.configuration.ModulesCombobox; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.ui.PanelWithAnchor; import com.intellij.ui.RawCommandLineEditor; @@ -35,6 +34,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.module.PluginModuleType; import org.jetbrains.idea.devkit.projectRoots.IdeaJdk; import org.jetbrains.idea.devkit.projectRoots.Sandbox; @@ -49,9 +49,7 @@ import java.io.IOException; import java.util.ArrayList; public class PluginRunConfigurationEditor extends SettingsEditor implements PanelWithAnchor { - - private DefaultComboBoxModel myModulesModel = new DefaultComboBoxModel(); - private final JComboBox myModules = new JComboBox(myModulesModel); + private final ModulesCombobox myModules = new ModulesCombobox(); private final JBLabel myModuleLabel = new JBLabel(ExecutionBundle.message("application.configuration.use.classpath.and.jdk.of.module.label")); private final LabeledComponent myVMParameters = new LabeledComponent(); private final LabeledComponent myProgramParameters = new LabeledComponent(); @@ -73,9 +71,10 @@ public class PluginRunConfigurationEditor extends SettingsEditor(myModules.getRenderer()) { - @Override - public void customize(JList list, final Module module, int index, boolean selected, boolean hasFocus) { - if (module != null) { - setText(module.getName()); - setIcon(ModuleType.get(module).getNodeIcon(true)); - } - } - }); + myModules.fillModules(myPRC.getProject(), PluginModuleType.getInstance()); JPanel wholePanel = new JPanel(new GridBagLayout()); myVMParameters.setText(DevKitBundle.message("vm.parameters")); myVMParameters.setComponent(new RawCommandLineEditor()); From b1064c1edda2da593636e58b0bd91e92a0b40ec6 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 28 Mar 2012 14:13:45 +0400 Subject: [PATCH 02/84] fixed state for recursive visitor interrupted by ProcessCanceledException (IDEA-55374) --- platform/util/src/com/intellij/util/WalkingState.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/WalkingState.java b/platform/util/src/com/intellij/util/WalkingState.java index 9106b72fa6d2..c4bcb1db6081 100644 --- a/platform/util/src/com/intellij/util/WalkingState.java +++ b/platform/util/src/com/intellij/util/WalkingState.java @@ -48,8 +48,12 @@ public class WalkingState { if (!startedWalking) { stopped = false; startedWalking = true; - walkChildren(element); - startedWalking = false; + try { + walkChildren(element); + } + finally { + startedWalking = false; + } } } From 34bfff2e1125748de6f74731e15e329c0aea92d3 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Wed, 28 Mar 2012 14:29:03 +0400 Subject: [PATCH 03/84] optimization: getting rid of string concatenation on every accept() call --- .../openapi/fileTypes/ExtensionFileNameMatcher.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java index f7d793af382d..fb1f1d8ab1b5 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java @@ -24,13 +24,15 @@ import org.jetbrains.annotations.NotNull; */ public class ExtensionFileNameMatcher implements FileNameMatcher { private final String myExtension; - + private final String myDotExtension; + public ExtensionFileNameMatcher(@NotNull @NonNls String extension) { myExtension = extension.toLowerCase(); + myDotExtension = "." + myExtension; } public boolean accept(@NotNull @NonNls String fileName) { - return fileName.regionMatches(true, fileName.length() - myExtension.length() - 1, "." + myExtension, 0, myExtension.length() + 1); + return fileName.regionMatches(true, fileName.length() - myDotExtension.length(), myDotExtension, 0, myDotExtension.length()); } @NonNls From 11e5b893295d0ff41b04ac2ea309846d62af3034 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 28 Mar 2012 12:23:23 +0200 Subject: [PATCH 04/84] Lazily evaluate system properties which require file access --- .../com/intellij/execution/util/ExecUtil.java | 17 +++---- .../src/com/intellij/ide/BrowserUtil.java | 4 +- .../ide/actions/RevealFileAction.java | 2 +- .../ide/actions/ShowFilePathAction.java | 29 ++++++------ .../intellij/ide/actions/ShowLogAction.java | 2 +- .../fileEditor/impl/EditorsSplitters.java | 2 +- .../com/intellij/openapi/util/SystemInfo.java | 47 ++++++++++++++++--- .../VcsGeneralConfigurationPanel.java | 5 +- 8 files changed, 71 insertions(+), 37 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java index f753d2500923..cb39f5fd76f6 100644 --- a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java +++ b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java @@ -27,9 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.script.ScriptException; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -103,12 +101,15 @@ public class ExecUtil { } @Nullable - public static String execAndReadLine(@NotNull final List command) { + public static String execAndReadLine(final String... command) { try { - final ProcessOutput output = execAndGetOutput(command, null); - final List lines = output.getStdoutLines(); - if (lines.size() > 0) { - return lines.get(0); + final Process process = new GeneralCommandLine(command).createProcess(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + try { + return reader.readLine(); + } + finally { + reader.close(); } } catch (Exception ignored) { } diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 05f3d11df639..efca09d692a7 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -133,7 +133,7 @@ public class BrowserUtil { if (SystemInfo.isMac || SystemInfo.isWindows) { return true; } - else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen) { + else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { return true; } else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { @@ -152,7 +152,7 @@ public class BrowserUtil { else if (SystemInfo.isMac) { return new String[]{ExecUtil.getOpenCommandPath()}; } - else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen) { + else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { return new String[]{"xdg-open"}; } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java index cbfaa06466b8..aa929d43c63b 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java @@ -41,7 +41,7 @@ public class RevealFileAction extends DumbAwareAction { @NotNull public static String getActionName() { - return SystemInfo.isMac ? "Reveal in Finder" : "Show in " + SystemInfo.nativeFileManagerName; + return SystemInfo.isMac ? "Reveal in Finder" : "Show in " + SystemInfo.getFileManagerName(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java index c7a065c40589..7d29e02c02a6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java @@ -35,6 +35,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.JarFileSystem; @@ -51,11 +52,19 @@ import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; public class ShowFilePathAction extends AnAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.ShowFilePathAction"); + private static NotNullLazyValue hasNautilusV3 = new NotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + final String version = ExecUtil.execAndReadLine("nautilus", "--version"); + return version != null && version.startsWith("GNOME nautilus 3"); + } + }; + @Override public void update(final AnActionEvent e) { if (SystemInfo.isMac || !isSupported()) { @@ -166,7 +175,7 @@ public class ShowFilePathAction extends AnAction { public static boolean isSupported() { return SystemInfo.isWindows || Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN) || - SystemInfo.hasXdgOpen || SystemInfo.hasNautilus; + SystemInfo.hasXdgOpen() || SystemInfo.hasNautilus(); } /** @deprecated use {@linkplain #openFile(java.io.File)} (to remove in IDEA 13) */ @@ -231,7 +240,7 @@ public class ShowFilePathAction extends AnAction { return; } - if (Registry.is("ide.use.nautilus3") && SystemInfo.hasNautilus && hasNautilusV3()) { + if (Registry.is("ide.use.nautilus3") && SystemInfo.hasNautilus() && hasNautilusV3.getValue()) { if (toSelect != null) { new GeneralCommandLine("nautilus", toSelect.getCanonicalPath()).createProcess(); } @@ -242,10 +251,10 @@ public class ShowFilePathAction extends AnAction { } final String path = dir.getCanonicalPath(); - if (SystemInfo.hasXdgOpen) { + if (SystemInfo.hasXdgOpen()) { new GeneralCommandLine("/usr/bin/xdg-open", path).createProcess(); } - else if (SystemInfo.hasNautilus) { + else if (SystemInfo.hasNautilus()) { new GeneralCommandLine("nautilus", path).createProcess(); } else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) { @@ -256,16 +265,6 @@ public class ShowFilePathAction extends AnAction { } } - private static Boolean hasNautilusV3 = null; - - private static boolean hasNautilusV3() { - if (hasNautilusV3 == null) { - final String version = ExecUtil.execAndReadLine(Arrays.asList("nautilus", "--version")); - hasNautilusV3 = version != null && version.startsWith("GNOME nautilus 3"); - } - return hasNautilusV3; - } - @Nullable private static VirtualFile getFile(final AnActionEvent e) { return PlatformDataKeys.VIRTUAL_FILE.getData(e.getDataContext()); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java index 1c99f828dcf8..ed5914b49483 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowLogAction.java @@ -44,6 +44,6 @@ public class ShowLogAction extends AnAction implements DumbAware { @NotNull public static String getActionName() { - return "Reveal Log in " + SystemInfo.nativeFileManagerName; + return "Reveal Log in " + SystemInfo.getFileManagerName(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index be81bbc8b2ea..20cc6e469da5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -166,7 +166,7 @@ public class EditorsSplitters extends JPanel { painter.appendLine("Open a file by name with " + getActionShortcutText("GotoFile")).smaller().withBullet() .appendLine("Open Recent files with " + getActionShortcutText("RecentFiles")).smaller().withBullet() .appendLine("Open Navigation Bar with " + getActionShortcutText("ShowNavBar")).smaller().withBullet() - .appendLine("Drag'n'Drop file(s) here from " + SystemInfo.nativeFileManagerName).smaller().withBullet() + .appendLine("Drag'n'Drop file(s) here from " + SystemInfo.getFileManagerName()).smaller().withBullet() .draw(g, new PairFunction>() { @Override public Pair fun(Integer width, Integer height) { diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index c62c32b6a71e..5921da2f0e62 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -51,9 +51,6 @@ public class SystemInfo extends SystemInfoRt { public static final boolean isKDE = _SUN_DESKTOP.contains("kde"); public static final boolean isGnome = _SUN_DESKTOP.contains("gnome"); - public static final boolean hasNautilus = isUnix && new File("/usr/bin/nautilus").canExecute(); - public static final boolean hasXdgOpen = isUnix && new File("/usr/bin/xdg-open").canExecute(); - public static final boolean isMacSystemMenu = isMac && "true".equals(System.getProperty("apple.laf.useScreenMenuBar")); public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive; @@ -65,10 +62,46 @@ public class SystemInfo extends SystemInfoRt { public static final boolean isAMD64 = "amd64".equals(OS_ARCH); public static final boolean isMacIntel64 = isMac && "x86_64".equals(OS_ARCH); - public static final String nativeFileManagerName = isMac ? "Finder" : - isWindows ? "Explorer" : - hasNautilus ? "Nautilus" : - "File Manager"; + /** @deprecated use {@linkplain #hasXdgOpen()} (to remove in IDEA 13) */ + public static final boolean hasXdgOpen = false; + private static final NotNullLazyValue ourHasXdgOpen = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + return isUnix && new File("/usr/bin/xdg-open").canExecute(); + } + }; + public static boolean hasXdgOpen() { + return ourHasXdgOpen.getValue(); + } + + private static final NotNullLazyValue hasNautilus = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + return isUnix && new File("/usr/bin/nautilus").canExecute(); + } + }; + public static boolean hasNautilus() { + return hasNautilus.getValue(); + } + + /** @deprecated use {@linkplain #getFileManagerName()} (to remove in IDEA 13) */ + public static final String nativeFileManagerName = "File Manager"; + private static final NotNullLazyValue ourFileManagerName = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected String compute() { + return isMac ? "Finder" : + isWindows ? "Explorer" : + hasNautilus() ? "Nautilus" : + "File Manager"; + } + }; + @NotNull + public static String getFileManagerName() { + return ourFileManagerName.getValue(); + } /** * Whether IDEA is running under MacOS X version 10.4 or later. diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java index 2b1b63bf1b6f..70428d9c5989 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -95,7 +95,8 @@ public class VcsGeneralConfigurationPanel implements SearchableConfigurable { } myPromptsPanel.setSize(myPromptsPanel.getPreferredSize()); - myOnPatchCreation.setName((SystemInfo.isMac ? "Reveal patch in" : "Show patch in ") + SystemInfo.nativeFileManagerName + " after creation:"); + myOnPatchCreation.setName((SystemInfo.isMac ? "Reveal patch in" : "Show patch in ") + + SystemInfo.getFileManagerName() + " after creation:"); } public void apply() throws ConfigurationException { From 1acbe7d68b9982f3e6048c5cde822637e4571ffd Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 28 Mar 2012 12:27:15 +0200 Subject: [PATCH 05/84] Cleanup --- .../projectRoots/impl/JavaSdkImpl.java | 25 ++++++++----------- .../openapi/projectRoots/SdkType.java | 4 +-- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index ace9c134e0a7..005be2d1bd4f 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.projectRoots.impl; +import com.intellij.execution.util.ExecUtil; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.*; @@ -154,33 +155,27 @@ public class JavaSdkImpl extends JavaSdk { public String suggestHomePath() { if (SystemInfo.isMac) { if (new File("/usr/libexec/java_home").exists()) { - try { - final Process exec = Runtime.getRuntime().exec("/usr/libexec/java_home"); - final BufferedReader input = new BufferedReader(new InputStreamReader(exec.getInputStream())); - try { - final String path = input.readLine(); - if (new File(path).exists()) return path; - } - finally { - input.close(); - } + final String path = ExecUtil.execAndReadLine("/usr/libexec/java_home"); + if (path != null && new File(path).exists()) { + return path; } - catch (IOException ignore) { } } - - return "/System/Library/Frameworks/JavaVM.framework/Versions/"; + return "/System/Library/Frameworks/JavaVM.framework/Versions"; } + if (SystemInfo.isLinux) { - final String[] homes = {"/usr/java", "/opt/java", "/usr/lib/jvm/"}; + final String[] homes = {"/usr/java", "/opt/java", "/usr/lib/jvm"}; for (String home : homes) { if (new File(home).isDirectory()) { return home; } } } + if (SystemInfo.isSolaris) { - return "/usr/jdk/"; + return "/usr/jdk"; } + return null; } diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java index bc558a8e2667..3f69ade8052a 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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 abstract class SdkType { private final String myName; /** - * @return path to set up filechooser to or null if not applicable + * @return path to set up file chooser to or null if not applicable */ @Nullable public abstract String suggestHomePath(); From 8d06f7224a8b3ef3696719ff56a853d3281bb5b4 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 28 Mar 2012 14:37:19 +0400 Subject: [PATCH 06/84] IDEA-55557: Attaching jar file sources in a module dependency (to another modules src) causes classpath issues --- .../resolve/class/ModuleSourceAsLibrarySource.java | 3 +++ .../resolve/class/ModuleSourceAsLibrarySourceDep.java | 1 + .../com/intellij/psi/resolve/ResolveClassTest.java | 11 +++++++++++ .../src/com/intellij/testFramework/PsiTestCase.java | 4 ++-- .../openapi/roots/impl/DirectoryIndexImpl.java | 3 +-- 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java create mode 100644 java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java diff --git a/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java new file mode 100644 index 000000000000..ae7482c76f32 --- /dev/null +++ b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySource.java @@ -0,0 +1,3 @@ +public class ModuleSourceAsLibrarySource { + ModuleSourceAsLibrarySourceDep field; +} diff --git a/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java new file mode 100644 index 000000000000..78a8b08ecc6f --- /dev/null +++ b/java/java-tests/testData/psi/resolve/class/ModuleSourceAsLibrarySourceDep.java @@ -0,0 +1 @@ +public class ModuleSourceAsLibrarySourceDep {} diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java index b67073bfcbca..8eab910851f0 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java @@ -8,6 +8,7 @@ import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -155,6 +156,16 @@ public class ResolveClassTest extends ResolveTestCase { assertNull(target); } + public void testModuleSourceAsLibrarySource() throws Exception { + final PsiReference ref = configure(); + final VirtualFile file = ref.getElement().getContainingFile().getVirtualFile(); + assertNotNull(file); + createFile(myModule, file.getParent(), "ModuleSourceAsLibrarySourceDep.java", loadFile("class/ModuleSourceAsLibrarySourceDep.java")); + addLibraryToRoots(file.getParent(), OrderRootType.SOURCES); + + assertInstanceOf(ref.resolve(), PsiClass.class); + } + public void testStaticImportInTheSameClass() throws Exception { PsiReference ref = configure(); long start = System.currentTimeMillis(); diff --git a/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java b/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java index 35d132f23637..ec471600d9f5 100644 --- a/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java @@ -216,7 +216,7 @@ public abstract class PsiTestCase extends ModuleTestCase { addLibraryToRoots(myModule, jarFile, rootType); } - protected static void addLibraryToRoots(final Module module, final VirtualFile jarFile, final OrderRootType rootType) { + protected static void addLibraryToRoots(final Module module, final VirtualFile root, final OrderRootType rootType) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -224,7 +224,7 @@ public abstract class PsiTestCase extends ModuleTestCase { final ModifiableRootModel rootModel = manager.getModifiableModel(); final Library jarLibrary = rootModel.getModuleLibraryTable().createLibrary(); final Library.ModifiableModel libraryModel = jarLibrary.getModifiableModel(); - libraryModel.addRoot(jarFile, rootType); + libraryModel.addRoot(root, rootType); libraryModel.commit(); rootModel.commit(); } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java index 6090e7ab87ae..6c8dd4145c98 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java @@ -248,7 +248,7 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone DirectoryInfo info = stateAndDirs.first.myDirToInfoMap.get(dir); assert info != null; - if (!info.isInLibrarySource || info.libraryClassRoot != null) { + if (!info.isInLibrarySource || info.isInModuleSource || info.libraryClassRoot != null) { if (!consumer.process(dir)) return false; } } @@ -613,7 +613,6 @@ public class DirectoryIndexImpl extends DirectoryIndex implements ProjectCompone if (definedPackage != null && definedPackage.isEmpty()) return; // another library source root starts here } - info.isInModuleSource = false; info.isInLibrarySource = true; info.sourceRoot = sourceRoot; setPackageName(dir, packageName); From b4c42eb07698204c05f71ecd5954a78b4fe4774f Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 11:41:04 +0200 Subject: [PATCH 07/84] IDEA-83600: pull up for local classes --- .../refactoring/memberPullUp/PullUpDialog.java | 10 +++++++--- .../refactoring/util/RefactoringHierarchyUtil.java | 9 ++++++++- .../daemonCodeAnalyzer/quickFix/pullUp/after6.java | 14 ++++++++++++++ .../quickFix/pullUp/before6.java | 12 ++++++++++++ .../quickFix/PullOverrideMethodUpFixTest.java | 4 ++++ 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java 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 5d06e931eab2..d960ac43f833 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java @@ -192,10 +192,14 @@ public class PullUpDialog extends RefactoringDialog { protected void doAction() { if (!myCallback.checkConflicts(this)) return; JavaRefactoringSettings.getInstance().PULL_UP_MEMBERS_JAVADOC = myJavaDocPanel.getPolicy(); - StatisticsManager - .getInstance().incUseCount(new StatisticsInfo(PULL_UP_STATISTICS_KEY + myClass.getQualifiedName(), getSuperClass().getQualifiedName())); + final PsiClass superClass = getSuperClass(); + String name = superClass.getQualifiedName(); + if (name != null) { + StatisticsManager + .getInstance().incUseCount(new StatisticsInfo(PULL_UP_STATISTICS_KEY + myClass.getQualifiedName(), name)); + } - invokeRefactoring(new PullUpHelper(myClass, getSuperClass(), getSelectedMemberInfos(), + invokeRefactoring(new PullUpHelper(myClass, superClass, getSelectedMemberInfos(), new DocCommentPolicy(getJavaDocPolicy()))); close(OK_EXIT_CODE); } diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java index fda1ea726c1e..c46864483270 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java @@ -25,6 +25,7 @@ package com.intellij.refactoring.util; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; @@ -129,7 +130,13 @@ public class RefactoringHierarchyUtil { Collections.sort( basesList, new Comparator() { public int compare(PsiClass c1, PsiClass c2) { - return c1.getQualifiedName().compareTo(c2.getQualifiedName()); + final String fqn1 = c1.getQualifiedName(); + final String fqn2 = c2.getQualifiedName(); + if (fqn1 != null && fqn2 != null) return fqn1.compareTo(fqn2); + if (fqn1 == null && fqn2 == null) { + return Comparing.compare(c1.getName(), c2.getName()); + } + return fqn1 == null ? 1 : -1; } } ); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java new file mode 100644 index 000000000000..6934fb76215a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/after6.java @@ -0,0 +1,14 @@ +// "Pull method 'foo' to 'Foo' and make it abstract" "true" +public class Test { + void bar() { + abstract class Foo { + abstract void foo(); + } + class FooImpl extends Foo { + @Override + void foo(){} + } + } +} + + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java new file mode 100644 index 000000000000..6cefa7bc162a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/pullUp/before6.java @@ -0,0 +1,12 @@ +// "Pull method 'foo' to 'Foo' and make it abstract" "true" +public class Test { + void bar() { + class Foo {} + class FooImpl extends Foo { + @Override + void foo(){} + } + } +} + + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java index 2d6115085c70..5754db7eb2cb 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PullOverrideMethodUpFixTest.java @@ -34,6 +34,10 @@ public class PullOverrideMethodUpFixTest extends LightQuickFixTestCase { doSingleTest("4.java"); } + public void test6() throws Exception { + doSingleTest("6.java"); + } + public void testRefactoringIntentionsAvailable() throws Exception { doTestActionAvailable(5, "Pull members up"); doTestActionAvailable(5, "Extract interface"); From bc7e569fa1af3ac975f1fe77727dd03b6ba2a58c Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 13:25:11 +0200 Subject: [PATCH 08/84] covariant return types: difference between java7 & java6 (IDEA-83599) --- .../impl/analysis/GenericsHighlightUtil.java | 13 ++++- .../SameErasureDifferentReturnTypes.java | 4 +- .../SameErasureDifferentReturnTypesJdk14.java | 48 +++++++++++++++++++ .../daemon/GenericsHighlightingTest.java | 8 ++++ .../openapi/projectRoots/JavaSdkVersion.java | 16 +++++++ 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 4a0ed7347583..4b7f8ce86cda 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -26,6 +26,7 @@ import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; @@ -505,7 +506,17 @@ public class GenericsHighlightUtil { final PsiType retErasure1 = TypeConversionUtil.erasure(checkMethod.getReturnType()); final PsiType retErasure2 = TypeConversionUtil.erasure(superMethod.getReturnType()); - if (!Comparing.equal(retErasure1, retErasure2) && + + boolean differentReturnTypeErasure = !Comparing.equal(retErasure1, retErasure2); + if (checkEqualsSuper && JavaSdkVersion.isAtLeast(checkMethod, JavaSdkVersion.JDK_1_7)) { + if (retErasure1 != null && retErasure2 != null) { + differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2); + } else { + differentReturnTypeErasure = !(retErasure1 == null && retErasure2 == null); + } + } + + if (differentReturnTypeErasure && !TypeConversionUtil.isVoidType(retErasure1) && !TypeConversionUtil.isVoidType(retErasure2) && !(checkEqualsSuper && Arrays.equals(superSignature.getParameterTypes(), signatureToCheck.getParameterTypes()))) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java index f203f95c25de..8bbd7b65154a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypes.java @@ -7,7 +7,7 @@ interface Matcher { } interface ArgumentConstraintPhrases { - T with(Matcher matcher); + T with(Matcher matcher); boolean with(Matcher matcher); byte with(Matcher matcher); short with(Matcher matcher); @@ -19,7 +19,7 @@ interface ArgumentConstraintPhrases { class ExpectationGroupBuilder implements ArgumentConstraintPhrases { - public T with(final Matcher matcher) { + public T with(final Matcher matcher) { return null; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java new file mode 100644 index 000000000000..b046069c784a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SameErasureDifferentReturnTypesJdk14.java @@ -0,0 +1,48 @@ +/** @noinspection UnusedDeclaration*/ +interface Matcher { + + boolean matches(Object object); + + void _dont_implement_Matcher___instead_extend_BaseMatcher_(); +} + +interface ArgumentConstraintPhrases { + T with(Matcher matcher); + boolean with(Matcher matcher); + byte with(Matcher matcher); + int with(Matcher matcher); + long with(Matcher matcher); + float with(Matcher matcher); + double with(Matcher matcher); +} + +class ExpectationGroupBuilder implements ArgumentConstraintPhrases { + + public T with(final Matcher matcher) { + return null; + } + + public boolean with(final Matcher matcher) { + return false; + } + + public byte with(final Matcher matcher) { + return 0; + } + + public int with(final Matcher matcher) { + return 0; + } + + public long with(final Matcher matcher) { + return 0; + } + + public float with(final Matcher matcher) { + return 0; + } + + public double with(final Matcher matcher) { + return 0; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index d33381ec1e2e..c8ed0105e79a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -4,6 +4,8 @@ import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiClass; @@ -34,6 +36,11 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(level); } + @Override + protected Sdk getProjectJDK() { + return getTestName(false).contains("Jdk14") ? JavaSdkImpl.getMockJdk14() : super.getProjectJDK(); + } + public void testReferenceTypeParams() throws Exception { doTest(false); } public void testOverridingMethods() throws Exception { doTest(false); } public void testTypeParameterBoundsList() throws Exception { doTest(false); } @@ -85,6 +92,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testGenericExtendException() throws Exception { doTest(false); } public void testSameErasureDifferentReturnTypes() throws Exception { doTest(false); } + public void testSameErasureDifferentReturnTypesJdk14() throws Exception { doTest(false); } public void testDeepConflictingReturnTypes() throws Exception { doTest(false); } public void testInheritFromTypeParameter() throws Exception { doTest(false); } public void testAnnotationsAsPartOfModifierList() throws Exception { doTest(false); } diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 57a56966449f..2d7e6629ad3b 100644 --- a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -15,7 +15,11 @@ */ package com.intellij.openapi.projectRoots; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -70,4 +74,16 @@ public enum JavaSdkVersion { String.format("Can't map Java SDK by description (%s). Available values: %s", description, Arrays.toString(values())) ); } + + public static boolean isAtLeast(PsiElement element, JavaSdkVersion minVersion) { + final Module module = ModuleUtil.findModuleForPsiElement(element); + if (module != null) { + final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { + final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk); + return version != null && version.isAtLeast(minVersion); + } + } + return false; + } } From aff5a3dde2db3f7d6bd92324e7b54f068506c701 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 14:02:20 +0400 Subject: [PATCH 09/84] EA-34566 - ROME: DocumentImpl.replaceString --- .../find/editorHeaderActions/Utils.java | 23 +------------------ .../LivePreviewControllerBase.java | 6 ++--- .../openapi/vfs/ReadonlyStatusHandler.java | 21 +++++++++++++++++ .../diff/impl/incrementalMerge/Change.java | 4 ++-- .../impl/incrementalMerge/ChangeType.java | 5 +++- .../openapi/diff/impl/util/DocumentUtil.java | 3 ++- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java index 0b5249e6757e..03c5c8592feb 100644 --- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java @@ -1,14 +1,9 @@ package com.intellij.find.editorHeaderActions; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.vfs.ReadonlyStatusHandler; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; import javax.swing.*; import javax.swing.text.JTextComponent; @@ -42,7 +37,7 @@ public class Utils { .setRequestFocus(true).setItemChoosenCallback(callback).createPopup(); if (ad != null) { - popup.setAdText(ad, SwingUtilities.LEFT); + popup.setAdText(ad, SwingConstants.LEFT); } if (toolbarComponent != null) { @@ -72,20 +67,4 @@ public class Utils { } } } - - public static boolean ensureOkToWrite(Editor e) { - final PsiFile psiFile = PsiDocumentManager.getInstance(e.getProject()).getPsiFile(e.getDocument()); - boolean okWritable; - if (psiFile != null) { - final VirtualFile virtualFile = psiFile.getVirtualFile(); - if (virtualFile != null) { - okWritable = ReadonlyStatusHandler.ensureFilesWritable(e.getProject(), virtualFile); - } else { - okWritable = psiFile.isWritable(); - } - } else { - okWritable = e.getDocument().isWritable(); - } - return okWritable; - } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java index a4d145e343bc..c746ee722c2f 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java @@ -3,13 +3,13 @@ package com.intellij.find.impl.livePreview; import com.intellij.find.FindManager; import com.intellij.find.FindModel; import com.intellij.find.FindUtil; -import com.intellij.find.editorHeaderActions.Utils; import com.intellij.find.impl.FindResultImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.util.Alarm; import org.jetbrains.annotations.Nullable; @@ -169,7 +169,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Nullable @Override public TextRange performReplace(final LiveOccurrence occurrence, final String replacement, final Editor editor) { - if (myReplaceDenied || !Utils.ensureOkToWrite(editor)) return null; + if (myReplaceDenied || !ReadonlyStatusHandler.ensureDocumentWritable(editor.getProject(), editor.getDocument())) return null; TextRange range = occurrence.getPrimaryRange(); FindModel findModel = mySearchResults.getFindModel(); TextRange result = null; @@ -197,7 +197,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Override public void performReplaceAll(Editor e) { - if (!Utils.ensureOkToWrite(e)) return; + if (!ReadonlyStatusHandler.ensureDocumentWritable(e.getProject(), e.getDocument())) return; if (mySearchResults.getFindModel() != null) { final FindModel copy = new FindModel(); copy.copyFrom(mySearchResults.getFindModel()); diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java b/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java index 53c8c5b651be..21ddd3bd36c4 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java @@ -16,7 +16,10 @@ package com.intellij.openapi.vfs; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -26,6 +29,24 @@ public abstract class ReadonlyStatusHandler { return !getInstance(project).ensureFilesWritable(files).hasReadonlyFiles(); } + public static boolean ensureDocumentWritable(@NotNull Project project, @NotNull Document document) { + final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + boolean okWritable; + if (psiFile != null) { + final VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile != null) { + okWritable = ensureFilesWritable(project, virtualFile); + } + else { + okWritable = psiFile.isWritable(); + } + } + else { + okWritable = document.isWritable(); + } + return okWritable; + } + public abstract static class OperationStatus { @NotNull public abstract VirtualFile[] getReadonlyFiles(); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java index faca9fb447ed..553b31a4e6f2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java @@ -40,13 +40,13 @@ import java.util.Comparator; public abstract class Change { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.Change"); - private void apply(FragmentSide original) { + private void apply(@NotNull FragmentSide original) { FragmentSide targetSide = original.otherSide(); RangeMarker originalRangeMarker = getRangeMarker(original); RangeMarker rangeMarker = getRangeMarker(targetSide); if (originalRangeMarker != null && rangeMarker != null) { - ChangeType.apply(originalRangeMarker, rangeMarker); + ChangeType.apply(getProject(), originalRangeMarker, rangeMarker); if (isValid()) { removeFromList(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java index e444ae67651e..fceefcf3cdf3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java @@ -25,7 +25,9 @@ import com.intellij.openapi.editor.markup.HighlighterLayer; import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.SeparatorPlacement; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -92,8 +94,9 @@ public class ChangeType { return CHANGE; } - public static void apply(RangeMarker original, RangeMarker target) { + public static void apply(@NotNull Project project, @NotNull RangeMarker original, @NotNull RangeMarker target) { Document document = target.getDocument(); + if (!ReadonlyStatusHandler.ensureDocumentWritable(project, document)) return; if (DocumentUtil.isEmpty(original)) { int offset = target.getStartOffset(); document.deleteString(offset, target.getEndOffset()); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java index b1567ece92f1..d15496b1a543 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/DocumentUtil.java @@ -17,6 +17,7 @@ package com.intellij.openapi.diff.impl.util; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; +import org.jetbrains.annotations.NotNull; public class DocumentUtil { @@ -24,7 +25,7 @@ public class DocumentUtil { return range.getDocument().getText().substring(range.getStartOffset(), range.getEndOffset()); } - public static boolean isEmpty(RangeMarker rangeMarker) { + public static boolean isEmpty(@NotNull RangeMarker rangeMarker) { return rangeMarker.getStartOffset() == rangeMarker.getEndOffset(); } From 1ac7fa4835903d2ffc5a4a9fc54ecd2452d4c13a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 14:12:33 +0400 Subject: [PATCH 10/84] EA-33742 - IAE: RangeMarkerImpl. --- .../platform-api/src/com/intellij/util/ui/RangeBlinker.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java b/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java index 059da22b5e34..f4f815b77116 100644 --- a/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java +++ b/platform/platform-api/src/com/intellij/util/ui/RangeBlinker.java @@ -73,8 +73,9 @@ public class RangeBlinker { MarkupModel markupModel = myEditor.getMarkupModel(); if (show) { - for (Segment rangeMarker : myMarkers) { - RangeHighlighter highlighter = markupModel.addRangeHighlighter(rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), + for (Segment segment : myMarkers) { + if (segment.getEndOffset() > myEditor.getDocument().getTextLength()) continue; + RangeHighlighter highlighter = markupModel.addRangeHighlighter(segment.getStartOffset(), segment.getEndOffset(), HighlighterLayer.ADDITIONAL_SYNTAX, myAttributes, HighlighterTargetArea.EXACT_RANGE); myAddedHighlighters.add(highlighter); @@ -85,6 +86,7 @@ public class RangeBlinker { } stopBlinking(); myBlinkingAlarm.addRequest(new Runnable() { + @Override public void run() { if (myTimeToLive > 0 || show) { myTimeToLive--; From 0ced40f7cc9b378a09051b572056aa6240efd538 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 14:16:15 +0400 Subject: [PATCH 11/84] EA-33658 - IAE: PsiDocumentManager.getInstance --- .../psi/impl/source/tree/injected/InjectedLanguageUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 84129b3b623a..93b19edb27b4 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -162,7 +162,9 @@ public class InjectedLanguageUtil { @NotNull public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, final PsiFile injectedFile) { if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed()) return hostEditor; - Document document = PsiDocumentManager.getInstance(hostEditor.getProject()).getDocument(injectedFile); + Project project = hostEditor.getProject(); + if (project == null) project = injectedFile.getProject(); + Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile); if (!(document instanceof DocumentWindowImpl)) return hostEditor; DocumentWindowImpl documentWindow = (DocumentWindowImpl)document; SelectionModel selectionModel = hostEditor.getSelectionModel(); From 95f7e8e5223647b3fb2199efc222606816f97b9d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 14:19:38 +0400 Subject: [PATCH 12/84] return -1 for not found severity --- .../intellij/codeInsight/daemon/impl/SeverityRegistrar.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index 4d01d1451764..676113932b20 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -345,9 +345,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator Date: Tue, 27 Mar 2012 14:25:51 +0400 Subject: [PATCH 13/84] correct index --- .../intellij/codeInsight/daemon/impl/SeverityRegistrar.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index 676113932b20..f153046f4b0d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon.impl; +import com.google.common.primitives.Ints; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -265,7 +266,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator Date: Tue, 27 Mar 2012 14:32:38 +0400 Subject: [PATCH 14/84] EA-33358 - AIOOBE: TextOccurrencesUtil$.process --- .../com/intellij/refactoring/util/TextOccurrencesUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java b/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java index b8b69cea51eb..ab7c5ef996e4 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/util/TextOccurrencesUtil.java @@ -108,11 +108,14 @@ public class TextOccurrencesUtil { @NotNull String stringToSearch, @NotNull final Collection results, @NotNull final UsageInfoFactory factory) { + final Object lock = new Object(); processUsagesInStringsAndComments(element, stringToSearch, false, new PairProcessor() { public boolean process(PsiElement commentOrLiteral, TextRange textRange) { UsageInfo usageInfo = factory.createUsageInfo(commentOrLiteral, textRange.getStartOffset(), textRange.getEndOffset()); if (usageInfo != null) { - results.add(usageInfo); + synchronized (lock) { + results.add(usageInfo); + } } return true; } From b6c3970623608bbe7475bb8bfb3394571b84c51d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 14:59:49 +0400 Subject: [PATCH 15/84] diagnostics --- .../daemon/impl/TextEditorHighlightingPassRegistrarImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TextEditorHighlightingPassRegistrarImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TextEditorHighlightingPassRegistrarImpl.java index cfd533138da4..c7920c9bb54c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TextEditorHighlightingPassRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TextEditorHighlightingPassRegistrarImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiCompiledElement; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.ArrayUtil; import gnu.trove.*; import org.jetbrains.annotations.NotNull; @@ -111,7 +112,8 @@ public class TextEditorHighlightingPassRegistrarImpl extends TextEditorHighlight if (!(fileFromDoc instanceof PsiCompiledElement)) { assert fileFromDoc == psiFile : "Files are different: " + psiFile + ";" + fileFromDoc; Document documentFromFile = documentManager.getDocument(psiFile); - assert documentFromFile == document : "Documents are different: " + document + ";" + documentFromFile; + assert documentFromFile == document : "Documents are different. Doc: " + document + "; Doc from file: " + documentFromFile +"; File: "+psiFile +"; Virtual file: "+ + PsiUtilCore.getVirtualFile(psiFile); } final TIntObjectHashMap id2Pass = new TIntObjectHashMap(); final TIntArrayList passesRefusedToCreate = new TIntArrayList(); From 4aacb96f11250cfaceff9fb27d19a03537bf972c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 15:00:43 +0400 Subject: [PATCH 16/84] notnull --- .../artifacts/nodes/PackagingElementNode.java | 1 + .../artifacts/sourceItems/SourceItemNode.java | 2 + .../sourceItems/SourceItemsTreeRoot.java | 1 + .../ProjectStructureDaemonAnalyzer.java | 1 + .../classpath/ChooseLibrariesDialogBase.java | 1 + .../src/com/intellij/slicer/SliceNode.java | 1 + .../impl/DaemonTooltipRendererProvider.java | 3 +- .../formattingblocks/BlockTreeNode.java | 2 + .../impl/NativeFileIconProvider.java | 2 + .../src/com/intellij/ide/UiActivity.java | 2 + .../ide/projectView/PresentationData.java | 1 + .../intellij/openapi/util/ActiveRunnable.java | 5 +- .../src/com/intellij/ui/navigation/Place.java | 1 + .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 1 + .../intellij/ui/treeStructure/SimpleNode.java | 2 + .../filtered/FilteringTreeStructure.java | 1 + .../ex/ErrorStripTooltipRendererProvider.java | 3 +- .../editor/impl/EditorMarkupModelImpl.java | 3 +- .../wm/impl/content/ToolWindowContentUi.java | 1 + .../src/com/intellij/ui/HeavyweightHint.java | 6 +- .../src/com/intellij/ui/Hint.java | 6 +- .../src/com/intellij/ui/LightweightHint.java | 101 +++++++++++------- .../util/ui/update/ComparableObject.java | 15 +-- .../util/xml/tree/BaseDomElementNode.java | 1 + .../util/xml/tree/DomElementsGroupNode.java | 2 + .../util/xml/tree/GenericValueNode.java | 2 + 26 files changed, 112 insertions(+), 55 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java index 74f8c0882532..e4e49aa18b0e 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/nodes/PackagingElementNode.java @@ -80,6 +80,7 @@ public class PackagingElementNode> extends Artifac return myPackagingElements.size() == 1 ? myPackagingElements.get(0) : null; } + @NotNull @Override public Object[] getEqualityObjects() { return ArrayUtil.toObjectArray(myPackagingElements); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java index 35dcd13d1c2d..3abe7671318a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemNode.java @@ -20,6 +20,7 @@ import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactEditorEx; import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingSourceItem; import com.intellij.ui.treeStructure.SimpleTree; +import org.jetbrains.annotations.NotNull; import java.awt.event.InputEvent; import java.util.Collections; @@ -35,6 +36,7 @@ public class SourceItemNode extends SourceItemNodeBase { mySourceItem = sourceItem; } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[]{mySourceItem}; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java index c094f3caa5bc..fa83689521e5 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/SourceItemsTreeRoot.java @@ -35,6 +35,7 @@ public class SourceItemsTreeRoot extends SourceItemNodeBase { return null; } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[]{"root"}; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java index 7d1e7c43b49f..b63cc1e5592e 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java @@ -290,6 +290,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable { return myElement.equals(other.myElement) && (!other.myCheck || myCheck) && (!other.myCollectUsages || myCollectUsages); } + @NotNull @Override public Object[] getEqualityObjects() { return myEqualityObjects; diff --git a/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java b/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java index 2598cc730981..97649e847afb 100644 --- a/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java +++ b/java/idea-ui/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java @@ -269,6 +269,7 @@ public abstract class ChooseLibrariesDialogBase extends DialogWrapper { return 0; } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myElement}; diff --git a/java/java-impl/src/com/intellij/slicer/SliceNode.java b/java/java-impl/src/com/intellij/slicer/SliceNode.java index 7247b7f0e31b..df114e5f9751 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceNode.java +++ b/java/java-impl/src/com/intellij/slicer/SliceNode.java @@ -144,6 +144,7 @@ public class SliceNode extends AbstractTreeNode implements Duplicate @Override protected PresentationData createPresentation() { return new PresentationData(){ + @NotNull @Override public Object[] getEqualityObjects() { return ArrayUtil.append(super.getEqualityObjects(), changed); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java index 00d0e8345a60..822e68e24e21 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java @@ -111,8 +111,9 @@ public class DaemonTooltipRendererProvider implements ErrorStripTooltipRendererP return new MyRenderer(text, width, new Object[] {text}); } + @NotNull @Override - public TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor) { + public TrafficTooltipRenderer createTrafficTooltipRenderer(@NotNull Runnable onHide, @NotNull Editor editor) { return new TrafficTooltipRendererImpl(onHide, editor); } diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java b/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java index 624c8d643c4f..057beb6772be 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/formattingblocks/BlockTreeNode.java @@ -7,6 +7,7 @@ import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.treeStructure.SimpleNode; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import java.awt.*; public class BlockTreeNode extends SimpleNode { @@ -56,6 +57,7 @@ public class BlockTreeNode extends SimpleNode { } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[]{myBlock}; diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java index 92d3cfa6a88b..2793909588ed 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java @@ -27,6 +27,7 @@ import com.intellij.ui.DeferredIconImpl; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.util.Function; import com.intellij.util.ui.update.ComparableObject; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -134,6 +135,7 @@ public class NativeFileIconProvider implements FileIconProvider { myText = new Object[] {text, flags}; } + @NotNull public Object[] getEqualityObjects() { return myText; } diff --git a/platform/platform-api/src/com/intellij/ide/UiActivity.java b/platform/platform-api/src/com/intellij/ide/UiActivity.java index baf0d0ce9105..9066837fb0a8 100644 --- a/platform/platform-api/src/com/intellij/ide/UiActivity.java +++ b/platform/platform-api/src/com/intellij/ide/UiActivity.java @@ -17,6 +17,7 @@ package com.intellij.ide; import com.intellij.util.ui.update.ComparableObject; import com.intellij.util.ui.update.ComparableObjectCheck; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -38,6 +39,7 @@ public class UiActivity implements ComparableObject{ } } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myElements}; diff --git a/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java b/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java index 0f9a05a55653..146be9277bce 100644 --- a/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java +++ b/platform/platform-api/src/com/intellij/ide/projectView/PresentationData.java @@ -247,6 +247,7 @@ public class PresentationData implements ColoredItemPresentation, ComparableObje mySeparatorAbove = false; } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myOpenIcon, myClosedIcon, myColoredText, myAttributesKey, myFont, myForcedTextForeground, myPresentableText, myLocationString, mySeparatorAbove}; diff --git a/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java b/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java index df59623806dd..d18d087232c2 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java +++ b/platform/platform-api/src/com/intellij/openapi/util/ActiveRunnable.java @@ -16,17 +16,18 @@ package com.intellij.openapi.util; import com.intellij.util.ui.update.ComparableObject; +import org.jetbrains.annotations.NotNull; public abstract class ActiveRunnable extends ComparableObject.Impl { protected ActiveRunnable() { } - protected ActiveRunnable(final Object object) { + protected ActiveRunnable(@NotNull Object object) { super(object); } - protected ActiveRunnable(final Object[] objects) { + protected ActiveRunnable(@NotNull Object[] objects) { super(objects); } diff --git a/platform/platform-api/src/com/intellij/ui/navigation/Place.java b/platform/platform-api/src/com/intellij/ui/navigation/Place.java index cc88c74b6745..1bddf5a01215 100644 --- a/platform/platform-api/src/com/intellij/ui/navigation/Place.java +++ b/platform/platform-api/src/com/intellij/ui/navigation/Place.java @@ -29,6 +29,7 @@ public class Place implements ComparableObject { private LinkedHashMap myPath = new LinkedHashMap(); + @NotNull public final Object[] getEqualityObjects() { return new Object[] {myPath}; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 53ec6dcc98ab..4ec35a3fd404 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -3221,6 +3221,7 @@ public class JBTabsImpl extends JComponent return myInfo.getText(); } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myInfo}; diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java index f39d2581d301..780680254082 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleNode.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.FileStatus; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.update.ComparableObject; import com.intellij.util.ui.update.ComparableObjectCheck; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -263,6 +264,7 @@ public abstract class SimpleNode extends PresentableNodeDescriptor implements Co return list.toArray(new ColoredFragment[list.size()]); } + @NotNull public Object[] getEqualityObjects() { return NONE; } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java index 9b391992054f..b8b944ff8a46 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeStructure.java @@ -243,6 +243,7 @@ public class FilteringTreeStructure extends AbstractTreeStructure { return super.getWeight(); } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myDelegate}; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java index 195fe6ffcd35..9236d90ae977 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java @@ -34,5 +34,6 @@ public interface ErrorStripTooltipRendererProvider { TooltipRenderer calcTooltipRenderer(@NotNull String text); TooltipRenderer calcTooltipRenderer(@NotNull String text, int width); - TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor); + @NotNull + TrafficTooltipRenderer createTrafficTooltipRenderer(@NotNull Runnable onHide, @NotNull Editor editor); } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 698ddff7dabd..2b11e3e28c5a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -813,8 +813,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark return new LineTooltipRenderer(text, width, new Object[] {text}); } + @NotNull @Override - public TrafficTooltipRenderer createTrafficTooltipRenderer(final Runnable onHide, Editor editor) { + public TrafficTooltipRenderer createTrafficTooltipRenderer(@NotNull final Runnable onHide, @NotNull Editor editor) { return new TrafficTooltipRenderer() { @Override public void repaintTooltipWindow() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java index 460b3ffe3810..a47f9ca87997 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java @@ -556,6 +556,7 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh return myContent.getDisplayName(); } + @NotNull @Override public Object[] getEqualityObjects() { return new Object[] {myContent}; diff --git a/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java b/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java index e6f2553604c3..374c3fa89a0c 100644 --- a/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java @@ -115,17 +115,17 @@ public class HeavyweightHint implements Hint { } @Override - public void setLocation(RelativePoint point) { + public void setLocation(@NotNull RelativePoint point) { if (myWindow != null) { myWindow.setLocation(point.getScreenPoint().x, point.getScreenPoint().y); } } - public void addHintListener(HintListener listener) { + public void addHintListener(@NotNull HintListener listener) { myListenerList.add(HintListener.class, listener); } - public void removeHintListener(HintListener listener) { + public void removeHintListener(@NotNull HintListener listener) { myListenerList.remove(HintListener.class, listener); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/Hint.java b/platform/platform-impl/src/com/intellij/ui/Hint.java index 451ee6fbffd9..bbdba268e32b 100644 --- a/platform/platform-impl/src/com/intellij/ui/Hint.java +++ b/platform/platform-impl/src/com/intellij/ui/Hint.java @@ -48,13 +48,13 @@ public interface Hint { */ void hide(); - void addHintListener(HintListener listener); + void addHintListener(@NotNull HintListener listener); - void removeHintListener(HintListener listener); + void removeHintListener(@NotNull HintListener listener); void pack(); - void setLocation(RelativePoint point); + void setLocation(@NotNull RelativePoint point); /** * Pack and set location diff --git a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java index 0f09b4ec66dc..895b38a61e3e 100644 --- a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java @@ -110,6 +110,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { * are in parentComponent coordinate system. Note that the component * appears on 250 layer. */ + @Override public void show(@NotNull final JComponent parentComponent, final int x, final int y, @@ -129,29 +130,33 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myComponent.validate(); if (!myForceShowAsPopup && - (myForceLightweightPopup || fitsLayeredPane(layeredPane, myComponent, new RelativePoint(parentComponent, new Point(x, y)), hintHint))) { + (myForceLightweightPopup || + fitsLayeredPane(layeredPane, myComponent, new RelativePoint(parentComponent, new Point(x, y)), hintHint))) { beforeShow(); final Dimension preferredSize = myComponent.getPreferredSize(); if (hintHint.isAwtTooltip()) { - IdeTooltip tooltip = new IdeTooltip(hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent, hintHint, myComponent) { - @Override - protected boolean canAutohideOn(TooltipEvent event) { - if (event.getInputEvent() instanceof MouseEvent) { - return !(hintHint.isContentActive() && event.isIsEventInsideBalloon()); - } else if (event.getAction() != null) { - return false; - } else { - return true; + IdeTooltip tooltip = + new IdeTooltip(hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent, hintHint, myComponent) { + @Override + protected boolean canAutohideOn(TooltipEvent event) { + if (event.getInputEvent() instanceof MouseEvent) { + return !(hintHint.isContentActive() && event.isIsEventInsideBalloon()); + } + else if (event.getAction() != null) { + return false; + } + else { + return true; + } } - } - @Override - protected void onHidden() { - fireHintHidden(); - TooltipController.getInstance().resetCurrent(); - } + @Override + protected void onHidden() { + fireHintHidden(); + TooltipController.getInstance().resetCurrent(); + } @Override public boolean canBeDismissedOnTimeout() { @@ -170,7 +175,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { .setHint(true); myComponent.validate(); myCurrentIdeTooltip = IdeTooltipManager.getInstance().show(tooltip, hintHint.isShowImmediately()); - } else { + } + else { final Point layeredPanePoint = SwingUtilities.convertPoint(parentComponent, x, y, layeredPane); myComponent.setBounds(layeredPanePoint.x, layeredPanePoint.y, preferredSize.width, preferredSize.height); layeredPane.add(myComponent, JLayeredPane.POPUP_LAYER); @@ -218,8 +224,9 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myPopup.show(new RelativePoint(myParentComponent, new Point(actualPoint.x, actualPoint.y))); } } - - protected void onPopupCancel() {} + + protected void onPopupCancel() { + } private void fixActualPoint(Point actualPoint) { if (!isAwtTooltip()) return; @@ -263,11 +270,13 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (pos == Balloon.Position.above || pos == Balloon.Position.below) { boolean heightFit = target.y - size.height - pointer > 0 || target.y + size.height + pointer < paneSize.height; return heightFit && size.width + pointer < paneSize.width; - } else { + } + else { boolean widthFit = target.x - size.width - pointer > 0 || target.x + size.width + pointer < paneSize.width; return widthFit && size.height + pointer < paneSize.height; } - } else { + } + else { final Rectangle lpRect = new Rectangle(pane.getLocationOnScreen().x, pane.getLocationOnScreen().y, pane.getWidth(), pane.getHeight()); Rectangle componentRect = new Rectangle(desiredLocation.getScreenPoint().x, desiredLocation.getScreenPoint().y, @@ -291,12 +300,15 @@ public class LightweightHint extends UserDataHolderBase implements Hint { return myComponent.getBounds(); } + @Override public boolean isVisible() { if (myIsRealPopup) { return myPopup != null && myPopup.isVisible(); - } else if (myCurrentIdeTooltip != null) { + } + else if (myCurrentIdeTooltip != null) { return myComponent.isShowing() || IdeTooltipManager.getInstance().isQueuedToShow(myCurrentIdeTooltip); - } else { + } + else { return myComponent.isShowing(); } } @@ -305,6 +317,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { return myIsRealPopup | myForceShowAsPopup; } + @Override public void hide() { hide(false); } @@ -314,7 +327,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (myIsRealPopup) { if (ok) { myPopup.closeOk(null); - } else { + } + else { myPopup.cancel(); } myPopup = null; @@ -324,7 +338,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { IdeTooltip tooltip = myCurrentIdeTooltip; myCurrentIdeTooltip = null; tooltip.hide(); - } else { + } + else { final JRootPane rootPane = myComponent.getRootPane(); if (rootPane != null) { final Rectangle bounds = myComponent.getBounds(); @@ -375,11 +390,13 @@ public class LightweightHint extends UserDataHolderBase implements Hint { return myComponent; } - public final void addHintListener(final HintListener listener) { + @Override + public final void addHintListener(@NotNull final HintListener listener) { myListenerList.add(HintListener.class, listener); } - public final void removeHintListener(final HintListener listener) { + @Override + public final void removeHintListener(@NotNull final HintListener listener) { myListenerList.remove(HintListener.class, listener); } @@ -388,13 +405,14 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (isRealPopup()) { location = myPopup.getLocationOnScreen(); SwingUtilities.convertPointFromScreen(location, c); - } else { + } + else { if (myCurrentIdeTooltip != null) { Point tipPoint = myCurrentIdeTooltip.getPoint(); Component tipComponent = myCurrentIdeTooltip.getComponent(); return SwingUtilities.convertPoint(tipComponent, tipPoint, c); - - } else { + } + else { location = SwingUtilities.convertPoint( myComponent.getParent(), myComponent.getLocation(), @@ -407,10 +425,11 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } @Override - public void setLocation(RelativePoint point) { + public void setLocation(@NotNull RelativePoint point) { if (isRealPopup()) { myPopup.setLocation(point.getScreenPoint()); - } else { + } + else { if (myCurrentIdeTooltip != null) { Point screenPoint = point.getScreenPoint(); if (!screenPoint.equals(new RelativePoint(myCurrentIdeTooltip.getComponent(), myCurrentIdeTooltip.getPoint()).getScreenPoint())) { @@ -418,7 +437,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myCurrentIdeTooltip.setComponent(point.getComponent()); IdeTooltipManager.getInstance().show(myCurrentIdeTooltip, true, false); } - } else { + } + else { Point targetPoint = point.getPoint(myComponent.getParent()); myComponent.setLocation(targetPoint); @@ -431,11 +451,13 @@ public class LightweightHint extends UserDataHolderBase implements Hint { public void setSize(Dimension size) { if (myIsRealPopup) { myPopup.setSize(size); - } else { + } + else { //todo kirillk if (isAwtTooltip()) { return; - } else { + } + else { myComponent.setSize(size); myComponent.revalidate(); @@ -458,14 +480,17 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (myIsRealPopup) { Window wnd = SwingUtilities.getWindowAncestor(myComponent); return wnd.getBounds().contains(target.getScreenPoint()); - } else if (myCurrentIdeTooltip != null) { + } + else if (myCurrentIdeTooltip != null) { return myCurrentIdeTooltip.isInside(target); - } else { + } + else { return new Rectangle(myComponent.getLocationOnScreen(), myComponent.getSize()).contains(target.getScreenPoint()); } } private final class MyEscListener implements ActionListener { + @Override public final void actionPerformed(final ActionEvent e) { hide(); } @@ -477,7 +502,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } public boolean canControlAutoHide() { - return myCurrentIdeTooltip != null && myCurrentIdeTooltip.getTipComponent().isShowing() ; + return myCurrentIdeTooltip != null && myCurrentIdeTooltip.getTipComponent().isShowing(); } public IdeTooltip getCurrentIdeTooltip() { diff --git a/platform/util/src/com/intellij/util/ui/update/ComparableObject.java b/platform/util/src/com/intellij/util/ui/update/ComparableObject.java index bfe5f48d776e..dea34bd8b0f9 100644 --- a/platform/util/src/com/intellij/util/ui/update/ComparableObject.java +++ b/platform/util/src/com/intellij/util/ui/update/ComparableObject.java @@ -16,40 +16,43 @@ package com.intellij.util.ui.update; import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; public interface ComparableObject { - Object[] NONE = ArrayUtil.EMPTY_OBJECT_ARRAY; + @NotNull Object[] getEqualityObjects(); class Impl implements ComparableObject { - - private Object[] myObjects; + private final Object[] myObjects; public Impl() { this(NONE); } - public Impl(Object object) { + public Impl(@NotNull Object object) { this(new Object[] {object}); } - public Impl(Object[] objects) { + public Impl(@NotNull Object[] objects) { myObjects = objects; } + @NotNull + @Override public Object[] getEqualityObjects() { return myObjects; } + @Override public final boolean equals(Object obj) { return ComparableObjectCheck.equals(this, obj); } + @Override public final int hashCode() { return ComparableObjectCheck.hashCode(this, super.hashCode()); } } - } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java b/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java index b24e352313a1..92aaedede5a5 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/tree/BaseDomElementNode.java @@ -178,6 +178,7 @@ public class BaseDomElementNode extends AbstractDomElementNode { return consolidated; } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myDomElement}; } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java b/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java index 83fba1184617..ea8ca192df60 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/tree/DomElementsGroupNode.java @@ -28,6 +28,7 @@ import com.intellij.util.xml.highlighting.DomElementAnnotationsManager; import com.intellij.util.xml.highlighting.DomElementProblemDescriptor; import com.intellij.util.xml.highlighting.DomElementsProblemsHolder; import com.intellij.util.xml.reflect.DomCollectionChildDescription; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.ArrayList; @@ -60,6 +61,7 @@ public class DomElementsGroupNode extends AbstractDomElementNode { return simpleNodes.toArray(new SimpleNode[simpleNodes.size()]); } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myParentElement, myChildrenTagName}; } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java b/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java index 77b161179468..d71a64c4692d 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/tree/GenericValueNode.java @@ -20,6 +20,7 @@ import com.intellij.ui.treeStructure.SimpleNode; import com.intellij.util.xml.GenericDomValue; import com.intellij.util.xml.DomElement; import com.intellij.ui.SimpleTextAttributes; +import org.jetbrains.annotations.NotNull; public class GenericValueNode extends AbstractDomElementNode { protected GenericDomValue myModelElement; @@ -66,6 +67,7 @@ public class GenericValueNode extends AbstractDomElementNode { return NO_CHILDREN; } + @NotNull public Object[] getEqualityObjects() { return new Object[]{myModelElement}; } From 54d5cdeee7180e9c61d736c56b1b5cb63ff7dbc7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 15:44:54 +0400 Subject: [PATCH 17/84] off by one index --- .../codeInsight/daemon/impl/TrafficLightRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java index d34cb067fbf9..7818e095e0cf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java @@ -108,7 +108,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { private void refresh() { int maxIndex = mySeverityRegistrar.getSeverityMaxIndex(); if (errorCount != null && maxIndex == errorCount.length) return; - int[] newErrors = new int[maxIndex]; + int[] newErrors = new int[maxIndex+1]; if (errorCount != null) { System.arraycopy(errorCount, 0, newErrors, 0, Math.min(errorCount.length, newErrors.length)); } @@ -140,7 +140,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable { HighlightSeverity infoSeverity = info.getSeverity(); final int severityIdx = mySeverityRegistrar.getSeverityIdx(infoSeverity); if (severityIdx != -1) { - errorCount[severityIdx]+= delta; + errorCount[severityIdx] += delta; } } From 755640f4a2f236f1c73638584cae7b37a523dd5e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 18:01:12 +0400 Subject: [PATCH 18/84] bookmarks memleaks --- .../com/intellij/ide/bookmarks/Bookmark.java | 110 +++++++++++------- .../ide/bookmarks/BookmarkManager.java | 89 ++++++++------ .../ide/bookmarks/BookmarksListener.java | 7 +- .../projectView/impl/ProjectTreeBuilder.java | 20 +++- .../ide/bookmarks/BookmarkManagerTest.java | 62 +++++++--- ...rProcessingOnDocumentModificationTest.java | 7 +- 6 files changed, 187 insertions(+), 108 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java index a94ac1a097e4..db019a2f0eda 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/Bookmark.java @@ -26,6 +26,7 @@ import com.intellij.navigation.NavigationItem; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.HighlighterLayer; @@ -41,6 +42,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.ui.LightColors; import com.intellij.util.PlatformIcons; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,45 +54,41 @@ public class Bookmark { private final VirtualFile myFile; private final OpenFileDescriptor myTarget; - private final RangeHighlighter myHighlighter; private final Project myProject; private String myDescription; private char myMnemonic = 0; public static final Font MNEMONIC_FONT = new Font("Monospaced", 0, 11); - public Bookmark(Project project, VirtualFile file, String description) { - this(project, file, -1, description); - } - - public Bookmark(Project project, VirtualFile file, int line, String description) { + public Bookmark(@NotNull Project project, @NotNull VirtualFile file, int line, @NotNull String description) { myFile = file; myProject = project; myDescription = description; + myTarget = new OpenFileDescriptor(project, file, line, -1, true); + + Document document = FileDocumentManager.getInstance().getCachedDocument(getFile()); + if (document != null) { + createHighlighter((MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true)); + } + } + + public RangeHighlighter createHighlighter(@NotNull MarkupModelEx markup) { + final RangeHighlighter myHighlighter; + int line = getLine(); if (line >= 0) { - Document document = getDocument(); - if (document == null) { - myHighlighter = null; - } - else { - MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true); - myHighlighter = markup.addPersistentLineHighlighter(line, HighlighterLayer.ERROR + 1, null); + myHighlighter = markup.addPersistentLineHighlighter(line, HighlighterLayer.ERROR + 1, null); + if (myHighlighter != null) { + myHighlighter.setGutterIconRenderer(new MyGutterIconRenderer(this)); - - if (myHighlighter != null) { - myHighlighter.setGutterIconRenderer(new MyGutterIconRenderer()); - - myHighlighter.setErrorStripeMarkColor(Color.black); - myHighlighter.setErrorStripeTooltip(getBookmarkTooltip()); - } + myHighlighter.setErrorStripeMarkColor(Color.black); + myHighlighter.setErrorStripeTooltip(getBookmarkTooltip()); } } else { myHighlighter = null; } - - myTarget = new OpenFileDescriptor(project, file, line, -1, true); + return myHighlighter; } public Document getDocument() { @@ -98,9 +96,28 @@ public class Bookmark { } public void release() { - if (myHighlighter != null) { - myHighlighter.dispose(); + int line = getLine(); + if (line < 0) { + return; } + final Document document = getDocument(); + if (document == null) return; + MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true); + int startOffset = markup.getDocument().getLineStartOffset(line); + int endOffset = markup.getDocument().getLineEndOffset(line); + final RangeHighlighterEx[] found = new RangeHighlighterEx[1]; + markup.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor() { + @Override + public boolean process(RangeHighlighterEx highlighter) { + GutterIconRenderer renderer = highlighter.getGutterIconRenderer(); + if (renderer instanceof MyGutterIconRenderer && ((MyGutterIconRenderer)renderer).myBookmark == Bookmark.this) { + found[0] = highlighter; + return false; + } + return true; + } + }); + if (found[0] != null) found[0].dispose(); } public Icon getIcon() { @@ -123,25 +140,18 @@ public class Bookmark { myMnemonic = Character.toUpperCase(mnemonic); } + @NotNull public VirtualFile getFile() { return myFile; } @Nullable public String getNotEmptyDescription() { - return isDescriptionEmpty() ? null : myDescription; - } - - public boolean isDescriptionEmpty() { - return myDescription == null || myDescription.trim().length() == 0; - } - - OpenFileDescriptor getTarget() { - return myTarget; + return StringUtil.isEmpty(myDescription) ? null : myDescription; } public boolean isValid() { - if (!getFile().isValid() || (myHighlighter != null && !myHighlighter.isValid())) { + if (!getFile().isValid()) { return false; } @@ -156,8 +166,10 @@ public class Bookmark { } public int getLine() { - if (myHighlighter != null && myHighlighter.isValid()) { - return myHighlighter.getDocument().getLineNumber(myHighlighter.getStartOffset()); + RangeMarker marker = myTarget.getRangeMarker(); + if (marker != null && marker.isValid()) { + Document document = marker.getDocument(); + return document.getLineNumber(marker.getStartOffset()); } return myTarget.getLine(); } @@ -169,7 +181,7 @@ public class Bookmark { public String getQualifiedName() { String presentableUrl = myFile.getPresentableUrl(); - if (myFile.isDirectory() || myHighlighter == null) return presentableUrl; + if (myFile.isDirectory()) return presentableUrl; PsiDocumentManager.getInstance(myProject).commitAllDocuments(); final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(myFile); @@ -188,8 +200,7 @@ public class Bookmark { } } - return IdeBundle - .message("bookmark.file.X.line.Y", presentableUrl, myHighlighter.getDocument().getLineNumber(myHighlighter.getStartOffset()) + 1); + return IdeBundle.message("bookmark.file.X.line.Y", presentableUrl, getLine() + 1); } private String getBookmarkTooltip() { @@ -211,6 +222,7 @@ public class Bookmark { myMnemonic = mnemonic; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(LightColors.YELLOW); g.fillRect(x, y, getIconWidth(), getIconHeight()); @@ -226,10 +238,12 @@ public class Bookmark { g.setFont(oldFont); } + @Override public int getIconWidth() { return 10; } + @Override public int getIconHeight() { return 12; } @@ -245,14 +259,22 @@ public class Bookmark { } } - private class MyGutterIconRenderer extends GutterIconRenderer { - @NotNull - public Icon getIcon() { - return Bookmark.this.getIcon(); + private static class MyGutterIconRenderer extends GutterIconRenderer { + private final Bookmark myBookmark; + + public MyGutterIconRenderer(@NotNull Bookmark bookmark) { + myBookmark = bookmark; } + @Override + @NotNull + public Icon getIcon() { + return myBookmark.getIcon(); + } + + @Override public String getTooltipText() { - return getBookmarkTooltip(); + return myBookmark.getBookmarkTooltip(); } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java index 3e46735e892c..0d995bebeb7b 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java @@ -16,25 +16,32 @@ package com.intellij.ide.bookmarks; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.AbstractProjectComponent; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.*; +import com.intellij.openapi.editor.ex.MarkupModelEx; +import com.intellij.openapi.editor.impl.DocumentMarkupModel; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.util.messages.MessageBus; +import com.intellij.util.ui.UIUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.awt.*; import java.awt.event.InputEvent; import java.util.*; @@ -46,51 +53,54 @@ import java.util.List; @Storage( file = "$WORKSPACE_FILE$") } ) -public class BookmarkManager implements PersistentStateComponent, ProjectComponent { - +public class BookmarkManager extends AbstractProjectComponent implements PersistentStateComponent { private static final int MAX_AUTO_DESCRIPTION_SIZE = 50; - private final List myBookmarks = new ArrayList(); - private final MyEditorMouseListener myEditorMouseListener = new MyEditorMouseListener(); + private final List myBookmarks = new ArrayList(); - private final Project myProject; private final MessageBus myBus; public static BookmarkManager getInstance(Project project) { return project.getComponent(BookmarkManager.class); } - public BookmarkManager(Project project, MessageBus bus) { - myProject = project; + public BookmarkManager(Project project, MessageBus bus, PsiDocumentManager documentManager) { + super(project); myBus = bus; - EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new MyDocumentListener(), myProject); + EditorEventMulticaster multicaster = EditorFactory.getInstance().getEventMulticaster(); + multicaster.addDocumentListener(new MyDocumentListener(), myProject); + multicaster.addEditorMouseListener(new MyEditorMouseListener(), myProject); + + documentManager.addListener(new PsiDocumentManager.Listener() { + @Override + public void documentCreated(@NotNull final Document document, PsiFile psiFile) { + final VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null) return; + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (myProject.isDisposed()) return; + for (Bookmark bookmark : myBookmarks) { + if (bookmark.getFile() == file) { + bookmark.createHighlighter((MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true)); + } + } + } + }); + } + + @Override + public void fileCreated(@NotNull PsiFile file, @NotNull Document document) { + } + }); } - public void projectOpened() { - EditorFactory.getInstance().getEventMulticaster().addEditorMouseListener(myEditorMouseListener, myProject); - } - - @Override - public void projectClosed() { - EditorFactory.getInstance().getEventMulticaster().removeEditorMouseListener(myEditorMouseListener); - } - - @Override - public void initComponent() {} - - @Override - public void disposeComponent() {} - @NotNull @Override public String getComponentName() { return "BookmarkManager"; } - public Project getProject() { - return myProject; - } - public void addEditorBookmark(Editor editor, int lineIndex) { Document document = editor.getDocument(); PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document); @@ -127,7 +137,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje if (file == null) return null; if (findFileBookmark(file) != null) return null; - Bookmark b = new Bookmark(myProject, file, description); + Bookmark b = new Bookmark(myProject, file, -1, description); myBookmarks.add(0, b); myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkAdded(b); return b; @@ -144,9 +154,9 @@ public class BookmarkManager implements PersistentStateComponent, Proje @Nullable - public Bookmark findEditorBookmark(Document document, int lineIndex) { + public Bookmark findEditorBookmark(@NotNull Document document, int line) { for (Bookmark bookmark : myBookmarks) { - if (bookmark.getDocument() == document && bookmark.getLine() == lineIndex) { + if (bookmark.getDocument() == document && bookmark.getLine() == line) { return bookmark; } } @@ -155,7 +165,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje } @Nullable - public Bookmark findFileBookmark(VirtualFile file) { + public Bookmark findFileBookmark(@NotNull VirtualFile file) { for (Bookmark bookmark : myBookmarks) { if (bookmark.getFile() == file && bookmark.getLine() == -1) return bookmark; } @@ -180,20 +190,23 @@ public class BookmarkManager implements PersistentStateComponent, Proje return false; } - public void removeBookmark(Bookmark bookmark) { + public void removeBookmark(@NotNull Bookmark bookmark) { myBookmarks.remove(bookmark); bookmark.release(); myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkRemoved(bookmark); } + @Override public Element getState() { Element container = new Element("BookmarkManager"); writeExternal(container); return container; } + @Override public void loadState(final Element state) { StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { + @Override public void run() { BookmarksListener publisher = myBus.syncPublisher(BookmarksListener.TOPIC); for (Bookmark bookmark : myBookmarks) { @@ -214,7 +227,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje if ("bookmark".equals(bookmarkElement.getName())) { String url = bookmarkElement.getAttributeValue("url"); String line = bookmarkElement.getAttributeValue("line"); - String description = bookmarkElement.getAttributeValue("description"); + String description = StringUtil.notNullize(bookmarkElement.getAttributeValue("description")); String mnemonic = bookmarkElement.getAttributeValue("mnemonic"); Bookmark b = null; @@ -335,6 +348,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje Bookmark[] bookmarks = answer.toArray(new Bookmark[answer.size()]); Arrays.sort(bookmarks, new Comparator() { + @Override public int compare(final Bookmark o1, final Bookmark o2) { return o1.getLine() - o2.getLine(); } @@ -342,7 +356,7 @@ public class BookmarkManager implements PersistentStateComponent, Proje return bookmarks; } - public void setMnemonic(Bookmark bookmark, char c) { + public void setMnemonic(@NotNull Bookmark bookmark, char c) { final Bookmark old = findBookmarkForMnemonic(c); if (old != null) removeBookmark(old); @@ -350,13 +364,14 @@ public class BookmarkManager implements PersistentStateComponent, Proje myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkChanged(bookmark); } - public void setDescription(Bookmark bookmark, String description) { + public void setDescription(@NotNull Bookmark bookmark, String description) { bookmark.setDescription(description); myBus.syncPublisher(BookmarksListener.TOPIC).bookmarkChanged(bookmark); } private class MyEditorMouseListener extends EditorMouseAdapter { + @Override public void mouseClicked(final EditorMouseEvent e) { if (e.getArea() != EditorMouseEventArea.LINE_MARKERS_AREA) return; if (e.getMouseEvent().isPopupTrigger()) return; diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java index 398ba6ef72cb..ea052a27ad79 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarksListener.java @@ -20,12 +20,13 @@ package com.intellij.ide.bookmarks; import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NotNull; public interface BookmarksListener { Topic TOPIC = Topic.create("Bookmarks", BookmarksListener.class); - void bookmarkAdded(Bookmark b); - void bookmarkRemoved(Bookmark b); + void bookmarkAdded(@NotNull Bookmark b); + void bookmarkRemoved(@NotNull Bookmark b); - void bookmarkChanged(Bookmark b); + void bookmarkChanged(@NotNull Bookmark b); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java index 83dc5f1c918f..6d2ef559b21a 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java @@ -64,8 +64,10 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { myPsiTreeChangeListener = createPsiTreeChangeListener(myProject); connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { + @Override public void beforeRootsChange(ModuleRootEvent event) { } + @Override public void rootsChanged(ModuleRootEvent event) { queueUpdate(); } @@ -87,6 +89,7 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { initRootNode(); } + @Override public final void dispose() { super.dispose(); PsiManager.getInstance(myProject).removePsiTreeChangeListener(myPsiTreeChangeListener); @@ -110,29 +113,35 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { super(project); } + @Override protected DefaultMutableTreeNode getRootNode(){ return ProjectTreeBuilder.this.getRootNode(); } + @Override protected AbstractTreeUpdater getUpdater() { return ProjectTreeBuilder.this.getUpdater(); } + @Override protected boolean isFlattenPackages(){ return ((AbstractProjectTreeStructure)getTreeStructure()).isFlattenPackages(); } } private final class MyBookmarksListener implements BookmarksListener { - public void bookmarkAdded(Bookmark b) { + @Override + public void bookmarkAdded(@NotNull Bookmark b) { updateForFile(b.getFile()); } - public void bookmarkRemoved(Bookmark b) { + @Override + public void bookmarkRemoved(@NotNull Bookmark b) { updateForFile(b.getFile()); } - public void bookmarkChanged(Bookmark b) { + @Override + public void bookmarkChanged(@NotNull Bookmark b) { updateForFile(b.getFile()); } @@ -145,10 +154,12 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { } private final class MyFileStatusListener implements FileStatusListener { + @Override public void fileStatusesChanged() { queueUpdate(false); } + @Override public void fileStatusChanged(@NotNull VirtualFile vFile) { queueUpdate(false); } @@ -171,10 +182,12 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { private final Alarm myUpdateProblemAlarm = new Alarm(); private final Collection myFilesToRefresh = new THashSet(); + @Override public void problemsAppeared(VirtualFile file) { queueUpdate(file); } + @Override public void problemsDisappeared(VirtualFile file) { queueUpdate(file); } @@ -184,6 +197,7 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { if (myFilesToRefresh.add(fileToRefresh)) { myUpdateProblemAlarm.cancelAllRequests(); myUpdateProblemAlarm.addRequest(new Runnable() { + @Override public void run() { if (!myProject.isOpen()) return; Set filesToRefresh; diff --git a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java index 81be185a1aa4..eae298f2cd06 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java @@ -19,7 +19,12 @@ import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.testFramework.LeakHunter; +import com.intellij.testFramework.TestFileType; +import org.jetbrains.annotations.NonNls; import java.io.IOException; import java.util.ArrayList; @@ -30,7 +35,6 @@ import java.util.List; * @since 12/27/10 1:43 PM */ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModificationTest { - private final List myBookmarks = new ArrayList(); @Override @@ -43,13 +47,13 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif } public void testWholeTextReplace() throws IOException { - String text = + @NonNls String text = "public class Test {\n" + " public void test() {\n" + " int i = 1;\n" + " }\n" + "}"; - init(text); + init(text, TestFileType.TEXT); addBookmark(2); List bookmarksBefore = getManager().getValidBookmarks(); @@ -60,19 +64,19 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif assertEquals(1, bookmarksAfter.size()); assertSame(bookmarksBefore.get(0), bookmarksAfter.get(0)); for (Bookmark bookmark : bookmarksAfter) { - checkBookmark(bookmark); + checkBookmarkNavigation(bookmark); } } public void testBookmarkLineRemove() throws IOException { - String text = + @NonNls String text = "public class Test {\n" + " public void test() {\n" + " int i = 1;\n" + " }\n" + "}"; - init(text); - + init(text, TestFileType.TEXT); + addBookmark(2); Document document = myEditor.getDocument(); myEditor.getSelectionModel().setSelection(document.getLineStartOffset(2) - 1, document.getLineEndOffset(2)); @@ -81,13 +85,13 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif } public void testBookmarkIsSavedAfterRemoteChange() throws IOException { - String text = + @NonNls String text = "public class Test {\n" + " public void test() {\n" + " int i = 1;\n" + " }\n" + "}"; - init(text); + init(text, TestFileType.TEXT); addBookmark(2); myEditor.getDocument().setText("111\n222" + text + "333"); @@ -95,7 +99,29 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif assertEquals(1, bookmarks.size()); Bookmark bookmark = bookmarks.get(0); assertEquals(3, bookmark.getLine()); - checkBookmark(bookmark); + checkBookmarkNavigation(bookmark); + } + + public void testBookmarkManagerDoesNotHardReferenceDocuments() throws IOException { + @NonNls String text = + "public class Test {\n" + + "}"; + + myVFile = getSourceRoot().createChildData(null, getTestName(false) + ".txt"); + VfsUtil.saveText(myVFile, text); + + Bookmark bookmark = getManager().addTextBookmark(myVFile, 1, "xxx"); + assertNotNull(bookmark); + LeakHunter.checkLeak(getManager(), Document.class); + + Document document = FileDocumentManager.getInstance().getDocument(myVFile); + assertNotNull(document); + + document.insertString(0, "line 0\n"); + assertEquals(2, bookmark.getLine()); + + myEditor = createEditor(myVFile); + checkBookmarkNavigation(bookmark); } private void addBookmark(int line) { @@ -106,8 +132,16 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif private static BookmarkManager getManager() { return BookmarkManager.getInstance(getProject()); } - - private static void checkBookmark(Bookmark bookmark) { + + @Override + public Object getData(String dataId) { + if (dataId.equals(OpenFileDescriptor.NAVIGATE_IN_EDITOR.getName())) { + return myEditor; + } + return super.getData(dataId); + } + + private static void checkBookmarkNavigation(Bookmark bookmark) { int line = bookmark.getLine(); int anotherLine = line; if (line > 0) { @@ -118,9 +152,7 @@ public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModif } CaretModel caretModel = myEditor.getCaretModel(); caretModel.moveToLogicalPosition(new LogicalPosition(anotherLine, 0)); - OpenFileDescriptor target = bookmark.getTarget(); - assertTrue(target.canNavigate()); - target.navigateIn(myEditor); + bookmark.navigate(); assertEquals(line, caretModel.getLogicalPosition().line); } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java index d9a2fc1ccfb2..daeed2381f55 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java @@ -44,12 +44,7 @@ import java.util.regex.Pattern; * @since 11/18/10 7:43 PM */ public abstract class AbstractEditorProcessingOnDocumentModificationTest extends LightPlatformCodeInsightTestCase { - - protected void init(String fileText) throws IOException { - init(fileText, TestFileType.TEXT); - } - - protected void init(String fileText, TestFileType type) throws IOException { + protected void init(@NotNull String fileText, @NotNull TestFileType type) throws IOException { configureFromFileText(getFileName(type), fileText); } From aa2105349c4fa065372e760e87fe662dcc6b3f63 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 18:50:02 +0400 Subject: [PATCH 19/84] cleanup --- .../src/com/intellij/psi/stubs/StubIndexImpl.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 3edcb908e65f..2af57b6d6bb2 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -198,7 +198,8 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe @NotNull final Project project, @Nullable final GlobalSearchScope scope, @NotNull final Processor processor) { - FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, scope); + final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance(); + fileBasedIndex.ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, scope); final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); final PsiManager psiManager = PsiManager.getInstance(project); @@ -212,7 +213,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe index.getReadLock().lock(); final ValueContainer container = index.getData(key); - final FileBasedIndex.ProjectIndexableFilesFilter projectFilesFilter = FileBasedIndex.getInstance().projectIndexableFiles(project); + final FileBasedIndex.ProjectIndexableFilesFilter projectFilesFilter = fileBasedIndex.projectIndexableFiles(project); return container.forEach(new ValueContainer.ContainerAction() { @Override @@ -278,7 +279,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - FileBasedIndex.getInstance().requestReindex(file); + fileBasedIndex.requestReindex(file); } }, ModalityState.NON_MODAL); } From 046257e2c4dfa589b452a6d7b166561e87fa1061 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 27 Mar 2012 18:50:30 +0400 Subject: [PATCH 20/84] cleanup LIst pool after compile --- .../impl/javaCompiler/api/CompAPIDriver.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java index 39d8996e296a..f4353c85a8e5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java @@ -27,6 +27,7 @@ import javax.tools.*; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.lang.reflect.Field; import java.net.URI; import java.util.List; import java.util.concurrent.BlockingQueue; @@ -145,6 +146,18 @@ class CompAPIDriver { assert !processing; //assert myCompilationResults.isEmpty() : myCompilationResults; myCompilationResults.clear(); + cleanupInternalFields(); + } + + private static void cleanupInternalFields() { + try { + Field freelist = Class.forName("com.sun.tools.javac.util.SharedNameTable").getDeclaredField("freelist"); + freelist.setAccessible(true); + freelist.set(null, com.sun.tools.javac.util.List.nil()); + } + catch (Exception ignored) { + + } } public void offerClassFile(URI uri, byte[] bytes) { From d6a0ec2446f528d40dc1b694dbfa24020e509374 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 28 Mar 2012 15:35:10 +0400 Subject: [PATCH 21/84] supply name in tests --- RegExpSupport/test/test/BaseParseTestcase.java | 2 +- .../intellij/codeInsight/SuppressExternalTest.java | 2 +- .../org/jetbrains/android/AndroidTestCase.java | 2 +- .../android/dom/AndroidLibraryProjectTest.java | 2 +- .../jetbrains/idea/maven/dom/MavenDomTestCase.java | 2 +- .../plugins/relaxNG/HighlightingTestBase.java | 11 ++++++----- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/RegExpSupport/test/test/BaseParseTestcase.java b/RegExpSupport/test/test/BaseParseTestcase.java index ccdf656619e3..e6cb0fc0d726 100644 --- a/RegExpSupport/test/test/BaseParseTestcase.java +++ b/RegExpSupport/test/test/BaseParseTestcase.java @@ -43,7 +43,7 @@ public abstract class BaseParseTestcase extends UsefulTestCase{ protected void setUp() throws Exception { super.setUp(); final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory(); - final TestFixtureBuilder builder = fixtureFactory.createFixtureBuilder(); + final TestFixtureBuilder builder = fixtureFactory.createFixtureBuilder(getName()); myFixture = fixtureFactory.createCodeInsightFixture(builder.getFixture()); myFixture.setTestDataPath(getTestDataPath()); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java index 02d1c996716b..a02a70ba3af8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/SuppressExternalTest.java @@ -37,7 +37,7 @@ public class SuppressExternalTest extends UsefulTestCase { public void setUp() throws Exception { super.setUp(); final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory(); - final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder(); + final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture()); myFixture.setTestDataPath(PathManagerEx.getTestDataPath() + "/codeInsight/externalAnnotations"); final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class); diff --git a/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java b/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java index cd47db4f160f..563eb772b0ff 100644 --- a/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java +++ b/plugins/android/testSrc/org/jetbrains/android/AndroidTestCase.java @@ -78,7 +78,7 @@ public abstract class AndroidTestCase extends UsefulTestCase { public void setUp() throws Exception { super.setUp(); - final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(); + final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class); tuneModule(moduleFixtureBuilder, myFixture.getTempDirPath()); diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java index 2c6ee20e6da2..50b9e37c84c4 100644 --- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidLibraryProjectTest.java @@ -49,7 +49,7 @@ public class AndroidLibraryProjectTest extends UsefulTestCase { @Override public void setUp() throws Exception { super.setUp(); - final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(); + final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); myFixture.enableInspections(AndroidDomInspection.class); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java index 97af461e12a6..3dcbe20edc8f 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java @@ -73,7 +73,7 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase { @Override protected void setUpFixtures() throws Exception { - myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder().getFixture(); + myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).getFixture(); myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(myTestFixture); myFixture.setUp(); diff --git a/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java b/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java index b8631e8083d7..130ea0ef209a 100644 --- a/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java +++ b/xml/relaxng/test/org/intellij/plugins/relaxNG/HighlightingTestBase.java @@ -24,12 +24,14 @@ import com.intellij.codeInspection.InspectionToolProvider; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection; import com.intellij.javaee.ExternalResourceManagerEx; -import com.intellij.mock.MockProgressIndicator; -import com.intellij.openapi.application.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -48,7 +50,6 @@ import org.intellij.plugins.relaxNG.inspections.RngDomInspection; import org.intellij.plugins.testUtil.IdeaCodeInsightTestCase; import org.intellij.plugins.testUtil.ResourceUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -130,7 +131,7 @@ public abstract class HighlightingTestBase extends UsefulTestCase implements Ide } protected CodeInsightTestFixture createContentFixture(IdeaTestFixtureFactory factory) { - final TestFixtureBuilder builder = factory.createFixtureBuilder(); + final TestFixtureBuilder builder = factory.createFixtureBuilder(getName()); final EmptyModuleFixtureBuilder moduleBuilder = builder.addModule(EmptyModuleFixtureBuilder.class); final IdeaProjectTestFixture fixture = builder.getFixture(); From 6138a246ff5390745659e7fd48f0b7ac43e18aa5 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 28 Mar 2012 15:37:52 +0400 Subject: [PATCH 22/84] notnull --- .../impl/actions/SuppressAllForClassFix.java | 2 +- .../daemon/impl/actions/SuppressFix.java | 2 +- .../impl/actions/SuppressParameterFix.java | 2 +- ...eWithDefaultParamValueIntentionAction.java | 2 +- .../impl/quickfix/QualifyThisArgumentFix.java | 2 +- .../impl/InsertLiteralUnderscoresAction.java | 2 +- .../impl/RemoveLiteralUnderscoresAction.java | 2 +- .../src/com/intellij/psi/PsiElement.java | 84 +++++++++++-------- .../intention/IntentionAction.java | 3 +- .../PsiElementBaseIntentionAction.java | 7 +- .../intention/impl/BaseIntentionAction.java | 2 + .../codeInspection/SuppressForMemberFix.java | 2 +- .../i18n/SuppressByCommentOutAction.java | 2 +- .../PropertySuppressableInspectionBase.java | 4 +- .../analysis/AddSchemaPrefixIntention.java | 2 +- ...ConvertSchemaPrefixToDefaultIntention.java | 2 +- .../XmlSuppressableInspectionTool.java | 4 +- .../relaxNG/inspections/BaseInspection.java | 2 +- 18 files changed, 74 insertions(+), 54 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java index 3f43a51568b0..c06a82b1062f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java @@ -66,7 +66,7 @@ public class SuppressAllForClassFix extends SuppressFix { } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiDocCommentOwner container = getContainer(element); LOG.assertTrue(container != null); if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java index 2c5cd77301aa..a8464dc6c9c8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java @@ -105,7 +105,7 @@ public class SuppressFix extends SuppressIntentionAction { } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { PsiDocCommentOwner container = getContainer(element); assert container != null; if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java index dbd6e2f38cc0..49682f21e312 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressParameterFix.java @@ -66,7 +66,7 @@ public class SuppressParameterFix extends SuppressIntentionAction { } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { PsiParameter container = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false); assert container != null; if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java index dc09b28a11e4..4348764edd35 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java @@ -83,7 +83,7 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); final PsiMethod method = (PsiMethod)parameter.getDeclarationScope(); final PsiMethod prototype = (PsiMethod)method.getContainingClass().addBefore(generateMethodPrototype(method, parameter), method); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java index ff23c5fcaa12..a5cfce5dd068 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyThisArgumentFix.java @@ -66,7 +66,7 @@ public class QualifyThisArgumentFix extends PsiElementBaseIntentionAction { } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { myExpression.replace(RefactoringUtil.createThisExpression(PsiManager.getInstance(project), myPsiClass)); } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java index 281a18d78abc..0681808cea69 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java @@ -46,7 +46,7 @@ public class InsertLiteralUnderscoresAction extends PsiElementBaseIntentionActio } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(element, PsiLiteralExpression.class, false); if (literalExpression == null) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java index 4207625a54ca..320104e934de 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/RemoveLiteralUnderscoresAction.java @@ -40,7 +40,7 @@ public class RemoveLiteralUnderscoresAction extends PsiElementBaseIntentionActio } @Override - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(element, PsiLiteralExpression.class, false); if (literalExpression == null) return; diff --git a/platform/core-api/src/com/intellij/psi/PsiElement.java b/platform/core-api/src/com/intellij/psi/PsiElement.java index 99bc7789c90c..fa58ea3d3797 100644 --- a/platform/core-api/src/com/intellij/psi/PsiElement.java +++ b/platform/core-api/src/com/intellij/psi/PsiElement.java @@ -46,7 +46,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * Returns the project to which the PSI element belongs. * * @return the project instance. - * @throws PsiInvalidElementAccessException if this element is invalid + * @throws PsiInvalidElementAccessException + * if this element is invalid */ @NotNull Project getProject() throws PsiInvalidElementAccessException; @@ -56,7 +57,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the language instance. */ - @NotNull Language getLanguage(); + @NotNull + Language getLanguage(); /** * Returns the PSI manager for the project to which the PSI element belongs. @@ -71,7 +73,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the array of child elements. */ - @NotNull PsiElement[] getChildren(); + @NotNull + PsiElement[] getChildren(); /** * Returns the parent of the PSI element. @@ -85,34 +88,40 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the first child, or null if the element has no children. */ - @Nullable PsiElement getFirstChild(); + @Nullable + PsiElement getFirstChild(); /** * Returns the last child of the PSI element. * * @return the last child, or null if the element has no children. */ - @Nullable PsiElement getLastChild(); + @Nullable + PsiElement getLastChild(); /** * Returns the next sibling of the PSI element. * * @return the next sibling, or null if the node is the last in the list of siblings. */ - @Nullable PsiElement getNextSibling(); + @Nullable + PsiElement getNextSibling(); /** * Returns the previous sibling of the PSI element. * * @return the previous sibling, or null if the node is the first in the list of siblings. */ - @Nullable PsiElement getPrevSibling(); + @Nullable + PsiElement getPrevSibling(); /** * Returns the file containing the PSI element. - * @throws PsiInvalidElementAccessException if this element is invalid + * * @return the file instance, or null if the PSI element is not contained in a file (for example, - * the element represents a package or directory). + * the element represents a package or directory). + * @throws PsiInvalidElementAccessException + * if this element is invalid */ PsiFile getContainingFile() throws PsiInvalidElementAccessException; @@ -178,7 +187,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the element text as a character array. */ - @NotNull char[] textToCharArray(); + @NotNull + char[] textToCharArray(); /** * Returns the PSI element which should be used as a navigation target @@ -246,7 +256,7 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * Creates a copy of the file containing the PSI element and returns the corresponding * element in the created copy. Resolve operations performed on elements in the copy - * of the file will resolve to elements in the copy, not in the original file. + * of the file will resolve to elements in the copy, not in the original file. * * @return the element in the file copy corresponding to this element. */ @@ -304,9 +314,9 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * Adds a range of elements as children to this PSI element, before the specified anchor element. * - * @param first the first child element to add. - * @param last the last child element to add (must have the same parent as first) - * @param anchor the anchor before which the child element is inserted (must be a child of this PSI element) + * @param first the first child element to add. + * @param last the last child element to add (must have the same parent as first) + * @param anchor the anchor before which the child element is inserted (must be a child of this PSI element) * @return the first child element which was actually added (either first or its copy). * @throws IncorrectOperationException if the modification is not supported or not possible for some reason. */ @@ -315,9 +325,9 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * Adds a range of elements as children to this PSI element, after the specified anchor element. * - * @param first the first child element to add. - * @param last the last child element to add (must have the same parent as first) - * @param anchor the anchor after which the child element is inserted (must be a child of this PSI element) + * @param first the first child element to add. + * @param last the last child element to add (must have the same parent as first) + * @param anchor the anchor after which the child element is inserted (must be a child of this PSI element) * @return the first child element which was actually added (either first or its copy). * @throws IncorrectOperationException if the modification is not supported or not possible for some reason. */ @@ -327,7 +337,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * Deletes this PSI element from the tree. * * @throws IncorrectOperationException if the modification is not supported - * or not possible for some reason (for example, the file containing the element is read-only). + * or not possible for some reason (for example, the file containing the element is read-only). */ void delete() throws IncorrectOperationException; @@ -382,7 +392,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * associated reference. * * @return the reference instance, or null if the PSI element does not have any - * associated references. + * associated references. */ @Nullable PsiReference getReference(); @@ -394,15 +404,16 @@ public interface PsiElement extends UserDataHolder, Iconable { * contains only one text fragment which acts as a reference but the reference has * multiple possible targets, {@link PsiPolyVariantReference} should be used instead * of returning multiple references. - * + *

* Actually, it's preferable to call {@link com.intellij.psi.PsiReferenceService#getReferences} instead * as it allows adding references by plugins when the element implements {@link com.intellij.psi.ContributedReferenceHost}. * * @return the array of references, or an empty array if the element has no associated - * references. + * references. * @see com.intellij.psi.PsiReferenceService#getReferences */ - @NotNull PsiReference[] getReferences(); + @NotNull + PsiReference[] getReferences(); /** * Returns a copyable user data object attached to this element. @@ -411,13 +422,14 @@ public interface PsiElement extends UserDataHolder, Iconable { * @return the user data object, or null if no such object is found in the current element. * @see #putCopyableUserData(com.intellij.openapi.util.Key, Object) */ - @Nullable T getCopyableUserData(Key key); + @Nullable + T getCopyableUserData(Key key); /** * Attaches a copyable user data object to this element. Copyable user data objects are copied * when the PSI elements are copied. * - * @param key the key for accessing the user data object. + * @param key the key for accessing the user data object. * @param value the user data object to attach. * @see #getCopyableUserData(com.intellij.openapi.util.Key) */ @@ -427,12 +439,12 @@ public interface PsiElement extends UserDataHolder, Iconable { * Passes the declarations contained in this PSI element and its children * for processing to the specified scope processor. * - * @param processor the processor receiving the declarations. + * @param processor the processor receiving the declarations. * @param state - * @param lastParent the child of this element has been processed during the previous - * step of the tree up walk (declarations under this element do not need - * to be processed again) - * @param place the original element from which the tree up walk was initiated. + * @param lastParent the child of this element has been processed during the previous + * step of the tree up walk (declarations under this element do not need + * to be processed again) + * @param place the original element from which the tree up walk was initiated. * @return true if the declaration processing should continue or false if it should be stopped. */ boolean processDeclarations(@NotNull PsiScopeProcessor processor, @@ -444,11 +456,12 @@ public interface PsiElement extends UserDataHolder, Iconable { * Returns the element which should be used as the parent of this element in a tree up * walk during a resolve operation. For most elements, this returns getParent(), * but the context can be overridden for some elements like code fragments (see - * {@link PsiElementFactory#createCodeBlockCodeFragment(String, PsiElement, boolean)}). + * {@link PsiElementFactory#createCodeBlockCodeFragment(String, PsiElement, boolean)}). * * @return the resolve context element. */ - @Nullable PsiElement getContext(); + @Nullable + PsiElement getContext(); /** * Checks if an actual source or class file corresponds to the element. Non-physical elements include, @@ -465,7 +478,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * * @return the resolve scope instance. */ - @NotNull GlobalSearchScope getResolveScope(); + @NotNull + GlobalSearchScope getResolveScope(); /** * Returns the scope in which references to this element are searched. @@ -473,7 +487,8 @@ public interface PsiElement extends UserDataHolder, Iconable { * @return the search scope instance. * @see {@link com.intellij.psi.search.PsiSearchHelper#getUseScope(PsiElement)} */ - @NotNull SearchScope getUseScope(); + @NotNull + SearchScope getUseScope(); /** * Returns the AST node corresponding to the element. @@ -485,7 +500,8 @@ public interface PsiElement extends UserDataHolder, Iconable { /** * toString() should never be presented to the user. */ - @NonNls String toString(); + @NonNls + String toString(); boolean isEquivalentTo(PsiElement another); } diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java index 15b366e17909..946e31137556 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/IntentionAction.java @@ -51,7 +51,8 @@ public interface IntentionAction { * @return the intention family ID. * @see IntentionManager#registerIntentionAndMetaData(com.intellij.codeInsight.intention.IntentionAction, java.lang.String...) */ - @NotNull String getFamilyName(); + @NotNull + String getFamilyName(); /** * Checks whether this intention is available at a caret offset in file. diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java index 453b022dc298..6967f36ecb86 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java @@ -43,16 +43,17 @@ public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction throw new IncorrectOperationException(); } + @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { final PsiElement element = getElement(editor, file); return element != null && isAvailable(project, editor, element); } @Nullable - protected static PsiElement getElement(Editor editor, PsiFile file) { + protected static PsiElement getElement(Editor editor, @NotNull PsiFile file) { if (!file.getManager().isInProject(file)) return null; - final CaretModel caretModel = editor.getCaretModel(); - final int position = caretModel.getOffset(); + CaretModel caretModel = editor.getCaretModel(); + int position = caretModel.getOffset(); return file.findElementAt(position); } diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java index 31c89570a388..81d3d9a245dc 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/BaseIntentionAction.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull; public abstract class BaseIntentionAction implements IntentionAction { private String myText = ""; + @Override @NotNull public String getText() { return myText; @@ -34,6 +35,7 @@ public abstract class BaseIntentionAction implements IntentionAction { myText = text; } + @Override public boolean startInWriteAction() { return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java index c327b42e1131..f23d90d93da8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java @@ -94,7 +94,7 @@ public class SuppressForMemberFix extends SuppressIntentionAction { return container != null && context != null && context.getManager().isInProject(context); } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { GrDocCommentOwner container = getContainer(element); assert container != null; if (!CodeInsightUtilBase.preparePsiElementForWrite(container)) return; diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java index 0c9ecaa47ce9..f674084163a0 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java @@ -41,7 +41,7 @@ class SuppressByCommentOutAction extends SuppressIntentionAction { } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return; element = findJavaCodeUpThere(element); PsiFile file = element.getContainingFile(); diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java b/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java index 6bbdcace6701..499e1fc8a78f 100644 --- a/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java +++ b/plugins/properties/src/com/intellij/lang/properties/PropertySuppressableInspectionBase.java @@ -110,7 +110,7 @@ public abstract class PropertySuppressableInspectionBase extends LocalInspection return property != null && property.isValid(); } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiFile file = element.getContainingFile(); if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; @@ -149,7 +149,7 @@ public abstract class PropertySuppressableInspectionBase extends LocalInspection return element.isValid() && element.getContainingFile() instanceof PropertiesFile; } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { final PsiFile file = element.getContainingFile(); if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java index 21c95935dd7a..e7d65657d0b4 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/AddSchemaPrefixIntention.java @@ -57,7 +57,7 @@ public class AddSchemaPrefixIntention extends PsiElementBaseIntentionAction { } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final XmlAttribute xmlns = getXmlnsDeclaration(element); if (xmlns == null) return; final String namespace = xmlns.getValue(); diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java index d524eb2c95bd..34c4809aa811 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java @@ -45,7 +45,7 @@ public class ConvertSchemaPrefixToDefaultIntention extends PsiElementBaseIntenti } @Override - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final XmlAttribute xmlns = getXmlnsDeclaration(element); if (xmlns == null) return; SchemaPrefixReference prefixRef = null; diff --git a/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java b/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java index 84623dd6d72d..26191bac3220 100644 --- a/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java +++ b/xml/openapi/src/com/intellij/codeInspection/XmlSuppressableInspectionTool.java @@ -66,7 +66,7 @@ public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool return PsiTreeUtil.getParentOfType(element, XmlTag.class) != null; } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForTag(element, id); } } @@ -88,7 +88,7 @@ public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool return getText(); } - public void invoke(final Project project, final Editor editor, final PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForFile(element, myInspectionId); } diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java index e01543514e80..0f8288f379aa 100644 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/inspections/BaseInspection.java @@ -205,7 +205,7 @@ public abstract class BaseInspection extends XmlSuppressableInspectionTool { return getDisplayName(); } - public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { suppress(element.getContainingFile(), getTarget(element)); } From b53f372dfafe6b075a1bd2ca549cb5df2ea29328 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 28 Mar 2012 16:03:23 +0400 Subject: [PATCH 23/84] IDEA-83610 Subversion: revert file rename from Repositories view causes errors --- .../RevertCommittedStuffAbstractAction.java | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java index 42b5a2838876..ad2fe9aeacaa 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java @@ -18,36 +18,35 @@ package com.intellij.openapi.vcs.changes.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.rt.Logger; import com.intellij.openapi.diff.impl.patch.BinaryFilePatch; import com.intellij.openapi.diff.impl.patch.FilePatch; import com.intellij.openapi.diff.impl.patch.IdeaTextPatchBuilder; import com.intellij.openapi.diff.impl.patch.formove.PatchApplier; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.BackgroundFromStartOption; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeList; -import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.ui.ChangeListChooser; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.WaitForProgressToShow; import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; abstract class RevertCommittedStuffAbstractAction extends AnAction implements DumbAware { private final Convertor myForUpdateConvertor; private final Convertor myForPerformConvertor; + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.actions.RevertCommittedStuffAbstractAction"); public RevertCommittedStuffAbstractAction(final Convertor forUpdateConvertor, final Convertor forPerformConvertor) { @@ -63,6 +62,7 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du if (changes == null || changes.length == 0) return; final List changesList = new ArrayList(); Collections.addAll(changesList, changes); + FileDocumentManager.getInstance().saveAllDocuments(); String defaultName = null; final ChangeList[] changeLists = e.getData(VcsDataKeys.CHANGE_LISTS); @@ -81,7 +81,8 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du @Override public void run(@NotNull ProgressIndicator indicator) { try { - patches.addAll(IdeaTextPatchBuilder.buildPatch(project, changesList, baseDir.getPresentableUrl(), true)); + final List preprocessed = preprocessChanges(changesList); + patches.addAll(IdeaTextPatchBuilder.buildPatch(project, preprocessed, baseDir.getPresentableUrl(), true)); } catch (final VcsException ex) { WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { @@ -101,6 +102,35 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du }); } + private List preprocessChanges(List list) { + final List result = new ArrayList(); + final Map map = new HashMap(); + for (Change change : list) { + if (change.getBeforeRevision() == null) { + result.add(change); + } else { + final FilePath beforePath = ChangesUtil.getBeforePath(change); + final Change existing = map.get(beforePath); + if (existing == null) { + map.put(beforePath, change); + continue; + } + if (change.getAfterRevision() == null && existing.getAfterRevision() == null) continue; + if (change.getAfterRevision() != null && existing.getAfterRevision() != null) { + LOG.error("Incorrect changes list: " + list); + } + if (existing.getAfterRevision() != null && change.getAfterRevision() == null) { + continue; // skip delete change + } + if (change.getAfterRevision() != null && existing.getAfterRevision() == null) { + map.put(beforePath, change); // skip delete change + } + } + } + result.addAll(map.values()); + return result; + } + public void update(final AnActionEvent e) { final Project project = e.getData(PlatformDataKeys.PROJECT); final Change[] changes = myForUpdateConvertor.convert(e); From 7968fd69cf154a69c34f7851dbd1c791ca4944a5 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 28 Mar 2012 12:26:19 +0400 Subject: [PATCH 24/84] IDEA-83061 Formatter option for spaces within list literal and spaces within map literal --- .../plugins/groovy/formatter/GroovyCodeStyleSettings.java | 1 + .../formatter/GroovyLanguageCodeStyleSettingsProvider.java | 1 + .../groovy/formatter/processors/GroovySpacingProcessor.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java index 895f178c762a..2869eb12bcf2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java @@ -43,6 +43,7 @@ public class GroovyCodeStyleSettings extends CustomCodeStyleSettings { public boolean SPACE_IN_NAMED_ARGUMENT = true; public boolean ALIGN_MULTILINE_LIST_OR_MAP = false; + public boolean SPACE_WITHIN_LIST_OR_MAP = false; public GroovyCodeStyleSettings(CodeStyleSettings container) { super("GroovyCodeStyleSettings", container); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java index 6cd8df934c1a..a93b3cf1549b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java @@ -115,6 +115,7 @@ public class GroovyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSe "SPACE_WITHIN_ANNOTATION_PARENTHESES" ); consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_IN_NAMED_ARGUMENT", "In named argument after ':'", CodeStyleSettingsCustomizable.SPACES_OTHER); + consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_WITHIN_LIST_OR_MAP", "List and maps literals", CodeStyleSettingsCustomizable.SPACES_WITHIN); return; } consumer.showAllStandardOptions(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java index 970d869780a1..46805d001b79 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java @@ -546,7 +546,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitListOrMap(GrListOrMap listOrMap) { if (myType1 == mLBRACK || myType2 == mRBRACK) { - createSpaceInCode(mySettings.SPACE_WITHIN_BRACKETS); + createSpaceInCode(myGroovySettings.SPACE_WITHIN_LIST_OR_MAP); } } From f91d836f5f8ee445fd8dfd94c8855417bb3a144f Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 28 Mar 2012 14:01:19 +0400 Subject: [PATCH 25/84] fold file header in groovy files --- .../lang/folding/GroovyFoldingBuilder.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index 574c5c9d4e1b..f695d0ebe0d8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -24,10 +24,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiAnonymousClass; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; +import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.hash.HashSet; @@ -215,6 +212,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy return text.contains("\n") || text.contains("\r") || text.contains("\r\n"); } + @Nullable @Override protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) { final IElementType elemType = node.getElementType(); @@ -245,8 +243,21 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy return settings.isCollapseImports(); } - if (node.getElementType() == GROOVY_DOC_COMMENT) { - return settings.isCollapseJavadocs(); + if (node.getElementType() == GROOVY_DOC_COMMENT || node.getElementType() == mML_COMMENT) { + PsiElement element = node.getPsi(); + PsiElement parent = element.getParent(); + if (parent instanceof GroovyFile) { + PsiElement firstChild = parent.getFirstChild(); + if (firstChild instanceof PsiWhiteSpace) { + firstChild = firstChild.getNextSibling(); + } + if (element.equals(firstChild)) { + return settings.isCollapseFileHeader(); + } + } + if (node.getElementType() == GROOVY_DOC_COMMENT) { + return settings.isCollapseJavadocs(); + } } if ((node.getElementType() == OPEN_BLOCK || node.getElementType() == CONSTRUCTOR_BODY) && node.getTreeParent().getElementType() == METHOD_DEFINITION) { From c5f76ad3c4eacbad0215b1222b2d904251b50113 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 28 Mar 2012 15:46:24 +0400 Subject: [PATCH 26/84] IDEA-81615 Groovy warning "Not All execution paths return a value" inside closures --- .../MissingReturnInspection.java | 55 ++++++++++++------- .../convertToJava/ClassItemGeneratorImpl.java | 2 +- .../convertToJava/ClosureGenerator.java | 2 +- .../convertToJava/CodeBlockGenerator.java | 3 +- .../MissingReturnInClosure.groovy | 4 +- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java index f2e268a51217..8a13a53cf64f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java @@ -65,14 +65,29 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { return GroovyInspectionBundle.message("no.return.display.name"); } + public enum ReturnStatus { + mustReturnValue, shouldReturnValue, shouldNotReturnValue; + + public static ReturnStatus getReturnStatus(PsiElement subject) { + if (subject instanceof GrClosableBlock) { + final PsiType inferredReturnType = GroovyExpectedTypesProvider.getExpectedClosureReturnType((GrClosableBlock)subject); + return inferredReturnType != null && inferredReturnType != PsiType.VOID ? shouldReturnValue : shouldNotReturnValue; + } + else if (subject instanceof GrMethod) { + return ((GrMethod)subject).getReturnTypeElementGroovy() != null && ((GrMethod)subject).getReturnType() != PsiType.VOID + ? mustReturnValue + : shouldNotReturnValue; + } + return shouldNotReturnValue; + } + } + @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean onTheFly) { return new GroovyPsiElementVisitor(new GroovyElementVisitor() { public void visitClosure(GrClosableBlock closure) { super.visitClosure(closure); - - final PsiType expectedClosureType = GroovyExpectedTypesProvider.getExpectedClosureReturnType(closure); - check(closure, problemsHolder, expectedClosureType != null && expectedClosureType != PsiType.VOID); + check(closure, problemsHolder, ReturnStatus.getReturnStatus(closure)); } public void visitMethod(GrMethod method) { @@ -80,72 +95,70 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { final GrOpenBlock block = method.getBlock(); if (block != null) { - final boolean mustReturnValue = method.getReturnTypeElementGroovy() != null && method.getReturnType() != PsiType.VOID; - check(block, problemsHolder, mustReturnValue); + check(block, problemsHolder, ReturnStatus.getReturnStatus(method)); } } }); - } - private static void check(GrCodeBlock block, ProblemsHolder holder, boolean mustReturnValue) { - if (methodMissesSomeReturns(block, mustReturnValue)) { + private static void check(GrCodeBlock block, ProblemsHolder holder, ReturnStatus returnStatus) { + if (methodMissesSomeReturns(block, returnStatus)) { addNoReturnMessage(block, holder); } } - public static boolean methodMissesSomeReturns(GrControlFlowOwner block, boolean mustReturnValue) { - if (!mustReturnValue) { + public static boolean methodMissesSomeReturns(GrControlFlowOwner block, ReturnStatus returnStatus) { + if (returnStatus == ReturnStatus.shouldNotReturnValue) { return false; } - final Ref always = new Ref(true); + final Ref alwaysHaveReturn = new Ref(true); + final Ref sometimesHaveReturn = new Ref(false); final Ref hasExplicitReturn = new Ref(false); - final Ref sometimes = new Ref(false); ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() { @Override public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) { if (instruction instanceof MaybeReturnInstruction) { if (((MaybeReturnInstruction)instruction).mayReturnValue()) { - sometimes.set(true); + sometimesHaveReturn.set(true); } else { - always.set(false); + alwaysHaveReturn.set(false); } return true; } final PsiElement element = instruction.getElement(); if (element instanceof GrReturnStatement) { - sometimes.set(true); + sometimesHaveReturn.set(true); if (returnValue != null) { hasExplicitReturn.set(true); } } else if (instruction instanceof ThrowingInstruction) { - sometimes.set(true); + sometimesHaveReturn.set(true); } else if (element instanceof GrAssertStatement) { - sometimes.set(true); + sometimesHaveReturn.set(true); int count = 0; for (Instruction _i : instruction.allSuccessors()) { count++; } if (count <= 1) { - always.set(false); + alwaysHaveReturn.set(false); } } else { - always.set(false); + alwaysHaveReturn.set(false); } return true; } }); - if (!sometimes.get()) { + if (returnStatus == ReturnStatus.mustReturnValue && !sometimesHaveReturn.get()) { return true; } - return sometimes.get() && !always.get(); + return sometimesHaveReturn.get() && !alwaysHaveReturn.get(); } private static void addNoReturnMessage(GrCodeBlock block, ProblemsHolder holder) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java index 32355663ea49..f47fbf22631a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java @@ -247,7 +247,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { ExpressionContext extended = context.extend(); extended.searchForLocalVarsToWrap((GroovyPsiElement)scriptFile); new CodeBlockGenerator(builder, extended, exitPoints) - .visitStatementOwner((GroovyFile)scriptFile, MissingReturnInspection.methodMissesSomeReturns((GroovyFile)scriptFile, true)); + .visitStatementOwner((GroovyFile)scriptFile, MissingReturnInspection.methodMissesSomeReturns((GroovyFile)scriptFile, MissingReturnInspection.ReturnStatus.mustReturnValue)); builder.append("\n}\n"); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java index b526545ce770..ff4ac8cd4acc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java @@ -87,7 +87,7 @@ public class ClosureGenerator { Collection myExitPoints = ControlFlowUtils.collectReturns(block); boolean shouldInsertReturnNull = - !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, false); + !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.shouldNotReturnValue); new CodeBlockGenerator(builder, context.extend(), myExitPoints).generateCodeBlock(block, shouldInsertReturnNull); builder.append('\n'); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java index f42e83d4de65..f921633f3d27 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java @@ -101,7 +101,8 @@ public class CodeBlockGenerator extends Generator { if (!method.isConstructor() && returnType != PsiType.VOID) { myExitPoints.addAll(ControlFlowUtils.collectReturns(block)); shouldInsertReturnNull = !(returnType instanceof PsiPrimitiveType) && - MissingReturnInspection.methodMissesSomeReturns(block, method.getReturnTypeElementGroovy() != null); + MissingReturnInspection.methodMissesSomeReturns(block, + MissingReturnInspection.ReturnStatus.getReturnStatus(method)); } if (block != null) { diff --git a/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy b/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy index dd8a60c60789..4fc8273eeaee 100644 --- a/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy +++ b/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy @@ -2,7 +2,7 @@ def mkString(def i) {} print([1, 2, 3].collect { mkString(it) -}) +}) print([1, 2, 3].collect { @@ -10,5 +10,5 @@ print([1, 2, 3].collect { }) Closure c1 = { mkString(it)} -Closure c2 = {mkString(it)} +Closure c2 = {mkString(it); if (a) return 2} def c3 = {mkString(it)} \ No newline at end of file From 1695bb3fecd87192b7de9d79923e52ff22bbc0d2 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 28 Mar 2012 16:10:33 +0400 Subject: [PATCH 27/84] report 'Missing return' for closure if there is explicit generic in expected type --- .../MissingReturnInspection.java | 8 +++++--- .../groovy/lang/MissingReturnTest.groovy | 1 + .../ClosureWithExplicitExpectedType.groovy | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java index 8a13a53cf64f..bf16de6542e3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java @@ -18,9 +18,7 @@ package org.jetbrains.plugins.groovy.codeInspection.noReturnMethod; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -71,6 +69,10 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { public static ReturnStatus getReturnStatus(PsiElement subject) { if (subject instanceof GrClosableBlock) { final PsiType inferredReturnType = GroovyExpectedTypesProvider.getExpectedClosureReturnType((GrClosableBlock)subject); + if (inferredReturnType instanceof PsiClassType) { + PsiClass resolved = ((PsiClassType)inferredReturnType).resolve(); + if (resolved != null && !(resolved instanceof PsiTypeParameter)) return mustReturnValue; + } return inferredReturnType != null && inferredReturnType != PsiType.VOID ? shouldReturnValue : shouldNotReturnValue; } else if (subject instanceof GrMethod) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy index e85cc9cd0a44..538fac39a666 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy @@ -41,6 +41,7 @@ public class MissingReturnTest extends LightCodeInsightFixtureTestCase { public void testImplicitReturnNull() throws Throwable {doTest();} public void testMissingReturnInClosure() {doTest();} public void testFinally() {doTest();} + public void testClosureWithExplicitExpectedType() {doTest()} private void doTest() { myFixture.enableInspections(new MissingReturnInspection()); diff --git a/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy b/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy new file mode 100644 index 000000000000..d8a58ad50356 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy @@ -0,0 +1,19 @@ +def foo(Closure c) { + return c().substring(1) +} + +foo { + print 2 +} + +foo { + 's' +} + +foo { + if (a) 's' +} + +foo { + if (a) 'a' else 'b' +} From 257cb18a580a37782d4d5d81ab010613e6c5f6e4 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 28 Mar 2012 14:30:48 +0200 Subject: [PATCH 28/84] findPrev and findNext ignore cycling if we do not remove unmatched elements from component --- .../src/com/intellij/ui/SpeedSearchBase.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java index 797edb0b4f98..458426a846dd 100644 --- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java +++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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,6 +17,7 @@ package com.intellij.ui; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.DataManager; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; @@ -198,6 +199,15 @@ public abstract class SpeedSearchBase extends SpeedSear final Object element = it.next(); if (isMatchingElement(element, _s)) return element; } + + if (UISettings.getInstance().CYCLE_SCROLLING) { + final ListIterator i = getElementIterator(0); + while (i.hasNext()) { + final Object element = i.next(); + if (isMatchingElement(element, _s)) return element; + } + } + return ( current != null && isMatchingElement(current, _s) ) ? current : null; } @@ -217,6 +227,15 @@ public abstract class SpeedSearchBase extends SpeedSear final Object element = it.previous(); if (isMatchingElement(element, _s)) return element; } + + if (UISettings.getInstance().CYCLE_SCROLLING) { + final ListIterator i = getElementIterator(getAllElements().length); + while (i.hasPrevious()) { + final Object element = i.previous(); + if (isMatchingElement(element, _s)) return element; + } + } + return selectedIndex != -1 && isMatchingElement(current, _s) ? current : null; } From 800ca62eab1351551a5cd9e5687a198f4a9cc181 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 28 Mar 2012 14:45:34 +0200 Subject: [PATCH 29/84] speed search for switcher in pinned mode --- .../com/intellij/ide/actions/Switcher.java | 135 +++++++++++++++--- .../SwitcherToolWindowsListRenderer.java | 37 ++++- 2 files changed, 149 insertions(+), 23 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 63b0ae1525a1..757c5a9d194a 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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,6 +34,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; @@ -43,10 +44,8 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.openapi.wm.impl.ToolWindowManagerImpl; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.Gray; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.SimpleTextAttributes; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; +import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; @@ -62,6 +61,8 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.util.*; import java.util.List; @@ -121,10 +122,12 @@ public class Switcher extends AnAction implements DumbAware { ToolWindow tw; if (SWITCHER != null && event instanceof KeyEvent) { final KeyEvent keyEvent = (KeyEvent)event; - if (event.getID() == KEY_RELEASED && keyEvent.getKeyCode() == CTRL_KEY && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if (event.getID() == KEY_RELEASED && keyEvent.getKeyCode() == CTRL_KEY && isAutoHide()) { SwingUtilities.invokeLater(CHECKER); } - else if (event.getID() == KEY_PRESSED && (tw = SWITCHER.twShortcuts.get(String.valueOf((char)keyEvent.getKeyCode()))) != null) { + else if (isAutoHide() + && event.getID() == KEY_PRESSED + && (tw = SWITCHER.twShortcuts.get(String.valueOf((char)keyEvent.getKeyCode()))) != null) { SWITCHER.myPopup.closeOk(null); tw.activate(null, true, true); } @@ -176,6 +179,7 @@ public class Switcher extends AnAction implements DumbAware { final Project project; final Map twShortcuts; final Alarm myAlarm; + final SwitcherSpeedSearch mySpeedSearch = isAutoHide() ? null : new SwitcherSpeedSearch(); @SuppressWarnings({"ManualArrayToCollectionCopy"}) SwitcherPanel(Project project) { @@ -225,7 +229,7 @@ public class Switcher extends AnAction implements DumbAware { toolWindows = new JBList(twModel); toolWindows.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); toolWindows.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - toolWindows.setCellRenderer(new SwitcherToolWindowsListRenderer(ids, map) { + toolWindows.setCellRenderer(new SwitcherToolWindowsListRenderer(mySpeedSearch, ids, map) { @Override public Component getListCellRendererComponent(JList list, Object value, @@ -297,7 +301,7 @@ public class Switcher extends AnAction implements DumbAware { files = new JBList(filesModel); files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); files.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); - files.setCellRenderer(new VirtualFilesRenderer(project) { + files.setCellRenderer(new VirtualFilesRenderer(project, mySpeedSearch) { @Override public Component getListCellRendererComponent(JList list, Object value, @@ -381,19 +385,33 @@ public class Switcher extends AnAction implements DumbAware { .setRequestFocus(true) .setTitle(SWITCHER_TITLE) .setMovable(false) + .setCancelKeyEnabled(false) .setCancelCallback(new Computable() { - public Boolean compute() { - SWITCHER = null; - return true; - } - }).createPopup(); + public Boolean compute() { + SWITCHER = null; + return true; + } + }).createPopup(); - new AnAction(null, null, null){ + if (!isAutoHide()) { + new AnAction(null, null, null) { @Override public void actionPerformed(AnActionEvent e) { //suppress all actions to activate a toolwindow : IDEA-71277 } }.registerCustomShortcutSet(TW_SHORTCUT, this, myPopup); + new AnAction(null, null, null) { + + @Override + public void actionPerformed(AnActionEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { + mySpeedSearch.hidePopup(); + } else { + myPopup.cancel(); + } + } + }.registerCustomShortcutSet(CustomShortcutSet.fromString("ESCAPE"), this, myPopup); + } Component comp = null; final EditorWindow result = FileEditorManagerEx.getInstanceEx(project).getActiveWindow().getResult(); @@ -407,6 +425,7 @@ public class Switcher extends AnAction implements DumbAware { myPopup.showInCenterOf(comp); } + private Map createShortcuts(List windows) { final Map keymap = new HashMap(windows.size()); final List pluginToolWindows = new ArrayList(); @@ -441,7 +460,7 @@ public class Switcher extends AnAction implements DumbAware { } public void keyReleased(KeyEvent e) { - if ((e.getKeyCode() == CTRL_KEY && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) + if ((e.getKeyCode() == CTRL_KEY && isAutoHide()) || e.getKeyCode() == VK_ENTER) { navigate(); } else @@ -453,6 +472,8 @@ public class Switcher extends AnAction implements DumbAware { } public void keyPressed(KeyEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) return; + switch (e.getKeyCode()) { case VK_UP: goBack(); @@ -546,7 +567,7 @@ public class Switcher extends AnAction implements DumbAware { } private void goRight() { - if ((isFilesSelected() || !isFilesVisible()) && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if ((isFilesSelected() || !isFilesVisible()) && isAutoHide()) { cancel(); } else { @@ -562,7 +583,7 @@ public class Switcher extends AnAction implements DumbAware { } private void goLeft() { - if (isToolWindowsSelected() && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if (isToolWindowsSelected() && isAutoHide()) { cancel(); } else { @@ -699,26 +720,102 @@ public class Switcher extends AnAction implements DumbAware { repaintLists(); } public void mouseDragged(MouseEvent e) {} + + private class SwitcherSpeedSearch extends SpeedSearchBase implements PropertyChangeListener { + private Object[] myElements; + + public SwitcherSpeedSearch() { + super(SwitcherPanel.this); + addChangeListener(this); + } + + @Override + protected int getSelectedIndex() { + return isFilesSelected() + ? files.getSelectedIndex() + : files.getModel().getSize() + toolWindows.getSelectedIndex(); + } + + @Override + protected Object[] getAllElements() { + if (myElements == null) { + final SwitcherPanel switcher = SwitcherPanel.this; + final Object[] files = ((DefaultListModel)switcher.files.getModel()).toArray(); + final Object[] toolWindows = ((DefaultListModel)switcher.toolWindows.getModel()).toArray(); + myElements = new Object[files.length + toolWindows.length]; + System.arraycopy(files, 0, myElements, 0, files.length); + System.arraycopy(toolWindows, 0, myElements, files.length, toolWindows.length); + } + return myElements; + } + + + @Override + protected String getElementText(Object element) { + return element instanceof ToolWindow + ? ids.get(element) + : element instanceof FileInfo + ? ((FileInfo)element).getFirst().getName() : ""; + } + + @Override + protected void selectElement(Object element, String selectedText) { + if (element instanceof FileInfo) { + toolWindows.getSelectionModel().clearSelection(); + files.setSelectedValue(element, false); + } else { + files.clearSelection(); + toolWindows.setSelectedValue(element, false); + } + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + files.repaint(); + toolWindows.repaint(); + } + } + } + + private static boolean isAutoHide() { + return UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; } private static class VirtualFilesRenderer extends ColoredListCellRenderer { private final Project myProject; + private final SpeedSearchBase mySearch; + private boolean hide = false; - public VirtualFilesRenderer(Project project) { + public VirtualFilesRenderer(Project project, SpeedSearchBase search) { myProject = project; + mySearch = search; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + hide = false; if (value instanceof FileInfo) { final VirtualFile virtualFile = ((FileInfo)value).first; final String name = virtualFile.getPresentableName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); + if ( mySearch != null && mySearch.isPopupActive()) { + hide = mySearch.matchingFragments(name) == null && !StringUtil.isEmpty(mySearch.getEnteredPrefix()); + } final FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile); final TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); } } + + @Override + protected void doPaint(Graphics2D g) { + GraphicsConfig config = new GraphicsConfig(g); + if (hide) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); + } + super.doPaint(g); + config.restore(); + } } private static class FileInfo extends Pair { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java b/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java index c56a31fd792d..e9117d735aa7 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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,11 +15,15 @@ */ package com.intellij.ide.actions; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.SpeedSearchBase; import com.intellij.util.PlatformIcons; import javax.swing.*; @@ -34,26 +38,51 @@ import java.util.Map; class SwitcherToolWindowsListRenderer extends ColoredListCellRenderer { private static final Map iconCache = new HashMap(); private static final SimpleTextAttributes ID_STYLE = new SimpleTextAttributes(SimpleTextAttributes.STYLE_UNDERLINE, Color.black); + private final SpeedSearchBase mySpeedSearch; private final Map ids; private final Map shortcuts; + private boolean hide = false; - SwitcherToolWindowsListRenderer(Map ids, Map shortcuts) { + SwitcherToolWindowsListRenderer(SpeedSearchBase speedSearch, + Map ids, + Map shortcuts) { + mySpeedSearch = speedSearch; this.ids = ids; this.shortcuts = shortcuts; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + hide = false; if (value instanceof ToolWindow) { final ToolWindow tw = (ToolWindow)value; setIcon(getIcon(tw)); - append(shortcuts.get(tw), ID_STYLE); - final String name = ": " + ids.get(tw); + final String name; + + if (UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + append(shortcuts.get(tw), ID_STYLE); + name = ": " + ids.get(tw); + } else { + name = ids.get(tw); + } final TextAttributes attributes = new TextAttributes(Color.BLACK, null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { + hide = mySpeedSearch.matchingFragments(ids.get(tw)) == null && !StringUtil.isEmpty(mySpeedSearch.getEnteredPrefix()); + } } } + @Override + protected void doPaint(Graphics2D g) { + GraphicsConfig config = new GraphicsConfig(g); + if (hide) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); + } + super.doPaint(g); + config.restore(); + } + private Icon getIcon(ToolWindow toolWindow) { Icon icon = iconCache.get(ids.get(toolWindow)); if (icon != null) return icon; From 3de1d61fe2959666d469a677568188f764acd3ff Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 28 Mar 2012 16:57:53 +0400 Subject: [PATCH 30/84] svn: blinking tests --- .../idea/svn16/SvnCommittedViewTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java index 9d214220cfae..f6fb8dbd5458 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCommittedViewTest.java @@ -10,10 +10,12 @@ import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import java.io.File; @@ -23,6 +25,13 @@ import java.util.List; public class SvnCommittedViewTest extends SvnTestCase { + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + SvnConfiguration.getInstance(myProject).DETECT_NESTED_COPIES = false; + } + @Test public void testAdd() throws Exception { enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); @@ -37,6 +46,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -68,6 +78,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -96,6 +107,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -124,6 +136,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -156,6 +169,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -181,6 +195,7 @@ public class SvnCommittedViewTest extends SvnTestCase { verify(runSvn("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch")); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), @@ -210,6 +225,7 @@ public class SvnCommittedViewTest extends SvnTestCase { checkin(); final SvnVcs vcs = SvnVcs.getInstance(myProject); + vcs.invokeRefreshSvnRoots(false); final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); final List changeListList = committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), From ce130a565816b40abb724c42e58994f81c4f4ee1 Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Wed, 28 Mar 2012 17:36:49 +0400 Subject: [PATCH 31/84] codestyle issue --- platform/platform-impl/src/com/intellij/ide/IdeTooltip.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java b/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java index 59511366ce00..44224ed6f10e 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java @@ -50,7 +50,7 @@ public class IdeTooltip extends ComparableObject.Impl { private Ui myUi; - private boolean hint = false; + private boolean myHint = false; public IdeTooltip(Component component, Point point, JComponent tipComponent, Object... identity) { @@ -235,12 +235,12 @@ public class IdeTooltip extends ComparableObject.Impl { } public IdeTooltip setHint(boolean hint) { - this.hint = hint; + this.myHint = hint; return this; } public boolean isHint() { - return hint; + return myHint; } public boolean isInside(RelativePoint target) { From da2ff9f141d2271ef3e497e268558cd42672fb89 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 15:29:04 +0200 Subject: [PATCH 32/84] add checks for mixed junit3/junit4 environment --- .../junit4/JUnit4TestResultsSender.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java index bfb590a18a02..9a2b844f55e4 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java @@ -34,6 +34,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class JUnit4TestResultsSender extends RunListener { + private static final String JUNIT_FRAMEWORK_COMPARISON_NAME = ComparisonFailure.class.getName(); + private static final String ORG_JUNIT_COMPARISON_NAME = "org.junit.ComparisonFailure"; + private static final String ASSERTION_CLASS_NAME = AssertionError.class.getName(); + private static final String ASSERTION_FAILED_CLASS_NAME = "junit.framework.AssertionFailedError"; + private final OutputObjectRegistry myRegistry; private Map myCurrentTestMeters = new HashMap(); private Set myCurrentTests = new HashSet(); @@ -46,7 +51,8 @@ public class JUnit4TestResultsSender extends RunListener { final Description description = failure.getDescription(); final Throwable throwable = failure.getException(); - if (throwable instanceof AssertionError || throwable.getCause() instanceof AssertionError) { + final Throwable cause = throwable.getCause(); + if (isAssertionError(throwable.getClass()) || isAssertionError(cause != null ? cause.getClass() : null)) { // junit4 makes no distinction between errors and failures doAddFailure(description, throwable); } @@ -81,13 +87,25 @@ public class JUnit4TestResultsSender extends RunListener { createExceptionNotification(assertion).createPacket(myRegistry, test).send(); } + private static boolean isComparisonFailure(Throwable throwable) { + final String throwableClassName = throwable.getClass().getName(); + return throwableClassName.equals(JUNIT_FRAMEWORK_COMPARISON_NAME) || throwableClassName.equals(ORG_JUNIT_COMPARISON_NAME); + } + + private static boolean isAssertionError(Class throwableClass) { + if (throwableClass == null) return false; + final String throwableClassName = throwableClass.getName(); + if (throwableClassName.equals(ASSERTION_CLASS_NAME) || throwableClassName.equals(ASSERTION_FAILED_CLASS_NAME)) return true; + return isAssertionError(throwableClass.getSuperclass()); + } + private static PacketFactory createExceptionNotification(Throwable assertion) { if (assertion instanceof KnownException) return ((KnownException)assertion).getPacketFactory(); - if (assertion instanceof ComparisonFailure || assertion instanceof org.junit.ComparisonFailure) { + if (isComparisonFailure(assertion)) { return ComparisonDetailsExtractor.create(assertion); } final Throwable cause = assertion.getCause(); - if (cause instanceof ComparisonFailure || cause instanceof org.junit.ComparisonFailure) { + if (isComparisonFailure(cause)) { try { return ComparisonDetailsExtractor.create(assertion, ComparisonDetailsExtractor.getExpected(cause), ComparisonDetailsExtractor.getActual(cause)); } From ff3ee4a60a53497838a687676995037888253585 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 15:32:27 +0200 Subject: [PATCH 33/84] exclude junit.jar from default idea sdk (leave only junit4.xxx.jar) --- plugins/devkit/src/projectRoots/IdeaJdk.java | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java index 07d46ffd7de4..9501558fb101 100644 --- a/plugins/devkit/src/projectRoots/IdeaJdk.java +++ b/plugins/devkit/src/projectRoots/IdeaJdk.java @@ -46,6 +46,7 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -183,17 +184,18 @@ public class IdeaJdk extends SdkType implements JavaSdkType { private static VirtualFile[] getIdeaLibrary(String home) { ArrayList result = new ArrayList(); - appendIdeaLibrary(home + File.separator + LIB_DIR_NAME, null, result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JAVAEE_DIR + File.separator + LIB_DIR_NAME, "javaee-impl.jar", - result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JSF_DIR + File.separator + LIB_DIR_NAME, "jsf-impl.jar", result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + PERSISTENCE_SUPPORT + File.separator + LIB_DIR_NAME, "persistence-impl.jar", result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + DATABASE_DIR + File.separator + LIB_DIR_NAME, "database-impl.jar", result); - appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + CSS_DIR + File.separator + LIB_DIR_NAME, "css.jar", result); + appendIdeaLibrary(home + File.separator + LIB_DIR_NAME, result, "junit.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JAVAEE_DIR + File.separator + LIB_DIR_NAME, result, "javaee-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + JSF_DIR + File.separator + LIB_DIR_NAME, result, "jsf-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + PERSISTENCE_SUPPORT + File.separator + LIB_DIR_NAME, result, "persistence-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + DATABASE_DIR + File.separator + LIB_DIR_NAME, result, "database-impl.jar"); + appendIdeaLibrary(home + File.separator + PLUGINS_DIR + File.separator + CSS_DIR + File.separator + LIB_DIR_NAME, result, "css.jar"); return VfsUtil.toVirtualFileArray(result); } - private static void appendIdeaLibrary(final String path, @Nullable @NonNls final String forbidden, final ArrayList result) { + private static void appendIdeaLibrary(final String path, + final ArrayList result, + @NonNls final String... forbidden) { final JarFileSystem jfs = JarFileSystem.getInstance(); final File lib = new File(path); if (lib.isDirectory()) { @@ -201,7 +203,7 @@ public class IdeaJdk extends SdkType implements JavaSdkType { if (jars != null) { for (File jar : jars) { @NonNls String name = jar.getName(); - if (jar.isFile() && !name.equals(forbidden) && (name.endsWith(".jar") || name.endsWith(".zip"))) { + if (jar.isFile() && Arrays.binarySearch(forbidden, name) < 0 && (name.endsWith(".jar") || name.endsWith(".zip"))) { result.add(jfs.findFileByPath(jar.getPath() + JarFileSystem.JAR_SEPARATOR)); } } From 3ac880a12ca69165fbd38c5f418ea16cc560d221 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 15:33:06 +0200 Subject: [PATCH 34/84] check for disposing during quick documentation (IDEA-83567) --- .../intellij/codeInsight/documentation/DocumentationManager.java | 1 + 1 file changed, 1 insertion(+) 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 9cd4000274db..23915b48aedc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -718,6 +718,7 @@ public class DocumentationManager { myUpdateDocAlarm.addRequest(new Runnable() { public void run() { + if (myProject.isDisposed()) return; final Throwable[] ex = new Throwable[1]; String text = null; try { From dccf7bc5ef2101482f24cd2ec00da8a238d97f39 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 15:35:14 +0200 Subject: [PATCH 35/84] resolve performance: static import shadowing checks perform all conflicts check on each add (IDEA-83594) --- .../intellij/psi/scope/processor/MethodCandidatesProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java index 79d526ac8ac7..b3dbf527fb1e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java @@ -79,7 +79,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{ protected boolean isShadowed(final PsiMethod candidate) { if (myCurrentFileContext instanceof PsiImportStaticStatement) { - for (JavaResolveResult result : getResult()) { + for (JavaResolveResult result : getResults()) { if (result.getElement() != candidate && result.isAccessible() && !(result.getCurrentFileResolveScope() instanceof PsiImportStaticStatement)) return true; From a04c3ac7cb96b355428ba59d5dd08fafd04003fe Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 28 Mar 2012 16:16:25 +0200 Subject: [PATCH 36/84] Runtime logger renamed to avoid confusion --- .../{rt/Logger.java => LoggerRt.java} | 19 ++++++++++--------- .../intellij/openapi/util/io/FileUtilRt.java | 4 ++-- .../RevertCommittedStuffAbstractAction.java | 4 ++-- 3 files changed, 14 insertions(+), 13 deletions(-) rename platform/util-rt/src/com/intellij/openapi/diagnostic/{rt/Logger.java => LoggerRt.java} (89%) diff --git a/platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java b/platform/util-rt/src/com/intellij/openapi/diagnostic/LoggerRt.java similarity index 89% rename from platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java rename to platform/util-rt/src/com/intellij/openapi/diagnostic/LoggerRt.java index 8eb116e18585..2e25291e4b6c 100644 --- a/platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java +++ b/platform/util-rt/src/com/intellij/openapi/diagnostic/LoggerRt.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.diagnostic.rt; +package com.intellij.openapi.diagnostic; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -22,15 +22,16 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Method; import java.util.logging.Level; import java.util.logging.LogManager; +import java.util.logging.Logger; /** * A wrapper which uses either IDE logging subsystem (if available) or java.util.logging. * * @since 12.0 */ -public abstract class Logger { +public abstract class LoggerRt { private interface Factory { - Logger getInstance(@NotNull @NonNls final String category); + LoggerRt getInstance(@NotNull @NonNls final String category); } private static Factory ourFactory; @@ -48,7 +49,7 @@ public abstract class Logger { } @NotNull - public static Logger getInstance(@NotNull @NonNls final String category) { + public static LoggerRt getInstance(@NotNull @NonNls final String category) { return getFactory().getInstance(category); } @@ -84,9 +85,9 @@ public abstract class Logger { private final LogManager myManager = LogManager.getLogManager(); @Override - public Logger getInstance(@NotNull @NonNls final String category) { - final java.util.logging.Logger logger = myManager.getLogger(category); - return new Logger() { + public LoggerRt getInstance(@NotNull @NonNls final String category) { + final Logger logger = myManager.getLogger(category); + return new LoggerRt() { @Override public void info(@Nullable @NonNls final String message, @Nullable final Throwable t) { logger.log(Level.INFO, message, t); @@ -124,10 +125,10 @@ public abstract class Logger { } @Override - public Logger getInstance(@NotNull @NonNls final String category) { + public LoggerRt getInstance(@NotNull @NonNls final String category) { try { final Object logger = myGetInstance.invoke(null, category); - return new Logger() { + return new LoggerRt() { @Override public void info(@Nullable @NonNls final String message, @Nullable final Throwable t) { try { diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index 2881afe12457..1b7440f97c56 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.util.io; -import com.intellij.openapi.diagnostic.rt.Logger; +import com.intellij.openapi.diagnostic.LoggerRt; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.text.StringUtilRt; import org.jetbrains.annotations.NonNls; @@ -34,7 +34,7 @@ import java.util.UUID; */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class FileUtilRt { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtilLight"); + private static final LoggerRt LOG = LoggerRt.getInstance("#com.intellij.openapi.util.io.FileUtilLight"); protected static final ThreadLocal BUFFER = new ThreadLocal() { protected byte[] initialValue() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java index ad2fe9aeacaa..82bd8486d1ec 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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,7 +18,7 @@ package com.intellij.openapi.vcs.changes.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.diagnostic.rt.Logger; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.patch.BinaryFilePatch; import com.intellij.openapi.diff.impl.patch.FilePatch; import com.intellij.openapi.diff.impl.patch.IdeaTextPatchBuilder; From 95a32c62641a3f648b31673b14f7ece317d045c3 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 28 Mar 2012 16:25:48 +0200 Subject: [PATCH 37/84] file system refresh animated icon --- platform/icons/src/process/fs/step_1.png | Bin 0 -> 1204 bytes platform/icons/src/process/fs/step_10.png | Bin 0 -> 1202 bytes platform/icons/src/process/fs/step_11.png | Bin 0 -> 1175 bytes platform/icons/src/process/fs/step_12.png | Bin 0 -> 1188 bytes platform/icons/src/process/fs/step_13.png | Bin 0 -> 1173 bytes platform/icons/src/process/fs/step_14.png | Bin 0 -> 1195 bytes platform/icons/src/process/fs/step_15.png | Bin 0 -> 1189 bytes platform/icons/src/process/fs/step_16.png | Bin 0 -> 1194 bytes platform/icons/src/process/fs/step_17.png | Bin 0 -> 1188 bytes platform/icons/src/process/fs/step_18.png | Bin 0 -> 1189 bytes platform/icons/src/process/fs/step_2.png | Bin 0 -> 1174 bytes platform/icons/src/process/fs/step_3.png | Bin 0 -> 1187 bytes platform/icons/src/process/fs/step_4.png | Bin 0 -> 1174 bytes platform/icons/src/process/fs/step_5.png | Bin 0 -> 1190 bytes platform/icons/src/process/fs/step_6.png | Bin 0 -> 1185 bytes platform/icons/src/process/fs/step_7.png | Bin 0 -> 1184 bytes platform/icons/src/process/fs/step_8.png | Bin 0 -> 1185 bytes platform/icons/src/process/fs/step_9.png | Bin 0 -> 1194 bytes platform/icons/src/process/fs/step_mask.png | Bin 0 -> 978 bytes .../icons/src/process/fs/step_passive.png | Bin 0 -> 1192 bytes .../util/ui/RefreshFileSystemIcon.java | 54 ++++++++++++++++++ .../wm/impl/status/InfoAndProgressPanel.java | 48 ++++++++-------- 22 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 platform/icons/src/process/fs/step_1.png create mode 100644 platform/icons/src/process/fs/step_10.png create mode 100644 platform/icons/src/process/fs/step_11.png create mode 100644 platform/icons/src/process/fs/step_12.png create mode 100644 platform/icons/src/process/fs/step_13.png create mode 100644 platform/icons/src/process/fs/step_14.png create mode 100644 platform/icons/src/process/fs/step_15.png create mode 100644 platform/icons/src/process/fs/step_16.png create mode 100644 platform/icons/src/process/fs/step_17.png create mode 100644 platform/icons/src/process/fs/step_18.png create mode 100644 platform/icons/src/process/fs/step_2.png create mode 100644 platform/icons/src/process/fs/step_3.png create mode 100644 platform/icons/src/process/fs/step_4.png create mode 100644 platform/icons/src/process/fs/step_5.png create mode 100644 platform/icons/src/process/fs/step_6.png create mode 100644 platform/icons/src/process/fs/step_7.png create mode 100644 platform/icons/src/process/fs/step_8.png create mode 100644 platform/icons/src/process/fs/step_9.png create mode 100644 platform/icons/src/process/fs/step_mask.png create mode 100644 platform/icons/src/process/fs/step_passive.png create mode 100644 platform/platform-api/src/com/intellij/util/ui/RefreshFileSystemIcon.java diff --git a/platform/icons/src/process/fs/step_1.png b/platform/icons/src/process/fs/step_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a02f0d104b398b50d5f8dc52940ff7220f45417a GIT binary patch literal 1204 zcmaJ>TWAzl7(TmcR=bVK#}59H#ZCyDg)G`oXJ^hPV=|Y{ zOx#K6#U#+Ev{0c6_CjjWVxUN0tp)QCDr(VCM0$BBEIt$zYA8rbE$NwtzJ< zsyKoQNR%hvyoTZcG!aU%WS4~3I7wGY(Z!ICYG5`1@m|Ler7>i~G8$2|1o8XjD+E;J z1ThpAXu-&!Q6)EJqQR;DqBJ!o#bl!Q6&QCoETAG=gpN9{S)7v~)^#}?yT=p(*CF;; zf_Pk1Nf>|`-9#`<(m{!iFfbA#nGhWd#r8s$W@w6GDLNWtXf7P(Xa;UP1kPs46|TVd zZREnc1Tkvc21ilVYL%?+BXx6xVq&ovMY9yk1~DRNO=`C21U0LxuD~NpG8MyCbPc+S zVp*TC69lgGaSN)kDXUo<*Mu*Oazuk-NZM_w4itp{hpOr(+OiAiNxlCmY!xRBL=}*w zPnZ%OT&2rRWpEi2iMDPQb$z^kivy#&ty`nI0W*VPl7T~tChJve9WMx6UbAdblTe;d z5Lkg!6q$=M=`5IftnL3x(r3n>jcAYCf;bt0gT`Q;t z&deiIIfCRqQ&-`7%be1-fS8lY1r*1 zwsi;iNdUmpo##_U=jZaHwYA=+Jx7mErx(2v&9XDf@Go0mhNt{Xt;z47SyGd4H6ObI zR_@)H8+znhn7#CA`%TaZZhz&IZ$4GKm5lE^Ht$*Kf<9$?bGZWF0inBF-t$ZyIay8~ zZVk+X+O=eM{^V!=(5}0~AKqJ?UVV5zbK~8!bJNcUeg(CsfBQHEx*xXX5_8|AeFx#p z>tDBAc(C&#XuAG)bAg&JZU4lx`{?S6?VdKjDvtZU_0)R#7Zy+40_DOf7=lcT<6WvP zE?2%g-_d=w`CR(*(_$DroBQF%7SD+lurLnqfZFf_klLTymHg5hnEm4ZbAj2~fsW3# zh2@XVw7&nr!O|dc`=ton<6Vj`_q@>}oY|6G=(zCbjyvb#hc30lMKJ%@Vei|Q@3*=C Nk$kqFznDHW^AFRIj0XS! literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_10.png b/platform/icons/src/process/fs/step_10.png new file mode 100644 index 0000000000000000000000000000000000000000..b6bfb992ece4a1610f1fcc17bf472efdde19caca GIT binary patch literal 1202 zcmaJ>TWB0r7(SbrZ5oqyYbs5nHpeLz3+`MtyPNKibuTlCS#(3(EM!rFnVmVC9g>+d z&YZZDAd)r^)1tm;1+mmnVj&{M2Olg74Hzn7ZHq+lh7bGTi-IotAh;0Eq}kL5*MXUH z;rqV-_AzJ2MxW^F=SaFk>jw zD2Ehn{`t?*AONk5o-dF>_9;=t2CH}&)-^2324FDZT8cV@2rQy$-HbE8eSD39x)x_9 zB3V9bNvN!kEZAs#VKlEU%&0MqNjwe*U6BeHh$zrCW=%(Q@4xY1B zI=IqtFO(%pHc|+-^BB)Ix;R$G1UqGHL1{d~3UER5FUr+9fd-QVEKSe-MFNg7=3E;rPa>si6DXk;1L z`U^-Kwy^F zEOQ%+%k{P#ce-%j+rGZVzaBc|JJ?|;v;I$f)r8!$aqbo<=FY<~6gu6O&FaSO()D+{ zAN{OtExr1t5&?%tzWTP)cdiE3XW=)XI{7C&(F2bQYOboXwr-+tq* z1FyXLY+;<)Ix+TMx374te1TiOe4}-BYyVcgb0&A}gCE-iQ{eTF$}MWwLCO1zWQIoN JE9t2-{{UXGiMs#* literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_11.png b/platform/icons/src/process/fs/step_11.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c85de9aa18d411490a8c5449cf9411f2f345be GIT binary patch literal 1175 zcmaJ>ZD<>19KSZ2Wl84VaMG&t;r0e%?jg1Cf0wV-o~FOoXkBGB@2oaEzgXTJehvHs4^?y82w#bbc@%+&wS+ ze!u_QkDKi8>)qh*^iveIA-_*5l68~&`n=@(!f(qmSvqj8j0eyVuE`dpGAgP-kk{p5 zScI}V{^oUw~xv#_e|o3P-(L|;jn7*P@`oqic49f1hw5X->PM-5wWQuKy>nxzg2MQQJ9 zEOJWGRg6u6Woxw>Q;RUj8fN)KBEfQDHXIHSM93aDuoTYe5+!tAx;Kvy1&zgpplECddxN7#DSv6?~x}VD)3Ge)rcq4G)VQ_v?eEaWT ze|Y+Grk$IKT+vu#V_lJCWbzUsA&LC^1Z>BV|!_og(pa8t~E z_vM+u$D;q|bAQb|6ZD<>19KYslsB4mT(?Oc)e7srxpt+YUmzN`1lisB^b5}|lX%w|y?w&Shb1&Xq zOj-wC=d=+NrigPBVGITeLlFETD*IrOsR-NGDGCKa*kla-FtKZVu4_6!7!U5A7k~3@6lb#i@u#IN8uh$-|H>%|vVr%Z#;5NnV5wsKNzR&l1o_-9(XojYk7)2+e49&4gj%L92L!fAuGS8KSiS1bE zlqG78V{#PLY&OZ}LDH}mC?=gwQ*?}q#i9riwU=~9YDIPXKvzM4wrr`UqZ&H!6s4-s zaIyr-^mYlFxg)FF+igM(qgs+lF(mDk)CG#-|3fux2W>kgcqiZg6t>GtCZtNxHX4?U z1~-4e3uSV=1trI@%7#(zc5%99IEGy_Ou)~uBm-tuT``*W7G4y&qHa5qF2kabC6EHC zstPwAPq2AGNG4N!f?*0wo)uC;G8UgGBzT_Bvt6!W$PEqZPM53P;ih_WJu7G?iY!1& zeF-WPmZ5>Ik~y_^E^JS|ZLZQgmqbr4g_5DX!TxK|-7DlCZ@Xh#bl5RI)REgQWb1Dx z>tAA6U$`jb%dIQbjZS9_A9de;!B59x$JA$k9LR%T2iNxJ&SPu!+{Q?I2)l9Z`_$t1FdzAAY@#C5Pu8A%1!e zXQ%|e*>{5?0yptsC4g_{f)CzRITQZcovR&v#tlaHh5bh-Lic5I_e8!5`(5Aa?#PpY z%Gne5w|{q!Opm{OoE`P;b@yC)8f*?8Zsa!hw_o9J)%!*KiIvNLg%%GVzw%JO*a%(v u&G*_5IQaSQwGZ6WzsTZu_)jbdR+_+b literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_13.png b/platform/icons/src/process/fs/step_13.png new file mode 100644 index 0000000000000000000000000000000000000000..29ee724831885f5d2548df3ece16ab2b0687ec40 GIT binary patch literal 1173 zcmaJ>ZD<>19DmZftWAwXra}uY4_EvkEccS;_1d&)?-G;Igpfp6VY*%Jo;KI)?z!DP zHEHp~F%-H_GW;SFbixKhWU#?hoG^!xsdKmwBBCEezxYLvG6zK_@wu+){9rt|dtUhc ze*d>0ce+x3E*O{y004r;f?TC*$a_cp^c%k0Q|K~Ia!aI!mq}Z(5t!F-1Hq!9te`4V zwDpr;p&0;%8NI$lmP(7FiVarrFl@)LC>wy8xsIi%Eks}gt>|Wk`QzGk2I^XdITA1N zB}+n0y|7`U+D5sqZnV_2#>~yanT|*W3`7*zF;19{*vT+Ex+2|s*Bk?PAf%OH9wfC? zsz3?b2*z1HqVfp=CSt4*=JRjw!rX)#zyAP_j|p$;b+`4tA0KjJ*B_&(+CSu;EO=^&{%gS`|8N%%CXr`e;qG8eKdT< zm%R;N|33T8X!j#`dw21?Tb5G&uR^ z1?koeR#~V{`mSz0mAF0>{QJ@Kf4SQ*%sLvliAAT`>;OyBs**`nR z4sV{WJrQ4QemM1JWBLz~<^ aS=R@CzqiVY_vU}|eiX%AS-!Mz{M0{d(0vO4 literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_14.png b/platform/icons/src/process/fs/step_14.png new file mode 100644 index 0000000000000000000000000000000000000000..83adfde6df2ae1350a31bdf23c1edac1c4e68810 GIT binary patch literal 1195 zcmaJ>TWs4@7(Q)inud1WCSckH_28;VY>O{hlO}GnB#s*rsm`L*Q?rMSIrd58w!X}E z7q{Y)P6B0sP?7eu2ehH_vWJO1PXeI^5E3s))i%b%B&6{On$V;opyjx0Ivxm?>~qog zegEx~FBc214+IYd0RRK}9ACogUhfU~@ptI=EeS6NoyoE@ZB(7QWFe4Nj0%EzO`1g| zBq>W5zC#lL_y|=jJ7r;tl?{!QJPhe-CT0ULk#tQ-o<|O>pjlN<5Wn5|l7Om`AZ8*0 zEtnZpQ*+A}nqDr5^76bKSBT_EIN`EbKtqlMU2Q?PSvNs!>#}(7T~h?yhB)&H;%QQ4 zp$IdEg9kUMK4(NW+??n0P!+(P1ha4q-&dUeX=O4e9o9TY*QmY^kQB8anh8rHZlW zBnX`8(-JguS5~)o+JqZMxspjSB<+>d1`5LeLp5y|Z966OEZ_eWw#6kAQ6*#>iFl4Dq+VJx(}SgaY2Vb=^3W~L(~17}oSG3xd+^3kDcJSOqt8*2 z4AmbL)P%O!wY^9-0s=uZ*>1jMSXi<@17|5u&)Y7{H-@WKL~!;Qc=GlLh`3cmC2pjp%(y literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_15.png b/platform/icons/src/process/fs/step_15.png new file mode 100644 index 0000000000000000000000000000000000000000..dd7c72f16c71bb04e31f95af91139d181ee5d5dd GIT binary patch literal 1189 zcmaJ>O>7ip82)xgN?QuSvt|yPet6HBPhHZo5j!{0fwnqE@1;OoUFK-K7%kUp()c&(09LV(9kpz z^wF5gsjiHs&9SP7CaU8Fy*i_d2Aw<%hbs~hun^W@#X4^LQYAsJ>q=xFT(dM>hv1n6 z{m4{N%|Y4m5R5TgMCal>j7J$h%860&c_?r^$MOQp4MliPiVaB|4>ul~MDvVEDX)xf z#3H8zJ&my|v23|qX37T{$D3k#Q50EDU)&GZD)+XA=dGy%te+v7Bc^9#HBf-l}45+QE)L?YK~$h%r1oYTAZV_Sf;MDrIdSYqpNEN`fW| zjAf4hD8 zzz_A6ul{^yH&|H?8G~WIcV{DftC3pnX?~r$Lp86ZzNex;F{eY-6K6k3z0kGL0Qa_? z|DbVYe9OS~t_yG1R`)FQGEcqq@XgS%-kycRR~R8|gE@^!7FC`xjp=zVmzS_Gk@I0H3p;eQ)*Dk>JOX&5SFTMqWGl4}KYjTmS$7 literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_16.png b/platform/icons/src/process/fs/step_16.png new file mode 100644 index 0000000000000000000000000000000000000000..a8628ed26f605bd7f0d7c69e45f832f14b912f3e GIT binary patch literal 1194 zcmaJ>TWBLy7@kSoUV^15x=>qn4^t|5$=sSWov~@s%%nE5DIpCuAmUDDPMg{8%o%4+ zO;QD?`yeU`S@1zDXk}TcpbPsbg|%P>1s5L#arI?a@nONsvPD>-SkH8ut`Ek6nRDU$ zzW??yuNUW@>Wd6TD2nRK&#EP|MuWGfi+oS)?rUUu0Ou-r9xdX!=0a-PKvf9xmbL^- zP&1k@d<7>dD$JPW3a%7R$~v-GEx@o1%OPxvnoKtwO<#r>RN<0orfZ%wa5Y zN-;Hz9hu|m^*UQ0W0AYW36dmnyvT`Sj38oO)5cmOW_u%T1r>U_YdY9OHV728Dq6uQ zhGcrD1j{*+wY|eOk%n;%&EW)=4@znS3x)rOTGkQT!zFk(-~SZ$%1sAyCFr3QS0{s8 z90@`>vf@GwBe#sunRXY8HH48@Lk>{p6RZFhOxr+p?*LyY$a&ktnytgUnqr6oYnq0v zBt>B+H=`yelyO1G2~t*^&Q9lY3ZKj=Qasz{sz_h4ppDyH<1RPXksDaSa!6zqy5@_} zm~oK>4oa5I&beee>K$^8&bcTZxg1G`3kLhILAS4ndxGteZOP%t_|PV9cZscEsW594 zML(QZr^}5Ws(btU>F}t3?sOL~if7H|e(ZS$j7D}snXlo{_b>SLFPFm~{g(N4?F!XO zzdtZ=6Ro||zfND<9!(6L>uZGHlCzn}YiWJ#)Npj`+PA%L_O@1^1ylYN|3YT(zRfQm z8iL>Z_e8&;f9kEwGsW|RtsA{N8xxnQowPrA|Kl6RW1$NtX#MBz@80fNc_i5?9jn^4 rr}qdZesjR!i@WIKd~@3!$@nyN{=?IM_H8#m3H~1W+?;wbd+O{z>rjQb literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_17.png b/platform/icons/src/process/fs/step_17.png new file mode 100644 index 0000000000000000000000000000000000000000..3184821bf5dcf9f4adec16860f69daf8b1321eba GIT binary patch literal 1188 zcmaJ>e`wrP9MA2prJNhqO4nOA=_7Mc!AoA!-enhhUam>!4!wF_kF|o+=8|`9)+R3| zsh1XoZHTn!u!?`^5UpCrgdqt2F;Uo|hajTVKjt6KKV1J(*(f^wLp)bsx?blWo)41u zgU{#l{qa7$rNZcgd!oHjilX-9jw(emcLrZaJNftB*i^~1&l{QW#&E@}st%&EIxZuS zGu0_nM5;dj)R$<8qQbOMn(!v_4~rT$88yH#zG)LSMGa+qTh(Te2g+#5u+sF#Czoho z=xKU9k%xI(M$^X81qY2SjFz;887-yLnFqj-FA@P0c`ESDS<4muG`*!Ol67#*(qIeX z&7|pDNloMnK*kON2?oYBnB+imkl_YlYA|&_;2{TDj%T3|=b)GnM96{dL6c~XUJ;AR zk?mMym!_vZ&lXv>TCFnG0R}r$ESE~9Sje+HA18>oJ8yZaAGh3tO$7zHnq%0Wfh`ay zs%1RqrD>AstrARoN7iz;+e8}1`l`)x3=B$Y0`vL*hnnUN+VzU)cE0~9?3U(j#1@f@ z=Nye(T;*U8$`)k@sUCJp7|%AlSeV8hcBioo6|3fAUKWO+@lew(Ybs+!e^|rZs>s*Fga#@lL8(i$aF1mR{+!HK!Y)dvf#zz)$yF+Xp z>$#kys8B4YWJ~_{<;Lb_CVc4R(y8IvE)DYhY2)~nj$`0ZwEk&fzHyU@2}xg{kj}+B`y%Ut)abdltv)MVh$MdBy|(-keAe!v5)Xyme_eWpTHFYA z|1G=M_pkKc4X%e*h49ah{G={N>u;U9c;^e1*u_Zw4e8p8@y>fr`g;pErXCNqzxr3( zDkEJk$EfIqaV63az_BkXwE=K*-$d$vtbGLcze#=D)z!CbP;={HaPy4*a!2Qt@UQCR><^!v?Rq=;Vfenn xJL}J%Xn$`hv$opkJ^!ch-RjWf$9I7mb^Ng>e>u}O`e^WOZD<>19KS4mGhH!=C>awUt`0j{?yY&*9liF_T)SkLQqsV(4`aRDJ#CKm?m6!+ zCM`13OslpeeVk*pNtQr~pCQP^MuP zD%#vzci;d)_(?sNck`Jy1r-^T;$f(YVPQ5w3=CB)MV)~zD8Omm6v@97uh+4W}96cFCrH?MPz~GM3iE|8Qs)S+1bNqGD6yPT*XvjS{6yHK%{3OTB%r);brqC6~s@(B5GGHR$FQc8|9`uq{3u7$2J0?KZYG8GY$8 zLHI&xIgzXUQh3s64Ec{$uPh9Idq`zC?xKF~*RJE>!@#YTg~wtlP;2=9ei>XS?QUN^ z4@%5O*O!U<*`8Fmy`a`VzdZirh1za4-(7#d`|R_*8?T8gspIwE{nEY8uO9Y){M&|f z`nlTeg~xv`Chx9ZUjd=o{mGvWACi_m;R;L*HX^+;LgvH-q54Ytz)mucDzG8 zcwKHA=nKN7(DuzGW sUTpj*&9;9Ls_%yE?9|cidtJdvVrTRGV!i#`5%0&59vPEw3{PJC2fzu8U;qFB literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_2.png b/platform/icons/src/process/fs/step_2.png new file mode 100644 index 0000000000000000000000000000000000000000..116c7739306a782558ca83ba178577b931620174 GIT binary patch literal 1174 zcmaJ>Pi)&%9Cn(LcG=1b(`Y-8c(_7PLHw^tT3gMM)Na>Ebyd_G{y{_A~Zt z<5pAE>;S8F*?|>lr*W7x#I$J=;sVnUiUx>DLp`z+Wrv9auye=Aa`Y0IkB_d!!tO4Izusz97(L1^lxd(2R20IWupQ4{7 zRa7T|j9ds33>VY6BoC5thL3Y%TznS@9M7@5z;XjIo|6&-632txhbGZnV^+#5qr0() zm7>cSI}*!QDix;E&meb>2IpH%Qc$k5^u_7Niu9O*nbVW;Ue1;T=&+N7<-EkZL;kyS?jx@YZDX| zisqDT!T+VSU9YFZZ?3IZhreynIYBsWzJIqp2hK-oFJ^AApDEwJ-lkxc0aj-OxPd=a#<9 zU;Ocb^yPNfO85Qn109?=`~6RB=4xB%y@l!zZMBc9U)5`uUVZ!V!Lb{m(i;nrQ*B$< zl*rMylHtsSdgo_7_g=7xvv+f8^*H12kG?iD_S^XJjJO0~huYO0`R1d|mj~ls=yM8e zgtpH9)p};*+~C@{2%fZEO4B_@4je|*ty_n#^u2WQ&^zZgTesHBx#e`{otBfU)kNRH cqTSlgQNDcQ&c(^=H-bM!Ze&8aIy`gwDL&wR_W%F@ literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_3.png b/platform/icons/src/process/fs/step_3.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd20857736b84b0ea956554fa08c47273afc0d0 GIT binary patch literal 1187 zcmaJ>TWB0r7(Sb=O`5bOr9$0^#Yy|-9$@WV*ymt6+%TE05`eQ@EOUO%)cth5>S5h1VdNped!K|Sa zP!1{D^ow7jBmhA|&yRQ`^0S<38KmN4$g*K$HUP;~*;dpd^57UM=q69Be)K5;b&V&6 zqcSbqBAU?qXB;#%GmuwjifTe5Qb%F3%wYioc?v8Wlcvj+d16zS!+ZalBH$*(EAqs> zq(3KhNb9un4!67oTC}I^$<9kqm6SpDYF#| zpLk-z^K6cyN~IE6I!szlfnpMg1VytH%Z4!`>`t4WQVyH$fx3c(T-DKSPq$3yD=K5w zl*bb|(|aWt_O`6)ZnX(Fj4CTO#gMdLQXMGE{|_~cZM5s<(EWV>Q`pT<+la~`*P3!v zJh<@#ekhw09i(`cleetNdKU*LEYET$EE|eLQIdhfx~W+ucM~tmT-J0w#Z*yN;t8xk z>bl0oGe;7AnP@bAM2s;^nn|!MD>9ilEvD0AT;wT35Ec|EjnvhvD$l@`7wUu)}M3amW| zkM7Ff-S^{?(02F4rFQtq%Revwe(jb5n`^6;&UWRy-A%&UGw@3AgF_dD>w%SDq`9j_ z_|xa()#LE*^ju)$?ZB%_wd+uK_w8egp*wBIn%YOj%kz`f!u9HB!ARxLCt^XNar2{NX;G;KAhX}v`~B}z&*0?R^P=39ul8ljx6qe_|4VDv(h;^x17HT tPLqS*C&9|2!pEU=fAN>kBuAI_!YY_QukGq4j`RL+Bby$O-tQZo{Rfg9ihKY7 literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_4.png b/platform/icons/src/process/fs/step_4.png new file mode 100644 index 0000000000000000000000000000000000000000..a237bd9c4a91093f2c0ce435a3fb1eb50a817388 GIT binary patch literal 1174 zcmaJ>ZD!yhKit7h)V;{=8vF*dy{34~0Jy)B$56cejo)><< z-~a8$ol6fN+1dV9J4I1DlS6Wbth>Fpt(AQDy{su@>B8|*Jc7n>NwFan(@+kAq@mHBbiqFQJ@JBmkBM+FrbjN)M!*RTkiq6VU_rKsZ&gB;B3W`zFp#w{A?T7*6x zOmQhof(3nO%7!CT!&!A|Tn%e<^e`B31tMTTtN_<2nvUQ`=yhFz?7eH22I~+!9-&_+ zHJVBT3E2~cxV#M*2aX4oY;s( zP7%6*u_drkgQUw1YG7O}_sr>|`e`$Y!8}CTx`q zZmio2WeJiE6^!gGLdAL)(*=Z)Q$QAwMuH3vj_am|O3peyl@gMsgB4SSNjX9j1xD93 zp+Ara#-xB0>X-U>KF-HDe<&W8d*gki`~AI%I#)*OgaJ)l=W1`bazn0X1;ZkdWoYYX zpq8+a0oF?v^v1cw8tQFuwZ^#&HsrD-8P*%@zXn~uBJT0Fo3a7(PdJ-rkIzkIuA7W^7*I=Cug3%IUR?U=O2zwAB;&*KH-jHl{sEGfiP8W7 literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_5.png b/platform/icons/src/process/fs/step_5.png new file mode 100644 index 0000000000000000000000000000000000000000..a9793e2aa4fc7e5204ceb1ad1eaaae00452c87e5 GIT binary patch literal 1190 zcmaJ>ZD<>19DllGp|%?Y+`y&`A8%SKTka*zrMV-wB+Vr@ZdXGZSjHIaa`&XYb@$@k zwYm0#EZx+~Q1FY0f;iY@`oVSc<6zTnf}$B47KAxO3X^>i5g7^=;&WZo`N4Q__q_1? z{r+!1?#02HbqroiyuiL$(pfs%8zrqApLN zGLqH#SH3|h00M+osk&9^5U-dzDf<}G(=E&fAeHtkS(!mDtf48*5QyKdUMHZY3dCVn zq9rSbrnT_}8%-`uRFs7og;R<20hsc5ETAJ-hMs=XaClE3HgtKs_pd1eZa~}_fq0Zu zRVu-pX(PyzbX1`e3{1pHCQfs4Za<9C3{5dHiXM$JG|!ImGy^vu0!OpeI$stGo3Zdo zAf{c{;wh@pXpoH&(zK^2hT}Mjj#05#6eFU}yy41T)NuB86h!1Gwr07SX+U35u9>s0 zK;TRtm7rT&vWBzSCfqQ}lP!uNX}_cnP?G*1s_R>5$1S7B`TnP{Q<=9ARYs0EYb$tg z^}T*5i_h6ec1^otnkPG5EKQrP=}emz%uTW+0}pG4YBrn=yd?2O!*OLpK}As@umY)R zDxVySCs{T-Hk!;O7$(mo6JuySmnb*4K!gbZ#9y|P*!N*`^~;CP z41(3~o={H!W?%U9uEj$rP?OYsz379)|be`qof_sqO>=I*oG&lBe& sKLvj8AHLSVl4+$c58dzi_ASs80@7J)+qHr0ul}E-n4b_o8#})E4-*N5djJ3c literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_6.png b/platform/icons/src/process/fs/step_6.png new file mode 100644 index 0000000000000000000000000000000000000000..3c7b285e2e5b54847ce0ed4eee0287ceb6dd39f7 GIT binary patch literal 1185 zcmaJ>OKjU@9Cs3}ZK{<8O~BeQ@!?W2CgMk4t-ZQ=*a;0KB}yYL2Of3pFOAjuf&G=Z z;gSvz83okCw9}Bvgn+|@7}5?CmFS@$Aq}((FyO#cga%xuK~Jb!`P?-f2ZAO0d+7K3 z{a-)%OmXt5zTSaef*|_x<5CH)A@A+!!rw>!+L7_nkFpgsWmZvLwjq&L%^3*tx;zU@ zP*xXT`U;K`M1a)F6;vra!z-pv$sUGsbqlizVl?SmvN8t|n1QpJA&|E|`P3=8%i5=XPuDqoUvd$I6I zAZrL&JWbc@b*dhvOna7QIgX>52px%pF(T|N8c24-hBMe!kf5X3nuRpe0G^^eV=f?p z#F^eLLAUm04QH=SxM8#_TQo~CUP*0Wq457uUEfDLs08oj`=7#2dC`J&2|DJ2t>D2` z2fa`hFWOK>rd>A8`F0nJH4~Xm&9s0x6{lEmN;6cm?(E_V1wL;$NH!Fhmjn_kP@1Ol z9K&XEiMTjCA|_Zi%Z?;Q#9Stui^k$2CyCKES2C3a9U7?3Rqt`7j$F?Qx`iW4(AHjt zYR)!wuv;>(bQ@)J@o8ON=81!B0E*rhqR$e*M_1h2GPyJ71!JXa>y7}gv3nw3{ zrBAH<8Q9#Kc;j4ByzLLQ{I`>iKUbF4v^Qjc91%{`YQDp__8_265bKKKk|B6OR|)2@YI8^hrN+w3YrH_&!=W zyj-n>u+>mCyjS q`q*}`^D=#$WrnfG6KaG5LQu;VEefl5Wc!Jpg literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_7.png b/platform/icons/src/process/fs/step_7.png new file mode 100644 index 0000000000000000000000000000000000000000..103ba21a4677fef9e7fa4836d6b3521061c164f1 GIT binary patch literal 1184 zcmaJ>ZD<>19KT#@leN}XonTjV4>zWMXzne!WOp>?wRMrDge2JbLA%S{)8=UIrFT!8 zYd_3%h^8MV3j5&82Vrb%pN4`=M21!3z&Q{>{IH2HLl9*kMLz^LiO+RS=Lh4#-Sfil z_xr#7xXr@sGb2L>h6sWf$sNrW@jB+c!9n~z_(xa9%Q%{@ppvKD2vp&sX2hxAKmLRQni{9( zggl$KGO(r{UAJLreYUKuFDar*C7uRTu7m}2h-BdEb;FU|IJKiI;k|dwP+$jwmg3ai zq$>FW$e1<+0?mdLHp+o$gytfw7!fA{&vGoo@eCUaajYc7B$fla4~3)I>Vj0v&g{m* zr#MwZ$dVYQ(P+?(Fm2k43@3^r!}1KzhcF`KtQkmlLxyvxr;vq?Vrv%COapj|a@AZx zaSCU8w*=kVlQo>(HsOXbu52+J&3YyEfcgCYLv?)*?VuvOm+yZHJLNSCGDYZ^E4G3M zw{XY{Wl0$u%E+|KrdjWGu~0LS>C{XMWJ&_ffjP}k&4#ms&*!C_;UL*iU@jY{umY`V zsw4_58x|v}*pW<>T$ECvZ6x+^| zt5BV>O&#o%ENT67Inq~em#g;AMeNIEa59WH*nbVWcZJ>KZTD=84|~Rk26nrRZB4%O z+HHdH?ayUXW%qjZPPd!zA8u}Lq_;?g<@uA^3paw#fx|=XJIQN1P#OE8G;lih3be`k9d#u@E3tuP5pDqPjm){%T z8g75p3U)@5lj&T9zxiz7-Dc&@p#N;M6OQ^Pi)&%9CqrhOUtUY2Zk~<_T;LUvBY+oq_vf_PUD0`EM1gFTclBjW4|<}wV$!w z#pwY#y{u&t;()}oAtAI10UAt`wiAEWkscTlH$V&|5QuR?nxIAMp-`T?rsF`cWWPW9 zzVG+%la~vV&-C>k=_LrFFP9aIceUfTi=%O60p-{dkR(Ux@1Bksh|o3IZc{@ zMJOqam+rziL6DSMD%<7!NnS=;Nb)ctM>8;+AmZbWA<47Q1{FA?>Iv$>N4F`UDhcXL zG|%LX6s)P)1rts!OqS$@S(#I)@i7p0cr2hnTLO+Yr(3*}pmub5y!WnY3hY4a*#z}4 zsdBymQpkiL8e)Pn6JtRv5@I6^7vWBTFvBu58>X3&Aj|O45uRbe?nB{drc&jLVrDlM zJ|(D{Z5upI*X#9AeK>^78Jgudj%LDiI2^=?pw-ZA$qDM#U|T_imTanqts)(Gic$s5 z+X)J1`mhAe*pt<*-8SKd(T-%$Y>4qnY6J86|A%VY9@?^t@KL`1DQuM*2BeG7Li47K z2Ui{RLK%F@gp!TS5<+wBE*5IYMpg|OAT<>YvEYoVE2wVm;PZJtr(3q9%P=P zdLAkn6KPZGH1v zD@zc*$8%z`H=8v){v zA7zR>*K@^p-Q9d*;PO4U+ p_g`dmBU)HT*K&B}+e5#7(ei#8x%8y?;lvAz{{X4RhnWBX literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_9.png b/platform/icons/src/process/fs/step_9.png new file mode 100644 index 0000000000000000000000000000000000000000..10c777aca3c0e9d6ac6b3c2ac4096f67bd506101 GIT binary patch literal 1194 zcmaJ>ZD<>19KR-Ygt*v<1=|YS<8}KGS?(oo%^l6!G}qcVuhcZ7k##SZyC?0@-HUfm z&9$GBfit?DWAkBdK$Kvh!Y zWL#uKGXrPT(FF@mER5ylg;|+X$btQ!-{G-<29X3D?YM69PKw;rV|}fe6DgG#jCrzA(%1@jjkm!PZ0KXqHmqbHd10 zEPP6lGYFYHO_$4MsvM;ZYno;`j-#0f9f^c7B5cp=NOHou-P=?Upel z=1_{nnLaB)Gq+`Rd#g>jVYDNeG)pmVNllsaJiRpK0x@Sd#@4fGR-+lLFb>+s?fjW{uC&={PmP|Che^Y(AZ1B{TcW3JZnHPjH(W^ID z!@7kX>PvQtkrF@TY(bb`NJ87`5C)oL!wYor>)UrC@LXM7S1s8J4bt|OcO$a4yHa;{ zJC5dx3)jJXg1LZCm<nW$%BYl6)k@AZiiKhx zDMfX_HL0`hlYkAl?g@8kBsXmZKje{35_$KCTZyO-`YB^?v=<(Fl$Rr}JKBpjk_)*R zm|pB(7d<%Q-IFedZOb>q#wP*q_K3Ijox=G;{v;|@vs6z$Hh=Yc3uBk}4$e$WD+e>L zGVk%@nHQPfx5Gy_FFw!g7dL<3-p}lhzwF%~KfAaEo?Uo)`pVqvIr8&!WltCrempQf TeQ7Or(pOe3ub6L^?mqkjf)p^W literal 0 HcmV?d00001 diff --git a/platform/icons/src/process/fs/step_passive.png b/platform/icons/src/process/fs/step_passive.png new file mode 100644 index 0000000000000000000000000000000000000000..e1d490fdbbeb99dce18e414c703fba0934da7dea GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh*)icxGNo zet9uiy|1s8XI^nhVqS8pr;Du;&;-5A%oHnES5rqvXA?tn3uiM!Lsvs5Q)4G5V{=nu zGdE*rCj%3hUYGpj(%jU%5}4i;gkB?@dO=Acw*Y9fOKMSOS!#+~QGTuh*vnR#INf6G zhSNN#-W1$!F~F%;ALtl;P{bldG)xGXdO%EgvITPB2|qOtnA(eg$=YR>+;j#8Mj1~R z$B>F!M<(yia&i=C+pPZRuaM~t3HgKP&S|M7O>`I3shMu$s!tdBk*{)?yjIrkS$ij)!&JkGWnKc4cEr9f zyYEl>9-Yn=Feg3w`pNSK?d1~|iC7por+ju_P!vA3g{^0y@1;{YqJ^1;+<_IZzgzwG zlTlvI5}Y9`e)`dwtFoSFzdpPpvZINyGkbmG$6W6Shg)hNSm)QV@q5lbAXHbw5#w~o z`@s1w=QC;_6pIsX^@Xe6cWT*Gd2?d}k7l;;Lmi)r25E_?xgJ3ia{YRiE!WMDZD_VW zI;Nfm9Qy?C^B;b6Mw< G&;$Sm- myOriginals = new ArrayList(); private final ArrayList myInfos = new ArrayList(); @@ -78,7 +75,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge private boolean myShouldClosePopupAndOnProcessFinish; private final Alarm myRefreshAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - private AsyncProcessIcon myRefreshIcon; + private AnimatedIcon myRefreshIcon; private EmptyIcon myEmptyRefreshIcon; private String myCurrentRequestor; @@ -89,24 +86,25 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge setOpaque(false); - myRefreshIcon = new AsyncProcessIcon("Refreshing filesystem") { - protected Icon getPassiveIcon() { - return myEmptyRefreshIcon; - } - - @Override - public Dimension getPreferredSize() { - if (!isRunning()) return new Dimension(0, 0); - return super.getPreferredSize(); - } - - @Override - public void paint(Graphics g) { - g.translate(0, -1); - super.paint(g); - g.translate(0, 1); - } - }; + myRefreshIcon = new RefreshFileSystemIcon(); + // new AsyncProcessIcon("Refreshing filesystem") { + // protected Icon getPassiveIcon() { + // return myEmptyRefreshIcon; + // } + // + // @Override + // public Dimension getPreferredSize() { + // if (!isRunning()) return new Dimension(0, 0); + // return super.getPreferredSize(); + // } + // + // @Override + // public void paint(Graphics g) { + // g.translate(0, -1); + // super.paint(g); + // g.translate(0, 1); + // } + //}; myRefreshIcon.setPaintPassiveIcon(false); myEmptyRefreshIcon = new EmptyIcon(0, myRefreshIcon.getPreferredSize().height); From 777bf85b5fb45ce1ac3be32ed534be36c67b2dcf Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 28 Mar 2012 15:12:27 +0400 Subject: [PATCH 38/84] Better fix for IDEA-78716 Master password prompt is "hidden" Don't call invoke and wait in AWT, just run in that case. Introduced GuiUtils.invokeAndWaitIfNeeded for this purpose, since we don't have a fair method in utils which invokes Application#invokeAndWait. It still leads to an assertion error in Settings | GitHub, the fix for the assertion will follow in the next commit. --- .../src/com/intellij/ui/GuiUtils.java | 15 +++++++++++++++ .../masterKey/MasterKeyPasswordSafe.java | 3 ++- .../passwordSafe/ui/PasswordSafePromptDialog.java | 4 ++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/GuiUtils.java b/platform/platform-api/src/com/intellij/ui/GuiUtils.java index 6abc627f752f..68c970d04780 100644 --- a/platform/platform-api/src/com/intellij/ui/GuiUtils.java +++ b/platform/platform-api/src/com/intellij/ui/GuiUtils.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; @@ -382,4 +383,18 @@ public class GuiUtils { invokeAndWait(runnable); } } + + /** + * Runs the runnable, if called from the dispatch thread. + * Otherwise calls {@link Application#invokeAndWait(Runnable, com.intellij.openapi.application.ModalityState)} + */ + public static void invokeAndWaitIfNeeded(@NotNull Runnable runnable, @NotNull ModalityState modalityState) { + Application application = ApplicationManager.getApplication(); + if (application.isDispatchThread()) { + runnable.run(); + } + else { + application.invokeAndWait(runnable, modalityState); + } + } } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java index 82fad28a4996..c632778b2646 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java @@ -26,6 +26,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.GuiUtils; import java.io.UnsupportedEncodingException; import java.util.HashMap; @@ -182,7 +183,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } if (key.get() == null) { final Ref ex = new Ref(); - ApplicationManager.getApplication().invokeAndWait(new Runnable() { + GuiUtils.invokeAndWaitIfNeeded(new Runnable() { public void run() { if (key.get() == null) { try { diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java index 21254efc1ba6..798875c744f9 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java @@ -18,12 +18,12 @@ package com.intellij.ide.passwordSafe.ui; import com.intellij.ide.passwordSafe.PasswordSafe; import com.intellij.ide.passwordSafe.PasswordSafeException; import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; +import com.intellij.ui.GuiUtils; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -273,7 +273,7 @@ public class PasswordSafePromptDialog extends DialogWrapper { } } final AtomicReference pw = new AtomicReference(null); - ApplicationManager.getApplication().invokeAndWait(new Runnable() { + GuiUtils.invokeAndWaitIfNeeded(new Runnable() { public void run() { final PasswordSafePromptDialog d = new PasswordSafePromptDialog(project, ps, title, message); if (promptLabel != null) { From 97c80e446f49cfb3a8439f125030ee8c3d0a1661 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 28 Mar 2012 16:57:33 +0400 Subject: [PATCH 39/84] Hide GitHub credentials from the settings Ground: * It fixes AE happening because of the necessary fix for IDEA-78716. * It makes master password not appear during navigation through the settings. Remove host, login and password fields. Rename "Test" button to "Change credentials", fix layout. Pressing the button invokes the standard GithubLoginDialog with credentials filled from the GitHubSettings (possibly with master password prompt). Connection failure notification is not needed, since the dialog doesn't allow to OK on failure. Connection success notification is shown, fix the parent of the Message. --- .../github/ui/GitHubSettingsConfigurable.java | 19 +---- .../github/ui/GithubSettingsPanel.form | 69 ++----------------- .../github/ui/GithubSettingsPanel.java | 43 +++--------- 3 files changed, 18 insertions(+), 113 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java index b5dfe06f98a9..3ec134a45def 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubSettingsConfigurable.java @@ -2,8 +2,6 @@ package org.jetbrains.plugins.github.ui; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.IconLoader; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.github.GithubSettings; import org.jetbrains.plugins.github.GithubUtil; @@ -29,38 +27,27 @@ public class GitHubSettingsConfigurable implements SearchableConfigurable { return GithubUtil.GITHUB_ICON; } + @NotNull public String getHelpTopic() { return "settings.github"; } public JComponent createComponent() { if (mySettingsPane == null) { - mySettingsPane = new GithubSettingsPanel(); + mySettingsPane = new GithubSettingsPanel(mySettings); } reset(); return mySettingsPane.getPanel(); } public boolean isModified() { - return mySettingsPane != null && (!Comparing.equal(mySettings.getLogin(), mySettingsPane.getLogin()) || - !Comparing.strEqual(mySettings.getPassword(), mySettingsPane.getPassword()) || - !Comparing.equal(mySettings.getHost(), mySettingsPane.getHost())); + return false; } public void apply() throws ConfigurationException { - if (mySettingsPane != null) { - mySettings.setLogin(mySettingsPane.getLogin()); - mySettings.setPassword(mySettingsPane.getPassword()); - mySettings.setHost(mySettingsPane.getHost()); - } } public void reset() { - if (mySettingsPane != null) { - mySettingsPane.setLogin(mySettings.getLogin()); - mySettingsPane.setPassword(mySettings.getPassword()); - mySettingsPane.setHost(mySettings.getHost()); - } } public void disposeUIResources() { diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form index f828dabfa194..043dc84c7ab0 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form @@ -1,6 +1,6 @@
- + @@ -8,36 +8,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -45,55 +18,25 @@ + - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java index 29e352692067..267941384273 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java @@ -16,11 +16,11 @@ package org.jetbrains.plugins.github.ui; import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.HyperlinkAdapter; -import org.jetbrains.plugins.github.GithubUtil; +import org.jetbrains.plugins.github.GithubSettings; import javax.swing.*; import javax.swing.event.HyperlinkEvent; @@ -33,14 +33,11 @@ import java.awt.event.ActionListener; * @date 10/20/10 */ public class GithubSettingsPanel { - private JTextField myLoginTextField; - private JPasswordField myPasswordField; private JTextPane mySignupTextField; private JPanel myPane; private JButton myTestButton; - private JTextField myHostTextField; - public GithubSettingsPanel() { + public GithubSettingsPanel(final GithubSettings settings) { mySignupTextField.addHyperlinkListener(new HyperlinkAdapter() { @Override protected void hyperlinkActivated(final HyperlinkEvent e) { @@ -54,10 +51,12 @@ public class GithubSettingsPanel { myTestButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (GithubUtil.checkCredentials(ProjectManager.getInstance().getDefaultProject(), getHost(), getLogin(), getPassword())){ - Messages.showInfoMessage("Connection successful", "Success"); - } else { - Messages.showErrorDialog("Cannot login to the " + getHost() + " using given credentials", "Failure"); + Project project = ProjectManager.getInstance().getDefaultProject(); + final GithubLoginDialog dialog = new GithubLoginDialog(project); + dialog.show(); + if (dialog.isOK()){ + // the dialog won't let close after pressing OK if the connection is not successful + Messages.showInfoMessage(myPane, "Connection successful", "Success"); } } }); @@ -67,29 +66,5 @@ public class GithubSettingsPanel { return myPane; } - public void setLogin(final String login) { - myLoginTextField.setText(login); - } - - public void setPassword(final String password) { - // Show password as blank if password is empty - myPasswordField.setText(StringUtil.isEmpty(password) ? null : password); - } - - public String getLogin() { - return myLoginTextField.getText().trim(); - } - - public String getPassword() { - return String.valueOf(myPasswordField.getPassword()); - } - - public void setHost(final String host) { - myHostTextField.setText(host); - } - - public String getHost() { - return myHostTextField.getText().trim(); - } } From 525863ef9a1c0a5b57570320503b380e87788570 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 28 Mar 2012 17:02:37 +0400 Subject: [PATCH 40/84] IDEA-83622 IAE Notification content can't be null. --- plugins/git4idea/src/git4idea/Notificator.java | 2 +- .../jetbrains/plugins/github/GithubCreateGistAction.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/git4idea/src/git4idea/Notificator.java b/plugins/git4idea/src/git4idea/Notificator.java index c164ac37bfbf..b1b11f4ab7f7 100644 --- a/plugins/git4idea/src/git4idea/Notificator.java +++ b/plugins/git4idea/src/git4idea/Notificator.java @@ -67,7 +67,7 @@ public class Notificator { notify(notificationGroup, title, message, type, null); } - public void notifyError(String title, String message) { + public void notifyError(@NotNull String title, @NotNull String message) { notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, title, message, NotificationType.ERROR, null); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java index 50f1f8b6c625..83412ba7f292 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java @@ -143,7 +143,7 @@ public class GithubCreateGistAction extends DumbAwareAction { response = method.getResponseBodyAsString(); } catch (IOException e1) { - showError(project, "Failed to create gist", null, null, e1); + showError(project, "Failed to create gist", "", null, e1); return; } finally { @@ -155,7 +155,7 @@ public class GithubCreateGistAction extends DumbAwareAction { jsonResponse = new JsonParser().parse(response).getAsJsonObject(); } catch (JsonSyntaxException jse) { - showError(project, "Couldn't parse GitHub response", null, response, jse); + showError(project, "Couldn't parse GitHub response", "", response, jse); return; } @@ -188,7 +188,7 @@ public class GithubCreateGistAction extends DumbAwareAction { } } - private static void showError(@NotNull Project project, @NotNull String title, @Nullable String content, + private static void showError(@NotNull Project project, @NotNull String title, @NotNull String content, @Nullable String details, @Nullable Exception e) { Notificator.getInstance(project).notifyError(title, content); LOG.info("Couldn't parse response as json data: \n" + content + "\n" + details, e); From b68e03ec5321597ad0e0820a04c5ed44a2b534ae Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 15:57:44 +0200 Subject: [PATCH 41/84] hide iterate intention for non expression statements (IDEA-83625) --- .../daemon/impl/quickfix/IterateOverIterableIntention.java | 4 +++- .../daemonCodeAnalyzer/quickFix/iterateOver/before3.java | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java index 514d5f78efaf..74ab0409705a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/IterateOverIterableIntention.java @@ -112,7 +112,9 @@ public class IterateOverIterableIntention implements IntentionAction { element = ((PsiExpressionStatement)element).getExpression().getLastChild(); } while ((element = PsiTreeUtil.getParentOfType(element, PsiExpression.class, true)) != null) { - if (element.getParent() instanceof PsiMethodCallExpression) continue; + final PsiElement parent = element.getParent(); + if (parent instanceof PsiMethodCallExpression) continue; + if (!(parent instanceof PsiExpressionStatement)) return null; final PsiType type = ((PsiExpression)element).getType(); if (type instanceof PsiArrayType || InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE)) return (PsiExpression)element; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java new file mode 100644 index 000000000000..b9ea90a0502e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver/before3.java @@ -0,0 +1,6 @@ +// "Iterate" "false" +class Test { + void foo() { + final Annotation[] annotations = getClass().getAnnotations(); + } +} \ No newline at end of file From 67e3633d0722cd6571492d2d8457115e3da79636 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 28 Mar 2012 17:11:57 +0200 Subject: [PATCH 42/84] IDEA-83619 (Sort by Version in CVS History broken) --- .../history/CvsHistoryProvider.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java index b3bc6111df5d..9467e665d90b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/history/CvsHistoryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -207,8 +207,7 @@ public class CvsHistoryProvider implements VcsHistoryProvider { } private static VcsRevisionNumber getCurrentRevision(FilePath filePath) { - final Entry entryFor = CvsEntriesManager.getInstance().getEntryFor(filePath.getVirtualFileParent(), - filePath.getName()); + final Entry entryFor = CvsEntriesManager.getInstance().getEntryFor(filePath.getVirtualFileParent(), filePath.getName()); if (entryFor == null) { return new CvsRevisionNumber("0"); } @@ -219,13 +218,13 @@ public class CvsHistoryProvider implements VcsHistoryProvider { @Nullable public List createRevisions(final FilePath filePath) { - final ArrayList result = new ArrayList(); final File file = filePath.getIOFile(); final VirtualFile root = CvsVfsUtil.refreshAndFindFileByIoFile(file.getParentFile()); // check if we have a history pane open for a file in a package which has just been deleted if (root == null) return null; final LocalPathIndifferentLogOperation logOperation = new LocalPathIndifferentLogOperation(file); final CvsOperationExecutor executor = new CvsOperationExecutor(myProject); + final ArrayList result = new ArrayList(); executor.performActionSync(new CommandCvsHandler(CvsBundle.message("operation.name.load.file.content"), logOperation), new CvsOperationExecutorCallback() { public void executionFinished(boolean successfully) { @@ -247,6 +246,7 @@ public class CvsHistoryProvider implements VcsHistoryProvider { } } }); + Collections.sort(result, VcsFileRevisionComparator.INSTANCE); return result; } @@ -306,12 +306,19 @@ public class CvsHistoryProvider implements VcsHistoryProvider { } private static List sortRevisions(List revisionsList) { - Collections.sort(revisionsList, new Comparator() { - public int compare(VcsFileRevision rev1, VcsFileRevision rev2) { - return VcsHistoryUtil.compare(rev1, rev2); - } - }); + Collections.sort(revisionsList, VcsFileRevisionComparator.INSTANCE); return revisionsList; } } + + private static class VcsFileRevisionComparator implements Comparator { + + public static final VcsFileRevisionComparator INSTANCE = new VcsFileRevisionComparator(); + + private VcsFileRevisionComparator() {} + + public int compare(VcsFileRevision rev1, VcsFileRevision rev2) { + return VcsHistoryUtil.compare(rev2, rev1); + } + } } From c1d62dddede467fe961d7ec689238a9e773e69f5 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Wed, 28 Mar 2012 19:58:37 +0400 Subject: [PATCH 43/84] Imports --- .../src/com/intellij/android/designer/profile/ProfileList.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java index beac64cdd0e6..dce09b2fd85c 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java +++ b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java @@ -32,8 +32,6 @@ import com.intellij.openapi.roots.ModuleRootListener; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Tag; -import org.jetbrains.android.sdk.AndroidPlatform; -import org.jetbrains.android.sdk.AndroidSdkAdditionalData; import org.jetbrains.android.sdk.AndroidSdkType; import org.jetbrains.android.uipreview.LayoutDeviceManager; From 394b34496f19d507b4cf6bed0e2709a4de796bce Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Wed, 28 Mar 2012 19:58:59 +0400 Subject: [PATCH 44/84] Error handling --- .../AndroidDesignerEditorPanel.java | 64 ++++++++------- .../designSurface/DesignerEditorPanel.java | 77 ++++++++++++++++--- 2 files changed, 101 insertions(+), 40 deletions(-) diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java index c22c7b18bf16..f5d7ae50e4df 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java @@ -38,7 +38,6 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.xml.XmlFile; @@ -50,7 +49,6 @@ import org.jetbrains.android.uipreview.LocaleData; import org.jetbrains.android.uipreview.RenderUtil; import org.jetbrains.android.uipreview.RenderingException; import org.jetbrains.android.util.AndroidSdkNotConfiguredException; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -67,6 +65,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { private final ExternalPSIChangeListener myPSIChangeListener; private final ProfileAction myProfileAction; private volatile RenderSession mySession; + private boolean myParseTime; public AndroidDesignerEditorPanel(@NotNull Module module, @NotNull VirtualFile file) { super(module, file); @@ -169,26 +168,22 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { } private void reparseFile() { - try { - myToolProvider.loadDefaultTool(); - mySurfaceArea.deselectAll(); + myToolProvider.loadDefaultTool(); + mySurfaceArea.deselectAll(); - parseFile(new Runnable() { - @Override - public void run() { - showDesignerCard(); - myLayeredPane.repaint(); + parseFile(new Runnable() { + @Override + public void run() { + showDesignerCard(); + myLayeredPane.repaint(); - DesignerToolWindowManager.getInstance(getProject()).refresh(); - } - }); - } - catch (Throwable e) { - showError("Parse error: ", e); - } + DesignerToolWindowManager.getInstance(getProject()).refresh(); + } + }); } - private void parseFile(final Runnable runnable) throws Exception { + private void parseFile(final Runnable runnable) { + myParseTime = true; final ModelParser parser = new ModelParser(getProject(), myXmlFile); createRenderer(parser.getLayoutXmlText(), new ThrowableRunnable() { @Override @@ -213,12 +208,15 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { myRootComponent = newRootComponent; myLayeredPane.add(rootPanel, LAYER_COMPONENT); + myParseTime = false; + runnable.run(); } }); } private void updateRenderer() { + myParseTime = true; final String layoutXmlText = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public String compute() { @@ -238,6 +236,8 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { rootView.setImage(mySession.getImage()); ModelParser.updateRootComponent(rootComponent, mySession, rootView); + myParseTime = false; + myLayeredPane.repaint(); DesignerToolWindowManager.getInstance(getProject()).refresh(); @@ -255,7 +255,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { throw exception; } else { - throw new Exception("No session result"); + throw new RenderingException("No session result"); } } } @@ -333,23 +333,17 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { } catch (Throwable e) { showError("Parse error: ", e); + myParseTime = false; } } }); } - catch (RenderingException e) { - // TODO - e.printStackTrace(); - } - catch (AndroidSdkNotConfiguredException e) { - // TODO - e.printStackTrace(); - } catch (final Throwable e) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { showError("Render session error: ", e); + myParseTime = false; } }); } @@ -365,9 +359,21 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { } @Override - public void showError(@NonNls String message, Throwable e) { + protected void configureError(ErrorInfo info) { + if (info.throwable instanceof AndroidSdkNotConfiguredException) { + info.message = "Please configure Android SDK"; + info.stack = false; + } + else if (!(info.throwable instanceof RenderingException)) { + info.show = myParseTime; + info.log = true; + } + } + + @Override + protected void showErrorPage(ErrorInfo info) { removeNativeRoot(); - super.showError(message, e); + super.showErrorPage(info); } public ProfileAction getProfileAction() { diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java index c3ffd4db2ad0..94d5ee9aba40 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java @@ -26,6 +26,7 @@ import com.intellij.designer.palette.Item; import com.intellij.ide.palette.impl.PaletteManager; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -41,17 +42,20 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; import java.util.List; /** * @author Alexander Lobas */ public abstract class DesignerEditorPanel extends JPanel implements DataProvider { + private static final Logger LOG = Logger.getInstance("#com.intellij.designer.designSurface.DesignerEditorPanel"); + protected static final Integer LAYER_COMPONENT = JLayeredPane.DEFAULT_LAYER; protected static final Integer LAYER_STATIC_DECORATION = JLayeredPane.POPUP_LAYER; protected static final Integer LAYER_DECORATION = JLayeredPane.DRAG_LAYER; @@ -85,7 +89,9 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider protected ToolProvider myToolProvider; protected EditableArea mySurfaceArea; - private JLabel myErrorLabel; + private JPanel myErrorPanel; + private JLabel myErrorMessage; + private JTextArea myErrorStack; private JPanel myProgressPanel; private AsyncProcessIcon myProgressIcon; @@ -249,8 +255,18 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } private void createErrorCard() { - myErrorLabel = new JLabel(IconLoader.getIcon("/ide/error_notifications.png"), SwingConstants.CENTER); - add(myErrorLabel, ERROR_CARD); + myErrorPanel = new JPanel(new BorderLayout()); + + myErrorMessage = new JLabel(IconLoader.getIcon("/ide/error_notifications.png")); + myErrorMessage.setFont(myErrorMessage.getFont().deriveFont(Font.BOLD)); + myErrorPanel.add(myErrorMessage, BorderLayout.PAGE_START); + + myErrorStack = new JTextArea(50, 20); + myErrorStack.setEditable(false); + + myErrorPanel.add(ScrollPaneFactory.createScrollPane(myErrorStack), BorderLayout.CENTER); + + add(myErrorPanel, ERROR_CARD); } private void createProgressPanel() { @@ -283,16 +299,47 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider myLayeredPane.remove(myProgressPanel); } - public void showError(@NonNls String message, Throwable e) { + public final void showError(@NonNls String message, Throwable e) { + while (e instanceof InvocationTargetException) { + e = e.getCause(); + } + + ErrorInfo info = new ErrorInfo(); + info.message = message; + info.throwable = e; + configureError(info); + + if (info.show) { + showErrorPage(info); + } + if (info.log || ApplicationManagerEx.getApplicationEx().isInternal()) { + LOG.error(message, e); + } + } + + protected abstract void configureError(ErrorInfo info); + + protected void showErrorPage(ErrorInfo info) { hideProgress(); myRootComponent = null; - myErrorLabel.setText(message + e.toString()); + + myErrorMessage.setText(info.message); + + if (info.stack) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + info.throwable.printStackTrace(new PrintStream(stream)); + myErrorStack.setText(stream.toString()); + myErrorStack.setVisible(true); + } + else { + myErrorStack.setText(null); + myErrorStack.setVisible(false); + } + myLayout.show(this, ERROR_CARD); + DesignerToolWindowManager.getInstance(getProject()).refresh(); repaint(); - if (ApplicationManagerEx.getApplicationEx().isInternal()) { - e.printStackTrace(); - } } public abstract String getPlatformTarget(); @@ -359,7 +406,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } public JComponent getPreferredFocusedComponent() { - return myDesignerCard.isVisible() ? myGlassLayer : myErrorLabel; + return myDesignerCard.isVisible() ? myGlassLayer : myErrorPanel; } public RadComponent getRootComponent() { @@ -519,4 +566,12 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } } } + + public static final class ErrorInfo { + public String message; + public Throwable throwable; + public boolean show = true; + public boolean stack = true; + public boolean log; + } } \ No newline at end of file From 09246f548277730a5490aed821a8195d2ab0a8ef Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 17:23:18 +0200 Subject: [PATCH 45/84] process captured wildcards (IDEA-82913) --- .../intellij/psi/util/TypeConversionUtil.java | 4 +-- .../CapturedWildcardAssignments.java | 27 +++++++++++++++++++ .../daemon/GenericsHighlightingTest.java | 1 + 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 2abb12f5f1c4..7aea5e6cdcdd 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -656,10 +656,10 @@ public class TypeConversionUtil { } if (left instanceof PsiCapturedWildcardType) { - return left.equals(right) || isAssignable(((PsiCapturedWildcardType)left).getLowerBound(), right, allowUncheckedConversion); + return left.equals(right) || isAssignable(((PsiCapturedWildcardType)left).getLowerBound(), right, false); } if (right instanceof PsiCapturedWildcardType) { - return isAssignable(left, ((PsiCapturedWildcardType)right).getUpperBound(), allowUncheckedConversion); + return isAssignable(left, ((PsiCapturedWildcardType)right).getUpperBound(), false); } if (left instanceof PsiWildcardType) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java new file mode 100644 index 000000000000..f105923eb1b1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CapturedWildcardAssignments.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2012 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. + */ + +import java.util.Iterator; + +public class Test { + public static void bar() { + Class> c = foo(); + } + + public static Class foo() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index c8ed0105e79a..af5988b5798e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -106,6 +106,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testInnerClassRef() throws Exception { doTest(false); } public void testPrivateInnerClassRef() throws Exception { doTest(false); } public void testWideningCastToTypeParam() throws Exception { doTest(false); } + public void testCapturedWildcardAssignments() throws Exception { doTest(false);} public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); From 7dec69fd9710f33f2ba193c68b0a9869f0f5657d Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 28 Mar 2012 15:51:35 +0200 Subject: [PATCH 46/84] more freedom for gc in gdsl processing --- .../dsl/holders/NonCodeMembersHolder.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java index d010e1b33a83..d114a69b3100 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java @@ -19,11 +19,10 @@ import com.google.common.collect.Maps; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.util.containers.ConcurrentFactoryMap; +import com.intellij.util.containers.ConcurrentSoftHashMap; import org.jetbrains.plugins.groovy.dsl.CustomMembersGenerator; import org.jetbrains.plugins.groovy.dsl.GroovyClassDescriptor; import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor; @@ -41,23 +40,24 @@ public class NonCodeMembersHolder implements CustomMembersHolder { public static final Key DOCUMENTATION = Key.create("GdslDocumentation"); public static final Key DOCUMENTATION_URL = Key.create("GdslDocumentationUrl"); private final List myMethods = new ArrayList(); - private static final Key, NonCodeMembersHolder>>> CACHED_HOLDERS = Key.create("CACHED_HOLDERS"); public static NonCodeMembersHolder generateMembers(Set methods, final PsiFile place) { - return CachedValuesManager.getManager(place.getProject()).getCachedValue(place, CACHED_HOLDERS, new CachedValueProvider, NonCodeMembersHolder>>() { - public Result, NonCodeMembersHolder>> compute() { - final ConcurrentFactoryMap, NonCodeMembersHolder> map = new ConcurrentFactoryMap, NonCodeMembersHolder>() { - @Override - protected NonCodeMembersHolder create(Set key) { - return new NonCodeMembersHolder(key, place); - } - }; + Map, NonCodeMembersHolder> map = CachedValuesManager.getManager(place.getProject()).getCachedValue( + place, new CachedValueProvider, NonCodeMembersHolder>>() { + public Result, NonCodeMembersHolder>> compute() { + final Map, NonCodeMembersHolder> map = new ConcurrentSoftHashMap, NonCodeMembersHolder>(); return Result.create(map, PsiModificationTracker.MODIFICATION_COUNT); } - }, false).get(methods); + }); + + NonCodeMembersHolder result = map.get(methods); + if (result == null) { + map.put(methods, result = new NonCodeMembersHolder(methods, place)); + } + return result; } - public NonCodeMembersHolder(Set data, PsiElement place) { + private NonCodeMembersHolder(Set data, PsiElement place) { final PsiManager manager = place.getManager(); for (Map prop : data) { String name = String.valueOf(prop.get("name")); From 197b9ae6524ea8fdc42c48442463c13551b78702 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 28 Mar 2012 17:33:32 +0200 Subject: [PATCH 47/84] IDEA-83641 Don't autopopup with word completion variants in XML --- plugins/devkit/devkit.iml | 1 + .../codeInsight/PluginXmlAutoPopupTest.groovy | 51 +++++++++++++++++++ .../completion/XmlCompletionContributor.java | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy diff --git a/plugins/devkit/devkit.iml b/plugins/devkit/devkit.iml index 47d21923aa17..f2f207869c5a 100644 --- a/plugins/devkit/devkit.iml +++ b/plugins/devkit/devkit.iml @@ -26,6 +26,7 @@ + diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy b/plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy new file mode 100644 index 000000000000..46a5a8367298 --- /dev/null +++ b/plugins/devkit/testSources/codeInsight/PluginXmlAutoPopupTest.groovy @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.devkit.codeInsight + +import com.intellij.codeInsight.completion.CompletionAutoPopupTestCase + +/** + * @author peter + */ +class PluginXmlAutoPopupTest extends CompletionAutoPopupTestCase { + + public void "test autopopup for class references"() { + myFixture.addClass("public class FooFooFooFooFoo { }"); + myFixture.configureByText 'plugin.xml', ''' + + + + + +''' + type 'o' + assert lookup + assert myFixture.lookupElementStrings == ['FooFooFooFooFoo'] + } + + public void "test no autopopup when only word completion is available"() { + myFixture.configureByText 'plugin.xml', ''' + + + + + +''' + type 'e' + assert !lookup + } + +} diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java index d293ff34118e..8cd06b130a29 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java @@ -108,7 +108,7 @@ public class XmlCompletionContributor extends CompletionContributor { addWordVariants.set(attributeValue.getReferences().length == 0); } - if (addWordVariants.get().booleanValue()) { + if (addWordVariants.get().booleanValue() && parameters.getInvocationCount() > 0) { WordCompletionContributor.addWordCompletionVariants(result, parameters, usedWords); } } From 268416fd8d43b45850342d6f46a9d9e576eeb928 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 28 Mar 2012 21:05:21 +0400 Subject: [PATCH 48/84] Spinning icon & NPE fixes --- .../artifactory/ArtifactoryRepositoryService.java | 12 ++++++++++-- .../maven/services/nexus/NexusRepositoryService.java | 10 +++++++++- .../idea/maven/utils/RepositoryAttachDialog.java | 6 +++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java index 0b4afdef44d3..7a62e53e9ef9 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/artifactory/ArtifactoryRepositoryService.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.maven.services.artifactory; import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenArtifactInfo; @@ -27,6 +28,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -53,6 +55,9 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { } return result; } + catch (JsonSyntaxException e) { + return Collections.emptyList(); + } catch (Exception e) { throw new IOException(e); } @@ -74,7 +79,7 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { final String name = StringUtil.join(Arrays.asList(template.getGroupId(), template.getArtifactId(), template.getVersion()), ":"); final InputStream stream = new Endpoint.Search.Artifact(url).getArtifactSearchResultJson(name, null).getInputStream(); - final ArtifactoryModel.GavcResults results = gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.GavcResults.class); + final ArtifactoryModel.GavcResults results = stream == null? null : gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.GavcResults.class); if (results != null && results.results != null) { for (ArtifactoryModel.GavcResult result : results.results) { if (!result.uri.endsWith(packaging)) continue; @@ -87,7 +92,7 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { final String searchString = className.endsWith("*") || className.endsWith("?") ? className : className + ".class"; final InputStream stream = new Endpoint.Search.Archive(url).getArchiveSearchResultJson(searchString, null).getInputStream(); - final ArtifactoryModel.ArchiveResults results = gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.ArchiveResults.class); + final ArtifactoryModel.ArchiveResults results = stream == null? null : gson.fromJson(new InputStreamReader(stream), ArtifactoryModel.ArchiveResults.class); if (results != null && results.results != null) { for (ArtifactoryModel.ArchiveResult result : results.results) { for (String uri : result.archiveUris) { @@ -99,6 +104,9 @@ public class ArtifactoryRepositoryService extends MavenRepositoryService { } return artifacts; } + catch (JsonSyntaxException e) { + return Collections.emptyList(); + } catch (Exception e) { throw new IOException(e); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java index f038a3d21b14..8698108f9b04 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/nexus/NexusRepositoryService.java @@ -23,9 +23,11 @@ import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import org.jetbrains.idea.maven.services.MavenRepositoryService; import javax.xml.bind.JAXBException; +import javax.xml.bind.UnmarshalException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -64,6 +66,9 @@ public class NexusRepositoryService extends MavenRepositoryService { } return result; } + catch (UnmarshalException e) { + return Collections.emptyList(); + } catch (JAXBException e) { throw new IOException(e); } @@ -74,12 +79,12 @@ public class NexusRepositoryService extends MavenRepositoryService { public List findArtifacts(@NotNull String url, @NotNull MavenArtifactInfo template) throws IOException { try { final String packaging = StringUtil.notNullize(template.getPackaging()); - final ArrayList result = new ArrayList(); final String name = StringUtil.join(Arrays.asList(template.getGroupId(), template.getArtifactId(), template.getVersion()), ":"); final SearchResults results = new Endpoint.DataIndex(url).getArtifactlistAsSearchResults( name, template.getGroupId(), template.getArtifactId(), template.getVersion(), null, template.getClassNames()); boolean tooManyResults = results.isTooManyResults(); final SearchResults.Data data = results.getData(); + final ArrayList result = new ArrayList(); if (data != null) { for (ArtifactType each : data.getArtifact()) { if (!Comparing.equal(each.packaging, packaging)) continue; @@ -89,6 +94,9 @@ public class NexusRepositoryService extends MavenRepositoryService { if (tooManyResults) result.add(null); return result; } + catch (UnmarshalException e) { + return Collections.emptyList(); + } catch (JAXBException e) { throw new IOException(e); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java index 0d1a24f7af83..7776c490de18 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java @@ -76,6 +76,7 @@ public class RepositoryAttachDialog extends DialogWrapper { private TextFieldWithBrowseButton myDirectoryField; private String myFilterString; + private boolean myInUpdate; public RepositoryAttachDialog(Project project, boolean managed, final @Nullable String initialFilter) { super(project, true); @@ -117,7 +118,7 @@ public class RepositoryAttachDialog extends DialogWrapper { @Override public void actionPerformed(ActionEvent e) { final boolean popupVisible = myCombobox.isPopupVisible(); - if (!popupVisible || myCoordinates.isEmpty()) { + if (!myInUpdate && (!popupVisible || myCoordinates.isEmpty())) { performSearch(); } else { @@ -181,6 +182,8 @@ public class RepositoryAttachDialog extends DialogWrapper { if (!force && Comparing.equal(myFilterString, prevFilter)) return; int prevSize = myShownItems.size(); myShownItems.clear(); + + myInUpdate = true; final boolean itemSelected = myCoordinates.containsKey(myFilterString) && Comparing.strEqual((String)myCombobox.getSelectedItem(), myFilterString, false); final boolean filtered; @@ -205,6 +208,7 @@ public class RepositoryAttachDialog extends DialogWrapper { } Collections.sort(myShownItems); ((CollectionComboBoxModel)myCombobox.getModel()).update(); + myInUpdate = false; field.setText(myFilterString); field.setCaretPosition(caret); updateInfoLabel(); From 3cab25379ed4ca9289721affbd1d7abb32b15933 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Wed, 28 Mar 2012 21:43:45 +0400 Subject: [PATCH 49/84] Android layouts --- .../android/designer/model/ModelParser.java | 5 ++++- .../android/designer/model/PropertyParser.java | 6 ++++-- .../designer/model/RadScrollViewComponent.java | 2 ++ .../android/designer/model/RadViewLayout.java | 4 +++- .../android/designer/model/views-meta-model.xml | 16 ---------------- ...addingProperty.java => CompoundProperty.java} | 6 +++--- 6 files changed, 16 insertions(+), 23 deletions(-) rename plugins/android-designer/src/com/intellij/android/designer/propertyTable/{PaddingProperty.java => CompoundProperty.java} (86%) diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java index 0de4c1179468..999c82c33e6a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java @@ -114,7 +114,10 @@ public class ModelParser extends XmlRecursiveElementVisitor { component.setTag(tag); Class layout = metaModel.getLayout(); - if (layout != null) { + if (layout == null) { + component.setLayout(RadViewLayout.INSTANCE); + } + else { component.setLayout(layout.newInstance()); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java index 62c155ea5646..707d353226c5 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java @@ -19,8 +19,8 @@ import com.android.ide.common.rendering.api.ViewInfo; import com.android.resources.ResourceType; import com.android.sdklib.IAndroidTarget; import com.intellij.android.designer.propertyTable.AttributeProperty; +import com.intellij.android.designer.propertyTable.CompoundProperty; import com.intellij.android.designer.propertyTable.FlagProperty; -import com.intellij.android.designer.propertyTable.PaddingProperty; import com.intellij.android.designer.propertyTable.editors.ResourceDialog; import com.intellij.designer.model.MetaManager; import com.intellij.designer.model.MetaModel; @@ -96,6 +96,8 @@ public class PropertyParser { else { component.setProperties(load(myClassLoader.loadClass(target), model)); } + + // TODO: load layout constrain properties } private List load(Class componentClass, MetaModel model) throws Exception { @@ -116,7 +118,7 @@ public class PropertyParser { Property property; if ("padding".equals(name) && "View".equals(component)) { - property = padding = new PaddingProperty(name, definition); + property = padding = new CompoundProperty(name, definition); } else if (formats.contains(AttributeFormat.Flag)) { property = new FlagProperty(name, definition); diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java index 163178a83053..c18661f35f0d 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadScrollViewComponent.java @@ -68,6 +68,8 @@ public class RadScrollViewComponent extends RadViewComponent { scrollContainer.getTag().setName(scrollContainer.getMetaModel().getTag()); } }); + + // TODO: maybe reload properties } }); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java index 97ff2f279b70..f26a67c7bf49 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayout.java @@ -27,7 +27,9 @@ import java.util.List; * @author Alexander Lobas */ public class RadViewLayout extends RadLayout { - @Override + public static final RadLayout INSTANCE = new RadViewLayout(); + + @Override public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { return new NonResizeSelectionDecorator(Color.RED, 1); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml index 85f7bcaeebab..0d9f8e077767 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml +++ b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml @@ -13,7 +13,6 @@ @@ -21,7 +20,6 @@ @@ -567,7 +565,6 @@ @@ -587,7 +584,6 @@ @@ -608,7 +604,6 @@ @@ -629,7 +624,6 @@ @@ -647,7 +641,6 @@ @@ -665,7 +658,6 @@ @@ -689,7 +681,6 @@ @@ -728,7 +719,6 @@ @@ -748,7 +738,6 @@ @@ -806,7 +795,6 @@ @@ -826,7 +814,6 @@ @@ -846,7 +833,6 @@ @@ -864,7 +850,6 @@ @@ -884,7 +869,6 @@ diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/PaddingProperty.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/CompoundProperty.java similarity index 86% rename from plugins/android-designer/src/com/intellij/android/designer/propertyTable/PaddingProperty.java rename to plugins/android-designer/src/com/intellij/android/designer/propertyTable/CompoundProperty.java index 9981f7ceb9c4..5a0b3f4936e0 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/PaddingProperty.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/CompoundProperty.java @@ -27,10 +27,10 @@ import java.util.List; /** * @author Alexander Lobas */ -public class PaddingProperty extends AttributeProperty { +public class CompoundProperty extends AttributeProperty { private List myChildren = new ArrayList(); - public PaddingProperty(@NotNull String name, @NotNull AttributeDefinition definition) { + public CompoundProperty(@NotNull String name, @NotNull AttributeDefinition definition) { super(name, definition); } @@ -41,7 +41,7 @@ public class PaddingProperty extends AttributeProperty { @Override public Property createForNewPresentation() { - PaddingProperty property = new PaddingProperty(getName(), myDefinition); + CompoundProperty property = new CompoundProperty(getName(), myDefinition); List children = property.getChildren(null); for (Property childProperty : myChildren) { children.add(childProperty.createForNewPresentation()); From 915bb96ff9a96523dd0e9aaf8eca63af57c373e5 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 28 Mar 2012 21:20:39 +0200 Subject: [PATCH 50/84] get rid of PseudoClassLoader; InstrumentationClassFinder used instead. Also InstrumenterClassWriter using this finder is available as utility for all ASM-based instrumentation tasks --- .idea/modules.xml | 1 + build/scripts/layouts.gant | 4 +- community-main.iml | 2 +- .../forms-compiler/forms-compiler.iml | 1 + .../uiDesigner/compiler/AsmCodeGenerator.java | 152 +++-- .../compiler/FontPropertyCodeGenerator.java | 3 +- .../compiler/PropertyCodeGenerator.java | 9 +- .../compiler/StringPropertyCodeGenerator.java | 28 +- .../intellij/uiDesigner/compiler/Utils.java | 545 +++++++++--------- java/compiler/impl/compiler-impl.iml | 2 +- .../instrumentation-util.iml} | 0 .../InstrumentationClassFinder.java | 231 ++++++-- .../InstrumenterClassWriter.java | 43 ++ .../NotNullVerifyingInstrumenter.java | 0 java/compiler/javac2/javac2.iml | 2 +- .../src/com/intellij/ant/AntClassWriter.java | 54 -- .../com/intellij/ant/InstrumentationUtil.java | 32 +- .../javac2/src/com/intellij/ant/Javac2.java | 52 +- .../com/intellij/ant/PseudoClassLoader.java | 275 --------- java/java-tests/java-tests.iml | 2 +- jps/jps-builders/jps-builders.iml | 2 +- .../jps/incremental/java/JavaBuilder.java | 105 +--- jps/jps.iml | 1 + .../org/jetbrains/jps/ModuleBuildState.groovy | 4 +- .../jps/builders/StandardBuilders.groovy | 16 +- .../javacApi/Java16ApiCompiler.groovy | 23 +- .../javacApi/OptimizedFileManager.java | 26 +- .../uiDesigner/actions/PreviewFormAction.java | 195 ++++--- .../make/Form2ByteCodeCompiler.java | 149 ++--- .../make/PreviewNestedFormLoader.java | 9 +- .../uiDesigner/core/AsmCodeGeneratorTest.java | 132 ++++- 31 files changed, 1040 insertions(+), 1060 deletions(-) rename java/compiler/{notNull/notNull.iml => instrumentation-util/instrumentation-util.iml} (100%) rename {jps/jps-builders/src/org/jetbrains/jps/incremental/java => java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation}/InstrumentationClassFinder.java (71%) create mode 100644 java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java rename java/compiler/{notNull => instrumentation-util}/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java (100%) delete mode 100644 java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java delete mode 100644 java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java diff --git a/.idea/modules.xml b/.idea/modules.xml index e6de17c97dfd..18bb3a5c3d05 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -51,6 +51,7 @@ + diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index e78e38697911..6381e2e9eab8 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -77,7 +77,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir //noinspection GroovyAssignabilityCheck List implementationModules = [platformImplementationModules(), - "notNull", + "instrumentation-util", "platform-main", "java-psi-impl", "java-impl", @@ -170,7 +170,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir module("javac2") module("forms-compiler") module("forms_rt") - module("notNull") + module("instrumentation-util") } jar("jps-server.jar") { diff --git a/community-main.iml b/community-main.iml index a52ba14d3c83..0dbcfb09ce10 100644 --- a/community-main.iml +++ b/community-main.iml @@ -31,7 +31,7 @@ - + diff --git a/java/compiler/forms-compiler/forms-compiler.iml b/java/compiler/forms-compiler/forms-compiler.iml index ce591cf3173e..39ba1446f119 100644 --- a/java/compiler/forms-compiler/forms-compiler.iml +++ b/java/compiler/forms-compiler/forms-compiler.iml @@ -13,6 +13,7 @@ + diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java index b7a344dcf74e..b838594d8f6f 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java @@ -15,6 +15,7 @@ */ package com.intellij.uiDesigner.compiler; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.uiDesigner.UIFormXmlConstants; import com.intellij.uiDesigner.lw.*; import com.intellij.uiDesigner.shared.BorderType; @@ -28,7 +29,6 @@ import javax.swing.*; import javax.swing.border.Border; import java.awt.*; import java.io.*; -import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; @@ -40,7 +40,7 @@ import java.util.Map; */ public class AsmCodeGenerator { private final LwRootContainer myRootContainer; - private final ClassLoader myLoader; + private final InstrumentationClassFinder myFinder; private final ArrayList myErrors; private final ArrayList myWarnings; @@ -96,20 +96,20 @@ public class AsmCodeGenerator { } public AsmCodeGenerator(LwRootContainer rootContainer, - ClassLoader loader, + InstrumentationClassFinder finder, NestedFormLoader formLoader, final boolean ignoreCustomCreation, final ClassWriter classWriter) { myFormLoader = formLoader; myIgnoreCustomCreation = ignoreCustomCreation; - if (loader == null){ + if (finder == null){ throw new IllegalArgumentException("loader cannot be null"); } if (rootContainer == null){ throw new IllegalArgumentException("rootContainer cannot be null"); } myRootContainer = rootContainer; - myLoader = loader; + myFinder = finder; myErrors = new ArrayList(); myWarnings = new ArrayList(); @@ -210,9 +210,9 @@ public class AsmCodeGenerator { codeGen.generatePushValue(generator, value); } - static Class getComponentClass(String className, final ClassLoader classLoader) throws CodeGenerationException { + static InstrumentationClassFinder.PseudoClass getComponentClass(String className, final InstrumentationClassFinder finder) throws CodeGenerationException { try { - return Class.forName(className, false, classLoader); + return finder.loadClass(className); } catch (ClassNotFoundException e) { throw new CodeGenerationException(null, "Class not found: " + className); @@ -220,6 +220,9 @@ public class AsmCodeGenerator { catch(UnsupportedClassVersionError e) { throw new CodeGenerationException(null, "Unsupported class version error: " + className); } + catch (IOException e) { + throw new CodeGenerationException(null, e.getMessage(), e); + } } public static Type typeFromClassName(final String className) { @@ -252,7 +255,7 @@ public class AsmCodeGenerator { for (Iterator iterator = myPropertyCodeGenerators.values().iterator(); iterator.hasNext();) { PropertyCodeGenerator propertyCodeGenerator = (PropertyCodeGenerator)iterator.next(); - propertyCodeGenerator.generateClassStart(this, name, myLoader); + propertyCodeGenerator.generateClassStart(this, name, myFinder); } } @@ -394,28 +397,30 @@ public class AsmCodeGenerator { myIdToLocalMap.put(lwComponent.getId(), new Integer(componentLocal)); - Class componentClass = getComponentClass(className, myLoader); + InstrumentationClassFinder.PseudoClass componentClass = getComponentClass(className, myFinder); validateFieldBinding(lwComponent, componentClass); if (myIgnoreCustomCreation) { - boolean creatable = true; - if ((componentClass.getModifiers() & (Modifier.PRIVATE | Modifier.ABSTRACT)) != 0) { - creatable = false; - } - else { - try { - final Constructor constructor = componentClass.getConstructor(new Class[0]); - if ((constructor.getModifiers() & Modifier.PUBLIC) == 0) { + try { + boolean creatable = true; + if ((componentClass.getModifiers() & (Modifier.PRIVATE | Modifier.ABSTRACT)) != 0) { + creatable = false; + } + else { + if (!componentClass.hasDefaultPublicConstructor()) { creatable = false; } } - catch(NoSuchMethodException ex) { - creatable = false; + if (!creatable) { + componentClass = Utils.suggestReplacementClass(componentClass); + componentType = Type.getType(componentClass.getDescriptor()); } } - if (!creatable) { - componentClass = Utils.suggestReplacementClass(componentClass); - componentType = Type.getType(componentClass); + catch (ClassNotFoundException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); + } + catch (IOException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); } } @@ -468,12 +473,11 @@ public class AsmCodeGenerator { } } - private int getNestedFormComponent(GeneratorAdapter generator, Class componentClass, int formLocal) throws CodeGenerationException { + private int getNestedFormComponent(GeneratorAdapter generator, InstrumentationClassFinder.PseudoClass componentClass, int formLocal) throws CodeGenerationException { final Type componentType = Type.getType(JComponent.class); int componentLocal = generator.newLocal(componentType); generator.loadLocal(formLocal); - generator.invokeVirtual(Type.getType(componentClass), - new Method(GET_ROOT_COMPONENT_METHOD_NAME, componentType, new Type[0])); + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method(GET_ROOT_COMPONENT_METHOD_NAME, componentType, new Type[0])); generator.storeLocal(componentLocal); return componentLocal; } @@ -502,7 +506,7 @@ public class AsmCodeGenerator { } private void generateComponentProperties(final LwComponent lwComponent, - final Class componentClass, + final InstrumentationClassFinder.PseudoClass componentClass, final GeneratorAdapter generator, final int componentLocal) throws CodeGenerationException { // introspected properties @@ -543,7 +547,12 @@ public class AsmCodeGenerator { else { setterClass = Class.forName(propertyClass); } - componentClass.getMethod(property.getWriteMethodName(), new Class[] { setterClass } ); + //componentClass.getMethod(property.getWriteMethodName(), new Class[] { setterClass } ); + final String descriptor = "(L"+setterClass.getName().replace('.', '/') + ";)V"; + final InstrumentationClassFinder.PseudoMethod setter = componentClass.findMethod(property.getWriteMethodName(), descriptor); + if (setter == null) { + continue; + } } catch (Exception e) { continue; @@ -551,9 +560,16 @@ public class AsmCodeGenerator { } final PropertyCodeGenerator propGen = (PropertyCodeGenerator) myPropertyCodeGenerators.get(propertyClass); - if (propGen != null && propGen.generateCustomSetValue(lwComponent, componentClass, property, - generator, componentLocal, myClassName)) { - continue; + try { + if (propGen != null && propGen.generateCustomSetValue(lwComponent, componentClass, property, generator, componentLocal, myClassName)) { + continue; + } + } + catch (IOException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); + } + catch (ClassNotFoundException e) { + throw new CodeGenerationException(lwComponent.getId(), e.getMessage(), e); } generator.loadLocal(componentLocal); @@ -602,7 +618,7 @@ public class AsmCodeGenerator { Type declaringType = (property.getDeclaringClassName() != null) ? typeFromClassName(property.getDeclaringClassName()) - : Type.getType(componentClass); + : Type.getType(componentClass.getDescriptor()); generator.invokeVirtual(declaringType, new Method(property.getWriteMethodName(), Type.VOID_TYPE, new Type[] { setterArgType } )); } @@ -611,7 +627,7 @@ public class AsmCodeGenerator { } private void generateClientProperties(final LwComponent lwComponent, - final Class componentClass, + final InstrumentationClassFinder.PseudoClass componentClass, final GeneratorAdapter generator, final int componentLocal) throws CodeGenerationException { HashMap props = lwComponent.getDelegeeClientProperties(); @@ -652,7 +668,7 @@ public class AsmCodeGenerator { } } - Type componentType = Type.getType(componentClass); + Type componentType = Type.getType(componentClass.getDescriptor()); Type objectType = Type.getType(Object.class); generator.invokeVirtual(componentType, new Method("putClientProperty", Type.VOID_TYPE, new Type[] { objectType, objectType } )); @@ -664,7 +680,7 @@ public class AsmCodeGenerator { if (component instanceof LwNestedForm) return; int componentLocal = ((Integer) myIdToLocalMap.get(component.getId())).intValue(); final LayoutCodeGenerator layoutCodeGenerator = getComponentCodeGenerator(component.getParent()); - Class componentClass = getComponentClass(layoutCodeGenerator.mapComponentClass(component.getComponentClassName()), myLoader); + InstrumentationClassFinder.PseudoClass componentClass = getComponentClass(layoutCodeGenerator.mapComponentClass(component.getComponentClassName()), myFinder); final LwIntrospectedProperty[] introspectedProperties = component.getAssignedIntrospectedProperties(); for (int i = 0; i < introspectedProperties.length; i++) { @@ -681,7 +697,7 @@ public class AsmCodeGenerator { generator.loadLocal(targetLocal); Type declaringType = (property.getDeclaringClassName() != null) ? typeFromClassName(property.getDeclaringClassName()) - : Type.getType(componentClass); + : Type.getType(componentClass.getDescriptor()); generator.invokeVirtual(declaringType, new Method(property.getWriteMethodName(), Type.VOID_TYPE, new Type[] { typeFromClassName(property.getPropertyClassName()) } )); @@ -702,33 +718,45 @@ public class AsmCodeGenerator { private void generateButtonGroups(final LwRootContainer rootContainer, final GeneratorAdapter generator) throws CodeGenerationException { IButtonGroup[] groups = rootContainer.getButtonGroups(); if (groups.length > 0) { - int groupLocal = generator.newLocal(ourButtonGroupType); - for(int groupIndex=0; groupIndex 0) { - generator.newInstance(ourButtonGroupType); - generator.dup(); - generator.invokeConstructor(ourButtonGroupType, Method.getMethod("void ()")); - generator.storeLocal(groupLocal); + if (ids.length > 0) { + generator.newInstance(ourButtonGroupType); + generator.dup(); + generator.invokeConstructor(ourButtonGroupType, Method.getMethod("void ()")); + generator.storeLocal(groupLocal); - if (groups [groupIndex].isBound() && !myIgnoreCustomCreation) { - validateFieldClass(groups [groupIndex].getName(), ButtonGroup.class, null); - generator.loadThis(); - generator.loadLocal(groupLocal); - generator.putField(getMainClassType(), groups [groupIndex].getName(), ourButtonGroupType); - } - - for(int i = 0; i= 0) { generator.loadLocal(componentLocal); generator.push(textWithMnemonic.myText); - generator.invokeVirtual(Type.getType(componentClass), + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method(property.getWriteMethodName(), Type.VOID_TYPE, new Type[] { Type.getType(String.class) } )); String setMnemonicMethodName; - if (AbstractButton.class.isAssignableFrom(componentClass)) { + if (abstractButtonClass.isAssignableFrom(componentClass)) { setMnemonicMethodName = "setMnemonic"; } else { @@ -89,14 +93,14 @@ public class StringPropertyCodeGenerator extends PropertyCodeGenerator implement generator.loadLocal(componentLocal); generator.push(textWithMnemonic.getMnemonicChar()); - generator.invokeVirtual(Type.getType(componentClass), + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method(setMnemonicMethodName, Type.VOID_TYPE, new Type[] { Type.CHAR_TYPE } )); if (myHaveSetDisplayedMnemonicIndex) { generator.loadLocal(componentLocal); generator.push(textWithMnemonic.myMnemonicIndex); - generator.invokeVirtual(Type.getType(componentClass), + generator.invokeVirtual(Type.getType(componentClass.getDescriptor()), new Method("setDisplayedMnemonicIndex", Type.VOID_TYPE, new Type[] { Type.INT_TYPE } )); } @@ -105,7 +109,7 @@ public class StringPropertyCodeGenerator extends PropertyCodeGenerator implement } else { Method method; - if (AbstractButton.class.isAssignableFrom(componentClass)) { + if (abstractButtonClass.isAssignableFrom(componentClass)) { myClassesRequiringLoadButtonText.add(formClassName); method = myLoadButtonTextMethod; } diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java index 4b28e2d04628..79fb947cacb5 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java @@ -15,6 +15,7 @@ */ package com.intellij.uiDesigner.compiler; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.lw.*; import org.jdom.Document; @@ -28,6 +29,7 @@ import javax.swing.*; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.awt.*; +import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.lang.reflect.Constructor; @@ -43,306 +45,323 @@ import java.util.Set; * NOTE: the class must be compilable with JDK 1.3, so any methods and filds introduced in 1.4 or later must not be used */ public final class Utils { - public static final String FORM_NAMESPACE = "http://www.intellij.com/uidesigner/form/"; - private static final SAXParser SAX_PARSER = createParser(); + public static final String FORM_NAMESPACE = "http://www.intellij.com/uidesigner/form/"; + private static final SAXParser SAX_PARSER = createParser(); - private Utils() { + private Utils() { + } + + private static SAXParser createParser() { + try { + return SAXParserFactory.newInstance().newSAXParser(); + } + catch (Exception e) { + return null; + } + } + + /** + * @param provider if null, no classes loaded and no properties read + */ + public static LwRootContainer getRootContainer(final String formFileContent, final PropertiesProvider provider) throws Exception { + if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { + throw new AlienFormFileException(); } - private static SAXParser createParser() { - try { - return SAXParserFactory.newInstance().newSAXParser(); - } - catch (Exception e) { - return null; + final Document document = new SAXBuilder().build(new StringReader(formFileContent), "UTF-8"); + + return getRootContainerFromDocument(document, provider); + } + + /** + * Get root from the url + * + * @param formFile the document URL + * @param provider the provider + * @return the root container + * @throws Exception if there is a problem with parsing DOM + */ + public static LwRootContainer getRootContainer(final URL formFile, final PropertiesProvider provider) throws Exception { + final Document document = new SAXBuilder().build(formFile); + return getRootContainerFromDocument(document, provider); + } + + + /** + * Get root from the document + * + * @param document the parsed document + * @param provider the provider + * @return the root container + * @throws Exception if there is a problem with parsing DOM + */ + private static LwRootContainer getRootContainerFromDocument(Document document, PropertiesProvider provider) throws Exception { + final LwRootContainer root = new LwRootContainer(); + root.read(document.getRootElement(), provider); + return root; + } + + public static LwRootContainer getRootContainer(final InputStream stream, final PropertiesProvider provider) throws Exception { + final Document document = new SAXBuilder().build(stream, "UTF-8"); + + return getRootContainerFromDocument(document, provider); + } + + public synchronized static String getBoundClassName(final String formFileContent) throws Exception { + if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { + throw new AlienFormFileException(); + } + + final String[] className = new String[]{null}; + try { + SAX_PARSER.parse(new InputSource(new StringReader(formFileContent)), new DefaultHandler() { + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if ("form".equals(qName)) { + className[0] = attributes.getValue("", "bind-to-class"); + throw new SAXException("stop parsing"); + } } + }); + } + catch (Exception e) { + // Do nothing. } - /** - * @param provider if null, no classes loaded and no properties read - */ - public static LwRootContainer getRootContainer(final String formFileContent, final PropertiesProvider provider) throws Exception { - if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { - throw new AlienFormFileException(); - } + return className[0]; + } - final Document document = new SAXBuilder().build(new StringReader(formFileContent), "UTF-8"); - - return getRootContainerFromDocument(document, provider); - } - - /** - * Get root from the url - * - * @param formFile the document URL - * @param provider the provider - * @return the root container - * @throws Exception if there is a problem with parsing DOM - */ - public static LwRootContainer getRootContainer(final URL formFile, final PropertiesProvider provider) throws Exception { - final Document document = new SAXBuilder().build(formFile); - return getRootContainerFromDocument(document, provider); - } - - - /** - * Get root from the document - * - * @param document the parsed document - * @param provider the provider - * @return the root container - * @throws Exception if there is a problem with parsing DOM - */ - private static LwRootContainer getRootContainerFromDocument(Document document, PropertiesProvider provider) throws Exception { - final LwRootContainer root = new LwRootContainer(); - root.read(document.getRootElement(), provider); - return root; - } - - public static LwRootContainer getRootContainer(final InputStream stream, final PropertiesProvider provider) throws Exception { - final Document document = new SAXBuilder().build(stream, "UTF-8"); - - return getRootContainerFromDocument(document, provider); - } - - public synchronized static String getBoundClassName(final String formFileContent) throws Exception { - if (formFileContent.indexOf(FORM_NAMESPACE) == -1) { - throw new AlienFormFileException(); - } - - final String[] className = new String[]{null}; - try { - SAX_PARSER.parse(new InputSource(new StringReader(formFileContent)), new DefaultHandler() { - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - if ("form".equals(qName)) { - className[0] = attributes.getValue("", "bind-to-class"); - throw new SAXException("stop parsing"); - } - } - }); - } - catch (Exception e) { - // Do nothing. - } - - return className[0]; - } - - /** - * Validates that specified class represents {@link javax.swing.JComponent} with - * empty constructor. - * - * @return descriptive human readable error message or null if - * no errors were detected. - */ + /** + * Validates that specified class represents {@link javax.swing.JComponent} with + * empty constructor. + * + * @return descriptive human readable error message or null if + * no errors were detected. + */ public static String validateJComponentClass(final ClassLoader loader, final String className, final boolean validateConstructor) { if (loader == null) { - throw new IllegalArgumentException("loader cannot be null"); - } - if (className == null) { - throw new IllegalArgumentException("className cannot be null"); - } + throw new IllegalArgumentException("loader cannot be null"); + } + if (className == null) { + throw new IllegalArgumentException("className cannot be null"); + } - // These classes are not visible for passed class loader! - if ("com.intellij.uiDesigner.HSpacer".equals(className) || "com.intellij.uiDesigner.VSpacer".equals(className)) { - return null; - } + // These classes are not visible for passed class loader! + if ("com.intellij.uiDesigner.HSpacer".equals(className) || "com.intellij.uiDesigner.VSpacer".equals(className)) { + return null; + } final Class aClass; - try { + try { aClass = Class.forName(className, false, loader); - } - catch (final ClassNotFoundException exc) { - return "Class \"" + className + "\"not found"; - } - catch (NoClassDefFoundError exc) { - return "Cannot load class " + className + ": " + exc.getMessage(); - } - catch (ExceptionInInitializerError exc) { - return "Cannot initialize class " + className + ": " + exc.getMessage(); - } - catch (UnsupportedClassVersionError exc) { - return "Unsupported class version error: " + className; - } + } + catch (final ClassNotFoundException exc) { + return "Class \"" + className + "\"not found"; + } + catch (NoClassDefFoundError exc) { + return "Cannot load class " + className + ": " + exc.getMessage(); + } + catch (ExceptionInInitializerError exc) { + return "Cannot initialize class " + className + ": " + exc.getMessage(); + } + catch (UnsupportedClassVersionError exc) { + return "Unsupported class version error: " + className; + } - if (validateConstructor) { + if (validateConstructor) { try { final Constructor constructor = aClass.getConstructor(new Class[0]); if ((constructor.getModifiers() & Modifier.PUBLIC) == 0) { - return "Class \"" + className + "\" does not have default public constructor"; - } - } + return "Class \"" + className + "\" does not have default public constructor"; + } + } catch (final Exception exc) { return "Class \"" + className + "\" does not have default constructor"; } } - // Check that JComponent is accessible via the loader + // Check that JComponent is accessible via the loader if (!JComponent.class.isAssignableFrom(aClass)) { - return "Class \"" + className + "\" is not an instance of javax.swing.JComponent"; - } + return "Class \"" + className + "\" is not an instance of javax.swing.JComponent"; + } - return null; + return null; + } + + public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader) + throws CodeGenerationException, RecursiveFormNestingException { + validateNestedFormLoop(formName, nestedFormLoader, null); + } + + public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader, final String targetForm) + throws CodeGenerationException, RecursiveFormNestingException { + HashSet usedFormNames = new HashSet(); + if (targetForm != null) { + usedFormNames.add(targetForm); } + validateNestedFormLoop(usedFormNames, formName, nestedFormLoader); + } - public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader) - throws CodeGenerationException, RecursiveFormNestingException { - validateNestedFormLoop(formName, nestedFormLoader, null); + private static void validateNestedFormLoop(final Set usedFormNames, final String formName, final NestedFormLoader nestedFormLoader) + throws CodeGenerationException, RecursiveFormNestingException { + if (usedFormNames.contains(formName)) { + throw new RecursiveFormNestingException(); } - - public static void validateNestedFormLoop(final String formName, final NestedFormLoader nestedFormLoader, final String targetForm) - throws CodeGenerationException, RecursiveFormNestingException { - HashSet usedFormNames = new HashSet(); - if (targetForm != null) { - usedFormNames.add(targetForm); - } - validateNestedFormLoop(usedFormNames, formName, nestedFormLoader); + usedFormNames.add(formName); + final LwRootContainer rootContainer; + try { + rootContainer = nestedFormLoader.loadForm(formName); } - - private static void validateNestedFormLoop(final Set usedFormNames, final String formName, final NestedFormLoader nestedFormLoader) - throws CodeGenerationException, RecursiveFormNestingException { - if (usedFormNames.contains(formName)) { - throw new RecursiveFormNestingException(); - } - usedFormNames.add(formName); - final LwRootContainer rootContainer; - try { - rootContainer = nestedFormLoader.loadForm(formName); - } - catch (Exception e) { - throw new CodeGenerationException(null, "Error loading nested form: " + e.getMessage(), e); - } - final Set thisFormNestedForms = new HashSet(); - final CodeGenerationException[] validateExceptions = new CodeGenerationException[1]; - final RecursiveFormNestingException[] recursiveNestingExceptions = new RecursiveFormNestingException[1]; - rootContainer.accept(new ComponentVisitor() { - public boolean visit(final IComponent component) { - if (component instanceof LwNestedForm) { - LwNestedForm nestedForm = (LwNestedForm)component; - if (!thisFormNestedForms.contains(nestedForm.getFormFileName())) { - thisFormNestedForms.add(nestedForm.getFormFileName()); - try { - validateNestedFormLoop(usedFormNames, nestedForm.getFormFileName(), nestedFormLoader); - } - catch (RecursiveFormNestingException e) { - recursiveNestingExceptions[0] = e; - return false; - } - catch (CodeGenerationException e) { - validateExceptions[0] = e; - return false; - } - } - } - return true; - } - }); - if (recursiveNestingExceptions[0] != null) { - throw recursiveNestingExceptions[0]; - } - if (validateExceptions[0] != null) { - throw validateExceptions[0]; - } + catch (Exception e) { + throw new CodeGenerationException(null, "Error loading nested form: " + e.getMessage(), e); } - - public static String findNotEmptyPanelWithXYLayout(final IComponent component) { - if (!(component instanceof IContainer)) { - return null; - } - final IContainer container = (IContainer)component; - if (container.getComponentCount() == 0) { - return null; - } - if (container.isXY()) { - return container.getId(); - } - for (int i = 0; i < container.getComponentCount(); i++) { - String id = findNotEmptyPanelWithXYLayout(container.getComponent(i)); - if (id != null) { - return id; - } - } - return null; - } - - public static int getHGap(LayoutManager layout) { - if (layout instanceof BorderLayout) { - return ((BorderLayout)layout).getHgap(); - } - if (layout instanceof CardLayout) { - return ((CardLayout)layout).getHgap(); - } - return 0; - } - - public static int getVGap(LayoutManager layout) { - if (layout instanceof BorderLayout) { - return ((BorderLayout)layout).getVgap(); - } - if (layout instanceof CardLayout) { - return ((CardLayout)layout).getVgap(); - } - return 0; - } - - public static int getCustomCreateComponentCount(final IContainer container) { - final int[] result = new int[1]; - result[0] = 0; - container.accept(new ComponentVisitor() { - public boolean visit(IComponent c) { - if (c.isCustomCreate()) { - result[0]++; - } - return true; - } - }); - return result[0]; - } - - public static Class suggestReplacementClass(Class componentClass) { - while (true) { - componentClass = componentClass.getSuperclass(); - if (componentClass.equals(JComponent.class)) { - return JPanel.class; - } - if ((componentClass.getModifiers() & (Modifier.ABSTRACT | Modifier.PRIVATE)) != 0) { - continue; - } + final Set thisFormNestedForms = new HashSet(); + final CodeGenerationException[] validateExceptions = new CodeGenerationException[1]; + final RecursiveFormNestingException[] recursiveNestingExceptions = new RecursiveFormNestingException[1]; + rootContainer.accept(new ComponentVisitor() { + public boolean visit(final IComponent component) { + if (component instanceof LwNestedForm) { + LwNestedForm nestedForm = (LwNestedForm)component; + if (!thisFormNestedForms.contains(nestedForm.getFormFileName())) { + thisFormNestedForms.add(nestedForm.getFormFileName()); try { - componentClass.getConstructor(new Class[]{}); + validateNestedFormLoop(usedFormNames, nestedForm.getFormFileName(), nestedFormLoader); } - catch (NoSuchMethodException ex) { - continue; + catch (RecursiveFormNestingException e) { + recursiveNestingExceptions[0] = e; + return false; } - return componentClass; + catch (CodeGenerationException e) { + validateExceptions[0] = e; + return false; + } + } } + return true; + } + }); + if (recursiveNestingExceptions[0] != null) { + throw recursiveNestingExceptions[0]; } + if (validateExceptions[0] != null) { + throw validateExceptions[0]; + } + } - public static int alignFromConstraints(final GridConstraints gc, final boolean horizontal) { - int anchor = gc.getAnchor(); - int fill = gc.getFill(); - int leftMask = horizontal ? GridConstraints.ANCHOR_WEST : GridConstraints.ANCHOR_NORTH; - int rightMask = horizontal ? GridConstraints.ANCHOR_EAST : GridConstraints.ANCHOR_SOUTH; - int fillMask = horizontal ? GridConstraints.FILL_HORIZONTAL : GridConstraints.FILL_VERTICAL; - if ((fill & fillMask) != 0) return GridConstraints.ALIGN_FILL; - if ((anchor & rightMask) != 0) return GridConstraints.ALIGN_RIGHT; - if ((anchor & leftMask) != 0) return GridConstraints.ALIGN_LEFT; - return GridConstraints.ALIGN_CENTER; + public static String findNotEmptyPanelWithXYLayout(final IComponent component) { + if (!(component instanceof IContainer)) { + return null; } + final IContainer container = (IContainer)component; + if (container.getComponentCount() == 0) { + return null; + } + if (container.isXY()) { + return container.getId(); + } + for (int i = 0; i < container.getComponentCount(); i++) { + String id = findNotEmptyPanelWithXYLayout(container.getComponent(i)); + if (id != null) { + return id; + } + } + return null; + } - public static boolean isBoundField(IComponent component, String fieldName) { - if (fieldName.equals(component.getBinding())) { - return true; - } - if (component instanceof IContainer) { - IContainer container = (IContainer)component; - for (int i = 0; i < container.getComponentCount(); i++) { - if (isBoundField(container.getComponent(i), fieldName)) { - return true; - } - } - } - return false; + public static int getHGap(LayoutManager layout) { + if (layout instanceof BorderLayout) { + return ((BorderLayout)layout).getHgap(); } + if (layout instanceof CardLayout) { + return ((CardLayout)layout).getHgap(); + } + return 0; + } + + public static int getVGap(LayoutManager layout) { + if (layout instanceof BorderLayout) { + return ((BorderLayout)layout).getVgap(); + } + if (layout instanceof CardLayout) { + return ((CardLayout)layout).getVgap(); + } + return 0; + } + + public static int getCustomCreateComponentCount(final IContainer container) { + final int[] result = new int[1]; + result[0] = 0; + container.accept(new ComponentVisitor() { + public boolean visit(IComponent c) { + if (c.isCustomCreate()) { + result[0]++; + } + return true; + } + }); + return result[0]; + } + + public static Class suggestReplacementClass(Class componentClass) { + while (true) { + componentClass = componentClass.getSuperclass(); + if (componentClass.equals(JComponent.class)) { + return JPanel.class; + } + if ((componentClass.getModifiers() & (Modifier.ABSTRACT | Modifier.PRIVATE)) != 0) { + continue; + } + try { + componentClass.getConstructor(new Class[]{}); + } + catch (NoSuchMethodException ex) { + continue; + } + return componentClass; + } + } + + public static InstrumentationClassFinder.PseudoClass suggestReplacementClass(InstrumentationClassFinder.PseudoClass componentClass) throws ClassNotFoundException, IOException { + final InstrumentationClassFinder.PseudoClass jComponentClass = componentClass.getFinder().loadClass(JComponent.class.getName()); + while (true) { + componentClass = componentClass.getSuperClass(); + if (componentClass.equals(jComponentClass)) { + return componentClass.getFinder().loadClass(JPanel.class.getName()); + } + if ((componentClass.getModifiers() & (Modifier.ABSTRACT | Modifier.PRIVATE)) != 0) { + continue; + } + if (!componentClass.hasDefaultPublicConstructor()) { + continue; + } + return componentClass; + } + } + + public static int alignFromConstraints(final GridConstraints gc, final boolean horizontal) { + int anchor = gc.getAnchor(); + int fill = gc.getFill(); + int leftMask = horizontal ? GridConstraints.ANCHOR_WEST : GridConstraints.ANCHOR_NORTH; + int rightMask = horizontal ? GridConstraints.ANCHOR_EAST : GridConstraints.ANCHOR_SOUTH; + int fillMask = horizontal ? GridConstraints.FILL_HORIZONTAL : GridConstraints.FILL_VERTICAL; + if ((fill & fillMask) != 0) return GridConstraints.ALIGN_FILL; + if ((anchor & rightMask) != 0) return GridConstraints.ALIGN_RIGHT; + if ((anchor & leftMask) != 0) return GridConstraints.ALIGN_LEFT; + return GridConstraints.ALIGN_CENTER; + } + + public static boolean isBoundField(IComponent component, String fieldName) { + if (fieldName.equals(component.getBinding())) { + return true; + } + if (component instanceof IContainer) { + IContainer container = (IContainer)component; + for (int i = 0; i < container.getComponentCount(); i++) { + if (isBoundField(container.getComponent(i), fieldName)) { + return true; + } + } + } + return false; + } } diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index f517eff750db..d9d39953f177 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -14,7 +14,7 @@ - + diff --git a/java/compiler/notNull/notNull.iml b/java/compiler/instrumentation-util/instrumentation-util.iml similarity index 100% rename from java/compiler/notNull/notNull.iml rename to java/compiler/instrumentation-util/instrumentation-util.iml diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/InstrumentationClassFinder.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java similarity index 71% rename from jps/jps-builders/src/org/jetbrains/jps/incremental/java/InstrumentationClassFinder.java rename to java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java index 8b2ee439af91..de009b37c9bf 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/InstrumentationClassFinder.java +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java @@ -1,10 +1,7 @@ -package org.jetbrains.jps.incremental.java; +package com.intellij.compiler.instrumentation; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.objectweb.asm.Attribute; import org.objectweb.asm.ClassReader; +import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.EmptyVisitor; import sun.misc.Resource; @@ -12,6 +9,7 @@ import sun.misc.Resource; import java.io.*; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLClassLoader; import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -23,22 +21,81 @@ import java.util.zip.ZipFile; public class InstrumentationClassFinder { private static final PseudoClass[] EMPTY_PSEUDOCLASS_ARRAY = new PseudoClass[0]; private static final String CLASS_RESOURCE_EXTENSION = ".class"; + private static final URL[] URL_EMPTY_ARRAY = new URL[0]; private final Map myLoaded = new HashMap(); // className -> class object private final ClassFinderClasspath myPlatformClasspath; private final ClassFinderClasspath myClasspath; + private final URL[] myPlatformUrls; + private final URL[] myClasspathUrls; + private ClassLoader myLoader; + private byte[] myBuffer; - public InstrumentationClassFinder(final URL[] platformClasspath, final URL[] classpath) { - myPlatformClasspath = new ClassFinderClasspath(platformClasspath); - myClasspath = new ClassFinderClasspath(classpath); + public InstrumentationClassFinder(final URL[] cp) { + this(URL_EMPTY_ARRAY, cp); + } + + public InstrumentationClassFinder(final URL[] platformUrls, final URL[] classpathUrls) { + myPlatformUrls = platformUrls; + myClasspathUrls = classpathUrls; + myPlatformClasspath = new ClassFinderClasspath(platformUrls); + myClasspath = new ClassFinderClasspath(classpathUrls); + } + + // compatibility with legacy code requiring ClassLoader + public ClassLoader getLoader() { + ClassLoader loader = myLoader; + if (loader != null) { + return loader; + } + final URLClassLoader platformLoader = myPlatformUrls.length > 0 ? new URLClassLoader(myPlatformUrls, null) : null; + final ClassLoader cpLoader = new URLClassLoader(myClasspathUrls, platformLoader); + loader = new ClassLoader(cpLoader) { + + public InputStream getResourceAsStream(String name) { + InputStream is = null; + is = super.getResourceAsStream(name); + if (is == null) { + try { + is = InstrumentationClassFinder.this.getResourceAsStream(name); + } + catch (IOException ignored) { + } + } + return is; + } + + protected Class findClass(String name) throws ClassNotFoundException { + final InputStream is = lookupClassBeforeClasspath(name.replace('.', '/')); + if (is == null) { + throw new ClassNotFoundException(name); + } + try { + final byte[] bytes = loadBytes(is); + return defineClass(name, bytes, 0, bytes.length); + } + finally { + try { + is.close(); + } + catch (IOException ignored) { + } + } + } + }; + myLoader = loader; + return loader; } public void releaseResources() { myPlatformClasspath.releaseResources(); myClasspath.releaseResources(); myLoaded.clear(); + myBuffer = null; + myLoader = null; } - public PseudoClass loadClass(final String internalName) throws IOException, ClassNotFoundException{ + public PseudoClass loadClass(final String name) throws IOException, ClassNotFoundException{ + final String internalName = name.replace('.', '/'); // normalize final PseudoClass aClass = myLoaded.get(internalName); if (aClass != null) { return aClass; @@ -81,12 +138,28 @@ public class InstrumentationClassFinder { } } - @Nullable + public InputStream getResourceAsStream(String resourceName) throws IOException { + InputStream is = null; + + Resource resource = myPlatformClasspath.getResource(resourceName, false); + if (resource != null) { + is = resource.getInputStream(); + } + + if (is == null) { + resource = myClasspath.getResource(resourceName, false); + if (resource != null) { + is = resource.getInputStream(); + } + } + + return is; + } + protected InputStream lookupClassBeforeClasspath(final String internalClassName) { return null; } - @Nullable protected InputStream lookupClassAfterClasspath(final String internalClassName) { return null; } @@ -97,20 +170,61 @@ public class InstrumentationClassFinder { reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - return new PseudoClass(visitor.myName, visitor.mySuperclassName, visitor.myInterfaces, visitor.myIsInterface); + return new PseudoClass(visitor.myName, visitor.mySuperclassName, visitor.myInterfaces, visitor.myModifiers, visitor.myMethods); } public final class PseudoClass { private final String myName; private final String mySuperClass; private final String[] myInterfaces; - private final boolean isInterface; + private final int myModifiers; + private final List myMethods; - private PseudoClass(final String name, final String superClass, final String[] interfaces, final boolean anInterface) { + private PseudoClass(final String name, final String superClass, final String[] interfaces, final int modifiers, List methods) { myName = name; mySuperClass = superClass; myInterfaces = interfaces; - isInterface = anInterface; + myModifiers = modifiers; + myMethods = methods; + } + + public int getModifiers() { + return myModifiers; + } + + public boolean isInterface() { + return (myModifiers & Opcodes.ACC_INTERFACE) > 0; + } + + public String getName() { + return myName; + } + + public List getMethods() { + return myMethods; + } + + public List findMethods(String name) { + final List result = new ArrayList(); + for (PseudoMethod method : myMethods) { + if (method.getName().equals(name)){ + result.add(method); + } + } + return result; + } + + public PseudoMethod findMethod(String name, String descriptor) { + for (PseudoMethod method : myMethods) { + if (method.getName().equals(name) && method.getSignature().equals(descriptor)){ + return method; + } + } + return null; + } + + public InstrumentationClassFinder getFinder() { + return InstrumentationClassFinder.this; } public PseudoClass getSuperClass() throws IOException, ClassNotFoundException { @@ -173,36 +287,69 @@ public class InstrumentationClassFinder { if (x.implementsInterface(this)) { return true; } - if (x.isInterface() && getName().equals("java/lang/Object")) { + if (x.isInterface() && "java/lang/Object".equals(getName())) { return true; } return false; } - public boolean isInterface() { - return isInterface; + public boolean hasDefaultPublicConstructor() { + for (PseudoMethod method : myMethods) { + if ("".equals(method.getName()) && "()V".equals(method.getSignature())) { + return true; + } + } + return false; + } + + public String getDescriptor() { + return "L" + myName + ";"; + } + } + + public static final class PseudoMethod { + private final int myAccess; + private final String myName; + private final String mySignature; + + public PseudoMethod(int access, String name, String signature) { + myAccess = access; + myName = name; + mySignature = signature; + } + + public int getModifiers() { + return myAccess; } public String getName() { return myName; } + + public String getSignature() { + return mySignature; + } } private static class V extends EmptyVisitor { public String mySuperclassName = null; public String[] myInterfaces = null; public String myName = null; - public boolean myIsInterface = false; + public int myModifiers; + private final List myMethods = new ArrayList(); - public void visitAttribute(Attribute attr) { - super.visitAttribute(attr); + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if ((access & Opcodes.ACC_PUBLIC) > 0) { + myMethods.add(new PseudoMethod(access, name, desc)); + } + return super.visitMethod(access, name, desc, signature, exceptions); } public void visit(int version, int access, String pName, String signature, String pSuperName, String[] pInterfaces) { mySuperclassName = pSuperName; myInterfaces = pInterfaces; myName = pName; - myIsInterface = (access & Opcodes.ACC_INTERFACE) > 0; + myModifiers = access; } } @@ -221,7 +368,6 @@ public class InstrumentationClassFinder { } } - @Nullable public Resource getResource(String s, boolean flag) { int i = 0; for (Loader loader; (loader = getLoader(i)) != null; i++) { @@ -242,7 +388,6 @@ public class InstrumentationClassFinder { myLoadersMap.clear(); } - @Nullable private synchronized Loader getLoader(int i) { while (myLoaders.size() < i + 1) { URL url; @@ -275,7 +420,6 @@ public class InstrumentationClassFinder { return myLoaders.get(i); } - @Nullable private Loader getLoader(final URL url, int index) throws IOException { String s; try { @@ -317,7 +461,6 @@ public class InstrumentationClassFinder { return myURL; } - @Nullable public abstract Resource getResource(final String name, boolean flag); public abstract void releaseResources(); @@ -345,7 +488,6 @@ public class InstrumentationClassFinder { public void releaseResources() { } - @Nullable public Resource getResource(final String name, boolean check) { URL url = null; File file = null; @@ -410,7 +552,6 @@ public class InstrumentationClassFinder { } } - @NonNls public String toString() { return "FileLoader [" + myRootDir + "]"; } @@ -438,7 +579,6 @@ public class InstrumentationClassFinder { } } - @Nullable private ZipFile acquireZipFile() throws IOException { ZipFile zipFile = myZipFile; if (zipFile == null) { @@ -448,7 +588,6 @@ public class InstrumentationClassFinder { return zipFile; } - @Nullable private ZipFile doGetZipFile() throws IOException { if (FILE_PROTOCOL.equals(myURL.getProtocol())) { String s = unescapePercentSequences(myURL.getFile().replace('/', File.separatorChar)); @@ -463,7 +602,6 @@ public class InstrumentationClassFinder { return null; } - @Nullable public Resource getResource(String name, boolean flag) { try { final ZipFile file = acquireZipFile(); @@ -501,11 +639,9 @@ public class InstrumentationClassFinder { return myURL; } - @Nullable public InputStream getInputStream() throws IOException { - ZipFile file = null; try { - file = acquireZipFile(); + final ZipFile file = acquireZipFile(); if (file == null) { return null; } @@ -527,7 +663,6 @@ public class InstrumentationClassFinder { } } - @NonNls public String toString() { return "JarLoader [" + myURL + "]"; } @@ -535,8 +670,7 @@ public class InstrumentationClassFinder { } - @NotNull - private static String unescapePercentSequences(@NotNull String s) { + private static String unescapePercentSequences(String s) { if (s.indexOf('%') == -1) { return s; } @@ -591,4 +725,27 @@ public class InstrumentationClassFinder { return -1; } + public byte[] loadBytes(InputStream stream) { + byte[] buf = myBuffer; + if (buf == null) { + buf = new byte[512]; + myBuffer = buf; + } + + final ByteArrayOutputStream result = new ByteArrayOutputStream(); + try { + while (true) { + int n = stream.read(buf, 0, buf.length); + if (n <= 0) { + break; + } + result.write(buf, 0, n); + } + result.close(); + } + catch (IOException ignored) { + } + return result.toByteArray(); + } + } diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java new file mode 100644 index 000000000000..ffdf058a2fbf --- /dev/null +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumenterClassWriter.java @@ -0,0 +1,43 @@ +package com.intellij.compiler.instrumentation; + +import org.objectweb.asm.ClassWriter; + +/** +* @author Eugene Zhuravlev +* Date: 3/27/12 +*/ +public class InstrumenterClassWriter extends ClassWriter { + private final InstrumentationClassFinder myFinder; + + public InstrumenterClassWriter(int flags, final InstrumentationClassFinder finder) { + super(flags); + myFinder = finder; + } + + protected String getCommonSuperClass(final String type1, final String type2) { + try { + final InstrumentationClassFinder.PseudoClass cls1 = myFinder.loadClass(type1); + final InstrumentationClassFinder.PseudoClass cls2 = myFinder.loadClass(type2); + if (cls1.isAssignableFrom(cls2)) { + return cls1.getName(); + } + if (cls2.isAssignableFrom(cls1)) { + return cls2.getName(); + } + if (cls1.isInterface() || cls2.isInterface()) { + return "java/lang/Object"; + } + else { + InstrumentationClassFinder.PseudoClass c = cls1; + do { + c = c.getSuperClass(); + } + while (!c.isAssignableFrom(cls2)); + return c.getName(); + } + } + catch (Exception e) { + throw new RuntimeException(e.toString(), e); + } + } +} diff --git a/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java similarity index 100% rename from java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java rename to java/compiler/instrumentation-util/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java diff --git a/java/compiler/javac2/javac2.iml b/java/compiler/javac2/javac2.iml index 49c3fa54efee..a8680af11500 100644 --- a/java/compiler/javac2/javac2.iml +++ b/java/compiler/javac2/javac2.iml @@ -11,7 +11,7 @@ - + diff --git a/java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java b/java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java deleted file mode 100644 index dc8b6552147d..000000000000 --- a/java/compiler/javac2/src/com/intellij/ant/AntClassWriter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2000-2009 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.ant; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; - -import java.io.IOException; - -/** - * @author yole - */ -public class AntClassWriter extends ClassWriter { - private final PseudoClassLoader myPseudoClassLoader; - - public AntClassWriter(int flags, final PseudoClassLoader pseudoLoader) { - super(flags); - myPseudoClassLoader = pseudoLoader; - } - - public AntClassWriter(ClassReader classReader, int flags, final PseudoClassLoader pseudoLoader) { - super(classReader, flags); - myPseudoClassLoader = pseudoLoader; - } - - protected String getCommonSuperClass(final String type1, final String type2) { - try { - PseudoClassLoader.PseudoClass p1 = myPseudoClassLoader.loadClass(type1); - PseudoClassLoader.PseudoClass p2 = myPseudoClassLoader.loadClass(type2); - - return p1.getCommonSuperClassName(p2); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - } -} diff --git a/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java b/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java index 8409618031a9..eb423ae59820 100644 --- a/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java +++ b/java/compiler/javac2/src/com/intellij/ant/InstrumentationUtil.java @@ -15,6 +15,8 @@ */ package com.intellij.ant; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.uiDesigner.compiler.*; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; @@ -39,14 +41,14 @@ import java.util.*; */ public class InstrumentationUtil { - public static PseudoClassLoader createPseudoClassLoader(final String classPath) throws MalformedURLException { + public static InstrumentationClassFinder createInstrumentationClassFinder(final String classPath) throws MalformedURLException { final ArrayList urls = new ArrayList(); for (StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer.hasMoreTokens();) { final String s = tokenizer.nextToken(); urls.add(new File(s).toURL()); } final URL[] urlsArr = (URL[])urls.toArray(new URL[urls.size()]); - return new PseudoClassLoader(urlsArr); + return new InstrumentationClassFinder(urlsArr); } public static int getClassFileVersion(ClassReader reader) { @@ -108,12 +110,12 @@ public class InstrumentationUtil { } private class AntNestedFormLoader implements NestedFormLoader { - private final PseudoClassLoader myLoader; + private final InstrumentationClassFinder myClassFinder; private final List myNestedFormPathList; private final HashMap myFormCache = new HashMap(); - public AntNestedFormLoader(final PseudoClassLoader loader, List nestedFormPathList) { - myLoader = loader; + public AntNestedFormLoader(final InstrumentationClassFinder classFinder, List nestedFormPathList) { + myClassFinder = classFinder; myNestedFormPathList = nestedFormPathList; } @@ -143,7 +145,7 @@ public class InstrumentationUtil { } } } - InputStream resourceStream = myLoader.getLoader ().getResourceAsStream(formFilePath); + InputStream resourceStream = myClassFinder.getResourceAsStream(formFilePath); if (resourceStream != null) { return loadForm(formFilePath, resourceStream); } @@ -164,11 +166,11 @@ public class InstrumentationUtil { } } - public void instrumentForm(final File file, final PseudoClassLoader loader) { + public void instrumentForm(final File file, final InstrumentationClassFinder classFinder) { log("compiling form " + file.getAbsolutePath(), Project.MSG_VERBOSE); final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(file.toURL(), new CompiledClassPropertiesProvider(loader.getLoader ())); + rootContainer = Utils.getRootContainer(file.toURL(), new CompiledClassPropertiesProvider(classFinder.getLoader())); } catch (AlienFormFileException e) { // ignore non-IDEA forms @@ -216,9 +218,9 @@ public class InstrumentationUtil { finally { stream.close(); } - AntNestedFormLoader formLoader = new AntNestedFormLoader(loader, myNestedFormPathList); - AntClassWriter classWriter = new AntClassWriter(InstrumentationUtil.getAsmClassWriterFlags(version), loader); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader.getLoader(), formLoader, false, classWriter); + AntNestedFormLoader formLoader = new AntNestedFormLoader(classFinder, myNestedFormPathList); + InstrumenterClassWriter classWriter = new InstrumenterClassWriter(InstrumentationUtil.getAsmClassWriterFlags(version), classFinder); + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, classFinder, formLoader, false, classWriter); codeGenerator.patchFile(classFile); final FormErrorInfo[] warnings = codeGenerator.getWarnings(); @@ -243,15 +245,15 @@ public class InstrumentationUtil { } } - public static byte[] instrumentNotNull(final byte[] buffer, final PseudoClassLoader loader) { + public static byte[] instrumentNotNull(final byte[] buffer, final InstrumentationClassFinder loader) { return instrumentNotNull(new ClassReader (buffer), loader); } - private static byte[] instrumentNotNull(final ClassReader reader, final PseudoClassLoader loader) { + private static byte[] instrumentNotNull(final ClassReader reader, final InstrumentationClassFinder loader) { int version = getClassFileVersion(reader); if (version >= Opcodes.V1_5) { - ClassWriter writer = new AntClassWriter(getAsmClassWriterFlags(version), loader); + ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), loader); final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer); reader.accept(instrumenter, 0); @@ -264,7 +266,7 @@ public class InstrumentationUtil { return null; } - public static int instrumentNotNull(final File file, final PseudoClassLoader loader) throws IOException { + public static int instrumentNotNull(final File file, final InstrumentationClassFinder loader) throws IOException { int instrumented = 0; final String path = file.getPath(); final FileInputStream inputStream = new FileInputStream(file); diff --git a/java/compiler/javac2/src/com/intellij/ant/Javac2.java b/java/compiler/javac2/src/com/intellij/ant/Javac2.java index be4354258ac8..5c3035534b44 100644 --- a/java/compiler/javac2/src/com/intellij/ant/Javac2.java +++ b/java/compiler/javac2/src/com/intellij/ant/Javac2.java @@ -15,6 +15,8 @@ */ package com.intellij.ant; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.uiDesigner.compiler.*; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; @@ -201,26 +203,34 @@ public class Javac2 extends Javac { * class files. */ protected void compile() { - // compile java - if (areJavaClassesCompiled()) { - super.compile(); - } + // compile java + if (areJavaClassesCompiled()) { + super.compile(); + } - PseudoClassLoader loader = buildClasspathClassLoader(); - if (loader == null) return; - instrumentForms(loader); + InstrumentationClassFinder finder = buildClasspathClassLoader(); + if (finder == null) { + return; + } + try { + instrumentForms(finder); //NotNull instrumentation - final int instrumented = instrumentNotNull(getDestdir(), loader); + final int instrumented = instrumentNotNull(getDestdir(), finder); + log("Added @NotNull assertions to " + instrumented + " files", Project.MSG_INFO); + } + finally { + finder.releaseResources(); + } } - /** + /** * Instrument forms * - * @param loader a classloader to use + * @param finder a classloader to use */ - private void instrumentForms(final PseudoClassLoader loader) { + private void instrumentForms(final InstrumentationClassFinder finder) { // we instrument every file, because we cannot find which files should not be instrumented without dependency storage final ArrayList formsToInstrument = myFormFiles; @@ -237,7 +247,7 @@ public class Javac2 extends Javac { log("compiling form " + formFile.getAbsolutePath(), Project.MSG_VERBOSE); final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(formFile.toURL(), new CompiledClassPropertiesProvider(loader.getLoader())); + rootContainer = Utils.getRootContainer(formFile.toURL(), new CompiledClassPropertiesProvider(finder.getLoader())); } catch (AlienFormFileException e) { // ignore non-IDEA forms @@ -283,9 +293,9 @@ public class Javac2 extends Javac { finally { stream.close(); } - AntNestedFormLoader formLoader = new AntNestedFormLoader(loader.getLoader(), myNestedFormPathList); - AntClassWriter classWriter = new AntClassWriter(getAsmClassWriterFlags(version), loader); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader.getLoader(), formLoader, false, classWriter); + AntNestedFormLoader formLoader = new AntNestedFormLoader(finder.getLoader(), myNestedFormPathList); + InstrumenterClassWriter classWriter = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, formLoader, false, classWriter); codeGenerator.patchFile(classFile); final FormErrorInfo[] warnings = codeGenerator.getWarnings(); @@ -322,7 +332,7 @@ public class Javac2 extends Javac { * * @return a URL classloader */ - private PseudoClassLoader buildClasspathClassLoader() { + private InstrumentationClassFinder buildClasspathClassLoader() { final StringBuffer classPathBuffer = new StringBuffer(); final Path cp = new Path(getProject()); appendPath(cp, getBootclasspath()); @@ -349,7 +359,7 @@ public class Javac2 extends Javac { log("classpath=" + classPath, Project.MSG_VERBOSE); try { - return InstrumentationUtil.createPseudoClassLoader(classPath); + return InstrumentationUtil.createInstrumentationClassFinder(classPath); } catch (MalformedURLException e) { fireError(e.getMessage()); @@ -373,10 +383,10 @@ public class Javac2 extends Javac { * Instrument classes with NotNull annotations * * @param dir the directory with classes to instrument (the directory is processed recursively) - * @param loader the classloader to use + * @param finder the classloader to use * @return the amount of classes actually affected by instrumentation */ - private int instrumentNotNull(File dir, final PseudoClassLoader loader) { + private int instrumentNotNull(File dir, final InstrumentationClassFinder finder) { int instrumented = 0; final File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { @@ -393,7 +403,7 @@ public class Javac2 extends Javac { int version = getClassFileVersion(reader); if (version >= Opcodes.V1_5) { - ClassWriter writer = new AntClassWriter(getAsmClassWriterFlags(version), loader); + ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer); reader.accept(instrumenter, 0); @@ -421,7 +431,7 @@ public class Javac2 extends Javac { } } else if (file.isDirectory()) { - instrumented += instrumentNotNull(file, loader); + instrumented += instrumentNotNull(file, finder); } } diff --git a/java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java b/java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java deleted file mode 100644 index 97a4172d7b94..000000000000 --- a/java/compiler/javac2/src/com/intellij/ant/PseudoClassLoader.java +++ /dev/null @@ -1,275 +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.ant; - -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.commons.EmptyVisitor; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * @author db - * Date: 06.06.11 - */ -public class PseudoClassLoader { - static final WeakHashMap myCache = new WeakHashMap(); - - final Map myDefinedClasses = new HashMap (); - final Map myDefinedClassesData = new HashMap (); - - private class MemoryClassLoader extends ClassLoader { - public MemoryClassLoader(URLClassLoader classpathLoader) { - super(classpathLoader); - } - - protected Class findClass(String name) throws ClassNotFoundException { - final byte[] data = (byte[])myDefinedClassesData.get(name); - if (data == null) { - throw new ClassNotFoundException(name); - } - return defineClass(name, data, 0, data.length); - } - - public URL findResource(String name) { - return super.findResource(name); - } - } - - public class PseudoClass { - final String myName; - final String mySuperClass; - final String[] myInterfaces; - final boolean isInterface; - - private PseudoClass(final Class repr) { - final Class superclass = repr.getSuperclass(); - final Class[] interfaces = repr.getInterfaces(); - - myName = repr.getName().replace('.', '/'); - mySuperClass = superclass == null ? null : superclass.getName().replace('.', '/'); - myInterfaces = interfaces.length == 0 ? null : new String[interfaces.length]; - - for (int i=0; i 0; - } - } - - private PseudoClass createPseudoClass(final ClassReader r) { - final V visitor = new V(); - - r.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - - return new PseudoClass(visitor.name, visitor.superName, visitor.interfaces, visitor.isInterface); - } - - private class Tag { - final PseudoClass myClass; - final long myStamp; - - private Tag(PseudoClass aClass, long stamp) { - myClass = aClass; - myStamp = stamp; - } - } - - public PseudoClass loadClass(final String internalName) throws IOException, ClassNotFoundException { - final PseudoClass defined = (PseudoClass) myDefinedClasses.get(internalName); - - if (defined != null) { - return defined; - } - - final URL resource = myLoader.findResource(internalName + ".class"); - - if (resource == null) { - final Class lastResort = myLoader.loadClass(internalName.replace('/', '.')); - return new PseudoClass(lastResort); - } - - final String fileName = resource.getFile(); - final boolean isFile = fileName.length() > 0; - final File file = new File(fileName); - - if (isFile) { - final Tag cached = (Tag)myCache.get(internalName); - - if (cached != null && cached.myStamp == file.lastModified()) { - return cached.myClass; - } - } - - final InputStream content = (InputStream)resource.getContent(); - final ClassReader reader = new ClassReader(content); - final PseudoClass result = createPseudoClass(reader); - - if (isFile) { - myCache.put(internalName, new Tag(result, file.lastModified())); - } - - return result; - } -} diff --git a/java/java-tests/java-tests.iml b/java/java-tests/java-tests.iml index 1750b2ea3852..38e0eb6d4c3d 100644 --- a/java/java-tests/java-tests.iml +++ b/java/java-tests/java-tests.iml @@ -17,7 +17,7 @@ - + diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml index 9c5878d1e2f3..e27c35289a56 100644 --- a/jps/jps-builders/jps-builders.iml +++ b/jps/jps-builders/jps-builders.iml @@ -12,7 +12,7 @@ - + diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 10b03b898693..5378c096312a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -1,5 +1,7 @@ package org.jetbrains.jps.incremental.java; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.compiler.instrumentation.InstrumenterClassWriter; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.execution.process.BaseOSProcessHandler; import com.intellij.openapi.application.PathManager; @@ -37,7 +39,6 @@ import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; import java.net.URL; -import java.net.URLClassLoader; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @@ -274,15 +275,14 @@ public class JavaBuilder extends ModuleLevelBuilder { context.checkCanceled(); if (!forms.isEmpty() || addNotNullAssertions) { - final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, outputSink); + final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, context.isCompilingTests()); + final InstrumentationClassFinder finder = createInstrumentationClassFinder(platformCp, classpath, chunkSourcePath, outputSink); try { if (!forms.isEmpty()) { try { context.processMessage(new ProgressMessage("Instrumenting forms [" + chunkName + "]")); - final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, context.isCompilingTests()); - final ClassLoader loader = createInstrumentationClassLoader(platformCp, classpath, chunkSourcePath, outputSink); - instrumentForms(context, chunk, chunkSourcePath, loader, finder, forms, outputSink); + instrumentForms(context, chunk, chunkSourcePath, finder, forms, outputSink); } finally { context.processMessage(new ProgressMessage("Finished instrumenting forms [" + chunkName + "]")); @@ -529,22 +529,24 @@ public class JavaBuilder extends ModuleLevelBuilder { private static InstrumentationClassFinder createInstrumentationClassFinder(Collection platformCp, Collection classpath, - final OutputFilesSink outputSink) throws MalformedURLException { + Map chunkSourcePath, final OutputFilesSink outputSink) throws MalformedURLException { final URL[] platformUrls = new URL[platformCp.size()]; int index = 0; for (File file : platformCp) { platformUrls[index++] = file.toURI().toURL(); } - final URL[] urls = new URL[classpath.size() + 1]; - index = 0; + final List urls = new ArrayList(classpath.size() + chunkSourcePath.size() + 1); for (File file : classpath) { - urls[index++] = file.toURI().toURL(); + urls.add(file.toURI().toURL()); } - urls[index++] = getResourcePath(GridConstraints.class).toURI().toURL(); // forms_rt.jar + urls.add(getResourcePath(GridConstraints.class).toURI().toURL()); // forms_rt.jar //urls.add(getResourcePath(CellConstraints.class).toURI().toURL()); // jgoodies-forms - - return new InstrumentationClassFinder(platformUrls, urls) { + for (File file : chunkSourcePath.keySet()) { // sourcepath for loading forms resources + urls.add(file.toURI().toURL()); + } + + return new InstrumentationClassFinder(platformUrls, urls.toArray(new URL[urls.size()])) { protected InputStream lookupClassBeforeClasspath(String internalClassName) { final OutputFileObject.Content content = outputSink.lookupClassBytes(internalClassName.replace("/", ".")); if (content != null) { @@ -555,23 +557,6 @@ public class JavaBuilder extends ModuleLevelBuilder { }; } - private static ClassLoader createInstrumentationClassLoader(Collection platformCp, Collection classpath, - Map chunkSourcePath, - OutputFilesSink outputSink) throws MalformedURLException { - final List urls = new ArrayList(); - for (Collection cp : Arrays.asList(platformCp, classpath)) { - for (File file : cp) { - urls.add(file.toURI().toURL()); - } - } - urls.add(getResourcePath(GridConstraints.class).toURI().toURL()); // forms_rt.jar - //urls.add(getResourcePath(CellConstraints.class).toURI().toURL()); // jgoodies-forms - for (File file : chunkSourcePath.keySet()) { - urls.add(file.toURI().toURL()); - } - return new CompiledClassesLoader(outputSink, urls.toArray(new URL[urls.size()])); - } - private static final Key> JAVAC_OPTIONS = Key.create("_javac_options_"); private static final Key> JAVAC_VM_OPTIONS = Key.create("_javac_vm_options_"); @@ -713,7 +698,6 @@ public class JavaBuilder extends ModuleLevelBuilder { private static void instrumentForms(CompileContext context, ModuleChunk chunk, final Map chunkSourcePath, - final ClassLoader loader, final InstrumentationClassFinder finder, Collection formsToInstrument, OutputFilesSink outputSink) throws ProjectBuildException { @@ -731,7 +715,7 @@ public class JavaBuilder extends ModuleLevelBuilder { for (File formFile : formsToInstrument) { final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(formFile.toURI().toURL(), new CompiledClassPropertiesProvider(loader)); + rootContainer = Utils.getRootContainer(formFile.toURI().toURL(), new CompiledClassPropertiesProvider(finder.getLoader())); } catch (AlienFormFileException e) { // ignore non-IDEA forms @@ -774,7 +758,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final int version = getClassFileVersion(classReader); final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader, nestedFormsLoader, false, classWriter); + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, nestedFormsLoader, false, classWriter); final byte[] patchedBytes = codeGenerator.patchClass(classReader); if (patchedBytes != null) { outputClassFile.updateContent(patchedBytes); @@ -923,42 +907,6 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - public static class InstrumenterClassWriter extends ClassWriter { - private final InstrumentationClassFinder myFinder; - - public InstrumenterClassWriter(int flags, final InstrumentationClassFinder finder) { - super(flags); - myFinder = finder; - } - - protected String getCommonSuperClass(final String type1, final String type2) { - try { - final InstrumentationClassFinder.PseudoClass cls1 = myFinder.loadClass(type1); - final InstrumentationClassFinder.PseudoClass cls2 = myFinder.loadClass(type2); - if (cls1.isAssignableFrom(cls2)) { - return cls1.getName(); - } - if (cls2.isAssignableFrom(cls1)) { - return cls2.getName(); - } - if (cls1.isInterface() || cls2.isInterface()) { - return "java/lang/Object"; - } - else { - InstrumentationClassFinder.PseudoClass c = cls1; - do { - c = c.getSuperClass(); - } - while (!c.isAssignableFrom(cls2)); - return c.getName(); - } - } - catch (Exception e) { - throw new RuntimeException(e.toString(), e); - } - } - } - private static class MyNestedFormLoader implements NestedFormLoader { private final Map mySourceRoots; private final Collection myOutputRoots; @@ -1039,27 +987,6 @@ public class JavaBuilder extends ModuleLevelBuilder { return new File(PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class")); } - private static class CompiledClassesLoader extends URLClassLoader { - private final OutputFilesSink mySink; - - public CompiledClassesLoader(OutputFilesSink sink, URL[] urls) { - super(urls, null); - mySink = sink; - } - - protected Class findClass(String name) throws ClassNotFoundException { - final OutputFileObject.Content content = mySink.lookupClassBytes(name); - if (content != null) { - return defineClass(name, content.getBuffer(), content.getOffset(), content.getLength()); - } - return super.findClass(name); - } - - public URL findResource(String name) { - return super.findResource(name); - } - } - private class ClassProcessingConsumer implements OutputFileConsumer { private final CompileContext myCompileContext; private final OutputFileConsumer myDelegateOutputFileSink; diff --git a/jps/jps.iml b/jps/jps.iml index 44d24bb8c46f..c08dac3c1a16 100644 --- a/jps/jps.iml +++ b/jps/jps.iml @@ -34,6 +34,7 @@ + diff --git a/jps/src/org/jetbrains/jps/ModuleBuildState.groovy b/jps/src/org/jetbrains/jps/ModuleBuildState.groovy index b82ef2422486..52f15608c417 100644 --- a/jps/src/org/jetbrains/jps/ModuleBuildState.groovy +++ b/jps/src/org/jetbrains/jps/ModuleBuildState.groovy @@ -1,7 +1,7 @@ package org.jetbrains.jps import com.intellij.ant.InstrumentationUtil.FormInstrumenter -import com.intellij.ant.PseudoClassLoader +import com.intellij.compiler.instrumentation.InstrumentationClassFinder import org.jetbrains.ether.ProjectWrapper import org.jetbrains.ether.dependencyView.Callbacks.Backend @@ -13,7 +13,7 @@ class ModuleBuildState { boolean tests Backend callback FormInstrumenter formInstrumenter - PseudoClassLoader loader + InstrumentationClassFinder loader ProjectWrapper projectWrapper List sourceFiles List sourceRoots diff --git a/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy b/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy index babacca78d33..1c7537687a48 100644 --- a/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy +++ b/jps/src/org/jetbrains/jps/builders/StandardBuilders.groovy @@ -3,6 +3,7 @@ package org.jetbrains.jps.builders import com.intellij.ant.InstrumentationUtil import com.intellij.ant.InstrumentationUtil.FormInstrumenter import com.intellij.ant.PrefixedPath +import com.intellij.compiler.instrumentation.InstrumentationClassFinder import org.apache.tools.ant.BuildListener import org.jetbrains.ether.ProjectWrapper import org.jetbrains.ether.dependencyView.AntListener @@ -332,17 +333,13 @@ class JetBrainsInstrumentations implements ModuleBuilder { def processModule(ModuleBuildState state, ModuleChunk moduleChunk, ProjectBuilder projectBuilder) { if (state.loader == null) { - final StringBuilder cp = new StringBuilder() - - cp.append(state.targetFolder) - cp.append(File.pathSeparator) - + final ArrayList urls = new ArrayList(); + urls.add(new File(state.targetFolder).toURL()); state.classpath.each { - cp.append(it) - cp.append(File.pathSeparator) + urls.add(new File(it).toURL()); } - state.loader = InstrumentationUtil.createPseudoClassLoader(cp.toString()) + state.loader = new InstrumentationClassFinder((URL[])urls.toArray(new URL[urls.size()])) final List formFiles = new ArrayList(); final ProjectWrapper pw = state.projectWrapper; @@ -409,6 +406,9 @@ class JetBrainsInstrumentations implements ModuleBuilder { InstrumentationUtil.instrumentNotNull(new File(state.targetFolder + File.separator + it + ".class"), state.loader) } } + if (state.loader != null) { + state.loader.releaseResources(); + } } } diff --git a/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy b/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy index 7ca3bb2dc8f3..a235e2fd9c97 100644 --- a/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy +++ b/jps/src/org/jetbrains/jps/builders/javacApi/Java16ApiCompiler.groovy @@ -1,17 +1,17 @@ package org.jetbrains.jps.builders.javacApi -import com.intellij.ant.InstrumentationUtil -import javax.tools.JavaCompiler -import javax.tools.JavaCompiler.CompilationTask -import javax.tools.JavaFileObject -import javax.tools.StandardLocation -import javax.tools.ToolProvider import org.jetbrains.jps.ModuleBuildState import org.jetbrains.jps.ModuleChunk import org.jetbrains.jps.ProjectBuilder import org.jetbrains.jps.Sdk import org.jetbrains.jps.builders.JavaFileCollector +import javax.tools.JavaCompiler +import javax.tools.JavaCompiler.CompilationTask +import javax.tools.JavaFileObject +import javax.tools.StandardLocation +import javax.tools.ToolProvider + /** * @author nik */ @@ -89,7 +89,7 @@ class Java16ApiCompiler { cp.append(state.targetFolder) fileManager.setLocation(StandardLocation.CLASS_PATH, classpath) - fileManager.setProperties(state.callback, InstrumentationUtil.createPseudoClassLoader(cp.toString())) + fileManager.setProperties(state.callback, toURLs(cp.toString())) Iterable toCompile = fileManager.getJavaFileObjectsFromFiles(filesToCompile) StringWriter out = new StringWriter() @@ -109,4 +109,13 @@ class Java16ApiCompiler { } } + private URL[] toURLs(final String classPath) { + final List urls = new ArrayList(); + for (StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer.hasMoreTokens();) { + final String s = tokenizer.nextToken(); + urls.add(new File(s).toURL()); + } + return (URL[])urls.toArray(new URL[urls.size()]); + } + } diff --git a/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java b/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java index a4617a93289d..d7163000ea5d 100644 --- a/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java +++ b/jps/src/org/jetbrains/jps/builders/javacApi/OptimizedFileManager.java @@ -1,7 +1,7 @@ package org.jetbrains.jps.builders.javacApi; import com.intellij.ant.InstrumentationUtil; -import com.intellij.ant.PseudoClassLoader; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.DefaultFileManager; import com.sun.tools.javac.util.List; @@ -14,10 +14,9 @@ import javax.lang.model.SourceVersion; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileObject; import javax.tools.JavaFileObject; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.lang.reflect.Field; +import java.net.URL; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -34,11 +33,17 @@ public class OptimizedFileManager extends DefaultFileManager { private final Map myArchives; private final Map myIsFile = new ConcurrentHashMap(); private Callbacks.Backend callback; - private PseudoClassLoader loader; + private InstrumentationClassFinder classFinder; + private Map myCompiledClasses = new HashMap(); - public void setProperties(final Callbacks.Backend c, final PseudoClassLoader l) { + public void setProperties(final Callbacks.Backend c, final URL[] classpath) { callback = c; - loader = l; + classFinder = new InstrumentationClassFinder(classpath) { + protected InputStream lookupClassBeforeClasspath(String internalClassName) { + final byte[] bytes = myCompiledClasses.get(internalClassName); + return bytes != null? new ByteArrayInputStream(bytes) : null; + } + }; } public OptimizedFileManager() { @@ -201,7 +206,7 @@ public class OptimizedFileManager extends DefaultFileManager { final byte[] buffer = Arrays.copyOfRange(b, off, len); if (kind.equals(JavaFileObject.Kind.CLASS)) { - loader.defineClass(className.replaceAll("\\.", "/"), buffer); + myCompiledClasses.put(className.replace('.', '/'), buffer); if (callback != null) { final ClassReader reader = new ClassReader(buffer); @@ -212,7 +217,7 @@ public class OptimizedFileManager extends DefaultFileManager { public void commit() throws IOException { final OutputStream result = superOpenOutputStream(); - final byte[] instrumented = InstrumentationUtil.instrumentNotNull(buffer, loader); + final byte[] instrumented = InstrumentationUtil.instrumentNotNull(buffer, classFinder); if (instrumented != null) { result.write(instrumented); @@ -247,5 +252,8 @@ public class OptimizedFileManager extends DefaultFileManager { } myWriters.clear(); + if (classFinder != null) { + classFinder.releaseResources(); + } } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java index 15bb312a9e48..bff58a5533db 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java @@ -18,6 +18,7 @@ package com.intellij.uiDesigner.actions; import com.intellij.CommonBundle; import com.intellij.compiler.PsiClassWriter; import com.intellij.compiler.impl.FileSetCompileScope; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.execution.*; import com.intellij.execution.configurations.*; import com.intellij.execution.executors.DefaultRunExecutor; @@ -128,118 +129,124 @@ public final class PreviewFormAction extends AnAction{ final String classPath = OrderEnumerator.orderEntries(module).recursively().getPathsList().getPathsString() + File.pathSeparator + sources.getPathsString() + File.pathSeparator + /* resources bundles */ tempPath; - final ClassLoader loader = Form2ByteCodeCompiler.createClassLoader(classPath); + final InstrumentationClassFinder finder = Form2ByteCodeCompiler.createClassFinder(classPath); - final Document doc = FileDocumentManager.getInstance().getDocument(formFile); - final LwRootContainer rootContainer; try { - rootContainer = Utils.getRootContainer(doc.getText(), new CompiledClassPropertiesProvider(loader)); - } - catch (Exception e) { - Messages.showErrorDialog( - module.getProject(), - UIDesignerBundle.message("error.cannot.read.form", formFile.getPath().replace('/', File.separatorChar), e.getMessage()), - CommonBundle.getErrorTitle() - ); - return; - } - - if (rootContainer.getComponentCount() == 0) { - Messages.showErrorDialog( - module.getProject(), - UIDesignerBundle.message("error.cannot.preview.empty.form", formFile.getPath().replace('/', File.separatorChar)), - CommonBundle.getErrorTitle() - ); - return; - } - - setPreviewBindings(rootContainer, CLASS_TO_BIND_NAME); - - // 2. Copy previewer class and all its superclasses into TEMP directory and instrument it. - try { - PreviewNestedFormLoader nestedFormLoader = new PreviewNestedFormLoader(module, tempPath, loader); - - final File tempFile = CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME, true); - //CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$1", true); - CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyExitAction", true); - CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyPackAction", true); - CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MySetLafAction", true); - - Locale locale = Locale.getDefault(); - if (locale.getCountry().length() > 0 && locale.getLanguage().length() > 0) { - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + - "_" + locale.getCountry() + PropertiesFileType.DOT_DEFAULT_EXTENSION); + final Document doc = FileDocumentManager.getInstance().getDocument(formFile); + final LwRootContainer rootContainer; + try { + rootContainer = Utils.getRootContainer(doc.getText(), new CompiledClassPropertiesProvider(finder.getLoader())); } - if (locale.getLanguage().length() > 0) { - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); - } - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); - CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + PropertiesFileType.DOT_DEFAULT_EXTENSION); - - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader, nestedFormLoader, true, - new PsiClassWriter(module)); - codeGenerator.patchFile(tempFile); - final FormErrorInfo[] errors = codeGenerator.getErrors(); - if(errors.length != 0){ + catch (Exception e) { Messages.showErrorDialog( module.getProject(), - UIDesignerBundle.message("error.cannot.preview.form", - formFile.getPath().replace('/', File.separatorChar), - errors[0].getErrorMessage()), + UIDesignerBundle.message("error.cannot.read.form", formFile.getPath().replace('/', File.separatorChar), e.getMessage()), CommonBundle.getErrorTitle() ); return; } - } - catch (Exception e) { - LOG.debug(e); - Messages.showErrorDialog( - module.getProject(), - UIDesignerBundle.message("error.cannot.preview.form", formFile.getPath().replace('/', File.separatorChar), - e.getMessage() != null ? e.getMessage() : e.toString()), - CommonBundle.getErrorTitle() - ); - return; - } - // 2.5. Copy up-to-date properties files to the output directory. - final HashSet bundleSet = new HashSet(); - FormEditingUtil.iterateStringDescriptors( - rootContainer, - new FormEditingUtil.StringDescriptorVisitor() { - public boolean visit(final IComponent component, final StringDescriptor descriptor) { - if (descriptor.getBundleName() != null) { - bundleSet.add(descriptor.getDottedBundleName()); - } - return true; + if (rootContainer.getComponentCount() == 0) { + Messages.showErrorDialog( + module.getProject(), + UIDesignerBundle.message("error.cannot.preview.empty.form", formFile.getPath().replace('/', File.separatorChar)), + CommonBundle.getErrorTitle() + ); + return; + } + + setPreviewBindings(rootContainer, CLASS_TO_BIND_NAME); + + // 2. Copy previewer class and all its superclasses into TEMP directory and instrument it. + try { + PreviewNestedFormLoader nestedFormLoader = new PreviewNestedFormLoader(module, tempPath, finder); + + final File tempFile = CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME, true); + //CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$1", true); + CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyExitAction", true); + CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MyPackAction", true); + CopyResourcesUtil.copyClass(tempPath, CLASS_TO_BIND_NAME + "$MySetLafAction", true); + + Locale locale = Locale.getDefault(); + if (locale.getCountry().length() > 0 && locale.getLanguage().length() > 0) { + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + + "_" + locale.getCountry() + PropertiesFileType.DOT_DEFAULT_EXTENSION); } - }); + if (locale.getLanguage().length() > 0) { + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); + } + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + "_" + locale.getLanguage() + PropertiesFileType.DOT_DEFAULT_EXTENSION); + CopyResourcesUtil.copyProperties(tempPath, RUNTIME_BUNDLE_PREFIX + PropertiesFileType.DOT_DEFAULT_EXTENSION); - if (bundleSet.size() > 0) { - HashSet virtualFiles = new HashSet(); - HashSet modules = new HashSet(); - PropertiesReferenceManager manager = PropertiesReferenceManager.getInstance(module.getProject()); - for(String bundleName: bundleSet) { - for(PropertiesFile propFile: manager.findPropertiesFiles(module, bundleName)) { - virtualFiles.add(propFile.getVirtualFile()); - final Module moduleForFile = ModuleUtil.findModuleForFile(propFile.getVirtualFile(), module.getProject()); - if (moduleForFile != null) { - modules.add(moduleForFile); - } + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator( + rootContainer, finder, nestedFormLoader, true, new PsiClassWriter(module) + ); + codeGenerator.patchFile(tempFile); + final FormErrorInfo[] errors = codeGenerator.getErrors(); + if(errors.length != 0){ + Messages.showErrorDialog( + module.getProject(), + UIDesignerBundle.message("error.cannot.preview.form", + formFile.getPath().replace('/', File.separatorChar), + errors[0].getErrorMessage()), + CommonBundle.getErrorTitle() + ); + return; } } - FileSetCompileScope scope = new FileSetCompileScope(virtualFiles, modules.toArray(new Module[modules.size()])); + catch (Exception e) { + LOG.debug(e); + Messages.showErrorDialog( + module.getProject(), + UIDesignerBundle.message("error.cannot.preview.form", formFile.getPath().replace('/', File.separatorChar), + e.getMessage() != null ? e.getMessage() : e.toString()), + CommonBundle.getErrorTitle() + ); + return; + } - CompilerManager.getInstance(module.getProject()).make(scope, new CompileStatusNotification() { - public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { - if (!aborted && errors == 0) { - runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + // 2.5. Copy up-to-date properties files to the output directory. + final HashSet bundleSet = new HashSet(); + FormEditingUtil.iterateStringDescriptors( + rootContainer, + new FormEditingUtil.StringDescriptorVisitor() { + public boolean visit(final IComponent component, final StringDescriptor descriptor) { + if (descriptor.getBundleName() != null) { + bundleSet.add(descriptor.getDottedBundleName()); + } + return true; + } + }); + + if (bundleSet.size() > 0) { + HashSet virtualFiles = new HashSet(); + HashSet modules = new HashSet(); + PropertiesReferenceManager manager = PropertiesReferenceManager.getInstance(module.getProject()); + for(String bundleName: bundleSet) { + for(PropertiesFile propFile: manager.findPropertiesFiles(module, bundleName)) { + virtualFiles.add(propFile.getVirtualFile()); + final Module moduleForFile = ModuleUtil.findModuleForFile(propFile.getVirtualFile(), module.getProject()); + if (moduleForFile != null) { + modules.add(moduleForFile); + } } } - }); + FileSetCompileScope scope = new FileSetCompileScope(virtualFiles, modules.toArray(new Module[modules.size()])); + + CompilerManager.getInstance(module.getProject()).make(scope, new CompileStatusNotification() { + public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { + if (!aborted && errors == 0) { + runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + } + } + }); + } + else { + runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + } } - else { - runPreviewProcess(tempPath, sources, module, formFile, stringDescriptorLocale); + finally { + finder.releaseResources(); } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java b/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java index b42fd6bf0520..8bcacec4b2ee 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java @@ -17,6 +17,7 @@ package com.intellij.uiDesigner.make; import com.intellij.compiler.PsiClassWriter; import com.intellij.compiler.impl.CompilerUtil; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.*; import com.intellij.openapi.diagnostic.Logger; @@ -50,7 +51,6 @@ import java.io.DataInput; import java.io.File; import java.io.IOException; import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -71,7 +71,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler { } @NotNull - public static URLClassLoader createClassLoader(@NotNull final String classPath){ + public static InstrumentationClassFinder createClassFinder(@NotNull final String classPath){ final ArrayList urls = new ArrayList(); for (StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer.hasMoreTokens();) { final String s = tokenizer.nextToken(); @@ -82,7 +82,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler { throw new RuntimeException(exc); } } - return new URLClassLoader(urls.toArray(new URL[urls.size()]), null); + return new InstrumentationClassFinder(urls.toArray(new URL[urls.size()])); } @Override @@ -274,81 +274,86 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler { List filesToRefresh = new ArrayList(); for (final Module module : module2itemsList.keySet()) { final String classPath = OrderEnumerator.orderEntries(module).recursively().getPathsList().getPathsString(); - final ClassLoader loader = createClassLoader(classPath); + final InstrumentationClassFinder finder = createClassFinder(classPath); - if (GuiDesignerConfiguration.getInstance(project).COPY_FORMS_RUNTIME_TO_OUTPUT) { - final String moduleOutputPath = CompilerPaths.getModuleOutputPath(module, false); - try { - if (moduleOutputPath != null) { - filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(moduleOutputPath, false)); + try { + if (GuiDesignerConfiguration.getInstance(project).COPY_FORMS_RUNTIME_TO_OUTPUT) { + final String moduleOutputPath = CompilerPaths.getModuleOutputPath(module, false); + try { + if (moduleOutputPath != null) { + filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(moduleOutputPath, false)); + } + final String testsOutputPath = CompilerPaths.getModuleOutputPath(module, true); + if (testsOutputPath != null && !testsOutputPath.equals(moduleOutputPath)) { + filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(testsOutputPath, false)); + } } - final String testsOutputPath = CompilerPaths.getModuleOutputPath(module, true); - if (testsOutputPath != null && !testsOutputPath.equals(moduleOutputPath)) { - filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(testsOutputPath, false)); + catch (IOException e) { + addMessage( + context, + UIDesignerBundle.message("error.cannot.copy.gui.designer.form.runtime", module.getName(), e.toString()), + null, CompilerMessageCategory.ERROR); } } - catch (IOException e) { - addMessage( - context, - UIDesignerBundle.message("error.cannot.copy.gui.designer.form.runtime", module.getName(), e.toString()), - null, CompilerMessageCategory.ERROR); + + final ArrayList list = module2itemsList.get(module); + + for (final MyInstrumentationItem item : list) { + //context.getProgressIndicator().setFraction((double)++formsProcessed / (double)items.length); + + final VirtualFile formFile = item.getFormFile(); + context.getProgressIndicator().setText2(formFile.getPresentableUrl()); + + final String text = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public String compute() { + if (!belongsToCompileScope(context, formFile, item.getClassToBindFQname())) { + return null; + } + Document document = FileDocumentManager.getInstance().getDocument(formFile); + return document == null ? null : document.getText(); + } + }); + if (text == null) { + continue; // does not belong to current scope + } + + final LwRootContainer rootContainer; + try { + rootContainer = Utils.getRootContainer(text, new CompiledClassPropertiesProvider(finder.getLoader())); + } + catch (Exception e) { + addMessage(context, UIDesignerBundle.message("error.cannot.process.form.file", e), formFile, CompilerMessageCategory.ERROR); + continue; + } + + final File classFile = VfsUtil.virtualToIoFile(item.getFile()); + LOG.assertTrue(classFile.exists(), classFile.getPath()); + + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator( + rootContainer, finder, new PsiNestedFormLoader(module), false, new PsiClassWriter(module) + ); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + codeGenerator.patchFile(classFile); + } + }); + final FormErrorInfo[] errors = codeGenerator.getErrors(); + final FormErrorInfo[] warnings = codeGenerator.getWarnings(); + for (FormErrorInfo warning : warnings) { + addMessage(context, warning, formFile, CompilerMessageCategory.WARNING); + } + for (FormErrorInfo error : errors) { + addMessage(context, error, formFile, CompilerMessageCategory.ERROR); + } + if (errors.length == 0) { + compiledItems.add(item); + } } } - - final ArrayList list = module2itemsList.get(module); - - for (final MyInstrumentationItem item : list) { - //context.getProgressIndicator().setFraction((double)++formsProcessed / (double)items.length); - - final VirtualFile formFile = item.getFormFile(); - context.getProgressIndicator().setText2(formFile.getPresentableUrl()); - - final String text = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public String compute() { - if (!belongsToCompileScope(context, formFile, item.getClassToBindFQname())) { - return null; - } - Document document = FileDocumentManager.getInstance().getDocument(formFile); - return document == null ? null : document.getText(); - } - }); - if (text == null) { - continue; // does not belong to current scope - } - - final LwRootContainer rootContainer; - try { - rootContainer = Utils.getRootContainer(text, new CompiledClassPropertiesProvider(loader)); - } - catch (Exception e) { - addMessage(context, UIDesignerBundle.message("error.cannot.process.form.file", e), formFile, CompilerMessageCategory.ERROR); - continue; - } - - final File classFile = VfsUtil.virtualToIoFile(item.getFile()); - LOG.assertTrue(classFile.exists(), classFile.getPath()); - - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, loader, - new PsiNestedFormLoader(module), false, - new PsiClassWriter(module)); - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - codeGenerator.patchFile(classFile); - } - }); - final FormErrorInfo[] errors = codeGenerator.getErrors(); - final FormErrorInfo[] warnings = codeGenerator.getWarnings(); - for (FormErrorInfo warning : warnings) { - addMessage(context, warning, formFile, CompilerMessageCategory.WARNING); - } - for (FormErrorInfo error : errors) { - addMessage(context, error, formFile, CompilerMessageCategory.ERROR); - } - if (errors.length == 0) { - compiledItems.add(item); - } + finally { + finder.releaseResources(); } } CompilerUtil.refreshIOFiles(filesToRefresh); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java b/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java index dbb2443c74a5..fbe4c8aaa86e 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/make/PreviewNestedFormLoader.java @@ -17,6 +17,7 @@ package com.intellij.uiDesigner.make; import com.intellij.compiler.PsiClassWriter; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; import com.intellij.openapi.module.Module; import com.intellij.uiDesigner.actions.PreviewFormAction; import com.intellij.uiDesigner.compiler.AsmCodeGenerator; @@ -41,13 +42,13 @@ import java.util.Set; */ public class PreviewNestedFormLoader extends PsiNestedFormLoader { private final String myTempPath; - private final ClassLoader myLoader; + private final InstrumentationClassFinder myFinder; private final Set myGeneratedClasses = new HashSet(); - public PreviewNestedFormLoader(final Module module, final String tempPath, final ClassLoader loader) { + public PreviewNestedFormLoader(final Module module, final String tempPath, final InstrumentationClassFinder finder) { super(module); myTempPath = tempPath; - myLoader = loader; + myFinder = finder; } public LwRootContainer loadForm(String formFileName) throws Exception { @@ -82,7 +83,7 @@ public class PreviewNestedFormLoader extends PsiNestedFormLoader { cw.visitEnd(); ByteArrayInputStream bais = new ByteArrayInputStream(cw.toByteArray()); - AsmCodeGenerator acg = new AsmCodeGenerator(rootContainer, myLoader, this, true, new PsiClassWriter(myModule)); + AsmCodeGenerator acg = new AsmCodeGenerator(rootContainer, myFinder, this, true, new PsiClassWriter(myModule)); byte[] data = acg.patchClass(bais); FormErrorInfo[] errors = acg.getErrors(); if (errors.length > 0) { diff --git a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java index 3bc39bccc584..d8ff9f5c68a6 100644 --- a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java +++ b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/core/AsmCodeGeneratorTest.java @@ -15,14 +15,21 @@ */ package com.intellij.uiDesigner.core; +import com.intellij.compiler.instrumentation.InstrumentationClassFinder; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.PluginPathManager; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.components.JBTabbedPane; import com.intellij.uiDesigner.compiler.AsmCodeGenerator; import com.intellij.uiDesigner.compiler.FormErrorInfo; import com.intellij.uiDesigner.compiler.NestedFormLoader; import com.intellij.uiDesigner.compiler.Utils; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; import com.intellij.uiDesigner.lw.LwRootContainer; +import com.intellij.util.PathUtil; +import com.intellij.util.ui.UIUtil; import junit.framework.TestCase; import org.objectweb.asm.ClassWriter; @@ -32,7 +39,13 @@ import javax.swing.border.TitledBorder; import java.awt.*; import java.io.*; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -41,19 +54,46 @@ import java.util.Map; */ public class AsmCodeGeneratorTest extends TestCase { private MyNestedFormLoader myNestedFormLoader; - private MyClassLoader myClassLoader; + private MyClassFinder myClassFinder; @Override protected void setUp() throws Exception { super.setUp(); myNestedFormLoader = new MyNestedFormLoader(); - myClassLoader = new MyClassLoader(getClass().getClassLoader()); + + final String swingPath = PathUtil.getJarPathForClass(AbstractButton.class); + + java.util.List cp = new ArrayList(); + appendPath(cp, JBTabbedPane.class); + appendPath(cp, UIUtil.class); + appendPath(cp, SystemInfoRt.class); + appendPath(cp, ApplicationManager.class); + appendPath(cp, PathManager.getResourceRoot(this.getClass(), "/messages/UIBundle.properties")); + appendPath(cp, PathManager.getResourceRoot(this.getClass(), "/RuntimeBundle.properties")); + appendPath(cp, GridLayoutManager.class); // forms_rt + myClassFinder = new MyClassFinder( + new URL[] {new File(swingPath).toURI().toURL()}, + cp.toArray(new URL[cp.size()]) + ); + } + + private static void appendPath(Collection container, Class cls) throws MalformedURLException { + final String path = PathUtil.getJarPathForClass(cls); + appendPath(container, path); + } + + private static void appendPath(Collection container, String path) throws MalformedURLException { + container.add(new File(path).toURI().toURL()); } @Override protected void tearDown() throws Exception { - myClassLoader = null; myNestedFormLoader = null; + final MyClassFinder classFinder = myClassFinder; + if (classFinder != null) { + classFinder.releaseResources(); + myClassFinder = null; + } super.tearDown(); } @@ -70,7 +110,7 @@ public class AsmCodeGeneratorTest extends TestCase { String classPath = tmpPath + "/" + className + ".class"; final LwRootContainer rootContainer = loadFormData(formPath); - final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, myClassLoader, myNestedFormLoader, false, + final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, myClassFinder, myNestedFormLoader, false, new ClassWriter(ClassWriter.COMPUTE_FRAMES)); final FileInputStream classStream = new FileInputStream(classPath); try { @@ -109,7 +149,8 @@ public class AsmCodeGeneratorTest extends TestCase { fos.close(); */ - return myClassLoader.doDefineClass(className, patchedData); + myClassFinder.addClassDefinition(className, patchedData); + return myClassFinder.getLoader().loadClass(className); } private static byte[] getVerifiedPatchedData(final AsmCodeGenerator codeGenerator) { @@ -168,10 +209,41 @@ public class AsmCodeGeneratorTest extends TestCase { public void testGridLayout() throws Exception { JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest"); - assertTrue(rootComponent.getLayout() instanceof GridLayoutManager); - GridLayoutManager gridLayout = (GridLayoutManager) rootComponent.getLayout(); - assertEquals(1, gridLayout.getRowCount()); - assertEquals(1, gridLayout.getColumnCount()); + final LayoutManager layout = rootComponent.getLayout(); + assertTrue(isInstanceOf(layout, GridLayoutManager.class.getName())); + + + assertEquals(1, invokeMethod(layout, "getRowCount")); + assertEquals(1, invokeMethod(layout, "getColumnCount")); + } + + private static boolean isInstanceOf(Object object, final String className) throws ClassNotFoundException { + final Class ethalon = object.getClass().getClassLoader().loadClass(className); + return ethalon.isAssignableFrom(object.getClass()); + } + + private static Object invokeMethod(Object obj, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + return invokeMethod(obj, methodName, new Class[0], new Object[0]); + } + + private static Object invokeMethod(Object obj, String methodName, Class[] params, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + final Method method = findMethod(obj.getClass(), methodName, params); + return method.invoke(obj, args); + } + + private static Method findMethod(Class aClass, String methodName, Class[] params) { + try { + final Method method = aClass.getDeclaredMethod(methodName, params); + method.setAccessible(true); + return method; + } + catch (NoSuchMethodException ignored) { + } + final Class parent = aClass.getSuperclass(); + if (parent == null) { + return null; + } + return findMethod(parent, methodName, params); } public void testCardLayout() throws Exception { @@ -193,10 +265,14 @@ public class AsmCodeGeneratorTest extends TestCase { public void testGridConstraints() throws Exception { JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest"); assertEquals(1, rootComponent.getComponentCount()); - GridLayoutManager gridLayout = (GridLayoutManager) rootComponent.getLayout(); - final GridConstraints constraints = gridLayout.getConstraints(0); - assertEquals(1, constraints.getColSpan()); - assertEquals(1, constraints.getRowSpan()); + final LayoutManager layout = rootComponent.getLayout(); + assertTrue(isInstanceOf(layout, GridLayoutManager.class.getName())); + + final Object constraints = invokeMethod(layout, "getConstraints", new Class[] {int.class}, new Object[] {0}); + assertTrue(isInstanceOf(constraints, GridConstraints.class.getName())); + + assertEquals(1, invokeMethod(constraints, "getColSpan")); + assertEquals(1, invokeMethod(constraints, "getRowSpan")); } public void testIntProperty() throws Exception { @@ -341,7 +417,7 @@ public class AsmCodeGeneratorTest extends TestCase { File.separatorChar + "formEmbedding" + File.separatorChar + "Ideadev14081" + File.separatorChar; AsmCodeGenerator embeddedClassGenerator = initCodeGenerator("Embedded.form", "Embedded", testDataPath); byte[] embeddedPatchedData = getVerifiedPatchedData(embeddedClassGenerator); - myClassLoader.doDefineClass("Embedded", embeddedPatchedData); + myClassFinder.addClassDefinition("Embedded", embeddedPatchedData); myNestedFormLoader.registerNestedForm("Embedded.form", testDataPath + "Embedded.form"); AsmCodeGenerator mainClassGenerator = initCodeGenerator("Main.form", "Main", testDataPath); byte[] mainPatchedData = getVerifiedPatchedData(mainClassGenerator); @@ -352,30 +428,34 @@ public class AsmCodeGeneratorTest extends TestCase { fos.close(); */ - final Class mainClass = myClassLoader.doDefineClass("Main", mainPatchedData); + myClassFinder.addClassDefinition("Main", mainPatchedData); + final Class mainClass = myClassFinder.getLoader().loadClass("Main"); Object instance = mainClass.newInstance(); assert instance != null : mainClass; } - private static class MyClassLoader extends ClassLoader { - private final byte[] myTestProperties = Charset.defaultCharset().encode(TEST_PROPERTY_CONTENT).array(); + private static class MyClassFinder extends InstrumentationClassFinder { private static final String TEST_PROPERTY_CONTENT = "test=Test Value\nmnemonic=Mne&monic"; + private final byte[] myTestProperties = Charset.defaultCharset().encode(TEST_PROPERTY_CONTENT).array(); + private final Map myClassData = new HashMap(); - public MyClassLoader(ClassLoader parent) { - super(parent); + private MyClassFinder(URL[] platformUrls, URL[] classpathUrls) { + super(platformUrls, classpathUrls); } - public Class doDefineClass(String name, byte[] data) { - return defineClass(name, data, 0, data.length); + public void addClassDefinition(String name, byte[] bytes) { + myClassData.put(name.replace('.', '/'), bytes); } - @Override - public Class loadClass(String name) throws ClassNotFoundException { - return super.loadClass(name); + protected InputStream lookupClassBeforeClasspath(String internalClassName) { + final byte[] bytes = myClassData.get(internalClassName); + if (bytes != null) { + return new ByteArrayInputStream(bytes); + } + return null; } - @Override - public InputStream getResourceAsStream(String name) { + public InputStream getResourceAsStream(String name) throws IOException { if (name.equals("TestProperties.properties")) { return new ByteArrayInputStream(myTestProperties, 0, TEST_PROPERTY_CONTENT.length()); } From 72d4d654ac58e617585fb21ce93a9956e2dec1e0 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 28 Mar 2012 22:06:35 +0200 Subject: [PATCH 51/84] remove zombie-module --- .idea/modules.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/.idea/modules.xml b/.idea/modules.xml index 18bb3a5c3d05..745b7901ffa3 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -81,7 +81,6 @@ - From d910983ba1c782b83a62c0258dba4e9f568a061d Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 28 Mar 2012 22:14:32 +0200 Subject: [PATCH 52/84] rename notNull->instrumentation-util --- .idea/artifacts/jps.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.idea/artifacts/jps.xml b/.idea/artifacts/jps.xml index dfbf48d9121b..50928bde9a11 100644 --- a/.idea/artifacts/jps.xml +++ b/.idea/artifacts/jps.xml @@ -11,7 +11,7 @@ - + From b8657935585f6c80b90c3e15d8b1be750158bb0d Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 29 Mar 2012 00:42:40 +0200 Subject: [PATCH 53/84] fix NPE --- .../src/org/jetbrains/jps/client/SimpleProtobufClient.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java index 8c762adf18b8..19544249f0c5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java +++ b/jps/jps-builders/src/org/jetbrains/jps/client/SimpleProtobufClient.java @@ -34,7 +34,7 @@ public class SimpleProtobufClient { private final AtomicReference myState = new AtomicReference(State.DISCONNECTED); protected final ChannelPipelineFactory myPipelineFactory; protected final ChannelFactory myChannelFactory; - protected ChannelFuture myConnectFuture; + protected volatile ChannelFuture myConnectFuture; private final ProtobufClientMessageHandler myMessageHandler; public SimpleProtobufClient(final MessageLite msgDefaultInstance, final AsyncTaskExecutor asyncExec, final UUIDGetter uuidGetter) { @@ -146,8 +146,9 @@ public class SimpleProtobufClient { public final RequestFuture sendMessage(final UUID messageId, MessageLite message, @Nullable final T responseHandler, @Nullable final RequestFuture.CancelAction cancelAction) { final RequestFuture requestFuture = new RequestFuture(responseHandler, messageId, cancelAction); myMessageHandler.registerFuture(messageId, requestFuture); - final Channel channel = myConnectFuture.getChannel(); - if (channel.isConnected()) { + final ChannelFuture connectFuture = myConnectFuture; + final Channel channel = connectFuture != null? connectFuture.getChannel() : null; + if (channel != null && channel.isConnected()) { Channels.write(channel, message).addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { From 9bf671aa81d41ceaf9fa7199aff1b65f7e655181 Mon Sep 17 00:00:00 2001 From: "kirill.safonov" Date: Thu, 29 Mar 2012 11:58:39 +0400 Subject: [PATCH 54/84] IDEA Flex projects conversion: more intelligent Flex libraries detection --- .../src/com/intellij/conversion/ConversionContext.java | 2 ++ .../intellij/conversion/impl/ConversionContextImpl.java | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java b/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java index 769a71783136..6b6f39b78565 100644 --- a/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java +++ b/platform/lang-impl/src/com/intellij/conversion/ConversionContext.java @@ -64,4 +64,6 @@ public interface ConversionContext { ProjectLibrariesSettings getProjectLibrariesSettings() throws CannotConvertException; + @NotNull + String expandPath(@NotNull String path); } diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java index ed0e38983de7..21b27fc5a113 100644 --- a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java @@ -159,6 +159,13 @@ public class ConversionContextImpl implements ConversionContext { return map; } + @Override + @NotNull + public String expandPath(@NotNull String path) { + ExpandMacroToPathMap map = createExpandMacroMap(null); + return map.substitute(path, SystemInfo.isFileSystemCaseSensitive); + } + @NotNull public String collapsePath(@NotNull String path) { ReplacePathToMacroMap map = createCollapseMacroMap(PathMacrosImpl.PROJECT_DIR_MACRO_NAME, myProjectBaseDir); From a4f3fc20a705eaaa98a58ee440e63881f085aa08 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Mar 2012 10:48:48 +0200 Subject: [PATCH 55/84] recent files in pinned mode --- .../com/intellij/ide/actions/Switcher.java | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 757c5a9d194a..5c633a0048b6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -278,11 +278,27 @@ public class Switcher extends AnAction implements DumbAware { for (Pair pair : editorManager.getSelectionHistory()) { editors.add(new FileInfo(pair.first, pair.second)); } - if (editors.size() < 2) { + if (editors.size() < 2 || isPinnedMode()) { + if (isPinnedMode() && editors.size() > 1) { + filesData.addAll(editors); + } final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles()); - final int len = Math.min(toolWindows.getModel().getSize(), Math.max(editors.size(), recentFiles.length)); + final int maxFiles = Math.max(editors.size(), recentFiles.length); + final int len = isPinnedMode() ? maxFiles : Math.min(toolWindows.getModel().getSize(), maxFiles); for (int i = 0; i < len; i++) { - filesData.add(new FileInfo(recentFiles[i], null)); + final FileInfo info = new FileInfo(recentFiles[i], null); + boolean add = true; + if (isPinnedMode()) { + for (FileInfo fileInfo : filesData) { + if (fileInfo.first.equals(info.first)) { + add = false; + break; + } + } + } + if (add) { + filesData.add(info); + } } if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) { filesData.add(0, editors.get(0)); @@ -393,7 +409,7 @@ public class Switcher extends AnAction implements DumbAware { } }).createPopup(); - if (!isAutoHide()) { + if (isPinnedMode()) { new AnAction(null, null, null) { @Override public void actionPerformed(AnActionEvent e) { @@ -781,6 +797,10 @@ public class Switcher extends AnAction implements DumbAware { return UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; } + private static boolean isPinnedMode() { + return !isAutoHide(); + } + private static class VirtualFilesRenderer extends ColoredListCellRenderer { private final Project myProject; private final SpeedSearchBase mySearch; From 24d2eeb3d09d4461fe042b6fc4aa4652cb0ae098 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 19:41:18 +0200 Subject: [PATCH 56/84] service to detect java version; highlight access to private class members according to java version used (IDEA-83045) --- .../impl/analysis/GenericsHighlightUtil.java | 3 +- .../projectRoots/JavaVersionServiceImpl.java | 29 ++++++++++++++ .../openapi/projectRoots/JavaSdkVersion.java | 15 ------- .../projectRoots/JavaVersionService.java | 34 ++++++++++++++++ .../intellij/core/JavaCoreEnvironment.java | 3 ++ .../impl/source/resolve/JavaResolveUtil.java | 23 +++++++---- .../TypeParameterBoundVisibility.java | 9 +++++ .../TypeParameterBoundVisibilityJdk14.java | 9 +++++ .../daemon/GenericsHighlightingTest.java | 13 ++++++- .../projectRoots/JavaSdkVersionUtil.java | 39 +++++++++++++++++++ resources/src/META-INF/IdeaPlugin.xml | 3 ++ 11 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java rename java/{openapi => java-psi-api}/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java (77%) create mode 100644 java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java create mode 100644 java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 4b7f8ce86cda..be5894779a33 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaSdkVersionUtil; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; @@ -508,7 +509,7 @@ public class GenericsHighlightUtil { final PsiType retErasure2 = TypeConversionUtil.erasure(superMethod.getReturnType()); boolean differentReturnTypeErasure = !Comparing.equal(retErasure1, retErasure2); - if (checkEqualsSuper && JavaSdkVersion.isAtLeast(checkMethod, JavaSdkVersion.JDK_1_7)) { + if (checkEqualsSuper && JavaSdkVersionUtil.isAtLeast(checkMethod, JavaSdkVersion.JDK_1_7)) { if (retErasure1 != null && retErasure2 != null) { differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2); } else { diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java new file mode 100644 index 000000000000..366a0b870404 --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2012 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.projectRoots; + +import com.intellij.psi.PsiElement; + +/** + * User: anna + * Date: 3/28/12 + */ +public class JavaVersionServiceImpl extends JavaVersionService { + @Override + public boolean isAtLeast(PsiElement element, JavaSdkVersion version) { + return JavaSdkVersionUtil.isAtLeast(element, version); + } +} diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java similarity index 77% rename from java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java rename to java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 2d7e6629ad3b..8d3ff5daaf60 100644 --- a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -15,11 +15,7 @@ */ package com.intellij.openapi.projectRoots; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; -import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -75,15 +71,4 @@ public enum JavaSdkVersion { ); } - public static boolean isAtLeast(PsiElement element, JavaSdkVersion minVersion) { - final Module module = ModuleUtil.findModuleForPsiElement(element); - if (module != null) { - final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); - if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { - final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk); - return version != null && version.isAtLeast(minVersion); - } - } - return false; - } } diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java new file mode 100644 index 000000000000..b1573f95da60 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2012 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. + */ + +/* + * @author max + */ +package com.intellij.openapi.projectRoots; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiUtil; + +public class JavaVersionService { + public static JavaVersionService getInstance() { + return ServiceManager.getService(JavaVersionService.class); + } + + public boolean isAtLeast(PsiElement element, JavaSdkVersion version) { + return PsiUtil.getLanguageLevel(element).isAtLeast(version.getMaxLanguageLevel()); + } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java index 6c2a98db24b7..d6f0e06de710 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java @@ -24,6 +24,8 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.lang.java.JavaParserDefinition; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.vfs.VirtualFile; @@ -86,6 +88,7 @@ public class JavaCoreEnvironment extends CoreEnvironment { myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl()); myApplication.registerService(JavaDirectoryService.class, new CoreJavaDirectoryService()); + myApplication.registerService(JavaVersionService.class, new JavaVersionService()); } public void addToClasspath(File path) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index df49e326cf5e..9d927c6832a4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -19,6 +19,8 @@ */ package com.intellij.psi.impl.source.resolve; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.javadoc.PsiDocComment; @@ -160,15 +162,20 @@ public class JavaResolveUtil { private static PsiClass getTopLevelClass(@NotNull PsiElement place, PsiClass memberClass) { PsiClass lastClass = null; + Boolean isAtLeast17 = null; for (PsiElement placeParent = place; placeParent != null; placeParent = placeParent.getContext()) { - if (placeParent instanceof PsiClass && - !(placeParent instanceof PsiAnonymousClass) && - !(placeParent instanceof PsiTypeParameter)) { - PsiClass aClass = (PsiClass)placeParent; - - if (memberClass != null && aClass.isInheritor(memberClass, true)) return aClass; - - lastClass = aClass; + if (placeParent instanceof PsiClass && !(placeParent instanceof PsiAnonymousClass)) { + final boolean isTypeParameter = placeParent instanceof PsiTypeParameter; + if (isTypeParameter && isAtLeast17 == null) { + isAtLeast17 = JavaVersionService.getInstance().isAtLeast(place, JavaSdkVersion.JDK_1_7); + } + if (!isTypeParameter || (isAtLeast17 != null && isAtLeast17)) { + PsiClass aClass = (PsiClass)placeParent; + + if (memberClass != null && aClass.isInheritor(memberClass, true)) return aClass; + + lastClass = aClass; + } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java new file mode 100644 index 000000000000..82ab1a7f8cdf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java @@ -0,0 +1,9 @@ +class A { + private int value = 1; + + static class B { + void print(T t) { + System.out.println(t.value); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java new file mode 100644 index 000000000000..ce2e57ded675 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java @@ -0,0 +1,9 @@ +class A { + private int value = 1; + + static class B { + void print(T t) { + System.out.println(t.value); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index af5988b5798e..cb955b02e898 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -32,7 +32,16 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { @Override protected void setUp() throws Exception { super.setUp(); - LanguageLevel level = getTestName(false).contains("Level6") ? LanguageLevel.JDK_1_6 : LanguageLevel.JDK_1_5; + LanguageLevel level; + final String testName = getTestName(false); + if (testName.contains("Level17")) { + level = LanguageLevel.JDK_1_7; + } else if (testName.contains("Level6")) { + level = LanguageLevel.JDK_1_6; + } + else { + level = LanguageLevel.JDK_1_5; + } LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(level); } @@ -107,6 +116,8 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testPrivateInnerClassRef() throws Exception { doTest(false); } public void testWideningCastToTypeParam() throws Exception { doTest(false); } public void testCapturedWildcardAssignments() throws Exception { doTest(false);} + public void testTypeParameterBoundVisibility() throws Exception { doTest(false);} + public void testTypeParameterBoundVisibilityJdk14() throws Exception { doTest(false);} public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java new file mode 100644 index 000000000000..859e269fbd1b --- /dev/null +++ b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2012 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.projectRoots; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.psi.PsiElement; + +/** + * User: anna + * Date: 3/28/12 + */ +public class JavaSdkVersionUtil { + public static boolean isAtLeast(PsiElement element, JavaSdkVersion minVersion) { + final Module module = ModuleUtil.findModuleForPsiElement(element); + if (module != null) { + final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { + final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk); + return version != null && version.isAtLeast(minVersion); + } + } + return false; + } +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e30a42bfee3b..1dfda1b79956 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -297,6 +297,9 @@ + + From 2f4ae6607399ba89628807a6405b1a166c48ac9c Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 20:01:45 +0200 Subject: [PATCH 57/84] do not raise a conflict for a synthetic methods (e.g. Enum.values()) --- .../intellij/refactoring/util/RefactoringConflictsUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java index cbb81cdc07ac..d5f6b4414ff3 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java @@ -22,6 +22,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchScopeUtil; import com.intellij.psi.search.searches.ReferencesSearch; @@ -241,7 +242,8 @@ public class RefactoringConflictsUtil { if (resolved != null && !reported.contains(resolved) && !CommonRefactoringUtil.isAncestor(resolved, scopes) && - !PsiSearchScopeUtil.isInScope(resolveScope, resolved)) { + !PsiSearchScopeUtil.isInScope(resolveScope, resolved) && + !(resolved instanceof LightElement)) { final String scopeDescription = RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(reference), true); final String message = RefactoringBundle.message("0.referenced.in.1.will.not.be.accessible.in.module.2", RefactoringUIUtil.getDescription(resolved, true), From b746d8a74f1a61c299bae27baddef1e201abd8da Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 27 Mar 2012 12:12:42 +0400 Subject: [PATCH 58/84] testing lockProfile() (cherry picked from commit df99c3f) --- .../codeInspection/InspectionProfileTest.java | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java index c2655b28e60e..c1ff86e4208a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java @@ -15,8 +15,8 @@ */ package com.intellij.codeInspection; -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.ex.InspectionToolRegistrar; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInspection.ex.*; import com.intellij.openapi.util.JDOMUtil; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.testFramework.LightIdeaTestCase; @@ -25,6 +25,8 @@ import org.jdom.Element; import org.jdom.JDOMException; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import static com.intellij.testFramework.PlatformTestUtil.assertElementsEqual; @@ -171,4 +173,51 @@ public class InspectionProfileTest extends LightIdeaTestCase { profile.writeExternal(copy); assertElementsEqual(element, copy); } + + public void testLockProfile() throws Exception { + + final List list = new ArrayList(); + list.add(createTool("foo")); + + InspectionToolRegistrar registrar = new InspectionToolRegistrar(null) { + @Override + public List createTools() { + LocalInspectionEP foo = new LocalInspectionEP(); + foo.shortName = "foo"; + return list; + } + }; + + InspectionProfileImpl profile = new InspectionProfileImpl("Foo", registrar, InspectionProfileManager.getInstance()); + profile.setBaseProfile(null); + List tools = profile.getAllTools(); + assertEquals(1, tools.size()); + ModifiableModel model = profile.getModifiableModel(); + model.lockProfile(true); + model.commit(); + Element element = new Element("element"); + profile.writeExternal(element); + + list.add(createTool("bar")); + + profile = new InspectionProfileImpl("Foo", registrar, InspectionProfileManager.getInstance()); + profile.readExternal(element); + + profile.setBaseProfile(null); + tools = profile.getAllTools(); + assertEquals(2, tools.size()); + + assertTrue(profile.isProfileLocked()); + assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("bar"))); + } + + private static LocalInspectionToolWrapper createTool(String s) { + LocalInspectionEP foo = new LocalInspectionEP(); + foo.shortName = s; + foo.displayName = s; + foo.groupDisplayName = s; + foo.level = "ERROR"; + foo.enabledByDefault = true; + return new LocalInspectionToolWrapper(foo); + } } From e207c327a0b5f94642a8ba97d4e6d3a020b39304 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 27 Mar 2012 12:12:53 +0400 Subject: [PATCH 59/84] displaying mnemonics fixed for IdeaTitledBorder (actually they do not work here) (cherry picked from commit 591c2cf) --- .../src/com/intellij/ui/border/IdeaTitledBorder.java | 9 ++++++++- .../src/com/intellij/util/ui/DialogUtil.java | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java b/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java index 4d5cf2d20b6b..f1f86b754ab1 100644 --- a/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java +++ b/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java @@ -1,6 +1,7 @@ package com.intellij.ui.border; import com.intellij.ui.TitledSeparator; +import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -20,19 +21,25 @@ public class IdeaTitledBorder extends TitledBorder { super(title); titledSeparator = new TitledSeparator(title); titledSeparator.setText(title); + DialogUtil.registerMnemonic(titledSeparator.getLabel(), null); this.outsideInsets = new Insets(insets.top, insets.left, insets.bottom, insets.right); this.insideInsets = new Insets(TitledSeparator.BOTTOM_INSET, indent, 0, 0); } + @Override + public void setTitle(String title) { + super.setTitle(title); + titledSeparator.setText(title); + } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { int labelX = x + outsideInsets.left; int labelY = y + outsideInsets.top; TitledSeparator titledSeparator = getTitledSeparator(c); - titledSeparator.setText(title); JLabel label = titledSeparator.getLabel(); Dimension labelSize = label.getPreferredSize(); label.setSize(labelSize); diff --git a/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java b/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java index 27f0ac706660..6a04e529ffaa 100644 --- a/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java @@ -16,6 +16,7 @@ package com.intellij.util.ui; import com.intellij.ide.ui.UISettings; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -66,7 +67,7 @@ public class DialogUtil{ } } - public static void registerMnemonic(JLabel label, JComponent target) { + public static void registerMnemonic(JLabel label, @Nullable JComponent target) { registerMnemonic(label, target, UIUtil.MNEMONIC); } @@ -76,7 +77,7 @@ public class DialogUtil{ * @param mn mnemonic char * @since 11.0 */ - public static void registerMnemonic(JLabel label, JComponent target, char mn) { + public static void registerMnemonic(JLabel label, @Nullable JComponent target, char mn) { String text = label.getText(); if (text != null) { final StringBuilder realText = new StringBuilder(text.length()); From 61fb82bc94e5812f2380be081b3d68d37e136f47 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 27 Mar 2012 13:07:14 +0400 Subject: [PATCH 60/84] testing GlobalInspectionContextImpl --- .../codeInspection/InspectionProfileTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java index c1ff86e4208a..bb012a5b2665 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java @@ -16,6 +16,7 @@ package com.intellij.codeInspection; import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.ex.*; import com.intellij.openapi.util.JDOMUtil; import com.intellij.profile.codeInspection.InspectionProfileManager; @@ -27,6 +28,7 @@ import org.jdom.JDOMException; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static com.intellij.testFramework.PlatformTestUtil.assertElementsEqual; @@ -211,6 +213,18 @@ public class InspectionProfileTest extends LightIdeaTestCase { assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("bar"))); } + public void testGlobalInspectionContext() throws Exception { + InspectionProfileImpl profile = new InspectionProfileImpl("Foo"); + profile.disableAllTools(); + profile.enableTool(new UnusedDeclarationInspection().getShortName()); + + GlobalInspectionContextImpl context = ((InspectionManagerEx)InspectionManager.getInstance(getProject())).createNewGlobalContext(false); + context.setExternalProfile(profile); + context.initializeTools(new ArrayList(), new ArrayList(), new ArrayList()); + Map tools = context.getTools(); + assertEquals(1, tools.size()); + } + private static LocalInspectionToolWrapper createTool(String s) { LocalInspectionEP foo = new LocalInspectionEP(); foo.shortName = s; From 0380bb928280f752e554b58c4a737cbe9a61f366 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 29 Mar 2012 13:27:13 +0400 Subject: [PATCH 61/84] IDEA-70554 HTML tags not allowed for XHTML Mobile 1.2 contexts for recursive entity resolving --- .../intellij/javaee/InternalResourceProvider.java | 2 ++ .../psi/impl/source/xml/XmlEntityDeclImpl.java | 3 ++- xml/impl/src/com/intellij/xml/util/XmlUtil.java | 12 ++++-------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java index 9c5a4d4ee306..8706f9f0b8a2 100644 --- a/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java +++ b/xml/impl/src/com/intellij/javaee/InternalResourceProvider.java @@ -55,6 +55,8 @@ public class InternalResourceProvider implements StandardResourceProvider{ impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile10-flat.dtd", "xhtml-mobile/xhtml-mobile10-flat.dtd"); impl.addInternalResource("http://www.wapforum.org/DTD/xhtml-mobile12.dtd", "xhtml-mobile/xhtml-mobile12.dtd"); + impl.addInternalResource("http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd", "xhtml-mobile/xhtml-mobile12.dtd"); + // svg and mathML impl.addIgnoredResource(HtmlUtil.MATH_ML_NAMESPACE); impl.addIgnoredResource(HtmlUtil.SVG_NAMESPACE); diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java index c64803b27d2e..a87b5905ddf5 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlEntityDeclImpl.java @@ -105,7 +105,8 @@ public class XmlEntityDeclImpl extends XmlElementImpl implements XmlEntityDecl, } public PsiElement parse(PsiFile baseFile, int context, final XmlEntityRef originalElement) { - PsiElement dependsOnElement = getValueElement(baseFile); + PsiElement dep = XmlElement.DEPENDING_ELEMENT.get(getParent()); + PsiElement dependsOnElement = getValueElement(dep instanceof PsiFile ? (PsiFile)dep : baseFile); String value = null; if (dependsOnElement instanceof XmlAttributeValue) { XmlAttributeValue attributeValue = (XmlAttributeValue)dependsOnElement; diff --git a/xml/impl/src/com/intellij/xml/util/XmlUtil.java b/xml/impl/src/com/intellij/xml/util/XmlUtil.java index 04d5d4d73ed4..da8f6f012152 100644 --- a/xml/impl/src/com/intellij/xml/util/XmlUtil.java +++ b/xml/impl/src/com/intellij/xml/util/XmlUtil.java @@ -55,7 +55,10 @@ import com.intellij.psi.impl.source.xml.XmlEntityRefImpl; import com.intellij.psi.scope.processor.FilterElementProcessor; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.*; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.*; import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; @@ -632,14 +635,7 @@ public class XmlUtil { if (element instanceof XmlEntityRef) { XmlEntityRef ref = (XmlEntityRef)element; - //if ("Number.datatype".equals(ref.getText().substring(1, ref.getTextLength() - 1))) { - // int a = 1; - //} PsiElement newElement = parseEntityRef(targetFile, ref, true); - //if (newElement == null) { - // System.out.println("No image for :" + ref.getText()); - // return true; - //} while (newElement != null) { if (!processElement(newElement, deepFlag, wideFlag, processIncludes)) return false; From ebc10c7cd251346788e0c2fd822675c7e3c2b471 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 29 Mar 2012 13:38:05 +0400 Subject: [PATCH 62/84] lazy InspectionTool initialization --- .../javaDoc/JavaDocLocalInspection.java | 2 - .../util/SpecialAnnotationsUtil.java | 4 -- .../codeInspection/ModifiableModel.java | 5 +- .../codeInspection/ex/Descriptor.java | 42 +++++++++----- .../ex/GlobalInspectionContextImpl.java | 3 +- .../ex/InspectionProfileImpl.java | 49 ++++++---------- .../intellij/codeInspection/ex/ToolsImpl.java | 58 ++++++++++--------- .../ui/InspectionConfigTreeNode.java | 33 +++++++++-- .../ui/InspectionsConfigTreeRenderer.java | 2 +- .../ui/SingleInspectionProfilePanel.java | 55 ++++++++---------- .../ui/actions/AddScopeAction.java | 5 +- .../openapi/util/NotNullLazyValue.java | 4 ++ .../inspection/DependsOnGroupsInspection.java | 3 - ...ddCustomTagOrAttributeIntentionAction.java | 2 - ...dHtmlTagOrAttributeToCustomsIntention.java | 2 - 15 files changed, 138 insertions(+), 131 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java index ee8959c4efab..e9963add3b43 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java @@ -5,7 +5,6 @@ package com.intellij.codeInspection.javaDoc; import com.intellij.ExtensionPoints; import com.intellij.codeInsight.CodeInsightUtil; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; @@ -1176,7 +1175,6 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); //correct save settings - ((ModifiableModel)inspectionProfile).isProperSetting(HighlightDisplayKey.find(SHORT_NAME)); InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile); //TODO lesya diff --git a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java index 2d89664d9568..e1ce6732f694 100644 --- a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java +++ b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java @@ -16,14 +16,11 @@ package com.intellij.codeInspection.util; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; import com.intellij.ide.DataManager; import com.intellij.ide.util.ClassFilter; import com.intellij.ide.util.TreeClassChooser; @@ -209,7 +206,6 @@ public class SpecialAnnotationsUtil { Collections.sort(targetList); final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); //correct save settings - ((InspectionProfileImpl)inspectionProfile).isProperSetting(HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME)); //TODO lesya InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile); diff --git a/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java b/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java index 4bbd1f3aaae2..d6c712357565 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java +++ b/platform/lang-api/src/com/intellij/codeInspection/ModifiableModel.java @@ -54,8 +54,11 @@ public interface ModifiableModel extends Profile { void setModified(final boolean toolsSettingsChanged); + @Deprecated boolean isProperSetting(HighlightDisplayKey key); + boolean isProperSetting(String toolId); + void resetToBase(); void resetToEmpty(); @@ -66,8 +69,6 @@ public interface ModifiableModel extends Profile { void copyFrom(InspectionProfile profile); - boolean isDefault(); - void setEditable(String toolDisplayName); void save() throws IOException; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java index a9b2ce6a04e9..8f3d92c65875 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/Descriptor.java @@ -18,14 +18,13 @@ package com.intellij.codeInspection.ex; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.search.scope.packageSet.NamedScope; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * User: anna @@ -35,26 +34,20 @@ public class Descriptor { private final String myText; private final String[] myGroup; private final HighlightDisplayKey myKey; - - private final Element myConfig; + + private Element myConfig; private final InspectionProfileEntry myTool; private final HighlightDisplayLevel myLevel; private boolean myEnabled = false; private final NamedScope myScope; private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.Descriptor"); private final ScopeToolState myState; + private final InspectionProfileImpl myInspectionProfile; - public Descriptor(ScopeToolState pair, InspectionProfile inspectionProfile) { + public Descriptor(ScopeToolState pair, InspectionProfileImpl inspectionProfile) { myState = pair; + myInspectionProfile = inspectionProfile; final InspectionProfileEntry tool = pair.getTool(); - @NonNls Element config = new Element("options"); - try { - tool.writeSettings(config); - } - catch (WriteExternalException e) { - LOG.error(e); - } - myConfig = config; myText = tool.getDisplayName(); final String[] groupPath = tool.getGroupPath(); myGroup = groupPath.length == 0 ? new String[]{InspectionProfileEntry.GENERAL_GROUP_NAME} : groupPath; @@ -100,8 +93,7 @@ public class Descriptor { return myLevel; } - - + @Nullable public Element getConfig() { return myConfig; } @@ -110,11 +102,31 @@ public class Descriptor { return myTool; } + @Nullable public String loadDescription() { + if (myConfig == null) { + myConfig = createConfigElement(getTool()); + } + if (!(myTool instanceof InspectionTool)) return null; return myTool.loadDescription(); } + public InspectionProfileImpl getInspectionProfile() { + return myInspectionProfile; + } + + public static Element createConfigElement(InspectionProfileEntry tool) { + Element element = new Element("options"); + try { + tool.writeSettings(element); + } + catch (WriteExternalException e) { + LOG.error(e); + } + return element; + } + public String[] getGroup() { return myGroup; } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index ac35d14d2cc4..d6febddfd9e2 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -631,8 +631,7 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G } protected List getUsedTools() { - final InspectionProfileImpl profile = new InspectionProfileImpl((InspectionProfileImpl)getCurrentProfile()); - return profile.getAllEnabledInspectionTools(myProject); + return ((InspectionProfileImpl)getCurrentProfile()).getAllEnabledInspectionTools(myProject); } private void classifyTool(List outGlobalTools, diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java index 6cbbba6a4c2b..b79c4338312d 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java @@ -32,6 +32,7 @@ import com.intellij.openapi.options.ExternalizableScheme; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.profile.ApplicationProfileManager; @@ -93,7 +94,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, private boolean myModified = false; private volatile boolean myInitialized; - public InspectionProfileImpl(InspectionProfileImpl inspectionProfile) { + private InspectionProfileImpl(@NotNull InspectionProfileImpl inspectionProfile) { super(inspectionProfile.getName()); myRegistrar = inspectionProfile.myRegistrar; @@ -168,20 +169,19 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, final ToolsImpl toolList1 = profile1.myTools.get(toolName); final ToolsImpl toolList2 = profile2.myTools.get(toolName); - return toolList1 == null && toolList2 == null || toolList1 != null && toolList2 != null && toolList1.equalTo(toolList2); + return Comparing.equal(toolList1, toolList2); } + @Override public boolean isProperSetting(HighlightDisplayKey key) { - final Map diffMap = getDisplayLevelMap(); - if (diffMap != null) { - final ToolsImpl tools = myBaseProfile.getTools(key.toString()); - final ToolsImpl currentTools = myTools.get(key.toString()); - if (tools != null && currentTools != null) { - diffMap.put(key.toString(), tools.equalTo(currentTools)); - } else { - diffMap.put(key.toString(), tools == currentTools); - } - return !diffMap.get(key.toString()).booleanValue(); + return isProperSetting(key.toString()); + } + + public boolean isProperSetting(String toolId) { + if (myBaseProfile != null) { + final ToolsImpl tools = myBaseProfile.getTools(toolId); + final ToolsImpl currentTools = myTools.get(toolId); + return !Comparing.equal(tools, currentTools); } return false; } @@ -376,27 +376,11 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, } } - public boolean isDefault() { - final Map map = getDisplayLevelMap(); - if (map != null) { - for (Boolean def : map.values()) { - if (!def.booleanValue()) return false; - } - } - return true; - } - public boolean isProfileLocked() { return myLockedProfile; } public void lockProfile(boolean isLocked) { - for (Tools toolList : myTools.values()) { - final String key = toolList.getShortName(); - if (isLocked) { - myDisplayLevelMap.put(key, Boolean.FALSE); - } - } myLockedProfile = isLocked; } @@ -490,16 +474,13 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, } myTools.put(tool.getShortName(), toolsList); } - if (mySource != null) { - copyToolsConfigurations(mySource, project); - } return true; } private HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key) { final ToolsImpl tools = getTools(key.toString()); LOG.assertTrue(tools != null, "profile name: " + myName + " base profile: " + (myBaseProfile != null ? myBaseProfile.getName() : "-") + " key: " + key); - return tools != null ? tools.getLevel() : HighlightDisplayLevel.WARNING; + return tools.getLevel(); } @NotNull @@ -807,4 +788,8 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, disableTool(entry.getShortName()); } } + + public String toString() { + return mySource == null ? getName() : getName() + " (copy)"; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java index 9e7285436365..9f1435366b3a 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java @@ -150,35 +150,40 @@ public class ToolsImpl implements Tools { final String enabledTool = toolElement.getAttributeValue(ENABLED_TAG); myDefaultState.setEnabled(enabledTool != null ? Boolean.parseBoolean(enabledTool) : isEnabled); final InspectionToolWrapper tool = (InspectionToolWrapper)myDefaultState.getTool(); - tool.readSettings(toolElement); + final List children = toolElement.getChildren(InspectionProfileImpl.SCOPE); - if (!children.isEmpty()) { - for (Object sO : children) { - final Element scopeElement = (Element)sO; - final String scopeName = scopeElement.getAttributeValue(InspectionProfileImpl.NAME); - if (scopeName != null) { - final NamedScopesHolder scopesHolder = profileManager.getScopesManager(); - NamedScope namedScope = null; - if (scopesHolder != null) { - namedScope = scopesHolder.getScope(scopeName); - } - final String errorLevel = scopeElement.getAttributeValue(InspectionProfileImpl.LEVEL_TAG); - final String enabledInScope = scopeElement.getAttributeValue(InspectionProfileImpl.ENABLED_TAG); - final InspectionProfileEntry copyTool = tool.createCopy(tool); - copyTool.readSettings(scopeElement); - HighlightDisplayLevel scopeLevel = errorLevel != null ? - HighlightDisplayLevel.find(((SeverityProvider)profileManager).getOwnSeverityRegistrar().getSeverity(errorLevel)) : null; - if (scopeLevel == null) { - scopeLevel = level; - } - if (namedScope != null) { - addTool(namedScope, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); - } else { - addTool(scopeName, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); - } + for (Object sO : children) { + final Element scopeElement = (Element)sO; + final String scopeName = scopeElement.getAttributeValue(InspectionProfileImpl.NAME); + if (scopeName != null) { + final NamedScopesHolder scopesHolder = profileManager.getScopesManager(); + NamedScope namedScope = null; + if (scopesHolder != null) { + namedScope = scopesHolder.getScope(scopeName); + } + final String errorLevel = scopeElement.getAttributeValue(InspectionProfileImpl.LEVEL_TAG); + final String enabledInScope = scopeElement.getAttributeValue(InspectionProfileImpl.ENABLED_TAG); + final InspectionProfileEntry copyTool = tool.createCopy(tool); + copyTool.readSettings(scopeElement); + HighlightDisplayLevel scopeLevel = errorLevel != null ? + HighlightDisplayLevel + .find(((SeverityProvider)profileManager).getOwnSeverityRegistrar().getSeverity(errorLevel)) + : null; + if (scopeLevel == null) { + scopeLevel = level; + } + if (namedScope != null) { + addTool(namedScope, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); + } + else { + addTool(scopeName, copyTool, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel); } } } + +// if (toolElement.getAttributes().size() > 4 || toolElement.getChildren().size() > children.size()) { + tool.readSettings(toolElement); +// } } public ScopeToolState addTool(String scopeName, InspectionProfileEntry tool, boolean enabled, HighlightDisplayLevel level) { @@ -386,7 +391,8 @@ public class ToolsImpl implements Tools { return myDefaultState.getLevel(); } - public boolean equalTo(ToolsImpl tools) { + public boolean equals(Object o) { + ToolsImpl tools = (ToolsImpl)o; if (myEnabled != tools.myEnabled) return false; if (getTools().size() != tools.getTools().size()) return false; for (int i = 0; i < getTools().size(); i++) { diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java index 339f0a2ae9bf..9b22317381e7 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionConfigTreeNode.java @@ -22,30 +22,45 @@ package com.intellij.profile.codeInspection.ui; import com.intellij.codeInspection.ex.Descriptor; import com.intellij.codeInspection.ex.ScopeToolState; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.psi.search.scope.packageSet.NamedScope; import com.intellij.ui.CheckedTreeNode; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class InspectionConfigTreeNode extends CheckedTreeNode { private ScopeToolState myState; private boolean myByDefault; private boolean myInspectionNode; - public boolean isProperSetting; + private final NotNullLazyValue myProperSetting = new NotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + Descriptor descriptor = getDesriptor(); + if (descriptor != null) return descriptor.getInspectionProfile().isProperSetting(descriptor.getTool().getShortName()); + for (int i = 0; i < getChildCount(); i++) { + InspectionConfigTreeNode node = (InspectionConfigTreeNode)getChildAt(i); + if (node.isProperSetting()) { + return true; + } + } + return false; + } + }; - public InspectionConfigTreeNode(Object userObject, ScopeToolState state, boolean byDefault, boolean properSetting, boolean inspectionNode) { + public InspectionConfigTreeNode(Object userObject, ScopeToolState state, boolean byDefault, boolean inspectionNode) { super(userObject); myState = state; myByDefault = byDefault; - isProperSetting = properSetting; myInspectionNode = inspectionNode; if (state != null) { setChecked(state.isEnabled()); } } - public InspectionConfigTreeNode(Descriptor descriptor, ScopeToolState state, boolean byDefault, boolean isEnabled, boolean properSetting, + public InspectionConfigTreeNode(Descriptor descriptor, ScopeToolState state, boolean byDefault, boolean isEnabled, boolean inspectionNode) { - this(descriptor, state, byDefault, properSetting, inspectionNode); + this(descriptor, state, byDefault, inspectionNode); setChecked(isEnabled); } @@ -85,4 +100,12 @@ public class InspectionConfigTreeNode extends CheckedTreeNode { public String getScopeName() { return myState != null ? myState.getScopeName() : null; } + + public boolean isProperSetting() { + return myProperSetting.getValue(); + } + + public void dropCache() { + myProperSetting.drop(); + } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java index 1fd982b5c461..dfacaad3b06d 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionsConfigTreeRenderer.java @@ -53,7 +53,7 @@ abstract class InspectionsConfigTreeRenderer extends CheckboxTree.CheckboxTreeCe final Color background = selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground(); UIUtil.changeBackGround(this, background); Color foreground = - selected ? UIUtil.getTreeSelectionForeground() : node.isProperSetting ? Color.BLUE : UIUtil.getTreeTextForeground(); + selected ? UIUtil.getTreeSelectionForeground() : node.isProperSetting() ? Color.BLUE : UIUtil.getTreeTextForeground(); @NonNls String text = null; int style = SimpleTextAttributes.STYLE_PLAIN; diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 3fd374b320bf..3010f8fa3d08 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -46,7 +46,6 @@ import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; import com.intellij.profile.ProfileManager; import com.intellij.profile.codeInspection.InspectionProfileManager; @@ -101,7 +100,7 @@ public class SingleInspectionProfilePanel extends JPanel { private JPanel myInspectionProfilePanel = null; private FilterComponent myProfileFilter; private final InspectionConfigTreeNode myRoot = - new InspectionConfigTreeNode(InspectionsBundle.message("inspection.root.node.title"), null, false, false, false); + new InspectionConfigTreeNode(InspectionsBundle.message("inspection.root.node.title"), null, false, false); private final Alarm myAlarm = new Alarm(); private boolean myModified = false; private Tree myTree; @@ -187,13 +186,8 @@ public class SingleInspectionProfilePanel extends JPanel { return false; } Element oldConfig = descriptor.getConfig(); - @NonNls Element newConfig = new Element("options"); - try { - tool.writeSettings(newConfig); - } - catch (WriteExternalException e) { - LOG.error(e); - } + if (oldConfig == null) return false; + Element newConfig = Descriptor.createConfigElement(tool); if (!JDOMUtil.areElementsEqual(oldConfig, newConfig)) { myAlarm.cancelAllRequests(); myAlarm.addRequest(new Runnable() { @@ -213,15 +207,15 @@ public class SingleInspectionProfilePanel extends JPanel { InspectionConfigTreeNode node = (InspectionConfigTreeNode)selectionPath.getLastPathComponent(); final Descriptor descriptor = node.getDesriptor(); if (descriptor != null) { - final boolean properSetting = mySelectedProfile.isProperSetting(descriptor.getKey()); - if (node.isProperSetting != properSetting) { + final boolean properSetting = mySelectedProfile.isProperSetting(descriptor.getKey().toString()); + if (node.isProperSetting() != properSetting) { myAlarm.cancelAllRequests(); myAlarm.addRequest(new Runnable() { public void run() { myTree.repaint(); } }, 300); - node.isProperSetting = properSetting; + node.dropCache(); updateUpHierarchy(node, (InspectionConfigTreeNode)node.getParent()); } } @@ -344,7 +338,7 @@ public class SingleInspectionProfilePanel extends JPanel { } @Override public void update(AnActionEvent e) { - e.getPresentation().setEnabled(myRoot.isProperSetting); + e.getPresentation().setEnabled(myRoot.isProperSetting()); } @Override @@ -611,7 +605,7 @@ public class SingleInspectionProfilePanel extends JPanel { mySelectedProfile.disableTool(toolShortName); } } - toolNode.isProperSetting = mySelectedProfile.isProperSetting(key); + toolNode.dropCache(); updateUpHierarchy(toolNode, (InspectionConfigTreeNode)toolNode.getParent()); } final TreePath path = new TreePath(toolNode.getPath()); @@ -622,7 +616,7 @@ public class SingleInspectionProfilePanel extends JPanel { private static void updateUpHierarchy(final InspectionConfigTreeNode node, final InspectionConfigTreeNode parent) { if (parent != null) { - parent.isProperSetting = node.isProperSetting || wasModified(parent); + parent.dropCache(); updateUpHierarchy(parent, (InspectionConfigTreeNode)parent.getParent()); } } @@ -630,7 +624,7 @@ public class SingleInspectionProfilePanel extends JPanel { private static boolean wasModified(InspectionConfigTreeNode node) { for (int i = 0; i < node.getChildCount(); i++) { final InspectionConfigTreeNode childNode = (InspectionConfigTreeNode)node.getChildAt(i); - if (childNode.isProperSetting) { + if (childNode.isProperSetting()) { return true; } } @@ -684,7 +678,7 @@ public class SingleInspectionProfilePanel extends JPanel { if (mySelectedProfile == null) return; myRoot.removeAllChildren(); myRoot.setChecked(false); - myRoot.isProperSetting = false; + myRoot.dropCache(); List> keySetList = new ArrayList>(); final Set quated = new HashSet(); if (filter != null && filter.length() > 0) { @@ -697,18 +691,17 @@ public class SingleInspectionProfilePanel extends JPanel { final List nonDefaultTools = mySelectedProfile.getNonDefaultTools(descriptor.getKey().toString()); final HighlightDisplayKey key = descriptor.getKey(); final boolean enabled = mySelectedProfile.isToolEnabled(key); - final boolean properSetting = mySelectedProfile.isProperSetting(key); boolean hasNonDefaultScope = nonDefaultTools != null && !nonDefaultTools.isEmpty(); - final InspectionConfigTreeNode node = new InspectionConfigTreeNode(descriptor, null, !hasNonDefaultScope, enabled, properSetting, !hasNonDefaultScope); - getGroupNode(myRoot, descriptor.getGroup(), properSetting).add(node); + final InspectionConfigTreeNode node = new InspectionConfigTreeNode(descriptor, null, !hasNonDefaultScope, enabled, !hasNonDefaultScope); + getGroupNode(myRoot, descriptor.getGroup()).add(node); if (hasNonDefaultScope) { for (ScopeToolState nonDefaultState : nonDefaultTools) { - node.add(new InspectionConfigTreeNode(new Descriptor(nonDefaultState, mySelectedProfile), nonDefaultState, false, properSetting, false)); + node.add(new InspectionConfigTreeNode(new Descriptor(nonDefaultState, mySelectedProfile), nonDefaultState, false, false)); } - node.add(new InspectionConfigTreeNode(descriptor, descriptor.getState(), true, properSetting, false)); + node.add(new InspectionConfigTreeNode(descriptor, descriptor.getState(), true, false)); } myRoot.setEnabled(myRoot.isEnabled() || enabled); - myRoot.isProperSetting |= properSetting; + myRoot.dropCache(); } if (filter != null && forceInclude && myRoot.getChildCount() == 0) { final Set filters = SearchableOptionsRegistrar.getInstance().getProcessedWords(filter); @@ -764,7 +757,7 @@ public class SingleInspectionProfilePanel extends JPanel { public void actionPerformed(ActionEvent e) { boolean toUpdate = mySelectedProfile.getErrorLevel(key, scope) != chooser.getLevel(); mySelectedProfile.setErrorLevel(key, chooser.getLevel(), node.isInspectionNode() || node.isByDefault() ? -1 : node.getParent().getIndex(node)); - if (toUpdate) node.isProperSetting = mySelectedProfile.isProperSetting(key); + if (toUpdate) node.dropCache(); } }); chooser.setLevel(mySelectedProfile.getErrorLevel(key, scope)); @@ -805,24 +798,23 @@ public class SingleInspectionProfilePanel extends JPanel { myOptionsPanel.repaint(); } - private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath, boolean properSetting) { + private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath) { InspectionConfigTreeNode currentRoot = root; for (final String group : groupPath) { - currentRoot = getGroupNode(currentRoot, group, properSetting); + currentRoot = getGroupNode(currentRoot, group); } return currentRoot; } - private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String group, boolean properSetting) { + private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String group) { final int childCount = root.getChildCount(); for (int i = 0; i < childCount; i++) { InspectionConfigTreeNode child = (InspectionConfigTreeNode)root.getChildAt(i); if (group.equals(child.getUserObject())) { - child.isProperSetting |= properSetting; return child; } } - InspectionConfigTreeNode child = new InspectionConfigTreeNode(group, null, false, properSetting, false); + InspectionConfigTreeNode child = new InspectionConfigTreeNode(group, null, false, false); root.add(child); return child; } @@ -1070,7 +1062,7 @@ public class SingleInspectionProfilePanel extends JPanel { private void updateErrorLevelUpInHierarchy(HighlightDisplayLevel level, boolean showOptionsAndDescriptorPanels, InspectionConfigTreeNode node) { - node.isProperSetting = false; + node.dropCache(); for (int j = 0; j < node.getChildCount(); j++) { final InspectionConfigTreeNode child = (InspectionConfigTreeNode)node.getChildAt(j); final Object userObject = child.getUserObject(); @@ -1080,7 +1072,6 @@ public class SingleInspectionProfilePanel extends JPanel { else { updateErrorLevelUpInHierarchy(level, showOptionsAndDescriptorPanels, child); } - node.isProperSetting |= child.isProperSetting; } } @@ -1088,7 +1079,7 @@ public class SingleInspectionProfilePanel extends JPanel { final boolean showOptionsAndDescriptorPanels, final HighlightDisplayLevel level) { final HighlightDisplayKey key = child.getDesriptor().getKey(); mySelectedProfile.setErrorLevel(key, level, child.isInspectionNode() || child.isByDefault() ? -1 : child.getParent().getIndex(child)); - child.isProperSetting = mySelectedProfile.isProperSetting(key); + child.dropCache(); if (showOptionsAndDescriptorPanels) { updateOptionsAndDescriptionPanel(new TreePath(child.getPath())); } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java index 67c9e658c90b..1a01b1e19629 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java @@ -20,7 +20,6 @@ */ package com.intellij.profile.codeInspection.ui.actions; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.ex.Descriptor; import com.intellij.codeInspection.ex.InspectionProfileImpl; @@ -97,9 +96,9 @@ public abstract class AddScopeAction extends AnAction { if (node.getChildCount() == 0) { node.add(new InspectionConfigTreeNode(descriptor, getSelectedProfile().getToolDefaultState(descriptor.getKey().getID()), true, true, false)); } - node.insert(new InspectionConfigTreeNode(addedDescriptor, scopeToolState, false, true, false), 0); + node.insert(new InspectionConfigTreeNode(addedDescriptor, scopeToolState, false, false), 0); node.setInspectionNode(false); - node.isProperSetting = getSelectedProfile().isProperSetting(HighlightDisplayKey.find(tool.getShortName())); + node.dropCache(); ((DefaultTreeModel)myTree.getModel()).reload(node); myTree.expandPath(new TreePath(node.getPath())); } diff --git a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java index 9c9390371f87..ea51d5f5ddc0 100644 --- a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java +++ b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java @@ -35,4 +35,8 @@ public abstract class NotNullLazyValue { } return myValue; } + + public void drop() { + myValue = null; + } } \ No newline at end of file diff --git a/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java b/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java index 5c8cac947f2d..b3565b8c2bb6 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java +++ b/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java @@ -15,9 +15,7 @@ */ package com.theoryinpractice.testng.inspection; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.*; -import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.LabeledComponent; @@ -171,7 +169,6 @@ public class DependsOnGroupsInspection extends BaseJavaLocalInspectionTool { final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); //correct save settings - ((InspectionProfileImpl)inspectionProfile).isProperSetting(HighlightDisplayKey.find(SHORT_NAME)); InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile); //TODO lesya /* diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java index 66c35bb6856d..faa61749ad05 100644 --- a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java +++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddCustomTagOrAttributeIntentionAction.java @@ -17,7 +17,6 @@ package com.intellij.codeInspection.htmlInspections; import com.intellij.CommonBundle; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ModifiableModel; @@ -79,7 +78,6 @@ public class AddCustomTagOrAttributeIntentionAction implements LocalQuickFix { final LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)model.getInspectionTool(myInspectionName, element); final HtmlUnknownTagInspection inspection = (HtmlUnknownTagInspection)wrapper.getTool(); inspection.addCustomPropertyName(myName); - model.isProperSetting(HighlightDisplayKey.find(myInspectionName)); try { model.commit(); } diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java index 18ae320ba9d2..9b8d73230b69 100644 --- a/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java +++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/AddHtmlTagOrAttributeToCustomsIntention.java @@ -17,7 +17,6 @@ package com.intellij.codeInspection.htmlInspections; import com.intellij.CommonBundle; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.ModifiableModel; @@ -80,7 +79,6 @@ public class AddHtmlTagOrAttributeToCustomsIntention implements IntentionAction final LocalInspectionToolWrapper wrapper = (LocalInspectionToolWrapper)model.getInspectionTool(myInspectionName, file); final XmlEntitiesInspection xmlEntitiesInspection = (XmlEntitiesInspection)wrapper.getTool(); xmlEntitiesInspection.setAdditionalEntries(myType, appendName(xmlEntitiesInspection.getAdditionalEntries(myType))); - model.isProperSetting(HighlightDisplayKey.find(myInspectionName));//update map with non-default settings try { model.commit(); } From 0700053f70a4d96b38eacd6d42e3cf4a69cbec8b Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 29 Mar 2012 14:10:13 +0400 Subject: [PATCH 63/84] IDEA-83645 Editor: Correct '`' (backtick) symbol drawing inside the editor 1. Checking if a font contains invalid glyphs on font info initialisation; 2. Ending painting iteration after the faulty glyphs (if any); --- .../application/impl/ApplicationImpl.java | 2 + .../openapi/editor/impl/EditorImpl.java | 11 +++- .../openapi/editor/impl/FontInfo.java | 60 ++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index ec3cb318914c..fa0f805fa22d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -73,6 +73,8 @@ import org.picocontainer.MutablePicoContainer; import javax.swing.*; import java.awt.*; +import java.io.BufferedInputStream; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; 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 9179a8ce4f7d..4e0e3c1d6ff9 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 @@ -2628,6 +2628,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int myCount = 0; @NotNull final FontInfo myFontType; + final boolean myHasBreakSymbols; final int spaceWidth; @Nullable private char[] myLastData; @@ -2635,6 +2636,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private CachedFontContent(@NotNull FontInfo fontInfo) { myFontType = fontInfo; spaceWidth = fontInfo.charWidth(' ', myEditorComponent); + myHasBreakSymbols = fontInfo.hasGlyphsToBreakDrawingIteration(); } private void flushContent(@NotNull Graphics g) { @@ -2666,7 +2668,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi final int lastCount = count - 1; final Color lastColor = color[lastCount]; if (_data == myLastData && _start == ends[lastCount] && (_color == null || lastColor == null || _color.equals(lastColor)) - && _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */) + && _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */ + && (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data[ends[lastCount] - 1]))) { ends[lastCount] = _end; if (lastColor == null) color[lastCount] = _color; @@ -3054,6 +3057,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myForceRefreshFont = true; } endX += charWidth; + + if (newFont.hasGlyphsToBreakDrawingIteration() && newFont.getSymbolsToBreakDrawingIteration().contains(c)) { + drawCharsCached(g, text, start, j + 1, x, y, fontType, fontColor); + x = endX; + start = j + 1; + } } if (!(x < clip.x && endX < clip.x || x > clip.x + clip.width && endX > clip.x + clip.width)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java index 9aaafa8a07b9..c7f7cbdc8d1c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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,14 +17,21 @@ package com.intellij.openapi.editor.impl; import gnu.trove.TIntHashSet; import org.intellij.lang.annotations.JdkConstants; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.image.BufferedImage; /** * @author max */ public class FontInfo { + + private final TIntHashSet mySymbolsToBreakDrawingIteration = new TIntHashSet(); + private final String myFamilyName; private final Font myFont; private final int mySize; @@ -32,12 +39,63 @@ public class FontInfo { private final TIntHashSet mySafeCharacters = new TIntHashSet(); private FontMetrics myFontMetrics = null; private final int[] charWidth = new int[128]; + private final boolean myHasGlyphsToBreakDrawingIteration; public FontInfo(final String familyName, final int size, @JdkConstants.FontStyle int style) { myFamilyName = familyName; mySize = size; myStyle = style; myFont = new Font(familyName, style, size); + + parseProblemGlyphs(); + myHasGlyphsToBreakDrawingIteration = !mySymbolsToBreakDrawingIteration.isEmpty(); + } + + private void parseProblemGlyphs() { + BufferedImage buffer = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB); + final Graphics graphics = buffer.getGraphics(); + if (!(graphics instanceof Graphics2D)) { + return; + } + final FontRenderContext context = ((Graphics2D)graphics).getFontRenderContext(); + char[] charBuffer = new char[1]; + for (char c = 0; c < 128; c++) { + if (!myFont.canDisplay(c)) { + continue; + } + charBuffer[0] = c; + final GlyphVector vector = myFont.createGlyphVector(context, charBuffer); + final float y = vector.getGlyphMetrics(0).getAdvanceY(); + if (Math.round(y) != 0) { + mySymbolsToBreakDrawingIteration.add(c); + } + } + } + + /** + * We've experienced a problem that particular symbols from particular font are represented really weird + * by the IJ editor (IDEA-83645). + *

+ * Eventually it was found out that outline font glyphs can have a 'y advance', i.e. instruction on how the subsequent + * glyphs location should be adjusted after painting the current glyph. In terms of java that means that such a problem + * glyph should be the last symbol at the {@link Graphics#drawChars(char[], int, int, int, int) text drawing iteration}. + *

+ * Hopefully, such glyphs are exceptions from the normal processing, so, this method allows to answer whether a font + * {@link #getFont() referenced} by the current object has such a glyph. + * + * @return true if the {@link #getFont() target font} has problem glyphs; false otherwise + */ + public boolean hasGlyphsToBreakDrawingIteration() { + return myHasGlyphsToBreakDrawingIteration; + } + + /** + * @return unicode symbols which glyphs {@link #hasGlyphsToBreakDrawingIteration() have problems} + * at the {@link #getFont() target font}. + */ + @NotNull + public TIntHashSet getSymbolsToBreakDrawingIteration() { + return mySymbolsToBreakDrawingIteration; } public boolean canDisplay(char c) { From 930c1fedb44757e3b5d4139ba36d6575ee7dff22 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 29 Mar 2012 12:18:06 +0200 Subject: [PATCH 64/84] Platform-independent detection of default UI font --- .../src/com/intellij/ide/ui/UISettings.java | 136 ++++++++---------- .../com/intellij/ide/ui/LafManagerImpl.java | 18 +-- .../com/intellij/util/SystemProperties.java | 17 +++ .../util/src/com/intellij/util/ui/UIUtil.java | 18 ++- 4 files changed, 99 insertions(+), 90 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java index f4175389bee6..705df1ef8530 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java @@ -26,8 +26,11 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.PlatformUtils; +import com.intellij.util.SystemProperties; +import com.intellij.util.ui.UIUtil; import com.intellij.util.xmlb.Accessor; import com.intellij.util.xmlb.SerializationFilter; import com.intellij.util.xmlb.XmlSerializerUtil; @@ -107,19 +110,15 @@ public class UISettings implements PersistentStateComponent, Exporta */ public static final int TABS_NONE = 0; - /** - * Invoked by reflection. - */ public UISettings() { - tweakPlatformDefaults(); myListenerList = new EventListenerList(); + tweakPlatformDefaults(); setSystemFontFaceAndSize(); } private void tweakPlatformDefaults() { // TODO: Make it pluggable if (PlatformUtils.isCidr()) { - //HIDE_TOOL_STRIPES = true; SHOW_MAIN_TOOLBAR = false; SHOW_ICONS_IN_MENUS = false; SHOW_MEMORY_INDICATOR = false; @@ -133,7 +132,7 @@ public class UISettings implements PersistentStateComponent, Exporta myListenerList.add(UISettingsListener.class, listener); } - public void addUISettingsListener(@NotNull final UISettingsListener listener, @NotNull Disposable parentDisposable){ + public void addUISettingsListener(@NotNull final UISettingsListener listener, @NotNull Disposable parentDisposable) { myListenerList.add(UISettingsListener.class,listener); Disposer.register(parentDisposable, new Disposable() { @Override @@ -146,7 +145,7 @@ public class UISettings implements PersistentStateComponent, Exporta /** * Notifies all registered listeners that UI settings has been changed. */ - public void fireUISettingsChanged(){ + public void fireUISettingsChanged() { UISettingsListener[] listeners= myListenerList.getListeners(UISettingsListener.class); for (UISettingsListener listener : listeners) { listener.uiSettingsChanged(this); @@ -166,29 +165,18 @@ public class UISettings implements PersistentStateComponent, Exporta return application != null ? getInstance() : new UISettings(); } - public void removeUISettingsListener(UISettingsListener listener){ + public void removeUISettingsListener(UISettingsListener listener) { myListenerList.remove(UISettingsListener.class,listener); } - private void setDefaultFontSettings() { - final Application application = ApplicationManager.getApplication(); - if (application == null) { - // we're the shadow settings - return; - } - FONT_FACE = SystemInfo.isLinux && application.isUnitTestMode() ? "Dialog.plain" : "Dialog"; - FONT_SIZE = 12; - } - - private static boolean isValidFont(final Font font){ + private static boolean isValidFont(final Font font) { try { - return - font.canDisplay('a') && - font.canDisplay('z') && - font.canDisplay('A') && - font.canDisplay('Z') && - font.canDisplay('0') && - font.canDisplay('1'); + return font.canDisplay('a') && + font.canDisplay('z') && + font.canDisplay('A') && + font.canDisplay('Z') && + font.canDisplay('0') && + font.canDisplay('1'); } catch (Exception e) { // JRE has problems working with the font. Just skip. @@ -196,30 +184,41 @@ public class UISettings implements PersistentStateComponent, Exporta } } - /** - * Under Win32 it's possible to determine face and size of default fount. - */ - private void setSystemFontFaceAndSize(){ - if(FONT_FACE == null || FONT_SIZE <= 0){ - if(SystemInfo.isWindows){ - //noinspection HardCodedStringLiteral - Font font=(Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font"); - if(font != null){ - FONT_FACE = font.getName(); - FONT_SIZE = font.getSize(); - }else{ - setDefaultFontSettings(); - } - }else{ // UNIXes go here - setDefaultFontSettings(); + private void setSystemFontFaceAndSize() { + if (FONT_FACE == null || FONT_SIZE <= 0) { + final Pair fontData = getSystemFontFaceAndSize(); + FONT_FACE = fontData.first; + FONT_SIZE = fontData.second; + } + } + + private static Pair getSystemFontFaceAndSize() { + final Pair fontData = UIUtil.getSystemFontData(); + if (fontData != null) { + return fontData; + } + + if (SystemInfo.isWindows) { + //noinspection HardCodedStringLiteral + final Font font = (Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font"); + if (font != null) { + return Pair.create(font.getName(), font.getSize()); } } + + return Pair.create("Dialog", 12); + } + + public static class FontFilter implements SerializationFilter { + public boolean accepts(Accessor accessor, Object bean) { + UISettings settings = (UISettings)bean; + return !hasDefaultFontSetting(settings); + } } private static boolean hasDefaultFontSetting(final UISettings settings) { - Font font=(Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font"); - return SystemInfo.isWindows && font != null && settings.FONT_FACE.equals(font.getName()) && settings.FONT_SIZE == font.getSize(); - + final Pair fontData = getSystemFontFaceAndSize(); + return fontData.first.equals(settings.FONT_FACE) && fontData.second.equals(settings.FONT_SIZE); } public UISettings getState() { @@ -230,28 +229,27 @@ public class UISettings implements PersistentStateComponent, Exporta XmlSerializerUtil.copyBean(object, this); // Check tab placement in editor - if( - EDITOR_TAB_PLACEMENT != TABS_NONE && - EDITOR_TAB_PLACEMENT != SwingConstants.TOP&& - EDITOR_TAB_PLACEMENT != SwingConstants.LEFT&& - EDITOR_TAB_PLACEMENT != SwingConstants.BOTTOM&& - EDITOR_TAB_PLACEMENT != SwingConstants.RIGHT - ){ - EDITOR_TAB_PLACEMENT=SwingConstants.TOP; + if (EDITOR_TAB_PLACEMENT != TABS_NONE && + EDITOR_TAB_PLACEMENT != SwingConstants.TOP && + EDITOR_TAB_PLACEMENT != SwingConstants.LEFT && + EDITOR_TAB_PLACEMENT != SwingConstants.BOTTOM && + EDITOR_TAB_PLACEMENT != SwingConstants.RIGHT) { + EDITOR_TAB_PLACEMENT = SwingConstants.TOP; } - // Check that alpha ration in in valid range - if(ALPHA_MODE_DELAY<0){ - ALPHA_MODE_DELAY=1500; + + // Check that alpha delay and ratio are valid + if (ALPHA_MODE_DELAY < 0) { + ALPHA_MODE_DELAY = 1500; } - if(ALPHA_MODE_RATIO< 0.0f ||ALPHA_MODE_RATIO>1.0f){ - ALPHA_MODE_RATIO=0.5f; + if (ALPHA_MODE_RATIO < 0.0f || ALPHA_MODE_RATIO > 1.0f) { + ALPHA_MODE_RATIO = 0.5f; } setSystemFontFaceAndSize(); - // 1. Sometimes system font cannot display standard ASCI symbols. If so we have + // 1. Sometimes system font cannot display standard ASCII symbols. If so we have // find any other suitable font withing "preferred" fonts first. boolean fontIsValid = isValidFont(new Font(FONT_FACE, Font.PLAIN, FONT_SIZE)); - if(!fontIsValid){ + if (!fontIsValid) { @NonNls final String[] preferredFonts = {"dialog", "Arial", "Tahoma"}; for (String preferredFont : preferredFonts) { if (isValidFont(new Font(preferredFont, Font.PLAIN, FONT_SIZE))) { @@ -263,7 +261,7 @@ public class UISettings implements PersistentStateComponent, Exporta // 2. If all preferred fonts are not valid in current environment // we have to find first valid font (if any) - if(!fontIsValid){ + if (!fontIsValid) { Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for (Font font : fonts) { if (isValidFont(font)) { @@ -278,23 +276,13 @@ public class UISettings implements PersistentStateComponent, Exporta MAX_CLIPBOARD_CONTENTS = 5; } - fireUISettingsChanged(); } - public static class FontFilter implements SerializationFilter { - public boolean accepts(Accessor accessor, Object bean) { - UISettings settings = (UISettings)bean; - - return !hasDefaultFontSetting(settings); - } - - } - - private static final boolean DONT_TOUCH_ALIASING = "true".equalsIgnoreCase(System.getProperty("idea.use.default.antialiasing.in.editor")); + private static final boolean DEFAULT_ALIASING = SystemProperties.getBooleanProperty("idea.use.default.antialiasing.in.editor", false); public static void setupAntialiasing(final Graphics g) { - if (DONT_TOUCH_ALIASING) return; + if (DEFAULT_ALIASING) return; Graphics2D g2d=(Graphics2D)g; UISettings uiSettings=getInstance(); @@ -350,10 +338,8 @@ public class UISettings implements PersistentStateComponent, Exporta } public void initComponent() { - } public void disposeComponent() { - } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java index 67cbb85de98b..2b29ce9e87ab 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java @@ -661,19 +661,19 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo defaults.put("Tree.ancestorInputMap", null); int uiFontSize = myUiSettings.FONT_SIZE; String uiFontFace = myUiSettings.FONT_FACE; - FontUIResource font = new FontUIResource(uiFontFace, Font.PLAIN, uiFontSize); - FontUIResource font1 = new FontUIResource("Serif", Font.PLAIN, uiFontSize); - FontUIResource font3 = new FontUIResource("Monospaced", Font.PLAIN, uiFontSize); + FontUIResource uiFont = new FontUIResource(uiFontFace, Font.PLAIN, uiFontSize); + FontUIResource textFont = new FontUIResource("Serif", Font.PLAIN, uiFontSize); + FontUIResource monoFont = new FontUIResource("Monospaced", Font.PLAIN, uiFontSize); for (String fontResource : ourPatchableFontResources) { - defaults.put(fontResource, font); + defaults.put(fontResource, uiFont); } - defaults.put("PasswordField.font", font3); - defaults.put("TextArea.font", font3); - defaults.put("TextPane.font", font1); - defaults.put("EditorPane.font", font1); - defaults.put("TitledBorder.font", font); + defaults.put("PasswordField.font", monoFont); + defaults.put("TextArea.font", monoFont); + defaults.put("TextPane.font", textFont); + defaults.put("EditorPane.font", textFont); + defaults.put("TitledBorder.font", uiFont); } diff --git a/platform/util/src/com/intellij/util/SystemProperties.java b/platform/util/src/com/intellij/util/SystemProperties.java index 6f7750c5d982..6a0bbdfa5e8c 100644 --- a/platform/util/src/com/intellij/util/SystemProperties.java +++ b/platform/util/src/com/intellij/util/SystemProperties.java @@ -110,4 +110,21 @@ public class SystemProperties { return defaultValue; } + + /** + * Returns the value of given property as a boolean. + * Returns {@code defaultValue} if property is not specified or malformed. + * + * @param key the property name + * @param defaultValue default value + * @return the property value as integer, or default value. + */ + public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) { + final String value = System.getProperty(key); + if (value != null) { + return Boolean.parseBoolean(value); + } + + return defaultValue; + } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 002432d18d20..ce17aba15305 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -70,7 +70,6 @@ import java.util.regex.Pattern; */ @SuppressWarnings("StaticMethodOnlyUsedInOneClass") public class UIUtil { - private static final String TABLE_DECORATION_KEY = "TABLE_DECORATION_KEY"; private static final Color DECORATED_ROW_BG_COLOR = new Color(242, 245, 249); @@ -136,6 +135,8 @@ public class UIUtil { // accessed only from EDT private static final HashMap ourAppleDotSamples = new HashMap(); + private static volatile Pair ourSystemFontData = null; + @NonNls private static final String ROOT_PANE = "JRootPane.future"; private UIUtil() { } @@ -1745,18 +1746,23 @@ public class UIUtil { } } - /** @deprecated use {@linkplain #initDefaultLAF()} (to remove in IDEA 12) */ - public static void initDefaultLAF(final String productName) { - initDefaultLAF(); - } - public static void initDefaultLAF() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + + if (ourSystemFontData == null) { + final Font font = getLabelFont(); + ourSystemFontData = Pair.create(font.getName(), font.getSize()); + } } catch (Exception ignored) { } } + @Nullable + public static Pair getSystemFontData() { + return ourSystemFontData; + } + public static void addKeyboardShortcut(final JComponent target, final AbstractButton button, final KeyStroke keyStroke) { target.registerKeyboardAction( new ActionListener() { From 62f6c0843b7077f49ae50fc2b9f398eeaeaede51 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 29 Mar 2012 12:42:42 +0200 Subject: [PATCH 65/84] IDEA-83638 (tolerate missing content roots) --- .../roots/ui/configuration/ContentEntryTreeEditor.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java index 1b90c18bfe4c..9eb223dff4ed 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeEditor.java @@ -40,6 +40,8 @@ import com.intellij.openapi.roots.ui.configuration.actions.ToggleExcludedStateAc import com.intellij.openapi.roots.ui.configuration.actions.ToggleSourcesStateAction; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.TreeSpeedSearch; @@ -144,8 +146,11 @@ public class ContentEntryTreeEditor { final ContentEntry entry = contentEntryEditor.getContentEntry(); assert entry != null : contentEntryEditor; final VirtualFile file = entry.getFile(); - assert file != null : entry.getUrl(); myDescriptor.setRoots(file); + if (file == null) { + final String path = VfsUtil.urlToPath(entry.getUrl()); + myDescriptor.setTitle(FileUtil.toSystemDependentName(path)); + } final Runnable init = new Runnable() { public void run() { From 21c363c621b03045d49642e72aa008eff4649bd4 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 29 Mar 2012 15:09:09 +0400 Subject: [PATCH 66/84] showing Inspection Results toolwindow restored --- .../codeInspection/ex/GlobalInspectionContextImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index d6febddfd9e2..1f6f52be9fb4 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -206,6 +206,10 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G myContent.setDisposer(myView); + ContentManager contentManager = getContentManager(); + contentManager.addContent(myContent); + contentManager.setSelectedContent(myContent); + ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.INSPECTION).activate(null); } From db15b10b5b24339c081ae1e2264c1798f31755cc Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Thu, 29 Mar 2012 15:15:26 +0400 Subject: [PATCH 67/84] FrameLayout --- .../android/designer/icons/FrameLayout.png | Bin 0 -> 1068 bytes .../designer/model/PropertyParser.java | 109 +++++++++++++++++- .../designer/model/RadFrameLayout.java | 56 +++++++++ .../designer/model/RadLinearLayout.java | 9 +- .../designer/model/RadViewGroupComponent.java | 36 ++++++ .../designer/model/RadViewLayoutWithData.java | 23 ++++ .../designer/model/views-meta-model.xml | 23 +++- 7 files changed, 249 insertions(+), 7 deletions(-) create mode 100644 plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png create mode 100644 plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png b/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png new file mode 100644 index 0000000000000000000000000000000000000000..66bd0421cb0c2c4bb0cddfaa78506607936693e7 GIT binary patch literal 1068 zcmbVLJ8aWH7&VxrZ{mzBQ>E)gQz;yv9FCu>~rlaamvJ_ z15`+KFYp&ulHtp8hE}rJN<29$UNEeH9 zszqGEj4?vw`i#wS(=(B8T6Ii86|Xv;#{YQpmIscl@mHlHEc#hob7nUJys%NKSQ~Xq zvH6(`U^-HnfQzXKBDdj%YNYWUU6t+QYmo;X2(4@UzEg|Ed5|Rm29f|17EB|MP6;Rl zm6S3Lk`O@=B}FJF5L6{ug$Q&Xo>>d*6}4>SySCU#<7<@qswg&_O`$mR5G$HhvQ9OgdAc8h>lcd$!d}=-6ib;HnZAew zD7tPOR|g%^GXCSnq3E#E^08RPAz2SBR*#jj9+~CtXhSiOd81wq999&wVGwKG#U3pf z8qfX+wqvstO+tj^6qJ)NJ&BN#n$Y#Up=1rHD>_W~G!Ek;DV52j4P8=X8KE4Sl#-bY zlAxp*`MhrAdfb8+Qq!|=&#uGlcDc%tTs0eDlaio9NTb&Q^EECPUk?R>bo1K7ZSvO>)8#>?R+W(U^kvSvA?eSN; z^sZPB#@mDDXNQCF!5*8LfDOmeuWCG)O9ex(L|>}k_V$*+z-w-;)l#-!PEAccJUiPz zKJxw3vzZg8&cA!{acAe|=H|fjzIN5@yH~w(zj0=_H2V2srmcVVK0Vdi*SPnOwzf`w gc+x+2yIto7Avbp8v=`lZ{4<{4Lat=I$}Hdd4enG properties = loadLayoutProperties(layoutParams, 0); + + if (!properties.isEmpty()) { + properties = new ArrayList(properties); + properties.addAll(component.getProperties()); + component.setProperties(properties); + } + } + } } - private List load(Class componentClass, MetaModel model) throws Exception { + private List loadWidgetProperties(Class componentClass, MetaModel model) throws Exception { String component = componentClass.getSimpleName(); List properties = myCachedProperties.get(component); if (properties == null) { properties = new ArrayList(); + myCachedProperties.put(component, properties); StyleableDefinition definitions = myDefinitions.getStyleableByName(component); if (definitions != null) { @@ -153,7 +180,8 @@ public class PropertyParser { superComponentClass = myClassLoader.loadClass("android.view.View"); } - List superProperties = load(superComponentClass, myMetaManager.getModelByTarget(superComponentClass.getName())); + List superProperties = loadWidgetProperties(superComponentClass, + myMetaManager.getModelByTarget(superComponentClass.getName())); for (Property superProperty : superProperties) { if (PropertyTable.findProperty(properties, superProperty) == -1) { if (model == null) { @@ -192,8 +220,79 @@ public class PropertyParser { } }); } + } + return properties; + } + + private List loadLayoutProperties(String[] components, int index) throws Exception { + String component = components[index]; + + List properties = myCachedProperties.get(component); + + if (properties == null) { + properties = new ArrayList(); myCachedProperties.put(component, properties); + + StyleableDefinition definitions = myDefinitions.getStyleableByName(component); + if (definitions != null) { + Property margin = null; + + for (AttributeDefinition definition : definitions.getAttributes()) { + String name = definition.getName(); + boolean important = true; + Set formats = definition.getFormats(); + Property property; + + if (name.startsWith(LAYOUT_MARGIN_PREFIX) && name.length() > LAYOUT_MARGIN_PREFIX.length()) { + name = name.substring(LAYOUT_PREFIX.length()); + important = false; + } + else if (name.startsWith(LAYOUT_PREFIX)) { + name = "layout:" + name.substring(LAYOUT_PREFIX.length()); + } + + if ("layout:margin".equals(name) && "ViewGroup_MarginLayout".equals(component)) { + property = margin = new CompoundProperty(name, definition); + } + else if (formats.contains(AttributeFormat.Flag)) { + property = new FlagProperty(name, definition); + } + else { + property = new AttributeProperty(name, definition); + } + + property.setImportant(important); + properties.add(property); + } + + if (margin != null) { + List children = margin.getChildren(null); + children.add(PropertyTable.extractProperty(properties, "marginLeft")); + children.add(PropertyTable.extractProperty(properties, "marginTop")); + children.add(PropertyTable.extractProperty(properties, "marginRight")); + children.add(PropertyTable.extractProperty(properties, "marginBottom")); + children.add(PropertyTable.extractProperty(properties, "marginStart")); + children.add(PropertyTable.extractProperty(properties, "marginEnd")); + } + } + + if (++index < components.length) { + for (Property property : loadLayoutProperties(components, index)) { + if (PropertyTable.findProperty(properties, property) == -1) { + properties.add(property); + } + } + } + + if (!properties.isEmpty()) { + Collections.sort(properties, new Comparator() { + @Override + public int compare(Property p1, Property p2) { + return p1.getName().compareTo(p2.getName()); + } + }); + } } return properties; diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java new file mode 100644 index 000000000000..1f97e251d2b7 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2012 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.android.designer.model; + +import com.intellij.designer.designSurface.ComponentDecorator; +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; + +import javax.swing.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RadFrameLayout extends RadViewLayoutWithData { + private static final String[] LAYOUT_PARAMS = {"FrameLayout_Layout", "ViewGroup_MarginLayout"}; + + @Override + public String[] getLayoutParams() { + return LAYOUT_PARAMS; + } + + @Override + public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { + return super.getChildSelectionDecorator(component, selection); // TODO: Auto-generated method stub + } + + @Override + public EditOperation processChildOperation(OperationContext context) { + return super.processChildOperation(context); // TODO: Auto-generated method stub + } + + @Override + public void addSelectionActions(DesignerEditorPanel designer, + DefaultActionGroup actionGroup, + JComponent shortcuts, + List selection) { + super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java index e6cbf4533c44..19e04a31053a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java @@ -30,7 +30,14 @@ import java.util.List; /** * @author Alexander Lobas */ -public class RadLinearLayout extends RadViewLayout { +public class RadLinearLayout extends RadViewLayoutWithData { + private static final String[] LAYOUT_PARAMS = {"LinearLayout_Layout", "ViewGroup_MarginLayout"}; + + @Override + public String[] getLayoutParams() { + return LAYOUT_PARAMS; + } + @Override public EditOperation processChildOperation(OperationContext context) { if (context.isCreate()) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java new file mode 100644 index 000000000000..af4d30984129 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2012 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.android.designer.model; + +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; + +import javax.swing.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RadViewGroupComponent extends RadViewComponent { + @Override + public void addSelectionActions(DesignerEditorPanel designer, + DefaultActionGroup actionGroup, + JComponent shortcuts, + List selection) { + super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java new file mode 100644 index 000000000000..ca1af9c2692d --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2012 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.android.designer.model; + +/** + * @author Alexander Lobas + */ +public abstract class RadViewLayoutWithData extends RadViewLayout { + public abstract String[] getLayoutParams(); +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml index 0d9f8e077767..a91e9ba6d1cd 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml +++ b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml @@ -983,7 +983,7 @@ - @@ -1004,6 +1004,26 @@ + + + + + + + + + + ]]> + + + @@ -1061,6 +1081,7 @@ + From 4a3e957120eea961d81ddbe3d783e3cdc89a6384 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 29 Mar 2012 12:31:11 +0200 Subject: [PATCH 68/84] a test for no folding when editing groovy imports --- .../groovy/lang/GroovyFoldingTest.groovy | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy index 04ee1eab49e1..7df5c8c1830e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy @@ -47,6 +47,25 @@ class GroovyFoldingTest extends LightCodeInsightFixtureTestCase { assert assertNoFolding(myFixture.file.text.indexOf(marker)), marker } + public void testEditingImports() { + configure """ +import java.util.List +import java.util.Map + + +println 'hello' + +class Foo { List a; Map b; } +""" + + assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10) + + myFixture.type 'import ' + myFixture.doHighlighting() + assert !myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10) + } + + void testOpenBlock() { configure '''def foo() {print 'a'} def bar() { From 8c2dc396709dff11a39a5abe79f76692646828b0 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 29 Mar 2012 13:10:42 +0200 Subject: [PATCH 69/84] don't expand single-line closure foldings when editing inside them --- .../folding/impl/JavaFoldingBuilder.java | 20 ++++++++++++-- .../folding/JavaFoldingTest.groovy | 26 +++++++++++++++++++ .../moveUpDown/MoverWrapper.java | 1 - .../folding/CodeFoldingManager.java | 10 ------- .../folding/impl/CodeFoldingManagerImpl.java | 5 ---- .../impl/UpdateFoldRegionsOperation.java | 25 +----------------- .../lang/folding/GroovyFoldingBuilder.java | 3 ++- 7 files changed, 47 insertions(+), 43 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java index 34305ef9bc58..6c1f9220644d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.folding.impl; +import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil; import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.lang.ASTNode; @@ -47,7 +48,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAware { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.folding.impl.JavaFoldingBuilder"); @@ -312,7 +316,9 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar if (importKeyword == null) return null; int startOffset = importKeyword.getTextRange().getEndOffset() + 1; int endOffset = statements[statements.length - 1].getTextRange().getEndOffset(); - return new TextRange(startOffset, endOffset); + if (!hasErrorElementsNearby(element.getContainingFile(), startOffset, endOffset)) { + return new TextRange(startOffset, endOffset); + } } if (element instanceof PsiDocComment) { return element.getTextRange(); @@ -330,6 +336,16 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar return null; } + public static boolean hasErrorElementsNearby(final PsiFile file, int startOffset, int endOffset) { + endOffset = CharArrayUtil.shiftForward(file.getText(), endOffset, " \t\n"); + for (PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffset, endOffset)) { + if (element instanceof PsiErrorElement) { + return true; + } + } + return false; + } + @Nullable private static TextRange getFileHeader(PsiJavaFile file) { PsiElement first = file.getFirstChild(); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy index 3b48d5e41fd3..5d13114d3e7f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy @@ -167,6 +167,32 @@ class Test { assertEquals(2, closureFolds.size()) } + public void "test closure folding doesn't expand when editing inside"() { + def text = """\ +class Test { + void test() { + new Runnable() { + public void run() { + System.out.println(); + } + }; + } +} +""" + + configure text + def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl + def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assertNotNull closureStartFold + assertFalse closureStartFold.expanded + assert text.substring(closureStartFold.endOffset).startsWith('System') //one line closure + + myFixture.type('2') + myFixture.doHighlighting() + closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assert closureStartFold + } + public void testFindInFolding() { def text = """\ class Test { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java index d87e82a67b38..a233872b8e6c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java @@ -131,7 +131,6 @@ class MoverWrapper { } }); } - CodeFoldingManager.getInstance(project).allowFoldingOnCaretLine(editor); if (hasSelection) { restoreSelection(editor, selectionStart, selectionEnd, start, myInfo.range2.getStartOffset()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java index be52c03fed31..7c9ed482d819 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java @@ -50,14 +50,4 @@ public abstract class CodeFoldingManager { public abstract void releaseFoldings(Editor editor); public abstract void buildInitialFoldings(Editor editor); - - /** - * Asks do not perform automatic expansion of fold region that is located on the caret line during the next fold regions update. - *

- * This method is necessary because fold regions that are located on caret line are automatically expanded to prevent problem - * from IDEA-64687. However, we don't want such an expansion when we, for example, move method up or down. - * - * @param editor target editor - */ - public abstract void allowFoldingOnCaretLine(@NotNull Editor editor); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java index f2008c380b8f..74c83d50d8cb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java @@ -331,9 +331,4 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec document.putUserData(FOLDING_STATE_INFO_IN_DOCUMENT_KEY, null); } } - - @Override - public void allowFoldingOnCaretLine(@NotNull Editor editor) { - editor.putUserData(UpdateFoldRegionsOperation.ALLOW_FOLDING_ON_CARET_LINE_KEY, true); - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java index e2e051772a6c..3ad2f94584a3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java @@ -18,14 +18,12 @@ package com.intellij.codeInsight.folding.impl; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.lang.injection.InjectedLanguageManager; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -43,9 +41,6 @@ import static com.intellij.util.containers.CollectionFactory.newTroveMap; * @author cdr */ class UpdateFoldRegionsOperation implements Runnable { - - static final Key ALLOW_FOLDING_ON_CARET_LINE_KEY = Key.create("AllowFoldingOnCaretLine.KEY"); - private final Project myProject; private final Editor myEditor; private final PsiFile myFile; @@ -80,9 +75,6 @@ class UpdateFoldRegionsOperation implements Runnable { List newRegions = addNewRegions(info, foldingModel, rangeToExpandStatusMap, shouldExpand, groupExpand); applyExpandStatus(newRegions, shouldExpand, groupExpand); - - // Reset the key. - myEditor.putUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY, false); } private static void applyExpandStatus(@NotNull List newRegions, @@ -147,24 +139,9 @@ class UpdateFoldRegionsOperation implements Runnable { // Considering that this code is executed only on initial fold regions construction on editor opening. return !FoldingPolicy.isCollapseByDefault(element); } - boolean caretInside; - if (myEditor.getUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY) == Boolean.TRUE) { - caretInside = FoldingUtil.caretInsideRange(myEditor, range); - } - else { - final Document document = myEditor.getDocument(); - final int firstLine = document.getLineNumber(range.getStartOffset()); - final int lastLine = document.getLineNumber(range.getEndOffset()); - int caretOffset = myEditor.getCaretModel().getOffset(); - if (caretOffset > myEditor.getDocument().getTextLength()) { - return false; - } - final int currentLine = document.getLineNumber(caretOffset); - caretInside = firstLine <= currentLine && currentLine <= lastLine; - } final Boolean oldStatus = rangeToExpandStatusMap.get(range); - return oldStatus == null || caretInside || oldStatus.booleanValue(); + return oldStatus == null || FoldingUtil.caretInsideRange(myEditor, range) || oldStatus.booleanValue(); } private void removeInvalidRegions(@NotNull EditorFoldingInfo info, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index f695d0ebe0d8..b77bd7c933fc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.folding; import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; +import com.intellij.codeInsight.folding.impl.JavaFoldingBuilder; import com.intellij.lang.ASTNode; import com.intellij.lang.folding.CustomFoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; @@ -194,7 +195,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy int start = first.getTextRange().getStartOffset(); int end = marker.getTextRange().getEndOffset(); int tail = "import ".length(); - if (start + tail < end) { + if (start + tail < end && !JavaFoldingBuilder.hasErrorElementsNearby(first.getContainingFile(), start, end)) { descriptors.add(new FoldingDescriptor(first.getNode(), new TextRange(start + tail, end))); } } From 9b6a24b86a033c48b7889b3efe070e065a7a70ac Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 29 Mar 2012 13:13:00 +0200 Subject: [PATCH 70/84] turn on light xi:includes --- .../src/com/intellij/xml/util/InclusionProvider.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java index d53f251bd356..9f637d59a193 100644 --- a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java +++ b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java @@ -17,13 +17,11 @@ package com.intellij.xml.util; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.RecursionManager; -import com.intellij.psi.PsiAnchor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.xml.XmlDocument; -import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.xmlb.JDOMXIncluder; @@ -82,12 +80,7 @@ class InclusionProvider implements CachedValueProvider { final XmlTag[] includeTag = extractXpointer(rootTag, xpointer); PsiElement[] result = new PsiElement[includeTag.length]; for (int i = 0; i < includeTag.length; i++) { - XmlTag xmlTag = includeTag[i]; - final PsiElement psiElement = xmlTag.copy(); - psiElement.putUserData(XmlElement.INCLUDING_ELEMENT, xincludeTag.getParentTag()); - psiElement.putUserData(XmlUtil.ORIGINAL_ELEMENT, PsiAnchor.create(xmlTag)); - result[i] = psiElement; - //result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag()); + result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag()); } return result; } From c588cea67406dcc0c7e0829f2bcf0d00bac6cb5d Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 29 Mar 2012 15:44:47 +0400 Subject: [PATCH 71/84] Add additional loggining to understand cause of maven test fail --- .../maven/dom/MavenExtensionCompletionAndResolutionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java index aa34ea474344..95f5341069c4 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java @@ -74,6 +74,7 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject); System.out.println("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins")); System.out.println("Indexes: " + instance.getIndices()); + throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + "Indexes: " + instance.getIndices()); } assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); From ea56fe5b0236f944d872a17418e6a684ccc87993 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 29 Mar 2012 09:35:02 +0400 Subject: [PATCH 72/84] library editor: attach files actions works in dumb mode --- .../ui/configuration/libraryEditor/LibraryRootsComponent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java index 4a6ea36e7de0..be3f59f985d2 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java @@ -27,6 +27,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.OrderRootType; @@ -371,7 +372,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } } - public abstract class AttachItemActionBase extends AnAction { + public abstract class AttachItemActionBase extends DumbAwareAction { private VirtualFile myLastChosen = null; protected AttachItemActionBase(String text) { From e5ca397cf685dcb49ea795974655495dbe165cb8 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 29 Mar 2012 12:31:39 +0400 Subject: [PATCH 73/84] update gutter icon for related file when related items are changed --- .../codeInsight/daemon/LineMarkerInfo.java | 4 ++-- .../daemon/RelatedItemLineMarkerInfo.java | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java index c944eec2ffb4..454e396c268a 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java @@ -35,7 +35,7 @@ import java.awt.event.MouseEvent; import java.lang.ref.WeakReference; public class LineMarkerInfo { - private final Icon myIcon; + protected final Icon myIcon; private final WeakReference elementRef; public final int startOffset; public final int endOffset; @@ -157,7 +157,7 @@ public class LineMarkerInfo { return myInfo.myIconAlignment; } - private boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { + protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { return myInfo.getElement() != null && renderer.myInfo.getElement() != null && diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java index 9889bdf263a8..55ce601e8943 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java @@ -60,4 +60,27 @@ public class RelatedItemLineMarkerInfo extends LineMarkerI public Collection createGotoRelatedItems() { return myTargets.getValue(); } + + @Override + public GutterIconRenderer createGutterRenderer() { + if (myIcon == null) return null; + return new RelatedItemLineMarkerGutterIconRenderer(this); + } + + private static class RelatedItemLineMarkerGutterIconRenderer extends LineMarkerGutterIconRenderer { + public RelatedItemLineMarkerGutterIconRenderer(final RelatedItemLineMarkerInfo markerInfo) { + super(markerInfo); + } + + @Override + protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { + if (!(renderer instanceof RelatedItemLineMarkerGutterIconRenderer) || !super.looksTheSameAs(renderer)) { + return false; + } + + final RelatedItemLineMarkerInfo markerInfo = (RelatedItemLineMarkerInfo)getLineMarkerInfo(); + final RelatedItemLineMarkerInfo otherInfo = (RelatedItemLineMarkerInfo)renderer.getLineMarkerInfo(); + return markerInfo.myTargets.equals(otherInfo.myTargets); + } + } } From 20ba32493ab25914e6d3cec21366864f9a88b0c7 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 29 Mar 2012 15:51:12 +0400 Subject: [PATCH 74/84] do not terminate hotswap if not all versions of class were reloaded (IDEA-68746) --- .../debugger/impl/ReloadClassesWorker.java | 129 +++++++++++++----- .../src/messages/DebuggerBundle.properties | 1 + 2 files changed, 98 insertions(+), 32 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java index 3cfdb3a8979f..f2459aadff39 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java @@ -32,20 +32,13 @@ import com.sun.jdi.ReferenceType; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author lex */ class ReloadClassesWorker { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.ReloadClassesWorker"); - /** - * number of clasess that will be reloaded in one go. - * Such restriction is needed to deal with big number of classes being reloaded - */ - private static final int CLASSES_CHUNK_SIZE = 100; private final DebuggerSession myDebuggerSession; private final HotSwapProgress myProgress; @@ -111,11 +104,12 @@ class ReloadClassesWorker { final Project project = debugProcess.getProject(); final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager(); breakpointManager.disableBreakpoints(debugProcess); - + //virtualMachineProxy.suspend(); - + try { - final Map redefineMap = new HashMap(); + RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy); + int processedClassesCount = 0; for (final String qualifiedName : modifiedClasses.keySet()) { processedClassesCount++; @@ -124,32 +118,30 @@ class ReloadClassesWorker { myProgress.setFraction(processedClassesCount / (double)modifiedClasses.size()); } final HotSwapFile fileDescr = modifiedClasses.get(qualifiedName); + final byte[] content; try { - final byte[] buffer = FileUtil.loadFileBytes(fileDescr.file); - final List classes = virtualMachineProxy.classesByName(qualifiedName); - for (final ReferenceType reference : classes) { - redefineMap.put(reference, buffer); - } + content = FileUtil.loadFileBytes(fileDescr.file); } catch (IOException e) { reportProblem(qualifiedName, e); + continue; } - if (redefineMap.size() >= CLASSES_CHUNK_SIZE) { - // reload this portion of clasess and clear the map to free memory - try { - virtualMachineProxy.redefineClasses(redefineMap); - } - finally { - redefineMap.clear(); - } - } - } - if (redefineMap.size() > 0) { - virtualMachineProxy.redefineClasses(redefineMap); + redefineProcessor.processClass(qualifiedName, content); } + redefineProcessor.processPending(); myProgress.setFraction(1); - - myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.classes.reloaded", modifiedClasses.size())); + + final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount(); + if (partiallyRedefinedClassesCount == 0) { + myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, + DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount())); + } + else { + final String message = DebuggerBundle.message("status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount, + redefineProcessor.getProcessedClassesCount()); + myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message); + } + if (LOG.isDebugEnabled()) { LOG.debug("classes reloaded"); } @@ -203,11 +195,10 @@ class ReloadClassesWorker { catch (Exception e) { processException(e); } - } private void reportProblem(final String qualifiedName, @Nullable Exception ex) { - String reason = null; + String reason = null; if (ex != null) { reason = ex.getLocalizedMessage(); } @@ -223,4 +214,78 @@ class ReloadClassesWorker { StringBuilderSpinAllocator.dispose(buf); } } + + private static class RedefineProcessor { + /** + * number of classes that will be reloaded in one go. + * Such restriction is needed to deal with big number of classes being reloaded + */ + private static final int CLASSES_CHUNK_SIZE = 100; + private final VirtualMachineProxyImpl myVirtualMachineProxy; + private final Map myRedefineMap = new HashMap(); + private int myProcessedClassesCount; + private int myPartiallyRedefinedClassesCount; + + public RedefineProcessor(VirtualMachineProxyImpl virtualMachineProxy) { + myVirtualMachineProxy = virtualMachineProxy; + } + + public void processClass(String qualifiedName, byte[] content) throws Throwable { + final List vmClasses = myVirtualMachineProxy.classesByName(qualifiedName); + if (vmClasses.isEmpty()) return; + + if (vmClasses.size() == 1) { + myRedefineMap.put(vmClasses.get(0), content); + if (myRedefineMap.size() >= CLASSES_CHUNK_SIZE) { + processChunk(); + } + return; + } + + int redefinedVersionsCount = 0; + Throwable error = null; + for (ReferenceType vmClass : vmClasses) { + try { + myVirtualMachineProxy.redefineClasses(Collections.singletonMap(vmClass, content)); + redefinedVersionsCount++; + } + catch (Throwable t) { + error = t; + } + } + if (redefinedVersionsCount == 0) { + throw error; + } + + if (redefinedVersionsCount < vmClasses.size()) { + myPartiallyRedefinedClassesCount++; + } + myProcessedClassesCount++; + } + + private void processChunk() throws Throwable { + // reload this portion of classes and clear the map to free memory + try { + myVirtualMachineProxy.redefineClasses(myRedefineMap); + myProcessedClassesCount += myRedefineMap.size(); + } + finally { + myRedefineMap.clear(); + } + } + + public void processPending() throws Throwable { + if (myRedefineMap.size() > 0) { + processChunk(); + } + } + + public int getProcessedClassesCount() { + return myProcessedClassesCount; + } + + public int getPartiallyRedefinedClassesCount() { + return myPartiallyRedefinedClassesCount; + } + } } diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 1a51ab4d3574..508ae6ee32c8 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -164,6 +164,7 @@ error.exception.while.reloading=Exception while reloading classes : {0} : {1} status.hotswap.loaded.classes.up.to.date=Loaded classes are up to date. Nothing to reload error.io.error=I/O error status.classes.reloaded={0,number} {0,choice, 0#classes|1#class|2#classes} reloaded +status.classes.not.all.versions.reloaded=For {0} of {1} {1,choice, 1#class|2#classes} not all versions were reloaded error.cannot.create.void.value=Cannot create void value warning.range.too.big=Range specified is too big. {0} needs too much resources to perform requested operation. Are you sure you want to continue? title.range.too.big=Range is Too Big From 477dd80b8375d120edc6e83fb59c8cdd9245d0ff Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Mar 2012 14:03:04 +0200 Subject: [PATCH 75/84] + recent files separator --- .../src/com/intellij/ide/actions/Switcher.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 5c633a0048b6..c439f4bc4b08 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -285,6 +285,7 @@ public class Switcher extends AnAction implements DumbAware { final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles()); final int maxFiles = Math.max(editors.size(), recentFiles.length); final int len = isPinnedMode() ? maxFiles : Math.min(toolWindows.getModel().getSize(), maxFiles); + boolean firstRecentMarked = false; for (int i = 0; i < len; i++) { final FileInfo info = new FileInfo(recentFiles[i], null); boolean add = true; @@ -298,6 +299,10 @@ public class Switcher extends AnAction implements DumbAware { } if (add) { filesData.add(info); + if (!firstRecentMarked) { + firstRecentMarked = true; + info.isSeparator = true; + } } } if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) { @@ -805,6 +810,7 @@ public class Switcher extends AnAction implements DumbAware { private final Project myProject; private final SpeedSearchBase mySearch; private boolean hide = false; + private boolean separator = false; public VirtualFilesRenderer(Project project, SpeedSearchBase search) { myProject = project; @@ -817,10 +823,12 @@ public class Switcher extends AnAction implements DumbAware { final VirtualFile virtualFile = ((FileInfo)value).first; final String name = virtualFile.getPresentableName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); + separator = ((FileInfo)value).isSeparator; if ( mySearch != null && mySearch.isPopupActive()) { hide = mySearch.matchingFragments(name) == null && !StringUtil.isEmpty(mySearch.getEnteredPrefix()); } + final FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile); final TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); @@ -835,10 +843,14 @@ public class Switcher extends AnAction implements DumbAware { } super.doPaint(g); config.restore(); + if (separator) { + UIUtil.drawDottedLine(g, 0, 0, getWidth(), 0, Color.WHITE, Color.BLACK); + } } } private static class FileInfo extends Pair { + boolean isSeparator = false; public FileInfo(VirtualFile first, EditorWindow second) { super(first, second); } From 20695de4fd9117adce883f4c89b275cff2c3179c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 29 Mar 2012 14:20:12 +0200 Subject: [PATCH 76/84] compile server: support classpath index generation --- .../compiler/CompileServerManager.java | 7 +- .../org/jetbrains/jps/api/GlobalOptions.java | 1 + .../jetbrains/jps/api/SharedThreadPool.java | 18 +++++ .../jps/incremental/IncProjectBuilder.java | 80 ++++++++++++++++++- .../jps/incremental/ModuleLevelBuilder.java | 2 +- .../jps/incremental/java/JavaBuilder.java | 6 +- .../resources/ResourcesBuilder.java | 5 +- .../jps/javac/JavacServerClient.java | 13 +-- .../AndroidLibraryPackagingBuilder.java | 9 ++- .../AndroidSourceGeneratingBuilder.java | 2 +- .../jps/incremental/groovy/GroovyBuilder.java | 2 +- 11 files changed, 117 insertions(+), 28 deletions(-) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index fc7c7d7b7eb8..3aef0d599083 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -70,8 +70,7 @@ import org.jetbrains.jps.client.CompileServerClient; import org.jetbrains.jps.server.ClasspathBootstrap; import org.jetbrains.jps.server.Server; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; +import javax.tools.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -586,6 +585,10 @@ public class CompileServerManager implements ApplicationComponent{ cmdLine.addParameter("-XX:ReservedCodeCacheSize=64m"); cmdLine.addParameter("-Xmx" + Registry.intValue("compiler.server.heap.size") + "m"); cmdLine.addParameter("-Djava.awt.headless=true"); + final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION); + if (shouldGenerateIndex != null) { + cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex); + } //noinspection ConstantConditions if (pingInterval > 0L) { cmdLine.addParameter("-D" + GlobalOptions.PING_INTERVAL_MS_OPTION + "=" + pingInterval); diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java index f2fdd71e4b0d..febbe3880eb7 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java +++ b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java @@ -9,4 +9,5 @@ public interface GlobalOptions { String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process"; String HOSTNAME_OPTION = "localhost.name"; String PING_INTERVAL_MS_OPTION = "server.ping.interval"; + String GENERATE_CLASSPATH_INDEX_OPTION = "generate.classpath.index"; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java b/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java new file mode 100644 index 000000000000..508abe015b3f --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java @@ -0,0 +1,18 @@ +package org.jetbrains.jps.api; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author Eugene Zhuravlev + * Date: 3/29/12 + */ +public class SharedThreadPool { + public static final ExecutorService INSTANCE = Executors.newCachedThreadPool(); + public static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() { + @Override + public void submit(Runnable runnable) { + INSTANCE.submit(runnable); + } + }; +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index f59e2c6a0da9..5d493a8dca64 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -9,7 +9,9 @@ import com.intellij.util.io.MappingFailedException; import com.intellij.util.io.PersistentEnumerator; import org.jetbrains.jps.*; import org.jetbrains.jps.api.CanceledStatus; +import org.jetbrains.jps.api.GlobalOptions; import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor; import org.jetbrains.jps.incremental.java.JavaBuilder; import org.jetbrains.jps.incremental.java.JavaBuilderLogger; @@ -21,10 +23,13 @@ import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.incremental.storage.SourceToOutputMapping; import org.jetbrains.jps.server.ProjectDescriptor; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** @@ -35,6 +40,8 @@ public class IncProjectBuilder { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.IncProjectBuilder"); public static final String COMPILE_SERVER_NAME = "COMPILE SERVER"; + private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index"; + private static final boolean GENERATE_CLASSPATH_INDEX = "true".equals(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION)); private final ProjectDescriptor myProjectDescriptor; private final BuilderRegistry myBuilderRegistry; @@ -54,6 +61,7 @@ public class IncProjectBuilder { private float myModulesProcessed = 0.0f; private final float myTotalModulesWork; private final int myTotalModuleLevelBuilderCount; + private final List myAsyncTasks = new ArrayList(); public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map builderParams, CanceledStatus cs) { myProjectDescriptor = pd; @@ -131,6 +139,15 @@ public class IncProjectBuilder { finally { memWatcher.stop(); flushContext(context); + // wait for the async tasks + for (Future task : myAsyncTasks) { + try { + task.get(); + } + catch (Throwable th) { + LOG.info(th); + } + } } } @@ -309,16 +326,18 @@ public class IncProjectBuilder { } } - private void buildChunk(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + private void buildChunk(CompileContext context, final ModuleChunk chunk) throws ProjectBuildException { + boolean doneSomething = false; try { context.ensureFSStateInitialized(chunk); if (context.isMake()) { processDeletedPaths(context, chunk); + doneSomething |= context.hasRemovedSources(); } context.onChunkBuildStart(chunk); - runModuleLevelBuilders(context, chunk); + doneSomething = runModuleLevelBuilders(context, chunk); } catch (ProjectBuildException e) { throw e; @@ -343,11 +362,59 @@ public class IncProjectBuilder { } finally { Paths.CHUNK_REMOVED_SOURCES_KEY.set(context, null); + if (doneSomething && GENERATE_CLASSPATH_INDEX) { + final boolean forTests = context.isCompilingTests(); + final Future future = SharedThreadPool.INSTANCE.submit(new Runnable() { + @Override + public void run() { + createClasspathIndex(chunk, forTests); + } + }); + myAsyncTasks.add(future); + } } } } } + private static void createClasspathIndex(final ModuleChunk chunk, boolean forTests) { + final Set outputPaths = new LinkedHashSet(); + for (Module module : chunk.getModules()) { + if (forTests) { + outputPaths.add(new File(module.getTestOutputPath())); + } + else { + outputPaths.add(new File(module.getOutputPath())); + } + } + for (File outputRoot : outputPaths) { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outputRoot, CLASSPATH_INDEX_FINE_NAME))); + try { + writeIndex(writer, outputRoot, ""); + } + finally { + writer.close(); + } + } + catch (IOException e) { + // Ignore. Failed to create optional classpath index + } + } + } + + private static void writeIndex(final BufferedWriter writer, final File file, final String path) throws IOException { + writer.write(path); + writer.write('\n'); + final File[] files = file.listFiles(); + if (files != null) { + for (File child : files) { + writeIndex(writer, child, path + "/" + child.getName()); + } + } + } + + private void processDeletedPaths(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { try { // cleanup outputs @@ -420,13 +487,14 @@ public class IncProjectBuilder { } } - private void runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + // return true if changed something, false otherwise + private boolean runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + boolean doneSomething = false; boolean rebuildFromScratchRequested = false; float stageCount = myTotalModuleLevelBuilderCount; final int modulesInChunk = chunk.getModules().size(); int buildersPassed = 0; boolean nextPassRequired; - do { nextPassRequired = false; context.beforeCompileRound(chunk); @@ -448,6 +516,8 @@ public class IncProjectBuilder { } final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk); + doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE); + if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) { throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop"); } @@ -492,6 +562,8 @@ public class IncProjectBuilder { } } while (nextPassRequired); + + return doneSomething; } private void runProjectLevelBuilders(CompileContext context) throws ProjectBuildException { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java index d503e83bff8e..5f442ca56ae0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java @@ -32,7 +32,7 @@ public abstract class ModuleLevelBuilder extends Builder { } public static enum ExitCode { - OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED + NOTHING_DONE, OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED } public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 5378c096312a..58db508502ac 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -33,8 +33,7 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.EmptyVisitor; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -239,7 +238,7 @@ public class JavaBuilder extends ModuleLevelBuilder { private ExitCode compile(final CompileContext context, ModuleChunk chunk, Collection files, Collection forms) throws Exception { - ExitCode exitCode = ExitCode.OK; + ExitCode exitCode = ExitCode.NOTHING_DONE; final boolean hasSourcesToCompile = !files.isEmpty() || !forms.isEmpty(); @@ -264,6 +263,7 @@ public class JavaBuilder extends ModuleLevelBuilder { DELTA_MAPPINGS_CALLBACK_KEY.set(context, delta.getCallback()); try { if (hasSourcesToCompile) { + exitCode = ExitCode.OK; final Set sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.emptySet()); final String chunkName = getChunkPresentableName(chunk); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java index 06e142335840..21238fa03190 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java @@ -1,6 +1,7 @@ package org.jetbrains.jps.incremental.resources; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.jps.Module; import org.jetbrains.jps.ModuleChunk; @@ -38,12 +39,14 @@ public class ResourcesBuilder extends ModuleLevelBuilder { } try { final ResourcePatterns finalPatterns = patterns; + final Ref doneSomething = new Ref(false); context.processFilesToRecompile(chunk, new FileProcessor() { public boolean apply(final Module module, final File file, final String sourceRoot) throws IOException { if (finalPatterns.isResourceFile(file, sourceRoot)) { try { context.processMessage(new ProgressMessage("Copying " + file.getPath())); final String moduleName = module.getName().toLowerCase(Locale.US); + doneSomething.set(true); copyResource(context, module, file, sourceRoot, context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests())); } catch (IOException e) { @@ -56,7 +59,7 @@ public class ResourcesBuilder extends ModuleLevelBuilder { } }); - return ExitCode.OK; + return doneSomething.get()? ExitCode.OK : ExitCode.NOTHING_DONE; } catch (Exception e) { throw new ProjectBuildException(e.getMessage(), e); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java index 75a3e7cb6e1d..136f07ce4798 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java @@ -2,31 +2,22 @@ package org.jetbrains.jps.javac; import org.jboss.netty.channel.MessageEvent; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.api.AsyncTaskExecutor; import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.client.SimpleProtobufClient; import org.jetbrains.jps.client.UUIDGetter; import java.io.File; import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * @author Eugene Zhuravlev * Date: 1/22/12 */ public class JavacServerClient extends SimpleProtobufClient{ - private static final ExecutorService ourExecutors = Executors.newCachedThreadPool(); - private static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() { - @Override - public void submit(Runnable runnable) { - ourExecutors.submit(runnable); - } - }; public JavacServerClient() { - super(JavacRemoteProto.Message.getDefaultInstance(), ASYNC_EXEC, new UUIDGetter() { + super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.ASYNC_EXEC, new UUIDGetter() { @NotNull public UUID getSessionUUID(@NotNull MessageEvent e) { final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage(); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java index 0720446f5288..827e177c5930 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java @@ -30,9 +30,9 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { } @Override - public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + public ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk) || AndroidJpsUtil.isLightBuild(context)) { - return ModuleLevelBuilder.ExitCode.OK; + return ExitCode.NOTHING_DONE; } try { @@ -48,6 +48,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { final AndroidFileSetStorage storage = new AndroidFileSetStorage(context.getDataManager().getDataStorageRoot(), "libs_packaging"); try { + boolean doneSomething = false; for (Module module : chunk.getModules()) { final AndroidFacet facet = AndroidJpsUtil.getFacet(module); if (facet == null || !facet.isLibrary()) { @@ -82,7 +83,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { if (subdirs.size() > 0) { context.processMessage(new ProgressMessage(AndroidJpsBundle.message("android.jps.progress.library.packaging", module.getName()))); final File outputJarFile = new File(outputDirectoryForPackagedFiles, AndroidCommonUtils.CLASSES_JAR_FILE_NAME); - + doneSomething = true; try { AndroidCommonUtils.packClassFilesIntoJar(ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.toStringArray(subdirs), outputJarFile); storage.update(module.getName(), newState); @@ -94,7 +95,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { } } } - return success ? ModuleLevelBuilder.ExitCode.OK : ModuleLevelBuilder.ExitCode.ABORT; + return success ? (doneSomething? ExitCode.OK : ExitCode.NOTHING_DONE) : ExitCode.ABORT; } finally { storage.close(); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java index c3f8d80ef2cd..e9ef804f1eef 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java @@ -61,7 +61,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder { @Override public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk)) { - return ModuleLevelBuilder.ExitCode.OK; + return ExitCode.NOTHING_DONE; } try { diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 2c6a41287403..0852f2e8fdfe 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -49,7 +49,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { try { final List toCompile = collectChangedFiles(context, chunk); if (toCompile.isEmpty()) { - return ExitCode.OK; + return ExitCode.NOTHING_DONE; } String moduleOutput = getModuleOutput(context, chunk); From d62313da175b2ad454492dde8f1339270ec03518 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Mar 2012 14:29:17 +0200 Subject: [PATCH 77/84] pin / unpin --- .../com/intellij/ide/actions/Switcher.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index c439f4bc4b08..158d0ecf6061 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -32,6 +32,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; @@ -75,6 +76,8 @@ import static java.awt.event.KeyEvent.*; @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod", "SSBasedInspection"}) public class Switcher extends AnAction implements DumbAware { private static volatile SwitcherPanel SWITCHER = null; + private static final Icon PIN_ON = IconLoader.getIcon("/general/autohideOn.png"); + private static final Icon PIN_OFF = IconLoader.getIcon("/general/autohideOff.png"); private static final Color BORDER_COLOR = Gray._135; private static final Color SEPARATOR_COLOR = BORDER_COLOR.brighter(); @NonNls private static final String SWITCHER_FEATURE_ID = "switcher"; @@ -189,7 +192,7 @@ public class Switcher extends AnAction implements DumbAware { addKeyListener(this); setBorder(new EmptyBorder(0, 0, 0, 0)); setBackground(Color.WHITE); - pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); + pathLabel.setHorizontalAlignment(SwingConstants.LEFT); final Font font = pathLabel.getFont(); pathLabel.setFont(font.deriveFont((float)10)); @@ -204,7 +207,19 @@ public class Switcher extends AnAction implements DumbAware { }; descriptions.setBorder(BorderFactory.createEmptyBorder(1, 4, 1, 4)); - descriptions.add(pathLabel); + descriptions.add(pathLabel, BorderLayout.CENTER); + final JLabel pinLabel = new JLabel(isPinnedMode() ? PIN_ON : PIN_OFF); + pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode"); + pinLabel.setBorder(IdeBorderFactory.createEmptyBorder(0, 10, 0, 0)); + descriptions.add(pinLabel, BorderLayout.EAST); + pinLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE = !UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; + pinLabel.setIcon(isPinnedMode() ? PIN_ON : PIN_OFF); + pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode"); + } + }); twManager = ToolWindowManager.getInstance(project); final DefaultListModel twModel = new DefaultListModel(); for (String id : twManager.getToolWindowIds()) { From cfbdc39e46263bfb6edc57f3260725e1714fa214 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 29 Mar 2012 16:35:21 +0400 Subject: [PATCH 78/84] NPE on null prompt --- .../execution/console/LanguageConsoleImpl.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 1be5c6ccf3c9..71b22aef2b5c 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -95,6 +95,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { private final JPanel myPanel = new JPanel(new MyLayout()); private String myTitle; + @Nullable private String myPrompt = "> "; private final LightVirtualFile myHistoryFile; private Editor myCurrentEditor; @@ -316,11 +317,12 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { return myHistoryFile; } + @Nullable public String getPrompt() { return myPrompt; } - public void setPrompt(String prompt) { + public void setPrompt(@Nullable String prompt) { // always add space to the prompt otherwise it may look ugly myPrompt = prompt != null && !prompt.endsWith(" ") ? prompt + " " : prompt; setPromptInner(myPrompt); @@ -435,8 +437,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { protected String addTextRangeToHistory(TextRange textRange, final EditorEx consoleEditor, boolean preserveMarkup) { final Document history = myHistoryViewer.getDocument(); final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true); - appendToHistoryDocument(history, myPrompt); - markupModel.addRangeHighlighter(history.getTextLength() - myPrompt.length(), history.getTextLength(), HighlighterLayer.SYNTAX, + if (myPrompt != null) { + appendToHistoryDocument(history, myPrompt); + } + markupModel.addRangeHighlighter(history.getTextLength() - StringUtil.length(myPrompt), history.getTextLength(), HighlighterLayer.SYNTAX, ConsoleViewContentType.USER_INPUT.getAttributes(), HighlighterTargetArea.EXACT_RANGE); From 1563df17f1fc1f08f8f4a90843c453aa4faa0910 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 29 Mar 2012 15:15:23 +0200 Subject: [PATCH 79/84] red code is green wildcard problems ++(IDEA-66750;IDEA-75178;IDEA-73377) --- .../impl/analysis/GenericsHighlightUtil.java | 44 +------------------ .../intellij/psi/util/TypeConversionUtil.java | 6 +-- .../psi/util/TypesDistinctProver.java | 9 ++-- .../genericsHighlighting/WildcardTypes.java | 44 +++++++++++++++++++ 4 files changed, 54 insertions(+), 49 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index be5894779a33..d2a350e0d918 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -688,7 +688,7 @@ public class GenericsHighlightUtil { return true; } } - if (isUncheckedTypeArgumentConversion(lTypeArg, rTypeArg)) return true; + if (!TypeConversionUtil.typesAgree(lTypeArg, rTypeArg, false)) return true; } return false; } @@ -730,48 +730,6 @@ public class GenericsHighlightUtil { return false; } - private static boolean isUncheckedTypeArgumentConversion (PsiType lTypeArg, PsiType rTypeArg) { - if (lTypeArg instanceof PsiPrimitiveType || rTypeArg instanceof PsiPrimitiveType) return false; - if (lTypeArg.equals(rTypeArg)) return false; - if (lTypeArg instanceof PsiCapturedWildcardType) { - //ignore capture conversion - return isUncheckedTypeArgumentConversion(((PsiCapturedWildcardType)lTypeArg).getWildcard(), rTypeArg); - } - if (rTypeArg instanceof PsiCapturedWildcardType) { - //ignore capture conversion - return isUncheckedTypeArgumentConversion(lTypeArg, ((PsiCapturedWildcardType)rTypeArg).getWildcard()); - } - - if (lTypeArg instanceof PsiWildcardType || rTypeArg instanceof PsiWildcardType) { - return !lTypeArg.isAssignableFrom(rTypeArg); - } - - if (lTypeArg instanceof PsiArrayType && rTypeArg instanceof PsiArrayType) { - return isUncheckedTypeArgumentConversion(((PsiArrayType)rTypeArg).getComponentType(), ((PsiArrayType)lTypeArg).getComponentType()); - } - if (lTypeArg instanceof PsiArrayType || rTypeArg instanceof PsiArrayType) return false; - if (lTypeArg instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)lTypeArg).getConjuncts()) { - if (!isUncheckedTypeArgumentConversion(type, rTypeArg)) return false; - } - return true; - } - if (!(lTypeArg instanceof PsiClassType)) { - LOG.error("left: "+lTypeArg + "; "+lTypeArg.getClass()); - } - if (rTypeArg instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)rTypeArg).getConjuncts()) { - if (!isUncheckedTypeArgumentConversion(lTypeArg, type)) return false; - } - return true; - } - if (!(rTypeArg instanceof PsiClassType)) { - LOG.error("right :"+rTypeArg + "; "+rTypeArg.getClass()); - } - return ((PsiClassType)lTypeArg).resolve() instanceof PsiTypeParameter || - ((PsiClassType)rTypeArg).resolve() instanceof PsiTypeParameter; - } - @Nullable public static HighlightInfo checkForeachLoopParameterType(PsiForeachStatement statement) { final PsiParameter parameter = statement.getIterationParameter(); diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 7aea5e6cdcdd..557c12198331 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -354,7 +354,7 @@ public class TypeConversionUtil { final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1); if (class1 instanceof PsiTypeParameter) { for (PsiType type : class1.getExtendsListTypes()) { - if (TypesDistinctProver.provablyDistinct(type, typeArg2)) return false; + if (TypesDistinctProver.provablyDistinct(type, typeArg2) && !isAssignable(type, typeArg2)) return false; } } } @@ -746,7 +746,7 @@ public class TypeConversionUtil { private static boolean isAssignableToWildcard(PsiWildcardType wildcardType, PsiType right) { if (wildcardType.isSuper()) { - return isAssignable(right, wildcardType.getSuperBound()); + return isAssignable(wildcardType.getSuperBound(), right); } return isAssignable(wildcardType.getExtendsBound(), right); } @@ -859,7 +859,7 @@ public class TypeConversionUtil { return true; } - private static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) { + public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) { if (typeLeft instanceof PsiWildcardType) { final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft; final PsiType leftBound = leftWildcard.getBound(); diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java index 4f86a7039399..4f479fc41c7f 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java @@ -92,7 +92,10 @@ public class TypesDistinctProver { for (PsiClassType type : parameter.getExtendsListTypes()) { if (!TypeConversionUtil.isAssignable(type, substitutedType1 != null ? substitutedType1 : substitutedType2, false)) return true; } - } else if (provablyDistinct(substitutedType1, substitutedType2)) return true; + } else { + if (provablyDistinct(substitutedType1, substitutedType2)) return true; + if (substitutedType1 instanceof PsiWildcardType && !((PsiWildcardType)substitutedType1).isBounded()) return true; + } } return false; } @@ -100,8 +103,8 @@ public class TypesDistinctProver { final PsiClass boundClass1 = classResolveResult1.getElement(); final PsiClass boundClass2 = classResolveResult2.getElement(); return type2 != null && type1 != null && !type1.equals(type2) && - !InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) && - !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true); + (!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) || + !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true)); } public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java index 5145e806c4b4..1a586323851c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java @@ -172,4 +172,48 @@ class My { public void test() { if (getSuperclass() == List.class); } +} + +class IDEA75178 { + void test(Set labels) { + final Matcher empty = isEmpty(); + assertThat(labels, empty); + assertAlsoThat(empty, labels); + } + + public static void assertThat(T actual, Matcher matcher) { throw new AssertionError(actual.toString() + matcher.toString());} + public static void assertAlsoThat(Matcher matcher, T actual) { throw new AssertionError(actual.toString() + matcher.toString());} + + public static Matcher isEmpty() { + return null; + } + + static class Matcher<T>{} + + class Foo {} + void testComment() { + Set foos = Collections.emptySet(); + assertThatComment(foos, hasSize(0)); + } + + Matcher> hasSize(int size) {return size == 0 ? null : null;} + void assertThatComment(T actual, Matcher matcher){ throw new AssertionError(actual.toString() + matcher.toString());} +} + +class IDEA66750 { + public void test() { + List> data = new ArrayList>(); + List> y = (List>)data; + System.out.println(y); + + ArrayList al = (ArrayList) new ArrayList(1); + System.out.println(al); + } +} + +class IDEA73377 { + public Iterator, ?>> iterator(Map map) { + //noinspection unchecked + return (Iterator, ?>>)map.entrySet().iterator(); + } } \ No newline at end of file From c7b47f11253a529c1576f34114145e1f8c0f1dea Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 29 Mar 2012 17:13:23 +0400 Subject: [PATCH 80/84] IDEA-81205 Indent on paste: Correct processing in case of 'indent block' 1. Corrected processing of the formatter-based 'adjust block on paste' when a pasted block starts with white space symbols; 2. Corresponding test has been added; --- .../BlockIndentOnPasteTest.groovy | 87 +++++++++++++------ .../editorActions/PasteHandler.java | 8 +- 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy index 23e2dcadaf3f..2b537de76906 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -618,7 +618,7 @@ class Test { doTest(before, toPaste2, expected) } - def testPlainTextPaste() { + void testPlainTextPaste() { def before = '''\ line1 line2 @@ -628,7 +628,7 @@ class Test { def toPaste = '''\ line to paste #1 - line to paste #2 + line to paste #2\ ''' @@ -641,10 +641,33 @@ line to paste #1 doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) } - def testPlainTextPasteWithCompleteReplacement() { + void "test plain text when pasted string ends by line feed"() { + def before = '''\ + line1 + line2 + +''' + + def toPaste = + '''\ +line to paste #1 +line to paste #2 +''' + + def expected = '''\ + line1 + line2 + line to paste #1 + line to paste #2 + +''' + doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) + } + + void "test plain text when caret is after selection"() { def before = '''\ line1 - line2\ +\ ''' def toPaste = @@ -655,32 +678,14 @@ line to paste #2 def expected = '''\ + line1 line to paste #1 line to paste #2 ''' doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) } - def testPlainTextMultilinePasteWithCaretAfterSelection() { - def before = '''\ - line1\ -''' - - def toPaste = - '''\ -line to paste #1 -line to paste #2 -''' - - - def expected = '''\ -line to paste #1 -line to paste #2 -''' - doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) - } - - def testPlainTextThatStartsByLineFeed() { + void testPlainTextThatStartsByLineFeed() { def before = '''\ line 1 # item1 @@ -715,6 +720,37 @@ line 1 doTest(before, toPaste2, expected2, StdFileTypes.PLAIN_TEXT) } + void "test formatter-based paste that starts with white space"() { + def before = '''\ +class Test { + int i; + int j; + + void test() { + + } +} +''' + + def toPaste = '''\ + int i; + int j;\ +''' + + def expected = '''\ +class Test { + int i; + int j; + + void test() { + int i; + int j; + } +} +''' + doTest(before, toPaste, expected) + } + def doTest(String before, toPaste, expected, FileType fileType = StdFileTypes.JAVA) { myFixture.configureByText(fileType, before) @@ -732,6 +768,7 @@ line 1 finally { settings.REFORMAT_ON_PASTE = old } + myFixture.editor.selectionModel.removeSelection() myFixture.checkResult(expected) } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java index 4b65a2c9716c..d2a99b30e253 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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,7 +379,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser // Algorithm: the main idea is to process the first line of the pasted block, adjust its indent if necessary, calculate indent // adjustment string and apply to each line of the pasted block starting from the second one. // - // We differentiate three possible states here: + // We differentiate the following possible states here: // --- pasted block doesn't start new line, i.e. there are non-white space symbols before it at the first line. // Example: // old content [pasted line 1 @@ -460,7 +460,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser final int i = CharArrayUtil.shiftBackward(chars, startOffset - 1, " \t"); - // Handle situation when pasted block doesn't start new line. + // Handle a situation when pasted block doesn't start a new line. if (chars.charAt(startOffset) != '\n' && i > 0 && chars.charAt(i) != '\n') { int firstNonWsOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t"); if (firstNonWsOffset > firstLineStart) { @@ -550,7 +550,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser } } else { - CharSequence toInsert = chars.subSequence(anchorLineStart, j + diff); + CharSequence toInsert = chars.subSequence(anchorLineStart, diff + startOffset); for (int line = anchorLine + 1; line <= lastLine; line++) { document.insertString(document.getLineStartOffset(line), toInsert); } From 33b7b9d9b09f53f5bb85607bb16d2ef5a6843bc5 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Mar 2012 15:34:43 +0200 Subject: [PATCH 81/84] add a small gap --- platform/icons/src/process/fs/step_1.png | Bin 1204 -> 1182 bytes platform/icons/src/process/fs/step_10.png | Bin 1202 -> 1188 bytes platform/icons/src/process/fs/step_11.png | Bin 1175 -> 1167 bytes platform/icons/src/process/fs/step_12.png | Bin 1188 -> 1165 bytes platform/icons/src/process/fs/step_13.png | Bin 1173 -> 1190 bytes platform/icons/src/process/fs/step_14.png | Bin 1195 -> 1188 bytes platform/icons/src/process/fs/step_15.png | Bin 1189 -> 1189 bytes platform/icons/src/process/fs/step_16.png | Bin 1194 -> 1163 bytes platform/icons/src/process/fs/step_17.png | Bin 1188 -> 1171 bytes platform/icons/src/process/fs/step_18.png | Bin 1189 -> 1183 bytes platform/icons/src/process/fs/step_2.png | Bin 1174 -> 1174 bytes platform/icons/src/process/fs/step_3.png | Bin 1187 -> 1170 bytes platform/icons/src/process/fs/step_4.png | Bin 1174 -> 1190 bytes platform/icons/src/process/fs/step_5.png | Bin 1190 -> 1188 bytes platform/icons/src/process/fs/step_6.png | Bin 1185 -> 1186 bytes platform/icons/src/process/fs/step_7.png | Bin 1184 -> 1160 bytes platform/icons/src/process/fs/step_8.png | Bin 1185 -> 1177 bytes platform/icons/src/process/fs/step_9.png | Bin 1194 -> 1183 bytes platform/icons/src/process/fs/step_mask.png | Bin 978 -> 997 bytes .../icons/src/process/fs/step_passive.png | Bin 1192 -> 1187 bytes 20 files changed, 0 insertions(+), 0 deletions(-) diff --git a/platform/icons/src/process/fs/step_1.png b/platform/icons/src/process/fs/step_1.png index a02f0d104b398b50d5f8dc52940ff7220f45417a..eb6c407124beac4edc399d9f81385a54bec4cf2b 100644 GIT binary patch delta 506 zcmdnOIgfLL8&iydg_E1Pv4xYlrMab{p{t>Vv7wWbqmi+Rv!RiTld+qULPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|8JFJ4ic03T_J=ap|3`$Lv)9 zkY6^8fq_xT)5S5Q;#Sh1|NrfoRU0N|u^AW{HD$)$=Fn7_%68lYXva|aW_WDcl>U!koEkfDd5d~^+Q5w1GB^WrckuFE4zOf1y{v{;1u-MtXKyy#Pbk|HfS|qH1k94JHEXS+#z-Dcp%; z+$dwl>>#yXn5%RF>;A?m3}(!BOse%lMhp^sZydV#XEVNUoV3QpWv`V$ags5ENJA1! z&U2<9Mu$H#vl+KHMzBeR-Y_XzsfD4dkqeM*;bvy(=&Ynrkz3&FYvq!k zT$-DjSK{ens{|C$OUX>Jg6eg~rFZfoCIgrSmbertDHN9krKVY>;I_aKm)^;G%ue;f z3^#ol7#KA?T^vIyZYBNs|KFZjwV|`o=>Su*fss*DX6$VaO@*mkNBA7ha39HasA28c z&+zf}>GtqHY%800&JjGvAjNQH4O_}NmPh9uY@|EpGk#Q7V9OL@O-fU!V=#Hb-o{u} zHZjQ|i%(!a!=sZ9uJb3(=aZuz%c)J7E|r+H~b7h;OXk;vd$@?2>|>RwzB{L diff --git a/platform/icons/src/process/fs/step_10.png b/platform/icons/src/process/fs/step_10.png index b6bfb992ece4a1610f1fcc17bf472efdde19caca..39aed3098195b47e575996efda71c2422c983375 100644 GIT binary patch delta 460 zcmdnQxrB3r8&kBgo3XKpqlK%vrMab{p{t>VnUSfJp{0qViK~U7n}M;CLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|4Ts*z3z-b%p=z9Qsrkqx3sd8QON}nGGeC;u5fChEBtG6qcKnh?cte+&rZt(oznDWQ-1Ve(w z24+pW9JW2|UYmpjzrJ!f(|ML5fT2rp!(46;R)&woIc#^>k|Z-i5-*?OT_UuQafh_B zY(tQe$wUu^kIWfU8jtiePEip!&TM#MLd=3Yv1>F1rT+Ub2;^cmZrmZ!v7V`r%ftBE h6pMtNf(i#1p6!emzRK@2$&vvGJYD@<);T3K0RReKpBw-H delta 474 zcmZ3&xruXw8&kBSsk5<(simR0g|nHVp{t>#fq}D&v6+*ZlcRx)o0GAULPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|2#4Ou3z-b%A!;n#aH;voBnwqzX@EYv|~$!HIB0`aau4f(Ud{Nz~JcZA>*)&NuYVr8&QGgM^VC3|5sj^GLx^TH##C%>55vwDq+SX wxr{mbZOhIuFSx>amdKI;Vst0QO6t&#L&dR(aqG{(%jO}(ACh<(7?sn(!$Zn)Ya9^+0aQzp(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=P}hD-0{MN9@T3yg6oQc@@`2}(_~O2KV`2`;^p^_ZRN zU$=kT&%nUQ?CIhdQgJKk&;S4S%&H9&v)BxbjG8iIZ*v$bOyxMT&OwJE^t)uoVtv`D ze?03M9nKm#q=^bNvwUaxm_0#6z&PG+&m)F_dCVu$7&q-d@b#cXRoTQp4qDP3@0mo` z9C@0uK=G5qE7c38_6{{_Dwe_u`+EJ2MfR{H)w4>l-((O}uyfM5&>+^3^XypK0rLe< zij|n>v(9E*@6lmvn8Wr*(M{bzK($ds+>Cjj)8bBn4UCV>Z}3zw9C@U`rjfNVaRKW? zhs;m~yJl_0j}3d6x{?!i6)6V=~kadBH63 rp6$_32gS4N6V@%sOH&eOV3A-@Vyk>zBQrmr0SG)@{an^LB{Ts5=OUw< delta 499 zcmeC@oX)wyjVZ>_$<@Tb!r0Q>!r9Ew(ACh<+}zaB#Ms%@*~G}j*~vsnp(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=Rfh)eI}MN9@T3(RpTQc@@`2}(_~O2KV`1ungl^_ZRN z11nX`85kJ3JzX3_DsCnH`TyUZS+$|F(dhtFvVoCNQ)cXK4o-!sY)ASW&Tvot$8+ST zL(Sh$4@LJoG8s%aJ|yYD+%PM(;SAe~)7O|ja<5?gmNtP34R{tFK?87HiW1N z*fTsj>)?9-!d&hx4qUHR{hrRJ`@dC=?U%zJmii9!gv&gv2I8Gb+%6MNx;M_Mf5c_5 z;Euh*SE-KHjglW^JM4udf5hD2`N72{td!g*J)OIQQQ_>I8$1>4N0bgsI5u-fL(v|{PMh51o^fRxyZNe(h>UJVX0%ssuwBZ8H# z%v|H(C9K(@zDV^cvx5!yil3I(me?fh6jV6C@OW*!yOl!U1O_1RboFyt=akR{0El<4 A;Q#;t diff --git a/platform/icons/src/process/fs/step_12.png b/platform/icons/src/process/fs/step_12.png index fe7462e4093ed267c5de79acf39c7633469b3008..31c891386732f3b3356f2add06527114e89d8973 100644 GIT binary patch delta 489 zcmZ3&*~_`XjVZ>&!qU>%$->0k(%jO}(AChw)X~Vzz{%Xg)X>$~$<$0qp(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=P}ic9b0MN9@T3yg3nQc@@`2}(_~O2KV`F)qE6^_ZRN zozL6kGcYhRdb&7dJM$nUPH zII3B)oaw2f-UHU1A}7)qcRk_X#ck5?!z$o&ePvD^Ygav6(ENolnF@6savggdYFZ~n zRPb(jYCiFo#74;vQ(3xqZam6l;VS4AQB^i^L4@E^6~&hdtZH41{tL}K7!CFLZl7(K zq9$;^ft_vF`tT8A?NR$p5tUD&eWfW8pAhI8@`~oF*&B#sCDKu6{1-oD!M<$i$(K delta 512 zcmeC>T*A4*jVZ>-#LU#u#l_s*!r9Ew(ACh<)WyQZ+{nbu)y&!1+0j%caYo^l_Nb6CT0B*)>8WCuUP z$2X_j!)=&XHotZ@V^|T%aiWJQiBG|f?MQsX4AzdNjTWLEGaD@=GEVUGFn@WYw6kG~ zw!nVoN5KxR_7~@JZ*k!F_{;F<_jEqp|GYxU^-hzfGe6>Y=xyJa$;PPmhxSA!PI(|S>Yb%k=YHi?kD@6VxA_=$i%~7ES2-$MDl$p0}yz+ L`njxgN@xNAvK^?| diff --git a/platform/icons/src/process/fs/step_13.png b/platform/icons/src/process/fs/step_13.png index 29ee724831885f5d2548df3ece16ab2b0687ec40..02210fd7087f7d84bc5ef5d774d0fae4ff407100 100644 GIT binary patch delta 514 zcmbQrxr}pz8&iylizn}v&og{85Dsj-E*iK&Z{LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|8JFJ4ic03T_J=ap|3`$Lv%e z;J&Msfq_xV)5S5Q;#Sh1|NrfoRU0N|u^AW{HD$)$=8#iJ4&k;56@Bhwoy z&OJS>J+JY~!LN$a3|G$Zr|e?*D6LS(btJwqf~TXk(L%VxwZTF*)JXDth0AtT^4(c!RNHvA%2+Um2(HBq`T=g?&xF#vBYs_cN@tQ;6d`GXJ5Ff_Q_$ z1vc3vCf-%kSeNnNWL@vcQ6ne8e6wM`io}7wvkm$?=JfO|bP$=%ILBfCQbt34FDFJf zeIvGGVj5BZ6O9>`7z%ZCF9_1@suTbK delta 497 zcmZ3+IhAvR8&iyvg|oT2nVYM*g|nHVp{t>VtE+{Zfsui+v9q(YiG`(-LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|4VT`@i5|o-|m4e#>7hHNL>oGgk zZ!$g6z`(%B>FMGaQgJKk&;S4S%&H9&v)BxbjG8iIZ*%A=q;ehQa?s&EV&hQ5(UBf+ zx95?hhir`eCPs&|3a!^1&Tt;t-tdE6pxA-;6hl&+f*-q75%*yR+ua^!3aJc7;v2Zu zEwmQRu<$4r6tHF}{Ib;f^g+Euryym|mJhm*CT2a=IajYc}Kk zh8uD#R><{BW?d-x$dv8HlEtPugY(FO3-kCwe+aJ%W0g94ykX-<)@-j9t6(mVrA!-n xuPiw3p#Ddo<9vfbz-RL{o|OlRlpPuv8Qy%&(zE*N_?!U#v#G1IsimWvlZCUZp|gRKLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|1ee~)i5|o-|m4e#>BV2kX>oGgk zOMK4R$-uxU;pyTSQgJKk&;S4S%&H9&v)BxbjG8iIZ*%x5Eag0M%0Y+eNRz`E)+7B5 z6_1}D){bksa`3C7G{coM+$mB_h8`D%75*_FVRF!6KQhr_4abqE4$gUr5)0DBPcm-( zX%ui!zGOKQ?{l`GNQXC^M+~R)>DIFer8@;F*Y|oGb1)p;&$RNT!yn0x%L$K8u>Co( zRPy8meTOVQf!l|VL`--RFC_Vaz2S$NnYe}{^TfsmZHKrW?PnWiI=pdMqJ3neWPw0O zaKpL>2bT+L@P9I6H)Bp?G(5pQ^Mc0VrIF$t^OJl#9ays*($od+vp;%z;mUVLsT)QC z%jdJVGG8;B!m*Wg$qD&czxFYHtX8OFK2qNJ!z$o&`5Mp414YUX4U7z%R}>aHo}3!U O00f?{elF{r5}E)X^0#XM delta 519 zcmZ3&xteo>8&iyvi-nPeshg|0g|nHVp{t>jqob3XiKCOLp^JsFlasTOLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|4VT`@i5|o-|m4e#>7hHNL>oGgk zANk7I!N9;M@9E+gQgJKk&;S4S%&H9&v)BxbjG8iIZ*!C>Eaf>W6rjU##J{oP=hMU5 z^BS)l{HiF;aODhVN*0r$bjV?Og*4WrOa(vYBvu7KcBvxn!wj~&JtnAyD*WR*;@{Bq zPr+I=!-9W;7F!a#Lf^iU49gp;J|0;v3(V~5-LCU6Ic(H-SjFFA&s?bGBXg4>PN9x7 z=}>9-r$+QoRp`;!_azBIfpHTVI!*`TLaT?eKTf0 z1$I6&h91r|1y!~q@f#!=xMboMEV5E~c5GoJTSsKW58i82I6{`NrTDQwvUac$@3`;8 zEVjhfgR7&S`6F*aPR;RILJQ3rMcN#K?^_34ar#&*z?Su|(^Qi`B9Dc`fZ^7=q901v ReK{C_z|+;wWt~$(69B8yr|19x diff --git a/platform/icons/src/process/fs/step_15.png b/platform/icons/src/process/fs/step_15.png index dd7c72f16c71bb04e31f95af91139d181ee5d5dd..96456a5122a643961a150baa431481a72cee392d 100644 GIT binary patch delta 513 zcmZ3=xs-E*8&iy_nVX}5sj;)UrMab{p{t>#g`u&Nn}va^k+HL@v$Ls^LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|1()8*i5|o-|m4e#>CtP|b>oGgk zE5A6-$iToT>FMGaQgQ3Z?E-k$K~ zcA?;&<981v?|;7kWX!>i`sb?IpA#ARUvmaOFxegDmwsqnybpUpt}utiqTlW9^AB|T zCTw=G$(gohCX;dOu9(MCitnzeU6{&n-Qrf6R!)|11>?%y)71~KT}o-c=BJ|J`-R2% z#es+}$4YVYBTpWlQ%L)h`POBxGpqX56^CTp0pExHX`se+B$CffMGsM0r|NCD3 R@?HiY@O1TaS?83{1OS$W#TWnp delta 513 zcmZ3=xs-E*8&iz4k&%(5k+F-pg|nHVp{t>#qmzk?rK6*nqqD2CiG{P0LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|6_?)0i5|o-|m4e#>XIy$G>oGgk z`)=GN$-uxU>FMGaQgJKk&;S4S%&H9&v)BxbjG8iIZ*!O_s4^aTb%m4jaur5UcAVNB6tG87ir&-7@&!x^3&Zs_>#1kV66Wb(`e?6E*SAiRr6K8l;}s@_ ze~d>~8Wg55i!}T&4R~lD!^k$}H`kIh=8eo|%xaE*JveNd*|gdiQy5d2?U*-;2v)sg zD3mi}=3^*SGT5?{Q-Xo(4f_oq239@|t;HK&GD!j5bt%Ah{l;Z33z!0|PBh-yz}#_v z;Z2^PKjsV)()JscxvcPYayZ2_tHrVNm9WVEMzsy`5tBbPJaubeU}h+pm8UY}MzcEu O5O})!xvX|*}%=v#mv#%(%jO}(ACh<*wxL^z|F|a#L>yf*~nQ*p(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=RfgiG(_MN9@T3oLLcQc@@`2}(_~O2KUb&}rBmH(8I_ zseVW6$20~8hX0-}jv*DdlK%YvZ_ljSF!2@Ji<_=R44Rn=&zK(7JDlM@lH~A5tV2K6 zZqFlQ4_P01Gv*_WU2#g?FK@XOFl%ZngfTzb>hM$Cf;S;0<;csJ1&(zNr+7NlW30CP z;q~ZYJ^74HV>4r{@+8&S4X<<>N-PBYSvd_9SJrQ4f3(@9<+h$eS$p9GUIx}{>`FX8 zSdToq!SjRrXbXd}NU{V2SEZQ}j{w7?^EY^Ia30BXkx1Ytzp00i_>zopr0GjrtmH+?% delta 518 zcmeC?T*bM;jVZ?2+{n<))y>7+!r9Ew(ACh=$;i>k(bd)2z}(f@(!@zgp(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=Rfic9b0MN9@T3!HE%Qc@@`2}(_~O2KV`GcLW8^_ZRN z>m!sJ85kJlJY5_^DsCnH`TyUZS+!we7Mp>QQB!8@ZH_PnRjwmU4rdsTDs0qusQLWq zp{T+v#&!HR85X2XNU~h;3Vz6MoWVbv@xcLAQ>lr(70kU>P7Yih_Q}Qx(gM35 zT;}ZIoKO|5VApWAVX4C(;T0!jrBZJ+un3%Ie8d?MtQ4?VV!}(#BMU6{F&wdPkPy*c zkfO!3)JC2$`7!&oDIBG0<`aTglkzgW{s0x3d=N}A2>6`8#zmvv4FO#rFVusr|( diff --git a/platform/icons/src/process/fs/step_17.png b/platform/icons/src/process/fs/step_17.png index 3184821bf5dcf9f4adec16860f69daf8b1321eba..bf4f3b9ec5b84ef0086725142c620f0546162bd9 100644 GIT binary patch delta 495 zcmZ3&Ihk{V8&iy#p^>GrtFxs!5E>e~8d^9yTDY2;S{gbV8yOjzIVves7BfY$pB`7IW9#?3dJQsscBXzxGk{2rFXI(vr~O$ zz`cD842KT1m_>8lwsUGM=U7tG@Pi}ZpRJF)@FXTp1ykXU-i?-`D_+`7*u`~Z zpTpJ~gF-bG(@cjyf*sX`KgBan*schFvq7>xf%C}ahAul{j_uYCIc;Yf!{KAY!tU-|uH8Qgq+Z$$Z zukhgPe|yy74F8eM20RRH|I`&&y&P^;l}+rj;IZI7^3q}J`2w}n1>8FtrWlT49_C7e%`awkY@k_Pgg&ebxsLQ0H0E-V*mgE delta 512 zcmbQtxrB3r8&iz4lcTetp`)|8g|nHVp{t>#v$>h0xq+h*5EvL)7%3@K7BfY$pB`7BQ8Zs3dJQsscBXzxGiwPrFXI(vs1l< z_*F9o21W@_7srr_TSsWZRl)tI>3}{U}V&k8GD-}OhJ|F$ew`8v=x)|9sa!e z^ib5^L1xBj$%i}(7#+@LIV{r^kY{;h?(j!kh4n~|!x|RTFFY3}^c&O`h%=aaGp?NJ zP{Yvio>BC#bMag01yaHaZ<&{vGr#nIkvO5A>&X1Z9sJ#C5<6Iq%yD?rqbnfWP$3rZ zIX#AvZOU)fC3+55lO!0p)`YvT{4rMuJC=69SmB>*3*!O?(Zgv6Y?T(riFNExGJc?; zVbo!uASx9s!6w7>==}i=qa(|>HO{dd`FdfCf%H6vi$X&36EYb}A2BQZ>rI)+A#j`d zV`4&%*_}hPgch1@WY!E=^r$V1ZE2_dg(ZKaR{S)-w!|i3r=Y?ChSFVdQ&MBb@0712|FaQ7m diff --git a/platform/icons/src/process/fs/step_18.png b/platform/icons/src/process/fs/step_18.png index ba0cb9b6147f9ae47a4cd9f3c04383b2f6553166..233501cadb812a8f088d61542d8f933ad438cb45 100644 GIT binary patch delta 507 zcmZ3=IiGWb8&iy#nW34flck}#rMab{p{t>#xuLV8k(;HXv!SVrxrM2cLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|2$$Z;iCgZF_ROjc6SLS1jEtHxV{db4DokZNa=PJ%oWN)1jSK>t z89)9#-5&mjVP*4cXETNsk-R77a2|j-&$>a5mAA=R%9bG2L;$X(SvOHkA!2)T9 zqJKII7U{DbdaEdqoovjo%yN9WK%!%5V};r zofuFw^o$|n5|PFq;sW&ykNO?fup9}zkWtrWs>vUb$HHO2;L%_3_gBrYECwL(boFyt I=akR{0NjrKyRfvyr8#sfDAZiGiV#LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|7?5|o-|m4e#>LtJ_%>oGgk zE18P5GcYhpdb&7CX>c@d~8|(--exSP{wVq05?-ykc2^R!^wtU!QQ9hsj~%eur0f0-KpPnr(9kVSIG* zhKaJ|C-zsWvN>!u43E@ZSZp)|Qa4I|kkRtwXxO9Be73>e;fz}gW08YS&)J68C;Sex zH5eY`Uh>J|VB_hA`3|mL7c>sDbuDjg}I@HtC5SDrG$_i>(q+L@y;X#R{s|442-?i5|o-|m4e#>6I^;H>oGgA z?77tVVsZ(yLcO8FRE{I-9CR3_{^L1vaXO!FecNS*6={+Rp{z#~>U~)sU02xLI74zt z?Ic{RTKy}g$o*&LVehCU* zOqzN*Y&EQ2MFNR!yaM|VrX65b5K~X6wwMsa`pEdhidJc-0_{Z%V zvdG~LlW$0_!%uaC+7B06xM~_zwAeHiLivyE33$oxut&P%IkV|v7PH3<&)pgrm>E8b WN6unv?Rmri1fH&bE-dSu5}E+fk)P!N delta 471 zcmbQnIgN9J8&izArIVwxg^8)Tg|nHVp{pT~W9e+->}=>}WN74UJg6cKHrFZfoCIgrS#<&zIDHN9krKVY>;I_a7m)^;G%uXz~ z8Q1$wE@4)v_f(k5c7)I24ENN3JV$;y)cpPQP;|c|lfiW3Ly`{64YN`k&xi?#cZ4&3 zEMCF*$Kemht4Hn*&UFbA3)00ogQhSa`QFGiEwNbd0+Z&7)$ii1w)_#Vl6b-VFnhjr{pfjNyQ*pIX~Zu@^^skFv-eviG3Ns2jaHSCYpyVSGUshcr7%=#~|Q1S_D z9#B;IQdwP$UIjOoOoGQ_pBM+rGKExLUvUYxJ#CkSEKG_SS28F}V|>*8fu&>G1d9eA zOND>zOYM~;rFca18IBzjUZW|PC9FN+63e5`49`k?f%8mRb&aN){1JI990m*(&T;1# T1Z>>P00f?{el9HQoD!Mzv6-`*v8kb>tAUfTiGj0{LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|9GBk7i5|o-|m4e#>Q(Sr{>oGfV zXy|{Q$H2hIHo1aXzMl2SHwPW&BTNo|ggf||KCba@pJsnJiy>q)$Am7%q%?(j>__Sw zXNY#RHdx4Zq%&>Q4`XhawX<=Gw17PGts<_wE33*TDu{n*is1@5%@p#P{VuDNLyfFP zq1^2F#z*rTucW&j6IEDeB4F>r?-Hl5&&g9~&%T<9qxlnrKPE=ZNUkw{pv@^(oNU~% zLWGsaAz)2M(4+|^4vn2>8zmvv4FO#uINoC5#= delta 485 zcmbQlxtMc<8&izAn}wy5o2jX}g|nHVp{t>#k&%(Jp_{pZv#YDKxr?KcLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|442-?i5|o-|m4e#>6I^;H>oGfV zyz)#hW?*0xpIpH#U(bHzox>W2BRLL#Bs=&SKE65K9&W?DvU%qm!E+2!3|DkmQrwsg z*#+d8AK5#c;X0z=9NaiVvZJ}N?au)Nhx2-qxIK0E@ukg>ch4KFa z#_q%e@)~MtuOc@{e&CK|;!kkC)}C`9{mFrY%qERLw9S|u8V_^yYO(1Ap5QyO&0!gX zfPIs?!=aZuz|g)qg;Pz5FW!~`2s~Z=T-G@yGywoMI;h(K diff --git a/platform/icons/src/process/fs/step_4.png b/platform/icons/src/process/fs/step_4.png index a237bd9c4a91093f2c0ce435a3fb1eb50a817388..c7b463f0662e854542db4ddee5251cd361153427 100644 GIT binary patch delta 491 zcmbQnxr}pz8&iy-qluf5v5T9zrMab{p{t>Vqnm-Fsk4Ejp{uE-n~R~6LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{U=)c}{?$%~i_U>3OGQlz9%ToRO;W|e}|0vA_YdME2K zJ8@)GvRr3iV3e9%!7NiRr;y5bgv~*R^T;BHGrUKpH&mQ^dRTj2XjYh$b`n>feelu(C0v*;eTa;+<=M;+cU z9Jx51Pq)5Jj;+g~hIMwD07F+jV^FQb9+?jN!>SH?42cVPtqjbJj|_KqL2Up delta 475 zcmZ3+IgN9J8&iyhiJPgTvx&30g|nHVp{t>zfswhZtBbL#nW2e+g|VBGLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|1()8*i5|o-|m4e#>CtP|b>oGfV zEDTOcVPIh7nq0vwQ?I9x%5?OTgAVtRJq|T29qI9Qdmc%8$ewxHQ^0nCVL_Ul!ey=w z%Z49(S8~b}rZGJ7S>gE7!8tEcVnMq2Nwy_C4L`U84w~kiV~q;nUn0|B@$1sUr{^ym zW=J{BuduK6^nQnC>BcLL3eOISbtpWyXVm)TtZ+w7;k9#rtGx@$pZNMG2i(mYCUP)K z6fSMHU*cxFi}8QM4grZvdv=sCJ$0Cs>R{M#Nl@brzE@X{2Q>RN8w7kdU*lPMph(%F bfsrBRX!Na__m(v=0D-5gp9{-6r-UW|=8>s! diff --git a/platform/icons/src/process/fs/step_5.png b/platform/icons/src/process/fs/step_5.png index a9793e2aa4fc7e5204ceb1ad1eaaae00452c87e5..a58da6614372f21a58c84b3a22e214f92ae9b2cc 100644 GIT binary patch delta 512 zcmZ3+xrB3r8&iy-tBa+ni=~^nrMab{p{t>Vi;1zLk*R^Hftj0$i=mm4LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{U=(Eyj;$%~i_U>3OGQlz9%ToRO;W|e}|0!vq1dME2K zJJs9FG2G0+z$oGA;uunKE9uYw|MtwP4V{fn2bhu#jEtHxV{dc#DJ_x6=}42q z8P+5H4Hb`{9@dU)x^gh)97j3>FGJQdRwLd6kX*O2ZjHg?;=-PA^>fp4ntW z>HU&)!E&{?zc)t$~4=f&W29{nJUE Q4Gciw>FVdQ&MBb@07pZ(BLDyZ delta 514 zcmZ3&xr}pz8&iyhlZl0?siTv*g|nHVp{t>VnUkrTsjI8Axr?QnrI~?}LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|8JFJ4i5|o-|m4e#>M_hU*>oGgk z2mDSEWnf^G@^oiobmU0|@6rjU$#J{oP?9;>A z^BS)l{HiF;aODhVN*05mwm`E;lTRvhQlf$%Tau{4ITooR?!yeWyFJWSG_7~|!?NOq z{-)r@wqoX$NeX2wk6w7UPiu}n)Uw2lrQ?4>{be2|hmGqU?y#iPu{{czVX=wP#^Ddw z>@*Vt=?>Wqk_UK>?C;?CA?$Fc@hpR-!ZWo)3;`0hhteEa1)>EK88kNhPc(kOpi$7U z@NBoYdO)A#EIqqqV+Iimg|n^>tu_%Rn;A4C71%E3Z&>ECK*?00SWUp5;Zfv;E8nG8 zc}hv0u(;l6_*FLBtL2so>k_4fQumlYa%=44KICxLexuq`#?!qFjBE_P-33hhBpu%} O0D-5gpUXO@geCx*w675W diff --git a/platform/icons/src/process/fs/step_6.png b/platform/icons/src/process/fs/step_6.png index 3c7b285e2e5b54847ce0ed4eee0287ceb6dd39f7..3838816d288f927052a6022b01aa4e448b103d32 100644 GIT binary patch delta 510 zcmZ3;xrlRv8&iytnTffHk+G|}rMab{p{t>Vi;0DWfwPODp{a?BnSr5_LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|4VT`@i5|o-|m4e#>7hHNL>oGgk zYd*X)kAZzKS zcz@n)ZjGB8FU|KUh5Lh^e1@`?zvZB`wP_%FwFH%oHR#l@fijn N@O1TaS?83{1ONt>zRLgr delta 509 zcmZ3)xsY>%8&iy>fuWO|nW?k6g|nHVp{t>VnT4~PldGGtiK(-ti?gwkLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|1()8*i5|o-|m4e#>CtP|b>oGgk z%jEr9#=yWR>gnPbQgJKk&;S4S%&HBYjZO!ck`0WEnlfW=bC@ZpG9FQKIKzI_#^DcR zhkuOSo=37CvS*(56tG=jSdhl25X^Xl_0e??F;2#f>>+tv7ba9ou)VnHx`|2CRpB4k z5&ed)e~YZeGaR)hd}4m|#k+l)z4J#VfexmR_4W&nEw9+Kho{4~Q6eQkxk^E6fu%Gv z126l|JUapFgzi>Phc!+v2b$-c^WK`_V)npTz*}(Pb3K9QiN+5YGzuCN&-Qw&2lR1D z-QeFKX&~L<_)>v!#RTE*v@``(&a2G)IbT|q@T5$0n7fm;<35w2hHZmMcjF?-j`z&T zkJ+zHG3MCHIptMOV}yW|-U5|BoE`B_!Z-BScvc=LQg&!yWbm30SCyUcWg`O+c)I$z JtaD0e0swf;tz!TH diff --git a/platform/icons/src/process/fs/step_7.png b/platform/icons/src/process/fs/step_7.png index 103ba21a4677fef9e7fa4836d6b3521061c164f1..aeef1d044d401dd5b554f10818f865102c5039f2 100644 GIT binary patch delta 484 zcmZ3$*}=KNjVZ>+$=Jl$+|AV7(%jO}(ACh<#m&Xi$;r&k(7+ieV63E2kz3&FYvq!k zT$-DjSK{ens{|C$OUX>Jg6cKHrFZfoCIgrS#<&zIDHN9krKVY>;I_a7m)^;G%ueshFfjb_ba4!+xRvzh|9^XC)rQVSrvpuT3)00;GA>!tID@<6Kck_(KsV#ZXoY9Ls0ZE}L&V&6?s9Lzn9KNM`PB`oCaVH8vdWjL~Y!NOkA z1;_b>gG3r1m2wH3W_o;EbXLWM%Z(PhB<`?oU||Vi>Eg9j5Mz539`L_O=NH=%|3=Oi j>|xAoQaa{LED{VQEitiNUp_7ah6IDBtDnm{r-UW|ophv= delta 508 zcmeC+T)?@(jVZ>`)WE>l(!|l+!r9Ew(ACh%%*Djn$lS!z&D7M_^_ZRN znP&I>W?*0x@pN$vskoK&=l_3uX4QtyMyCTz$p%J7O_{N`Il>fFxsLpCIKy`2jRTL+ zZ>}TT_2uIj7fB}QrMDP2urZhxGt4Yfs8pz9Uh24xrBm90_a2|g6VW!tsKAuMxzk>eUR?p%h93q2 z7wwrIZe#D*yFu~*_mT4*96$ISbeud*j2?Nh&u@sB!NI(w;fJvqa~Z=%b%QOIg)do7 zHD0;R^pP=#?F{>)c!xJky+%0>OdZb|3Z?JZXK->ZIl$i$&-5{JMeu*eU?rUga*WBZ z*so3DFe+8!pAf{JB=A?dqu#+#<4ZiV>HlN1rm*XnGqFf89N|wCzV##g5Caf+y85}S Ib4q9e0LnqCcK`qY diff --git a/platform/icons/src/process/fs/step_8.png b/platform/icons/src/process/fs/step_8.png index 03898c63b27a4077d435c506a5d7befbd025da85..06d4602e9071e194a57c1d898dcad989de2b353e 100644 GIT binary patch delta 501 zcmZ3;Ig@jP8&iz2fvJ(Do3VkprMab{p{t>jv!kn}v4xR^lYybRvx|X}LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|5SQM`i*n{@MD><2)IrsbDJH(Yw*| z>!pQHzc*e9Rrtob>gi!IwoHdVf*sX`KgBaX+pee&f3ra{f%C}ahAz9qds_MyKHw9W zooM`kUBF&Z>A`-cjV5Ny_ZU9rEAcQK?cy+Fp2uWpF35I*!I0gI*^hA}m)+b07oM{Q zMLN{T%w}wFn8CfmgR@`qsKXilBbyC)7~1}+D{PhQ*xJ~p@yOtTj=*x}t9H%H6P`@r zC{+`m5X81qo2}!%6Z1Fz4&Ez2n3oAEYw}0rv2YkLe8>%x7xNNxWB>wBS3j3^P6%8&iy>rL&8rg^7{5g|nHVp{t>zo1vkTtGSV-rKN$3o0FxILPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|7?5|o-|m4e#>LtJ_%>oGgk zZ&`ELgMooj)YHW=q~cc6pa1{unN=G)8=Vd?B^wwSHD$)$<_J?za8y}K%U~ZUowZSJ^!H(lde!~y>5aSa8tP0QA9&tN3+a3IJFqYwp4(pOM zrjLvY``AOi@Sok9-OBNjY!vKHGhpbN&mJ_#A*WqeK(?X6 zOz>fuWXIZ#k_?~jCo3_>bIxX5-|$0RaMsO+2(H{be zW7Sx+$3csCmDu5iy$*k5JH8fVu&vZ(N{V}Oz|G&|kHa!flfL(khgp_1NOrh3+>qz Jmvv4FO#o6jvKjyY diff --git a/platform/icons/src/process/fs/step_9.png b/platform/icons/src/process/fs/step_9.png index 10c777aca3c0e9d6ac6b3c2ac4096f67bd506101..c4a3766def38a4ac562079d1e784a9e2d036f7e7 100644 GIT binary patch delta 481 zcmZ3*IiGWb8&iz2qq(7liKCIZrMab{p{t>#v4y#dn~9~lfvc0Do0*}KLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|7?5|o-|m4e#>LtJ_%>oGfV z*iG4ant_2)cya}^d_CKd(+xl51U@rwWDwZQ`0?-Q_V7OpE1P%D5j@8r#c*W}Tgo|> zNBRzT7(!~q(ij8!#62V#KDsXWp+3V-O@%cm;4FKC1y`go2gA?#j4Z3<|RwuUN0}HsE2ftQQNoD9-fon?T3bjgkzPDyDZd)N|J#5xT)s!F;r( zfkPx&;saAhYo~#OWJl!&$pX=irypOkwAt~S^xip?c7Rnuj7jU!;f0b@__`V+q&mb8 z3M)i8F=bw3mu!=n>QI;*aHz@3R#u~&JKL*8>ls5(m%|_K4ts`=?h0W{s(KkF_J?Op hVb?KdVv%6jc_wA63iDhO1_mw$22WQ%mvv4FO#rf*ogDxG delta 492 zcmbQwxr%dx8&iyViKU~9g_EVJiGibqi;J<6LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|5trV{i5|o-|m4e#>3tW09>oGfV zycPJckb!|wZgK^)d_C8Z;|)JF1&oMQ(XI4&*A#g`1m`fuWJJg{!5Rv89EQLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|0+-&&i5|o-|m4e#>GhBKn>oGf( ziuKpeV_;y2^mK6yskn7!@J1rF!vFaP)du_~Ro$x*N}WJW$8>y*i>o^H6cWV>^a z+k+p8t`6HY&q#iLm7unFWkbyW@Sq>T4CaS=7{Yh7awkv9a8)?Gt!)2-<(egoYzz-3 W^Q)foEZz&Wgu&C*&t;ucLK6U3jc8r~ delta 300 zcmaFLeu;g98&iy{fw_sHtCOR-g|nHVp{t>ziK(fZiHoy^xrLdbk%g&}LPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|376ic03T_K5ap|3`$Ly38 zYA$t?fq}uz)5S5Q;#Sh1|NrfoRU0OXu?ZMW6r9g^#Hw9zHsk+~H(R{rrZe_fh*)L+lt8W@-vel$8ie3|Bu4K$I#)78&qol`;+0HMBG A*#H0l diff --git a/platform/icons/src/process/fs/step_passive.png b/platform/icons/src/process/fs/step_passive.png index e1d490fdbbeb99dce18e414c703fba0934da7dea..70d281bbc1b6f7b23a381b294db54f66b661f561 100644 GIT binary patch delta 485 zcmZ3%xtMc<8&kA}v7>>jrMa28rMab{p{t>zqp_KziG{P9n}LCWxwDCqLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|9EaY?3z-b%p=wNUsrkqx3sYl?ON}nGbA5F5>zND; zjN+ayjv*DdlK%YvZ_ljS(Ans8fGOF)$fzk(U0q#K;VI)0D~B^X^Y8C-TCqc7!Y_s= z|Cv4}>bVy(2250$z?2!l@`%^LM%43{t^hal)dGdri7hjqym@nmf61iAAAADunQnby zzPr=m>=_3y$qxB9cXxjm-^Jb2@I$m-;Qf(hk}M66>KE!wJS5g}$f1U3#S8Vug5MlR z7Tw@s$gJ_vxY8*0hcW2R4W1udQ~vm#U`Vjoz@({{!&bxSwMjtm>m`RXZD$z*7(NMa zm@DfM$?(xShs}mLNiZWM@iI?Wy|@CK>I!a&mkd*c7Iv{Xu4{CY^zdQTdd71^;pa>T z)1A*Ff|X4E-FI3n!nUc=LZCyQ@uSLwv^AQA2a1#(8Wjsj-ujvAL$_i>(q+L@y;X#R{s|2#4Ou3z-b%A!>}>aH;voBnwqzVt`AHF0*sJ%PhI+ z3=E7io-U3d6}OH|-ks&-DA2Z9{n1|`(;E`<2hW|;QcIfXE~ry8-NsdGBUfCLenN7p z<_r&g1zhyxljM*+n*eFg!hPW_|n3{~Fgz_5C7WeP4FppY%OCohx8Ydi3>^=MCD+>nAJ{u`qB>`Ru-+D12%QThBt@OQ&)~3o{M5 z11nyCxBBfTqr99YI73$a^rJIZWj)V+eRxM?M-yXb_WH(;x!w^Dx70qc&aY$R_ndt| zsIG=1#_5pvf%9F?XVg9@7AM^53s=4G)Uv7a=Eepd&1~U^IzAN*(h^Z~J%T3W`t>YZ zu4|Pa+t6%%bY}maW2>)r{#w>BugInR#+7q2oz|N3qSyY(uYc^ Date: Thu, 29 Mar 2012 15:57:38 +0200 Subject: [PATCH 82/84] fix test data --- .../fieldProperties/nonIncremental1/.idea/misc.xml | 2 +- .../src/org/jetbrains/jps/incremental/BuilderRegistry.java | 4 ++-- .../src/org/jetbrains/jps/incremental/java/JavaBuilder.java | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml index 8a6459d2c612..83d038f968a4 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index 62b2c1fd2cb4..dbe6eecef318 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -30,7 +30,7 @@ public class BuilderRegistry { myTasksExecutor = Executors.newFixedThreadPool(runtime.availableProcessors()); runtime.addShutdownHook(new Thread() { public void run() { - myTasksExecutor.shutdownNow(); + myTasksExecutor.shutdown(); } }); @@ -70,7 +70,7 @@ public class BuilderRegistry { } public void shutdown() { - myTasksExecutor.shutdownNow(); + myTasksExecutor.shutdown(); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 58db508502ac..0e5360167d20 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -868,7 +868,8 @@ public class JavaBuilder extends ModuleLevelBuilder { myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "OutOfMemoryError: insufficient memory")); } else { - myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, line)); + final BuildMessage.Kind kind = line.toLowerCase(Locale.US).contains("error")? BuildMessage.Kind.ERROR : BuildMessage.Kind.INFO; + myContext.processMessage(new CompilerMessage(BUILDER_NAME, kind, line)); } } } From 1c494ad50cb4e815de1a80306f850f74966191d2 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Mar 2012 16:10:50 +0200 Subject: [PATCH 83/84] correct speed search comparator --- .../platform-impl/src/com/intellij/ide/actions/Switcher.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 158d0ecf6061..697399225e26 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -763,6 +763,7 @@ public class Switcher extends AnAction implements DumbAware { public SwitcherSpeedSearch() { super(SwitcherPanel.this); addChangeListener(this); + setComparator(new SpeedSearchComparator(false, true)); } @Override From 684f8982a3a6edb5d8c7b50c946aa8b0cd943e10 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 29 Mar 2012 16:17:54 +0200 Subject: [PATCH 84/84] prefer current library when navigating from its source --- .../psi/resolve/ResolveInLibrariesTest.groovy | 54 +++++++++++++++++++ .../scopes/LibraryRuntimeClasspathScope.java | 13 +++-- .../file/impl/ResolveScopeManagerImpl.java | 27 +++++++++- .../intellij/testFramework/PsiTestUtil.java | 27 ++++++++-- .../EclipseLibrariesModificationsTest.java | 19 ++----- 5 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy new file mode 100644 index 000000000000..ceb2bbd93df6 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2012 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.psi.resolve + +import com.intellij.openapi.application.ex.PathManagerEx +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.testFramework.PsiTestUtil +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase + +/** + * @author peter + */ +class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase { + + public void "test prefer current library when navigation from its source"() { + def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib") + def nanoJar = lib.children.find { it.name.startsWith("nanoxml") } + def nanoSrc = lib.findChild("src").children.find { it.name.startsWith("nanoxml") } + + def jarCopy = myFixture.copyFileToProject(nanoJar.path, 'lib/nanoJar.jar') + def srcCopy = myFixture.copyFileToProject(nanoSrc.path, 'lib/nanoSrc.zip') + + PsiTestUtil.addLibrary(myModule, 'nano1', lib.path, ["/$nanoJar.name!/"] as String[], ["/src/$nanoSrc.name!/"] as String[]) + PsiTestUtil.addLibrary(myModule, 'nano2', jarCopy.parent.path, ["/$jarCopy.name!/"] as String[], ["/$srcCopy.name!/"] as String[]) + + def parsers = JavaPsiFacade.getInstance(project).findClasses('net.n3.nanoxml.IXMLParser', GlobalSearchScope.allScope(project)) + assert parsers.size() == 2 + + def file0 = parsers[0].navigationElement.containingFile + assert file0.virtualFile.path.startsWith(nanoSrc.path) + assert file0.findReferenceAt(file0.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(nanoSrc.path) + + def file1 = parsers[1].navigationElement.containingFile + assert file1.virtualFile.path.startsWith(srcCopy.path) + assert file1.findReferenceAt(file1.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(srcCopy.path) + + } + +} diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java index dbbbacc90f1d..90ad86b3980b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java @@ -29,6 +29,7 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -39,11 +40,9 @@ import java.util.Set; public class LibraryRuntimeClasspathScope extends GlobalSearchScope { private final ProjectFileIndex myIndex; private final LinkedHashSet myEntries = new LinkedHashSet(); - private final List myModules; public LibraryRuntimeClasspathScope(final Project project, final List modules) { super(project); - myModules = modules; myIndex = ProjectRootManager.getInstance(project).getFileIndex(); final Set processedSdk = new THashSet(); final Set processedLibraries = new THashSet(); @@ -63,8 +62,14 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope { } } + public LibraryRuntimeClasspathScope(Project project, LibraryOrderEntry entry) { + super(project); + myIndex = ProjectRootManager.getInstance(project).getFileIndex(); + Collections.addAll(myEntries, entry.getRootFiles(OrderRootType.CLASSES)); + } + public int hashCode() { - return myModules.hashCode(); + return myEntries.hashCode(); } public boolean equals(Object object) { @@ -72,7 +77,7 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope { if (object == null || object.getClass() != LibraryRuntimeClasspathScope.class) return false; final LibraryRuntimeClasspathScope that = (LibraryRuntimeClasspathScope)object; - return that.myModules.equals(myModules); + return that.myEntries.equals(myEntries); } private void buildEntries(@NotNull final Module module, diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java index d00bba8e12d7..a7c4277861f2 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.file.impl; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; @@ -25,6 +26,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.ResolveScopeManager; import com.intellij.psi.impl.source.resolve.FileContextUtil; +import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.util.containers.ConcurrentFactoryMap; @@ -91,6 +93,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { List modulesLibraryUsedIn = new ArrayList(); List orderEntries = projectFileIndex.getOrderEntriesForFile(vFile); + LibraryOrderEntry lib = null; for (OrderEntry entry : orderEntries) { ProgressManager.checkCanceled(); @@ -98,12 +101,32 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { return ((ProjectRootManagerEx)myProjectRootManager).getScopeForJdk((JdkOrderEntry)entry); } - if (entry instanceof LibraryOrderEntry || entry instanceof ModuleOrderEntry) { + if (entry instanceof LibraryOrderEntry) { + lib = (LibraryOrderEntry)entry; + modulesLibraryUsedIn.add(entry.getOwnerModule()); + } + else if (entry instanceof ModuleOrderEntry) { modulesLibraryUsedIn.add(entry.getOwnerModule()); } } - return ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn); + GlobalSearchScope allCandidates = ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn); + if (lib != null) { + final LibraryRuntimeClasspathScope preferred = new LibraryRuntimeClasspathScope(myProject, lib); + // prefer current library + return new DelegatingGlobalSearchScope(allCandidates, preferred) { + @Override + public int compare(VirtualFile file1, VirtualFile file2) { + boolean c1 = preferred.contains(file1); + boolean c2 = preferred.contains(file2); + if (c1 && !c2) return 1; + if (c2 && !c1) return -1; + + return super.compare(file1, file2); + } + }; + } + return allCandidates; } } diff --git a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java index 480dc6312069..4f66a034eae0 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java @@ -30,10 +30,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; @@ -278,4 +275,26 @@ import java.util.Collection; } }.execute().throwException(); } + + public static void addLibrary(final Module module, + final String libName, final String libDir, + final String[] classRoots, + final String[] sourceRoots) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); + final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, libDir); + final Library library = model.getModuleLibraryTable().createLibrary(libName); + final Library.ModifiableModel libModifiableModel = library.getModifiableModel(); + for (String classRoot : classRoots) { + libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES); + } + for (String sourceRoot : sourceRoots) { + libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES); + } + libModifiableModel.commit(); + model.commit(); + } + }); + } } \ No newline at end of file diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java index 05dfc5829a4b..d7972ddbb3fc 100644 --- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java +++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.ArrayUtil; public class EclipseLibrariesModificationsTest extends EclipseVarsTest { @@ -38,22 +39,8 @@ public class EclipseLibrariesModificationsTest extends EclipseVarsTest { final Project project = getProject(); final String path = project.getBaseDir().getPath() + "/test"; final Module module = EclipseClasspathTest.setUpModule(path, project); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); - final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, model.getContentRoots()[0].getParent().getPath()); - final Library library = model.getModuleLibraryTable().createLibrary("created"); - final Library.ModifiableModel libModifiableModel = library.getModifiableModel(); - for (String classRoot : classRoots) { - libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES); - } - for (String sourceRoot : sourceRoots) { - libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES); - } - libModifiableModel.commit(); - model.commit(); - } - }); + PsiTestUtil.addLibrary(module, "created", ModuleRootManager.getInstance(module).getContentRoots()[0].getParent().getPath(), classRoots, + sourceRoots); EclipseClasspathTest.checkModule(project.getBaseDir().getPath() + "/expected", module); }