From a03cf30603c15c11b9d9b55115b6ad5661551044 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Wed, 11 Feb 2015 03:16:57 +0300 Subject: [PATCH 01/32] gradle tests: fix for upward compatibility with groovy gradle plugins --- .../gradle/tooling/builder/AbstractModelBuilderTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java index 4ed63cd009ac..706693e11da2 100644 --- a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java +++ b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; import org.gradle.tooling.BuildActionExecuter; import org.gradle.tooling.GradleConnector; import org.gradle.tooling.ProjectConnection; @@ -150,7 +151,8 @@ public abstract class AbstractModelBuilderTest { // gradle-tooling-extension-api jar ProjectImportAction.class, // gradle-tooling-extension-impl jar - ModelBuildScriptClasspathBuilderImpl.class + ModelBuildScriptClasspathBuilderImpl.class, + ShortTypeHandling.class ); ContainerUtil.addAllNotNull(classes, doGetToolingExtensionClasses()); From 5e0f014c773bdad9409dc48ab8c55504a56b8260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Wed, 11 Feb 2015 09:03:43 +0100 Subject: [PATCH 02/32] jetbrains.dic: +"uncommenting" --- spellchecker/src/com/intellij/spellchecker/jetbrains.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 55a6c61237b4..99657468b768 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -601,6 +601,7 @@ unboxing unbuffered uncomment uncommented +uncommenting undef underwave undoable From 4c8db81822baf0f785b4fba382105d1556e96e45 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 11:10:05 +0300 Subject: [PATCH 03/32] Added not null check to prevent from inserting fqn in javadoc if fqn is null (EA-64712) --- .../JavaClassNameInsertHandler.java | 2 +- .../completion/JavadocCompletionTest.groovy | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java index 51ab95efc0da..48ddfdcaa851 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java @@ -132,7 +132,7 @@ class JavaClassNameInsertHandler implements InsertHandler} + */ + Super aSuper = new Super(); + + } +} +''' + myFixture.configureByText "a.java", text + myFixture.completeBasic() + myFixture.type('\t') + myFixture.checkResult ''' +public class Test { + + public static void main(String[] args) { + class Super { + } + + /** + * {@link Super} + */ + Super aSuper = new Super(); + + } +} +''' + + } public void testShortNameIfImplicitlyImported() { javaSettings.CLASS_NAMES_IN_JAVADOC = JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED From 752dfdc582d6b0952bb3edd3829e60f7e2293336 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 11 Feb 2015 09:27:39 +0100 Subject: [PATCH 04/32] CIDR: temp fix for IDEA installers --- build/scripts/libLicenses.gant | 1 + 1 file changed, 1 insertion(+) diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index f7c62a02dc4d..333c8135687b 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -278,6 +278,7 @@ libraryLicense(name: "json-smart", libraryName: "json-smart-1.1.1.jar", version: libraryLicense(name: "fxg-utils", libraryName: "fxg-utils", version: "4.9.1", license: "Apache 2.0", url: "http://flex.apache.org", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "jayatana", libraryName: "jayatana", version: "1.2.4", license: "MIT License", url: "https://code.google.com/p/java-swing-ayatana/", licenseUrl: "http://opensource.org/licenses/mit-license.php") libraryLicense(name: "ForkJoin", version: "", license: "Creative Commons Public Domain Dedication", url: "http://gee.cs.oswego.edu/dl/concurrency-interest/index.html", licenseUrl: "http://creativecommons.org/publicdomain/zero/1.0/") +libraryLicense(name: "ANTLR 4 Runtime", libraryName: "antlr-runtime-4.1.jar", version: "4.1", license: "BSD", url: "http://www.antlr.org", licenseUrl: "http://www.antlr.org/license.html") libraryLicense(name: "minlog", libraryName: "minlog-1.2.jar", version: "1.2", license: "BSD", url: "https://github.com/EsotericSoftware/minlog", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0") From 177450ca468b0784d821a68b132dcd7cc77eef55 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 11 Feb 2015 11:27:42 +0300 Subject: [PATCH 05/32] Properties Files: insert new property in alpha-order if it is possible (addPropertyFirst, addPropertyLast) removed --- .../lang/properties/psi/PropertiesFile.java | 11 +--- ...AlphaUnsortedPropertiesFileInspection.java | 33 ++---------- .../lang/properties/PropertiesImplUtil.java | 20 +++++-- .../psi/impl/PropertiesFileImpl.java | 53 +++++++++++++------ .../properties/xml/XmlPropertiesFileImpl.java | 15 ++---- ...urceBundlePropertiesInsertManagerImpl.java | 40 ++++++-------- 6 files changed, 78 insertions(+), 94 deletions(-) diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesFile.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesFile.java index 2b9a3743631e..b269e1a6fdb4 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesFile.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertiesFile.java @@ -89,18 +89,9 @@ public interface PropertiesFile { */ @NotNull PsiElement addPropertyAfter(@NotNull Property property, @Nullable Property anchor) throws IncorrectOperationException; - /** - * delegates call to {@link PropertiesFile#addPropertyLast()} method - */ - @Deprecated IProperty addProperty(String key, String value); - IProperty addPropertyFirst(String key, String value); - - IProperty addPropertyLast(String key, String value); - IProperty addPropertyAfter(String key, String value, Property anchor); - /** * @return Property key to the property value map. * Do not modify this map. It's no use anyway. @@ -116,4 +107,6 @@ public interface PropertiesFile { Project getProject(); String getText(); + + boolean isAlphaSorted(); } 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 360d9ce86dda..60ad79f7e1b3 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 @@ -17,7 +17,6 @@ package com.intellij.codeInspection.unsorted; import com.intellij.codeInspection.*; import com.intellij.lang.properties.IProperty; -import com.intellij.lang.properties.PropertiesBundle; import com.intellij.lang.properties.PropertiesImplUtil; import com.intellij.lang.properties.ResourceBundle; import com.intellij.lang.properties.psi.PropertiesElementFactory; @@ -30,11 +29,8 @@ import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.NullableFunction; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -68,7 +64,7 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool { holder.registerProblem(file, String.format(MESSAGE_TEMPLATE_WHOLE_RESOURCE_BUNDLE, resourceBundleBaseName), ProblemHighlightType.INFO, new PropertiesSorterQuickFix(true, propertiesFile)); return; } - if (!isAlphaSorted(propertiesFile)) { + if (!propertiesFile.isAlphaSorted()) { holder.registerProblem(file, "Properties file is unsorted", ProblemHighlightType.INFO, new PropertiesSorterQuickFix(true, propertiesFile)); } } @@ -81,32 +77,9 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool { if (!(file instanceof PropertiesFileImpl)) { return true; } - if (!file.equals(exceptedFile)) { - if (!isAlphaSorted(file)) { - return false; - } - } - } - return true; - } - - private static boolean isAlphaSorted(final @NotNull PropertiesFile propertiesFile) { - return isAlphaSorted(ContainerUtil.mapNotNull(propertiesFile.getProperties(), new NullableFunction() { - @Nullable - @Override - public String fun(IProperty property) { - return property.getKey(); - } - })); - } - - private static boolean isAlphaSorted(final List keys) { - String prevKey = null; - for (String key : keys) { - if (prevKey != null && prevKey.compareTo(key) > 0) { + if (!file.equals(exceptedFile) && !file.isAlphaSorted()) { return false; } - prevKey = key; } return true; } @@ -137,7 +110,7 @@ public class AlphaUnsortedPropertiesFileInspection extends LocalInspectionTool { public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final boolean force = myFilesToSort.length == 1; for (PropertiesFile file : myFilesToSort) { - if (!force && isAlphaSorted(file)) { + if (!force && file.isAlphaSorted()) { continue; } sortPropertiesFile(file); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java index 47569143b922..00feb42ba56e 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java @@ -33,10 +33,7 @@ import com.intellij.util.indexing.FileBasedIndex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author Konstantin Bulenkov @@ -162,4 +159,19 @@ public class PropertiesImplUtil extends PropertiesUtil { } return getResourceBundle(baseName, baseDirectory); } + + public static boolean isAlphaSorted(final Collection properties) { + String previousKey = null; + for (IProperty property : properties) { + final String key = property.getKey(); + if (key == null) { + return false; + } + if (previousKey != null && previousKey.compareTo(key) > 0) { + return false; + } + previousKey = key; + } + return true; + } } \ No newline at end of file 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 9d04b993b6ca..7c77848a47ba 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 @@ -25,6 +25,7 @@ import com.intellij.lang.properties.parsing.PropertiesElementTypes; import com.intellij.lang.properties.psi.PropertiesElementFactory; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.lang.properties.psi.Property; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; @@ -44,9 +45,11 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { + private static final Logger LOG = Logger.getInstance(PropertiesFileImpl.class); private static final TokenSet PROPERTIES_LIST_SET = TokenSet.create(PropertiesElementTypes.PROPERTIES_LIST); private volatile MostlySingularMultiMap myPropertiesMap; //guarded by lock private volatile List myProperties; //guarded by lock + private volatile boolean myAlphaSorted; private final Object lock = new Object(); public PropertiesFileImpl(FileViewProvider viewProvider) { @@ -87,10 +90,12 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { propertiesMap.add(key, property); properties.add(property); } + final boolean isAlphaSorted = PropertiesImplUtil.isAlphaSorted(properties); synchronized (lock) { if (myPropertiesMap != null) return; myProperties = properties; myPropertiesMap = propertiesMap; + myAlphaSorted = isAlphaSorted; } } @@ -135,12 +140,30 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { @Override @NotNull public PsiElement addProperty(@NotNull IProperty property) throws IncorrectOperationException { - if (haveToAddNewLine()) { - insertLineBreakBefore(null); + final IProperty position = findInsertionPosition(property); + return addPropertyAfter((Property)property, (Property)position); + } + + private IProperty findInsertionPosition(@NotNull IProperty property) { + synchronized (lock) { + ensurePropertiesLoaded(); + if (myProperties.isEmpty()) { + return null; + } + if (myAlphaSorted) { + final int insertIndex = Collections.binarySearch(myProperties, property, new Comparator() { + @Override + public int compare(IProperty p1, IProperty p2) { + final String k1 = p1.getKey(); + final String k2 = p2.getKey(); + LOG.assertTrue(k1 != null && k2 != null); + return k1.compareTo(k2); + } + }); + return insertIndex == -1 ? null :myProperties.get(insertIndex < 0 ? - insertIndex - 2 : insertIndex); + } + return myProperties.get(myProperties.size() - 1); } - final TreeElement copy = ChangeUtil.copyToElement(property.getPsiElement()); - getPropertiesList().addChild(copy); - return copy.getPsi(); } @Override @@ -171,18 +194,6 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { return (IProperty)addProperty(PropertiesElementFactory.createProperty(getProject(), key, value)); } - @NotNull - @Override - public IProperty addPropertyFirst(String key, String value) { - return (IProperty)addPropertyAfter((Property) PropertiesElementFactory.createProperty(getProject(), key, value), null); - } - - @NotNull - @Override - public IProperty addPropertyLast(String key, String value) { - return addProperty(key, value); - } - @NotNull @Override public IProperty addPropertyAfter(String key, String value, @Nullable Property anchor) { @@ -208,6 +219,14 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { return result; } + @Override + public boolean isAlphaSorted() { + synchronized (lock) { + ensurePropertiesLoaded(); + return myAlphaSorted; + } + } + @Override public void clearCaches() { super.clearCaches(); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java index b110dc429d74..a3a94c8f7f18 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java @@ -120,16 +120,6 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { return null; } - @Override - public IProperty addPropertyFirst(String key, String value) { - return null; - } - - @Override - public IProperty addPropertyLast(String key, String value) { - return null; - } - @Override public IProperty addPropertyAfter(String key, String value, Property anchor) { return null; @@ -202,6 +192,11 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { return getContainingFile().getText(); } + @Override + public boolean isAlphaSorted() { + return PropertiesImplUtil.isAlphaSorted(getProperties()); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundlePropertiesInsertManagerImpl.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundlePropertiesInsertManagerImpl.java index 213b0f2c47cc..fa1ac625769c 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundlePropertiesInsertManagerImpl.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundlePropertiesInsertManagerImpl.java @@ -65,17 +65,9 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle } final PropertiesFile propertiesFile = myResourceBundle.getDefaultPropertiesFile(); if (myAlphaSorted) { - final Pair propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile); - if (propertyAndPosition == null) { - propertiesFile.addPropertyFirst(key, value); - myKeysOrder.add(0, key); - } else { - propertiesFile.addPropertyAfter(key, value, (Property)propertyAndPosition.getFirst()); - final Integer position = propertyAndPosition.getSecond(); - myKeysOrder.add(position, key); - } + propertiesFile.addProperty(key, value); } else { - propertiesFile.addPropertyLast(key, value); + insertPropertyLast(key, value, propertiesFile); if (myOrdered) { myKeysOrder.add(key); } @@ -85,14 +77,14 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle @Override public void insertTranslation(String key, String value, final PropertiesFile propertiesFile) { if (myOrdered) { - final Pair propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile); - if (propertyAndPosition == null) { - propertiesFile.addPropertyFirst(key, value); - } else { - propertiesFile.addPropertyAfter(key, value, (Property)propertyAndPosition.getFirst()); + if (myAlphaSorted) { + propertiesFile.addProperty(key, value); + return; } + final Pair propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile); + propertiesFile.addPropertyAfter(key, value, propertyAndPosition == null ? null :(Property)propertyAndPosition.getFirst()); } else { - propertiesFile.addPropertyLast(key, value); + insertPropertyLast(key, value, propertiesFile); } } @@ -100,13 +92,7 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle if (myKeysOrder.isEmpty()) { return null; } - final int prevPosition; - if (myAlphaSorted) { - final int rawInsertionPosition = Collections.binarySearch(myKeysOrder, key); - prevPosition = rawInsertionPosition < 0 ? - rawInsertionPosition - 2 : rawInsertionPosition - 1; - } else { - prevPosition = myKeysOrder.indexOf(key); - } + final int prevPosition = myKeysOrder.indexOf(key); for (int i = prevPosition; i >= 0 ; i--) { final String prevKey = myKeysOrder.get(i); final IProperty property = file.findPropertyByKey(prevKey); @@ -117,6 +103,12 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle return null; } + public void insertPropertyLast(String key, String value, PropertiesFile propertiesFile) { + final List properties = propertiesFile.getProperties(); + final IProperty lastProperty = properties.isEmpty() ? null : properties.get(properties.size() - 1); + propertiesFile.addPropertyAfter(key, value, (Property)lastProperty); + } + @Override public void reload() { final List keysOrder = keysOrder(myResourceBundle); @@ -124,7 +116,7 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle if (myOrdered) { Collections.reverse(keysOrder); myAlphaSorted = isAlphaSorted(keysOrder); - myKeysOrder = keysOrder; + myKeysOrder = myAlphaSorted ? null : keysOrder; } else { myKeysOrder = null; } From 4b93f0346d194665df05f85e1fcacf985bef9e79 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 11 Feb 2015 12:19:40 +0300 Subject: [PATCH 06/32] editor settings statistics --- .../EditorSettingsStatisticsCollector.java | 122 ++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 1 + 2 files changed, 123 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/internal/statistic/editor/EditorSettingsStatisticsCollector.java diff --git a/platform/lang-impl/src/com/intellij/internal/statistic/editor/EditorSettingsStatisticsCollector.java b/platform/lang-impl/src/com/intellij/internal/statistic/editor/EditorSettingsStatisticsCollector.java new file mode 100644 index 000000000000..f2591af1689f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/internal/statistic/editor/EditorSettingsStatisticsCollector.java @@ -0,0 +1,122 @@ +/* + * 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.internal.statistic.editor; + +import com.intellij.codeInsight.CodeInsightSettings; +import com.intellij.codeInsight.editorActions.SmartBackspaceMode; +import com.intellij.internal.statistic.CollectUsagesException; +import com.intellij.internal.statistic.UsagesCollector; +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; +import com.intellij.openapi.editor.richcopy.settings.RichCopySettings; +import com.intellij.openapi.util.Comparing; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.Set; + +class EditorSettingsStatisticsCollector extends UsagesCollector { + @NotNull + @Override + public GroupDescriptor getGroupId() { + return GroupDescriptor.create("Editor"); + } + + @NotNull + @Override + public Set getUsages() throws CollectUsagesException { + Set set = new HashSet(); + + EditorSettingsExternalizable es = EditorSettingsExternalizable.getInstance(); + addIfDiffers(set, es.isVirtualSpace(), false, "caretAfterLineEnd"); + addIfDiffers(set, es.isCaretInsideTabs(), false, "caretInsideTabs"); + addIfDiffers(set, es.isAdditionalPageAtBottom(), false, "virtualSpaceAtFileBottom"); + addIfDiffers(set, es.isUseSoftWraps(SoftWrapAppliancePlaces.MAIN_EDITOR), false, "softWraps"); + addIfDiffers(set, es.isUseSoftWraps(SoftWrapAppliancePlaces.CONSOLE), false, "softWraps.console"); + addIfDiffers(set, es.isUseCustomSoftWrapIndent(), false, "softWraps.relativeIndent"); + addIfDiffers(set, es.isAllSoftWrapsShown(), false, "softWraps.showAll"); + addIfDiffers(set, es.getStripTrailingSpaces(), EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED, "stripTrailingSpaces"); + addIfDiffers(set, es.isEnsureNewLineAtEOF(), false, "ensureNewlineAtEOF"); + addIfDiffers(set, es.isShowQuickDocOnMouseOverElement(), false, "quickDocOnMouseHover"); + addIfDiffers(set, es.isBlinkCaret(), true, "nonBlinkingCaret"); + addIfDiffers(set, es.isBlockCursor(), false, "blockCaret"); + addIfDiffers(set, es.isRightMarginShown(), true, "noRightMargin"); + addIfDiffers(set, es.isLineNumbersShown(), false, "lineNumbers"); + addIfDiffers(set, es.isFoldingOutlineShown(), true, "noFoldingOutline"); + addIfDiffers(set, es.isWhitespacesShown() && es.isLeadingWhitespacesShown(), false, "showLeadingWhitespace"); + addIfDiffers(set, es.isWhitespacesShown() && es.isInnerWhitespacesShown(), false, "showInnerWhitespace"); + addIfDiffers(set, es.isWhitespacesShown() && es.isTrailingWhitespacesShown(), false, "showTrailingWhitespace"); + addIfDiffers(set, es.isIndentGuidesShown(), true, "noIndentGuides"); + addIfDiffers(set, es.isSmoothScrolling(), true, "noAnimatedScroll"); + addIfDiffers(set, es.isDndEnabled(), false, "dragNDrop"); + addIfDiffers(set, es.isWheelFontChangeEnabled(), false, "wheelZoom"); + addIfDiffers(set, es.isMouseClickSelectionHonorsCamelWords(), true, "mouseNoCamel"); + addIfDiffers(set, es.isVariableInplaceRenameEnabled(), true, "noInplaceRename"); + addIfDiffers(set, es.isPreselectRename(), true, "noPreselectOnRename"); + addIfDiffers(set, es.isShowInlineLocalDialog(), true, "noInlineDialog"); + addIfDiffers(set, es.isRefrainFromScrolling(), false, "minimizeScrolling"); + addIfDiffers(set, es.getOptions().SHOW_REFORMAT_DIALOG, true, "noReformatDialog"); + addIfDiffers(set, es.getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG, true, "noOptimizeImportsDialog"); + addIfDiffers(set, es.isSmartHome(), true, "noSmartHome"); + addIfDiffers(set, es.isCamelWords(), false, "camelWords"); + + RichCopySettings rcs = RichCopySettings.getInstance(); + addIfDiffers(set, rcs.isEnabled(), true, "noRichCopy"); + + CodeInsightSettings cis = CodeInsightSettings.getInstance(); + addIfDiffers(set, cis.AUTO_POPUP_PARAMETER_INFO, true, "noParameterAutoPopup"); + addIfDiffers(set, cis.AUTO_POPUP_JAVADOC_INFO, false, "javadocAutoPopup"); + addIfDiffers(set, cis.AUTO_POPUP_COMPLETION_LOOKUP, true, "noCompletionAutoPopup"); + addIfDiffers(set, cis.COMPLETION_CASE_SENSITIVE, CodeInsightSettings.FIRST_LETTER, "completionCaseSensitivity"); + addIfDiffers(set, cis.SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS, false, "autoPopupCharComplete"); + addIfDiffers(set, cis.AUTOCOMPLETE_ON_CODE_COMPLETION, true, "noAutoCompleteBasic"); + addIfDiffers(set, cis.AUTOCOMPLETE_ON_SMART_TYPE_COMPLETION, true, "noAutoCompleteSmart"); + addIfDiffers(set, cis.SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO, false, "parameterInfoFullSignature"); + addIfDiffers(set, cis.getBackspaceMode(), SmartBackspaceMode.AUTOINDENT, "smartBackspace"); + addIfDiffers(set, cis.SMART_INDENT_ON_ENTER, true, "noIndentOnEnter"); + addIfDiffers(set, cis.INSERT_BRACE_ON_ENTER, true, "noBraceOnEnter"); + addIfDiffers(set, cis.JAVADOC_STUB_ON_ENTER, true, "noJavadocOnEnter"); + addIfDiffers(set, cis.SMART_END_ACTION, true, "noSmartEnd"); + addIfDiffers(set, cis.JAVADOC_GENERATE_CLOSING_TAG, true, "noAutoCloseJavadocTags"); + addIfDiffers(set, cis.SURROUND_SELECTION_ON_QUOTE_TYPED, false, "surroundByQuoteOrBrace"); + addIfDiffers(set, cis.AUTOINSERT_PAIR_BRACKET, true, "noPairBracketAutoInsert"); + addIfDiffers(set, cis.AUTOINSERT_PAIR_QUOTE, true, "noPairQuoteAutoInsert"); + addIfDiffers(set, cis.REFORMAT_BLOCK_ON_RBRACE, true, "noReformatOnRBrace"); + addIfDiffers(set, cis.REFORMAT_ON_PASTE, CodeInsightSettings.INDENT_EACH_LINE, "reformatOnPaste"); + addIfDiffers(set, cis.ADD_IMPORTS_ON_PASTE, CodeInsightSettings.ASK, "importsOnPaste"); + addIfDiffers(set, cis.HIGHLIGHT_BRACES, true, "noBracesHighlight"); + addIfDiffers(set, cis.HIGHLIGHT_SCOPE, false, "scopeHighlight"); + addIfDiffers(set, cis.HIGHLIGHT_IDENTIFIER_UNDER_CARET, true, "noIdentifierUnderCaretHighlight"); + addIfDiffers(set, cis.OPTIMIZE_IMPORTS_ON_THE_FLY, false, "autoOptimizeImports"); + addIfDiffers(set, cis.ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY, false, "autoAddImports"); + + return set; + } + + private static void addIfDiffers(Set set, boolean value, boolean defaultValue, String featureId) { + if (value != defaultValue) { + set.add(new UsageDescriptor(featureId, 1)); + } + } + + private static void addIfDiffers(Set set, Object value, Object defaultValue, String featureIdPrefix) { + if (!Comparing.equal(value, defaultValue)) { + set.add(new UsageDescriptor(featureIdPrefix + "." + value, 1)); + } + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 65f8821d530a..091211c6d028 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -813,6 +813,7 @@ + From ce62eac5056e41bbf893ffa1d4badde3fb7105cd Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 11:29:05 +0300 Subject: [PATCH 07/32] Detect indent notification: refactoring, made LabelWithAction inner class of EditorNotificationInfo --- .../psi/codeStyle/EditorNotificationInfo.java | 11 +++++++ .../psi/codeStyle/LabelWithAction.java | 29 ------------------- .../DetectableIndentOptionsProvider.java | 2 ++ ...ctedIndentOptionsNotificationProvider.java | 2 ++ 4 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/LabelWithAction.java diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java index 59315c245631..e937357cd692 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java @@ -64,6 +64,17 @@ public class EditorNotificationInfo { return myTitle; } + + public static class LabelWithAction { + public final String label; + public final Runnable action; + + public LabelWithAction(@NotNull String label, @NotNull Runnable action) { + this.label = label; + this.action = action; + } + } + } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/LabelWithAction.java b/platform/lang-api/src/com/intellij/psi/codeStyle/LabelWithAction.java deleted file mode 100644 index b39afc320102..000000000000 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/LabelWithAction.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.psi.codeStyle; - -import org.jetbrains.annotations.NotNull; - -public class LabelWithAction { - - public final String label; - public final Runnable action; - - public LabelWithAction(@NotNull String label, @NotNull Runnable action) { - this.label = label; - this.action = action; - } -} diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java index 1687817f5a22..1606e5dc64a0 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java @@ -35,6 +35,8 @@ import org.jetbrains.annotations.TestOnly; import java.util.List; +import static com.intellij.psi.codeStyle.EditorNotificationInfo.*; + /** * @author Rustam Vishnyakov */ diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index b0be0cee284f..9035aa334dcb 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -32,6 +32,8 @@ import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.intellij.psi.codeStyle.EditorNotificationInfo.*; + /** * @author Rustam Vishnyakov */ From 8721aef9026564153f02e218798c146e28697dea Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 11:48:15 +0300 Subject: [PATCH 08/32] Detect Indent Notification: refactoring: added flag to updateAllNotification on action finish --- .../psi/codeStyle/EditorNotificationInfo.java | 6 ++++++ .../DetectableIndentOptionsProvider.java | 9 +++------ .../DetectedIndentOptionsNotificationProvider.java | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java index e937357cd692..429cbbca6742 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java @@ -68,11 +68,17 @@ public class EditorNotificationInfo { public static class LabelWithAction { public final String label; public final Runnable action; + public boolean updateAllNotificationsOnFinish; public LabelWithAction(@NotNull String label, @NotNull Runnable action) { this.label = label; this.action = action; } + + public LabelWithAction setUpdateAllNotificationsOnActionEnd(boolean value) { + updateAllNotificationsOnFinish = value; + return this; + } } } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java index 1606e5dc64a0..320de2a70e7c 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java @@ -94,10 +94,9 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { @Override public void run() { setAccepted(file); - EditorNotifications.getInstance(project).updateAllNotifications(); } } - ); + ).setUpdateAllNotificationsOnActionEnd(true); LabelWithAction disableForSingleFile = new LabelWithAction( labels.revertToOldSettingsLabel, @@ -108,10 +107,9 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { if (editor instanceof EditorEx) { ((EditorEx)editor).reinitSettings(); } - EditorNotifications.getInstance(project).updateAllNotifications(); } } - ); + ).setUpdateAllNotificationsOnActionEnd(true); LabelWithAction showSettings = new LabelWithAction( ApplicationBundle.message("code.style.indents.detector.show.settings"), @@ -120,10 +118,9 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { public void run() { ShowSettingsUtilImpl.showSettingsDialog(project, "preferences.sourceCode", ApplicationBundle.message("settings.code.style.general.autodetect.indents")); - EditorNotifications.getInstance(project).updateAllNotifications(); } } - ); + ).setUpdateAllNotificationsOnActionEnd(true); return new EditorNotificationInfo(labels.title, okAction, disableForSingleFile, showSettings); } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index 9035aa334dcb..7e23d577094c 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -79,8 +79,18 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio if (info.getIcon() != null) { panel.icon(info.getIcon()); } - for (LabelWithAction action : info.getLabelAndActions()) { - panel.createActionLabel(action.label, action.action); + for (final LabelWithAction actionLabelData : info.getLabelAndActions()) { + Runnable onClickAction = actionLabelData.action; + if (actionLabelData.updateAllNotificationsOnFinish) { + onClickAction = new Runnable() { + @Override + public void run() { + actionLabelData.action.run(); + EditorNotifications.getInstance(project).updateAllNotifications(); + } + }; + } + panel.createActionLabel(actionLabelData.label, onClickAction); } return panel; } From d0d37fc9c4f995202b8de57bcfc05c015759a489 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 11:49:58 +0300 Subject: [PATCH 09/32] Detect Indent Notification: renamed LabelWithAction into ActionLabelData --- .../psi/codeStyle/EditorNotificationInfo.java | 18 +++++++++--------- .../DetectableIndentOptionsProvider.java | 7 +++---- ...ectedIndentOptionsNotificationProvider.java | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java index 429cbbca6742..c71c68fc319d 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java @@ -27,11 +27,11 @@ public class EditorNotificationInfo { private String myTitle; private Icon myIcon; - private List myLabelsWithActions = ContainerUtil.newArrayList(); + private List myLabelsWithActions = ContainerUtil.newArrayList(); public EditorNotificationInfo(@NotNull String title, - @NotNull LabelWithAction firstLabel, - @Nullable LabelWithAction... otherLabels) + @NotNull ActionLabelData firstLabel, + @Nullable ActionLabelData... otherLabels) { myTitle = title; myLabelsWithActions.add(firstLabel); @@ -42,15 +42,15 @@ public class EditorNotificationInfo { public EditorNotificationInfo(@NotNull String title, @NotNull Icon icon, - @NotNull LabelWithAction firstLabel, - @Nullable LabelWithAction... otherLabels) + @NotNull ActionLabelData firstLabel, + @Nullable ActionLabelData... otherLabels) { this(title, firstLabel, otherLabels); myIcon = icon; } @NotNull - public List getLabelAndActions() { + public List getLabelAndActions() { return myLabelsWithActions; } @@ -65,17 +65,17 @@ public class EditorNotificationInfo { } - public static class LabelWithAction { + public static class ActionLabelData { public final String label; public final Runnable action; public boolean updateAllNotificationsOnFinish; - public LabelWithAction(@NotNull String label, @NotNull Runnable action) { + public ActionLabelData(@NotNull String label, @NotNull Runnable action) { this.label = label; this.action = action; } - public LabelWithAction setUpdateAllNotificationsOnActionEnd(boolean value) { + public ActionLabelData setUpdateAllNotificationsOnActionEnd(boolean value) { updateAllNotificationsOnFinish = value; return this; } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java index 320de2a70e7c..0b1e26f616be 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java @@ -27,7 +27,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.*; import com.intellij.testFramework.LightVirtualFile; -import com.intellij.ui.EditorNotifications; import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -88,7 +87,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { final Editor editor = fileEditor instanceof TextEditor ? ((TextEditor)fileEditor).getEditor() : null; if (labels == null || editor == null) return null; - LabelWithAction okAction = new LabelWithAction( + ActionLabelData okAction = new ActionLabelData( ApplicationBundle.message("code.style.indents.detector.accept"), new Runnable() { @Override @@ -98,7 +97,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { } ).setUpdateAllNotificationsOnActionEnd(true); - LabelWithAction disableForSingleFile = new LabelWithAction( + ActionLabelData disableForSingleFile = new ActionLabelData( labels.revertToOldSettingsLabel, new Runnable() { @Override @@ -111,7 +110,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { } ).setUpdateAllNotificationsOnActionEnd(true); - LabelWithAction showSettings = new LabelWithAction( + ActionLabelData showSettings = new ActionLabelData( ApplicationBundle.message("code.style.indents.detector.show.settings"), new Runnable() { @Override diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index 7e23d577094c..c50a0d487e0d 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -79,7 +79,7 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio if (info.getIcon() != null) { panel.icon(info.getIcon()); } - for (final LabelWithAction actionLabelData : info.getLabelAndActions()) { + for (final ActionLabelData actionLabelData : info.getLabelAndActions()) { Runnable onClickAction = actionLabelData.action; if (actionLabelData.updateAllNotificationsOnFinish) { onClickAction = new Runnable() { From 8c387992449d6a9996b5a05aff98a59b017cfb1a Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 12:07:18 +0300 Subject: [PATCH 10/32] Detect Indent Notification: updating all notifications on after every action --- .../psi/codeStyle/EditorNotificationInfo.java | 6 ------ .../DetectableIndentOptionsProvider.java | 6 +++--- ...tectedIndentOptionsNotificationProvider.java | 17 +++++++---------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java index c71c68fc319d..4787fa37d0de 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java @@ -68,17 +68,11 @@ public class EditorNotificationInfo { public static class ActionLabelData { public final String label; public final Runnable action; - public boolean updateAllNotificationsOnFinish; public ActionLabelData(@NotNull String label, @NotNull Runnable action) { this.label = label; this.action = action; } - - public ActionLabelData setUpdateAllNotificationsOnActionEnd(boolean value) { - updateAllNotificationsOnFinish = value; - return this; - } } } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java index 0b1e26f616be..fb1ddb804f12 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java @@ -95,7 +95,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { setAccepted(file); } } - ).setUpdateAllNotificationsOnActionEnd(true); + ); ActionLabelData disableForSingleFile = new ActionLabelData( labels.revertToOldSettingsLabel, @@ -108,7 +108,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { } } } - ).setUpdateAllNotificationsOnActionEnd(true); + ); ActionLabelData showSettings = new ActionLabelData( ApplicationBundle.message("code.style.indents.detector.show.settings"), @@ -119,7 +119,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { ApplicationBundle.message("settings.code.style.general.autodetect.indents")); } } - ).setUpdateAllNotificationsOnActionEnd(true); + ); return new EditorNotificationInfo(labels.title, okAction, disableForSingleFile, showSettings); } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index c50a0d487e0d..078d8f5eff0f 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -80,16 +80,13 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio panel.icon(info.getIcon()); } for (final ActionLabelData actionLabelData : info.getLabelAndActions()) { - Runnable onClickAction = actionLabelData.action; - if (actionLabelData.updateAllNotificationsOnFinish) { - onClickAction = new Runnable() { - @Override - public void run() { - actionLabelData.action.run(); - EditorNotifications.getInstance(project).updateAllNotifications(); - } - }; - } + Runnable onClickAction = new Runnable() { + @Override + public void run() { + actionLabelData.action.run(); + EditorNotifications.getInstance(project).updateAllNotifications(); + } + }; panel.createActionLabel(actionLabelData.label, onClickAction); } return panel; From 7af0c70ead4903288a30889a59b4ef23b11673ec Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 12:12:54 +0300 Subject: [PATCH 11/32] Detect Indent Notification: EditorNotification info made abstract --- .../psi/codeStyle/EditorNotificationInfo.java | 45 +++---------------- .../DetectableIndentOptionsProvider.java | 18 +++++++- 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java index 4787fa37d0de..8455382bf1e6 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/EditorNotificationInfo.java @@ -15,56 +15,25 @@ */ package com.intellij.psi.codeStyle; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.util.Collections; +import javax.swing.Icon; import java.util.List; -public class EditorNotificationInfo { - - private String myTitle; - private Icon myIcon; - private List myLabelsWithActions = ContainerUtil.newArrayList(); - - public EditorNotificationInfo(@NotNull String title, - @NotNull ActionLabelData firstLabel, - @Nullable ActionLabelData... otherLabels) - { - myTitle = title; - myLabelsWithActions.add(firstLabel); - if (otherLabels != null) { - Collections.addAll(myLabelsWithActions, otherLabels); - } - } - - public EditorNotificationInfo(@NotNull String title, - @NotNull Icon icon, - @NotNull ActionLabelData firstLabel, - @Nullable ActionLabelData... otherLabels) - { - this(title, firstLabel, otherLabels); - myIcon = icon; - } +public abstract class EditorNotificationInfo { @NotNull - public List getLabelAndActions() { - return myLabelsWithActions; - } + public abstract List getLabelAndActions(); + + @NotNull + public abstract String getTitle(); @Nullable public Icon getIcon() { - return myIcon; + return null; } - @NotNull - public String getTitle() { - return myTitle; - } - - public static class ActionLabelData { public final String label; public final Runnable action; diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java index fb1ddb804f12..7dc8bdbd2dd3 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectableIndentOptionsProvider.java @@ -27,6 +27,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.*; import com.intellij.testFramework.LightVirtualFile; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -83,7 +84,7 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { @NotNull CommonCodeStyleSettings.IndentOptions userOptions, @NotNull CommonCodeStyleSettings.IndentOptions detectedOptions) { - NotificationLabels labels = getNotificationLabels(userOptions, detectedOptions); + final NotificationLabels labels = getNotificationLabels(userOptions, detectedOptions); final Editor editor = fileEditor instanceof TextEditor ? ((TextEditor)fileEditor).getEditor() : null; if (labels == null || editor == null) return null; @@ -121,7 +122,20 @@ public class DetectableIndentOptionsProvider extends FileIndentOptionsProvider { } ); - return new EditorNotificationInfo(labels.title, okAction, disableForSingleFile, showSettings); + final List actions = ContainerUtil.newArrayList(okAction, disableForSingleFile, showSettings); + return new EditorNotificationInfo() { + @NotNull + @Override + public List getLabelAndActions() { + return actions; + } + + @NotNull + @Override + public String getTitle() { + return labels.title; + } + }; } @Nullable From dbeac272f865b54a1ed63142df6ce7ddefdb3500 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 11 Feb 2015 12:33:08 +0300 Subject: [PATCH 12/32] IDEA-136331 View text popups does not appear - reverted faulty change --- .../src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java index 6758d5e9b356..43f159e5b6db 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -127,8 +127,8 @@ public class DebuggerUIUtil { JComponent component, @Nullable final FullValueEvaluationCallbackImpl callback) { ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(component, null); - builder.setResizable(true).setAlpha(1) - .setMovable(true) + builder.setResizable(true)/*.setAlpha(1)*/ // alpha disabled because of IDEA-136331 + .setMovable(true) .setDimensionServiceKey(project, FULL_VALUE_POPUP_DIMENSION_KEY, false) .setRequestFocus(false); if (callback != null) { From 3b781b3b75a9a30ebf3d2796055ad219a001dfd0 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 11 Feb 2015 12:36:27 +0300 Subject: [PATCH 13/32] IDEA-136295 pycharm launcher on OSX does not set idea.executable causing failure to load vmoptions files --- python/build/pycharm_community_build.gant | 1 + 1 file changed, 1 insertion(+) diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant index 27ca91008a8b..dc268982e831 100644 --- a/python/build/pycharm_community_build.gant +++ b/python/build/pycharm_community_build.gant @@ -377,5 +377,6 @@ private layoutMac(Map _args, String target) { args.help_id = "PY" args."idea.properties.path" = "${paths.distAll}/bin/idea.properties" args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"]; + args.executable = "pycharm" layoutMacApp(target, ch, args) } From 3032d5e85effa0df251b4de8b0e80ff6ffbf043b Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 11 Feb 2015 10:40:47 +0100 Subject: [PATCH 14/32] IDEA-136118 (Make (private/public/protected) creates a new line) --- .../com/siyeh/ipp/modifiers/ModifierIntention.java | 14 ++++++++++++-- .../ipp/modifiers/make_public/AnnotatedMember.java | 5 +++++ .../make_public/AnnotatedMember_after.java | 5 +++++ .../ipp/modifiers/MakePrivateIntentionTest.java | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember_after.java diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java index 728c07cdf6fa..bb3fdb60124a 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,10 @@ package com.siyeh.ipp.modifiers; import com.intellij.codeInsight.intention.LowPriorityAction; import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.searches.ReferencesSearch; @@ -60,11 +62,12 @@ abstract class ModifierIntention extends Intention implements LowPriorityAction return; } final MultiMap conflicts = checkForConflicts(member); + final Project project = member.getProject(); final boolean conflictsDialogOK; if (conflicts.isEmpty()) { conflictsDialogOK = true; } else { - final ConflictsDialog conflictsDialog = new ConflictsDialog(member.getProject(), conflicts, new Runnable() { + final ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts, new Runnable() { @Override public void run() { final AccessToken token = start(); @@ -80,6 +83,13 @@ abstract class ModifierIntention extends Intention implements LowPriorityAction } if (conflictsDialogOK) { modifierList.setModifierProperty(getModifier(), true); + final PsiElement whitespace = PsiParserFacade.SERVICE.getInstance(project).createWhiteSpaceFromText(" "); + final PsiElement sibling = modifierList.getNextSibling(); + if (sibling instanceof PsiWhiteSpace) { + sibling.replace(whitespace); + CodeStyleManager.getInstance(project).reformatRange(member, modifierList.getTextOffset() + 1, + modifierList.getNextSibling().getTextOffset()); + } } } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember.java new file mode 100644 index 000000000000..76b2ae6f4def --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember.java @@ -0,0 +1,5 @@ +class AnnotatedMember { + + @SuppressWarnings("ALL") + String s; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember_after.java new file mode 100644 index 000000000000..5f0fe6e1ab04 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/AnnotatedMember_after.java @@ -0,0 +1,5 @@ +class AnnotatedMember { + + @SuppressWarnings("ALL") + private String s; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java index e7e39115c918..5dd3f794e0ee 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java @@ -27,6 +27,7 @@ public class MakePrivateIntentionTest extends IPPTestCase { public void testMyClass() { assertIntentionNotAvailable(); } public void testMyInterface() { assertIntentionNotAvailable(); } public void testMethod() { doTest(); } + public void testAnnotatedMember() { doTest(); } @Override protected String getRelativePath() { From 1dabe1fbd21887c83ca29da88a809185ea2e362b Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Wed, 11 Feb 2015 13:14:01 +0300 Subject: [PATCH 15/32] moved everything python dependent to language part of plugin --- .../coursecreator/PyStudyLanguageManager.java | 13 +++++++ .../edu/coursecreator/CCProjectService.java | 8 +++- .../jetbrains/edu/coursecreator/CCUtils.java | 9 +++++ .../coursecreator/StudyLanguageManager.java | 6 +++ .../actions/CCCreateCourseArchive.java | 39 +++++++++++++++---- .../coursecreator/actions/CCCreateTask.java | 15 ++++--- .../actions/CCCreateTaskFile.java | 9 ++--- .../actions/CCRunTestsAction.java | 13 ++++++- .../coursecreator/actions/CCShowPreview.java | 9 ++++- .../ui/CreateTaskFileDialog.java | 25 ++++++------ 10 files changed, 108 insertions(+), 38 deletions(-) diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java index 1b711f818b90..be2f399ffe58 100644 --- a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java +++ b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java @@ -6,6 +6,8 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; + public class PyStudyLanguageManager implements StudyLanguageManager { @Nullable @Override @@ -28,6 +30,17 @@ public class PyStudyLanguageManager implements StudyLanguageManager { return getInternalTemplateByName(project, "tests.py"); } + @Override + public boolean packFile(File pathname) { + String name = pathname.getName(); + return !name.contains("__pycache__") && !name.contains(".pyc"); + } + + @Override + public String[] getAdditionalFilesToPack() { + return new String[]{"test_helper.py"}; + } + private static FileTemplate getInternalTemplateByName(@NotNull final Project project, String name) { return FileTemplateManager.getInstance(project).getInternalTemplate(name); } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java index 8b9659353313..f49baee259f1 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java @@ -25,6 +25,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.xmlb.XmlSerializer; @@ -184,11 +186,13 @@ public class CCProjectService implements PersistentStateComponent { return Integer.parseInt(fullName.substring(logicalName.length())) - 1; } public static String getRealTaskFileName(String name) { - if (!name.contains(".answer")) { + String nameWithoutExtension = FileUtil.getNameWithoutExtension(name); + String extension = FileUtilRt.getExtension(name); + if (!nameWithoutExtension.endsWith(".answer")) { return null; } int nameEnd = name.indexOf(".answer"); - return name.substring(0, nameEnd) + ".py"; + return name.substring(0, nameEnd) + "." + extension; } public static boolean setCCActionAvailable(@NotNull AnActionEvent e) { diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java index 1e82811a6d8d..d453a59c92ae 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java @@ -1,6 +1,7 @@ package com.jetbrains.edu.coursecreator; import com.intellij.ide.projectView.actions.MarkRootActionBase; +import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.ApplicationManager; @@ -12,7 +13,9 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.coursecreator.format.Course; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class CCUtils { private static final Logger LOG = Logger.getInstance(CCUtils.class.getName()); @@ -56,4 +59,10 @@ public class CCUtils { return -1; } } + + @Nullable + public static StudyLanguageManager getStudyLanguageManager(@NotNull final Course course) { + Language language = Language.findLanguageByID(course.getLanguage()); + return language == null ? null : StudyLanguageManager.INSTANCE.forLanguage(language); + } } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java index bdef802bab94..cce016575e09 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java @@ -6,6 +6,8 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; + public interface StudyLanguageManager { LanguageExtension INSTANCE = new LanguageExtension("Edu.StudyLanguageManager"); @@ -17,4 +19,8 @@ public interface StudyLanguageManager { @Nullable FileTemplate getTestsTemplate(@NotNull final Project project); + + boolean packFile(File pathname); + + String[] getAdditionalFilesToPack(); } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java index f34aacba345f..ac774b3659e7 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java @@ -21,6 +21,8 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.io.ZipUtil; import com.jetbrains.edu.coursecreator.CCDocumentListener; import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.StudyLanguageManager; import com.jetbrains.edu.coursecreator.format.*; import com.jetbrains.edu.coursecreator.ui.CreateCourseArchiveDialog; import org.jetbrains.annotations.NotNull; @@ -92,7 +94,7 @@ public class CCCreateCourseArchive extends DumbAwareAction { } } generateJson(project); - packCourse(baseDir, lessons); + packCourse(baseDir, lessons, course); resetTaskFiles(taskFiles); synchronize(project); } @@ -204,11 +206,11 @@ public class CCCreateCourseArchive extends DumbAwareAction { } } - private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Map lessons) { + private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Map lessons, @NotNull final Course course) { try { File zipFile = new File(myLocationDir, myZipName + ".zip"); ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); - + final StudyLanguageManager manager = CCUtils.getStudyLanguageManager(course); for (Map.Entry entry : lessons.entrySet()) { final VirtualFile lessonDir = baseDir.findChild(entry.getKey()); if (lessonDir == null) continue; @@ -217,13 +219,21 @@ public class CCCreateCourseArchive extends DumbAwareAction { public boolean accept(File pathname) { String name = pathname.getName(); String nameWithoutExtension = FileUtil.getNameWithoutExtension(pathname); - return !nameWithoutExtension.endsWith(".answer") && !name.contains("__pycache__") && !name.contains("_windows") && !name.contains(".pyc"); + if (nameWithoutExtension.endsWith(".answer") || name.contains("_windows")) { + return false; + } + return manager == null || manager.packFile(pathname); } }, null); } - ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "hints"), "hints", null, null); - ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "course.json"), "course.json", null, null); - ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "test_helper.py"), "test_helper.py", null, null); + packFile("hints", zos, baseDir); + packFile("course.json", zos, baseDir); + if (manager != null) { + String[] additionalFilesToPack = manager.getAdditionalFilesToPack(); + for (String filename: additionalFilesToPack) { + packFile(filename, zos, baseDir); + } + } zos.close(); Messages.showInfoMessage("Course archive was saved to " + zipFile.getPath(), "Course Archive Was Created Successfully"); } @@ -271,4 +281,19 @@ public class CCCreateCourseArchive extends DumbAwareAction { return true; } } + + private static void packFile(@NotNull final String filename, + @NotNull final ZipOutputStream zipOutputStream, + @NotNull final VirtualFile baseDir) { + try { + File file = new File(baseDir.getPath(), filename); + if (!file.exists()) { + return; + } + ZipUtil.addFileOrDirRecursively(zipOutputStream, null, file, filename, null, null); + } + catch (IOException e) { + LOG.error(e); + } + } } \ No newline at end of file diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java index fefa795f4ff6..538fc76b59f2 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java @@ -18,6 +18,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -80,25 +81,23 @@ public class CCCreateTask extends DumbAwareAction { final StudyLanguageManager studyLanguageManager = StudyLanguageManager.INSTANCE.forLanguage(language); CCUtils.markDirAsSourceRoot(taskDirectory.getVirtualFile(), project); + final Task task = new Task(taskName); + task.setIndex(size + 1); + lesson.addTask(task, taskDirectory); + createFromTemplateAndOpen(taskDirectory, studyLanguageManager.getTestsTemplate(project), view); createFromTemplateAndOpen(taskDirectory, FileTemplateManager.getInstance(project).getInternalTemplate("task.html"), view); String defaultExtension = studyLanguageManager.getDefaultTaskFileExtension(); - String taskFileName = null; if (defaultExtension != null) { FileTemplate taskFileTemplate = studyLanguageManager.getTaskFileTemplateForExtension(project, defaultExtension); createFromTemplateAndOpen(taskDirectory, taskFileTemplate, view); if (taskFileTemplate != null) { - taskFileName = taskFileTemplate.getName(); + String taskFileName = FileUtil.getNameWithoutExtension(taskFileTemplate.getName()); + task.addTaskFile(taskFileName + "." + defaultExtension, size + 1); } } - final Task task = new Task(taskName); - task.setIndex(size + 1); - lesson.addTask(task, taskDirectory); - if (taskFileName != null) { - task.addTaskFile(taskFileName, size + 1); - } ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java index 73b50d39b3be..374a141fa067 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java @@ -7,7 +7,6 @@ import com.intellij.ide.fileTemplates.FileTemplateUtil; import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.ide.util.EditorHelper; -import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.LangDataKeys; @@ -21,6 +20,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; import com.jetbrains.edu.coursecreator.StudyLanguageManager; import com.jetbrains.edu.coursecreator.format.Course; import com.jetbrains.edu.coursecreator.format.Lesson; @@ -57,7 +57,7 @@ public class CCCreateTaskFile extends DumbAwareAction { final int index = task.getTaskFiles().size() + 1; String generatedName = "file" + index; - CreateTaskFileDialog dialog = new CreateTaskFileDialog(project, generatedName); + CreateTaskFileDialog dialog = new CreateTaskFileDialog(project, generatedName, course); dialog.show(); if (dialog.getExitCode() != OK_EXIT_CODE) { return; @@ -68,11 +68,10 @@ public class CCCreateTaskFile extends DumbAwareAction { if (type == null) { return; } - Language language = Language.findLanguageByID(course.getLanguage()); - if (language == null) { + final StudyLanguageManager studyLanguageManager = CCUtils.getStudyLanguageManager(course); + if (studyLanguageManager == null) { return; } - final StudyLanguageManager studyLanguageManager = StudyLanguageManager.INSTANCE.forLanguage(language); final String extension = type.getDefaultExtension(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java index e8ea54843535..bb4187026691 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java @@ -18,6 +18,7 @@ package com.jetbrains.edu.coursecreator.actions; import com.intellij.execution.Location; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.icons.AllIcons; +import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; @@ -34,6 +35,8 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.containers.HashMap; import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.StudyLanguageManager; import com.jetbrains.edu.coursecreator.format.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -130,8 +133,16 @@ public abstract class CCRunTestsAction extends AnAction { clearTestEnvironment(taskDir, project); for (final Map.Entry entry : task.getTaskFiles().entrySet()) { final String name = entry.getKey(); + StudyLanguageManager manager = CCUtils.getStudyLanguageManager(course); + if (manager == null) { + return; + } createTestEnvironment(taskDir, name, entry.getValue(), project); - VirtualFile testFile = taskDir.findChild("tests.py"); + FileTemplate testsTemplate = manager.getTestsTemplate(project); + if (testsTemplate == null) { + return; + } + VirtualFile testFile = taskDir.findChild(testsTemplate.getName()); if (testFile == null) { return; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java index 42fa66169633..7dfed6ef223d 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java @@ -30,7 +30,6 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; @@ -92,6 +91,9 @@ public class CCShowPreview extends DumbAwareAction { Lesson lesson = course.getLesson(lessonDir.getName()); Task task = lesson.getTask(taskDir.getName()); TaskFile taskFile = task.getTaskFile(file.getName()); + if (taskFile == null) { + return; + } final Map taskFilesCopy = new HashMap(); for (final Map.Entry entry : task.getTaskFiles().entrySet()) { if (entry.getValue() == taskFile) { @@ -103,7 +105,10 @@ public class CCShowPreview extends DumbAwareAction { }); } } - String userFileName = FileUtil.getNameWithoutExtension(file.getName()) + ".py"; + String userFileName = CCProjectService.getRealTaskFileName(file.getName()); + if (userFileName == null) { + return; + } VirtualFile userFile = taskDir.getVirtualFile().findChild(userFileName); if (userFile == null) { LOG.info("Generated file " + userFileName + "was not found"); diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java index 40abda126c58..6c79854aaba8 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java @@ -8,21 +8,25 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.ui.DoubleClickListener; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.components.JBList; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.StudyLanguageManager; +import com.jetbrains.edu.coursecreator.format.Course; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.awt.event.MouseEvent; public class CreateTaskFileDialog extends DialogWrapper { + private final Course myCourse; private JPanel myPanel; private JBList myList; private JTextField myTextField; @SuppressWarnings("unchecked") - public CreateTaskFileDialog(@Nullable Project project, String generatedFileName) { + public CreateTaskFileDialog(@Nullable Project project, String generatedFileName, @NotNull final Course course) { super(project); + myCourse = course; FileType[] fileTypes = FileTypeManager.getInstance().getRegisteredFileTypes(); DefaultListModel model = new DefaultListModel(); @@ -51,16 +55,11 @@ public class CreateTaskFileDialog extends DialogWrapper { } }.installOn(myList); - myList.getSelectionModel().addListSelectionListener( - new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - //TODO: do smth to check validness - } - } - ); - - ListScrollingUtil.selectItem(myList, FileTypeManager.getInstance().getFileTypeByExtension("py")); + StudyLanguageManager manager = CCUtils.getStudyLanguageManager(myCourse); + if (manager != null) { + String extension = manager.getDefaultTaskFileExtension(); + ListScrollingUtil.selectItem(myList, FileTypeManager.getInstance().getFileTypeByExtension(extension != null ? extension : "txt")); + } return myPanel; } From effd7102feaf5ec4e152b742b92de2f2ef745392 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 11 Feb 2015 13:27:38 +0300 Subject: [PATCH 16/32] IDEA-135786 Mac OSX Window Switch/Cycle Restores Window from Minimized State --- .../com/intellij/openapi/wm/impl/ProjectWindowAction.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java index 15045cedc05c..7941484edafd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.WindowManager; import com.intellij.util.BitUtil; import org.jetbrains.annotations.NotNull; @@ -121,6 +122,12 @@ public class ProjectWindowAction extends ToggleAction implements DumbAware { } final JFrame projectFrame = WindowManager.getInstance().getFrame(project); final int frameState = projectFrame.getExtendedState(); + + if (SystemInfo.isMac && (projectFrame.getExtendedState() & Frame.ICONIFIED) != 0) { + // On Mac minimized window should not be restored this way + return; + } + if (BitUtil.isSet(frameState, Frame.ICONIFIED)) { // restore the frame if it is minimized projectFrame.setExtendedState(frameState ^ Frame.ICONIFIED); From 929ade4b542c04cd2e122a56c1d5c9f078f16c5e Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 11 Feb 2015 13:30:26 +0300 Subject: [PATCH 17/32] MnemonicHelper refactoring --- .../src/com/intellij/ide/util/FileStructurePopup.java | 2 +- .../intellij/ide/util/gotoByName/ChooseByNameBase.java | 2 +- .../src/com/intellij/openapi/MnemonicHelper.java | 9 +++++++++ .../src/com/intellij/openapi/ui/DialogWrapper.java | 2 +- .../src/com/intellij/util/net/AuthenticationDialog.java | 4 ++-- .../openapi/application/ImportOldConfigsPanel.java | 2 +- .../com/intellij/openapi/wm/impl/FloatingDecorator.java | 2 +- .../src/com/intellij/openapi/wm/impl/IdeFrameImpl.java | 2 +- .../openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java | 2 +- .../openapi/wm/impl/welcomeScreen/WelcomeFrame.java | 2 +- .../src/com/intellij/util/xml/ui/DomFileEditor.java | 2 +- 11 files changed, 20 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 5c1f4cc35402..6f13af4fed19 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -242,7 +242,7 @@ public class FileStructurePopup implements Disposable { public void show() { //final long time = System.currentTimeMillis(); JComponent panel = createCenterPanel(); - new MnemonicHelper().register(panel); + MnemonicHelper.init(panel); boolean shouldSetWidth = DimensionService.getInstance().getSize(getDimensionServiceKey(), myProject) == null; myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, null) .setTitle(myTitle) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index ff3ad83bcafe..5ccd42cfd4cb 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -897,7 +897,7 @@ public abstract class ChooseByNameBase { myTextPopup.setSize(bounds.getSize()); myTextPopup.setLocation(bounds.getLocation()); - new MnemonicHelper().register(myTextFieldPanel); + MnemonicHelper.init(myTextFieldPanel); if (myProject != null && !myProject.isDefault()) { DaemonCodeAnalyzer.getInstance(myProject).disableUpdateByTimer(myTextPopup); } diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java index 1e4577c58dac..05bbcac3b354 100644 --- a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java @@ -143,4 +143,13 @@ public class MnemonicHelper extends ComponentTreeWatcher { "alt pressed " + mnemonic; return CustomShortcutSet.fromString(shortcut); } + + /** + * Initializes mnemonics support for the specified component and for its children if needed. + * + * @param component the root component of the hierarchy + */ + public static void init(Component component) { + new MnemonicHelper().register(component); + } } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 35f0b92cdb8b..bd6daff16513 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -1242,7 +1242,7 @@ public abstract class DialogWrapper { southSection.add(south, BorderLayout.SOUTH); } - new MnemonicHelper().register(root); + MnemonicHelper.init(root); if (!postponeValidation()) { startTrackingValidation(); } diff --git a/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java b/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java index 83cca8a039df..0f8c2495f929 100644 --- a/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java +++ b/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java @@ -30,7 +30,7 @@ public class AuthenticationDialog extends DialogWrapper { super(component, true); setTitle(title); - new MnemonicHelper().register(getContentPane()); + MnemonicHelper.init(getContentPane()); panel = new AuthenticationPanel(description, login, password, rememberPassword); final Window window = getWindow(); @@ -45,7 +45,7 @@ public class AuthenticationDialog extends DialogWrapper { super(JOptionPane.getRootFrame(), true); setTitle(title); - new MnemonicHelper().register(getContentPane()); + MnemonicHelper.init(getContentPane()); panel = new AuthenticationPanel(description, login, password, rememberPassword); final Window window = getWindow(); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java b/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java index d25f2949b347..1097409baaee 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java @@ -57,7 +57,7 @@ public class ImportOldConfigsPanel extends JDialog { } private void init() { - new MnemonicHelper().register(getContentPane()); + MnemonicHelper.init(getContentPane()); ButtonGroup group = new ButtonGroup(); group.add(myRbDoNotImport); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java index fb494bb140d7..5a0a20351c29 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java @@ -66,7 +66,7 @@ public final class FloatingDecorator extends JDialog { FloatingDecorator(final IdeFrameImpl owner,final WindowInfoImpl info,final InternalDecorator internalDecorator){ super(owner,internalDecorator.getToolWindow().getId()); - new MnemonicHelper().register(getContentPane()); + MnemonicHelper.init(getContentPane()); myInternalDecorator=internalDecorator; setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index cbb8931a2225..a20bca20cd63 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -109,7 +109,7 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider { setFocusTraversalPolicy(layoutFocusTraversalPolicy); setupCloseAction(); - new MnemonicHelper().register(this); + MnemonicHelper.init(this); myBalloonLayout = new BalloonLayoutImpl(myRootPane, new Insets(8, 8, 8, 8)); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java index 80d4739c5631..0da90ca293a1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java @@ -113,7 +113,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { myBalloonLayout = new BalloonLayoutImpl(rootPane, new JBInsets(8, 8, 8, 8)); WelcomeFrame.setupCloseAction(this); - new MnemonicHelper().register(this); + MnemonicHelper.init(this); Disposer.register(ApplicationManager.getApplication(), new Disposable() { @Override public void dispose() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java index d638fde23562..339f6a3e76a3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java @@ -80,7 +80,7 @@ public class WelcomeFrame extends JFrame implements IdeFrame { myScreen = screen; setupCloseAction(this); - new MnemonicHelper().register(this); + MnemonicHelper.init(this); myScreen.setupFrame(this); Disposer.register(ApplicationManager.getApplication(), new Disposable() { @Override diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/DomFileEditor.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/DomFileEditor.java index ee8f1faaf450..dcce76401d42 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ui/DomFileEditor.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/DomFileEditor.java @@ -102,7 +102,7 @@ public class DomFileEditor extends Perspecti @Override @NotNull protected JComponent createCustomComponent() { - new MnemonicHelper().register(getComponent()); + MnemonicHelper.init(getComponent()); myComponent = myComponentFactory.create(); DomUIFactory.getDomUIFactory().setupErrorOutdatingUserActivityWatcher(this, getDomElement()); DomManager.getDomManager(getProject()).addDomEventListener(new DomEventListener() { From 4f6e6dd0330a44def92df3958a1197a4cb2fe233 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 11 Feb 2015 13:39:14 +0300 Subject: [PATCH 18/32] Add ability to use another way to process mnemonics --- .../openapi/MnemonicContainerListener.java | 79 +++++++++++++++++++ .../com/intellij/openapi/MnemonicHelper.java | 13 ++- .../util/resources/misc/registry.properties | 3 + 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 platform/platform-api/src/com/intellij/openapi/MnemonicContainerListener.java diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicContainerListener.java b/platform/platform-api/src/com/intellij/openapi/MnemonicContainerListener.java new file mode 100644 index 000000000000..fb3ffd1fe25d --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicContainerListener.java @@ -0,0 +1,79 @@ +/* + * 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.openapi; + +import javax.swing.CellRendererPane; +import java.awt.*; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; + +/** + * @author Sergey.Malenkov + */ +final class MnemonicContainerListener implements ContainerListener { + void addTo(Component component) { + if (component == null || component instanceof CellRendererPane) { + return; + } + if (component instanceof Container) { + addTo((Container)component); + } + MnemonicWrapper.getWrapper(component); + } + + void removeFrom(Component component) { + if (component instanceof Container) { + removeFrom((Container)component); + } + } + + @Override + public void componentAdded(ContainerEvent event) { + addTo(event.getChild()); + } + + @Override + public void componentRemoved(ContainerEvent event) { + removeFrom(event.getChild()); + } + + private void addTo(Container container) { + if (!isAddedTo(container)) { + container.addContainerListener(this); + for (Component component : container.getComponents()) { + addTo(component); + } + } + } + + private void removeFrom(Container container) { + if (isAddedTo(container)) { + container.removeContainerListener(this); + for (Component component : container.getComponents()) { + removeFrom(component); + } + } + } + + private boolean isAddedTo(Container container) { + for (ContainerListener listener : container.getContainerListeners()) { + if (listener == this) { + return true; + } + } + return false; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java index 05bbcac3b354..e18ac0958634 100644 --- a/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java +++ b/platform/platform-api/src/com/intellij/openapi/MnemonicHelper.java @@ -42,6 +42,7 @@ import java.util.Map; * @since 5.1 */ public class MnemonicHelper extends ComponentTreeWatcher { + private static final MnemonicContainerListener LISTENER = new MnemonicContainerListener(); private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.MnemonicHelper"); private Map myMnemonics = null; @@ -57,6 +58,11 @@ public class MnemonicHelper extends ComponentTreeWatcher { }; @NonNls public static final String TEXT_CHANGED_PROPERTY = "text"; + /** + * @see #init(Component) + * @deprecated do not use this object as a tree watcher + */ + @Deprecated public MnemonicHelper() { super(ArrayUtil.EMPTY_CLASS_ARRAY); } @@ -150,6 +156,11 @@ public class MnemonicHelper extends ComponentTreeWatcher { * @param component the root component of the hierarchy */ public static void init(Component component) { - new MnemonicHelper().register(component); + if (Registry.is("ide.mnemonic.helper.old") || Registry.is("ide.checkDuplicateMnemonics")) { + new MnemonicHelper().register(component); + } + else { + LISTENER.addTo(component); + } } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 0136a7f74244..4cc3d152fc74 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -54,6 +54,9 @@ ide.popup.resizable.border.sensitivity=4 ide.consumeKnownToolkitBugs=true ide.highlight.match.in.selected.only=true ide.lazyIconLoading=true +ide.mnemonic.helper.old=true +ide.mnemonic.helper.old.restartRequired=true +ide.mnemonic.helper.old.description=Use new algorithm of mnemonics processing ide.checkDuplicateMnemonics=false ide.checkDuplicateMnemonics.description=Check for duplicate mnemonics. ide.dnd.textHints=false From 44a0bb404f05d4eb5608cb2936a7c738ea64db67 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 11 Feb 2015 13:48:13 +0300 Subject: [PATCH 19/32] IDEA-136128 XML attribute error in IDEA 14, works in IDEA 13 --- .../daemon/XmlHighlightingTest.java | 11 ++++++++ xml/tests/testData/xml/DocBookRole.xml | 25 +++++++++++++++++++ .../impl/schema/ComplexTypeDescriptor.java | 16 ++++++------ 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 xml/tests/testData/xml/DocBookRole.xml diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java index 370f22d6cf3d..e5932749068b 100644 --- a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java +++ b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java @@ -1574,6 +1574,17 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase { ); } + public void testDocBookRole() throws Exception { + doTestWithLocations( + new String[][] { + {"http://docbook.org/ns/docbook", "DocBookV5.xsd"}, + {"http://www.w3.org/1999/xlink", "xlink.xsd"}, + {"http://www.w3.org/XML/1998/namespace", "xml.xsd"} + }, + "xml" + ); + } + public void testCorrectGeneratedDtdUpdate() throws Exception { configureByFile(BASE_PATH + getTestName(false) + ".xml"); Collection infos = filterInfos(doHighlighting()); diff --git a/xml/tests/testData/xml/DocBookRole.xml b/xml/tests/testData/xml/DocBookRole.xml new file mode 100644 index 000000000000..49cfaf99d2e0 --- /dev/null +++ b/xml/tests/testData/xml/DocBookRole.xml @@ -0,0 +1,25 @@ + + + A simple Test File + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco + laboris nisi ut aliquip ex ea + commodo + consequat. Duis aute irure dolor in reprehenderit in + voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + + diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java index 09a51017260f..e86f655bc6d1 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java @@ -217,7 +217,7 @@ public class ComplexTypeDescriptor extends TypeDescriptor { // Read-only calculation private XmlAttributeDescriptor[] doCollectAttributes(@Nullable final XmlElement context) { - final List result = new ArrayList(); + final List result = new ArrayList(); XmlSchemaTagsProcessor processor = new XmlSchemaTagsProcessor(myDocumentDescriptor, "element") { @Override @@ -234,7 +234,7 @@ public class ComplexTypeDescriptor extends TypeDescriptor { if (use == null) use = tag.getAttributeValue("use"); if (PROHIBITED_ATTR_VALUE.equals(use)) { - removeAttributeDescriptor(result, name); + removeAttributeDescriptor(result, name, null); } else { XmlAttributeDescriptorImpl descriptor = myDocumentDescriptor.createAttributeDescriptor(tag); @@ -260,18 +260,18 @@ public class ComplexTypeDescriptor extends TypeDescriptor { result.put(element.getName(),element); } - private static void removeAttributeDescriptor(List result, String name) { - for (Iterator iterator = result.iterator(); iterator.hasNext();) { - XmlAttributeDescriptor attributeDescriptor = iterator.next(); + private static void removeAttributeDescriptor(List result, String name, String referenceName) { + for (Iterator iterator = result.iterator(); iterator.hasNext();) { + XmlAttributeDescriptorImpl descriptor = iterator.next(); - if (attributeDescriptor.getName().equals(name)) { + if (descriptor.getName().equals(name) && (referenceName == null || referenceName.equals(descriptor.myReferenceName))) { iterator.remove(); } } } - private static void addAttributeDescriptor(List result, XmlAttributeDescriptor descriptor) { - removeAttributeDescriptor(result, descriptor.getName()); + private static void addAttributeDescriptor(List result, XmlAttributeDescriptorImpl descriptor) { + removeAttributeDescriptor(result, descriptor.getName(), descriptor.myReferenceName); result.add(descriptor); } From d21766ecc3bd644c1978801aa87e6b1ad637537f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 9 Feb 2015 14:52:34 +0300 Subject: [PATCH 20/32] restart earlier --- .../com/intellij/codeInsight/daemon/impl/DaemonListeners.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java index 083ea16e5091..6dfc2cb1079e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java @@ -429,7 +429,7 @@ public class DaemonListeners implements Disposable { @Override public void beforeWriteActionStart(Object action) { myDaemonWasRunning = myDaemonCodeAnalyzer.isRunning(); - if (!myDaemonWasRunning || isUnderIgnoredAction(action)) return; // we'll restart in writeActionFinished() + if (!myDaemonWasRunning) return; // we'll restart in writeActionFinished() stopDaemon(true, "Write action start"); } From 49873e4269d6d1d1e298ee524ddf3cbad07ff4b3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Feb 2015 17:48:01 +0300 Subject: [PATCH 21/32] UP-3008 Groovy exception --- .../resources/TypeCustomizerInspection.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java index e55cc758c4ef..541f041bf51d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,12 +50,11 @@ public class TypeCustomizerInspection extends BaseInspection { return new BaseInspectionVisitor() { @Override public void visitFile(GroovyFileBase file) { - if (!CompilerConfiguration.getInstance(file.getProject()).isResourceFile(file.getVirtualFile())) { - if (fileSeemsToBeTypeCustomizer(file)) { - final LocalQuickFix[] fixes = {new AddToResourceFix(file)}; - final String message = GroovyInspectionBundle.message("type.customizer.is.not.marked.as.a.resource.file"); - registerError(file, message, fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } + CompilerConfiguration configuration = CompilerConfiguration.getInstance(file.getProject()); + if (configuration != null && !configuration.isResourceFile(file.getVirtualFile()) && fileSeemsToBeTypeCustomizer(file)) { + final LocalQuickFix[] fixes = {new AddToResourceFix(file)}; + final String message = GroovyInspectionBundle.message("type.customizer.is.not.marked.as.a.resource.file"); + registerError(file, message, fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } } }; From 6a0fd6eb49c3b75f874c704b2bc72ba0e0999ba3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Feb 2015 18:30:55 +0300 Subject: [PATCH 22/32] show stack trace in tests --- .../intellij/openapi/progress/ProcessCanceledException.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java b/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java index e6133b255411..0cdde2c48e87 100644 --- a/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java +++ b/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package com.intellij.openapi.progress; import com.intellij.util.SystemProperties; public class ProcessCanceledException extends RuntimeException { - private static final boolean ourHasStackTraces = SystemProperties.getBooleanProperty("idea.is.internal", false); + private static final boolean ourHasStackTraces = SystemProperties.getBooleanProperty("idea.is.internal", false) || SystemProperties.getBooleanProperty("idea.is.unit.test", false); public ProcessCanceledException() { } From 84eb867335044d93f9eb09222943bf4d2cc87ba7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Feb 2015 18:52:35 +0300 Subject: [PATCH 23/32] lists sorted --- build/scripts/utils.gant | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 900381b45908..5a10eaa016a2 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -272,7 +272,9 @@ binding.setVariable("classPathLibs", [ binding.setVariable("platformApiModules", [ "analysis-api", + "built-in-server-api", "core-api", + "diff-api", "dvcs-api", "editor-ui-api", "external-system-api", @@ -280,60 +282,57 @@ binding.setVariable("platformApiModules", [ "jps-model-api", "lang-api", "lvcs-api", - "projectModel-api", "platform-api", + "projectModel-api", + "remote-servers-agent-rt", + "remote-servers-api", "structure-view-api", "usageView", - "diff-api", - "vcs-api", "vcs-api-core", + "vcs-api", "vcs-log-api", "vcs-log-graph-api", "xdebugger-api", - "remote-servers-api", - "remote-servers-agent-rt", "xml-analysis-api", "xml-openapi", "xml-psi-api", - "xml-structure-view-api", - "built-in-server-api" + "xml-structure-view-api" ]) - binding.setVariable("platformImplementationModules", [ "analysis-impl", + "built-in-server", "core-impl", + "diff-impl", "dvcs-impl", "editor-ui-ex", "images", "indexing-impl", "jps-model-impl", "jps-model-serialization", + "json", "lang-impl", "lvcs-impl", - "projectModel-impl", "platform-impl", + "projectModel-impl", + "protocol-reader-runtime", + "RegExpSupport", + "relaxng", + "remote-servers-impl", + "script-debugger-backend", + "script-debugger-ui", + "smRunner", + "spellchecker", "structure-view-impl", - "diff-impl", + "testRunner", "vcs-impl", "vcs-log-graph", "vcs-log-impl", - "testRunner", - "smRunner", - "relaxng", - "RegExpSupport", - "spellchecker", "xdebugger-impl", - "remote-servers-impl", - "xml", "xml-analysis-impl", "xml-psi-impl", "xml-structure-view-impl", - "json", - "protocol-reader-runtime", - "script-debugger-backend", - "script-debugger-ui", - "built-in-server" + "xml" ]) binding.setVariable("layoutMacApp", { String path, String ch, Map args -> From 5c6f660df32fda03ea60bdab31d7d18c995a0825 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Feb 2015 18:53:38 +0300 Subject: [PATCH 24/32] debug DaemonProgressIndicator on --- .../codeInsight/daemon/impl/DaemonProgressIndicator.java | 4 ++-- .../fixtures/impl/CodeInsightTestFixtureImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java index 378564c7a6c1..6afba8d8eaa0 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,7 +83,7 @@ public class DaemonProgressIndicator extends AbstractProgressIndicatorBase imple } @TestOnly - static void setDebug(boolean debug) { + public static void setDebug(boolean debug) { DaemonProgressIndicator.debug = debug; } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 0b958006e33a..37c08ee7baf9 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -1624,7 +1624,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project); TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor); ProcessCanceledException exception = null; - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 1000; i++) { try { List infos = codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, toIgnore, canChangeDocument, null); infos.addAll(DaemonCodeAnalyzerEx.getInstanceEx(project).getFileLevelHighlights(project, file)); From cb33f58dbe0cfc6046447f58d935639ab5072a24 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 11 Feb 2015 14:17:01 +0300 Subject: [PATCH 25/32] test fix: should have stack frame in tests --- .../progress/impl/ProgressIndicatorTest.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java index e172c7d55f52..1b3f39f2546d 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java @@ -55,7 +55,9 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { } catch(ProcessCanceledException ex) { boolean isInternal = SystemProperties.getBooleanProperty("idea.is.internal", false); - assertTrue("Should have no stackframe", isInternal ? ex.getStackTrace().length != 0 : ex.getStackTrace().length == 0); + boolean isTest = SystemProperties.getBooleanProperty("idea.is.unit.test", false); + boolean hasStackFrame = ex.getStackTrace().length != 0; + assertTrue("Should have no stackframe", (isInternal || isTest) == hasStackFrame); } } @@ -112,7 +114,7 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { }, "", false, getProject(), null, ""); long averageDelay = PlatformTestUtil.averageAmongMedians(times.toNativeArray(), 5); System.out.println("averageDelay = " + averageDelay); - assertTrue(averageDelay < ProgressManagerImpl.CHECK_CANCELED_DELAY_MILLIS*3); + assertTrue(averageDelay < CoreProgressManager.CHECK_CANCELED_DELAY_MILLIS *3); } public void testProgressIndicatorUtilsScheduleWithWriteActionPriority() throws Throwable { @@ -133,7 +135,7 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { }); UIUtil.dispatchAllInvocationEvents(); while (!insideReadAction.get()) { - ; + } ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override @@ -316,11 +318,11 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { @Override public void run() { - assertFalse(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread())); ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator(); assertTrue(indicator != null && !indicator.isCanceled()); indicator.cancel(); - assertTrue(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread())); assertTrue(indicator.isCanceled()); final ProgressIndicatorEx nested = new ProgressIndicatorBase(); nested.addStateDelegate(new ProgressIndicatorStub() { @@ -332,7 +334,7 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { @Override public void run() { - assertFalse(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread())); ProgressIndicator indicator2 = ProgressIndicatorProvider.getGlobalProgressIndicator(); assertTrue(indicator2 != null && !indicator2.isCanceled()); assertSame(indicator2, nested); @@ -343,7 +345,7 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { ProgressIndicator indicator3 = ProgressIndicatorProvider.getGlobalProgressIndicator(); assertSame(indicator, indicator3); - assertTrue(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread())); } }, new EmptyProgressIndicator()); assertFalse(checkCanceledCalled); @@ -386,10 +388,10 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { @Override public void run() { - assertFalse(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertFalse(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread())); assertTrue(!progress.isCanceled()); progress.cancel(); - assertTrue(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertTrue(CoreProgressManager.threadsUnderCanceledIndicator.contains(Thread.currentThread())); assertTrue(progress.isCanceled()); while (true) { // wait for PCE ProgressManager.checkCanceled(); From 013314cfbc0d4dabb887597e92cda2c2d0b8704b Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 11 Feb 2015 14:29:12 +0300 Subject: [PATCH 26/32] Unindent action doesn't place caret inside text, if it was not there already. (IDEA-111438) --- .../intellij/openapi/editor/actions/EditorActionUtil.java | 4 ++++ .../intellij/openapi/editor/actions/EditorActionTest.java | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java index 9ddac3c2aae5..e1c160f2f7f5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java @@ -198,9 +198,13 @@ public class EditorActionUtil { } } + int newSpacesEnd = lineStart + buf.length(); if (newCaretOffset >= spacesEnd) { newCaretOffset += buf.length() - (spacesEnd - lineStart); } + else if (newCaretOffset >= lineStart && newCaretOffset < spacesEnd && newCaretOffset > newSpacesEnd) { + newCaretOffset = newSpacesEnd; + } if (buf.length() > 0) { if (spacesEnd > lineStart) { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java index 2545df56d20c..13381591fb4d 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java @@ -22,6 +22,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.AbstractEditorTest; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.testFramework.EditorTestUtil; +import com.intellij.testFramework.LightPlatformCodeInsightTestCase; import com.intellij.testFramework.TestFileType; import java.awt.datatransfer.StringSelection; @@ -187,4 +188,10 @@ public class EditorActionTest extends AbstractEditorTest { "blah blah\n" + "blah blah"); } + + public void testCaretComesBeforeTextOnUnindent() throws IOException { + initText(" text"); + unindent(); + checkResultByText(" text"); + } } \ No newline at end of file From 0d93daa17b0e9615d4812683101413cd47a5d5fc Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 Feb 2015 12:26:37 +0100 Subject: [PATCH 27/32] IDEA-136341 SmartPointerManagerImpl consumes too much memory during indexing --- .../intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index 401ab76370e0..dc66978ba613 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -200,6 +200,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { if (!file.isValid()) { LOG.error("Invalid element:" + file); } + processQueue(); SmartPsiFileRangePointerImpl pointer = new SmartPsiFileRangePointerImpl(file, ProperTextRange.create(range)); initPointer(pointer, file.getViewProvider().getVirtualFile()); From 2ea61b4f70dab98f3048dfc2d3c6a32af3363874 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 11 Feb 2015 14:28:02 +0300 Subject: [PATCH 28/32] external system: do not modify data graph of the running import --- .../externalSystem/model/DataNode.java | 35 +++++++++---------- .../manage/ExternalProjectsDataStorage.java | 2 +- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java index 869731d2d90b..1e879da7e922 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java @@ -24,10 +24,7 @@ import org.jetbrains.annotations.Nullable; import java.io.*; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; +import java.util.*; /** * This class provides a generic graph infrastructure with ability to store particular data. The main purpose is to @@ -48,6 +45,7 @@ public class DataNode implements Serializable { private static final Logger LOG = Logger.getInstance(DataNode.class); @NotNull private final List> myChildren = ContainerUtilRt.newArrayList(); + @NotNull private final List> myChildrenView = Collections.unmodifiableList(myChildren); @NotNull private final Key myKey; private transient T myData; @@ -73,18 +71,6 @@ public class DataNode implements Serializable { return result; } - @NotNull - public DataNode createOrReplaceChild(@NotNull Key key, @NotNull T data) { - for (Iterator> iterator = myChildren.iterator(); iterator.hasNext(); ) { - DataNode child = iterator.next(); - if (child.getKey().equals(key)) { - iterator.remove(); - break; - } - } - return createChild(key, data); - } - @NotNull public Key getKey() { return myKey; @@ -237,7 +223,7 @@ public class DataNode implements Serializable { @NotNull public Collection> getChildren() { - return myChildren; + return myChildrenView; } private void writeObject(ObjectOutputStream out) throws IOException { @@ -304,7 +290,7 @@ public class DataNode implements Serializable { public void clear(boolean removeFromGraph) { if (removeFromGraph && myParent != null) { - for (Iterator> iterator = myParent.getChildren().iterator(); iterator.hasNext(); ) { + for (Iterator> iterator = myParent.myChildren.iterator(); iterator.hasNext(); ) { DataNode dataNode = iterator.next(); if (System.identityHashCode(dataNode) == System.identityHashCode(this)) { iterator.remove(); @@ -316,4 +302,17 @@ public class DataNode implements Serializable { myRawData = null; myChildren.clear(); } + + public DataNode graphCopy() { + return nodeCopy(this, null); + } + + private static DataNode nodeCopy(@NotNull DataNode dataNode, @Nullable DataNode newParent) { + DataNode copy = new DataNode(dataNode.myKey, dataNode.myData, newParent); + copy.myRawData = dataNode.myRawData; + for (DataNode child : dataNode.myChildren) { + copy.addChild(nodeCopy(child, copy)); + } + return copy; + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java index 4b487ca55232..0c61d23d6a7a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java @@ -138,7 +138,7 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent { InternalExternalProjectInfo merged = new InternalExternalProjectInfo( projectSystemId, projectPath, - externalProjectStructure + externalProjectStructure != null ? externalProjectStructure.graphCopy() : null ); merged.setLastImportTimestamp(lastImportTimestamp); merged.setLastSuccessfulImportTimestamp(lastSuccessfulImportTimestamp); From 186eddad1e16abea6431133d373c577f6453d037 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 11 Feb 2015 14:53:39 +0300 Subject: [PATCH 29/32] test fixed to new properties insertion logic --- .../intellij/lang/properties/PropertiesFileTest.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java index 159dd58d140d..b0d0c5e162f2 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java @@ -22,6 +22,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; @@ -30,16 +31,13 @@ import java.util.List; /** * @author max */ -public class PropertiesFileTest extends LightPlatformTestCase { +public class PropertiesFileTest extends LightPlatformCodeInsightFixtureTestCase { private Property myPropertyToAdd; - public PropertiesFileTest() { - PlatformTestCase.initPlatformLangPrefix(); - } - @Override protected void setUp() throws Exception { super.setUp(); + PlatformTestCase.initPlatformLangPrefix(); myPropertyToAdd = (Property)PropertiesElementFactory.createProperty(getProject(), "kkk", "vvv"); } @@ -73,8 +71,8 @@ public class PropertiesFileTest extends LightPlatformTestCase { List properties = propertiesFile.getProperties(); assertEquals(2, properties.size()); - assertPropertyEquals(properties.get(0), "xxx", "yyy"); - assertPropertyEquals(properties.get(1), myPropertyToAdd.getName(), myPropertyToAdd.getValue()); + assertPropertyEquals(properties.get(1), "xxx", "yyy"); + assertPropertyEquals(properties.get(0), myPropertyToAdd.getName(), myPropertyToAdd.getValue()); } public void testDeleteProperty() throws Exception { PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "xxx=yyy\n#s\nzzz=ttt\n\n"); From 6066258ca811fb7810ea5c382a0481b3a97a379e Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 11 Feb 2015 12:56:09 +0100 Subject: [PATCH 30/32] Cleanup (formatting) --- .../com/intellij/openapi/updateSettings/impl/UpdateChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 6bb4d1116278..1ced92ad9f97 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -566,7 +566,7 @@ public final class UpdateChecker { String bundledJdk = ""; String jdkMacRedist = System.getProperty("idea.java.redist"); - if (jdkMacRedist != null && jdkMacRedist.lastIndexOf("jdk-bundled") >= 0 ){ + if (jdkMacRedist != null && jdkMacRedist.lastIndexOf("jdk-bundled") >= 0) { bundledJdk = "jdk-bundled".equals(jdkMacRedist) ? "-jdk-bundled" : "-custom-jdk-bundled"; } From 13d3e721ba92f339416f67d93385bcf0ada4622c Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 11 Feb 2015 13:00:13 +0100 Subject: [PATCH 31/32] platform: restart capability check on Windows --- platform/util/src/com/intellij/util/Restarter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/Restarter.java b/platform/util/src/com/intellij/util/Restarter.java index 3e8692d7b9bd..aa0f024463a5 100644 --- a/platform/util/src/com/intellij/util/Restarter.java +++ b/platform/util/src/com/intellij/util/Restarter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ public class Restarter { public static boolean isSupported() { if (getRestartCode() != 0) return true; - if (SystemInfo.isWindows) return true; + if (SystemInfo.isWindows) return new File(PathManager.getBinPath(), "restarter.exe").exists(); if (SystemInfo.isMac) return PathManager.getHomePath().contains(".app"); return false; } From 47e6e070ab01fcdd50063b6022f339de6806b3bd Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 11 Feb 2015 15:21:37 +0300 Subject: [PATCH 32/32] XmlPropertiesFiles inserts property in alpha-order if it is possible --- .../properties/xml/XmlPropertiesFileImpl.java | 145 ++++++++++++++---- plugins/properties/testData/xml/bar.xml | 7 + .../properties/xml/XmlPropertiesTest.java | 19 +++ 3 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 plugins/properties/testData/xml/bar.xml diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java index a3a94c8f7f18..3590681522f8 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java @@ -33,7 +33,10 @@ import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.reference.SoftLazyValue; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; @@ -47,29 +50,54 @@ import java.util.*; * Date: 7/26/11 */ public class XmlPropertiesFileImpl extends XmlPropertiesFile { - private static final Key> KEY = Key.create("xml properties file"); private final XmlFile myFile; - private final SoftLazyValue> myPropertiesMap = new SoftLazyValue>() { + private final SoftLazyValue myInfo = new SoftLazyValue() { @NotNull @Override - protected MultiMap compute() { - XmlTag rootTag = myFile.getRootTag(); - if (rootTag == null) { - return MultiMap.emptyInstance(); - } - - XmlTag[] entries = rootTag.findSubTags("entry"); - MultiMap map = new MultiMap(); - - for (XmlTag entry : entries) { - XmlProperty property = new XmlProperty(entry, XmlPropertiesFileImpl.this); - map.putValue(property.getKey(), property); - } - return map; + protected Info compute() { + return new Info(); } }; + private class Info { + private final MultiMap myPropertiesMap = MultiMap.create(); + private List myPropertiesOrder; + private boolean mySorted; + + public Info() { + XmlTag rootTag = myFile.getRootTag(); + final List propertiesOrder = new ArrayList(); + if (rootTag != null) { + XmlTag[] entries = rootTag.findSubTags("entry"); + for (XmlTag entry : entries) { + XmlProperty property = new XmlProperty(entry, XmlPropertiesFileImpl.this); + propertiesOrder.add(property); + myPropertiesMap.putValue(property.getKey(), property); + } + } + mySorted = PropertiesImplUtil.isAlphaSorted(propertiesOrder); + myPropertiesOrder = mySorted ? propertiesOrder : null; + } + + public void setSorted(boolean sorted) { + mySorted = sorted; + myPropertiesOrder = null; + } + + public MultiMap getPropertiesMap() { + return myPropertiesMap; + } + + public List getPropertiesOrder() { + return myPropertiesOrder; + } + + public boolean isSorted() { + return mySorted; + } + } + private XmlPropertiesFileImpl(XmlFile file) { myFile = file; } @@ -83,19 +111,19 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { @NotNull @Override public List getProperties() { - return new ArrayList(myPropertiesMap.getValue().values()); + return new ArrayList(myInfo.getValue().getPropertiesMap().values()); } @Override public IProperty findPropertyByKey(@NotNull @NonNls String key) { - Collection properties = myPropertiesMap.getValue().get(key); + Collection properties = myInfo.getValue().getPropertiesMap().get(key); return properties.isEmpty() ? null : properties.iterator().next(); } @NotNull @Override public List findPropertiesByKey(@NotNull @NonNls String key) { - return new ArrayList(myPropertiesMap.getValue().get(key)); + return new ArrayList(myInfo.getValue().getPropertiesMap().get(key)); } @NotNull @@ -122,22 +150,62 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { @Override public IProperty addPropertyAfter(String key, String value, Property anchor) { - return null; + return addPropertyAfterAndCheckAlphaSorting(key, value, anchor, true, true); + } + + @NotNull + public IProperty addPropertyAfterAndCheckAlphaSorting(String key, String value, @Nullable IProperty anchor, boolean addToEnd, boolean checkAlphaSorting) { + final XmlTag anchorTag = anchor == null ? null : (XmlTag)anchor.getPsiElement(); + final XmlTag rootTag = myFile.getRootTag(); + final XmlTag entry = createPropertyTag(key, value); + final XmlTag addedEntry = (XmlTag) (anchorTag == null ? myFile.getRootTag().addSubTag(entry, !addToEnd) : rootTag.addAfter(entry, anchorTag)); + final XmlProperty property = new XmlProperty(addedEntry, this); + myInfo.getValue().getPropertiesMap().putValue(key, property); + if (checkAlphaSorting) { + checkAlphaSorting(property); + } + return property; } @NotNull @Override public IProperty addProperty(String key, String value) { + final XmlTag entry = createPropertyTag(key, value); + if (myInfo.getValue().isSorted()) { + final XmlProperty dummyProperty = new XmlProperty(entry, this); + final int insertIndex = Collections.binarySearch(myInfo.getValue().getPropertiesOrder(), dummyProperty, new Comparator() { + @Override + public int compare(IProperty p1, IProperty p2) { + final String k1 = p1.getKey(); + final String k2 = p2.getKey(); + return k1.compareTo(k2); + } + }); + final IProperty insertPosition; + final IProperty inserted; + if (insertIndex == -1) { + inserted = addPropertyAfterAndCheckAlphaSorting(key, value, null, false, false); + myInfo.getValue().getPropertiesOrder().add(0, inserted); + } + else { + final int position = insertIndex < 0 ? -insertIndex - 2 : insertIndex; + insertPosition = myInfo.getValue().getPropertiesOrder().get(position); + inserted = addPropertyAfterAndCheckAlphaSorting(key, value, insertPosition, false, false); + myInfo.getValue().getPropertiesOrder().add(position + 1, inserted); + } + return inserted; + } else { + return addPropertyAfterAndCheckAlphaSorting(key, value, null, true, false); + } + } + + private XmlTag createPropertyTag(final String key, final String value) { XmlTag rootTag = myFile.getRootTag(); XmlTag entry = rootTag.createChildTag("entry", "", value, false); entry.setAttribute("key", key); - rootTag.addSubTag(entry, false); - final XmlProperty property = new XmlProperty(entry, this); - myPropertiesMap.getValue().putValue(key, property); - return property; + return entry; } - public static PropertiesFile getPropertiesFile(final PsiFile file) { CachedValuesManager manager = CachedValuesManager.getManager(file.getProject()); if (file instanceof XmlFile) { @@ -194,7 +262,7 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { @Override public boolean isAlphaSorted() { - return PropertiesImplUtil.isAlphaSorted(getProperties()); + return myInfo.getValue().isSorted(); } @Override @@ -213,4 +281,29 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { public int hashCode() { return myFile.hashCode(); } + + private void checkAlphaSorting(final IProperty property) { + if (myInfo.getValue().isSorted()) { + final String key = property.getKey(); + final XmlTag prev = getSibling((XmlTag)property.getPsiElement(), true); + final String prevKey = prev == null ? null : new XmlProperty(prev, this).getKey(); + if (prevKey != null && key != null && prevKey.compareTo(key) > 0) { + myInfo.getValue().setSorted(false); + } else { + final XmlTag next = getSibling((XmlTag)property.getPsiElement(), false); + final String nextKey = next == null ? null : new XmlProperty(next, this).getKey(); + if (nextKey != null && key != null && nextKey.compareTo(key) < 0) { + myInfo.getValue().setSorted(false); + } + } + } + } + + private static XmlTag getSibling(final XmlTag entry, final boolean prev) { + XmlTag sibling = (XmlTag)(prev ? entry.getPrevSibling() : entry.getNextSibling()); + while (sibling != null && !"entry".equals(sibling.getName())) { + sibling = (XmlTag)(prev ? sibling.getPrevSibling() : sibling.getNextSibling()); + } + return sibling; + } } diff --git a/plugins/properties/testData/xml/bar.xml b/plugins/properties/testData/xml/bar.xml new file mode 100644 index 000000000000..b85abb53cc8e --- /dev/null +++ b/plugins/properties/testData/xml/bar.xml @@ -0,0 +1,7 @@ + + + + Hi + bar + baz + \ No newline at end of file diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/xml/XmlPropertiesTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/xml/XmlPropertiesTest.java index d16eaf352f38..fd4b1212107f 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/xml/XmlPropertiesTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/xml/XmlPropertiesTest.java @@ -9,6 +9,8 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.psi.PsiFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import java.util.List; @@ -81,6 +83,23 @@ public class XmlPropertiesTest extends LightPlatformCodeInsightFixtureTestCase { assertEquals("vvv", property2.getValue()); } + public void testAddPropertyInAlphaOrder() { + final PsiFile psiFile = myFixture.configureByFile("bar.xml"); + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(psiFile); + assertNotNull(propertiesFile); + + WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() { + public void run() { + propertiesFile.addProperty("d", "vvv"); + propertiesFile.addProperty("a", "vvv"); + propertiesFile.addProperty("l", "vvv"); + propertiesFile.addProperty("v", "vvv"); + } + }); + assertTrue(propertiesFile.isAlphaSorted()); + assertTrue(PropertiesImplUtil.getPropertiesFile(psiFile).isAlphaSorted()); + } + @Override protected String getTestDataPath() { return PluginPathManager.getPluginHomePath("properties") + "/testData/xml/";