reduce SchemeManagerImpl complexity — extract addNewScheme

This commit is contained in:
Vladimir Krivosheev
2017-10-11 13:30:34 +02:00
parent 5d5a09ad40
commit 41dd07dca5
3 changed files with 59 additions and 52 deletions
@@ -24,7 +24,6 @@ import com.intellij.openapi.components.impl.stores.FileStorageCoreUtil
import com.intellij.openapi.components.impl.stores.FileStorageCoreUtil.DEFAULT_EXT
import com.intellij.openapi.diagnostic.runAndLogException
import com.intellij.openapi.extensions.AbstractExtensionPointBean
import com.intellij.openapi.options.ExternalizableScheme
import com.intellij.openapi.options.NonLazySchemeProcessor
import com.intellij.openapi.options.SchemeProcessor
import com.intellij.openapi.options.SchemeState
@@ -61,7 +60,7 @@ import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import java.util.function.Function
class SchemeManagerImpl<T : Any, in MUTABLE_SCHEME : T>(val fileSpec: String,
class SchemeManagerImpl<T : Any, MUTABLE_SCHEME : T>(val fileSpec: String,
processor: SchemeProcessor<T, MUTABLE_SCHEME>,
private val provider: StreamProvider?,
private val ioDirectory: Path,
@@ -83,7 +82,7 @@ class SchemeManagerImpl<T : Any, in MUTABLE_SCHEME : T>(val fileSpec: String,
private val schemeExtension: String
private val updateExtension: Boolean
private val filesToDelete = ContainerUtil.newConcurrentSet<String>()
internal val filesToDelete = ContainerUtil.newConcurrentSet<String>()
// scheme could be changed - so, hashcode will be changed - we must use identity hashing strategy
internal val schemeToInfo = ConcurrentCollectionFactory.createMap<T, ExternalInfo>(ContainerUtil.identityStrategy())
@@ -841,54 +840,7 @@ class SchemeManagerImpl<T : Any, in MUTABLE_SCHEME : T>(val fileSpec: String,
}
}
override fun addNewScheme(scheme: T, replaceExisting: Boolean) {
var toReplace = -1
val schemes = schemes
for ((index, existing) in schemes.withIndex()) {
if (processor.getSchemeKey(existing) != processor.getSchemeKey(scheme)) {
continue
}
toReplace = index
if (existing === scheme) {
// do not just return, below scheme will be removed from filesToDelete list
break
}
if (existing.javaClass != scheme.javaClass) {
LOG.warn("'${processor.getSchemeKey(scheme)}' ${existing.javaClass.simpleName} replaced with ${scheme.javaClass.simpleName}")
}
if (replaceExisting && processor.isExternalizable(existing)) {
val oldInfo = schemeToInfo.remove(existing)
if (oldInfo != null && processor.isExternalizable(scheme) && !schemeToInfo.containsKey(scheme)) {
schemeToInfo.put(scheme, oldInfo)
}
}
}
when {
toReplace == -1 -> schemes.add(scheme)
(replaceExisting || !processor.isExternalizable(scheme)) -> {
if (schemes.get(toReplace) !== scheme) {
// avoid "set" (LockFreeCopyOnWriteArrayList calls ARRAY_UPDATER.compareAndSet and so on)
schemes.set(toReplace, scheme)
}
}
else -> {
(scheme as ExternalizableScheme).renameScheme(UniqueNameGenerator.generateUniqueName(scheme.name, schemeListManager.collectExistingNames(schemes)))
schemes.add(scheme)
}
}
if (processor.isExternalizable(scheme) && filesToDelete.isNotEmpty()) {
schemeToInfo.get(scheme)?.let {
filesToDelete.remove(it.fileName)
}
}
processPendingCurrentSchemeName(scheme)
}
override fun addNewScheme(scheme: T, replaceExisting: Boolean) = schemeListManager.addScheme(scheme, replaceExisting)
override fun findSchemeByName(schemeName: String) = schemes.firstOrNull { processor.getSchemeKey(it) == schemeName }
@@ -1,10 +1,13 @@
package com.intellij.configurationStore.schemeManager
import com.intellij.configurationStore.LOG
import com.intellij.configurationStore.SchemeManagerImpl
import com.intellij.openapi.options.ExternalizableScheme
import com.intellij.openapi.util.Condition
import com.intellij.util.containers.ConcurrentList
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.filterSmart
import com.intellij.util.text.UniqueNameGenerator
import gnu.trove.THashSet
import java.util.concurrent.atomic.AtomicReference
@@ -22,6 +25,58 @@ internal class SchemeListManager<T : Any>(private val schemeManager: SchemeManag
}
}
fun addScheme(scheme: T, replaceExisting: Boolean) {
var toReplace = -1
val schemes = schemes
val processor = schemeManager.processor
val schemeToInfo = schemeManager.schemeToInfo
for ((index, existing) in schemes.withIndex()) {
if (processor.getSchemeKey(existing) != processor.getSchemeKey(scheme)) {
continue
}
toReplace = index
if (existing === scheme) {
// do not just return, below scheme will be removed from filesToDelete list
break
}
if (existing.javaClass != scheme.javaClass) {
LOG.warn("'${processor.getSchemeKey(scheme)}' ${existing.javaClass.simpleName} replaced with ${scheme.javaClass.simpleName}")
}
if (replaceExisting && processor.isExternalizable(existing)) {
val oldInfo = schemeToInfo.remove(existing)
if (oldInfo != null && processor.isExternalizable(scheme) && !schemeToInfo.containsKey(scheme)) {
schemeToInfo.put(scheme, oldInfo)
}
}
}
when {
toReplace == -1 -> schemes.add(scheme)
(replaceExisting || !processor.isExternalizable(scheme)) -> {
if (schemes.get(toReplace) !== scheme) {
// avoid "set" (LockFreeCopyOnWriteArrayList calls ARRAY_UPDATER.compareAndSet and so on)
schemes.set(toReplace, scheme)
}
}
else -> {
(scheme as ExternalizableScheme).renameScheme(
UniqueNameGenerator.generateUniqueName(scheme.name, collectExistingNames(schemes)))
schemes.add(scheme)
}
}
if (processor.isExternalizable(scheme) && schemeManager.filesToDelete.isNotEmpty()) {
schemeToInfo.get(scheme)?.let {
schemeManager.filesToDelete.remove(it.fileName)
}
}
schemeManager.processPendingCurrentSchemeName(scheme)
}
fun setSchemes(newSchemes: List<T>, newCurrentScheme: T?, removeCondition: Condition<T>?) {
if (schemes.isNotEmpty()) {
if (removeCondition == null) {
@@ -21,7 +21,7 @@ abstract class SchemeManagerBase<T : Any, in MUTABLE_SCHEME : T>(internal val pr
get() = currentScheme?.let { processor.getSchemeKey(it) } ?: currentPendingSchemeName
set(schemeName) = setCurrentSchemeName(schemeName, true)
protected fun processPendingCurrentSchemeName(newScheme: T) {
internal fun processPendingCurrentSchemeName(newScheme: T) {
if (processor.getSchemeKey(newScheme) == currentPendingSchemeName) {
setCurrent(newScheme, false)
}