[JPS] Fix incremental build after changing Java enum used in Kotlin when

EnumWhenTracker implemented for tracking changed java enum class items, that used in kotlin when expression.

#KT-47824 Fixed
diff --git a/build-common/src/org/jetbrains/kotlin/incremental/EnumWhenTrackerImpl.kt b/build-common/src/org/jetbrains/kotlin/incremental/EnumWhenTrackerImpl.kt
new file mode 100644
index 0000000..ea912c7
--- /dev/null
+++ b/build-common/src/org/jetbrains/kotlin/incremental/EnumWhenTrackerImpl.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010-2021 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.incremental
+
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
+
+@Suppress("unused")
+class EnumWhenTrackerImpl: EnumWhenTracker {
+    private val pathWhenToEnumClass = hashMapOf<String, MutableSet<String>>()
+
+    val pathWhenToEnumClassMap: Map<String, Collection<String>>
+        get() = pathWhenToEnumClass
+
+    override fun report(whenUsageClassPath: String, enumClassFqName: String) {
+        pathWhenToEnumClass.getOrPut(whenUsageClassPath) { hashSetOf() }.add(enumClassFqName)
+    }
+}
\ No newline at end of file
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt
index f5cf22c..e0461a3 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt
@@ -39,6 +39,7 @@
 import org.jetbrains.kotlin.cli.jvm.config.ClassicFrontendSpecificJvmConfigurationKeys
 import org.jetbrains.kotlin.codegen.CompilationException
 import org.jetbrains.kotlin.config.*
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
@@ -247,6 +248,8 @@
 
                 putIfNotNull(CommonConfigurationKeys.INLINE_CONST_TRACKER, services[InlineConstTracker::class.java])
 
+                putIfNotNull(CommonConfigurationKeys.ENUM_WHEN_TRACKER, services[EnumWhenTracker::class.java])
+
                 putIfNotNull(
                     JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS,
                     services[IncrementalCompilationComponents::class.java]
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt
index 1d48ab8..017824b 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt
@@ -43,6 +43,7 @@
 import org.jetbrains.kotlin.frontend.java.di.createContainerForLazyResolveWithJava
 import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
 import org.jetbrains.kotlin.frontend.java.di.initialize
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
@@ -162,6 +163,7 @@
         val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: LookupTracker.DO_NOTHING
         val expectActualTracker = configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER) ?: ExpectActualTracker.DoNothing
         val inlineConstTracker = configuration.get(CommonConfigurationKeys.INLINE_CONST_TRACKER) ?: InlineConstTracker.DoNothing
+        val enumWhenTracker = configuration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER) ?: EnumWhenTracker.DoNothing
         val targetIds = configuration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId)
 
         val separateModules = !configuration.getBoolean(JVMConfigurationKeys.USE_SINGLE_MODULE)
