From e93031907995fa28e96aedfa04025ad3cdbbddd1 Mon Sep 17 00:00:00 2001 From: Konstantin Nisht Date: Fri, 19 Sep 2025 14:30:57 +0200 Subject: [PATCH] [ab] IJPL-186222: Drop old implementation (cherry picked from commit 7278d60df00844be60eaf39efc278e2a1738ff6b) (cherry picked from commit 09aeb31397b41611a0a3021fb807fd34b99ff3ea) IJ-CR-176469 GitOrigin-RevId: 4cab7a72b9a4d6dc9c7e3c24c1fba5e71737f1bc --- .../intellij.platform.experiment.xml | 16 -- .../ab/impl/experiment/ABExperiment.kt | 159 ------------------ .../ABExperimentGroupStorageService.kt | 122 -------------- .../ab/impl/experiment/ABExperimentOption.kt | 55 ------ .../impl/experiment/ABExperimentOptionBean.kt | 17 -- .../impl/experiment/ABExperimentOptionId.kt | 5 - .../experiment/ABExperimentPluginTracker.kt | 25 --- .../ab/impl/experiment/package-info.java | 5 - .../experiment/ab/impl/experiments.kt | 14 +- .../impl/option/ABExperimentControlOption.kt | 30 ---- .../option/ABExperimentOptionGroupSize.kt | 20 --- .../ab/impl/option/package-info.java | 5 - .../ab/temporary/ShowTrialSurveyOption.kt | 27 +-- .../FuzzyFileSearchExperimentOption.kt | 29 +--- ...tellij.platform.ide.newUsersOnboarding.xml | 2 - .../NewUsersOnboardingExperiment.kt | 4 +- .../NewUsersOnboardingExperimentOption.kt | 25 --- 17 files changed, 14 insertions(+), 546 deletions(-) delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperiment.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentGroupStorageService.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOption.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionBean.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionId.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentPluginTracker.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/package-info.java delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentControlOption.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentOptionGroupSize.kt delete mode 100644 platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/package-info.java delete mode 100644 platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperimentOption.kt diff --git a/platform/experiment/resources/intellij.platform.experiment.xml b/platform/experiment/resources/intellij.platform.experiment.xml index 4c97bac3d591..7f97e68fee6e 100644 --- a/platform/experiment/resources/intellij.platform.experiment.xml +++ b/platform/experiment/resources/intellij.platform.experiment.xml @@ -1,25 +1,9 @@ - - - - - - - - - - - - diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperiment.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperiment.kt deleted file mode 100644 index d1af03ae63be..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperiment.kt +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.experiment - -import com.intellij.internal.statistic.eventLog.fus.MachineIdManager -import com.intellij.internal.statistic.utils.getPluginInfoByDescriptor -import com.intellij.openapi.application.ApplicationInfo.getInstance -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.components.service -import com.intellij.openapi.diagnostic.debug -import com.intellij.openapi.diagnostic.logger -import com.intellij.openapi.diagnostic.runAndLogException -import com.intellij.openapi.extensions.ExtensionPointName -import com.intellij.platform.experiment.ab.impl.option.ABExperimentControlOption -import com.intellij.platform.experiment.ab.impl.statistic.ABExperimentCountCollector -import com.intellij.util.MathUtil -import com.intellij.util.PlatformUtils - -fun getABExperimentInstance(): ABExperiment { - return ABExperiment.getABExperimentInstance() -} - -/** - * This is a multi-optional A/B experiment for all IDEs and JetBrains plugins, - * which affects IDE metrics like user retention in the IDE. - * - * Each feature is represented as an option. - * An option defines the number of user groups which will be associated with this option. - * There is a control option for default behavior. - * You need to implement `ABExperimentOption` extension point to implement an option for your feature. - * - * The number of A/B experimental groups is limited. - * It is necessary to keep a group audience enough to make statistically significant conclusions. - * So it is crucial to choose group size judiciously. - * If group capacity is exhausted for a specific IDE, there will be an error. - * In such a case, you need to communicate with related people to handle such a case and rearrange option groups accordingly. - * - * A/B experiment supports the implemented options from JetBrains plugins. - * Plugins can be installed/uninstalled or enabled/disabled. - * Accordingly, the options defined in plugins may appear when the plugin is enabled or installed, - * or disappear when the plugin is disabled or uninstalled. - * The experiment uses special storage to be able to work with such conditions correctly. - * - * @see ABExperimentControlOption - * @see ABExperimentGroupStorageService - */ -interface ABExperiment { - companion object { - fun getABExperimentInstance(): ABExperiment { - val application = ApplicationManager.getApplication() ?: return DummyABExperiment - return application.service() - } - } - - fun isControlExperimentOptionEnabled() : Boolean - - fun isExperimentOptionEnabled(experimentOptionClass: Class): Boolean -} - -internal object DummyABExperiment : ABExperiment { - // is never a control group - override fun isControlExperimentOptionEnabled(): Boolean = false - - // always turned on - override fun isExperimentOptionEnabled(experimentOptionClass: Class): Boolean = true -} - -private val AB_EXPERIMENTAL_OPTION_EP: ExtensionPointName = - ExtensionPointName("com.intellij.experiment.abExperimentOption") - -private val LOG = logger() - -private fun getDeviceIdPurpose(): String { - return "A/B Experiment" + getInstance().shortVersion -} - -private const val TOTAL_NUMBER_OF_BUCKETS = 1024 -internal const val TOTAL_NUMBER_OF_GROUPS = 256 - -internal val OPTION_ID_FREE_GROUP = ABExperimentOptionId("free.option") - -internal fun isPopularIDE(): Boolean = PlatformUtils.isIdeaUltimate() || PlatformUtils.isPyCharmPro() - -internal fun getJbABExperimentOptionList(): List { - return getJbABExperimentOptionBeanList().map { it.instance } -} - -internal fun getJbABExperimentOptionBeanList(): List { - return AB_EXPERIMENTAL_OPTION_EP.extensionList.filter { - val pluginDescriptor = it.pluginDescriptor - val pluginInfo = getPluginInfoByDescriptor(pluginDescriptor) - pluginInfo.isDevelopedByJetBrains() && it.instance.isEnabled() - } -} - -internal class ABExperimentImpl : ABExperiment { - override fun isControlExperimentOptionEnabled(): Boolean { - return isExperimentOptionEnabled(ABExperimentControlOption::class.java) - } - - override fun isExperimentOptionEnabled(experimentOptionClass: Class): Boolean { - return experimentOptionClass.isInstance(getUserExperimentOption()) - } - - internal fun getUserExperimentOption(): ABExperimentOption? { - val userOptionId = getUserExperimentOptionId() - ABExperimentCountCollector.logABExperimentOptionUsed(userOptionId, getUserGroupNumber(), getUserBucketNumber()) - return getJbABExperimentOptionList().find { it.id.value == userOptionId?.value } - } - - internal fun getUserExperimentOptionId(): ABExperimentOptionId? { - val manualOptionIdText = System.getProperty("platform.experiment.ab.manual.option", "") - if (manualOptionIdText.isNotBlank()) { - LOG.debug { "Use manual option id from Registry. Registry key value is: $manualOptionIdText" } - - val manualOption = getJbABExperimentOptionList().find { it.id.value == manualOptionIdText } - if (manualOption != null) { - LOG.debug { "Found manual option is: $manualOption" } - return manualOption.id - } - else if (manualOptionIdText == OPTION_ID_FREE_GROUP.value) { - LOG.debug { "Found manual option is: $manualOptionIdText" } - return ABExperimentOptionId(manualOptionIdText) - } - else { - LOG.debug { "Manual option with id $manualOptionIdText not found." } - return null - } - } - - val userGroupNumber = getUserGroupNumber() - val userOptionId = ABExperimentGroupStorageService.getUserExperimentOptionId(userGroupNumber) - - LOG.debug { "User option id is: ${userOptionId.value}." } - - return userOptionId - } - - private fun getUserGroupNumber(): Int { - val bucket = getUserBucketNumber() - if (TOTAL_NUMBER_OF_BUCKETS < TOTAL_NUMBER_OF_GROUPS) { - LOG.error("Number of buckets is less than number of groups. " + - "Please revise related experiment constants and adjust them accordingly.") - } - - val experimentGroup = bucket % TOTAL_NUMBER_OF_GROUPS - LOG.debug { "User group number is: $experimentGroup." } - return experimentGroup - } - - private fun getUserBucketNumber(): Int { - val deviceId = LOG.runAndLogException { - MachineIdManager.getAnonymizedMachineId(getDeviceIdPurpose()) - } - - val bucketNumber = MathUtil.nonNegativeAbs(deviceId.hashCode()) % TOTAL_NUMBER_OF_BUCKETS - LOG.debug { "User bucket number is: $bucketNumber." } - return bucketNumber - } -} diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentGroupStorageService.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentGroupStorageService.kt deleted file mode 100644 index 9b67cf266a6a..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentGroupStorageService.kt +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.experiment - -import com.intellij.ide.plugins.DynamicPluginEnabler -import com.intellij.ide.plugins.PluginStateManager -import com.intellij.openapi.components.* -import com.intellij.openapi.diagnostic.debug -import com.intellij.openapi.diagnostic.logger - -/** - * This storage is used to ensure that option groups are assigned properly. - * It maintains a map from a group's number to an assigned option id. - * It uses a special id to mark free groups. - * - * At the start, the map is initialized with available options. - * After that, for each event of plugin enabling/disabling/installing/uninstalling and after startup, - * it checks new available options and puts its id into the map. - * Ids of options that become not available are not removed from the map. - * This is to avoid mixing different options with the user and - * handle a case when a user enables and disables a plugin several times. - * - * @see com.intellij.platform.experiment.ab.impl.experiment.OPTION_ID_FREE_GROUP - */ -@Service(Service.Level.APP) -@State( - name = "ABExperimentGroupStorageService", - storages = [Storage("ABExperimentGroupStorageService.xml", roamingType = RoamingType.DISABLED)] -) -internal class ABExperimentGroupStorageService : PersistentStateComponent { - - companion object { - private val LOG = logger() - - fun getUserExperimentOptionId(userGroupNumber: Int): ABExperimentOptionId { - val experimentOptionIdText = service().state.groupNumberToExperimentOptionId[userGroupNumber]!! - return ABExperimentOptionId(experimentOptionIdText) - } - } - - private lateinit var myState: ABExperimentGroupStorage - - override fun getState(): ABExperimentGroupStorage { - return myState - } - - override fun loadState(state: ABExperimentGroupStorage) { - myState = state - } - - override fun noStateLoaded() { - myState = ABExperimentGroupStorage(getInitialGroupToOptionState()) - } - - override fun initializeComponent() { - val tracker = ABExperimentPluginTracker() - PluginStateManager.addStateListener(tracker) - DynamicPluginEnabler.addPluginStateChangedListener(tracker) - - setupNewPluginABExperimentOptions() - } - - internal fun setupNewPluginABExperimentOptions() { - val groupNumberToExperimentOptionId = myState.groupNumberToExperimentOptionId - LOG.debug { "State BEFORE update is: $groupNumberToExperimentOptionId" } - - val optionBeans = getJbABExperimentOptionBeanList() - val usedOptionIds = groupNumberToExperimentOptionId.values.toSet() - val newOptionBeans = optionBeans.filter { it.instance.id.value !in usedOptionIds } - - if (newOptionBeans.isEmpty()) { - return - } - - val isPopularIDE = isPopularIDE() - - for (newOptionBean in newOptionBeans) { - val newOption = newOptionBean.instance - val groupCount = newOption.getGroupSizeForIde(isPopularIDE).groupCount - for (i in 0 until groupCount) { - val freeGroupKey = groupNumberToExperimentOptionId.entries.find { entry -> - entry.value == OPTION_ID_FREE_GROUP.value - }?.key - - if (freeGroupKey == null) { - LOG.error("There is no available groups for option ${newOption.id} from plugin " + - newOptionBean.pluginDescriptor.pluginId.idString) - return - } - - LOG.debug { "Assign experiment option ${newOption.id} to group $freeGroupKey." } - - groupNumberToExperimentOptionId[freeGroupKey] = newOption.id.value - } - } - LOG.debug { "State AFTER update is: $groupNumberToExperimentOptionId" } - } - - private fun getInitialGroupToOptionState(): MutableMap { - val initialGroupNumberToExperimentOptionId = (0.rangeUntil(TOTAL_NUMBER_OF_GROUPS).associateWith { - OPTION_ID_FREE_GROUP.value - }).toMutableMap() - - val isPopularIDE = isPopularIDE() - val options = getJbABExperimentOptionList().sortedBy { it.id.value } - var counter = 0 - - for (option in options) { - val optionGroupsCount = option.getGroupSizeForIde(isPopularIDE).groupCount - for (groupNumber in counter.rangeUntil(counter + optionGroupsCount)) { - LOG.debug { "Assign experiment option ${option.id} to group $groupNumber." } - initialGroupNumberToExperimentOptionId[groupNumber] = option.id.value - } - counter += optionGroupsCount - } - - LOG.debug { "Initial state of group to option map is: $initialGroupNumberToExperimentOptionId" } - - return initialGroupNumberToExperimentOptionId - } -} - -internal data class ABExperimentGroupStorage(val groupNumberToExperimentOptionId: MutableMap) \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOption.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOption.kt deleted file mode 100644 index b2e33d575594..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOption.kt +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.experiment - -import com.intellij.platform.experiment.ab.impl.option.ABExperimentOptionGroupSize - -/** - * A/B Experiment option interface. - * - * Implement and register an option for your feature. - */ -interface ABExperimentOption { - val id: ABExperimentOptionId - - /** - * Returns the size of an audience group for the option. - * - * The number of A/B experimental groups is limited. - * The group size must be agreed with the analysts so that the result of the experiment is statistically significant. - * - * If group capacity is exhausted for a specific IDE, there will be an error in runtime. - * In such a case, you need to communicate with related persons with other options - * to handle such a case and rearrange option groups accordingly. - * - * @param isPopularIde true if the current IDE is popular. - * It can be used to adjust the group size of the option accordingly. - * Popular IDEs have more users, and the group size should be smaller than it is in other IDEs. - * - * @see com.intellij.platform.experiment.ab.impl.experiment.TOTAL_NUMBER_OF_GROUPS - */ - fun getGroupSizeForIde(isPopularIde: Boolean): ABExperimentOptionGroupSize - - /** - * Check if the option should be enabled in a certain IDE. - * - * Mostly useful for options in Intellij Platform to enable option only in certain IDEs. - */ - fun checkIdeIsSuitable(): Boolean - - /** - * Check if the option should be enabled in a certain IDE version. - * - * Must be agreed with analytics to do not spoil an experiment. - * - * Mostly useful for plugins that potentially can be installed to a different version of a certain IDE. - * In this case, the plugin must specify the target version so as not to spoil the experiment - * by overflowing the maximum number of user groups. - * - * For IDEs, it allows to control in what version of IDE what options are enabled. - */ - fun checkIdeVersionIsSuitable(): Boolean -} - -fun ABExperimentOption.isEnabled(): Boolean { - return checkIdeIsSuitable() && checkIdeVersionIsSuitable() -} \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionBean.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionBean.kt deleted file mode 100644 index 6f40edbdd6b8..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionBean.kt +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.experiment - -import com.intellij.openapi.extensions.RequiredElement -import com.intellij.serviceContainer.BaseKeyedLazyInstance -import com.intellij.util.xmlb.annotations.Attribute - -class ABExperimentOptionBean : BaseKeyedLazyInstance() { - @Attribute("implementation") - @JvmField - @RequiredElement - var implementationClass: String? = null - - override fun getImplementationClassName(): String? { - return implementationClass - } -} \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionId.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionId.kt deleted file mode 100644 index 2838ca4e100b..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentOptionId.kt +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.experiment - -@JvmInline -value class ABExperimentOptionId(val value: String) diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentPluginTracker.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentPluginTracker.kt deleted file mode 100644 index d6e83d6d9fc6..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/ABExperimentPluginTracker.kt +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.experiment - -import com.intellij.ide.plugins.IdeaPluginDescriptor -import com.intellij.ide.plugins.PluginEnableStateChangedListener -import com.intellij.ide.plugins.PluginStateListener -import com.intellij.openapi.components.service - -internal class ABExperimentPluginTracker : PluginStateListener, PluginEnableStateChangedListener { - override fun stateChanged(pluginDescriptors: Collection, enable: Boolean) { - if (!enable) { - return - } - - service().setupNewPluginABExperimentOptions() - } - - override fun install(descriptor: IdeaPluginDescriptor) { - service().setupNewPluginABExperimentOptions() - } - - override fun uninstall(descriptor: IdeaPluginDescriptor) { - service().setupNewPluginABExperimentOptions() - } -} \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/package-info.java b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/package-info.java deleted file mode 100644 index f3580e330d16..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiment/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -@ApiStatus.Internal -package com.intellij.platform.experiment.ab.impl.experiment; - -import org.jetbrains.annotations.ApiStatus; \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiments.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiments.kt index 8171cf02282d..d66ab7e51e83 100644 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiments.kt +++ b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/experiments.kt @@ -17,9 +17,10 @@ import kotlin.math.absoluteValue * The plugins are welcome to use [ABExperimentOption.isEnabled] to check whether the experiment is enabled on the user's machine */ enum class ABExperimentOption { - EXPERIMENT_1, - EXPERIMENT_2, - EXPERIMENT_3, + KUBERNETES_SEPARATE_SERVICE_VIEW, + FUZZY_FILE_SEARCH, + SHOW_TRIAL_SURVEY, + NEW_USERS_ONBOARDING, /** * A group for users which are not assigned to any experiment. @@ -49,10 +50,9 @@ internal const val NUMBER_OF_BUCKETS: Int = 1024 */ @VisibleForTesting internal val experimentsPartition: List = listOf( - ExperimentAssignment(experiment = EXPERIMENT_1, experimentBuckets = (0 until 180).toSet(), controlBuckets = (180 until 256).toSet()), - ExperimentAssignment(experiment = EXPERIMENT_2, experimentBuckets = (256 until 384).toSet(), controlBuckets = (384 until 512).toSet()), - ExperimentAssignment(experiment = EXPERIMENT_3, experimentBuckets = (512 until 640).toSet(), controlBuckets = (640 until 768).toSet()), - // the rest belongs to the unassigned experiment + ExperimentAssignment(experiment = KUBERNETES_SEPARATE_SERVICE_VIEW, experimentBuckets = (0 until 128).toSet(), controlBuckets = (128 until 256).toSet()), + ExperimentAssignment(experiment = FUZZY_FILE_SEARCH, experimentBuckets = (256 until 512).toSet(), controlBuckets = (512 until 768).toSet()), + // the rest belongs to the "unassigned" experiment ) /** diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentControlOption.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentControlOption.kt deleted file mode 100644 index 5d9077e43a2c..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentControlOption.kt +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.option - -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentImpl -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOption -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOptionId -import com.intellij.platform.experiment.ab.impl.experiment.getABExperimentInstance - - -fun isControlOptionEnabled(): Boolean { - val abImpl = getABExperimentInstance() as? ABExperimentImpl ?: return false - return abImpl.getUserExperimentOption() is ABExperimentControlOption -} - -internal class ABExperimentControlOption : ABExperimentOption { - - override val id: ABExperimentOptionId = ABExperimentOptionId("control.option") - - override fun getGroupSizeForIde(isPopularIde: Boolean): ABExperimentOptionGroupSize { - return ABExperimentOptionGroupSize(32) - } - - override fun checkIdeIsSuitable(): Boolean { - return true - } - - override fun checkIdeVersionIsSuitable(): Boolean { - return true - } -} \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentOptionGroupSize.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentOptionGroupSize.kt deleted file mode 100644 index 71888386cb8f..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/ABExperimentOptionGroupSize.kt +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.experiment.ab.impl.option - -/** - * Represent experiment option user group size. - * - * Must be greater than 0 and less than the total number of user groups. - * - * The group size must be agreed with the analysts so that the result of the experiment is statistically significant. - * - * @see com.intellij.platform.experiment.ab.impl.experiment.TOTAL_NUMBER_OF_GROUPS - */ -@JvmInline -value class ABExperimentOptionGroupSize(val groupCount: Int) { - init { - if (groupCount <= 0) { - error("Size of option group should be greater then 0.") - } - } -} \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/package-info.java b/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/package-info.java deleted file mode 100644 index 5a3d63c1122e..000000000000 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/impl/option/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -@ApiStatus.Internal -package com.intellij.platform.experiment.ab.impl.option; - -import org.jetbrains.annotations.ApiStatus; \ No newline at end of file diff --git a/platform/experiment/src/com/intellij/platform/experiment/ab/temporary/ShowTrialSurveyOption.kt b/platform/experiment/src/com/intellij/platform/experiment/ab/temporary/ShowTrialSurveyOption.kt index c6260c9b8fc2..695ad071afd3 100644 --- a/platform/experiment/src/com/intellij/platform/experiment/ab/temporary/ShowTrialSurveyOption.kt +++ b/platform/experiment/src/com/intellij/platform/experiment/ab/temporary/ShowTrialSurveyOption.kt @@ -1,36 +1,15 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.experiment.ab.temporary -import com.intellij.openapi.application.ApplicationInfo -import com.intellij.platform.experiment.ab.impl.experiment.ABExperiment -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOption -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOptionId -import com.intellij.platform.experiment.ab.impl.option.ABExperimentOptionGroupSize -import com.intellij.util.PlatformUtils +import com.intellij.platform.experiment.ab.impl.ABExperimentOption import org.jetbrains.annotations.ApiStatus @ApiStatus.Internal -class ShowTrialSurveyOption : ABExperimentOption { - override val id: ABExperimentOptionId = ABExperimentOptionId("showTrialSurvey") - - override fun getGroupSizeForIde(isPopularIde: Boolean): ABExperimentOptionGroupSize { - return ABExperimentOptionGroupSize(192) - } - - override fun checkIdeIsSuitable(): Boolean = PlatformUtils.isIdeaUltimate() - - /** - * Experiment should be available only in 2024.3.5 - */ - override fun checkIdeVersionIsSuitable(): Boolean { - val appInfo = ApplicationInfo.getInstance() - return appInfo.majorVersion == "2024" && appInfo.minorVersion.startsWith("3.5") - } - +class ShowTrialSurveyOption { @Suppress("CompanionObjectInExtension") companion object { @JvmStatic val isTrialSurveyEnabled: Boolean get() = System.getProperty("test.ide.trial.survey", "false").toBoolean() || - ABExperiment.getABExperimentInstance().isExperimentOptionEnabled(ShowTrialSurveyOption::class.java) + ABExperimentOption.SHOW_TRIAL_SURVEY.isEnabled() } } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FuzzyFileSearchExperimentOption.kt b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FuzzyFileSearchExperimentOption.kt index 8c17d464f596..7176b46ce52e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FuzzyFileSearchExperimentOption.kt +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FuzzyFileSearchExperimentOption.kt @@ -1,36 +1,11 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.util.gotoByName -import com.intellij.openapi.application.ApplicationInfo import com.intellij.openapi.util.registry.Registry.Companion.`is` -import com.intellij.platform.experiment.ab.impl.experiment.ABExperiment -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOption -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOptionId -import com.intellij.platform.experiment.ab.impl.option.ABExperimentOptionGroupSize +import com.intellij.platform.experiment.ab.impl.ABExperimentOption import org.jetbrains.annotations.ApiStatus @ApiStatus.Internal internal fun isFuzzyFileSearchEnabled(): Boolean { - return `is`("search.everywhere.fuzzy.file.search.ab.experiment.enabled", false) && - ABExperiment.getABExperimentInstance().isExperimentOptionEnabled(FuzzyFileSearchExperimentOption::class.java) -} - -@ApiStatus.Internal -internal class FuzzyFileSearchExperimentOption : ABExperimentOption { - override val id: ABExperimentOptionId = ABExperimentOptionId(FUZZY_FILE_SEARCH_EXPERIMENT_OPTION_ID) - - override fun getGroupSizeForIde(isPopularIde: Boolean): ABExperimentOptionGroupSize { - return ABExperimentOptionGroupSize(128) - } - - override fun checkIdeIsSuitable(): Boolean = true - - override fun checkIdeVersionIsSuitable(): Boolean { - val appInfo = ApplicationInfo.getInstance() - return appInfo.isEAP && appInfo.majorVersion == "2025" && appInfo.minorVersionMainPart == "2" - } - - companion object { - const val FUZZY_FILE_SEARCH_EXPERIMENT_OPTION_ID = "fuzzyFileSearch" - } + return `is`("search.everywhere.fuzzy.file.search.enabled", false) || ABExperimentOption.FUZZY_FILE_SEARCH.isEnabled() } \ No newline at end of file diff --git a/platform/new-users-onboarding/resources/intellij.platform.ide.newUsersOnboarding.xml b/platform/new-users-onboarding/resources/intellij.platform.ide.newUsersOnboarding.xml index d4b1a065ca78..f5a79e6ec50f 100644 --- a/platform/new-users-onboarding/resources/intellij.platform.ide.newUsersOnboarding.xml +++ b/platform/new-users-onboarding/resources/intellij.platform.ide.newUsersOnboarding.xml @@ -17,8 +17,6 @@ - - diff --git a/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperiment.kt b/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperiment.kt index 32d3d423a01d..e8a9166ef8d8 100644 --- a/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperiment.kt +++ b/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperiment.kt @@ -7,7 +7,7 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.components.serviceAsync import com.intellij.openapi.extensions.ExtensionNotApplicableException import com.intellij.openapi.util.registry.Registry -import com.intellij.platform.experiment.ab.impl.experiment.getABExperimentInstance +import com.intellij.platform.experiment.ab.impl.ABExperimentOption import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.jetbrains.annotations.ApiStatus @@ -20,7 +20,7 @@ class NewUsersOnboardingExperiment { * Since it is not changed during IDE session, better to calculate it once. */ private val isExperimentEnabled: Boolean by lazy { - getABExperimentInstance().isExperimentOptionEnabled(NewUsersOnboardingExperimentOption::class.java) + ABExperimentOption.NEW_USERS_ONBOARDING.isEnabled() } fun isEnabled(): Boolean { diff --git a/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperimentOption.kt b/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperimentOption.kt deleted file mode 100644 index 2f053dc0a156..000000000000 --- a/platform/new-users-onboarding/src/com/intellij/platform/ide/newUsersOnboarding/NewUsersOnboardingExperimentOption.kt +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.platform.ide.newUsersOnboarding - -import com.intellij.openapi.application.ApplicationInfo -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOption -import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOptionId -import com.intellij.platform.experiment.ab.impl.option.ABExperimentOptionGroupSize - -internal class NewUsersOnboardingExperimentOption : ABExperimentOption { - override val id: ABExperimentOptionId = ABExperimentOptionId("newUsersOnboarding") - - override fun getGroupSizeForIde(isPopularIde: Boolean): ABExperimentOptionGroupSize { - return ABExperimentOptionGroupSize(128) - } - - override fun checkIdeIsSuitable(): Boolean = true - - /** - * Experiment should be available only in 2024.2.1 - */ - override fun checkIdeVersionIsSuitable(): Boolean { - val appInfo = ApplicationInfo.getInstance() - return appInfo.majorVersion == "2024" && appInfo.minorVersion == "2.1" - } -} \ No newline at end of file