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
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker;
import org.jetbrains.kotlin.incremental.components.LookupTracker;
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider;
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer;
@@ -418,6 +419,11 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, lookupTracker);
}
ExpectActualTracker expectActualTracker = services.get(ExpectActualTracker.class);
if (expectActualTracker != null) {
configuration.put(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER, expectActualTracker);
}
String sourceMapEmbedContentString = arguments.getSourceMapEmbedSources();
SourceMapSourceEmbedding sourceMapContentEmbedding = sourceMapEmbedContentString != null ?
sourceMapContentEmbeddingMap.get(sourceMapEmbedContentString) :
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
import org.jetbrains.kotlin.codegen.CompilationException
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.JavaClassesTracker
@@ -300,6 +301,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, it)
}
services.get(ExpectActualTracker::class.java)?.let {
configuration.put(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER, it)
}
services.get(IncrementalCompilationComponents::class.java)?.let {
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, it)
}
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDependenciesImpl
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
import org.jetbrains.kotlin.frontend.java.di.initialize
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.javac.components.JavacBasedClassFinder
import org.jetbrains.kotlin.javac.components.JavacBasedSourceElementFactory
@@ -133,6 +134,7 @@ object TopDownAnalyzerFacadeForJVM {
val incrementalComponents = configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS)
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: LookupTracker.DO_NOTHING
val expectActualTracker = configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER) ?: ExpectActualTracker.DoNothing
val targetIds = configuration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId)
val separateModules = !configuration.getBoolean(JVMConfigurationKeys.USE_SINGLE_MODULE)
@@ -171,7 +173,7 @@ object TopDownAnalyzerFacadeForJVM {
val dependencyScope = GlobalSearchScope.notScope(sourceScope)
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker,
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker, expectActualTracker,
packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder
)
@@ -196,7 +198,7 @@ object TopDownAnalyzerFacadeForJVM {
// to be stored in CliLightClassGenerationSupport, and it better be the source one (otherwise light classes would not be found)
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
val container = createContainerForTopDownAnalyzerForJvm(
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker, expectActualTracker,
partProvider, moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder,
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
).apply {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackagePartProvider
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.java.AbstractJavaClassFinder
import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
@@ -49,10 +50,12 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
private fun StorageComponentContainer.configureJavaTopDownAnalysis(
moduleContentScope: GlobalSearchScope,
project: Project,
lookupTracker: LookupTracker
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker
) {
useInstance(moduleContentScope)
useInstance(lookupTracker)
useInstance(expectActualTracker)
useImpl<ResolveSession>()
useImpl<LazyTopDownAnalyzer>()
@@ -79,6 +82,7 @@ fun createContainerForLazyResolveWithJava(
moduleClassResolver: ModuleClassResolver,
targetEnvironment: TargetEnvironment,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
packagePartProvider: PackagePartProvider,
jvmTarget: JvmTarget,
languageVersionSettings: LanguageVersionSettings,
@@ -87,7 +91,7 @@ fun createContainerForLazyResolveWithJava(
javaClassTracker: JavaClassesTracker? = null
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatform) {
configureModule(moduleContext, JvmPlatform, jvmTarget, bindingTrace)
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker)
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker, expectActualTracker)
if (configureJavaClassFinder != null) {
configureJavaClassFinder()
@@ -127,6 +131,7 @@ fun createContainerForTopDownAnalyzerForJvm(
declarationProviderFactory: DeclarationProviderFactory,
moduleContentScope: GlobalSearchScope,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
packagePartProvider: PackagePartProvider,
moduleClassResolver: ModuleClassResolver,
jvmTarget: JvmTarget,
@@ -135,7 +140,7 @@ fun createContainerForTopDownAnalyzerForJvm(
javaClassTracker: JavaClassesTracker? = null
): ComponentProvider = createContainerForLazyResolveWithJava(
moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver,
CompilerEnvironment, lookupTracker, packagePartProvider, jvmTarget, languageVersionSettings,
CompilerEnvironment, lookupTracker, expectActualTracker, packagePartProvider, jvmTarget, languageVersionSettings,
useBuiltInsProvider = true,
configureJavaClassFinder = configureJavaClassFinder,
javaClassTracker = javaClassTracker
@@ -25,6 +25,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.java.di.createContainerForLazyResolveWithJava
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolverImpl
import org.jetbrains.kotlin.load.java.structure.JavaClass
@@ -92,6 +93,7 @@ object JvmAnalyzerFacade : AnalyzerFacade() {
moduleClassResolver,
targetEnvironment,
lookupTracker,
ExpectActualTracker.DoNothing,
packagePartProvider,
jvmTarget,
languageVersionSettings,
@@ -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) {
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import java.io.File
internal class ExpectActualTrackerImpl : ExpectActualTracker {
private val expectToActual = hashMapOf<File, MutableSet<File>>()
val expectToActualMap: Map<File, Set<File>>
get() = expectToActual
override fun report(expectedFile: File, actualFile: File) {
expectToActual.getOrPut(expectedFile) { hashSetOf() }.add(actualFile)
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem
import org.jetbrains.kotlin.compilerRunner.toGeneratedFile
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
@@ -153,11 +154,13 @@ abstract class IncrementalCompilerRunner<
protected open fun makeServices(
args: Args,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
caches: CacheManager,
compilationMode: CompilationMode
): Services.Builder =
Services.Builder().apply {
register(LookupTracker::class.java, lookupTracker)
register(ExpectActualTracker::class.java, expectActualTracker)
register(CompilationCanceledStatus::class.java, EmptyCompilationCanceledStatus)
}
@@ -191,10 +194,13 @@ abstract class IncrementalCompilerRunner<
var exitCode = ExitCode.OK
while (dirtySources.any() || runWithNoDirtyKotlinSources(caches)) {
val complementaryFiles = caches.inputsCache.clearComplementaryFilesMapping(dirtySources)
dirtySources.addAll(complementaryFiles)
caches.platformCache.markDirty(dirtySources)
caches.inputsCache.removeOutputForSourceFiles(dirtySources)
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
val expectActualTracker = ExpectActualTrackerImpl()
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
@@ -203,7 +209,7 @@ abstract class IncrementalCompilerRunner<
val text = allSourcesToCompile.joinToString(separator = System.getProperty("line.separator")) { it.canonicalPath }
dirtySourcesSinceLastTimeFile.writeText(text)
val services = makeServices(args, lookupTracker, caches, compilationMode).build()
val services = makeServices(args, lookupTracker, expectActualTracker, caches, compilationMode).build()
args.reportOutputFiles = true
val outputItemsCollector = OutputItemsCollectorImpl()
@@ -227,6 +233,7 @@ abstract class IncrementalCompilerRunner<
}
}
caches.inputsCache.registerComplementaryFiles(expectActualTracker)
caches.inputsCache.registerOutputForSourceFiles(generatedFiles)
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
val changesCollector = ChangesCollector()
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.*
import java.io.File
@@ -97,10 +98,11 @@ class IncrementalJsCompilerRunner(
override fun makeServices(
args: K2JSCompilerArguments,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
caches: IncrementalJsCachesManager,
compilationMode: CompilationMode
): Services.Builder =
super.makeServices(args, lookupTracker, caches, compilationMode).apply {
super.makeServices(args, lookupTracker, expectActualTracker, caches, compilationMode).apply {
register(IncrementalResultsConsumer::class.java, IncrementalResultsConsumerImpl())
if (compilationMode is CompilationMode.Incremental) {
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
@@ -401,10 +402,11 @@ class IncrementalJvmCompilerRunner(
override fun makeServices(
args: K2JVMCompilerArguments,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
caches: IncrementalJvmCachesManager,
compilationMode: CompilationMode
): Services.Builder =
super.makeServices(args, lookupTracker, caches, compilationMode).apply {
super.makeServices(args, lookupTracker, expectActualTracker, caches, compilationMode).apply {
val targetId = TargetId(args.moduleName!!, "java-production")
val targetToCache = mapOf(targetId to caches.platformCache)
val incrementalComponents = IncrementalCompilationComponentsImpl(targetToCache)
@@ -23,20 +23,63 @@ import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
import org.jetbrains.kotlin.incremental.storage.StringCollectionExternalizer
import org.jetbrains.kotlin.modules.TargetId
import java.io.File
import java.util.*
import kotlin.collections.HashSet
class InputsCache(
workingDir: File,
private val reporter: ICReporter
) : BasicMapsOwner(workingDir) {
companion object {
private val SOURCE_TO_OUTPUT_FILES = "source-to-output"
private val SOURCE_SNAPSHOTS = "source-snapshot"
private val SOURCE_TO_OUTPUT_FILES = "source-to-output"
private val COMPLEMENTARY_FILES = "complementary-files"
}
internal val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile))
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile))
private val sourceToOutputMap = registerMap(FilesMap(SOURCE_TO_OUTPUT_FILES.storageFile))
/**
* A file X is a complementary to a file Y if they contain corresponding expect/actual declarations.
* Complementary files should be compiled together during IC so the compiler does not complain
* about missing parts.
* TODO: provide a better solution (maintain an index of expect/actual declarations akin to IncrementalPackagePartProvider)
*/
private val complementaryFilesMap = registerMap(FilesMap(COMPLEMENTARY_FILES.storageFile))
fun clearComplementaryFilesMapping(dirtyFiles: Collection<File>): Collection<File> {
val complementaryFiles = HashSet<File>()
val filesQueue = ArrayDeque(dirtyFiles)
while (filesQueue.isNotEmpty()) {
val file = filesQueue.pollFirst()
complementaryFilesMap.remove(file).filterTo(filesQueue) { complementaryFiles.add(it) }
}
complementaryFiles.removeAll(dirtyFiles)
return complementaryFiles
}
internal fun registerComplementaryFiles(expectActualTracker: ExpectActualTrackerImpl) {
val actualToExpect = hashMapOf<File, MutableSet<File>>()
for ((expect, actuals) in expectActualTracker.expectToActualMap) {
for (actual in actuals) {
actualToExpect.getOrPut(actual) { hashSetOf() }.add(expect)
}
complementaryFilesMap[expect] = actuals
}
for ((actual, expects) in actualToExpect) {
complementaryFilesMap[actual] = expects
}
}
fun removeOutputForSourceFiles(sources: Iterable<File>) {
for (sourceFile in sources) {
sourceToOutputMap.remove(sourceFile).forEach { it ->
reporter.report { "Deleting $it on clearing cache for $sourceFile" }
it.delete()
}
}
}
// generatedFiles can contain multiple entries with the same source file
// for example Kapt3 IC will generate a .java stub and .class stub for each source file
@@ -53,29 +96,21 @@ class InputsCache(
sourceToOutputMap[source] = outputs
}
}
}
fun removeOutputForSourceFiles(sources: Iterable<File>) {
sources.forEach { sourceToOutputMap.remove(it) }
private class FilesMap(storageFile: File)
: BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
storage[sourceFile.absolutePath] = outputFiles.map { it.absolutePath }
}
inner class SourceToOutputFilesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
storage[sourceFile.absolutePath] = outputFiles.map { it.absolutePath }
}
operator fun get(sourceFile: File): Collection<File> =
storage[sourceFile.absolutePath].orEmpty().map(::File)
operator fun get(sourceFile: File): Collection<File> =
storage[sourceFile.absolutePath].orEmpty().map(::File)
override fun dumpValue(value: Collection<String>) =
value.dumpCollection()
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
fun remove(file: File) {
// TODO: do it in the code that uses cache, since cache should not generally delete anything outside of it!
// but for a moment it is an easiest solution to implement
get(file).forEach {
reporter.report { "Deleting $it on clearing cache for $file" }
it.delete()
}
storage.remove(file.absolutePath)
}
}
fun remove(file: File): Collection<File> =
get(file).also { storage.remove(file.absolutePath) }
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import java.io.File
abstract class AbstractIncrementalMultiplatformJsCompilerRunnerTest : AbstractIncrementalJsCompilerRunnerTest() {
override fun createCompilerArguments(destinationDir: File, testDir: File): K2JSCompilerArguments {
return super.createCompilerArguments(destinationDir, testDir).apply {
multiPlatform = true
}
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import java.io.File
abstract class AbstractIncrementalMultiplatformJvmCompilerRunnerTest : AbstractIncrementalJvmCompilerRunnerTest() {
override fun createCompilerArguments(destinationDir: File, testDir: File): K2JVMCompilerArguments {
return super.createCompilerArguments(destinationDir, testDir).apply {
multiPlatform = true
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/multiplatform")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalMultiplatformJsCompilerRunnerTestGenerated extends AbstractIncrementalMultiplatformJsCompilerRunnerTest {
public void testAllFilesPresentInMultiplatform() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
@TestMetadata("touchActual")
public void testTouchActual() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/multiplatform/touchActual/");
doTest(fileName);
}
@TestMetadata("touchExpect")
public void testTouchExpect() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/multiplatform/touchExpect/");
doTest(fileName);
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental/multiplatform")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IncrementalMultiplatformJvmCompilerRunnerTestGenerated extends AbstractIncrementalMultiplatformJvmCompilerRunnerTest {
public void testAllFilesPresentInMultiplatform() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
@TestMetadata("touchActual")
public void testTouchActual() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/multiplatform/touchActual/");
doTest(fileName);
}
@TestMetadata("touchExpect")
public void testTouchExpect() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/multiplatform/touchExpect/");
doTest(fileName);
}
}
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver
import org.jetbrains.kotlin.name.FqName
@@ -322,6 +323,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
moduleContentScope,
LookupTracker.DO_NOTHING,
ExpectActualTracker.DoNothing,
environment.createPackagePartProvider(moduleContentScope),
moduleClassResolver,
JvmTarget.JVM_1_6,
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.components
import org.jetbrains.kotlin.container.DefaultImplementation
import java.io.File
@DefaultImplementation(ExpectActualTracker.DoNothing::class)
interface ExpectActualTracker {
fun report(expectedFile: File, actualFile: File)
object DoNothing : ExpectActualTracker {
override fun report(expectedFile: File, actualFile: File) {
}
}
}
@@ -137,6 +137,8 @@ import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest
import org.jetbrains.kotlin.idea.stubs.AbstractStubBuilderTest
import org.jetbrains.kotlin.incremental.AbstractIncrementalJsCompilerRunnerTest
import org.jetbrains.kotlin.incremental.AbstractIncrementalJvmCompilerRunnerTest
import org.jetbrains.kotlin.incremental.AbstractIncrementalMultiplatformJsCompilerRunnerTest
import org.jetbrains.kotlin.incremental.AbstractIncrementalMultiplatformJvmCompilerRunnerTest
import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterForWebDemoTest
import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterMultiFileTest
import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest
@@ -920,6 +922,13 @@ fun main(args: Array<String>) {
model("incremental/pureKotlin", extension = null, recursive = false)
model("incremental/classHierarchyAffected", extension = null, recursive = false)
}
testClass<AbstractIncrementalMultiplatformJvmCompilerRunnerTest> {
model("incremental/multiplatform", extension = null, excludeParentDirs = true)
}
testClass<AbstractIncrementalMultiplatformJsCompilerRunnerTest> {
model("incremental/multiplatform", extension = null, excludeParentDirs = true)
}
}
testGroup("plugins/android-extensions/android-extensions-compiler/test", "plugins/android-extensions/android-extensions-compiler/testData") {
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.idea.project.ResolveElementCache
import org.jetbrains.kotlin.idea.stubindex.KotlinOverridableInternalMembersShortNameIndex
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.lexer.KtTokens
@@ -288,6 +289,7 @@ object IDELightClassContexts {
useInstance(GlobalSearchScope.EMPTY_SCOPE)
useInstance(LookupTracker.DO_NOTHING)
useInstance(ExpectActualTracker.DoNothing)
useImpl<FileScopeProviderImpl>()
useInstance(IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project))
useInstance(FileBasedDeclarationProviderFactory(sm, files))
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.core.toDescriptor
import org.jetbrains.kotlin.idea.facet.implementingDescriptors
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration
@@ -50,7 +51,8 @@ class PlatformExpectedAnnotator : Annotator {
val trace = BindingTraceContext()
for (module in implementingModules) {
ExpectedActualDeclarationChecker.checkExpectedDeclarationHasActual(declaration, descriptor, trace, module)
ExpectedActualDeclarationChecker.checkExpectedDeclarationHasActual(declaration, descriptor, trace, module,
ExpectActualTracker.DoNothing)
}
val suppressionCache = KotlinCacheService.getInstance(declaration.project).getSuppressionCache()
@@ -0,0 +1,3 @@
actual class X {
actual fun foo(): Any = 0
}
@@ -0,0 +1,3 @@
actual class Y {
actual fun foo(): Any = 0
}
@@ -0,0 +1,3 @@
actual class Z {
actual fun foo(): Any = 0
}
@@ -0,0 +1,19 @@
================ Step #1 =================
Compiling files:
src/X.kt
src/commonX.kt
src/useX.kt
End of files
Exit code: SUCCESS
================ Step #2 =================
Compiling files:
src/Y.kt
src/Z.kt
src/commonY.kt
src/commonZ.kt
src/useYZ.kt
End of files
Exit code: SUCCESS
@@ -0,0 +1,5 @@
expect class X {
fun foo(): Any
}
expect fun useX(x: X): Unit
@@ -0,0 +1,5 @@
expect class Y {
fun foo(): Any
}
expect fun useY(y: Y): Unit
@@ -0,0 +1,5 @@
expect class Z {
fun foo(): Any
}
expect fun useZ(z: Z): Unit
@@ -0,0 +1 @@
fun dummy() {}
@@ -0,0 +1,3 @@
actual fun useX(x: X): Unit {
x.foo()
}
@@ -0,0 +1,7 @@
actual fun useY(y: Y): Unit {
y.foo()
}
actual fun useZ(z: Z): Unit {
z.foo()
}
@@ -0,0 +1,3 @@
actual class X {
actual fun foo(): Any = 0
}
@@ -0,0 +1,3 @@
actual class Y {
actual fun foo(): Any = 0
}
@@ -0,0 +1,3 @@
actual class Z {
actual fun foo(): Any = 0
}
@@ -0,0 +1,19 @@
================ Step #1 =================
Compiling files:
src/X.kt
src/commonX.kt
src/useX.kt
End of files
Exit code: SUCCESS
================ Step #2 =================
Compiling files:
src/Y.kt
src/Z.kt
src/commonY.kt
src/commonZ.kt
src/useYZ.kt
End of files
Exit code: SUCCESS
@@ -0,0 +1,5 @@
expect class X {
fun foo(): Any
}
expect fun useX(x: X): Unit
@@ -0,0 +1,5 @@
expect class Y {
fun foo(): Any
}
expect fun useY(y: Y): Unit
@@ -0,0 +1,5 @@
expect class Z {
fun foo(): Any
}
expect fun useZ(z: Z): Unit
@@ -0,0 +1 @@
fun dummy() {}
@@ -0,0 +1,3 @@
actual fun useX(x: X): Unit {
x.foo()
}
@@ -0,0 +1,2 @@
fun useX(x: String): Int =
x.length
@@ -0,0 +1,7 @@
actual fun useY(y: Y): Unit {
y.foo()
}
actual fun useZ(z: Z): Unit {
z.foo()
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
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.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.*
@@ -42,6 +43,7 @@ fun createTopDownAnalyzerForJs(
declarationProviderFactory: DeclarationProviderFactory,
languageVersionSettings: LanguageVersionSettings,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
fallbackPackage: PackageFragmentProvider?
): LazyTopDownAnalyzer {
val storageComponentContainer = createContainer("TopDownAnalyzerForJs", JsPlatform) {
@@ -52,6 +54,7 @@ fun createTopDownAnalyzerForJs(
CompilerEnvironment.configure(this)
useInstance(lookupTracker)
useInstance(expectActualTracker)
useInstance(languageVersionSettings)
useImpl<ResolveSession>()
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.context.ContextForNewModule
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
@@ -66,6 +67,7 @@ object TopDownAnalyzerFacadeForJS {
config: JsConfig
): JsAnalysisResult {
val lookupTracker = config.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: LookupTracker.DO_NOTHING
val expectActualTracker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER) ?: ExpectActualTracker.DoNothing
val languageVersionSettings = config.configuration.languageVersionSettings
val packageFragment = config.configuration[JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER]?.let {
val metadata = PackagesWithHeaderMetadata(it.headerMetadata, it.compiledPackageParts.values.map { it.metadata })
@@ -79,6 +81,7 @@ object TopDownAnalyzerFacadeForJS {
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
languageVersionSettings,
lookupTracker,
expectActualTracker,
packageFragment
)
analyzerForJs.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.reportFromPlugin
import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.noarg.NO_ARG_CLASS_KEY
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -43,7 +44,8 @@ abstract class AbstractNoArgDeclarationChecker : DeclarationChecker, AnnotationB
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
// Handle only classes
if (descriptor !is ClassDescriptor || declaration !is KtClass) return