BaseState - introduce convenient methods for treeSet/set instead of basic
authordevelar <develar@gmail.com>
Sat, 27 Apr 2019 07:14:38 +0000 (09:14 +0200)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Sun, 28 Apr 2019 16:47:34 +0000 (19:47 +0300)
GitOrigin-RevId: 54962a138324938c0d3ba28fc14fbabdcc9c2f6e

platform/lang-impl/src/com/intellij/codeInspection/ex/VisibleTreeState.kt
platform/projectModel-api/src/com/intellij/configurationStore/properties/CollectionStoredProperty.kt
platform/projectModel-api/src/com/intellij/openapi/components/BaseState.kt
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointsDialogState.kt

index cc05e7fd01ee118282439275148cbbb540579655..7d8e07300b7a4825f27f5be171b98d73d2d4d6c3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.codeInspection.ex
 
 import com.intellij.openapi.components.BaseState
@@ -15,10 +15,10 @@ import javax.swing.tree.TreePath
 @Tag("profile-state")
 internal class VisibleTreeState : BaseState() {
   @get:XCollection(elementName = "expanded", valueAttributeName = "path", propertyElementName = "expanded-state")
-  var expandedNodes by property(TreeSet<State>())
+  var expandedNodes by treeSet<State>()
 
   @get:XCollection(elementName = "selected", valueAttributeName = "path", propertyElementName = "selected-state")
-  var selectedNodes by property(TreeSet<State>())
+  var selectedNodes by treeSet<State>()
 
   fun expandNode(node: InspectionConfigTreeNode) {
     expandedNodes.add(getState(node))
index a1dcf85a001464133d24b60e746aec3fe0788c99..ba543ac2fce420d3251b681275e257745c1f6a01 100644 (file)
@@ -8,6 +8,9 @@ import com.intellij.openapi.components.StoredPropertyBase
 import com.intellij.util.SmartList
 import kotlin.reflect.KProperty
 
+// Technically, it is not possible to proxy write operations because collection/map can be mutated via iterator.
+// So, even if Kotlin can create delegator for us, still, to track mutations via iterator we have to reimplement collection/map.
+
 /**
  * AbstractCollectionBinding modifies collection directly, so, we cannot use null as default null and return empty list on get.
  */
index f0b01c77f55cce2b84a3ed0ab583c8a4405ad0af..3129fdf7d76b4b6ca3b121f73c9ed0c51cdcdba1 100644 (file)
@@ -9,9 +9,12 @@ import com.intellij.util.xmlb.PropertyAccessor
 import com.intellij.util.xmlb.SerializationFilter
 import com.intellij.util.xmlb.annotations.Transient
 import gnu.trove.THashMap
+import gnu.trove.THashSet
 import org.jetbrains.annotations.ApiStatus
 import java.nio.charset.Charset
+import java.util.*
 import java.util.concurrent.atomic.AtomicLongFieldUpdater
+import kotlin.collections.ArrayList
 
 private val LOG = logger<BaseState>()
 
@@ -65,8 +68,18 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
    * Collection considered as default if empty. It is *your* responsibility to call `incrementModificationCount` on collection modification.
    * You cannot set value to a new collection - on set current collection is cleared and new collection is added to current.
    */
-  protected fun <E, C : MutableCollection<E>> property(initialValue: C): StoredPropertyBase<C> {
-    val result = CollectionStoredProperty(initialValue)
+  protected fun stringSet(): StoredPropertyBase<MutableSet<String>> {
+    val result = CollectionStoredProperty<String, MutableSet<String>>(THashSet())
+    addProperty(result)
+    return result
+  }
+
+  /**
+   * Collection considered as default if empty. It is *your* responsibility to call `incrementModificationCount` on collection modification.
+   * You cannot set value to a new collection - on set current collection is cleared and new collection is added to current.
+   */
+  protected fun <E> treeSet(): StoredPropertyBase<MutableSet<E>> where E : Comparable<E>, E : BaseState {
+    val result = CollectionStoredProperty<E, MutableSet<E>>(TreeSet())
     addProperty(result)
     return result
   }
@@ -187,6 +200,12 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
 
   fun isEqualToDefault(): Boolean = properties.all { it.isEqualToDefault() }
 
+  /**
+   * If you use [set], [treeSet] or [map], you must ensure that [incrementModificationCount] is called for each mutation operation on corresponding property value (e.g. add, remove).
+   * Setting property to a new value updates modification count, but direct modification of mutable collection or map doesn't.
+   *
+   * The only exclusion - [list].
+   */
   @Transient
   override fun getModificationCount(): Long {
     var result = ownModificationCount
index 63b321cb313a6f7ca4636a2220e0380b7c2bc15e..601f37371216dc7f54e02411ad205415883f2ccd 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.xdebugger.impl.breakpoints
 
 import com.intellij.ide.util.treeView.TreeState
@@ -6,13 +6,13 @@ import com.intellij.openapi.components.BaseState
 import com.intellij.util.xmlb.annotations.Tag
 import com.intellij.util.xmlb.annotations.Transient
 import com.intellij.util.xmlb.annotations.XCollection
-import gnu.trove.THashSet
 
 @Tag("breakpoints-dialog")
 class XBreakpointsDialogState : BaseState() {
   @get:XCollection(propertyElementName = "selected-grouping-rules", elementName = "grouping-rule", valueAttributeName = "id")
-  var selectedGroupingRules by property(THashSet<String>())
+  var selectedGroupingRules by stringSet()
 
-  @get:Transient // Not saved for now
+  // not saved for now
+  @get:Transient
   var treeState: TreeState? = null
 }