@@ -196,7 +198,7 @@
             val dependenciesContainer = createContainerForLazyResolveWithJava(
                 jvmPlatform,
                 dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, moduleClassResolver,
-                targetEnvironment, lookupTracker, expectActualTracker, inlineConstTracker,
+                targetEnvironment, lookupTracker, expectActualTracker, inlineConstTracker, enumWhenTracker,
                 packagePartProvider(dependencyScope), languageVersionSettings,
                 useBuiltInsProvider = true,
                 configureJavaClassFinder = configureJavaClassFinder,
@@ -231,7 +233,7 @@
         val container = createContainerForLazyResolveWithJava(
             jvmPlatform,
             moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, moduleClassResolver,
-            targetEnvironment, lookupTracker, expectActualTracker, inlineConstTracker,
+            targetEnvironment, lookupTracker, expectActualTracker, inlineConstTracker, enumWhenTracker,
             partProvider, languageVersionSettings,
             useBuiltInsProvider = true,
             configureJavaClassFinder = configureJavaClassFinder,
diff --git a/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt b/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt
index f724cce..27e52ae 100644
--- a/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt
+++ b/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt
@@ -16,6 +16,7 @@
 
 package org.jetbrains.kotlin.config
 
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
@@ -44,6 +45,9 @@
     val INLINE_CONST_TRACKER = CompilerConfigurationKey.create<InlineConstTracker>("inline constant tracker")
 
     @JvmField
+    val ENUM_WHEN_TRACKER = CompilerConfigurationKey.create<EnumWhenTracker>("enum when tracker")
+
+    @JvmField
     val METADATA_VERSION = CompilerConfigurationKey.create<BinaryVersion>("metadata version")
 
     @JvmField
diff --git a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt
index 1cdc60d..16ed590 100644
--- a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt
+++ b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt
@@ -17,10 +17,7 @@
 package org.jetbrains.kotlin.daemon.client
 
 import org.jetbrains.kotlin.daemon.common.*
-import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
-import org.jetbrains.kotlin.incremental.components.InlineConstTracker
-import org.jetbrains.kotlin.incremental.components.LookupInfo
-import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.incremental.components.*
 import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
 import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
 import org.jetbrains.kotlin.incremental.js.JsInlineFunctionHash
@@ -38,6 +35,7 @@
     val compilationCanceledStatus: CompilationCanceledStatus? = null,
     val expectActualTracker: ExpectActualTracker? = null,
     val inlineConstTracker: InlineConstTracker? = null,
+    val enumWhenTracker: EnumWhenTracker? = null,
     val incrementalResultsConsumer: IncrementalResultsConsumer? = null,
     val incrementalDataProvider: IncrementalDataProvider? = null,
     port: Int = SOCKET_ANY_FREE_PORT
@@ -57,6 +55,8 @@
 
     override fun hasInlineConstTracker(): Boolean = inlineConstTracker != null
 
+    override fun hasEnumWhenTracker(): Boolean = enumWhenTracker != null
+
     override fun hasIncrementalResultsConsumer(): Boolean = incrementalResultsConsumer != null
 
     override fun hasIncrementalDataProvider(): Boolean = incrementalDataProvider != null
@@ -124,6 +124,10 @@
         inlineConstTracker?.report(filePath, owner, name, constType) ?: throw NullPointerException("inlineConstTracker was not initialized")
     }
 
+    override fun enumWhenTracker_report(whenUsageClassPath: String, enumClassFqName: String) {
+        enumWhenTracker?.report(whenUsageClassPath, enumClassFqName) ?: throw NullPointerException("enumWhenTracker was not initialized")
+    }
+
     override fun incrementalResultsConsumer_processHeader(headerMetadata: ByteArray) {
         incrementalResultsConsumer!!.processHeader(headerMetadata)
     }
diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt
index 647f008..bae65e7 100644
--- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt
+++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt
@@ -52,6 +52,9 @@
     fun hasInlineConstTracker(): Boolean
 
     @Throws(RemoteException::class)
+    fun hasEnumWhenTracker(): Boolean
+
+    @Throws(RemoteException::class)
     fun hasIncrementalResultsConsumer(): Boolean
 
     @Throws(RemoteException::class)
@@ -110,6 +113,11 @@
     fun inlineConstTracker_report(filePath: String, owner: String, name: String, constType: String)
 
     // ---------------------------------------------------
+    // EnumWhenTracker
+    @Throws(RemoteException::class)
+    fun enumWhenTracker_report(whenUsageClassPath: String, enumClassFqName: String)
+
+    // ---------------------------------------------------
     // IncrementalResultsConsumer (js)
     @Throws(RemoteException::class)
     fun incrementalResultsConsumer_processHeader(headerMetadata: ByteArray)
diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt
index e0c0611..6d018d7 100644
--- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt
+++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt
@@ -46,6 +46,7 @@
 import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapter
 import org.jetbrains.kotlin.daemon.report.getBuildReporter
 import org.jetbrains.kotlin.incremental.*
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
@@ -886,6 +887,9 @@
         if (facade.hasInlineConstTracker()) {
             builder.register(InlineConstTracker::class.java, RemoteInlineConstTracker(facade, rpcProfiler))
         }
+        if (facade.hasEnumWhenTracker()) {
+            builder.register(EnumWhenTracker::class.java, RemoteEnumWhenTracker(facade, rpcProfiler))
+        }
         if (facade.hasIncrementalResultsConsumer()) {
             builder.register(IncrementalResultsConsumer::class.java, RemoteIncrementalResultsConsumer(facade, eventManager, rpcProfiler))
         }
diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteEnumWhenTracker.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteEnumWhenTracker.kt
new file mode 100644
index 0000000..7efd8ba
--- /dev/null
+++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteEnumWhenTracker.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2010-2021 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.daemon
+
+import org.jetbrains.kotlin.daemon.common.DummyProfiler
+import org.jetbrains.kotlin.daemon.common.Profiler
+import org.jetbrains.kotlin.daemon.common.withMeasure
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
+
+class RemoteEnumWhenTracker(
+    @Suppress("DEPRECATION") val facade: org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade,
+    val profiler: Profiler = DummyProfiler()
+): EnumWhenTracker {
+    override fun report(whenUsageClassPath: String, enumClassFqName: String) {
+        profiler.withMeasure(this) {
+            facade.enumWhenTracker_report(whenUsageClassPath, enumClassFqName)
+        }
+    }
+}
\ No newline at end of file
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt
index b9d3344..ea0ff5a 100644
--- a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt
@@ -28,6 +28,7 @@
 import org.jetbrains.kotlin.frontend.di.configureIncrementalCompilation
 import org.jetbrains.kotlin.frontend.di.configureModule
 import org.jetbrains.kotlin.frontend.di.configureStandardResolveComponents
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -63,6 +64,7 @@
     lookupTracker: LookupTracker,
     expectActualTracker: ExpectActualTracker,
     inlineConstTracker: InlineConstTracker,
+    enumWhenTracker: EnumWhenTracker,
     packagePartProvider: PackagePartProvider,
     languageVersionSettings: LanguageVersionSettings,
     useBuiltInsProvider: Boolean,
@@ -76,7 +78,7 @@
         sealedInheritorsProvider
     )
 
