Compile actual and expected declarations together

#KT-20840 fixed
This commit is contained in:
Alexey Tsvetkov
2017-12-01 16:07:40 +03:00
parent 123fd64a34
commit fec2d08d22
56 changed files with 515 additions and 43 deletions
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.di.configureModule
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
import org.jetbrains.kotlin.name.Name
@@ -142,6 +143,7 @@ object CommonAnalyzerFacade : AnalyzerFacade() {
useInstance(moduleContentScope)
useInstance(LookupTracker.DO_NOTHING)
useInstance(ExpectActualTracker.DoNothing)
useImpl<ResolveSession>()
useImpl<LazyTopDownAnalyzer>()
useInstance(languageVersionSettings)
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.config
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
object CommonConfigurationKeys {
@@ -33,6 +34,9 @@ object CommonConfigurationKeys {
@JvmField
val LOOKUP_TRACKER = CompilerConfigurationKey.create<LookupTracker>("lookup tracker")
@JvmField
val EXPECT_ACTUAL_TRACKER = CompilerConfigurationKey.create<ExpectActualTracker>("expect actual tracker")
}
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.*
@@ -127,6 +128,7 @@ fun createContainerForLazyLocalClassifierAnalyzer(
useInstance(localClassDescriptorHolder)
useInstance(lookupTracker)
useInstance(ExpectActualTracker.DoNothing)
useImpl<LazyTopDownAnalyzer>()
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension;
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker;
import org.jetbrains.kotlin.lexer.KtKeywordToken;
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -280,7 +281,7 @@ public class ModifiersChecker {
@NotNull DeclarationDescriptor descriptor
) {
for (DeclarationChecker checker : declarationCheckers) {
checker.check(declaration, descriptor, trace, trace.getBindingContext(), languageVersionSettings);
checker.check(declaration, descriptor, trace, trace.getBindingContext(), languageVersionSettings, expectActualTracker);
}
OperatorModifierChecker.INSTANCE.check(declaration, descriptor, trace, languageVersionSettings);
PublishedApiUsageChecker.INSTANCE.check(declaration, descriptor, trace);
@@ -304,14 +305,19 @@ public class ModifiersChecker {
@NotNull
private final LanguageVersionSettings languageVersionSettings;
@NotNull
private final ExpectActualTracker expectActualTracker;
public ModifiersChecker(
@NotNull AnnotationChecker annotationChecker,
@NotNull Iterable<DeclarationChecker> declarationCheckers,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull ExpectActualTracker expectActualTracker
) {
this.annotationChecker = annotationChecker;
this.declarationCheckers = declarationCheckers;
this.languageVersionSettings = languageVersionSettings;
this.expectActualTracker = expectActualTracker;
}
@NotNull
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
@@ -29,7 +30,8 @@ interface DeclarationChecker {
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
)
}
@@ -38,7 +40,9 @@ interface SimpleDeclarationChecker : DeclarationChecker {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext, languageVersionSettings: LanguageVersionSettings
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) = check(declaration, descriptor, diagnosticHolder, bindingContext)
fun check(
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
@@ -37,7 +38,8 @@ class DelegationChecker : DeclarationChecker {
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
if (descriptor !is ClassDescriptor) return
if (declaration !is KtClassOrObject) return
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.checkers
import com.intellij.openapi.vfs.VfsUtilCore
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.LanguageFeature
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtConstructor
@@ -40,6 +42,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
@@ -48,7 +51,9 @@ import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.checker.TypeCheckerContext
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.keysToMap
import java.io.File
object ExpectedActualDeclarationChecker : DeclarationChecker {
override fun check(
@@ -56,7 +61,8 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return
@@ -64,7 +70,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
if (descriptor !is MemberDescriptor || DescriptorUtils.isEnumEntry(descriptor)) return
if (descriptor.isExpect) {
checkExpectedDeclarationHasActual(declaration, descriptor, diagnosticHolder, descriptor.module)
checkExpectedDeclarationHasActual(declaration, descriptor, diagnosticHolder, descriptor.module, expectActualTracker)
}
else {
val checkActual = !languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckActual)
@@ -76,7 +82,8 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
reportOn: KtNamedDeclaration,
descriptor: MemberDescriptor,
diagnosticHolder: DiagnosticSink,
platformModule: ModuleDescriptor
platformModule: ModuleDescriptor,
expectActualTracker: ExpectActualTracker
) {
// Only look for top level actual members; class members will be handled as a part of that expected class
if (descriptor.containingDeclaration !is PackageFragmentDescriptor) return
@@ -96,8 +103,32 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
diagnosticHolder.report(Errors.NO_ACTUAL_FOR_EXPECT.on(reportOn, descriptor, platformModule, incompatibility))
}
else {
val actualMembers = compatibility.asSequence()
.filter { (compatibility, _) ->
compatibility is Compatible || (compatibility is Incompatible && compatibility.kind != Compatibility.IncompatibilityKind.STRONG)
}.flatMap { it.value.asSequence() }
expectActualTracker?.reportExpectActual(expected = descriptor, actualMembers = actualMembers)
}
}
private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: Sequence<MemberDescriptor>) {
if (this is ExpectActualTracker.DoNothing) return
val expectedFile = sourceFile(expected) ?: return
for (actual in actualMembers) {
val actualFile = sourceFile(actual) ?: continue
report(expectedFile = expectedFile, actualFile = actualFile)
}
}
private fun sourceFile(descriptor: MemberDescriptor): File? =
descriptor.source
.containingFile
.safeAs<PsiSourceFile>()
?.run { VfsUtilCore.virtualToIoFile(psiFile.virtualFile) }
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
@@ -37,7 +38,8 @@ abstract class KotlinVersionStringAnnotationValueChecker(
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
val annotation = descriptor.annotations.findAnnotation(annotationFqName) ?: return
val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
@@ -61,7 +62,8 @@ object UnderscoreChecker : DeclarationChecker {
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
if (declaration is KtProperty && descriptor !is VariableDescriptor) return
if (declaration is KtCallableDeclaration) {