diff --git a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java index b420c5801a2f..d3f5d3e056b7 100644 --- a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java +++ b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java @@ -114,6 +114,25 @@ public class RainbowHighlighter { return RAINBOW_TYPE + " " + (language == null ? UIBundle.message("color.settings.common.default.language") : language.getID()); } + @Contract(value = "null -> false", pure = true) + public static boolean isRainbowKey(@Nullable Object key) { + return key instanceof String && ((String)key).startsWith(RAINBOW_TYPE); + } + + public static void transferRainbowState(@NotNull SchemeMetaInfo dst, @NotNull SchemeMetaInfo src) { + final Properties dstProps = dst.getMetaProperties(); + dstProps.keySet().forEach((key) -> { + if (isRainbowKey(key)) { + dstProps.remove(key); + } + }); + src.getMetaProperties().forEach((Object key, Object value) -> { + if (isRainbowKey(key) && value instanceof String) { + dstProps.setProperty((String)key, (String)value); + } + }); + } + @NotNull public static String generatePaletteExample(@NotNull String indent) { int stopCount = RAINBOW_COLOR_KEYS.length; diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index f11a7fb528d6..e2f3a3f28c41 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -19,6 +19,7 @@ package com.intellij.application.options.colors; import com.intellij.application.options.OptionsContainingConfigurable; import com.intellij.application.options.editor.EditorOptionsProvider; import com.intellij.application.options.schemes.SchemesModel; +import com.intellij.codeHighlighting.RainbowHighlighter; import com.intellij.execution.impl.ConsoleViewUtil; import com.intellij.ide.ui.LafManager; import com.intellij.ide.ui.laf.LafManagerImpl; @@ -593,7 +594,6 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract @NotNull MyColorScheme scheme) { String group = provider.getDisplayName(); List attributeDescriptors = ColorSettingsUtil.getAllAttributeDescriptors(provider); - //todo: single point configuration? if (provider instanceof RainbowColorSettingsPage) { descriptions.add(new RainbowAttributeDescriptor(((RainbowColorSettingsPage)provider).getLanguage(), group, @@ -603,17 +603,6 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } for (AttributesDescriptor descriptor : attributeDescriptors) { addSchemedDescription(descriptions, descriptor.getDisplayName(), group, descriptor.getKey(), scheme, null, null); - // if (provider instanceof RainbowColorSettingsPage - // && ((RainbowColorSettingsPage)provider).isRainbowType(descriptor.getKey())) { - // //todo: joined sub-descriptor? - // descriptions.add(new RainbowAttributeDescriptor(group, - // descriptor.getDisplayName() - // + EditorSchemeAttributeDescriptorWithPath.NAME_SEPARATOR - // + ApplicationBundle.message("rainbow.option.panel.display.name"), - // scheme, - // scheme.getInitRainbowState(), - // scheme.getCurrentRainbowState())); - // } } ColorDescriptor[] colorDescriptors = provider.getColorDescriptors(); @@ -1101,8 +1090,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract setQuickDocFontSize(parentScheme.getQuickDocFontSize()); myName = parentScheme.getName(); - //noinspection UseOfPropertiesAsHashtable - getMetaProperties().putAll(parentScheme.getMetaProperties()); + RainbowHighlighter.transferRainbowState(this, parentScheme); myRainbowState = new RainbowColorsInSchemeState(this, parentScheme); initFonts(); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java index b4957eafd0b0..71e57b12c6ad 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java @@ -62,11 +62,8 @@ class RainbowAttributeDescriptor implements EditorSchemeAttributeDescriptorWithP } @Override - public void apply(@NotNull EditorColorsScheme scheme) { - if (myLanguage == null) { - // call it once for 'Default Language' - myRainbowColorsInSchemaState.apply(scheme); - } + public void apply(@Nullable EditorColorsScheme scheme) { + myRainbowColorsInSchemaState.apply(scheme); } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java index b02b2e81b087..7c365b26cd2b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java @@ -40,11 +40,9 @@ public class RainbowColorsInSchemeState { myOriginalScheme = originalScheme; } - public void apply(@NotNull EditorColorsScheme scheme) { - if (scheme != myEditedScheme) { - scheme.getMetaProperties().clear(); - //noinspection UseOfPropertiesAsHashtable - scheme.getMetaProperties().putAll(myEditedScheme.getMetaProperties()); + public void apply(@Nullable EditorColorsScheme scheme) { + if (scheme != null && scheme != myEditedScheme) { + RainbowHighlighter.transferRainbowState(scheme, myEditedScheme); for (TextAttributesKey key : RainbowHighlighter.RAINBOW_COLOR_KEYS) { Color color = myEditedScheme.getAttributes(key).getForegroundColor(); if (!color.equals(scheme.getAttributes(key).getForegroundColor()) ) { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index cb4bfe00a33e..05fd0e8db173 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -15,7 +15,9 @@ */ package com.intellij.openapi.editor.colors.impl; +import com.intellij.codeHighlighting.RainbowHighlighter; import com.intellij.editor.EditorColorSchemeTestCase; +import com.intellij.lang.Language; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.markup.EffectType; @@ -325,4 +327,57 @@ public class EditorColorsSchemeImplTest extends EditorColorSchemeTestCase { TextAttributesKey.removeTextAttributesKey(testKey.getExternalName()); } } + + public void testWriteDefaultSemanticHighlighting() throws Exception { + EditorColorsScheme defaultScheme = EditorColorsManager.getInstance().getScheme(EditorColorsScheme.DEFAULT_SCHEME_NAME); + EditorColorsScheme editorColorsScheme = (EditorColorsScheme)defaultScheme.clone(); + editorColorsScheme.setName("rainbow"); + + final String BEGIN = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n"; + final String END = + " \n" + + ""; + + boolean nonDefaultRainbow = !RainbowHighlighter.DEFAULT_RAINBOW_ON; + + RainbowHighlighter.setRainbowEnabled(editorColorsScheme, null, nonDefaultRainbow); + assertTrue(RainbowHighlighter.isRainbowEnabled(editorColorsScheme, null) == nonDefaultRainbow); + assertXmlOutputEquals( + BEGIN + + " " + nonDefaultRainbow + "\n" + + END, + serializeWithFixedMeta(editorColorsScheme)); + + RainbowHighlighter.setRainbowEnabled(editorColorsScheme, Language.ANY, nonDefaultRainbow); + assertTrue(RainbowHighlighter.isRainbowEnabled(editorColorsScheme, Language.ANY) == nonDefaultRainbow); + assertXmlOutputEquals( + BEGIN + + " " + nonDefaultRainbow + "\n" + + " " + nonDefaultRainbow + "\n" + + END, + serializeWithFixedMeta(editorColorsScheme)); + + RainbowHighlighter.setRainbowEnabled(editorColorsScheme, Language.ANY, null); + assertNull(RainbowHighlighter.isRainbowEnabled(editorColorsScheme, Language.ANY)); + assertTrue(RainbowHighlighter.isRainbowEnabledWithInheritance(editorColorsScheme, Language.ANY) == nonDefaultRainbow); + assertXmlOutputEquals( + BEGIN + + " " + nonDefaultRainbow + "\n" + + END, + serializeWithFixedMeta(editorColorsScheme)); + + RainbowHighlighter.setRainbowEnabled(editorColorsScheme, null, RainbowHighlighter.DEFAULT_RAINBOW_ON); + assertTrue(RainbowHighlighter.isRainbowEnabledWithInheritance(editorColorsScheme, null) == RainbowHighlighter.DEFAULT_RAINBOW_ON); + assertTrue(RainbowHighlighter.isRainbowEnabledWithInheritance(editorColorsScheme, Language.ANY) == RainbowHighlighter.DEFAULT_RAINBOW_ON); + assertXmlOutputEquals( + BEGIN + END, + serializeWithFixedMeta(editorColorsScheme)); + } } diff --git a/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java b/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java index 1159a7632411..357d999b6e8a 100644 --- a/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java +++ b/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java @@ -15,6 +15,7 @@ */ package com.intellij.editor; +import com.intellij.codeHighlighting.RainbowHighlighter; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; @@ -23,6 +24,7 @@ import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Pair; import com.intellij.testFramework.LightPlatformTestCase; +import org.jdom.Attribute; import org.jdom.Element; import org.jdom.input.DOMBuilder; import org.jdom.output.Format; @@ -91,6 +93,24 @@ public abstract class EditorColorSchemeTestCase extends LightPlatformTestCase { return root; } + protected Element serializeWithFixedMeta(@NotNull EditorColorsScheme scheme) { + Element root = new Element("scheme"); + ((AbstractColorsScheme)scheme).writeExternal(root); + fixPlatformSpecificValues(root); + Element metaInfo = root.getChild("metaInfo"); + if (metaInfo != null) { + metaInfo.getChildren().forEach((child) -> { + Attribute name = child.getAttribute("name"); + if (!child.getName().equals("property") + || name == null + || !RainbowHighlighter.isRainbowKey(name.getValue())) { + child.removeContent(); + } + }); + } + return root; + } + private static void fixPlatformSpecificValues(@NotNull Element root) { List fontOptions = new ArrayList<>(root.getChildren("option")); for (Element option : fontOptions) {