-    configureIncrementalCompilation(lookupTracker, expectActualTracker, inlineConstTracker)
+    configureIncrementalCompilation(lookupTracker, expectActualTracker, inlineConstTracker, enumWhenTracker)
     configureStandardResolveComponents()
 
     useInstance(moduleContentScope)
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmResolverForModuleFactory.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmResolverForModuleFactory.kt
index bc8a107..7d0a695 100644
--- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmResolverForModuleFactory.kt
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmResolverForModuleFactory.kt
@@ -25,6 +25,7 @@
 import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
 import org.jetbrains.kotlin.frontend.java.di.createContainerForLazyResolveWithJava
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -114,6 +115,7 @@
             lookupTracker,
             ExpectActualTracker.DoNothing,
             InlineConstTracker.DoNothing,
+            EnumWhenTracker.DoNothing,
             packagePartProvider,
             languageVersionSettings,
             sealedInheritorsProvider = sealedInheritorsProvider,
diff --git a/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt b/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt
index faa6cce..d25e006 100644
--- a/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt
+++ b/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt
@@ -34,6 +34,7 @@
 import org.jetbrains.kotlin.diagnostics.Errors.*
 import org.jetbrains.kotlin.diagnostics.WhenMissingCase
 import org.jetbrains.kotlin.idea.MainFunctionDetector
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.lexer.KtTokens
 import org.jetbrains.kotlin.psi.*
 import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
@@ -49,6 +50,7 @@
 import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
 import org.jetbrains.kotlin.resolve.calls.util.*
 import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
 import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
 import org.jetbrains.kotlin.resolve.descriptorUtil.module
 import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
@@ -64,7 +66,8 @@
     private val trace: BindingTrace,
     private val pseudocode: Pseudocode,
     private val languageVersionSettings: LanguageVersionSettings,
-    private val diagnosticSuppressor: PlatformDiagnosticSuppressor
+    private val diagnosticSuppressor: PlatformDiagnosticSuppressor,
+    private val enumWhenTracker: EnumWhenTracker
 ) : ControlFlowInformationProvider {
     private val pseudocodeVariablesData by lazy {
         PseudocodeVariablesData(pseudocode, trace.bindingContext)
@@ -74,13 +77,15 @@
         declaration: KtElement,
         trace: BindingTrace,
         languageVersionSettings: LanguageVersionSettings,
-        diagnosticSuppressor: PlatformDiagnosticSuppressor
+        diagnosticSuppressor: PlatformDiagnosticSuppressor,
+        enumWhenTracker: EnumWhenTracker
     ) : this(
         declaration,
         trace,
         ControlFlowProcessor(trace, languageVersionSettings).generatePseudocode(declaration),
         languageVersionSettings,
-        diagnosticSuppressor
+        diagnosticSuppressor,
+        enumWhenTracker
     )
 
     override fun checkForLocalClassOrObjectMode() {
@@ -231,7 +236,7 @@
                 val expectedType = functionDescriptor?.returnType
 
                 val providerForLocalDeclaration = ControlFlowInformationProviderImpl(
-                    element, trace, localDeclarationInstruction.body, languageVersionSettings, diagnosticSuppressor
+                    element, trace, localDeclarationInstruction.body, languageVersionSettings, diagnosticSuppressor, enumWhenTracker
                 )
 
                 providerForLocalDeclaration.checkFunction(expectedType)
@@ -1030,6 +1035,9 @@
                         }
                         continue
                     }
