diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfile.kt b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfile.kt index 57d6462609e0..08f21737413e 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfile.kt +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfile.kt @@ -27,6 +27,7 @@ import com.intellij.profile.codeInspection.BaseInspectionProfileManager import com.intellij.profile.codeInspection.InspectionProfileManager import com.intellij.profile.codeInspection.ProjectInspectionProfileManager import com.intellij.util.xmlb.annotations.Transient +import org.jdom.Element const val DEFAULT_PROFILE_NAME = "Default" val BASE_PROFILE by lazy { InspectionProfileImpl(DEFAULT_PROFILE_NAME) } @@ -120,6 +121,16 @@ abstract class NewInspectionProfile(name: String, private var profileManager: Ba } protected abstract fun initialize(project: Project?) + + fun copyFrom(profile: InspectionProfileImpl) { + var element = profile.writeScheme() + if (element.name == "component") { + element = element.getChild("profile") + } + readExternal(element) + } + + abstract fun readExternal(element: Element) } fun createSimple(name: String, project: Project, toolWrappers: List>): InspectionProfileImpl { diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java index 03c112561ec3..15961321ddb7 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java @@ -143,9 +143,8 @@ public class InspectionProfileImpl extends NewInspectionProfile { return level; } - @Override public void readExternal(@NotNull Element element) { - super.readExternal(element); + mySerializer.readExternal(this, element); final Element highlightElement = element.getChild(USED_LEVELS); if (highlightElement != null) { @@ -208,7 +207,8 @@ public class InspectionProfileImpl extends NewInspectionProfile { return myDataHolder.read(); } - Element element = super.writeScheme(); + Element element = new Element(PROFILE); + writeExternal(element); if (isProjectLevel()) { element.setAttribute("version", "1.0"); } @@ -222,12 +222,11 @@ public class InspectionProfileImpl extends NewInspectionProfile { return element; } - @Override public void writeExternal(@NotNull Element element) { // must be first - compatibility element.setAttribute(VERSION_TAG, VALID_VERSION); - super.writeExternal(element); + mySerializer.writeExternal(this, element); synchronized (myLock) { if (!wasInitialized()) { diff --git a/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java b/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java index 0d5c69902433..a04f7b38207b 100644 --- a/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java +++ b/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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,6 @@ package com.intellij.profile; import com.intellij.openapi.options.ExternalizableScheme; import com.intellij.util.xmlb.SmartSerializer; import com.intellij.util.xmlb.annotations.OptionTag; -import org.jdom.Element; import org.jetbrains.annotations.NotNull; /** @@ -30,7 +29,7 @@ public abstract class ProfileEx implements Comparable, ExternalizableScheme { public static final String NAME = "name"; public static final String PROFILE = "profile"; - private final SmartSerializer mySerializer; + protected final SmartSerializer mySerializer; @NotNull protected String myName; @@ -57,14 +56,6 @@ public abstract class ProfileEx implements Comparable, ExternalizableScheme { myName = name; } - public void readExternal(Element element) { - mySerializer.readExternal(this, element); - } - - public void writeExternal(@NotNull Element element) { - mySerializer.writeExternal(this, element, false); - } - public boolean equals(Object o) { return this == o || o instanceof ProfileEx && myName.equals(((ProfileEx)o).myName); } @@ -80,19 +71,4 @@ public abstract class ProfileEx implements Comparable, ExternalizableScheme { } return 0; } - - public final void copyFrom(@NotNull ProfileEx profile) { - Element element = profile.writeScheme(); - if (element.getName().equals("component")) { - element = element.getChild("profile"); - } - readExternal(element); - } - - @NotNull - public Element writeScheme() { - Element element = new Element(PROFILE); - writeExternal(element); - return element; - } } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt b/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt index dbf9f7437faa..c6fb2f2dd884 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt +++ b/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt @@ -19,6 +19,7 @@ import com.intellij.openapi.util.ModificationTracker import com.intellij.util.SmartList import com.intellij.util.xmlb.Accessor import com.intellij.util.xmlb.SerializationFilter +import com.intellij.util.xmlb.annotations.Transient import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -26,7 +27,8 @@ abstract class BaseState : SerializationFilter, ModificationTracker { // if property value differs from default private val properties: MutableList = SmartList() - @Volatile internal var modificationCount: Long = 0 + @Volatile + internal var modificationCount: Long = 0 // reset on load state fun resetModificationCount() { @@ -52,6 +54,15 @@ abstract class BaseState : SerializationFilter, ModificationTracker { return result } + /** + * Empty string is always normalized to null. + */ + fun string(defaultValue: String? = null): ReadWriteProperty { + val result = StringStoredProperty(defaultValue) + properties.add(result) + return result + } + fun storedProperty(defaultValue: Int = 0): ReadWriteProperty { val result = IntStoredProperty(defaultValue) properties.add(result) @@ -70,6 +81,7 @@ abstract class BaseState : SerializationFilter, ModificationTracker { return result } + @Transient override fun getModificationCount(): Long { var result = modificationCount for (property in properties) { @@ -97,27 +109,49 @@ abstract class BaseState : SerializationFilter, ModificationTracker { builder.setLength(builder.length - 1) return builder.toString() } + + fun copyFrom(state: BaseState) { + assert(state.properties.size == properties.size) + for ((index, property) in properties.withIndex()) { + val otherProperty = state.properties.get(index) + if (property.name != null) { + if (otherProperty.name == null) { + otherProperty.name = property.name + } + else { + assert(otherProperty.name == property.name) + } + } + property.setValue(otherProperty) + } + } } internal interface StoredProperty { val defaultValue: Any? val value: Any? - val name: String? + var name: String? + + fun setValue(other: StoredProperty) } private class ObjectStoredProperty(override val defaultValue: T) : ReadWriteProperty, StoredProperty { override var value = defaultValue override var name: String? = null - override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value + override operator fun getValue(thisRef: BaseState, property: KProperty<*>): T { + name = property.name + return value + } @Suppress("UNCHECKED_CAST") override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: T) { + name = property.name + if (value != newValue) { thisRef.modificationCount++ - name = property.name value = newValue } } @@ -127,20 +161,64 @@ private class ObjectStoredProperty(override val defaultValue: T) : ReadWriteP override fun hashCode() = value?.hashCode() ?: 0 override fun toString() = if (value === defaultValue) "" else value?.toString() ?: super.toString() + + override fun setValue(other: StoredProperty) { + @Suppress("UNCHECKED_CAST") + value = (other as ObjectStoredProperty).value + } +} + +private class StringStoredProperty(override val defaultValue: String?) : ReadWriteProperty, StoredProperty { + override var value = defaultValue + override var name: String? = null + + override operator fun getValue(thisRef: BaseState, property: KProperty<*>): String? { + name = property.name + return value + } + + @Suppress("UNCHECKED_CAST") + override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") _newValue: String?) { + name = property.name + + var newValue = _newValue + if (newValue != null && newValue.isEmpty()) { + newValue = null + } + + if (value != newValue) { + thisRef.modificationCount++ + value = newValue + } + } + + override fun equals(other: Any?) = this === other || (other is ObjectStoredProperty<*> && value == other.value) + + override fun hashCode() = value?.hashCode() ?: 0 + + override fun toString() = if (value == defaultValue) "" else value ?: super.toString() + + override fun setValue(other: StoredProperty) { + value = (other as StringStoredProperty).value + } } private class IntStoredProperty(override val defaultValue: Int) : ReadWriteProperty, StoredProperty { override var value = defaultValue override var name: String? = null - override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value + override operator fun getValue(thisRef: BaseState, property: KProperty<*>): Int { + name = property.name + return value + } @Suppress("UNCHECKED_CAST") override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Int) { + name = property.name + if (value != newValue) { thisRef.modificationCount++ - name = property.name value = newValue } } @@ -150,20 +228,28 @@ private class IntStoredProperty(override val defaultValue: Int) : ReadWritePrope override fun hashCode() = value.hashCode() override fun toString() = if (value == defaultValue) "" else value.toString() + + override fun setValue(other: StoredProperty) { + value = (other as IntStoredProperty).value + } } private class FloatStoredProperty(override val defaultValue: Float) : ReadWriteProperty, StoredProperty { override var value = defaultValue override var name: String? = null - override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value + override operator fun getValue(thisRef: BaseState, property: KProperty<*>): Float { + name = property.name + return value + } @Suppress("UNCHECKED_CAST") override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Float) { + name = property.name + if (value != newValue) { thisRef.modificationCount++ - name = property.name value = newValue } } @@ -173,4 +259,8 @@ private class FloatStoredProperty(override val defaultValue: Float) : ReadWriteP override fun hashCode() = value.hashCode() override fun toString() = if (value == defaultValue) "" else value.toString() + + override fun setValue(other: StoredProperty) { + value = (other as FloatStoredProperty).value + } } \ No newline at end of file diff --git a/plugins/copyright/src/CopyrightManager.kt b/plugins/copyright/src/CopyrightManager.kt index fa7c89c346a0..9d9bb7b96e3e 100644 --- a/plugins/copyright/src/CopyrightManager.kt +++ b/plugins/copyright/src/CopyrightManager.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -79,14 +79,13 @@ class CopyrightManager(private val project: Project, schemeManagerFactory: Schem val options = Options() private val schemeWriter = { scheme: CopyrightProfile -> - val element = Element("copyright") - scheme.writeExternal(element) + val element = scheme.writeScheme() if (project.isDirectoryBased) wrapScheme(element) else element } private val schemeManagerIprProvider = if (project.isDirectoryBased) null else SchemeManagerIprProvider("copyright") - val schemeManager = schemeManagerFactory.create("copyright", object : LazySchemeProcessor, SchemeWrapper>() { + val schemeManager = schemeManagerFactory.create("copyright", object : LazySchemeProcessor, SchemeWrapper>("myName") { override fun createScheme(dataHolder: SchemeDataHolder>, name: String, attributeProvider: Function, @@ -264,7 +263,8 @@ private class CopyrightLazySchemeWrapper(name: String, element = element.getChild(subStateTagName) } - scheme.readExternal(element) + element.deserializeInto(scheme) + scheme.resetModificationCount() dataHolder.updateDigest(writer(scheme)) scheme } diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.kt b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.kt index c42c0e410932..075ea410ccea 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.kt +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.kt @@ -15,27 +15,50 @@ */ package com.maddyhome.idea.copyright -import com.intellij.openapi.util.text.StringUtil -import com.intellij.profile.ProfileEx -import com.intellij.util.xmlb.SmartSerializer +import com.intellij.configurationStore.SerializableScheme +import com.intellij.configurationStore.serializeInto +import com.intellij.openapi.components.BaseState +import com.intellij.openapi.options.ExternalizableScheme +import com.intellij.util.xmlb.annotations.OptionTag +import com.intellij.util.xmlb.annotations.Transient import com.maddyhome.idea.copyright.pattern.EntityUtil +import org.jdom.Element -class CopyrightProfile @JvmOverloads constructor(profileName: String = "") : ProfileEx(profileName, SmartSerializer()) { - companion object { - @JvmField - val DEFAULT_COPYRIGHT_NOTICE: String = EntityUtil.encode( - "Copyright (c) \$today.year. Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n" + - "Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. \n" + - "Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. \n" + - "Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. \n" + - "Vestibulum commodo. Ut rhoncus gravida arcu. ") +@JvmField +val DEFAULT_COPYRIGHT_NOTICE: String = EntityUtil.encode( + "Copyright (c) \$today.year. Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n" + + "Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. \n" + + "Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. \n" + + "Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. \n" + + "Vestibulum commodo. Ut rhoncus gravida arcu. ") + +class CopyrightProfile @JvmOverloads constructor(profileName: String? = null) : ExternalizableScheme, BaseState(), SerializableScheme { + // ugly name to preserve compatibility + // must be not private because otherwise binding is not created for private accessor + @get:OptionTag("myName") + internal var profileName by string() + + var notice by string(DEFAULT_COPYRIGHT_NOTICE) + var keyword by string(EntityUtil.encode("Copyright")) + var allowReplaceRegexp by string() + + init { + // otherwise will be as default value and name will be not serialized + this.profileName = profileName } - var notice = DEFAULT_COPYRIGHT_NOTICE - var keyword = EntityUtil.encode("Copyright") + @Transient + override fun getName() = profileName ?: "" - var allowReplaceRegexp: String? = null - set(allowReplaceRegexp) { - field = StringUtil.nullize(allowReplaceRegexp) - } -}//read external + override fun setName(value: String) { + profileName = value + } + + override fun toString() = profileName ?: "" + + override fun writeScheme(): Element { + val element = Element("copyright") + serializeInto(element) + return element + } +} diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java index ba2231a3ab8b..fc6e8cd898a7 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/ui/TemplateCommentPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -28,7 +28,7 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.DocumentAdapter; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.util.ui.UIUtil; -import com.maddyhome.idea.copyright.CopyrightProfile; +import com.maddyhome.idea.copyright.CopyrightProfileKt; import com.maddyhome.idea.copyright.options.LanguageOptions; import com.maddyhome.idea.copyright.options.Options; import com.maddyhome.idea.copyright.pattern.EntityUtil; @@ -340,7 +340,7 @@ public class TemplateCommentPanel implements SearchableConfigurable { private void showPreview(LanguageOptions options) { final String defaultCopyrightText = myNoCopyright.isSelected() ? "" : FileTypeUtil - .buildComment(fileType, VelocityHelper.evaluate(null, null, null, EntityUtil.decode(CopyrightProfile.DEFAULT_COPYRIGHT_NOTICE)), options); + .buildComment(fileType, VelocityHelper.evaluate(null, null, null, EntityUtil.decode(CopyrightProfileKt.DEFAULT_COPYRIGHT_NOTICE)), options); SwingUtilities.invokeLater(() -> preview.setText(defaultCopyrightText)); }