diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java
index fbf3b77ddf20..9a7268339b7e 100644
--- a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java
+++ b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,11 +48,7 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings {
}
@Override
- public void importLegacySettings() {
- importLegacyUseFqClassNamesInJavadocSetting();
- }
-
- private void importLegacyUseFqClassNamesInJavadocSetting() {
+ protected void importLegacySettings() {
CodeStyleSettings settings = getContainer();
boolean isDefaultValue = settings.USE_FQ_CLASS_NAMES_IN_JAVADOC;
if (!isDefaultValue) {
diff --git a/platform/configuration-store-impl/testSrc/CodeStyleTest.kt b/platform/configuration-store-impl/testSrc/CodeStyleTest.kt
new file mode 100644
index 000000000000..014e10432220
--- /dev/null
+++ b/platform/configuration-store-impl/testSrc/CodeStyleTest.kt
@@ -0,0 +1,45 @@
+package com.intellij.configurationStore
+
+import com.intellij.openapi.util.JDOMUtil
+import com.intellij.psi.codeStyle.CodeStyleSettings
+import com.intellij.testFramework.ProjectRule
+import com.intellij.util.loadElement
+import org.assertj.core.api.Assertions.assertThat
+import org.jdom.Element
+import org.junit.ClassRule
+import org.junit.Test
+
+class CodeStyleTest {
+ companion object {
+ @JvmField
+ @ClassRule
+ val projectRule = ProjectRule()
+ }
+
+ @Test fun `do not remove unknown`() {
+ val settings = CodeStyleSettings()
+ val loaded = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """.trimIndent()
+ settings.readExternal(loadElement(loaded))
+
+ val serialized = Element("code_scheme").setAttribute("name", "testSchemeName")
+ settings.writeExternal(serialized)
+ assertThat(JDOMUtil.writeElement(serialized)).isEqualTo(loaded)
+ }
+}
\ No newline at end of file
diff --git a/platform/lang-api/lang-api.iml b/platform/lang-api/lang-api.iml
index c6851ed56112..f854eaacf13a 100644
--- a/platform/lang-api/lang-api.iml
+++ b/platform/lang-api/lang-api.iml
@@ -16,5 +16,6 @@
+
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/configurationStore/UnknownElementManager.kt b/platform/lang-api/src/com/intellij/configurationStore/UnknownElementManager.kt
new file mode 100644
index 000000000000..0f68e88d8918
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/configurationStore/UnknownElementManager.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2016 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.configurationStore
+
+import gnu.trove.THashMap
+import gnu.trove.THashSet
+import org.jdom.Element
+import java.util.function.Consumer
+import java.util.function.Function
+
+// Empty unknown tags supported to simplify client write code (with and without unknown elements)
+class UnknownElementWriter internal constructor(private val unknownElements: Map = emptyMap()) {
+ companion object {
+ @JvmField
+ val EMPTY = UnknownElementWriter()
+ }
+
+ fun write(outElement: Element, items: Collection, itemToTagName: Function, writer: Consumer) {
+ val knownNameToWriter = THashMap(items.size)
+ for (item in items) {
+ knownNameToWriter.put(itemToTagName.apply(item), item)
+ }
+ write(outElement, knownNameToWriter, writer)
+ }
+
+ fun write(outElement: Element, knownNameToWriter: Map, writer: Consumer) {
+ val names: Set
+ if (unknownElements.isEmpty()) {
+ names = knownNameToWriter.keys
+ }
+ else {
+ names = THashSet(unknownElements.keys)
+ names.addAll(knownNameToWriter.keys)
+ }
+
+ val sortedNames = names.toTypedArray()
+ sortedNames.sort()
+ for (name in sortedNames) {
+ val known = knownNameToWriter.get(name)
+ if (known == null) {
+ outElement.addContent(unknownElements.get(name)!!.clone())
+ }
+ else {
+ writer.accept(known)
+ }
+ }
+ }
+}
+
+class UnknownElementCollector {
+ private val knownTagNames = THashSet()
+
+ fun addKnownName(name: String) {
+ knownTagNames.add(name)
+ }
+
+ fun createWriter(element: Element): UnknownElementWriter? {
+ var unknownElements: MutableMap? = null
+ val iterator = element.children.iterator()
+ for (child in iterator) {
+ if (child.name != "option" && !knownTagNames.contains(child.name)) {
+ if (unknownElements == null) {
+ unknownElements = THashMap()
+ }
+ unknownElements.put(child.name, child)
+ iterator.remove()
+ }
+ }
+
+ return unknownElements?.let { UnknownElementWriter(it) } ?: UnknownElementWriter.EMPTY
+ }
+}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
index fcff0cbbef86..518fdbe2b5ae 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
@@ -15,6 +15,8 @@
*/
package com.intellij.psi.codeStyle;
+import com.intellij.configurationStore.UnknownElementCollector;
+import com.intellij.configurationStore.UnknownElementWriter;
import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -57,6 +59,8 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
@NonNls private static final String FILETYPE = "fileType";
private CommonCodeStyleSettingsManager myCommonSettingsManager = new CommonCodeStyleSettingsManager(this);
+ private UnknownElementWriter myUnknownElementWriter = UnknownElementWriter.EMPTY;
+
public CodeStyleSettings() {
this(true);
}
@@ -490,11 +494,14 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
}
}
+
+ UnknownElementCollector unknownElementCollector = new UnknownElementCollector();
for (CustomCodeStyleSettings settings : getCustomSettingsValues()) {
+ unknownElementCollector.addKnownName(settings.getTagName());
settings.readExternal(element);
- settings.importLegacySettings();
}
+ unknownElementCollector.addKnownName(ADDITIONAL_INDENT_OPTIONS);
List list = element.getChildren(ADDITIONAL_INDENT_OPTIONS);
if (list != null) {
for (Element additionalIndentElement : list) {
@@ -512,8 +519,11 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
}
}
+ unknownElementCollector.addKnownName(CommonCodeStyleSettingsManager.COMMON_SETTINGS_TAG);
myCommonSettingsManager.readExternal(element);
+ myUnknownElementWriter = unknownElementCollector.createWriter(element);
+
if (USE_SAME_INDENTS) {
IGNORE_SAME_INDENTS_FOR_LANGUAGES = true;
}
@@ -523,16 +533,14 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public void writeExternal(Element element) throws WriteExternalException {
final CodeStyleSettings parentSettings = new CodeStyleSettings();
DefaultJDOMExternalizer.writeExternal(this, element, new DifferenceFilter(this, parentSettings));
- List customSettings = new ArrayList(getCustomSettingsValues());
- customSettings.sort((o1, o2) -> o1.getTagName().compareTo(o2.getTagName()));
- for (final CustomCodeStyleSettings settings : customSettings) {
- final CustomCodeStyleSettings parentCustomSettings = parentSettings.getCustomSettings(settings.getClass());
+ myUnknownElementWriter.write(element, getCustomSettingsValues(), CustomCodeStyleSettings::getTagName, settings -> {
+ CustomCodeStyleSettings parentCustomSettings = parentSettings.getCustomSettings(settings.getClass());
if (parentCustomSettings == null) {
throw new WriteExternalException("Custom settings are null for " + settings.getClass());
}
settings.writeExternal(element, parentCustomSettings);
- }
+ });
final FileType[] fileTypes = myAdditionalIndentOptions.keySet().toArray(new FileType[myAdditionalIndentOptions.keySet().size()]);
Arrays.sort(fileTypes, (o1, o2) -> o1.getDefaultExtension().compareTo(o2.getDefaultExtension()));
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java
index be7167d389ef..bc280db0fe54 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java
@@ -45,7 +45,7 @@ public class CommonCodeStyleSettingsManager {
@NotNull private final CodeStyleSettings myParentSettings;
- @NonNls private static final String COMMON_SETTINGS_TAG = "codeStyleSettings";
+ @NonNls static final String COMMON_SETTINGS_TAG = "codeStyleSettings";
private static final String LANGUAGE_ATTR = "language";
CommonCodeStyleSettingsManager(@NotNull CodeStyleSettings parentSettings) {
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CustomCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CustomCodeStyleSettings.java
index 3ccfa1ca4e8c..967cb4d65e82 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CustomCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CustomCodeStyleSettings.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,11 @@ public abstract class CustomCodeStyleSettings implements Cloneable {
}
public void readExternal(Element parentElement) throws InvalidDataException {
- DefaultJDOMExternalizer.readExternal(this, parentElement.getChild(myTagName));
+ Element child = parentElement.getChild(myTagName);
+ if (child != null) {
+ DefaultJDOMExternalizer.readExternal(this, child);
+ importLegacySettings();
+ }
}
public void writeExternal(Element parentElement, @NotNull final CustomCodeStyleSettings parentSettings) throws WriteExternalException {
@@ -69,7 +73,6 @@ public abstract class CustomCodeStyleSettings implements Cloneable {
/**
* For compatibility with old code style settings stored in CodeStyleSettings.
*/
- public void importLegacySettings() {
+ protected void importLegacySettings() {
}
-
}
diff --git a/platform/util/src/com/intellij/openapi/util/WriteExternalException.java b/platform/util/src/com/intellij/openapi/util/WriteExternalException.java
index 76714142f974..586a2b520337 100644
--- a/platform/util/src/com/intellij/openapi/util/WriteExternalException.java
+++ b/platform/util/src/com/intellij/openapi/util/WriteExternalException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ package com.intellij.openapi.util;
* Throw this exception from {@link JDOMExternalizable#writeExternal(org.jdom.Element)} method if you don't want to store any settings.
* If you simply return from the method empty '' tag will be written leading to unneeded modification of configuration files.
*/
-public class WriteExternalException extends Exception {
+public class WriteExternalException extends RuntimeException {
public WriteExternalException() {
super();
}
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java
index 5489e3f75b05..aa52d88f058d 100644
--- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlCodeStyleSettings.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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 XmlCodeStyleSettings extends CustomCodeStyleSettings {
}
@Override
- public void importLegacySettings() {
+ protected void importLegacySettings() {
if (!XML_LEGACY_SETTINGS_IMPORTED) {
CodeStyleSettings container = getContainer();
CodeStyleSettings defaults = new CodeStyleSettings();