+
+                    reportEnumWhenUsage(subjectType, subjectExpression, elseEntry)
+
                     if (!usedAsExpression) {
                         if (languageVersionSettings.supportsFeature(LanguageFeature.WarnAboutNonExhaustiveWhenOnAlgebraicTypes)) {
                             // report warnings on all non-exhaustive when's with algebraic subject
@@ -1056,6 +1064,23 @@
         }
     }
 
+    private fun reportEnumWhenUsage(subjectType: KotlinType?, subjectExpression: KtExpression, elseEntry: KtWhenEntry?) {
+        if (elseEntry != null) return
+        if (subjectExpression !is KtNameReferenceExpression) return
+
+        val declarationDescriptor = subjectType?.constructor?.declarationDescriptor ?: return
+        val containingPackage = declarationDescriptor.containingPackage()?.toString() ?: return
+        val fqName = declarationDescriptor.fqNameSafe.asString()
+        val filePath = subjectExpression.containingKtFile.virtualFilePath
+        val owner = if (fqName.startsWith("$containingPackage.")) {
+            containingPackage + "." + fqName.substring(containingPackage.length + 1).replace(".", "$")
+        } else {
+            fqName.replace(".", "$")
+        }
+
+        enumWhenTracker.report(filePath, owner)
+    }
+
     private fun checkWhenStatement(
         subjectType: KotlinType?,
         element: KtWhenExpression,
@@ -1290,9 +1315,10 @@
             declaration: KtElement,
             trace: BindingTrace,
             languageVersionSettings: LanguageVersionSettings,
-            diagnosticSuppressor: PlatformDiagnosticSuppressor
+            diagnosticSuppressor: PlatformDiagnosticSuppressor,
+            enumWhenTracker: EnumWhenTracker
         ): ControlFlowInformationProvider =
-            ControlFlowInformationProviderImpl(declaration, trace, languageVersionSettings, diagnosticSuppressor)
+            ControlFlowInformationProviderImpl(declaration, trace, languageVersionSettings, diagnosticSuppressor, enumWhenTracker)
     }
 
     companion object {
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt
index 69b753c..00a5b29 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt
@@ -6,6 +6,7 @@
 package org.jetbrains.kotlin.cfg
 
 import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.psi.KtElement
 import org.jetbrains.kotlin.resolve.BindingTrace
 import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
@@ -24,6 +25,7 @@
             trace: BindingTrace,
             languageVersionSettings: LanguageVersionSettings,
             diagnosticSuppressor: PlatformDiagnosticSuppressor,
+            enumWhenTracker: EnumWhenTracker
         ): ControlFlowInformationProvider
     }
 }
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt
index d9df642..322ac12 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt
@@ -26,6 +26,7 @@
 import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
 import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
 import org.jetbrains.kotlin.idea.MainFunctionDetector
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -127,10 +128,16 @@
     useImpl<AnnotationResolverImpl>()
 }
 
