[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
This commit is contained in:
Aleksei.Cherepanov
2021-11-04 17:13:56 +03:00
committed by Space
parent ee8de63497
commit 3d8f140d6b
38 changed files with 319 additions and 57 deletions
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.diagnostics.Errors
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.ResolvedCall
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
@@ -58,13 +60,15 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.record
class ControlFlowInformationProviderImpl private constructor(
private val subroutine: KtElement,
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 +78,15 @@ class ControlFlowInformationProviderImpl private constructor(
declaration: KtElement,
trace: BindingTrace,
languageVersionSettings: LanguageVersionSettings,
diagnosticSuppressor: PlatformDiagnosticSuppressor
diagnosticSuppressor: PlatformDiagnosticSuppressor,
enumWhenTracker: EnumWhenTracker? = null
) : this(
declaration,
trace,
ControlFlowProcessor(trace, languageVersionSettings).generatePseudocode(declaration),
languageVersionSettings,
diagnosticSuppressor
diagnosticSuppressor,
enumWhenTracker
)
override fun checkForLocalClassOrObjectMode() {
@@ -231,7 +237,7 @@ class ControlFlowInformationProviderImpl private constructor(
val expectedType = functionDescriptor?.returnType
val providerForLocalDeclaration = ControlFlowInformationProviderImpl(
element, trace, localDeclarationInstruction.body, languageVersionSettings, diagnosticSuppressor
element, trace, localDeclarationInstruction.body, languageVersionSettings, diagnosticSuppressor, enumWhenTracker
)
providerForLocalDeclaration.checkFunction(expectedType)
@@ -1057,6 +1063,9 @@ class ControlFlowInformationProviderImpl private constructor(
}
continue
}
enumWhenTracker?.record(subjectType, subjectExpression, elseEntry)
if (!usedAsExpression) {
if (languageVersionSettings.supportsFeature(LanguageFeature.WarnAboutNonExhaustiveWhenOnAlgebraicTypes)) {
// report warnings on all non-exhaustive when's with algebraic subject
@@ -1318,9 +1327,10 @@ class ControlFlowInformationProviderImpl private constructor(
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 {
@@ -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 @@ interface ControlFlowInformationProvider {
trace: BindingTrace,
languageVersionSettings: LanguageVersionSettings,
diagnosticSuppressor: PlatformDiagnosticSuppressor,
enumWhenTracker: EnumWhenTracker
): ControlFlowInformationProvider
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.extensions.TypeAttributeTranslatorExtension
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
@@ -130,10 +131,16 @@ fun StorageComponentContainer.configureStandardResolveComponents() {
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(
@@ -209,6 +216,7 @@ fun createContainerForLazyLocalClassifierAnalyzer(
useInstance(lookupTracker)
useInstance(ExpectActualTracker.DoNothing)
useInstance(InlineConstTracker.DoNothing)
useInstance(EnumWhenTracker.DoNothing)
useImpl<LazyTopDownAnalyzer>()
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings;
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 @@ public class ControlFlowAnalyzer {
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 @@ public class ControlFlowAnalyzer {
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 @@ public class ControlFlowAnalyzer {
// 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 @@ public class ControlFlowAnalyzer {
) {
ControlFlowInformationProvider controlFlowInformationProvider =
controlFlowInformationProviderFactory.createControlFlowInformationProvider(
function, trace, languageVersionSettings, diagnosticSuppressor
function, trace, languageVersionSettings, diagnosticSuppressor, enumWhenTracker
);
if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
controlFlowInformationProvider.checkForLocalClassOrObjectMode();
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.types.error.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
import org.jetbrains.kotlin.util.KotlinFrontEndException;
import org.jetbrains.kotlin.util.LookupTrackerUtilKt;
import org.jetbrains.kotlin.util.IncrementalTrackerUtilKt;
import org.jetbrains.kotlin.util.PerformanceCounter;
import org.jetbrains.kotlin.util.ReenteringLazyValueComputationException;
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
@@ -236,7 +236,7 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
KotlinType resultType = typeInfo.getType();
if (resultType != null) {
LookupTrackerUtilKt.record(lookupTracker, expression, resultType);
IncrementalTrackerUtilKt.record(lookupTracker, expression, resultType);
}
}
@@ -18,11 +18,16 @@ package org.jetbrains.kotlin.util
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.containingPackage
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtWhenEntry
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.isUnit
@@ -50,3 +55,20 @@ fun LookupTracker.record(expression: KtExpression, type: KotlinType) {
}
}
}
fun EnumWhenTracker.record(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.containingFile.virtualFile?.path ?: return
val owner = if (fqName.startsWith("$containingPackage.")) {
containingPackage + "." + fqName.substring(containingPackage.length + 1).replace(".", "$")
} else {
fqName.replace(".", "$")
}
this.report(filePath, owner)
}