diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/FUSEventGroups.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/FUSEventGroups.kt index f734d82250e..0f26c4c27cf 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/FUSEventGroups.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/statistics/FUSEventGroups.kt @@ -22,7 +22,8 @@ enum class FUSEventGroups(groupIdSuffix: String, val events: Set = setOf J2K("ide.j2k"), Editor("ide.editor"), Settings("ide.settings"), - GradlePerformance("gradle.performance"); + GradlePerformance("gradle.performance"), + NewWizard("ide.new.wizard"); val GROUP_ID: String = "kotlin.$groupIdSuffix" } diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/IdeWizard.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/IdeWizard.kt index 39be9ca01a3..39705be1da8 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/IdeWizard.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/IdeWizard.kt @@ -8,6 +8,8 @@ import org.jetbrains.kotlin.tools.projectWizard.core.service.WizardService import org.jetbrains.kotlin.tools.projectWizard.core.service.ServicesManager import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin +import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin +import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin import org.jetbrains.kotlin.tools.projectWizard.wizard.service.IdeaWizardService import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -37,6 +39,8 @@ class IdeWizard( var artifactId by setting(StructurePlugin::artifactId.reference) var buildSystemType by setting(BuildSystemPlugin::type.reference) + val projectTemplate by setting(ProjectTemplatesPlugin::template.reference) + private fun > setting(reference: SettingReference) = object : ReadWriteProperty { override fun setValue(thisRef: Any?, property: KProperty<*>, value: V?) { diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/NewProjectWizardModuleBuilder.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/NewProjectWizardModuleBuilder.kt index dfbc1abd6ca..a75025b707c 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/NewProjectWizardModuleBuilder.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/NewProjectWizardModuleBuilder.kt @@ -15,6 +15,9 @@ import com.intellij.util.SystemProperties import org.jetbrains.kotlin.idea.framework.KotlinModuleSettingStep import org.jetbrains.kotlin.idea.framework.KotlinTemplatesFactory import org.jetbrains.kotlin.idea.projectWizard.NewProjectWizardService +import org.jetbrains.kotlin.idea.projectWizard.ProjectCreationStats +import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats +import org.jetbrains.kotlin.idea.projectWizard.WizardStatsService import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.tools.projectWizard.core.Failure @@ -42,6 +45,7 @@ As EmptyModuleBuilder has not expert panel option which are redundant */ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() { private val wizard = IdeWizard(Plugins.allPlugins, IdeaServices.PROJECT_INDEPENDENT, isUnitTestMode = false) + private val uiEditorUsagesStats = UiEditorUsageStats() override fun isOpenProjectSettingsAfter(): Boolean = false override fun canCreateModule(): Boolean = false @@ -69,7 +73,7 @@ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() { modulesProvider: ModulesProvider ): Array { this.wizardContext = wizardContext - return arrayOf(ModuleNewWizardSecondStep(wizard)) + return arrayOf(ModuleNewWizardSecondStep(wizard, uiEditorUsagesStats)) } override fun commit( @@ -86,6 +90,16 @@ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() { val errorMessages = errors.joinToString(separator = "\n") { it.message } Messages.showErrorDialog(project, errorMessages, "The following errors arose during project generation") }.isSuccess + if (success) { + val projectCreationStats = ProjectCreationStats( + wizard.projectTemplate!!.title, + wizard.buildSystemType!!.text + ) + WizardStatsService.logDataOnProjectGenerated( + projectCreationStats, + uiEditorUsagesStats + ) + } return when { !success -> null wizard.buildSystemType == BuildSystemType.Jps -> runWriteAction { @@ -207,8 +221,11 @@ class ModuleNewWizardFirstStep(wizard: IdeWizard) : WizardStep(wizard, Generatio ) } -class ModuleNewWizardSecondStep(wizard: IdeWizard) : WizardStep(wizard, GenerationPhase.SECOND_STEP) { - private val component = SecondStepWizardComponent(wizard) +class ModuleNewWizardSecondStep( + wizard: IdeWizard, + uiEditorUsagesStats: UiEditorUsageStats +) : WizardStep(wizard, GenerationPhase.SECOND_STEP) { + private val component = SecondStepWizardComponent(wizard, uiEditorUsagesStats) override fun getComponent(): JComponent = component.component override fun _init() { diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt index 0ca4b25293f..b36d909afb2 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt @@ -1,6 +1,7 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep import com.intellij.ui.components.JBTabbedPane +import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidators import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.configuratorSettings @@ -15,13 +16,16 @@ import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList import java.awt.BorderLayout import javax.swing.JComponent -class ModuleSettingsComponent(valuesReadingContext: ValuesReadingContext) : DynamicComponent(valuesReadingContext) { +class ModuleSettingsComponent( + valuesReadingContext: ValuesReadingContext, + uiEditorUsagesStats: UiEditorUsageStats +) : DynamicComponent(valuesReadingContext) { private val validateModuleName = StringValidators.shouldNotBeBlank("Module name") and StringValidators.shouldBeValidIdentifier("Module Name", ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES) private val moduleConfiguratorSettingsList = SettingsList(emptyList(), valuesReadingContext).asSubComponent() - private val templateComponent = TemplatesComponent(valuesReadingContext).asSubComponent() + private val templateComponent = TemplatesComponent(valuesReadingContext, uiEditorUsagesStats).asSubComponent() private val tabPanel = JBTabbedPane().apply { add("Template", templateComponent.component) diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/SecondStepWizardComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/SecondStepWizardComponent.kt index c536aeb84c2..b1e3f6f73ac 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/SecondStepWizardComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/SecondStepWizardComponent.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep +import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module @@ -11,10 +12,13 @@ import java.awt.BorderLayout import javax.swing.BorderFactory import javax.swing.JComponent -class SecondStepWizardComponent(wizard: IdeWizard) : WizardStepComponent(wizard.valuesReadingContext) { +class SecondStepWizardComponent( + wizard: IdeWizard, + uiEditorUsagesStats: UiEditorUsageStats +) : WizardStepComponent(wizard.valuesReadingContext) { private val moduleEditorSubStep = - ModulesEditorSubStep(wizard.valuesReadingContext, ::onNodeSelected).asSubComponent() - private val templatesSubStep = ModuleSettingsSubStep(wizard).asSubComponent() + ModulesEditorSubStep(wizard.valuesReadingContext, uiEditorUsagesStats, ::onNodeSelected).asSubComponent() + private val templatesSubStep = ModuleSettingsSubStep(wizard, uiEditorUsagesStats).asSubComponent() override val component = splitterFor( moduleEditorSubStep.component, @@ -29,10 +33,12 @@ class SecondStepWizardComponent(wizard: IdeWizard) : WizardStepComponent(wizard. class ModulesEditorSubStep( valuesReadingContext: ValuesReadingContext, + uiEditorUsagesStats: UiEditorUsageStats, onNodeSelected: (data: DisplayableSettingItem?) -> Unit ) : SubStep(valuesReadingContext) { private val moduleSettingComponent = ModulesEditorComponent( valuesReadingContext, + uiEditorUsagesStats, onNodeSelected ).asSubComponent() @@ -47,9 +53,12 @@ class ModulesEditorSubStep( } -class ModuleSettingsSubStep(wizard: IdeWizard) : SubStep(wizard.valuesReadingContext) { +class ModuleSettingsSubStep( + wizard: IdeWizard, + uiEditorUsagesStats: UiEditorUsageStats +) : SubStep(wizard.valuesReadingContext) { private val sourcesetSettingsComponent = SourcesetSettingsComponent(wizard.valuesReadingContext).asSubComponent() - private val moduleSettingsComponent = ModuleSettingsComponent(valuesReadingContext).asSubComponent() + private val moduleSettingsComponent = ModuleSettingsComponent(valuesReadingContext, uiEditorUsagesStats).asSubComponent() private val nothingSelectedComponent = NothingSelectedComponent().asSubComponent() private val panel = panel { diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/TemplatesComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/TemplatesComponent.kt index 2397d3e29db..855a18e8487 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/TemplatesComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/TemplatesComponent.kt @@ -8,10 +8,10 @@ import com.intellij.ui.SimpleTextAttributes import com.intellij.util.ui.StatusText import com.intellij.util.ui.UIUtil import org.jetbrains.kotlin.idea.KotlinIcons +import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module -import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Sourceset import org.jetbrains.kotlin.tools.projectWizard.templates.Template import org.jetbrains.kotlin.tools.projectWizard.templates.settings import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.* @@ -21,9 +21,13 @@ import java.awt.* import javax.swing.JComponent import javax.swing.JPanel -class TemplatesComponent(valuesReadingContext: ValuesReadingContext) : DynamicComponent(valuesReadingContext) { +class TemplatesComponent( + valuesReadingContext: ValuesReadingContext, + uiEditorUsagesStats: UiEditorUsageStats +) : DynamicComponent(valuesReadingContext) { private val chooseTemplateComponent: ChooseTemplateComponent = ChooseTemplateComponent(valuesReadingContext) { template -> + uiEditorUsagesStats.moduleTemplatesSet++ module?.template = template switchState(template) } @@ -38,6 +42,7 @@ class TemplatesComponent(valuesReadingContext: ValuesReadingContext) : DynamicCo null ) == Messages.OK ) { + uiEditorUsagesStats.moduleTemplatesRemoved++ module?.template = null switchState(null) } diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/ModulesEditorComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/ModulesEditorComponent.kt index 7105e28493e..cbca7123eec 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/ModulesEditorComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/ModulesEditorComponent.kt @@ -1,6 +1,7 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep.modulesEditor import com.intellij.ui.JBColor +import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.tools.projectWizard.core.entity.ListSettingType import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference @@ -18,6 +19,7 @@ import javax.swing.JComponent class ModulesEditorComponent( valuesReadingContext: ValuesReadingContext, + uiEditorUsagesStats: UiEditorUsageStats, oneEntrySelected: (data: DisplayableSettingItem?) -> Unit ) : SettingComponent, ListSettingType>(KotlinPlugin::modules.reference, valuesReadingContext) { private val tree: ModulesEditorTree = @@ -37,7 +39,7 @@ class ModulesEditorComponent( } ) - private val model = TargetsModel(tree, ::value, valuesReadingContext.context) + private val model = TargetsModel(tree, ::value, valuesReadingContext.context, uiEditorUsagesStats) override fun onInit() { super.onInit() diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/TargetsModel.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/TargetsModel.kt index f3c8adf3e3c..c679675c474 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/TargetsModel.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/modulesEditor/TargetsModel.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep.modulesEditor +import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind @@ -11,7 +12,8 @@ import kotlin.reflect.KMutableProperty0 class TargetsModel( private val tree: ModulesEditorTree, private val value: KMutableProperty0?>, - private val context: Context + private val context: Context, + private val uiEditorUsagesStats: UiEditorUsageStats ) { private val root get() = tree.model.root as DefaultMutableTreeNode @@ -61,6 +63,7 @@ class TargetsModel( } fun add(module: Module) { + uiEditorUsagesStats.modulesCreated++ module.initDefaultValuesForSettings(context) addToTheTree(module, modifyValue = true, parent = tree.selectedNode ?: root) } @@ -75,6 +78,7 @@ class TargetsModel( fun removeSelected() { val selectedNode = tree.selectedNode?.takeIf { it.userObject is Module } ?: return + uiEditorUsagesStats.modulesRemoved++ when (val parent = selectedNode.parent.safeAs()?.userObject) { ModulesEditorTree.PROJECT_USER_OBJECT -> { val index = selectedNode.parent.getIndex(selectedNode) diff --git a/idea/resources/META-INF/plugin.xml b/idea/resources/META-INF/plugin.xml index 7b7c1e8f9ed..ad77898df68 100644 --- a/idea/resources/META-INF/plugin.xml +++ b/idea/resources/META-INF/plugin.xml @@ -79,6 +79,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. + diff --git a/idea/resources/META-INF/plugin.xml.191 b/idea/resources/META-INF/plugin.xml.191 index c521ecea85e..887134806f2 100644 --- a/idea/resources/META-INF/plugin.xml.191 +++ b/idea/resources/META-INF/plugin.xml.191 @@ -79,6 +79,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. + diff --git a/idea/resources/META-INF/plugin.xml.192 b/idea/resources/META-INF/plugin.xml.192 index ced1dbdda60..0c0aecba01f 100644 --- a/idea/resources/META-INF/plugin.xml.192 +++ b/idea/resources/META-INF/plugin.xml.192 @@ -79,6 +79,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. + diff --git a/idea/src/org/jetbrains/kotlin/idea/projectWizard/NewProjectWizardService.kt b/idea/src/org/jetbrains/kotlin/idea/projectWizard/NewProjectWizardService.kt index 51aa092915d..ddef65730bf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/projectWizard/NewProjectWizardService.kt +++ b/idea/src/org/jetbrains/kotlin/idea/projectWizard/NewProjectWizardService.kt @@ -14,6 +14,9 @@ object NewProjectWizardService { var isEnabled get() = PropertiesComponent.getInstance().getBoolean(optionName, enabledByDefault) set(value) { + if (value != isEnabled) { + WizardStatsService.logWizardStatusChanged(isEnabled = value) + } PropertiesComponent.getInstance().setValue(optionName, value, enabledByDefault) } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/projectWizard/WizardStatsService.kt b/idea/src/org/jetbrains/kotlin/idea/projectWizard/WizardStatsService.kt new file mode 100644 index 00000000000..163b42721d6 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/projectWizard/WizardStatsService.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.projectWizard + +import org.jetbrains.kotlin.idea.statistics.FUSEventGroups +import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger + +interface WizardStats { + fun toMap(): Map +} + +data class ProjectCreationStats( + val projectTemplateName: String, + val buildSystemType: String +) : WizardStats { + override fun toMap(): Map = mapOf( + ::projectTemplateName.name to projectTemplateName, + ::buildSystemType.name to buildSystemType + ) +} + +data class UiEditorUsageStats( + var modulesCreated: Int = 0, + var modulesRemoved: Int = 0, + var moduleTemplatesRemoved: Int = 0, + var moduleTemplatesSet: Int = 0 +) : WizardStats { + override fun toMap(): Map = mapOf( + ::modulesCreated.name to modulesCreated.toString(), + ::modulesRemoved.name to modulesRemoved.toString(), + ::moduleTemplatesRemoved.name to moduleTemplatesRemoved.toString(), + ::moduleTemplatesSet.name to moduleTemplatesSet.toString() + ) +} + +private enum class WizardStatsEvent(val text: String) { + PROJECT_CREATED("Project Created"), + WIZARD_STATE_CHANGE("New Wizard enabled or disable") +} + +object WizardStatsService { + fun logDataOnProjectGenerated(projectCreationStats: ProjectCreationStats, uiEditorUsageStats: UiEditorUsageStats) { + val data = projectCreationStats.toMap() + uiEditorUsageStats.toMap() + KotlinFUSLogger.log(FUSEventGroups.NewWizard, WizardStatsEvent.PROJECT_CREATED.text, data) + } + + fun logWizardStatusChanged(isEnabled: Boolean) { + val data = mapOf("enabled" to isEnabled.toString()) + KotlinFUSLogger.log(FUSEventGroups.NewWizard, WizardStatsEvent.WIZARD_STATE_CHANGE.text, data) + } +} \ No newline at end of file