-fun StorageComponentContainer.configureIncrementalCompilation(lookupTracker: LookupTracker, expectActualTracker: ExpectActualTracker, inlineConstTracker: InlineConstTracker) {
+fun StorageComponentContainer.configureIncrementalCompilation(
+    lookupTracker: LookupTracker,
+    expectActualTracker: ExpectActualTracker,
+    inlineConstTracker: InlineConstTracker,
+    enumWhenTracker: EnumWhenTracker
+) {
     useInstance(lookupTracker)
     useInstance(expectActualTracker)
     useInstance(inlineConstTracker)
+    useInstance(enumWhenTracker)
 }
 
 fun createContainerForBodyResolve(
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java
index 9652a7c..b23e287 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java
@@ -24,6 +24,7 @@
 import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor;
 import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
 import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker;
 import org.jetbrains.kotlin.psi.*;
 import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor;
 import org.jetbrains.kotlin.types.KotlinType;
@@ -38,19 +39,22 @@
     private final LanguageVersionSettings languageVersionSettings;
     private final PlatformDiagnosticSuppressor diagnosticSuppressor;
     private final ControlFlowInformationProvider.Factory controlFlowInformationProviderFactory;
+    private final EnumWhenTracker enumWhenTracker;
 
     public ControlFlowAnalyzer(
             @NotNull BindingTrace trace,
             @NotNull KotlinBuiltIns builtIns,
             @NotNull LanguageVersionSettings languageVersionSettings,
             @NotNull PlatformDiagnosticSuppressor diagnosticSuppressor,
-            @NotNull ControlFlowInformationProvider.Factory controlFlowInformationProviderFactory
+            @NotNull ControlFlowInformationProvider.Factory controlFlowInformationProviderFactory,
+            @NotNull EnumWhenTracker enumWhenTracker
     ) {
         this.trace = trace;
         this.builtIns = builtIns;
         this.languageVersionSettings = languageVersionSettings;
         this.diagnosticSuppressor = diagnosticSuppressor;
         this.controlFlowInformationProviderFactory = controlFlowInformationProviderFactory;
+        this.enumWhenTracker = enumWhenTracker;
     }
 
     public void process(@NotNull BodiesResolveContext c) {
@@ -84,7 +88,7 @@
     private void checkSecondaryConstructor(@NotNull KtSecondaryConstructor constructor) {
         ControlFlowInformationProvider controlFlowInformationProvider =
                 controlFlowInformationProviderFactory.createControlFlowInformationProvider(
-                        constructor, trace, languageVersionSettings, diagnosticSuppressor
+                        constructor, trace, languageVersionSettings, diagnosticSuppressor, enumWhenTracker
                 );
         controlFlowInformationProvider.checkDeclaration();
         controlFlowInformationProvider.checkFunction(builtIns.getUnitType());
@@ -95,7 +99,7 @@
         // or initialization of properties corresponds to a package declared in a file
         ControlFlowInformationProvider controlFlowInformationProvider =
                 controlFlowInformationProviderFactory.createControlFlowInformationProvider(
-                        (KtElement) declarationContainer, trace, languageVersionSettings, diagnosticSuppressor
+                        (KtElement) declarationContainer, trace, languageVersionSettings, diagnosticSuppressor, enumWhenTracker
                 );
         if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
             controlFlowInformationProvider.checkForLocalClassOrObjectMode();
@@ -120,7 +124,7 @@
     ) {
         ControlFlowInformationProvider controlFlowInformationProvider =
                 controlFlowInformationProviderFactory.createControlFlowInformationProvider(
-                        function, trace, languageVersionSettings, diagnosticSuppressor
+                        function, trace, languageVersionSettings, diagnosticSuppressor, enumWhenTracker
                 );
         if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
             controlFlowInformationProvider.checkForLocalClassOrObjectMode();
diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontendFacade.kt
index ee6d963..3820970 100644
--- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontendFacade.kt
+++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontendFacade.kt
@@ -27,6 +27,7 @@
 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
 import org.jetbrains.kotlin.frontend.java.di.createContainerForLazyResolveWithJava
 import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -214,6 +215,7 @@
             CompilerEnvironment, LookupTracker.DO_NOTHING,
             ExpectActualTracker.DoNothing,
             InlineConstTracker.DoNothing,
+            EnumWhenTracker.DoNothing,
             packagePartProviderFactory(moduleContentScope),
             module.languageVersionSettings,
             useBuiltInsProvider = true
diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt
index 394a1f1..3ec6e13 100644
--- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt
+++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt
@@ -40,6 +40,7 @@
 import org.jetbrains.kotlin.diagnostics.Errors.*
 import org.jetbrains.kotlin.frontend.java.di.createContainerForLazyResolveWithJava
 import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -424,7 +425,7 @@
             moduleContentScope,
             moduleClassResolver,
             CompilerEnvironment,
-            LookupTracker.DO_NOTHING, ExpectActualTracker.DoNothing, InlineConstTracker.DoNothing,
+            LookupTracker.DO_NOTHING, ExpectActualTracker.DoNothing, InlineConstTracker.DoNothing, EnumWhenTracker.DoNothing,
             environment.createPackagePartProvider(moduleContentScope),
             languageVersionSettings,
             useBuiltInsProvider = true
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/incremental/components/EnumWhenTracker.kt b/core/compiler.common/src/org/jetbrains/kotlin/incremental/components/EnumWhenTracker.kt
new file mode 100644
index 0000000..91277d7
--- /dev/null
+++ b/core/compiler.common/src/org/jetbrains/kotlin/incremental/components/EnumWhenTracker.kt
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2010-2021 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.incremental.components
+
+import org.jetbrains.kotlin.container.DefaultImplementation
+
+@DefaultImplementation(EnumWhenTracker.DoNothing::class)
+interface EnumWhenTracker {
+    fun report(whenUsageClassPath: String, enumClassFqName: String)
+
+    object DoNothing : EnumWhenTracker {
+        override fun report(whenUsageClassPath: String, enumClassFqName: String) {}
+    }
+}
\ No newline at end of file
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/frontend/js/di/injection.kt b/js/js.frontend/src/org/jetbrains/kotlin/frontend/js/di/injection.kt
index 916aa81..aa8d563 100644
--- a/js/js.frontend/src/org/jetbrains/kotlin/frontend/js/di/injection.kt
+++ b/js/js.frontend/src/org/jetbrains/kotlin/frontend/js/di/injection.kt
@@ -27,6 +27,7 @@
 import org.jetbrains.kotlin.frontend.di.configureIncrementalCompilation
 import org.jetbrains.kotlin.frontend.di.configureModule
 import org.jetbrains.kotlin.frontend.di.configureStandardResolveComponents
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -47,6 +48,7 @@
     lookupTracker: LookupTracker,
     expectActualTracker: ExpectActualTracker,
     inlineConstTracker: InlineConstTracker,
+    enumWhenTracker: EnumWhenTracker,
     additionalPackages: List<PackageFragmentProvider>,
     targetEnvironment: TargetEnvironment,
 ): StorageComponentContainer {
@@ -59,7 +61,7 @@
             languageVersionSettings
         )
 
-        configureIncrementalCompilation(lookupTracker, expectActualTracker, inlineConstTracker)
+        configureIncrementalCompilation(lookupTracker, expectActualTracker, inlineConstTracker, enumWhenTracker)
         configureStandardResolveComponents()
 
         useInstance(declarationProviderFactory)
@@ -83,11 +85,12 @@
     lookupTracker: LookupTracker,
     expectActualTracker: ExpectActualTracker,
     inlineConstTracker: InlineConstTracker,
+    enumWhenTracker: EnumWhenTracker,
     additionalPackages: List<PackageFragmentProvider>,
     targetEnvironment: TargetEnvironment,
 ): LazyTopDownAnalyzer {
     return createContainerForJS(
         moduleContext, bindingTrace, declarationProviderFactory, languageVersionSettings,
-        lookupTracker, expectActualTracker, inlineConstTracker, additionalPackages, targetEnvironment
+        lookupTracker, expectActualTracker, inlineConstTracker, enumWhenTracker, additionalPackages, targetEnvironment
     ).get<LazyTopDownAnalyzer>()
 }
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt
index 69b7687..0ce3b62 100644
--- a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt
+++ b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.kt
@@ -20,6 +20,7 @@
 import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
 import org.jetbrains.kotlin.frontend.js.di.createContainerForJS
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -107,6 +108,7 @@
         val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: LookupTracker.DO_NOTHING
         val expectActualTracker = configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER) ?: ExpectActualTracker.DoNothing
         val inlineConstTracker = configuration.get(CommonConfigurationKeys.INLINE_CONST_TRACKER) ?: InlineConstTracker.DoNothing
+        val enumWhenTracker = configuration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER) ?: EnumWhenTracker.DoNothing
         val languageVersionSettings = configuration.languageVersionSettings
         val packageFragment = configuration[JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER]?.let {
             loadIncrementalCacheMetadata(it, moduleContext, lookupTracker, languageVersionSettings)
@@ -119,6 +121,7 @@
             lookupTracker,
             expectActualTracker,
             inlineConstTracker,
+            enumWhenTracker,
             additionalPackages + listOfNotNull(packageFragment),
             targetEnvironment,
         )
diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/AbstractJsScriptlikeCodeAnalyser.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/AbstractJsScriptlikeCodeAnalyser.kt
index ba32c177..8f47811 100644
--- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/AbstractJsScriptlikeCodeAnalyser.kt
+++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/AbstractJsScriptlikeCodeAnalyser.kt
@@ -17,6 +17,7 @@
 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
 import org.jetbrains.kotlin.diagnostics.Severity
 import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
+import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
 import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
 import org.jetbrains.kotlin.incremental.components.InlineConstTracker
 import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -56,6 +57,7 @@
         val lookupTracker = LookupTracker.DO_NOTHING
         val expectActualTracker = ExpectActualTracker.DoNothing
         val inlineConstTracker = InlineConstTracker.DoNothing
+        val enumWhenTracker = EnumWhenTracker.DoNothing
         val additionalPackages = emptyList<PackageFragmentProvider>()
         val moduleDescriptor = moduleContext.module
 
@@ -68,6 +70,7 @@
             lookupTracker,
             expectActualTracker,
             inlineConstTracker,
+            enumWhenTracker,
             additionalPackages,
             CompilerEnvironment,
         )