diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index d2ae0f0f4fe4..ec9f324aa728 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -754,7 +754,7 @@ public class BuildManager implements ApplicationComponent{ myBuildsInProgress.remove(projectPath); notifySessionTerminationIfNeeded(sessionId, execFailure); - if (isProcessPreloadingEnabled() && !project.isDisposed()) { + if (isProcessPreloadingEnabled(project)) { runCommand(new Runnable() { public void run() { if (!myPreloadedBuilds.containsKey(projectPath)) { @@ -783,9 +783,20 @@ public class BuildManager implements ApplicationComponent{ return _future; } - private static boolean isProcessPreloadingEnabled() { + private static boolean isProcessPreloadingEnabled(Project project) { // automatically disable process preloading when debugging or testing - return !IS_UNIT_TEST_MODE && Registry.is("compiler.process.preload") && Registry.intValue("compiler.process.debug.port") <= 0; + if (IS_UNIT_TEST_MODE || !Registry.is("compiler.process.preload") || Registry.intValue("compiler.process.debug.port") > 0) { + return false; + } + if (project.isDisposed()) { + return true; + } + for (BuildProcessParametersProvider provider : project.getExtensions(BuildProcessParametersProvider.EP_NAME)) { + if (!provider.isProcessPreloadingEnabled()) { + return false; + } + } + return true; } private void notifySessionTerminationIfNeeded(UUID sessionId, @Nullable Throwable execFailure) { diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java index 1da1b5c26631..48ebb966fa65 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java @@ -47,5 +47,9 @@ public abstract class BuildProcessParametersProvider { public @NotNull List getVMArguments() { return Collections.emptyList(); } - + + public boolean isProcessPreloadingEnabled() { + return true; + } + } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalSystemJdkComboBox.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalSystemJdkComboBox.java index 4a1d89817cfd..d2ca6e62157b 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalSystemJdkComboBox.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalSystemJdkComboBox.java @@ -156,7 +156,7 @@ public class ExternalSystemJdkComboBox extends ComboBoxWithWidePopup { )); } - if (myProject != null) { + if (myProject != null && !myProject.isDisposed()) { final Sdk projectSdk = ProjectRootManager.getInstance(myProject).getProjectSdk(); result.put(ExternalSystemJdkUtil.USE_PROJECT_JDK, new JdkComboBoxItem( diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java index 31c1ecd533d1..207f6f86bce9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; -import com.intellij.psi.PsiCodeFragment; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -73,7 +72,6 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler { if (HintManagerImpl.getInstanceImpl().performCurrentQuestionAction()) return; //intentions check isWritable before modification: if (!file.isWritable()) return; - if (file instanceof PsiCodeFragment) return; TemplateState state = TemplateManagerImpl.getTemplateState(editor); if (state != null && !state.isFinished()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index 9e9460e8b896..20f304ea1ae8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -30,10 +30,7 @@ import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowType; import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; -import com.intellij.ui.DoubleClickListener; -import com.intellij.ui.InplaceButton; -import com.intellij.ui.PopupHandler; -import com.intellij.ui.UIBundle; +import com.intellij.ui.*; import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.tabs.TabsUtil; import com.intellij.util.BitUtil; @@ -224,6 +221,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS return true; } }.installOn(westPanel); + MouseForwarder.installOn(westPanel, this, true); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 60ccd5f21c04..0fda4c04a47d 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -205,7 +205,9 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { if (cmp == myCloseRec) return true; if (UIUtil.isDescendingFrom(cmp, myComp)) return true; if (myComp == null || !myComp.isShowing()) return false; - return myComp.contains(target.getScreenPoint().x, target.getScreenPoint().y); + Point point = target.getScreenPoint(); + SwingUtilities.convertPointFromScreen(point, myComp); + return myComp.contains(point); } public boolean isMovingForward(RelativePoint target) { diff --git a/platform/platform-resources-en/src/inspectionDescriptions/WrongPropertyKeyValueDelimiter.html b/platform/platform-resources-en/src/inspectionDescriptions/WrongPropertyKeyValueDelimiter.html new file mode 100644 index 000000000000..949a0108e642 --- /dev/null +++ b/platform/platform-resources-en/src/inspectionDescriptions/WrongPropertyKeyValueDelimiter.html @@ -0,0 +1,5 @@ + + +This inspection reports on properties in which key/value delimiter doesn't corresponds to code style settings. + + \ No newline at end of file diff --git a/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java b/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java index 55441aeb4a7f..f70d41102242 100644 --- a/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java +++ b/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java @@ -52,4 +52,17 @@ public class LogUtil { return ExceptionUtil.getThrowableText(e); } } + + public static String getSystemMemoryInfo() { + try { + @SuppressWarnings("SpellCheckingInspection") Process process = new ProcessBuilder() + .command(new String[]{SystemInfo.isWindows ? "systeminfo" : SystemInfo.isMac ? "vm_stat" : "free"}) + .redirectErrorStream(true) + .start(); + return FileUtil.loadTextAndClose(process.getInputStream()); + } + catch (IOException e) { + return ExceptionUtil.getThrowableText(e); + } + } } diff --git a/platform/util/src/com/intellij/ui/MouseForwarder.java b/platform/util/src/com/intellij/ui/MouseForwarder.java new file mode 100644 index 000000000000..cb07abfa77a7 --- /dev/null +++ b/platform/util/src/com/intellij/ui/MouseForwarder.java @@ -0,0 +1,70 @@ +package com.intellij.ui; + +import com.intellij.openapi.Disposable; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +public class MouseForwarder implements MouseListener{ + @NotNull private Component myTarget; + private boolean myLater; + + public static Disposable installOn(@NotNull final Component component, @NotNull Component target, boolean later) { + final MouseForwarder forwarder = new MouseForwarder(target, later); + component.addMouseListener(forwarder); + return new Disposable() { + @Override + public void dispose() { + component.removeMouseListener(forwarder); + } + }; + } + + private MouseForwarder(@NotNull Component target, boolean later) { + myTarget = target; + myLater = later; + } + private void redispatch(final MouseEvent e) { + Runnable runnable = new Runnable() { + @Override + public void run() { + myTarget.dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, myTarget)); + } + }; + if (myLater) { + //noinspection SSBasedInspection + SwingUtilities.invokeLater(runnable); + } + else { + runnable.run(); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + redispatch(e); + } + + @Override + public void mousePressed(MouseEvent e) { + redispatch(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + redispatch(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + redispatch(e); + } + + @Override + public void mouseExited(MouseEvent e) { + redispatch(e); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerMultilineEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerMultilineEditor.java index b2222ce556c5..be06fa33b14a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerMultilineEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerMultilineEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,13 @@ package com.intellij.xdebugger.impl.ui; import com.intellij.lang.Language; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; import com.intellij.ui.EditorTextField; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; @@ -54,6 +57,16 @@ public class XDebuggerMultilineEditor extends XDebuggerEditorBase { return editor; } + @Override + public Object getData(String dataId) { + if (LangDataKeys.CONTEXT_LANGUAGES.is(dataId)) { + return new Language[]{myExpression.getLanguage()}; + } else if (CommonDataKeys.PSI_FILE.is(dataId)) { + return PsiDocumentManager.getInstance(getProject()).getPsiFile(getDocument()); + } + return super.getData(dataId); + } + @Override protected boolean isOneLineMode() { return false; diff --git a/plugins/properties/properties-psi-api/properties-psi-api.iml b/plugins/properties/properties-psi-api/properties-psi-api.iml index fa09be36a180..bfbb8149469f 100644 --- a/plugins/properties/properties-psi-api/properties-psi-api.iml +++ b/plugins/properties/properties-psi-api/properties-psi-api.iml @@ -15,6 +15,7 @@ + + - - + \ No newline at end of file diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties index 1a58d5b832a4..19be683fa99a 100644 --- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties +++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties @@ -66,3 +66,4 @@ dissociate.resource.bundle.quick.fix.name=Dissociate Resource Bundle dissociate.resource.bundle.quick.fix.options.label=Additional language codes\: dissociate.resource.bundle.quick.fix.options.input.text=Inter language code dissociate.resource.bundle.quick.fix.options.input.title=Additional Locale Languages +wrong.property.key.value.delimiter.inspection.display.name=Property key/value delimiter doesn't correspond to code style \ No newline at end of file diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java index c114506ec4aa..ebafb102010d 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesElementFactory.java @@ -18,12 +18,14 @@ package com.intellij.lang.properties.psi; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.PropertiesFileType; +import com.intellij.lang.properties.psi.codeStyle.PropertiesCodeStyleSettings; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.UserDataCache; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFileFactory; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -42,14 +44,20 @@ public class PropertiesElementFactory { @NotNull public static IProperty createProperty(@NotNull Project project, @NonNls @NotNull String name, @NonNls @NotNull String value) { - String text = getPropertyText(name, value); + String text = getPropertyText(name, value, null, project); final PropertiesFile dummyFile = createPropertiesFile(project, text); return dummyFile.getProperties().get(0); } @NotNull - public static String getPropertyText(@NonNls @NotNull String name, @NonNls @NotNull String value) { - return escape(name) + "=" + escapeValue(value); + public static String getPropertyText(@NonNls @NotNull String name, + @NonNls @NotNull String value, + @NonNls @Nullable Character delimiter, + @Nullable Project project) { + if (delimiter == null) { + delimiter = project == null ? PropertiesCodeStyleSettings.DEFAULT_KEY_VALUE_DELIMITER : PropertiesCodeStyleSettings.getInstance(project).KEY_VALUE_DELIMITER; + } + return escape(name) + String.valueOf(delimiter) + escapeValue(value); } @NotNull diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettings.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettings.java new file mode 100644 index 000000000000..1ba1422ff3a4 --- /dev/null +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettings.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.lang.properties.psi.codeStyle; + +import com.intellij.lang.properties.PropertiesLanguage; +import com.intellij.openapi.project.Project; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; + +/** + * @author Dmitry Batkovich + */ +public class PropertiesCodeStyleSettings extends CustomCodeStyleSettings { + public final static char DEFAULT_KEY_VALUE_DELIMITER = '='; + + public PropertiesCodeStyleSettings(CodeStyleSettings container) { + super(PropertiesLanguage.INSTANCE.getID(), container); + } + + public static PropertiesCodeStyleSettings getInstance(final Project project) { + return CodeStyleSettingsManager.getSettings(project).getCustomSettings(PropertiesCodeStyleSettings.class); + } + + public char KEY_VALUE_DELIMITER = DEFAULT_KEY_VALUE_DELIMITER; +} diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsPanel.form b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsPanel.form new file mode 100644 index 000000000000..1c2c50f97d1b --- /dev/null +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsPanel.form @@ -0,0 +1,37 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsPanel.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsPanel.java new file mode 100644 index 000000000000..6c9819b77695 --- /dev/null +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsPanel.java @@ -0,0 +1,111 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.lang.properties.psi.codeStyle; + +import com.intellij.application.options.CodeStyleAbstractPanel; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.highlighter.EditorHighlighter; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * @author Dmitry Batkovich + */ +public class PropertiesCodeStyleSettingsPanel extends CodeStyleAbstractPanel { + private final static String WHITESPACE_ELEMENT = "Whitespace symbol"; + + private ComboBox myDelimiterCombo; + private JPanel myPanel; + + public PropertiesCodeStyleSettingsPanel(CodeStyleSettings settings) { + super(settings); + final DefaultComboBoxModel model = new DefaultComboBoxModel(); + model.addElement(':'); + model.addElement('='); + model.addElement(WHITESPACE_ELEMENT); + myDelimiterCombo.setModel(model); + selectChar(settings.getCustomSettings(PropertiesCodeStyleSettings.class)); + } + + private void selectChar(PropertiesCodeStyleSettings settings) { + myDelimiterCombo.setSelectedItem(settings.KEY_VALUE_DELIMITER == ' ' ? WHITESPACE_ELEMENT : settings.KEY_VALUE_DELIMITER); + } + + private char getSelectedChar() { + final Object item = myDelimiterCombo.getModel().getSelectedItem(); + if (item instanceof Character) { + return (Character)item; + } + assert item == WHITESPACE_ELEMENT; + return ' '; + } + + private void createUIComponents() { + } + + @Override + protected int getRightMargin() { + return 0; + } + + @Nullable + @Override + protected EditorHighlighter createHighlighter(EditorColorsScheme scheme) { + return null; + } + + @NotNull + @Override + protected FileType getFileType() { + return StdFileTypes.PROPERTIES; + } + + @Nullable + @Override + protected String getPreviewText() { + return null; + } + + @Override + public void apply(CodeStyleSettings settings) throws ConfigurationException { + final PropertiesCodeStyleSettings propertiesCodeStyleSettings = settings.getCustomSettings(PropertiesCodeStyleSettings.class); + propertiesCodeStyleSettings.KEY_VALUE_DELIMITER = getSelectedChar(); + } + + @Override + public boolean isModified(CodeStyleSettings settings) { + final PropertiesCodeStyleSettings propertiesCodeStyleSettings = settings.getCustomSettings(PropertiesCodeStyleSettings.class); + return propertiesCodeStyleSettings.KEY_VALUE_DELIMITER != getSelectedChar(); + } + + @Nullable + @Override + public JComponent getPanel() { + return myPanel; + } + + @Override + protected void resetImpl(CodeStyleSettings settings) { + selectChar(settings.getCustomSettings(PropertiesCodeStyleSettings.class)); + } +} diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java new file mode 100644 index 000000000000..7746d66f670d --- /dev/null +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/codeStyle/PropertiesCodeStyleSettingsProvider.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.lang.properties.psi.codeStyle; + +import com.intellij.application.options.CodeStyleAbstractConfigurable; +import com.intellij.application.options.CodeStyleAbstractPanel; +import com.intellij.lang.properties.PropertiesLanguage; +import com.intellij.openapi.options.Configurable; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Dmitry Batkovich + */ +public class PropertiesCodeStyleSettingsProvider extends CodeStyleSettingsProvider { + @NotNull + @Override + public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { + return new CodeStyleAbstractConfigurable(settings, originalSettings, "Properties Files") { + @Nullable + @Override + public String getHelpTopic() { + return "reference.settingsdialog.codestyle.properties"; + } + + @Override + protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) { + return new PropertiesCodeStyleSettingsPanel(settings); + } + }; + } + + @Nullable + @Override + public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) { + return new PropertiesCodeStyleSettings(settings); + } + + @Nullable + @Override + public String getConfigurableDisplayName() { + return PropertiesLanguage.INSTANCE.getDisplayName(); + } +} \ No newline at end of file diff --git a/plugins/properties/properties-psi-impl/properties-psi-impl.iml b/plugins/properties/properties-psi-impl/properties-psi-impl.iml index d297116cb114..e40048fbfeb1 100644 --- a/plugins/properties/properties-psi-impl/properties-psi-impl.iml +++ b/plugins/properties/properties-psi-impl/properties-psi-impl.iml @@ -16,6 +16,7 @@ + diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/WrongPropertyKeyValueDelimiterInspection.java b/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/WrongPropertyKeyValueDelimiterInspection.java new file mode 100644 index 000000000000..b8ead119072f --- /dev/null +++ b/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/WrongPropertyKeyValueDelimiterInspection.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection; + +import com.intellij.codeInsight.intention.HighPriorityAction; +import com.intellij.lang.properties.PropertiesBundle; +import com.intellij.lang.properties.PropertySuppressableInspectionBase; +import com.intellij.lang.properties.psi.codeStyle.PropertiesCodeStyleSettings; +import com.intellij.lang.properties.psi.impl.PropertiesFileImpl; +import com.intellij.lang.properties.psi.impl.PropertyImpl; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +/** + * @author Dmitry Batkovich + */ +public class WrongPropertyKeyValueDelimiterInspection extends PropertySuppressableInspectionBase { + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { + if (!(holder.getFile() instanceof PropertiesFileImpl)) { + return PsiElementVisitor.EMPTY_VISITOR; + } + final PropertiesCodeStyleSettings codeStyleSettings = PropertiesCodeStyleSettings.getInstance(holder.getProject()); + final char codeStyleKeyValueDelimiter = codeStyleSettings.KEY_VALUE_DELIMITER; + return new PsiElementVisitor() { + @Override + public void visitElement(PsiElement element) { + if (element instanceof PropertyImpl) { + final Character delimiter = ((PropertyImpl)element).getKeyValueDelimiter(); + if (delimiter != null && !delimiter.equals(codeStyleKeyValueDelimiter)) { + holder.registerProblem(element, PropertiesBundle.message("wrong.property.key.value.delimiter.inspection.display.name"), new ReplaceKeyValueDelimiterQuickFix(element)); + } + } + } + }; + } + + private static final class ReplaceKeyValueDelimiterQuickFix extends LocalQuickFixOnPsiElement implements HighPriorityAction { + public ReplaceKeyValueDelimiterQuickFix(@NotNull PsiElement element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return getFamilyName(); + } + + @Override + public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement element, @NotNull PsiElement endElement) { + ((PropertyImpl) element).replaceKeyValueDelimiterWithDefault(); + } + + @NotNull + @Override + public String getFamilyName() { + return "Replace Property Key/Value Delimiter According Code Style"; + } + } +} diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java b/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java index 60ad79f7e1b3..28d36a0af23e 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/codeInspection/unsorted/AlphaUnsortedPropertiesFileInspection.java @@ -22,6 +22,7 @@ import com.intellij.lang.properties.ResourceBundle; import com.intellij.lang.properties.psi.PropertiesElementFactory; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.lang.properties.psi.PropertiesList; +import com.intellij.lang.properties.psi.codeStyle.PropertiesCodeStyleSettings; import com.intellij.lang.properties.psi.impl.PropertiesFileImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -127,12 +128,12 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool { return Comparing.compare(p1.getKey(), p2.getKey()); } }); - + final char delimiter = PropertiesCodeStyleSettings.getInstance(file.getProject()).KEY_VALUE_DELIMITER; final StringBuilder rawText = new StringBuilder(); for (int i = 0; i < properties.size(); i++) { IProperty property = properties.get(i); final String value = property.getValue(); - rawText.append(PropertiesElementFactory.getPropertyText(property.getName(), value != null ? value : "")); + rawText.append(PropertiesElementFactory.getPropertyText(property.getName(), value != null ? value : "", delimiter, null)); if (i != properties.size() - 1) { rawText.append("\n"); } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java index 7c77848a47ba..b839ff919e15 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java @@ -99,6 +99,16 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { } } + public Character findFirstKeyValueDelimiter() { + for (IProperty property : myProperties) { + final Character separator = ((PropertyImpl)property).getKeyValueDelimiter(); + if (separator != null) { + return separator; + } + } + return null; + } + @Override public IProperty findPropertyByKey(@NotNull String key) { ensurePropertiesLoaded(); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java index 0d34b1e74126..2bce158b7069 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java @@ -441,4 +441,24 @@ public class PropertyImpl extends PropertiesStubElementImpl implem public LiteralTextEscaper createLiteralTextEscaper() { return new PropertyImplEscaper(this); } + + @Nullable + public Character getKeyValueDelimiter() { + final PsiElement delimiter = findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR); + if (delimiter == null) { + return null; + } + final String separatorText = delimiter.getText(); + LOG.assertTrue(separatorText.length() == 1); + return separatorText.charAt(0); + } + + public void replaceKeyValueDelimiterWithDefault() { + PropertyImpl property = (PropertyImpl)PropertiesElementFactory.createProperty(getProject(), "yyy", "xxx"); + final ASTNode oldDelimiter = getNode().findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR); + LOG.assertTrue(oldDelimiter != null); + final ASTNode newDelimiter = property.getNode().findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR); + LOG.assertTrue(newDelimiter != null); + getNode().replaceChild(oldDelimiter, newDelimiter); + } } diff --git a/plugins/properties/src/META-INF/plugin.xml b/plugins/properties/src/META-INF/plugin.xml index d928df37ea79..dbe1091741a4 100644 --- a/plugins/properties/src/META-INF/plugin.xml +++ b/plugins/properties/src/META-INF/plugin.xml @@ -81,6 +81,10 @@ key="alpha.unsorted.properties.file.inspection.display.name" groupKey="properties.files.inspection.group.display.name" enabledByDefault="false" level="INFO" implementationClass="com.intellij.codeInspection.unsorted.AlphaUnsortedPropertiesFileInspection"/> + @@ -99,6 +103,8 @@ + + diff --git a/plugins/properties/testData/wrongPropertyKeyDelimiter/expected.xml b/plugins/properties/testData/wrongPropertyKeyDelimiter/expected.xml new file mode 100644 index 000000000000..245d7fe84930 --- /dev/null +++ b/plugins/properties/testData/wrongPropertyKeyDelimiter/expected.xml @@ -0,0 +1,13 @@ + + + + Test1.properties + 2 + Property key/value delimiter doesn't correspond to code style + + + Test1.properties + 3 + Property key/value delimiter doesn't correspond to code style + + \ No newline at end of file diff --git a/plugins/properties/testData/wrongPropertyKeyDelimiter/src/Test1.properties b/plugins/properties/testData/wrongPropertyKeyDelimiter/src/Test1.properties new file mode 100644 index 000000000000..3759b7d43ff9 --- /dev/null +++ b/plugins/properties/testData/wrongPropertyKeyDelimiter/src/Test1.properties @@ -0,0 +1,4 @@ +a=1 +c:123 +z 123123 +zxc=zxc \ No newline at end of file diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java index b0d0c5e162f2..ee61d7ba27f0 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java @@ -18,6 +18,8 @@ package com.intellij.lang.properties; import com.intellij.lang.properties.psi.PropertiesElementFactory; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.lang.properties.psi.Property; +import com.intellij.lang.properties.psi.codeStyle.PropertiesCodeStyleSettings; +import com.intellij.lang.properties.psi.impl.PropertyImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.testFramework.LightPlatformTestCase; @@ -97,8 +99,9 @@ public class PropertiesFileTest extends LightPlatformCodeInsightFixtureTestCase PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "xxx=yyy\nxxx2=tyrt\nxxx3=ttt\n\n"); final Property property = (Property)propertiesFile.findPropertyByKey("xxx2"); - WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() { - property.delete(); + WriteCommandAction.runWriteCommandAction(null, new Runnable() { + public void run() { + property.delete(); } }); @@ -177,4 +180,15 @@ public class PropertiesFileTest extends LightPlatformCodeInsightFixtureTestCase assertEquals(" e=f", properties.get(2).getUnescapedKey()); assertEquals("\u1234\\uxyzt", properties.get(3).getUnescapedKey()); } + + public void testNonDefaultKeyValueDelimiter() { + final PropertiesCodeStyleSettings codeStyleSettings = PropertiesCodeStyleSettings.getInstance(getProject()); + codeStyleSettings.KEY_VALUE_DELIMITER = ':'; + final PropertyImpl property = (PropertyImpl)PropertiesElementFactory.createProperty(getProject(), "xxx", "yyy"); + final Character delimiter = property.getKeyValueDelimiter(); + assertNotNull(delimiter); + assertEquals(':', (char)delimiter); + assertEquals("xxx:yyy", property.getPsiElement().getText()); + codeStyleSettings.KEY_VALUE_DELIMITER = PropertiesCodeStyleSettings.DEFAULT_KEY_VALUE_DELIMITER; + } } diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/WrongPropertyKeyValueDelimiterInspectionTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/WrongPropertyKeyValueDelimiterInspectionTest.java new file mode 100644 index 000000000000..afb0a79343fd --- /dev/null +++ b/plugins/properties/testSrc/com/intellij/lang/properties/WrongPropertyKeyValueDelimiterInspectionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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.lang.properties; + +import com.intellij.codeInspection.WrongPropertyKeyValueDelimiterInspection; +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.InspectionTestCase; +import org.jetbrains.annotations.NotNull; + +/** + * @author Dmitry Batkovich + */ +public class WrongPropertyKeyValueDelimiterInspectionTest extends InspectionTestCase { + + @NotNull + @Override + protected String getTestDataPath() { + return PluginPathManager.getPluginHomePath("properties") + "/testData"; + } + + public void testSimple() throws Exception { + doTest("wrongPropertyKeyDelimiter/", new WrongPropertyKeyValueDelimiterInspection()); + } +} diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/PerspectiveFileEditor.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/PerspectiveFileEditor.java index 7e57a41074d4..5307483cb76e 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ui/PerspectiveFileEditor.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/PerspectiveFileEditor.java @@ -48,6 +48,8 @@ import java.beans.PropertyChangeSupport; abstract public class PerspectiveFileEditor extends UserDataHolderBase implements DocumentsEditor, Committable { private final Wrapper myWrapper = new Wrapper(); private boolean myInitialised = false; + /** createCustomComponent() is in progress */ + private boolean myInitializing; private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this); private final Project myProject; @@ -214,7 +216,9 @@ abstract public class PerspectiveFileEditor extends UserDataHolderBase implement if (!checkIsValid() || myInvalidated) return; ensureInitialized(); setShowing(true); - reset(); + if (myInitialised) { + reset(); + } } protected final void setShowing(final boolean b) { @@ -222,8 +226,10 @@ abstract public class PerspectiveFileEditor extends UserDataHolderBase implement } protected final synchronized void ensureInitialized() { - if (!isInitialised()) { - myWrapper.setContent(createCustomComponent()); + if (!isInitialised() && !myInitializing) { + myInitializing = true; + JComponent component = createCustomComponent(); + myWrapper.setContent(component); myInitialised = true; } }