mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-11 08:31:29 +00:00
Compare commits
52 Commits
push/pdn_b
...
dsavvinov/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2b57bf3a3 | ||
|
|
2a9cd58de8 | ||
|
|
97098143a5 | ||
|
|
7ecfaf8be1 | ||
|
|
9693b1734f | ||
|
|
dea1308ac3 | ||
|
|
2ddc897ff2 | ||
|
|
b64e8c380c | ||
|
|
900346fa0b | ||
|
|
af7b28ae8e | ||
|
|
c07711d3e1 | ||
|
|
1fa892b436 | ||
|
|
363ca3b902 | ||
|
|
a4a54179a8 | ||
|
|
fc0855e004 | ||
|
|
7437f29656 | ||
|
|
34abbdf72d | ||
|
|
86b4d3a311 | ||
|
|
c57cdb12b3 | ||
|
|
0fbe8d7725 | ||
|
|
811b31342c | ||
|
|
62908efbfc | ||
|
|
df5b935a38 | ||
|
|
365b3908ea | ||
|
|
bb5287f127 | ||
|
|
b85556df61 | ||
|
|
344f7a4b27 | ||
|
|
bf8e523d0d | ||
|
|
62f7d6fa6a | ||
|
|
20571b974e | ||
|
|
b22fa28491 | ||
|
|
51e3141c24 | ||
|
|
e68fca80da | ||
|
|
9514079c4a | ||
|
|
78597c5904 | ||
|
|
690d940b98 | ||
|
|
465577ac63 | ||
|
|
674fd627f3 | ||
|
|
f0f9f1061e | ||
|
|
9bba5cf291 | ||
|
|
f28e5e193f | ||
|
|
e236e94e8a | ||
|
|
e2b64245c1 | ||
|
|
7672d2b0a9 | ||
|
|
1d26c389f7 | ||
|
|
0f9da30a64 | ||
|
|
b921dd9e4d | ||
|
|
f43738bf8d | ||
|
|
811a5b4d1e | ||
|
|
09d1603304 | ||
|
|
66547f9c6c | ||
|
|
e424f06b7c |
@@ -8,6 +8,7 @@ dependencies {
|
||||
compile(project(":core:util.runtime"))
|
||||
compile(project(":compiler:frontend"))
|
||||
compile(project(":compiler:frontend.java"))
|
||||
compile(project(":js:js.frontend"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeIntellijCoreJarDependencies(project) }
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.analyzer.common
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.frontend.di.createContainerToResolveCommonCode
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||
|
||||
class CommonAnalysisParameters(
|
||||
val metadataPartProviderFactory: (ModuleContent<*>) -> MetadataPartProvider
|
||||
) : PlatformAnalysisParameters
|
||||
|
||||
/**
|
||||
* A facade that is used to analyze common (platform-independent) modules in multi-platform projects.
|
||||
* See [CommonPlatform]
|
||||
*/
|
||||
class CommonResolverForModuleFactory(
|
||||
private val platformParameters: CommonAnalysisParameters,
|
||||
private val targetEnvironment: TargetEnvironment,
|
||||
private val targetPlatform: TargetPlatform
|
||||
) : ResolverForModuleFactory() {
|
||||
private class SourceModuleInfo(
|
||||
override val name: Name,
|
||||
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>,
|
||||
private val dependOnOldBuiltIns: Boolean
|
||||
) : ModuleInfo {
|
||||
override fun dependencies() = listOf(this)
|
||||
|
||||
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns =
|
||||
if (dependOnOldBuiltIns) ModuleInfo.DependencyOnBuiltIns.LAST else ModuleInfo.DependencyOnBuiltIns.NONE
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = CommonPlatforms.defaultCommonPlatform
|
||||
|
||||
override val compilerServices: PlatformDependentCompilerServices
|
||||
get() = CommonPlatformCompilerServices
|
||||
}
|
||||
|
||||
override fun <M : ModuleInfo> createResolverForModule(
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
moduleContext: ModuleContext,
|
||||
moduleContent: ModuleContent<M>,
|
||||
resolverForProject: ResolverForProject<M>,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): ResolverForModule {
|
||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||
val project = moduleContext.project
|
||||
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
|
||||
project, moduleContext.storageManager, syntheticFiles,
|
||||
moduleContentScope,
|
||||
moduleInfo
|
||||
)
|
||||
|
||||
val metadataPartProvider = (platformParameters as CommonAnalysisParameters).metadataPartProviderFactory(moduleContent)
|
||||
val trace = CodeAnalyzerInitializer.getInstance(project).createTrace()
|
||||
val container = createContainerToResolveCommonCode(
|
||||
moduleContext, trace, declarationProviderFactory, moduleContentScope, targetEnvironment, metadataPartProvider,
|
||||
languageVersionSettings, moduleInfo.platform!!, CommonPlatformCompilerServices
|
||||
)
|
||||
|
||||
val packageFragmentProviders = listOf(
|
||||
container.get<ResolveSession>().packageFragmentProvider,
|
||||
container.get<MetadataPackageFragmentProvider>()
|
||||
)
|
||||
|
||||
return ResolverForModule(CompositePackageFragmentProvider(packageFragmentProviders), container)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun analyzeFiles(
|
||||
files: Collection<KtFile>, moduleName: Name, dependOnBuiltIns: Boolean, languageVersionSettings: LanguageVersionSettings,
|
||||
capabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap(),
|
||||
metadataPartProviderFactory: (ModuleContent<ModuleInfo>) -> MetadataPartProvider
|
||||
): AnalysisResult {
|
||||
val moduleInfo = SourceModuleInfo(moduleName, capabilities, dependOnBuiltIns)
|
||||
val project = files.firstOrNull()?.project ?: throw AssertionError("No files to analyze")
|
||||
|
||||
val multiplatformLanguageSettings = object : LanguageVersionSettings by languageVersionSettings {
|
||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
||||
if (feature == LanguageFeature.MultiPlatformProjects) LanguageFeature.State.ENABLED
|
||||
else languageVersionSettings.getFeatureSupport(feature)
|
||||
}
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val resolver = ResolverForProjectImpl(
|
||||
"sources for metadata serializer",
|
||||
ProjectContext(project, "metadata serializer"),
|
||||
listOf(moduleInfo),
|
||||
modulesContent = { ModuleContent(it, files, GlobalSearchScope.allScope(project)) },
|
||||
moduleLanguageSettingsProvider = object : LanguageSettingsProvider {
|
||||
override fun getLanguageVersionSettings(
|
||||
moduleInfo: ModuleInfo,
|
||||
project: Project,
|
||||
isReleaseCoroutines: Boolean?
|
||||
) = multiplatformLanguageSettings
|
||||
|
||||
override fun getTargetPlatform(
|
||||
moduleInfo: ModuleInfo,
|
||||
project: Project
|
||||
) = TargetPlatformVersion.NoVersion
|
||||
},
|
||||
resolverForModuleFactoryByPlatform = {
|
||||
CommonResolverForModuleFactory(
|
||||
CommonAnalysisParameters(metadataPartProviderFactory),
|
||||
CompilerEnvironment,
|
||||
CommonPlatforms.defaultCommonPlatform
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val moduleDescriptor = resolver.descriptorForModule(moduleInfo)
|
||||
val container = resolver.resolverForModule(moduleInfo).componentProvider
|
||||
|
||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||
|
||||
return AnalysisResult.success(container.get<BindingTrace>().bindingContext, moduleDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.platform
|
||||
|
||||
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
||||
import org.jetbrains.kotlin.platform.js.JsPlatforms.defaultJsPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms.jvm18
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatforms.defaultKonanPlatform
|
||||
|
||||
object CommonPlatforms {
|
||||
|
||||
val defaultCommonPlatform: TargetPlatform = TargetPlatform(
|
||||
setOf(
|
||||
jvm18.single(),
|
||||
defaultJsPlatform.single(),
|
||||
defaultKonanPlatform.single()
|
||||
)
|
||||
)
|
||||
|
||||
val allSimplePlatforms: List<TargetPlatform>
|
||||
get() = sequence {
|
||||
yieldAll(JvmPlatforms.allJvmPlatforms)
|
||||
yieldAll(KonanPlatforms.allKonanPlatforms)
|
||||
yieldAll(JsPlatforms.allJsPlatforms)
|
||||
|
||||
// TODO(dsavvinov): extensions points?
|
||||
}.toList()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.platform.konan
|
||||
|
||||
import org.jetbrains.kotlin.platform.SimplePlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.toTargetPlatform
|
||||
|
||||
abstract class KonanPlatform : SimplePlatform("Native") {
|
||||
override val oldFashionedDescription: String
|
||||
get() = "Kotlin/Native "
|
||||
}
|
||||
|
||||
object KonanPlatforms {
|
||||
val defaultKonanPlatform: TargetPlatform = object : KonanPlatform() {}.toTargetPlatform()
|
||||
|
||||
val allKonanPlatforms: List<TargetPlatform> = listOf(defaultKonanPlatform)
|
||||
}
|
||||
|
||||
fun TargetPlatform?.isNative(): Boolean = this?.singleOrNull() is KonanPlatform
|
||||
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
|
||||
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.ExpectActualTracker
|
||||
@@ -55,6 +55,7 @@ import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentPr
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||
@@ -166,10 +167,13 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
// Scope for the dependency module contains everything except files present in the scope for the source module
|
||||
val dependencyScope = GlobalSearchScope.notScope(sourceScope)
|
||||
|
||||
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
|
||||
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker, expectActualTracker,
|
||||
packagePartProvider(dependencyScope), moduleClassResolver, targetEnvironment, jvmTarget, languageVersionSettings,
|
||||
configureJavaClassFinder
|
||||
val dependenciesContainer = createContainerForLazyResolveWithJava(
|
||||
JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget),
|
||||
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, moduleClassResolver,
|
||||
CompilerEnvironment, lookupTracker, expectActualTracker,
|
||||
packagePartProvider(dependencyScope), languageVersionSettings,
|
||||
useBuiltInsProvider = true,
|
||||
configureJavaClassFinder = configureJavaClassFinder
|
||||
)
|
||||
|
||||
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get()
|
||||
@@ -195,10 +199,14 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
// CliLightClassGenerationSupport#initialize is invoked when container is created, so only the last module descriptor is going
|
||||
// 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, expectActualTracker,
|
||||
partProvider, moduleClassResolver, targetEnvironment, jvmTarget, languageVersionSettings, configureJavaClassFinder,
|
||||
configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
|
||||
val container = createContainerForLazyResolveWithJava(
|
||||
JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget),
|
||||
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, moduleClassResolver,
|
||||
CompilerEnvironment, lookupTracker, expectActualTracker,
|
||||
partProvider, languageVersionSettings,
|
||||
useBuiltInsProvider = true,
|
||||
configureJavaClassFinder = configureJavaClassFinder,
|
||||
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
|
||||
).apply {
|
||||
initJvmBuiltInsForTopDownAnalysis()
|
||||
(partProvider as? IncrementalPackagePartProvider)?.deserializationConfiguration = get()
|
||||
@@ -268,7 +276,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
}
|
||||
|
||||
private fun createModuleContext(project: Project, configuration: CompilerConfiguration): MutableModuleContext {
|
||||
val projectContext = ProjectContext(project)
|
||||
val projectContext = ProjectContext(project, "TopDownAnalyzer for JVM")
|
||||
val builtIns = JvmBuiltIns(projectContext.storageManager, JvmBuiltIns.Kind.FROM_DEPENDENCIES)
|
||||
return ContextForNewModule(
|
||||
projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, null
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.cli.metadata
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
@@ -68,7 +68,7 @@ open class MetadataSerializer(
|
||||
|
||||
val analyzer = AnalyzerWithCompilerReport(messageCollector, configuration.languageVersionSettings)
|
||||
analyzer.analyzeAndReport(files) {
|
||||
CommonAnalyzerFacade.analyzeFiles(files, moduleName, dependOnOldBuiltIns, configuration.languageVersionSettings) { content ->
|
||||
CommonResolverForModuleFactory.analyzeFiles(files, moduleName, dependOnOldBuiltIns, configuration.languageVersionSettings) { content ->
|
||||
environment.createPackagePartProvider(content.moduleContentScope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,11 @@ class StorageComponentContainer(
|
||||
return this
|
||||
}
|
||||
|
||||
internal fun registerClashResolvers(resolvers: List<PlatformExtensionsClashResolver<*>>): StorageComponentContainer {
|
||||
componentStorage.registerClashResolvers(resolvers)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <T> create(request: Class<T>): T {
|
||||
val constructorBinding = request.bindToConstructor(unknownContext)
|
||||
val args = constructorBinding.argumentDescriptors.map { it.getValue() }.toTypedArray()
|
||||
|
||||
@@ -46,6 +46,14 @@ fun StorageComponentContainer.useInstance(instance: Any) {
|
||||
registerInstance(instance)
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.useInstanceIfNotNull(instance: Any?) {
|
||||
if (instance != null) registerInstance(instance)
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.useClashResolver(clashResolver: PlatformExtensionsClashResolver<*>) {
|
||||
registerClashResolvers(listOf(clashResolver))
|
||||
}
|
||||
|
||||
inline operator fun <reified T : Any> ComponentProvider.getValue(thisRef: Any?, desc: KProperty<*>): T {
|
||||
return getService(T::class.java)
|
||||
}
|
||||
|
||||
@@ -70,4 +70,20 @@ internal class ComponentRegistry {
|
||||
}
|
||||
registrationMap += other.registrationMap
|
||||
}
|
||||
|
||||
fun resolveClashesIfAny(container: ComponentContainer, clashResolvers: List<PlatformExtensionsClashResolver<*>>) {
|
||||
/*
|
||||
The idea is to create descriptor, which is very similar to other SingletonDescriptor, but instead of calling
|
||||
constructor we call 'resolveExtensionsClash' with values of clashed components as arguments.
|
||||
|
||||
By mimicking the usual descriptors we get lazy evaluation and consistency checks for free.
|
||||
*/
|
||||
for (resolver in clashResolvers) {
|
||||
val clashedComponents = registrationMap[resolver.applicableTo] as? Collection<ComponentDescriptor> ?: continue
|
||||
if (clashedComponents.isEmpty()) continue // Shouldn't actually happen, but just in case
|
||||
|
||||
val substituteDescriptor = ClashResolutionDescriptor(container, resolver, clashedComponents.toList())
|
||||
registrationMap[resolver.applicableTo] = substituteDescriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.container
|
||||
|
||||
import java.io.Closeable
|
||||
import java.lang.IllegalStateException
|
||||
import java.lang.reflect.Type
|
||||
import java.util.*
|
||||
|
||||
@@ -144,6 +145,29 @@ open class SingletonTypeComponentDescriptor(container: ComponentContainer, val k
|
||||
override fun toString(): String = "Singleton: ${klass.simpleName}"
|
||||
}
|
||||
|
||||
internal class ClashResolutionDescriptor<E : PlatformSpecificExtension<E>>(
|
||||
container: ComponentContainer,
|
||||
private val resolver: PlatformExtensionsClashResolver<E>,
|
||||
private val clashedComponents: List<ComponentDescriptor>
|
||||
) : SingletonDescriptor(container) {
|
||||
|
||||
override fun createInstance(context: ValueResolveContext): Any {
|
||||
state = ComponentState.Initializing
|
||||
val extensions = computeArguments(clashedComponents) as List<E>
|
||||
val resolution = resolver.resolveExtensionsClash(extensions)
|
||||
state = ComponentState.Initialized
|
||||
return resolution
|
||||
}
|
||||
|
||||
override fun getRegistrations(): Iterable<Type> {
|
||||
throw IllegalStateException("Shouldn't be called")
|
||||
}
|
||||
|
||||
override fun getDependencies(context: ValueResolveContext): Collection<Type> {
|
||||
throw IllegalStateException("Shouldn't be called")
|
||||
}
|
||||
}
|
||||
|
||||
class ImplicitSingletonTypeComponentDescriptor(container: ComponentContainer, klass: Class<*>) : SingletonTypeComponentDescriptor(container, klass) {
|
||||
override fun toString(): String {
|
||||
return "Implicit: ${klass.simpleName}"
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.container
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import java.io.Closeable
|
||||
import java.io.PrintStream
|
||||
import java.lang.IllegalStateException
|
||||
import java.lang.reflect.Modifier
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
@@ -33,19 +34,26 @@ enum class ComponentStorageState {
|
||||
Disposed
|
||||
}
|
||||
|
||||
internal class InvalidCardinalityException(message: String, val descriptors: Collection<ComponentDescriptor>) : Exception(message)
|
||||
internal class InvalidCardinalityException(message: String) : Exception(message)
|
||||
|
||||
class ComponentStorage(private val myId: String, parent: ComponentStorage?) : ValueResolver {
|
||||
var state = ComponentStorageState.Initial
|
||||
private val registry = ComponentRegistry()
|
||||
init {
|
||||
parent?.let { registry.addAll(it.registry) }
|
||||
}
|
||||
|
||||
private val descriptors = LinkedHashSet<ComponentDescriptor>()
|
||||
private val dependencies = MultiMap.createLinkedSet<ComponentDescriptor, Type>()
|
||||
private val clashResolvers = ArrayList<PlatformExtensionsClashResolver<*>>()
|
||||
private val registry = ComponentRegistry()
|
||||
|
||||
init {
|
||||
parent?.let { registry.addAll(it.registry) }
|
||||
parent?.let { clashResolvers.addAll(it.clashResolvers) }
|
||||
}
|
||||
|
||||
|
||||
override fun resolve(request: Type, context: ValueResolveContext): ValueDescriptor? {
|
||||
fun ComponentDescriptor.isDefaultComponent(): Boolean =
|
||||
this is DefaultInstanceComponentDescriptor || this is DefaultSingletonTypeComponentDescriptor
|
||||
|
||||
if (state == ComponentStorageState.Initial)
|
||||
throw ContainerConsistencyException("Container was not composed before resolving")
|
||||
|
||||
@@ -53,9 +61,24 @@ class ComponentStorage(private val myId: String, parent: ComponentStorage?) : Va
|
||||
if (entry.isNotEmpty()) {
|
||||
registerDependency(request, context)
|
||||
|
||||
if (entry.size > 1)
|
||||
throw InvalidCardinalityException("Request $request cannot be satisfied because there is more than one type registered", entry)
|
||||
return entry.singleOrNull()
|
||||
return when {
|
||||
// Fastpath
|
||||
entry.size == 1 -> {
|
||||
entry.single()
|
||||
}
|
||||
|
||||
entry.all { it.isDefaultComponent() } -> {
|
||||
entry.first()
|
||||
}
|
||||
|
||||
else -> {
|
||||
entry.singleOrNull { !it.isDefaultComponent() }
|
||||
?: throw InvalidCardinalityException(
|
||||
"Request $request cannot be satisfied because there is more than one type registered\n" +
|
||||
"Clashed registrations: ${entry.filter { !it.isDefaultComponent() }.joinToString()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -97,6 +120,10 @@ class ComponentStorage(private val myId: String, parent: ComponentStorage?) : Va
|
||||
return registry.tryGetEntry(request)
|
||||
}
|
||||
|
||||
internal fun registerClashResolvers(resolvers: List<PlatformExtensionsClashResolver<*>>) {
|
||||
clashResolvers.addAll(resolvers)
|
||||
}
|
||||
|
||||
internal fun registerDescriptors(context: ComponentResolveContext, items: List<ComponentDescriptor>) {
|
||||
if (state == ComponentStorageState.Disposed) {
|
||||
throw ContainerConsistencyException("Cannot register descriptors in $state state")
|
||||
@@ -125,6 +152,7 @@ class ComponentStorage(private val myId: String, parent: ComponentStorage?) : Va
|
||||
|
||||
val implicits = inspectDependenciesAndRegisterAdhoc(context, descriptors)
|
||||
|
||||
registry.resolveClashesIfAny(context.container, clashResolvers)
|
||||
injectProperties(context, descriptors + implicits)
|
||||
}
|
||||
|
||||
@@ -150,7 +178,13 @@ class ComponentStorage(private val myId: String, parent: ComponentStorage?) : Va
|
||||
visitedTypes: HashSet<Type>, adhocDescriptors: LinkedHashSet<ComponentDescriptor>
|
||||
) {
|
||||
val dependencies = descriptor.getDependencies(context)
|
||||
if (descriptor.toString().contains("DescriptorResolver")) {
|
||||
println("gotcha")
|
||||
}
|
||||
for (type in dependencies) {
|
||||
if (type.toString().contains("DeclarationReturnTypeSanitizer")) {
|
||||
println("gotcha")
|
||||
}
|
||||
if (!visitedTypes.add(type))
|
||||
continue
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
class FirModuleDescriptor(val session: FirSession) : ModuleDescriptor {
|
||||
override val builtIns: KotlinBuiltIns
|
||||
@@ -25,6 +27,9 @@ class FirModuleDescriptor(val session: FirSession) : ModuleDescriptor {
|
||||
return false
|
||||
}
|
||||
|
||||
override val platform: TargetPlatform?
|
||||
get() = JvmPlatforms.jvm18 // TODO(dsavvinov): provide proper platform
|
||||
|
||||
override fun getPackage(fqName: FqName): PackageViewDescriptor {
|
||||
val symbolProvider = FirSymbolProvider.getInstance(session)
|
||||
if (symbolProvider.getPackage(fqName) != null) {
|
||||
|
||||
@@ -18,7 +18,7 @@ class FirDefaultSimpleImportingScope(session: FirSession) : FirAbstractSimpleImp
|
||||
|
||||
override val simpleImports = run {
|
||||
val importResolveTransformer = FirImportResolveTransformer(session)
|
||||
session.moduleInfo?.platform?.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT, true)
|
||||
session.moduleInfo?.compilerServices?.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT, true)
|
||||
?.filter { !it.isAllUnder }
|
||||
?.map {
|
||||
FirImportImpl(session, null, it.fqName, isAllUnder = false, aliasName = null)
|
||||
|
||||
@@ -14,7 +14,7 @@ class FirDefaultStarImportingScope(session: FirSession, lookupInFir: Boolean = f
|
||||
FirAbstractStarImportingScope(session, lookupInFir) {
|
||||
|
||||
// TODO: put languageVersionSettings into FirSession?
|
||||
override val starImports = session.moduleInfo?.platform?.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT, true)
|
||||
override val starImports = session.moduleInfo?.compilerServices?.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT, true)
|
||||
?.filter { it.isAllUnder }
|
||||
?.map {
|
||||
FirResolvedImportImpl(
|
||||
|
||||
@@ -22,10 +22,15 @@ import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentCompilerServices
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformCompilerServices
|
||||
import java.io.File
|
||||
import java.lang.IllegalStateException
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
@@ -128,21 +133,27 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
private val builtInsModuleInfo = BuiltInModuleInfo(Name.special("<built-ins>"))
|
||||
|
||||
protected open fun createModule(moduleName: String): TestModuleInfo {
|
||||
val nameSuffix = moduleName.substringAfterLast("-", "")
|
||||
val nameSuffix = moduleName.substringAfterLast("-", "").toUpperCase()
|
||||
// TODO: use platform
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
@Suppress("UNUSED_VARIBALE")
|
||||
val platform =
|
||||
when {
|
||||
nameSuffix.isEmpty() -> null
|
||||
nameSuffix == "common" -> MultiTargetPlatform.Common
|
||||
else -> MultiTargetPlatform.Specific(nameSuffix.toUpperCase())
|
||||
nameSuffix.isEmpty() -> null // TODO(dsavvinov): this leads to 'null'-platform in ModuleDescriptor
|
||||
nameSuffix == "COMMON" -> CommonPlatforms.defaultCommonPlatform
|
||||
nameSuffix == "JVM" -> JvmPlatforms.defaultJvmPlatform // TODO(dsavvinov): determine JvmTarget precisely
|
||||
nameSuffix == "JS" -> JsPlatforms.defaultJsPlatform
|
||||
nameSuffix == "NATIVE" -> KonanPlatforms.defaultKonanPlatform
|
||||
else -> throw IllegalStateException("Can't determine platform by name $nameSuffix")
|
||||
}
|
||||
return TestModuleInfo(Name.special("<$moduleName>"))
|
||||
}
|
||||
|
||||
class BuiltInModuleInfo(override val name: Name) : ModuleInfo {
|
||||
override val platform: TargetPlatform?
|
||||
get() = JvmPlatform
|
||||
override val platform: TargetPlatform
|
||||
get() = JvmPlatforms.defaultJvmPlatform
|
||||
|
||||
override val compilerServices: PlatformDependentCompilerServices
|
||||
get() = JvmPlatformCompilerServices
|
||||
|
||||
override fun dependencies(): List<ModuleInfo> {
|
||||
return listOf(this)
|
||||
@@ -150,8 +161,11 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
}
|
||||
|
||||
protected class TestModuleInfo(override val name: Name) : ModuleInfo {
|
||||
override val platform: TargetPlatform?
|
||||
get() = JvmPlatform
|
||||
override val platform: TargetPlatform
|
||||
get() = JvmPlatforms.defaultJvmPlatform
|
||||
|
||||
override val compilerServices: PlatformDependentCompilerServices
|
||||
get() = JvmPlatformCompilerServices
|
||||
|
||||
val dependencies = mutableListOf<ModuleInfo>(this)
|
||||
override fun dependencies(): List<ModuleInfo> {
|
||||
@@ -160,7 +174,7 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
|
||||
}
|
||||
|
||||
protected open fun createSealedModule(): TestModuleInfo =
|
||||
createModule("test-module").apply {
|
||||
createModule("test-module-jvm").apply {
|
||||
dependencies += builtInsModuleInfo
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ package org.jetbrains.kotlin.analyzer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentCompilerServices
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
|
||||
interface ModuleInfo {
|
||||
@@ -15,7 +16,8 @@ interface ModuleInfo {
|
||||
val displayedName: String get() = name.asString()
|
||||
fun dependencies(): List<ModuleInfo>
|
||||
val expectedBy: List<ModuleInfo> get() = emptyList()
|
||||
val platform: TargetPlatform? get() = null
|
||||
val platform: TargetPlatform
|
||||
val compilerServices: PlatformDependentCompilerServices
|
||||
fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> = listOf()
|
||||
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
get() = mapOf(Capability to this)
|
||||
@@ -28,7 +30,7 @@ interface ModuleInfo {
|
||||
// but if they are present, they should come after JVM built-ins in the dependencies list, because JVM built-ins contain
|
||||
// additional members dependent on the JDK
|
||||
fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns =
|
||||
platform?.dependencyOnBuiltIns() ?: ModuleInfo.DependencyOnBuiltIns.LAST
|
||||
compilerServices?.dependencyOnBuiltIns() ?: ModuleInfo.DependencyOnBuiltIns.LAST
|
||||
|
||||
//TODO: (module refactoring) provide dependency on builtins after runtime in IDEA
|
||||
enum class DependencyOnBuiltIns { NONE, AFTER_SDK, LAST }
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
|
||||
interface PlatformConfigurator {
|
||||
val platformSpecificContainer: StorageComponentContainer
|
||||
fun configureModuleComponents(container: StorageComponentContainer)
|
||||
fun configureModuleDependentCheckers(container: StorageComponentContainer)
|
||||
}
|
||||
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.util.*
|
||||
import java.util.ArrayList
|
||||
|
||||
abstract class TargetPlatform(val platformName: String) {
|
||||
abstract class PlatformDependentCompilerServices {
|
||||
private data class DefaultImportsKey(val includeKotlinComparisons: Boolean, val includeLowPriorityImports: Boolean)
|
||||
|
||||
private val defaultImports = LockBasedStorageManager("TargetPlatform").let { storageManager ->
|
||||
@@ -42,8 +41,6 @@ abstract class TargetPlatform(val platformName: String) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = platformName
|
||||
|
||||
abstract val platformConfigurator: PlatformConfigurator
|
||||
|
||||
open val defaultLowPriorityImports: List<ImportPath> get() = emptyList()
|
||||
@@ -56,28 +53,24 @@ abstract class TargetPlatform(val platformName: String) {
|
||||
)
|
||||
)
|
||||
|
||||
protected abstract fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>)
|
||||
abstract fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>)
|
||||
|
||||
open val excludedImports: List<FqName> get() = emptyList()
|
||||
|
||||
abstract val multiTargetPlatform: MultiTargetPlatform
|
||||
|
||||
// This function is used in "cat.helm.clean:0.1.1-SNAPSHOT": https://plugins.jetbrains.com/plugin/index?xmlId=cat.helm.clean
|
||||
@Suppress("DeprecatedCallableAddReplaceWith", "unused")
|
||||
@Deprecated("Use getDefaultImports(LanguageVersionSettings, Boolean) instead.", level = DeprecationLevel.ERROR)
|
||||
fun getDefaultImports(includeKotlinComparisons: Boolean): List<ImportPath> {
|
||||
return getDefaultImports(
|
||||
if (includeKotlinComparisons) LanguageVersionSettingsImpl.DEFAULT
|
||||
else LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_0, ApiVersion.KOTLIN_1_0),
|
||||
else LanguageVersionSettingsImpl(
|
||||
LanguageVersion.KOTLIN_1_0,
|
||||
ApiVersion.KOTLIN_1_0
|
||||
),
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
open fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns = ModuleInfo.DependencyOnBuiltIns.LAST
|
||||
}
|
||||
|
||||
interface PlatformConfigurator {
|
||||
val platformSpecificContainer: StorageComponentContainer
|
||||
fun configureModuleComponents(container: StorageComponentContainer)
|
||||
fun configureModuleDependentCheckers(container: StorageComponentContainer)
|
||||
}
|
||||
open fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns =
|
||||
ModuleInfo.DependencyOnBuiltIns.LAST
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.config
|
||||
|
||||
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
enum class JvmTarget(override val description: String) : TargetPlatformVersion {
|
||||
|
||||
@@ -16,19 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.frontend.java.di
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.config.JvmAnalysisFlags
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.*
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
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.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder
|
||||
@@ -41,77 +40,85 @@ import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
|
||||
import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
|
||||
private fun StorageComponentContainer.configureJavaTopDownAnalysis(
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
project: Project,
|
||||
lookupTracker: LookupTracker,
|
||||
expectActualTracker: ExpectActualTracker
|
||||
) {
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(lookupTracker)
|
||||
useInstance(expectActualTracker)
|
||||
useImpl<ResolveSession>()
|
||||
fun createContainerForLazyResolveWithJava(
|
||||
jvmPlatform: TargetPlatform,
|
||||
moduleContext: ModuleContext,
|
||||
bindingTrace: BindingTrace,
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
moduleClassResolver: ModuleClassResolver,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
lookupTracker: LookupTracker,
|
||||
expectActualTracker: ExpectActualTracker,
|
||||
packagePartProvider: PackagePartProvider,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
useBuiltInsProvider: Boolean,
|
||||
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)? = null,
|
||||
javaClassTracker: JavaClassesTracker? = null
|
||||
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatformCompilerServices) {
|
||||
configureModule(moduleContext, jvmPlatform, JvmPlatformCompilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
configureIncrementalCompilation(lookupTracker, expectActualTracker)
|
||||
configureStandardResolveComponents()
|
||||
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(packagePartProvider)
|
||||
useInstance(declarationProviderFactory)
|
||||
|
||||
useInstance(VirtualFileFinderFactory.getInstance(moduleContext.project).create(moduleContentScope))
|
||||
|
||||
configureJavaSpecificComponents(
|
||||
moduleContext, moduleClassResolver, languageVersionSettings, configureJavaClassFinder,
|
||||
javaClassTracker, useBuiltInsProvider
|
||||
)
|
||||
|
||||
targetEnvironment.configure(this)
|
||||
|
||||
}.apply {
|
||||
initializeJavaSpecificComponents(bindingTrace)
|
||||
}
|
||||
|
||||
// FIXME(dsavvinov): get rid of that
|
||||
fun StorageComponentContainer.initializeJavaSpecificComponents(bindingTrace: BindingTrace) {
|
||||
get<AbstractJavaClassFinder>().initialize(bindingTrace, get<KotlinCodeAnalyzer>())
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.configureJavaSpecificComponents(
|
||||
moduleContext: ModuleContext,
|
||||
moduleClassResolver: ModuleClassResolver,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)?,
|
||||
javaClassTracker: JavaClassesTracker?,
|
||||
useBuiltInsProvider: Boolean
|
||||
) {
|
||||
useImpl<JavaDescriptorResolver>()
|
||||
useImpl<DeserializationComponentsForJava>()
|
||||
|
||||
useInstance(VirtualFileFinderFactory.getInstance(project).create(moduleContentScope))
|
||||
|
||||
useInstance(JavaPropertyInitializerEvaluatorImpl)
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<SignaturePropagatorImpl>()
|
||||
useImpl<TraceBasedErrorReporter>()
|
||||
useInstance(InternalFlexibleTypeTransformer)
|
||||
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
|
||||
useInstance(JavaDeprecationSettings)
|
||||
}
|
||||
|
||||
fun createContainerForLazyResolveWithJava(
|
||||
moduleContext: ModuleContext,
|
||||
bindingTrace: BindingTrace,
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
moduleClassResolver: ModuleClassResolver,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
lookupTracker: LookupTracker,
|
||||
expectActualTracker: ExpectActualTracker,
|
||||
packagePartProvider: PackagePartProvider,
|
||||
jvmTarget: JvmTarget,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
useBuiltInsProvider: Boolean,
|
||||
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)? = null,
|
||||
javaClassTracker: JavaClassesTracker? = null
|
||||
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatform) {
|
||||
configureModule(moduleContext, JvmPlatform, jvmTarget, bindingTrace)
|
||||
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker, expectActualTracker)
|
||||
useInstance(moduleClassResolver)
|
||||
|
||||
// configureJavaClassFinder != null <=> javac integration is enabled
|
||||
if (configureJavaClassFinder != null) {
|
||||
configureJavaClassFinder()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
useImpl<JavaClassFinderImpl>()
|
||||
useImpl<LazyResolveBasedCache>()
|
||||
useImpl<JavaSourceElementFactoryImpl>()
|
||||
}
|
||||
|
||||
useInstance(packagePartProvider)
|
||||
useInstance(moduleClassResolver)
|
||||
useInstance(declarationProviderFactory)
|
||||
|
||||
useInstance(languageVersionSettings)
|
||||
|
||||
useInstance(languageVersionSettings.getFlag(JvmAnalysisFlags.jsr305))
|
||||
|
||||
// Currently, false in IDE environment (ideally, should be true everywhere)
|
||||
if (useBuiltInsProvider) {
|
||||
useInstance((moduleContext.module.builtIns as JvmBuiltIns).settings)
|
||||
useImpl<JvmBuiltInsPackageFragmentProvider>()
|
||||
@@ -122,38 +129,9 @@ fun createContainerForLazyResolveWithJava(
|
||||
JavaResolverSettings.create(isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
|
||||
)
|
||||
|
||||
targetEnvironment.configure(this)
|
||||
|
||||
useImpl<ContractDeserializerImpl>()
|
||||
useImpl<FilesByFacadeFqNameIndexer>()
|
||||
}.apply {
|
||||
get<AbstractJavaClassFinder>().initialize(bindingTrace, get<KotlinCodeAnalyzer>())
|
||||
}
|
||||
|
||||
|
||||
fun createContainerForTopDownAnalyzerForJvm(
|
||||
moduleContext: ModuleContext,
|
||||
bindingTrace: BindingTrace,
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
lookupTracker: LookupTracker,
|
||||
expectActualTracker: ExpectActualTracker,
|
||||
packagePartProvider: PackagePartProvider,
|
||||
moduleClassResolver: ModuleClassResolver,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
jvmTarget: JvmTarget,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)? = null,
|
||||
javaClassTracker: JavaClassesTracker? = null
|
||||
): ComponentProvider = createContainerForLazyResolveWithJava(
|
||||
moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver,
|
||||
targetEnvironment, lookupTracker, expectActualTracker, packagePartProvider, jvmTarget, languageVersionSettings,
|
||||
useBuiltInsProvider = true,
|
||||
configureJavaClassFinder = configureJavaClassFinder,
|
||||
javaClassTracker = javaClassTracker
|
||||
)
|
||||
|
||||
|
||||
fun ComponentProvider.initJvmBuiltInsForTopDownAnalysis() {
|
||||
get<JvmBuiltIns>().initialize(get<ModuleDescriptor>(), get<LanguageVersionSettings>())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.platform.jvm
|
||||
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.platform.SimplePlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.toTargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
||||
|
||||
abstract class JvmPlatform : SimplePlatform("JVM") {
|
||||
override val oldFashionedDescription: String
|
||||
get() = "JVM "
|
||||
}
|
||||
|
||||
object JvmPlatforms {
|
||||
private val jvmTargetToJdkPlatform: Map<JvmTarget, TargetPlatform> =
|
||||
JvmTarget.values().map { it to JdkPlatform(it).toTargetPlatform() }.toMap()
|
||||
|
||||
val defaultJvmPlatform: TargetPlatform = JdkPlatform(JvmTarget.DEFAULT).toTargetPlatform()
|
||||
|
||||
val jvm16: TargetPlatform = jvmTargetToJdkPlatform[JvmTarget.JVM_1_6]!!
|
||||
val jvm18: TargetPlatform = JdkPlatform(JvmTarget.JVM_1_8).toTargetPlatform()
|
||||
|
||||
fun jvmPlatformByTargetVersion(targetVersion: JvmTarget) = jvmTargetToJdkPlatform[targetVersion]!!
|
||||
|
||||
val allJvmPlatforms: List<TargetPlatform> = jvmTargetToJdkPlatform.values.toList()
|
||||
}
|
||||
|
||||
data class JdkPlatform(val targetVersion: JvmTarget) : JvmPlatform() {
|
||||
override fun toString(): String = "$platformName ($targetVersion)"
|
||||
|
||||
override val oldFashionedDescription: String
|
||||
get() = "JVM " + targetVersion.description
|
||||
|
||||
override val targetPlatformVersion: TargetPlatformVersion
|
||||
get() = targetVersion
|
||||
}
|
||||
|
||||
fun TargetPlatform?.isJvm(): Boolean = this?.singleOrNull() is JvmPlatform
|
||||
@@ -17,9 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.*
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
@@ -30,11 +28,12 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolverImpl
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
|
||||
@@ -44,16 +43,17 @@ class JvmPlatformParameters(
|
||||
) : PlatformAnalysisParameters
|
||||
|
||||
|
||||
object JvmAnalyzerFacade : ResolverForModuleFactory() {
|
||||
class JvmResolverForModuleFactory(
|
||||
private val platformParameters: JvmPlatformParameters,
|
||||
private val targetEnvironment: TargetEnvironment,
|
||||
private val platform: TargetPlatform
|
||||
) : ResolverForModuleFactory() {
|
||||
override fun <M : ModuleInfo> createResolverForModule(
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
moduleContext: ModuleContext,
|
||||
moduleContent: ModuleContent<M>,
|
||||
platformParameters: PlatformAnalysisParameters,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
resolverForProject: ResolverForProject<M>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
targetPlatformVersion: TargetPlatformVersion
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): ResolverForModule {
|
||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||
val project = moduleContext.project
|
||||
@@ -73,7 +73,7 @@ object JvmAnalyzerFacade : ResolverForModuleFactory() {
|
||||
val resolverForReferencedModule = referencedClassModule?.let { resolverForProject.tryGetResolverForModule(it as M) }
|
||||
|
||||
val resolverForModule = resolverForReferencedModule?.takeIf {
|
||||
referencedClassModule.platform == JvmPlatform || referencedClassModule.platform == null
|
||||
referencedClassModule.platform.isJvm() || referencedClassModule.platform == null
|
||||
} ?: run {
|
||||
// in case referenced class lies outside of our resolver, resolve the class as if it is inside our module
|
||||
// this leads to java class being resolved several times
|
||||
@@ -82,12 +82,12 @@ object JvmAnalyzerFacade : ResolverForModuleFactory() {
|
||||
resolverForModule.componentProvider.get<JavaDescriptorResolver>()
|
||||
}
|
||||
|
||||
val jvmTarget = targetPlatformVersion as? JvmTarget ?: JvmTarget.DEFAULT
|
||||
val trace = CodeAnalyzerInitializer.getInstance(project).createTrace()
|
||||
|
||||
val lookupTracker = LookupTracker.DO_NOTHING
|
||||
val packagePartProvider = (platformParameters as JvmPlatformParameters).packagePartProviderFactory(moduleContent)
|
||||
val container = createContainerForLazyResolveWithJava(
|
||||
moduleDescriptor.platform!!,
|
||||
moduleContext,
|
||||
trace,
|
||||
declarationProviderFactory,
|
||||
@@ -97,7 +97,6 @@ object JvmAnalyzerFacade : ResolverForModuleFactory() {
|
||||
lookupTracker,
|
||||
ExpectActualTracker.DoNothing,
|
||||
packagePartProvider,
|
||||
jvmTarget,
|
||||
languageVersionSettings,
|
||||
useBuiltInsProvider = false // TODO: load built-ins from module dependencies in IDE
|
||||
)
|
||||
@@ -120,7 +119,4 @@ object JvmAnalyzerFacade : ResolverForModuleFactory() {
|
||||
|
||||
return ResolverForModule(CompositePackageFragmentProvider(providersForModule), container)
|
||||
}
|
||||
|
||||
override val targetPlatform: TargetPlatform
|
||||
get() = JvmPlatform
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
object JvmPlatform : TargetPlatform("JVM") {
|
||||
object JvmPlatformCompilerServices : PlatformDependentCompilerServices() {
|
||||
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {
|
||||
result.add(ImportPath.fromString("kotlin.jvm.*"))
|
||||
|
||||
@@ -40,6 +40,4 @@ object JvmPlatform : TargetPlatform("JVM") {
|
||||
override val defaultLowPriorityImports: List<ImportPath> = listOf(ImportPath.fromString("java.lang.*"))
|
||||
|
||||
override val platformConfigurator: PlatformConfigurator = JvmPlatformConfigurator
|
||||
|
||||
override val multiTargetPlatform = MultiTargetPlatform.Specific(platformName)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.load.java.components.SamConversionResolverClashesResolver
|
||||
import org.jetbrains.kotlin.load.java.sam.JvmSamConversionTransformer
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConversionResolverImpl
|
||||
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
|
||||
@@ -22,7 +23,6 @@ import org.jetbrains.kotlin.types.DynamicTypesSettings
|
||||
import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport
|
||||
|
||||
object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
DynamicTypesSettings(),
|
||||
additionalDeclarationCheckers = listOf(
|
||||
JvmNameAnnotationChecker(),
|
||||
VolatileAnnotationChecker(),
|
||||
@@ -34,7 +34,6 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
TypeParameterBoundIsNotArrayChecker(),
|
||||
JvmSyntheticApplicabilityChecker(),
|
||||
StrictfpApplicabilityChecker(),
|
||||
ExpectedActualDeclarationChecker(listOf(JavaActualAnnotationArgumentExtractor())),
|
||||
JvmAnnotationsTargetNonExistentAccessorChecker(),
|
||||
BadInheritedJavaSignaturesChecker,
|
||||
JvmMultifileClassStateChecker,
|
||||
@@ -74,6 +73,10 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
ExplicitMetadataChecker
|
||||
),
|
||||
|
||||
additionalClashResolvers = listOf(
|
||||
SamConversionResolverClashesResolver()
|
||||
),
|
||||
|
||||
identifierChecker = JvmSimpleNameBacktickChecker,
|
||||
|
||||
overloadFilter = JvmOverloadFilter,
|
||||
@@ -100,5 +103,11 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
container.useImpl<JvmDefaultSuperCallChecker>()
|
||||
container.useImpl<JvmSamConversionTransformer>()
|
||||
container.useInstance(FunctionWithBigAritySupport.LANGUAGE_VERSION_DEPENDENT)
|
||||
container.useInstance(JavaActualAnnotationArgumentExtractor())
|
||||
}
|
||||
|
||||
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
|
||||
super.configureModuleDependentCheckers(container)
|
||||
container.useImpl<ExpectedActualDeclarationChecker>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.config.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
@@ -37,10 +36,10 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDependencies
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import java.util.*
|
||||
@@ -90,12 +89,10 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
|
||||
class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
private val debugName: String,
|
||||
private val projectContext: ProjectContext,
|
||||
modules: Collection<M>,
|
||||
private val modulesFromThisResolver: Collection<M>,
|
||||
private val modulesContent: (M) -> ModuleContent<M>,
|
||||
private val moduleLanguageSettingsProvider: LanguageSettingsProvider,
|
||||
private val resolverForModuleFactoryByPlatform: (TargetPlatform?) -> ResolverForModuleFactory,
|
||||
private val platformParameters: (TargetPlatform) -> PlatformAnalysisParameters,
|
||||
private val targetEnvironment: TargetEnvironment = CompilerEnvironment,
|
||||
override val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance,
|
||||
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||
private val firstDependency: M? = null,
|
||||
@@ -121,14 +118,6 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
// Protected by ("projectContext.storageManager.lock")
|
||||
private val moduleInfoByDescriptor = mutableMapOf<ModuleDescriptorImpl, M>()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val moduleInfoToResolvableInfo: Map<M, M> =
|
||||
modules.flatMap { module -> module.flatten().map { modulePart -> modulePart to module } }.toMap() as Map<M, M>
|
||||
|
||||
init {
|
||||
assert(moduleInfoToResolvableInfo.values.toSet() == modules.toSet())
|
||||
}
|
||||
|
||||
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? {
|
||||
if (!isCorrectModuleInfo(moduleInfo)) {
|
||||
return null
|
||||
@@ -159,7 +148,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
private val resolverByModuleDescriptor = mutableMapOf<ModuleDescriptor, ResolverForModule>()
|
||||
|
||||
override val allModules: Collection<M> by lazy {
|
||||
this.moduleInfoToResolvableInfo.keys + delegateResolver.allModules
|
||||
modulesFromThisResolver + delegateResolver.allModules
|
||||
}
|
||||
|
||||
override val name: String
|
||||
@@ -182,21 +171,20 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
|
||||
|
||||
val moduleContent = modulesContent(module)
|
||||
val resolverForModuleFactory = resolverForModuleFactoryByPlatform(module.platform)
|
||||
|
||||
val languageVersionSettings =
|
||||
moduleLanguageSettingsProvider.getLanguageVersionSettings(module, projectContext.project, isReleaseCoroutines)
|
||||
|
||||
// FIXME(dsavvinov): make sure that module.platform returns platform with the same JvmTarget as this one
|
||||
val targetPlatformVersion = moduleLanguageSettingsProvider.getTargetPlatform(module, projectContext.project)
|
||||
|
||||
val resolverForModuleFactory = resolverForModuleFactoryByPlatform(module.platform)
|
||||
resolverForModuleFactory.createResolverForModule(
|
||||
descriptor as ModuleDescriptorImpl,
|
||||
projectContext.withModule(descriptor),
|
||||
moduleContent,
|
||||
platformParameters(resolverForModuleFactory.targetPlatform),
|
||||
targetEnvironment,
|
||||
this@ResolverForProjectImpl,
|
||||
languageVersionSettings,
|
||||
targetPlatformVersion
|
||||
languageVersionSettings
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -223,9 +211,8 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
}
|
||||
|
||||
private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl {
|
||||
val moduleFromThisResolver = moduleInfoToResolvableInfo[module]
|
||||
val moduleFromThisResolver = module.takeIf { it in modulesFromThisResolver }
|
||||
?: return delegateResolver.descriptorForModule(module) as ModuleDescriptorImpl
|
||||
|
||||
return projectContext.storageManager.compute {
|
||||
var moduleData = descriptorByModule.getOrPut(moduleFromThisResolver) {
|
||||
createModuleDescriptor(moduleFromThisResolver)
|
||||
@@ -255,7 +242,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
module.name,
|
||||
projectContext.storageManager,
|
||||
builtIns,
|
||||
module.platform?.multiTargetPlatform,
|
||||
module.platform,
|
||||
module.capabilities,
|
||||
module.stableName
|
||||
)
|
||||
@@ -277,15 +264,6 @@ interface PlatformAnalysisParameters {
|
||||
object Empty : PlatformAnalysisParameters
|
||||
}
|
||||
|
||||
interface CombinedModuleInfo : ModuleInfo {
|
||||
val containedModules: List<ModuleInfo>
|
||||
}
|
||||
|
||||
fun ModuleInfo.flatten(): List<ModuleInfo> = when (this) {
|
||||
is CombinedModuleInfo -> listOf(this) + containedModules
|
||||
else -> listOf(this)
|
||||
}
|
||||
|
||||
interface TrackableModuleInfo : ModuleInfo {
|
||||
fun createModificationTracker(): ModificationTracker
|
||||
}
|
||||
@@ -301,14 +279,9 @@ abstract class ResolverForModuleFactory {
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
moduleContext: ModuleContext,
|
||||
moduleContent: ModuleContent<M>,
|
||||
platformParameters: PlatformAnalysisParameters,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
resolverForProject: ResolverForProject<M>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
targetPlatformVersion: TargetPlatformVersion
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): ResolverForModule
|
||||
|
||||
abstract val targetPlatform: TargetPlatform
|
||||
}
|
||||
|
||||
class LazyModuleDependencies<M : ModuleInfo>(
|
||||
@@ -405,12 +378,6 @@ interface LanguageSettingsProvider {
|
||||
isReleaseCoroutines: Boolean? = null
|
||||
): LanguageVersionSettings
|
||||
|
||||
@Deprecated("Use `getLanguageVersionSettings` method with default parameter instead", level = DeprecationLevel.HIDDEN)
|
||||
fun getLanguageVersionSettings(
|
||||
moduleInfo: ModuleInfo,
|
||||
project: Project
|
||||
) = getLanguageVersionSettings(moduleInfo, project, null)
|
||||
|
||||
fun getTargetPlatform(moduleInfo: ModuleInfo, project: Project): TargetPlatformVersion
|
||||
|
||||
object Default : LanguageSettingsProvider {
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* 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.analyzer.common
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
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
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||
|
||||
class CommonAnalysisParameters(
|
||||
val metadataPartProviderFactory: (ModuleContent<*>) -> MetadataPartProvider
|
||||
) : PlatformAnalysisParameters
|
||||
|
||||
/**
|
||||
* A facade that is used to analyze common (platform-independent) modules in multi-platform projects.
|
||||
* See [CommonPlatform]
|
||||
*/
|
||||
object CommonAnalyzerFacade : ResolverForModuleFactory() {
|
||||
private class SourceModuleInfo(
|
||||
override val name: Name,
|
||||
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>,
|
||||
private val dependOnOldBuiltIns: Boolean
|
||||
) : ModuleInfo {
|
||||
override fun dependencies() = listOf(this)
|
||||
|
||||
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns =
|
||||
if (dependOnOldBuiltIns) ModuleInfo.DependencyOnBuiltIns.LAST else ModuleInfo.DependencyOnBuiltIns.NONE
|
||||
}
|
||||
|
||||
fun analyzeFiles(
|
||||
files: Collection<KtFile>, moduleName: Name, dependOnBuiltIns: Boolean, languageVersionSettings: LanguageVersionSettings,
|
||||
capabilities: Map<ModuleDescriptor.Capability<*>, Any?> = mapOf(MultiTargetPlatform.CAPABILITY to MultiTargetPlatform.Common),
|
||||
metadataPartProviderFactory: (ModuleContent<ModuleInfo>) -> MetadataPartProvider
|
||||
): AnalysisResult {
|
||||
val moduleInfo = SourceModuleInfo(moduleName, capabilities, dependOnBuiltIns)
|
||||
val project = files.firstOrNull()?.project ?: throw AssertionError("No files to analyze")
|
||||
|
||||
val multiplatformLanguageSettings = object : LanguageVersionSettings by languageVersionSettings {
|
||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State =
|
||||
if (feature == LanguageFeature.MultiPlatformProjects) LanguageFeature.State.ENABLED
|
||||
else languageVersionSettings.getFeatureSupport(feature)
|
||||
}
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val resolver = ResolverForProjectImpl(
|
||||
"sources for metadata serializer",
|
||||
ProjectContext(project),
|
||||
listOf(moduleInfo),
|
||||
modulesContent = { ModuleContent(it, files, GlobalSearchScope.allScope(project)) },
|
||||
moduleLanguageSettingsProvider = object : LanguageSettingsProvider {
|
||||
override fun getLanguageVersionSettings(
|
||||
moduleInfo: ModuleInfo,
|
||||
project: Project,
|
||||
isReleaseCoroutines: Boolean?
|
||||
) = multiplatformLanguageSettings
|
||||
|
||||
override fun getTargetPlatform(
|
||||
moduleInfo: ModuleInfo,
|
||||
project: Project
|
||||
) = TargetPlatformVersion.NoVersion
|
||||
},
|
||||
resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade },
|
||||
platformParameters = { _ -> CommonAnalysisParameters(metadataPartProviderFactory) }
|
||||
)
|
||||
|
||||
val moduleDescriptor = resolver.descriptorForModule(moduleInfo)
|
||||
val container = resolver.resolverForModule(moduleInfo).componentProvider
|
||||
|
||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||
|
||||
return AnalysisResult.success(container.get<BindingTrace>().bindingContext, moduleDescriptor)
|
||||
}
|
||||
|
||||
override fun <M : ModuleInfo> createResolverForModule(
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
moduleContext: ModuleContext,
|
||||
moduleContent: ModuleContent<M>,
|
||||
platformParameters: PlatformAnalysisParameters,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
resolverForProject: ResolverForProject<M>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
targetPlatformVersion: TargetPlatformVersion
|
||||
): ResolverForModule {
|
||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||
val project = moduleContext.project
|
||||
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
|
||||
project, moduleContext.storageManager, syntheticFiles,
|
||||
moduleContentScope,
|
||||
moduleInfo
|
||||
)
|
||||
|
||||
val metadataPartProvider = (platformParameters as CommonAnalysisParameters).metadataPartProviderFactory(moduleContent)
|
||||
val trace = CodeAnalyzerInitializer.getInstance(project).createTrace()
|
||||
val container = createContainerToResolveCommonCode(
|
||||
moduleContext, trace, declarationProviderFactory, moduleContentScope, targetEnvironment, metadataPartProvider,
|
||||
languageVersionSettings
|
||||
)
|
||||
|
||||
val packageFragmentProviders = listOf(
|
||||
container.get<ResolveSession>().packageFragmentProvider,
|
||||
container.get<MetadataPackageFragmentProvider>()
|
||||
)
|
||||
|
||||
return ResolverForModule(CompositePackageFragmentProvider(packageFragmentProviders), container)
|
||||
}
|
||||
|
||||
private fun createContainerToResolveCommonCode(
|
||||
moduleContext: ModuleContext,
|
||||
bindingTrace: BindingTrace,
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
metadataPartProvider: MetadataPartProvider,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): StorageComponentContainer = createContainer("ResolveCommonCode", targetPlatform) {
|
||||
configureModule(moduleContext, targetPlatform, TargetPlatformVersion.NoVersion, bindingTrace)
|
||||
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(LookupTracker.DO_NOTHING)
|
||||
useInstance(ExpectActualTracker.DoNothing)
|
||||
useImpl<ResolveSession>()
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
useInstance(languageVersionSettings)
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
useInstance(metadataPartProvider)
|
||||
useInstance(declarationProviderFactory)
|
||||
useImpl<MetadataPackageFragmentProvider>()
|
||||
useImpl<ContractDeserializerImpl>()
|
||||
|
||||
val metadataFinderFactory = ServiceManager.getService(moduleContext.project, MetadataFinderFactory::class.java)
|
||||
?: error("No MetadataFinderFactory in project")
|
||||
useInstance(metadataFinderFactory.create(moduleContentScope))
|
||||
|
||||
targetEnvironment.configure(this)
|
||||
}
|
||||
|
||||
override val targetPlatform: TargetPlatform
|
||||
get() = CommonPlatform
|
||||
}
|
||||
@@ -6,38 +6,18 @@
|
||||
package org.jetbrains.kotlin.analyzer.common
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.builtins.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.SamConversionTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.DynamicTypesSettings
|
||||
|
||||
object CommonPlatform : TargetPlatform("Default") {
|
||||
private object CommonPlatformConfigurator : PlatformConfiguratorBase() {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {}
|
||||
}
|
||||
|
||||
object CommonPlatformCompilerServices : PlatformDependentCompilerServices() {
|
||||
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {}
|
||||
|
||||
override val multiTargetPlatform: MultiTargetPlatform
|
||||
get() = MultiTargetPlatform.Common
|
||||
|
||||
override val platformConfigurator: PlatformConfigurator = CommonPlatformConfigurator
|
||||
|
||||
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns = ModuleInfo.DependencyOnBuiltIns.AFTER_SDK
|
||||
}
|
||||
|
||||
private object CommonPlatformConfigurator : PlatformConfiguratorBase(
|
||||
DynamicTypesSettings(), listOf(), listOf(), listOf(), listOf(), listOf(),
|
||||
IdentifierChecker.Default, OverloadFilter.Default, PlatformToKotlinClassMap.EMPTY, DelegationFilter.Default,
|
||||
OverridesBackwardCompatibilityHelper.Default,
|
||||
DeclarationReturnTypeSanitizer.Default
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(SyntheticScopes.Empty)
|
||||
container.useInstance(SamConversionTransformer.Empty)
|
||||
container.useInstance(TypeSpecificityComparator.NONE)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,9 +67,9 @@ class TextDiagnostic(
|
||||
return result
|
||||
}
|
||||
|
||||
fun asString(): String {
|
||||
fun asString(withNewInference: Boolean = true, renderParameters: Boolean = true): String {
|
||||
val result = StringBuilder()
|
||||
if (inferenceCompatibility.abbreviation != null) {
|
||||
if (withNewInference && inferenceCompatibility.abbreviation != null) {
|
||||
result.append(inferenceCompatibility.abbreviation)
|
||||
result.append(";")
|
||||
}
|
||||
@@ -78,9 +78,10 @@ class TextDiagnostic(
|
||||
result.append(":")
|
||||
}
|
||||
result.append(name)
|
||||
if (parameters != null) {
|
||||
|
||||
if (renderParameters && parameters != null) {
|
||||
result.append("(")
|
||||
result.append(StringUtil.join(parameters, { "\"$it\"" }, ", "))
|
||||
result.append(StringUtil.join(parameters, { "\"${it.replace('\n', ' ')}\"" }, ", "))
|
||||
result.append(")")
|
||||
}
|
||||
return result.toString()
|
||||
|
||||
@@ -20,17 +20,18 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.platform.oldFashionedDescription
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
|
||||
import java.util.*
|
||||
@@ -48,7 +49,7 @@ object CheckerTestUtil {
|
||||
|
||||
fun getDiagnosticsIncludingSyntaxErrors(
|
||||
bindingContext: BindingContext,
|
||||
implementingModulesBindings: List<Pair<MultiTargetPlatform, BindingContext>>,
|
||||
implementingModulesBindings: List<Pair<TargetPlatform, BindingContext>>,
|
||||
root: PsiElement,
|
||||
markDynamicCalls: Boolean,
|
||||
dynamicCallDescriptors: MutableList<DeclarationDescriptor>,
|
||||
@@ -70,10 +71,11 @@ object CheckerTestUtil {
|
||||
moduleDescriptor,
|
||||
diagnosedRanges
|
||||
)
|
||||
val sortedBindings = implementingModulesBindings.sortedBy { it.first }
|
||||
|
||||
val sortedBindings = implementingModulesBindings.sortedBy { it.first.oldFashionedDescription }
|
||||
|
||||
for ((platform, second) in sortedBindings) {
|
||||
assert(platform is MultiTargetPlatform.Specific) { "Implementing module must have a specific platform: $platform" }
|
||||
assert(!platform.isCommon()) { "Implementing module must have a specific platform: $platform" }
|
||||
|
||||
result.addAll(
|
||||
getDiagnosticsIncludingSyntaxErrors(
|
||||
@@ -81,7 +83,7 @@ object CheckerTestUtil {
|
||||
root,
|
||||
markDynamicCalls,
|
||||
dynamicCallDescriptors,
|
||||
(platform as MultiTargetPlatform.Specific).platform,
|
||||
platform.single().platformName,
|
||||
withNewInference,
|
||||
languageVersionSettings,
|
||||
dataFlowValueFactory,
|
||||
@@ -326,6 +328,7 @@ object CheckerTestUtil {
|
||||
return false
|
||||
if (expected.parameters == null)
|
||||
return true
|
||||
|
||||
if (actual.parameters == null || expected.parameters.size != actual.parameters.size)
|
||||
return false
|
||||
|
||||
@@ -418,7 +421,7 @@ object CheckerTestUtil {
|
||||
psiFile,
|
||||
diagnostics,
|
||||
emptyMap(),
|
||||
com.intellij.util.Function { it.text },
|
||||
{ it.text },
|
||||
emptyList(),
|
||||
false,
|
||||
false
|
||||
@@ -428,12 +431,12 @@ object CheckerTestUtil {
|
||||
psiFile: PsiFile,
|
||||
diagnostics: Collection<ActualDiagnostic>,
|
||||
diagnosticToExpectedDiagnostic: Map<AbstractTestDiagnostic, TextDiagnostic>,
|
||||
getFileText: com.intellij.util.Function<PsiFile, String>,
|
||||
getFileText: (PsiFile) -> String,
|
||||
uncheckedDiagnostics: Collection<PositionalTextDiagnostic>,
|
||||
withNewInferenceDirective: Boolean,
|
||||
renderDiagnosticMessages: Boolean
|
||||
): StringBuffer {
|
||||
val text = getFileText.`fun`(psiFile)
|
||||
val text = getFileText(psiFile)
|
||||
val result = StringBuffer()
|
||||
val diagnosticsFiltered = diagnostics.filter { actualDiagnostic -> psiFile == actualDiagnostic.file }
|
||||
if (diagnosticsFiltered.isEmpty() && uncheckedDiagnostics.isEmpty()) {
|
||||
@@ -512,33 +515,15 @@ object CheckerTestUtil {
|
||||
|
||||
for (diagnostic in diagnostics) {
|
||||
val expectedDiagnostic = diagnosticToExpectedDiagnostic[diagnostic]
|
||||
if (expectedDiagnostic != null) {
|
||||
val actualTextDiagnostic = TextDiagnostic.asTextDiagnostic(diagnostic)
|
||||
val actualTextDiagnostic = TextDiagnostic.asTextDiagnostic(diagnostic)
|
||||
|
||||
if (expectedDiagnostic != null || !hasExplicitDefinitionOnlyOption(diagnostic)) {
|
||||
val shouldRenderParameters =
|
||||
renderDiagnosticMessages || expectedDiagnostic?.parameters != null
|
||||
|
||||
diagnosticsAsText.add(
|
||||
if (compareTextDiagnostic(expectedDiagnostic, actualTextDiagnostic))
|
||||
expectedDiagnostic.asString() else actualTextDiagnostic.asString()
|
||||
actualTextDiagnostic.asString(withNewInferenceDirective, shouldRenderParameters)
|
||||
)
|
||||
} else if (!hasExplicitDefinitionOnlyOption(diagnostic)) {
|
||||
val diagnosticText = StringBuilder()
|
||||
if (withNewInferenceDirective && diagnostic.inferenceCompatibility.abbreviation != null) {
|
||||
diagnosticText.append(diagnostic.inferenceCompatibility.abbreviation)
|
||||
diagnosticText.append(";")
|
||||
}
|
||||
if (diagnostic.platform != null) {
|
||||
diagnosticText.append(diagnostic.platform)
|
||||
diagnosticText.append(":")
|
||||
}
|
||||
diagnosticText.append(diagnostic.name)
|
||||
if (renderDiagnosticMessages) {
|
||||
val textDiagnostic = TextDiagnostic.asTextDiagnostic(diagnostic)
|
||||
if (textDiagnostic.parameters != null) {
|
||||
diagnosticText
|
||||
.append("(")
|
||||
.append(textDiagnostic.parameters.joinToString(", "))
|
||||
.append(")")
|
||||
}
|
||||
}
|
||||
diagnosticsAsText.add(diagnosticText.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.checkers.utils
|
||||
|
||||
import java.io.File
|
||||
|
||||
fun clearFileFromDiagnosticMarkup(file: File) {
|
||||
val text = file.readText()
|
||||
val cleanText = CheckerTestUtil.parseDiagnosedRanges(text, mutableListOf(), null) // will clear text from markup as side-effect
|
||||
file.writeText(cleanText)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.storage.ExceptionTracker
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
@@ -83,14 +83,14 @@ class MutableModuleContextImpl(
|
||||
projectContext: ProjectContext
|
||||
) : MutableModuleContext, ProjectContext by projectContext
|
||||
|
||||
fun GlobalContext(): GlobalContextImpl {
|
||||
fun GlobalContext(debugName: String): GlobalContextImpl {
|
||||
val tracker = ExceptionTracker()
|
||||
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling("GlobalContext", tracker), tracker)
|
||||
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(debugName, tracker), tracker)
|
||||
}
|
||||
|
||||
fun ProjectContext(project: Project): ProjectContext = ProjectContextImpl(project, GlobalContext())
|
||||
fun ModuleContext(module: ModuleDescriptor, project: Project): ModuleContext =
|
||||
ModuleContextImpl(module, ProjectContext(project))
|
||||
fun ProjectContext(project: Project, debugName: String): ProjectContext = ProjectContextImpl(project, GlobalContext(debugName))
|
||||
fun ModuleContext(module: ModuleDescriptor, project: Project, debugName: String): ModuleContext =
|
||||
ModuleContextImpl(module, ProjectContext(project, debugName))
|
||||
|
||||
fun GlobalContext.withProject(project: Project): ProjectContext = ProjectContextImpl(project, this)
|
||||
fun ProjectContext.withModule(module: ModuleDescriptor): ModuleContext = ModuleContextImpl(module, this)
|
||||
@@ -99,8 +99,8 @@ fun ContextForNewModule(
|
||||
projectContext: ProjectContext,
|
||||
moduleName: Name,
|
||||
builtIns: KotlinBuiltIns,
|
||||
multiTargetPlatform: MultiTargetPlatform?
|
||||
platform: TargetPlatform?
|
||||
): MutableModuleContext {
|
||||
val module = ModuleDescriptorImpl(moduleName, projectContext.storageManager, builtIns, multiTargetPlatform)
|
||||
val module = ModuleDescriptorImpl(moduleName, projectContext.storageManager, builtIns, platform)
|
||||
return MutableModuleContextImpl(module, projectContext)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.ModulePath;
|
||||
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
@@ -645,6 +646,10 @@ public interface Errors {
|
||||
DiagnosticFactory2<KtNamedDeclaration, MemberDescriptor,
|
||||
Map<Incompatible, Collection<MemberDescriptor>>> ACTUAL_WITHOUT_EXPECT =
|
||||
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||
DiagnosticFactory2<KtNamedDeclaration, DeclarationDescriptor, Collection<ModuleDescriptor>> AMBIGUOUS_ACTUALS =
|
||||
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||
DiagnosticFactory2<KtNamedDeclaration, DeclarationDescriptor, Collection<ModuleDescriptor>> AMBIGUOUS_EXPECTS =
|
||||
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||
|
||||
DiagnosticFactory2<KtNamedDeclaration, ClassDescriptor,
|
||||
List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>> NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS =
|
||||
|
||||
@@ -280,10 +280,14 @@ public class DefaultErrorMessages {
|
||||
"Expected function source is not found, therefore it's impossible to generate default argument values declared there. " +
|
||||
"Please add the corresponding file to compilation sources");
|
||||
|
||||
MAP.put(NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module{1}{2}", DECLARATION_NAME_WITH_KIND,
|
||||
PLATFORM, PlatformIncompatibilityDiagnosticRenderer.TEXT);
|
||||
MAP.put(NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module {1}{2}", DECLARATION_NAME_WITH_KIND,
|
||||
MODULE_WITH_PLATFORM, PlatformIncompatibilityDiagnosticRenderer.TEXT);
|
||||
MAP.put(ACTUAL_WITHOUT_EXPECT, "{0} has no corresponding expected declaration{1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM,
|
||||
PlatformIncompatibilityDiagnosticRenderer.TEXT);
|
||||
MAP.put(AMBIGUOUS_ACTUALS, "{0} has several compatible actual declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
|
||||
MODULE_WITH_PLATFORM));
|
||||
MAP.put(AMBIGUOUS_EXPECTS, "{0} has several compatible expect declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
|
||||
MODULE_WITH_PLATFORM));
|
||||
|
||||
MAP.put(NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, "Actual class ''{0}'' has no corresponding members for expected class members:{1}",
|
||||
NAME, IncompatibleExpectedActualClassScopesRenderer.TEXT);
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.newTable
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.newText
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer.Companion.DEBUG_TEXT
|
||||
@@ -84,12 +85,24 @@ object Renderers {
|
||||
val NAME = Renderer<Named> { it.name.asString() }
|
||||
|
||||
@JvmField
|
||||
val PLATFORM = Renderer<ModuleDescriptor> {
|
||||
val platform = it.getMultiTargetPlatform()
|
||||
" ${it.getCapability(ModuleInfo.Capability)?.displayedName ?: ""}" + when (platform) {
|
||||
MultiTargetPlatform.Common -> ""
|
||||
is MultiTargetPlatform.Specific -> " for " + platform.platform
|
||||
null -> ""
|
||||
val MODULE_WITH_PLATFORM = Renderer<ModuleDescriptor> { module ->
|
||||
val platform = module.platform
|
||||
val moduleName = module.getCapability(ModuleInfo.Capability)?.displayedName ?: ""
|
||||
val platformNameIfAny = if (platform == null || platform.isCommon()) "" else " for " + platform.single().platformName
|
||||
|
||||
moduleName + platformNameIfAny
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val MODULE_PATH = object : DiagnosticParameterRenderer<ModulePath> {
|
||||
override fun render(obj: ModulePath, renderingContext: RenderingContext): String {
|
||||
// Prettify rendering for two-level MPP projects
|
||||
// - path of size = 2 is usual 'common' -> 'platform' configuration
|
||||
// - path of size = 1 is trivial path consisting of one module. It may appear as the result of misconfiguration
|
||||
// In either case, we should take last node in path for rendering
|
||||
if (obj.nodes.size <= 2) return " in module ${MODULE_WITH_PLATFORM.render(obj.nodes.last(), renderingContext)}"
|
||||
|
||||
return " on path ${obj.nodes.joinToString(separator = " -> ") { MODULE_WITH_PLATFORM.render(it, renderingContext) }}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.extensions
|
||||
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
interface StorageComponentContainerContributor {
|
||||
companion object : ProjectExtensionDescriptor<StorageComponentContainerContributor>(
|
||||
|
||||
@@ -16,27 +16,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.frontend.di
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.config.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
|
||||
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.platform.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||
import org.jetbrains.kotlin.resolve.lazy.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
|
||||
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
||||
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
||||
@@ -44,19 +48,29 @@ import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
||||
fun StorageComponentContainer.configureModule(
|
||||
moduleContext: ModuleContext,
|
||||
platform: TargetPlatform,
|
||||
platformVersion: TargetPlatformVersion
|
||||
compilerServices: PlatformDependentCompilerServices,
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
useInstance(moduleContext)
|
||||
useInstance(moduleContext.module)
|
||||
useInstance(moduleContext.project)
|
||||
useInstance(moduleContext.storageManager)
|
||||
useInstance(moduleContext.module.builtIns)
|
||||
useInstance(trace)
|
||||
useInstance(languageVersionSettings)
|
||||
|
||||
useInstance(platform)
|
||||
useInstance(platformVersion)
|
||||
useInstance(compilerServices)
|
||||
|
||||
platform.platformConfigurator.configureModuleComponents(this)
|
||||
platform.platformConfigurator.configureModuleDependentCheckers(this)
|
||||
val nonTrivialPlatformVersion = platform
|
||||
.mapNotNull { it.targetPlatformVersion.takeIf { it != TargetPlatformVersion.NoVersion } }
|
||||
.singleOrNull()
|
||||
|
||||
useInstance(nonTrivialPlatformVersion ?: TargetPlatformVersion.NoVersion)
|
||||
|
||||
compilerServices.platformConfigurator.configureModuleComponents(this)
|
||||
compilerServices.platformConfigurator.configureModuleDependentCheckers(this)
|
||||
|
||||
for (extension in StorageComponentContainerContributor.getInstances(moduleContext.project)) {
|
||||
extension.registerModuleComponents(this, platform, moduleContext.module)
|
||||
@@ -73,17 +87,30 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() {
|
||||
useImpl<ExperimentalUsageChecker>()
|
||||
useImpl<ExperimentalUsageChecker.Overrides>()
|
||||
useImpl<ExperimentalUsageChecker.ClassifierUsage>()
|
||||
|
||||
useImpl<ContractDeserializerImpl>()
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
|
||||
useImpl<ClassicTypeSystemContextForCS>()
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.configureModule(
|
||||
moduleContext: ModuleContext,
|
||||
platform: TargetPlatform,
|
||||
platformVersion: TargetPlatformVersion,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
configureModule(moduleContext, platform, platformVersion)
|
||||
useInstance(trace)
|
||||
/**
|
||||
* Actually, those should be present in 'configurePlatformIndependentComponents',
|
||||
* but, unfortunately, this is currently impossible, because in some lightweight
|
||||
* containers (see [createContainerForBodyResolve] and similar) some dependencies
|
||||
* are missing
|
||||
*
|
||||
* If you're not doing some trickery with containers, you should use them.
|
||||
*/
|
||||
fun StorageComponentContainer.configureStandardResolveComponents() {
|
||||
useImpl<ResolveSession>()
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.configureIncrementalCompilation(lookupTracker: LookupTracker, expectActualTracker: ExpectActualTracker) {
|
||||
useInstance(lookupTracker)
|
||||
useInstance(expectActualTracker)
|
||||
}
|
||||
|
||||
fun createContainerForBodyResolve(
|
||||
@@ -91,18 +118,19 @@ fun createContainerForBodyResolve(
|
||||
bindingTrace: BindingTrace,
|
||||
platform: TargetPlatform,
|
||||
statementFilter: StatementFilter,
|
||||
targetPlatformVersion: TargetPlatformVersion,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): StorageComponentContainer = createContainer("BodyResolve", platform) {
|
||||
configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace)
|
||||
compilerServices: PlatformDependentCompilerServices,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
moduleStructureOracle: ModuleStructureOracle
|
||||
): StorageComponentContainer = createContainer("BodyResolve", compilerServices) {
|
||||
configureModule(moduleContext, platform, compilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
useInstance(statementFilter)
|
||||
|
||||
useInstance(BodyResolveCache.ThrowException)
|
||||
useInstance(languageVersionSettings)
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
|
||||
useImpl<BodyResolver>()
|
||||
useInstance(moduleStructureOracle)
|
||||
}
|
||||
|
||||
fun createContainerForLazyBodyResolve(
|
||||
@@ -111,18 +139,19 @@ fun createContainerForLazyBodyResolve(
|
||||
bindingTrace: BindingTrace,
|
||||
platform: TargetPlatform,
|
||||
bodyResolveCache: BodyResolveCache,
|
||||
targetPlatformVersion: TargetPlatformVersion,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): StorageComponentContainer = createContainer("LazyBodyResolve", platform) {
|
||||
configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace)
|
||||
compilerServices: PlatformDependentCompilerServices,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
moduleStructureOracle: ModuleStructureOracle
|
||||
): StorageComponentContainer = createContainer("LazyBodyResolve", compilerServices) {
|
||||
configureModule(moduleContext, platform, compilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
useInstance(kotlinCodeAnalyzer)
|
||||
useInstance(kotlinCodeAnalyzer.fileScopeProvider)
|
||||
useInstance(bodyResolveCache)
|
||||
useInstance(languageVersionSettings)
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
useImpl<BasicAbsentDescriptorHandler>()
|
||||
useInstance(moduleStructureOracle)
|
||||
}
|
||||
|
||||
fun createContainerForLazyLocalClassifierAnalyzer(
|
||||
@@ -130,12 +159,12 @@ fun createContainerForLazyLocalClassifierAnalyzer(
|
||||
bindingTrace: BindingTrace,
|
||||
platform: TargetPlatform,
|
||||
lookupTracker: LookupTracker,
|
||||
targetPlatformVersion: TargetPlatformVersion,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
statementFilter: StatementFilter,
|
||||
localClassDescriptorHolder: LocalClassDescriptorHolder
|
||||
): StorageComponentContainer = createContainer("LocalClassifierAnalyzer", platform) {
|
||||
configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace)
|
||||
localClassDescriptorHolder: LocalClassDescriptorHolder,
|
||||
compilerServices: PlatformDependentCompilerServices
|
||||
): StorageComponentContainer = createContainer("LocalClassifierAnalyzer", compilerServices) {
|
||||
configureModule(moduleContext, platform, compilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
useInstance(localClassDescriptorHolder)
|
||||
useInstance(lookupTracker)
|
||||
@@ -153,7 +182,6 @@ fun createContainerForLazyLocalClassifierAnalyzer(
|
||||
useImpl<DeclarationScopeProviderForLocalClassifierAnalyzer>()
|
||||
useImpl<LocalLazyDeclarationResolver>()
|
||||
|
||||
useInstance(languageVersionSettings)
|
||||
useInstance(statementFilter)
|
||||
}
|
||||
|
||||
@@ -162,30 +190,48 @@ fun createContainerForLazyResolve(
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
bindingTrace: BindingTrace,
|
||||
platform: TargetPlatform,
|
||||
targetPlatformVersion: TargetPlatformVersion,
|
||||
compilerServices: PlatformDependentCompilerServices,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): StorageComponentContainer = createContainer("LazyResolve", platform) {
|
||||
configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace)
|
||||
): StorageComponentContainer = createContainer("LazyResolve", compilerServices) {
|
||||
configureModule(moduleContext, platform, compilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
configureStandardResolveComponents()
|
||||
|
||||
useInstance(declarationProviderFactory)
|
||||
useInstance(languageVersionSettings)
|
||||
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
targetEnvironment.configure(this)
|
||||
|
||||
useImpl<ResolveSession>()
|
||||
useImpl<LazyTopDownAnalyzer>()
|
||||
}
|
||||
|
||||
fun createLazyResolveSession(moduleContext: ModuleContext, files: Collection<KtFile>): ResolveSession =
|
||||
createContainerForLazyResolve(
|
||||
moduleContext,
|
||||
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
|
||||
BindingTraceContext(),
|
||||
CommonPlatform,
|
||||
TargetPlatformVersion.NoVersion,
|
||||
CompilerEnvironment,
|
||||
LanguageVersionSettingsImpl.DEFAULT
|
||||
).get<ResolveSession>()
|
||||
fun createContainerToResolveCommonCode(
|
||||
moduleContext: ModuleContext,
|
||||
bindingTrace: BindingTrace,
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
metadataPartProvider: MetadataPartProvider,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
platform: TargetPlatform,
|
||||
compilerServices: PlatformDependentCompilerServices
|
||||
): StorageComponentContainer = createContainer("ResolveCommonCode", compilerServices) {
|
||||
configureModule(moduleContext, platform, compilerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(declarationProviderFactory)
|
||||
|
||||
configureStandardResolveComponents()
|
||||
|
||||
configureCommonSpecificComponents()
|
||||
useInstance(metadataPartProvider)
|
||||
|
||||
val metadataFinderFactory = ServiceManager.getService(moduleContext.project, MetadataFinderFactory::class.java)
|
||||
?: error("No MetadataFinderFactory in project")
|
||||
useInstance(metadataFinderFactory.create(moduleContentScope))
|
||||
|
||||
targetEnvironment.configure(this)
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.configureCommonSpecificComponents() {
|
||||
useImpl<MetadataPackageFragmentProvider>()
|
||||
}
|
||||
@@ -27,5 +27,6 @@ object CompilerEnvironment : TargetEnvironment("Compiler") {
|
||||
container.useInstance(BodyResolveCache.ThrowException)
|
||||
container.useImpl<CompilerLocalDescriptorResolver>()
|
||||
container.useImpl<BasicAbsentDescriptorHandler>()
|
||||
container.useInstance(ModuleStructureOracle.SingleModule)
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,12 @@
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.WrappedTypeFactory
|
||||
|
||||
@DefaultImplementation(impl = DeclarationReturnTypeSanitizer.Default::class)
|
||||
interface DeclarationReturnTypeSanitizer {
|
||||
fun sanitizeReturnType(
|
||||
inferred: UnwrappedType,
|
||||
|
||||
@@ -52,13 +52,13 @@ internal class DeclarationsCheckerBuilder(
|
||||
private val descriptorResolver: DescriptorResolver,
|
||||
private val originalModifiersChecker: ModifiersChecker,
|
||||
private val annotationChecker: AnnotationChecker,
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val identifierCheckers: Iterable<IdentifierChecker>,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val typeSpecificityComparator: TypeSpecificityComparator,
|
||||
private val diagnosticSuppressor: PlatformDiagnosticSuppressor
|
||||
) {
|
||||
fun withTrace(trace: BindingTrace) = DeclarationsChecker(
|
||||
descriptorResolver, originalModifiersChecker, annotationChecker, identifierChecker, trace, languageVersionSettings,
|
||||
descriptorResolver, originalModifiersChecker, annotationChecker, identifierCheckers, trace, languageVersionSettings,
|
||||
typeSpecificityComparator, diagnosticSuppressor
|
||||
)
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class DeclarationsChecker(
|
||||
private val descriptorResolver: DescriptorResolver,
|
||||
modifiersChecker: ModifiersChecker,
|
||||
private val annotationChecker: AnnotationChecker,
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val identifierCheckers: Iterable<IdentifierChecker>,
|
||||
private val trace: BindingTrace,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
typeSpecificityComparator: TypeSpecificityComparator,
|
||||
@@ -89,20 +89,20 @@ class DeclarationsChecker(
|
||||
for ((classOrObject, classDescriptor) in bodiesResolveContext.declaredClasses.entries) {
|
||||
checkClass(classDescriptor, classOrObject)
|
||||
modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor)
|
||||
identifierChecker.checkDeclaration(classOrObject, trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(classOrObject, trace) }
|
||||
exposedChecker.checkClassHeader(classOrObject, classDescriptor)
|
||||
}
|
||||
|
||||
for ((function, functionDescriptor) in bodiesResolveContext.functions.entries) {
|
||||
checkFunction(function, functionDescriptor)
|
||||
modifiersChecker.checkModifiersForDeclaration(function, functionDescriptor)
|
||||
identifierChecker.checkDeclaration(function, trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(function, trace) }
|
||||
}
|
||||
|
||||
for ((property, propertyDescriptor) in bodiesResolveContext.properties.entries) {
|
||||
checkProperty(property, propertyDescriptor)
|
||||
modifiersChecker.checkModifiersForDeclaration(property, propertyDescriptor)
|
||||
identifierChecker.checkDeclaration(property, trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(property, trace) }
|
||||
}
|
||||
|
||||
val destructuringDeclarations = bodiesResolveContext.destructuringDeclarationEntries.entries
|
||||
@@ -112,7 +112,7 @@ class DeclarationsChecker(
|
||||
|
||||
for (multiDeclaration in destructuringDeclarations) {
|
||||
modifiersChecker.checkModifiersForDestructuringDeclaration(multiDeclaration)
|
||||
identifierChecker.checkDeclaration(multiDeclaration, trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(multiDeclaration, trace) }
|
||||
}
|
||||
|
||||
for ((declaration, constructorDescriptor) in bodiesResolveContext.secondaryConstructors.entries) {
|
||||
@@ -246,7 +246,7 @@ class DeclarationsChecker(
|
||||
|
||||
private fun checkConstructorDeclaration(constructorDescriptor: ClassConstructorDescriptor, declaration: KtConstructor<*>) {
|
||||
modifiersChecker.checkModifiersForDeclaration(declaration, constructorDescriptor)
|
||||
identifierChecker.checkDeclaration(declaration, trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(declaration, trace) }
|
||||
checkVarargParameters(trace, constructorDescriptor)
|
||||
checkConstructorVisibility(constructorDescriptor, declaration)
|
||||
checkExpectedClassConstructor(constructorDescriptor, declaration)
|
||||
@@ -845,7 +845,7 @@ class DeclarationsChecker(
|
||||
val accessor = if (accessorDescriptor is PropertyGetterDescriptor) property.getter else property.setter
|
||||
if (accessor != null) {
|
||||
modifiersChecker.checkModifiersForDeclaration(accessor, accessorDescriptor)
|
||||
identifierChecker.checkDeclaration(accessor, trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(accessor, trace) }
|
||||
} else {
|
||||
modifiersChecker.runDeclarationCheckers(property, accessorDescriptor)
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
interface IdentifierChecker {
|
||||
interface IdentifierChecker : PlatformSpecificExtension<IdentifierChecker> {
|
||||
fun checkIdentifier(simpleNameExpression: KtSimpleNameExpression, diagnosticHolder: DiagnosticSink)
|
||||
fun checkDeclaration(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink)
|
||||
|
||||
@@ -29,3 +31,17 @@ interface IdentifierChecker {
|
||||
override fun checkDeclaration(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) {}
|
||||
}
|
||||
}
|
||||
|
||||
class IdentifierCheckerClashesResolver : PlatformExtensionsClashResolver<IdentifierChecker>(IdentifierChecker::class.java) {
|
||||
override fun resolveExtensionsClash(extensions: List<IdentifierChecker>): IdentifierChecker = CompositeIdentifierChecker(extensions)
|
||||
}
|
||||
|
||||
class CompositeIdentifierChecker(private val identifierCheckers: List<IdentifierChecker>) : IdentifierChecker {
|
||||
override fun checkIdentifier(simpleNameExpression: KtSimpleNameExpression, diagnosticHolder: DiagnosticSink) {
|
||||
identifierCheckers.forEach { it.checkIdentifier(simpleNameExpression, diagnosticHolder) }
|
||||
}
|
||||
|
||||
override fun checkDeclaration(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) {
|
||||
identifierCheckers.forEach { it.checkDeclaration(declaration, diagnosticHolder) }
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ class LazyTopDownAnalyzer(
|
||||
private val fileScopeProvider: FileScopeProvider,
|
||||
private val declarationScopeProvider: DeclarationScopeProvider,
|
||||
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val identifierCheckers: Iterable<IdentifierChecker>,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val classifierUsageCheckers: Iterable<ClassifierUsageChecker>,
|
||||
@@ -102,7 +102,7 @@ class LazyTopDownAnalyzer(
|
||||
}
|
||||
|
||||
override fun visitPackageDirective(directive: KtPackageDirective) {
|
||||
directive.packageNames.forEach { identifierChecker.checkIdentifier(it, trace) }
|
||||
directive.packageNames.forEach { packageName -> identifierCheckers.forEach { it.checkIdentifier(packageName, trace) } }
|
||||
qualifiedExpressionResolver.resolvePackageHeader(directive, moduleDescriptor, trace)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
|
||||
|
||||
class LocalVariableResolver(
|
||||
private val modifiersChecker: ModifiersChecker,
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val identifierCheckers: Iterable<IdentifierChecker>,
|
||||
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
||||
private val annotationResolver: AnnotationResolver,
|
||||
private val variableTypeAndInitializerResolver: VariableTypeAndInitializerResolver,
|
||||
@@ -144,7 +144,7 @@ class LocalVariableResolver(
|
||||
ExpressionTypingUtils.checkVariableShadowing(context.scope, context.trace, descriptor)
|
||||
|
||||
modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(ktProperty, descriptor)
|
||||
identifierChecker.checkDeclaration(ktProperty, context.trace)
|
||||
identifierCheckers.forEach { it.checkDeclaration(ktProperty, context.trace) }
|
||||
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(context.trace, ktProperty, descriptor)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
|
||||
interface ModuleStructureOracle {
|
||||
// May be faster than `findAllImplementingModules(module).isNotEmpty()`
|
||||
fun hasImplementingModules(module: ModuleDescriptor): Boolean
|
||||
|
||||
// TODO(dsavvinov): consider moving to comilation-terminology rather than inventing new "path"-terms
|
||||
fun findAllActualizationPaths(module: ModuleDescriptor): List<ModulePath>
|
||||
|
||||
fun findAllExpectedByPaths(module: ModuleDescriptor): List<ModulePath>
|
||||
|
||||
/**
|
||||
* Works like all sources are effectively in one module.
|
||||
*
|
||||
* This is the mode CLI currently operates in.
|
||||
*/
|
||||
object SingleModule : ModuleStructureOracle {
|
||||
override fun hasImplementingModules(module: ModuleDescriptor): Boolean = false
|
||||
|
||||
override fun findAllActualizationPaths(module: ModuleDescriptor): List<ModulePath> = listOf(ModulePath(module))
|
||||
|
||||
override fun findAllExpectedByPaths(module: ModuleDescriptor): List<ModulePath> = listOf(ModulePath(module))
|
||||
}
|
||||
}
|
||||
|
||||
class ModulePath(val nodes: List<ModuleDescriptor>) {
|
||||
constructor(vararg nodes: ModuleDescriptor) : this(nodes.toList())
|
||||
}
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorNonRoot
|
||||
|
||||
|
||||
@DefaultImplementation(impl = OverloadFilter.Default::class)
|
||||
interface OverloadFilter {
|
||||
fun filterPackageMemberOverloads(overloads: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot>
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
|
||||
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import java.util.*
|
||||
@@ -290,7 +291,7 @@ class OverloadResolver(
|
||||
if (member1 !is MemberDescriptor || member2 !is MemberDescriptor) return false
|
||||
|
||||
return member1.isActual && member2.isActual &&
|
||||
member1.getMultiTargetPlatform() != member2.getMultiTargetPlatform()
|
||||
member1.platform != member2.platform
|
||||
}
|
||||
|
||||
private fun reportRedeclarations(redeclarations: Collection<DeclarationDescriptorNonRoot>) {
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
|
||||
@DefaultImplementation(impl = OverridesBackwardCompatibilityHelper.Default::class)
|
||||
interface OverridesBackwardCompatibilityHelper {
|
||||
fun overrideCanBeOmitted(overridingDescriptor: CallableMemberDescriptor): Boolean
|
||||
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.PlatformToKotlinClassMap
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.composeContainer
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.container.*
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||
import org.jetbrains.kotlin.container.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparatorClashesResolver
|
||||
import org.jetbrains.kotlin.resolve.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||
import org.jetbrains.kotlin.types.DynamicTypesSettings
|
||||
import org.jetbrains.kotlin.types.DynamicTypesSettingsClashesResolver
|
||||
import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupportClashesResolver
|
||||
|
||||
private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
DataClassDeclarationChecker(),
|
||||
@@ -54,47 +56,65 @@ private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
|
||||
)
|
||||
private val DEFAULT_ANNOTATION_CHECKERS = listOf<AdditionalAnnotationChecker>()
|
||||
|
||||
private val DEFAULT_CLASH_RESOLVERS = listOf<PlatformExtensionsClashResolver<*>>(
|
||||
IdentifierCheckerClashesResolver(),
|
||||
TypeSpecificityComparatorClashesResolver(),
|
||||
DynamicTypesSettingsClashesResolver(),
|
||||
FunctionWithBigAritySupportClashesResolver()
|
||||
)
|
||||
|
||||
fun StorageComponentContainer.configureDefaultCheckers() {
|
||||
DEFAULT_DECLARATION_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_CALL_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_TYPE_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_CLASSIFIER_USAGE_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_ANNOTATION_CHECKERS.forEach { useInstance(it) }
|
||||
DEFAULT_CLASH_RESOLVERS.forEach { useClashResolver(it) }
|
||||
}
|
||||
|
||||
|
||||
abstract class PlatformConfiguratorBase(
|
||||
private val dynamicTypesSettings: DynamicTypesSettings,
|
||||
additionalDeclarationCheckers: List<DeclarationChecker>,
|
||||
additionalCallCheckers: List<CallChecker>,
|
||||
additionalTypeCheckers: List<AdditionalTypeChecker>,
|
||||
additionalClassifierUsageCheckers: List<ClassifierUsageChecker>,
|
||||
additionalAnnotationCheckers: List<AdditionalAnnotationChecker>,
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val overloadFilter: OverloadFilter,
|
||||
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
|
||||
private val delegationFilter: DelegationFilter,
|
||||
private val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper,
|
||||
private val declarationReturnTypeSanitizer: DeclarationReturnTypeSanitizer
|
||||
val dynamicTypesSettings: DynamicTypesSettings? = null,
|
||||
val additionalDeclarationCheckers: List<DeclarationChecker> = emptyList(),
|
||||
val additionalCallCheckers: List<CallChecker> = emptyList(),
|
||||
val additionalTypeCheckers: List<AdditionalTypeChecker> = emptyList(),
|
||||
val additionalClassifierUsageCheckers: List<ClassifierUsageChecker> = emptyList(),
|
||||
val additionalAnnotationCheckers: List<AdditionalAnnotationChecker> = emptyList(),
|
||||
val additionalClashResolvers: List<PlatformExtensionsClashResolver<*>> = emptyList(),
|
||||
val identifierChecker: IdentifierChecker? = null,
|
||||
val overloadFilter: OverloadFilter? = null,
|
||||
val platformToKotlinClassMap: PlatformToKotlinClassMap? = null,
|
||||
val delegationFilter: DelegationFilter? = null,
|
||||
val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper? = null,
|
||||
val declarationReturnTypeSanitizer: DeclarationReturnTypeSanitizer? = null
|
||||
) : PlatformConfigurator {
|
||||
private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers
|
||||
private val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers
|
||||
private val typeCheckers: List<AdditionalTypeChecker> = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers
|
||||
private val classifierUsageCheckers: List<ClassifierUsageChecker> =
|
||||
DEFAULT_CLASSIFIER_USAGE_CHECKERS + additionalClassifierUsageCheckers
|
||||
private val annotationCheckers: List<AdditionalAnnotationChecker> = DEFAULT_ANNOTATION_CHECKERS + additionalAnnotationCheckers
|
||||
|
||||
override val platformSpecificContainer = composeContainer(this::class.java.simpleName) {
|
||||
useInstance(dynamicTypesSettings)
|
||||
declarationCheckers.forEach { useInstance(it) }
|
||||
callCheckers.forEach { useInstance(it) }
|
||||
typeCheckers.forEach { useInstance(it) }
|
||||
classifierUsageCheckers.forEach { useInstance(it) }
|
||||
annotationCheckers.forEach { useInstance(it) }
|
||||
useInstance(identifierChecker)
|
||||
useInstance(overloadFilter)
|
||||
useInstance(platformToKotlinClassMap)
|
||||
useInstance(delegationFilter)
|
||||
useInstance(overridesBackwardCompatibilityHelper)
|
||||
useInstance(declarationReturnTypeSanitizer)
|
||||
configureDefaultCheckers()
|
||||
configureExtensionsAndCheckers(this)
|
||||
}
|
||||
|
||||
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
|
||||
container.useImpl<ExperimentalMarkerDeclarationAnnotationChecker>()
|
||||
}
|
||||
|
||||
fun configureExtensionsAndCheckers(container: StorageComponentContainer) {
|
||||
with(container) {
|
||||
useInstanceIfNotNull(dynamicTypesSettings)
|
||||
additionalDeclarationCheckers.forEach { useInstance(it) }
|
||||
additionalCallCheckers.forEach { useInstance(it) }
|
||||
additionalTypeCheckers.forEach { useInstance(it) }
|
||||
additionalClassifierUsageCheckers.forEach { useInstance(it) }
|
||||
additionalAnnotationCheckers.forEach { useInstance(it) }
|
||||
additionalClashResolvers.forEach { useClashResolver(it) }
|
||||
useInstanceIfNotNull(identifierChecker)
|
||||
useInstanceIfNotNull(overloadFilter)
|
||||
useInstanceIfNotNull(platformToKotlinClassMap)
|
||||
useInstanceIfNotNull(delegationFilter)
|
||||
useInstanceIfNotNull(overridesBackwardCompatibilityHelper)
|
||||
useInstanceIfNotNull(declarationReturnTypeSanitizer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createContainer(id: String, platform: TargetPlatform, init: StorageComponentContainer.() -> Unit) =
|
||||
composeContainer(id, platform.platformConfigurator.platformSpecificContainer, init)
|
||||
fun createContainer(id: String, compilerServices: PlatformDependentCompilerServices, init: StorageComponentContainer.() -> Unit) =
|
||||
composeContainer(id, compilerServices.platformConfigurator.platformSpecificContainer, init)
|
||||
|
||||
@@ -65,7 +65,7 @@ class TypeResolver(
|
||||
private val typeTransformerForTests: TypeTransformerForTests,
|
||||
private val dynamicTypesSettings: DynamicTypesSettings,
|
||||
private val dynamicCallableDescriptors: DynamicCallableDescriptors,
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val identifierCheckers: Iterable<IdentifierChecker>,
|
||||
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
@@ -288,9 +288,9 @@ class TypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
parameters.forEach {
|
||||
identifierChecker.checkDeclaration(it, c.trace)
|
||||
checkParameterInFunctionType(it)
|
||||
parameters.forEach { param ->
|
||||
identifierCheckers.forEach { it.checkDeclaration(param, c.trace) }
|
||||
checkParameterInFunctionType(param)
|
||||
}
|
||||
return parameters.map { parameter ->
|
||||
val parameterType = resolveType(c.noBareTypes(), parameter.typeReference!!)
|
||||
|
||||
@@ -35,15 +35,23 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
import java.io.File
|
||||
|
||||
class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnotationArgumentExtractor> = emptyList()) : DeclarationChecker {
|
||||
open class ExpectedActualDeclarationChecker(
|
||||
val moduleStructureOracle: ModuleStructureOracle,
|
||||
val argumentExtractor: ActualAnnotationArgumentExtractor
|
||||
) : DeclarationChecker {
|
||||
interface ActualAnnotationArgumentExtractor {
|
||||
fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>?
|
||||
|
||||
object Default : ActualAnnotationArgumentExtractor {
|
||||
override fun extractDefaultValue(parameter: ValueParameterDescriptor, expectedType: KotlinType): ConstantValue<*>? = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
@@ -56,46 +64,130 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
if (descriptor !is MemberDescriptor || DescriptorUtils.isEnumEntry(descriptor)) return
|
||||
|
||||
if (descriptor.isExpect) {
|
||||
checkExpectedDeclarationHasActual(declaration, descriptor, context.trace, descriptor.module, context.expectActualTracker)
|
||||
checkExpectedDeclarationHasProperActuals(declaration, descriptor, context.trace, context.expectActualTracker)
|
||||
} else {
|
||||
val checkActual = !context.languageVersionSettings.getFlag(AnalysisFlags.multiPlatformDoNotCheckActual)
|
||||
checkActualDeclarationHasExpected(declaration, descriptor, context.trace, checkActual)
|
||||
|
||||
val allImplementedModules = moduleStructureOracle.findAllExpectedByPaths(descriptor.module).flatMap { it.nodes }.toHashSet()
|
||||
checkActualDeclarationHasExpected(
|
||||
declaration,
|
||||
descriptor,
|
||||
context.trace,
|
||||
checkActual,
|
||||
moduleVisibilityFilter = { it in allImplementedModules }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkExpectedDeclarationHasActual(
|
||||
private fun checkExpectedDeclarationHasProperActuals(
|
||||
reportOn: KtNamedDeclaration,
|
||||
descriptor: MemberDescriptor,
|
||||
trace: BindingTrace,
|
||||
platformModule: ModuleDescriptor,
|
||||
expectActualTracker: ExpectActualTracker
|
||||
) {
|
||||
val allActualizationPaths = moduleStructureOracle.findAllActualizationPaths(descriptor.module)
|
||||
val leafModuleToVisibleModules = allActualizationPaths.groupBy { it.nodes.last() }
|
||||
.mapValues { it.value.flatMap { it.nodes }.toSet() }
|
||||
|
||||
for ((leafModule, modulesVisibleFromLeaf) in leafModuleToVisibleModules) {
|
||||
checkExpectedDeclarationHasAtLeastOneActual(
|
||||
reportOn,
|
||||
descriptor,
|
||||
trace,
|
||||
leafModule,
|
||||
expectActualTracker,
|
||||
moduleVisibilityFilter = { it in modulesVisibleFromLeaf }
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
Note that we have to check for 'duplicate actuals' separately, considering paths
|
||||
instead of only leaf-module, because currently we have to distinguish the following
|
||||
two cases:
|
||||
|
||||
expect class A expect class A
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
actual class A actual class A actual class A (no actual)
|
||||
\ / \ /
|
||||
\ / \ /
|
||||
(warning or nothing, TBD) actual class A
|
||||
(ERROR: duplicate actuals)
|
||||
|
||||
If we merge behaviour (e.g. decide to report ERROR for first case too)
|
||||
for those two cases, we can drop separate logic for DUPLICATE_ACTUALS
|
||||
*/
|
||||
for (path in allActualizationPaths) {
|
||||
val modulesOnThisPath = path.nodes.toSet()
|
||||
checkExpectedDeclarationHasAtMostOneActual(
|
||||
reportOn, descriptor, trace, path, moduleVisibilityFilter = { it in modulesOnThisPath }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkExpectedDeclarationHasAtMostOneActual(
|
||||
reportOn: KtNamedDeclaration,
|
||||
descriptor: MemberDescriptor,
|
||||
trace: BindingTrace,
|
||||
path: ModulePath,
|
||||
moduleVisibilityFilter: ModuleFilter
|
||||
) {
|
||||
val compatibility = path.nodes
|
||||
.mapNotNull { ExpectedActualResolver.findActualForExpected(descriptor, it, moduleVisibilityFilter) }
|
||||
.ifEmpty { return }
|
||||
.fold(LinkedHashMap<Compatibility, List<MemberDescriptor>>()) { resultMap, partialMap ->
|
||||
resultMap.apply { putAll(partialMap) }
|
||||
}
|
||||
|
||||
// Several compatible actuals on one path: report AMBIGUIOUS_ACTUALS here
|
||||
val atLeastWeaklyCompatibleActuals = compatibility.filterKeys { it.isCompatibleOrWeakCompatible() }.values.flatten()
|
||||
if (atLeastWeaklyCompatibleActuals.size > 1) {
|
||||
trace.report(Errors.AMBIGUOUS_ACTUALS.on(reportOn, descriptor, atLeastWeaklyCompatibleActuals.map { it.module }.distinct()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkExpectedDeclarationHasAtLeastOneActual(
|
||||
reportOn: KtNamedDeclaration,
|
||||
descriptor: MemberDescriptor,
|
||||
trace: BindingTrace,
|
||||
module: ModuleDescriptor,
|
||||
expectActualTracker: ExpectActualTracker,
|
||||
moduleVisibilityFilter: ModuleFilter
|
||||
) {
|
||||
// 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
|
||||
|
||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, platformModule) ?: return
|
||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, module, moduleVisibilityFilter) ?: return
|
||||
|
||||
// Only strong incompatibilities, but this is an OptionalExpectation -- don't report it
|
||||
if (compatibility.allStrongIncompatibilities() && isOptionalAnnotationClass(descriptor)) return
|
||||
|
||||
val shouldReportError =
|
||||
compatibility.allStrongIncompatibilities() ||
|
||||
Compatible !in compatibility && compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
|
||||
val expectedOnes = ExpectedActualResolver.findExpectedForActual(actual, descriptor.module)
|
||||
expectedOnes != null && Compatible in expectedOnes.keys
|
||||
}
|
||||
|
||||
if (shouldReportError) {
|
||||
// Only strong incompatibilities, or error won't be reported on actual: report NO_ACTUAL_FOR_EXPECT here
|
||||
if (compatibility.allStrongIncompatibilities() ||
|
||||
Compatible !in compatibility && descriptor.hasNoActualWithDiagnostic(compatibility)
|
||||
) {
|
||||
assert(compatibility.keys.all { it is Incompatible })
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
||||
trace.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() }
|
||||
trace.report(Errors.NO_ACTUAL_FOR_EXPECT.on(reportOn, descriptor, module, incompatibility))
|
||||
return
|
||||
}
|
||||
|
||||
expectActualTracker.reportExpectActual(expected = descriptor, actualMembers = actualMembers)
|
||||
// Here we have exactly one compatible actual and/or some weakly incompatible. In either case, we don't report anything on expect
|
||||
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 MemberDescriptor.hasNoActualWithDiagnostic(
|
||||
compatibility: Map<Compatibility, List<MemberDescriptor>>
|
||||
): Boolean {
|
||||
return compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
|
||||
val expectedOnes = ExpectedActualResolver.findExpectedForActual(actual, module)
|
||||
expectedOnes != null && Compatible in expectedOnes.keys
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,19 +208,16 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
?.run { VfsUtilCore.virtualToIoFile(psiFile.virtualFile) }
|
||||
|
||||
private fun checkActualDeclarationHasExpected(
|
||||
reportOn: KtNamedDeclaration, descriptor: MemberDescriptor, trace: BindingTrace, checkActual: Boolean
|
||||
reportOn: KtNamedDeclaration,
|
||||
descriptor: MemberDescriptor,
|
||||
trace: BindingTrace,
|
||||
checkActual: Boolean,
|
||||
moduleVisibilityFilter: ModuleFilter
|
||||
) {
|
||||
// TODO: ideally, we should always use common module here
|
||||
// However, in compiler context platform & common modules are joined into one module,
|
||||
// so there is yet no "common module" in this situation.
|
||||
// So yet we are using own module in compiler context and common module in IDE context.
|
||||
val commonOrOwnModules = descriptor.module.expectedByModules.ifEmpty { listOf(descriptor.module) }
|
||||
val compatibility = commonOrOwnModules
|
||||
.mapNotNull { ExpectedActualResolver.findExpectedForActual(descriptor, it) }
|
||||
.ifEmpty { return }
|
||||
.fold(LinkedHashMap<Compatibility, List<MemberDescriptor>>()) { resultMap, partialMap ->
|
||||
resultMap.apply { putAll(partialMap) }
|
||||
}
|
||||
val compatibility = ExpectedActualResolver.findExpectedForActual(descriptor, descriptor.module, moduleVisibilityFilter)
|
||||
?: return
|
||||
|
||||
checkAmbiguousExpects(compatibility, trace, reportOn, descriptor)
|
||||
|
||||
val hasActualModifier = descriptor.isActual && reportOn.hasActualModifier()
|
||||
if (!hasActualModifier) {
|
||||
@@ -174,7 +263,7 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
if (nonTrivialUnfulfilled.isNotEmpty()) {
|
||||
val classDescriptor =
|
||||
(descriptor as? TypeAliasDescriptor)?.expandedType?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||
?: (descriptor as ClassDescriptor)
|
||||
?: (descriptor as ClassDescriptor)
|
||||
trace.report(
|
||||
Errors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS.on(
|
||||
reportOn, classDescriptor, nonTrivialUnfulfilled
|
||||
@@ -190,8 +279,8 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
val expected = compatibility[Compatible]!!.first()
|
||||
if (expected is ClassDescriptor && expected.kind == ClassKind.ANNOTATION_CLASS) {
|
||||
val actualConstructor =
|
||||
(descriptor as? ClassDescriptor)?.constructors?.singleOrNull() ?:
|
||||
(descriptor as? TypeAliasDescriptor)?.constructors?.singleOrNull()?.underlyingConstructorDescriptor
|
||||
(descriptor as? ClassDescriptor)?.constructors?.singleOrNull()
|
||||
?: (descriptor as? TypeAliasDescriptor)?.constructors?.singleOrNull()?.underlyingConstructorDescriptor
|
||||
val expectedConstructor = expected.constructors.singleOrNull()
|
||||
if (expectedConstructor != null && actualConstructor != null) {
|
||||
checkAnnotationConstructors(expectedConstructor, actualConstructor, trace, reportOn)
|
||||
@@ -200,6 +289,31 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAmbiguousExpects(
|
||||
compatibility: Map<Compatibility, List<MemberDescriptor>>,
|
||||
trace: BindingTrace,
|
||||
reportOn: KtNamedDeclaration,
|
||||
descriptor: MemberDescriptor
|
||||
) {
|
||||
val modulesWithAtLeastWeaklyCompatibleExpects = compatibility.asSequence()
|
||||
.filter { (compatibility, _) ->
|
||||
compatibility.isCompatibleOrWeakCompatible()
|
||||
}
|
||||
.map { (_, members) -> members }
|
||||
.flatten()
|
||||
.map { it.module }
|
||||
.distinct()
|
||||
.toList()
|
||||
|
||||
if (modulesWithAtLeastWeaklyCompatibleExpects.size > 1) {
|
||||
trace.report(Errors.AMBIGUOUS_EXPECTS.on(reportOn, descriptor, modulesWithAtLeastWeaklyCompatibleExpects))
|
||||
}
|
||||
}
|
||||
|
||||
private fun Compatibility.isCompatibleOrWeakCompatible() =
|
||||
this is Compatible ||
|
||||
this is Incompatible && kind == ExpectedActualResolver.Compatibility.IncompatibilityKind.WEAK
|
||||
|
||||
// we don't require `actual` modifier on
|
||||
// - annotation constructors, because annotation classes can only have one constructor
|
||||
// - inline class primary constructors, because inline class must have primary constructor
|
||||
@@ -256,11 +370,7 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
return bindingContext.get(BindingContext.COMPILE_TIME_VALUE, declaration.defaultValue)?.toConstantValue(expectedType)
|
||||
}
|
||||
|
||||
for (extractor in argumentExtractors) {
|
||||
extractor.extractDefaultValue(actualParameter, expectedType)?.let { return it }
|
||||
}
|
||||
|
||||
return null
|
||||
return argumentExtractor.extractDefaultValue(actualParameter, expectedType)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -289,5 +399,14 @@ class ExpectedActualDeclarationChecker(val argumentExtractors: List<ActualAnnota
|
||||
|
||||
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
||||
|
||||
private fun <K, V> LinkedHashMap<K, List<V>>.merge(other: Map<K, List<V>>): LinkedHashMap<K, List<V>> {
|
||||
for ((key, newValue) in other) {
|
||||
val oldValue = this[key] ?: emptyList()
|
||||
this[key] = oldValue + newValue
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,8 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.getMultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
|
||||
|
||||
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
||||
@@ -23,8 +22,9 @@ class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
||||
}
|
||||
|
||||
val ktFile = element.containingFile as KtFile
|
||||
// TODO(dsavvinov): unify for compiler/IDE
|
||||
// The first part is for the compiler, and the second one is for IDE
|
||||
if (ktFile.isCommonSource != true && targetDescriptor.module.getMultiTargetPlatform() != MultiTargetPlatform.Common) {
|
||||
if (ktFile.isCommonSource != true && !targetDescriptor.platform.isCommon()) {
|
||||
context.trace.report(Errors.OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE.on(element))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
|
||||
@DefaultImplementation(PlatformDiagnosticSuppressor.Default::class)
|
||||
interface PlatformDiagnosticSuppressor {
|
||||
interface PlatformDiagnosticSuppressor : PlatformSpecificExtension<PlatformDiagnosticSuppressor>{
|
||||
fun shouldReportUnusedParameter(parameter: VariableDescriptor): Boolean
|
||||
|
||||
fun shouldReportNoBody(descriptor: CallableMemberDescriptor): Boolean
|
||||
@@ -32,3 +34,18 @@ interface PlatformDiagnosticSuppressor {
|
||||
override fun shouldReportNoBody(descriptor: CallableMemberDescriptor): Boolean = true
|
||||
}
|
||||
}
|
||||
|
||||
class CompositePlatformDiagnosticSuppressor(private val suppressors: List<PlatformDiagnosticSuppressor>) : PlatformDiagnosticSuppressor {
|
||||
override fun shouldReportUnusedParameter(parameter: VariableDescriptor): Boolean =
|
||||
suppressors.all { it.shouldReportUnusedParameter(parameter) }
|
||||
|
||||
override fun shouldReportNoBody(descriptor: CallableMemberDescriptor): Boolean =
|
||||
suppressors.all { it.shouldReportNoBody(descriptor) }
|
||||
}
|
||||
|
||||
class PlatformDiagnosticSuppressorClashesResolver : PlatformExtensionsClashResolver<PlatformDiagnosticSuppressor>(
|
||||
PlatformDiagnosticSuppressor::class.java
|
||||
) {
|
||||
override fun resolveExtensionsClash(extensions: List<PlatformDiagnosticSuppressor>): PlatformDiagnosticSuppressor =
|
||||
CompositePlatformDiagnosticSuppressor(extensions)
|
||||
}
|
||||
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.resolve.deprecation
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -61,7 +63,7 @@ internal fun createDeprecationDiagnostic(
|
||||
}
|
||||
|
||||
@DefaultImplementation(CoroutineCompatibilitySupport::class)
|
||||
class CoroutineCompatibilitySupport private constructor(val enabled: Boolean) {
|
||||
class CoroutineCompatibilitySupport private constructor(val enabled: Boolean) : PlatformSpecificExtension<CoroutineCompatibilitySupport>{
|
||||
@Suppress("unused")
|
||||
constructor() : this(true)
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.jetbrains.kotlin.resolve.lazy
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
|
||||
@DefaultImplementation(impl = DelegationFilter.Default::class)
|
||||
interface DelegationFilter {
|
||||
|
||||
fun filter(interfaceMember: CallableMemberDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.KtImportInfo
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
@@ -40,13 +40,13 @@ data class FileScopes(val lexicalScope: LexicalScope, val importingScope: Import
|
||||
class FileScopeFactory(
|
||||
private val topLevelDescriptorProvider: TopLevelDescriptorProvider,
|
||||
private val bindingTrace: BindingTrace,
|
||||
private val targetPlatform: TargetPlatform,
|
||||
private val compilerServices: PlatformDependentCompilerServices,
|
||||
private val components: ImportResolutionComponents
|
||||
) {
|
||||
private val defaultImports =
|
||||
targetPlatform.getDefaultImports(components.languageVersionSettings, includeLowPriorityImports = false).map(::DefaultImportImpl)
|
||||
compilerServices.getDefaultImports(components.languageVersionSettings, includeLowPriorityImports = false).map(::DefaultImportImpl)
|
||||
|
||||
private val defaultLowPriorityImports = targetPlatform.defaultLowPriorityImports.map(::DefaultImportImpl)
|
||||
private val defaultLowPriorityImports = compilerServices.defaultLowPriorityImports.map(::DefaultImportImpl)
|
||||
|
||||
private class DefaultImportImpl(private val importPath: ImportPath) : KtImportInfo {
|
||||
override val isAllUnder: Boolean get() = importPath.isAllUnder
|
||||
@@ -95,7 +95,7 @@ class FileScopeFactory(
|
||||
tempTrace,
|
||||
packageFragment = null,
|
||||
aliasImportNames = aliasImportNames,
|
||||
excludedImports = targetPlatform.excludedImports
|
||||
excludedImports = compilerServices.excludedImports
|
||||
)
|
||||
val lowPriority = createDefaultImportResolver(
|
||||
AllUnderImportsIndexed(defaultLowPriorityImports.also { imports ->
|
||||
|
||||
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.ModifierCheckerCore;
|
||||
import org.jetbrains.kotlin.resolve.ModifiersChecker;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
@@ -427,7 +424,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
|
||||
ModifiersChecker.ModifiersCheckingProcedure modifiersCheckingProcedure = components.modifiersChecker.withTrace(context.trace);
|
||||
modifiersCheckingProcedure.checkModifiersForLocalDeclaration(loopParameter, variableDescriptor);
|
||||
components.identifierChecker.checkDeclaration(loopParameter, context.trace);
|
||||
for (IdentifierChecker checker : components.identifierCheckers) {
|
||||
checker.checkDeclaration(loopParameter, context.trace);
|
||||
}
|
||||
loopScope.addVariableDescriptor(variableDescriptor);
|
||||
KtDestructuringDeclaration multiParameter = loopParameter.getDestructuringDeclaration();
|
||||
if (multiParameter != null) {
|
||||
@@ -438,7 +437,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
|
||||
);
|
||||
modifiersCheckingProcedure.checkModifiersForDestructuringDeclaration(multiParameter);
|
||||
components.identifierChecker.checkDeclaration(multiParameter, context.trace);
|
||||
for (IdentifierChecker checker : components.identifierCheckers) {
|
||||
checker.checkDeclaration(multiParameter, context.trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,7 +789,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
private void checkCatchParameterDeclaration(KtParameter catchParameter, ExpressionTypingContext context) {
|
||||
components.identifierChecker.checkDeclaration(catchParameter, context.trace);
|
||||
components.identifierCheckers.forEach((checker) -> checker.checkDeclaration(catchParameter, context.trace));
|
||||
ModifiersChecker.ModifiersCheckingProcedure modifiersChecking = components.modifiersChecker.withTrace(context.trace);
|
||||
modifiersChecking.checkParameterHasNoValOrVar(catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
|
||||
ModifierCheckerCore.INSTANCE.check(catchParameter, context.trace, null, components.languageVersionSettings);
|
||||
|
||||
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
@@ -823,7 +825,7 @@ class DoubleColonExpressionResolver(
|
||||
// By default, function types with big arity are supported. On platforms where they are not supported by default (e.g. JVM),
|
||||
// LANGUAGE_VERSION_DEPENDENT should be used which makes the code check if the corresponding language feature is enabled.
|
||||
@DefaultImplementation(FunctionWithBigAritySupport::class)
|
||||
class FunctionWithBigAritySupport private constructor(val shouldCheckLanguageVersionSettings: Boolean) {
|
||||
class FunctionWithBigAritySupport private constructor(val shouldCheckLanguageVersionSettings: Boolean) : PlatformSpecificExtension<FunctionWithBigAritySupport>{
|
||||
constructor() : this(false)
|
||||
|
||||
companion object {
|
||||
@@ -831,3 +833,13 @@ class FunctionWithBigAritySupport private constructor(val shouldCheckLanguageVer
|
||||
val LANGUAGE_VERSION_DEPENDENT = FunctionWithBigAritySupport(true)
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionWithBigAritySupportClashesResolver :
|
||||
PlatformExtensionsClashResolver<FunctionWithBigAritySupport>(FunctionWithBigAritySupport::class.java) {
|
||||
|
||||
override fun resolveExtensionsClash(extensions: List<FunctionWithBigAritySupport>): FunctionWithBigAritySupport =
|
||||
if (extensions.any { it.shouldCheckLanguageVersionSettings })
|
||||
FunctionWithBigAritySupport.LANGUAGE_VERSION_DEPENDENT
|
||||
else
|
||||
FunctionWithBigAritySupport()
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class ExpressionTypingComponents {
|
||||
/*package*/ ModifiersChecker modifiersChecker;
|
||||
/*package*/ DataFlowAnalyzer dataFlowAnalyzer;
|
||||
/*package*/ Iterable<CallChecker> callCheckers;
|
||||
/*package*/ IdentifierChecker identifierChecker;
|
||||
/*package*/ Iterable<IdentifierChecker> identifierCheckers;
|
||||
/*package*/ DeclarationsCheckerBuilder declarationsCheckerBuilder;
|
||||
/*package*/ LocalVariableResolver localVariableResolver;
|
||||
/*package*/ LookupTracker lookupTracker;
|
||||
@@ -164,8 +164,8 @@ public class ExpressionTypingComponents {
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setIdentifierChecker(@NotNull IdentifierChecker identifierChecker) {
|
||||
this.identifierChecker = identifierChecker;
|
||||
public void setIdentifierCheckers(@NotNull Iterable<IdentifierChecker> identifierCheckers) {
|
||||
this.identifierCheckers = identifierCheckers;
|
||||
}
|
||||
|
||||
@Inject
|
||||
|
||||
@@ -140,7 +140,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
components.destructuringDeclarationResolver
|
||||
.defineLocalVariablesFromDestructuringDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
|
||||
components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiDeclaration);
|
||||
components.identifierChecker.checkDeclaration(multiDeclaration, context.trace);
|
||||
components.identifierCheckers.forEach((checker) -> checker.checkDeclaration(multiDeclaration, context.trace));
|
||||
|
||||
if (expressionReceiver == null) {
|
||||
return TypeInfoFactoryKt.noTypeInfo(context);
|
||||
|
||||
@@ -109,7 +109,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
)
|
||||
|
||||
components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(function, functionDescriptor)
|
||||
components.identifierChecker.checkDeclaration(function, context.trace)
|
||||
components.identifierCheckers.forEach { it.checkDeclaration(function, context.trace) }
|
||||
components.declarationsCheckerBuilder.withTrace(context.trace).checkFunction(function, functionDescriptor)
|
||||
|
||||
return if (isDeclaration) {
|
||||
@@ -150,9 +150,9 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
val suspendFunctionTypeExpected = expectedType.isSuspendFunctionType()
|
||||
|
||||
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
|
||||
expression.valueParameters.forEach {
|
||||
components.identifierChecker.checkDeclaration(it, context.trace)
|
||||
UnderscoreChecker.checkNamed(it, context.trace, components.languageVersionSettings, allowSingleUnderscore = true)
|
||||
expression.valueParameters.forEach { param ->
|
||||
components.identifierCheckers.forEach { it.checkDeclaration(param, context.trace) }
|
||||
UnderscoreChecker.checkNamed(param, context.trace, components.languageVersionSettings, allowSingleUnderscore = true)
|
||||
}
|
||||
val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected)
|
||||
functionDescriptor.setReturnType(safeReturnType)
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.GlobalContext
|
||||
import org.jetbrains.kotlin.context.withModule
|
||||
@@ -60,9 +60,9 @@ class LocalClassifierAnalyzer(
|
||||
private val typeResolver: TypeResolver,
|
||||
private val annotationResolver: AnnotationResolver,
|
||||
private val platform: TargetPlatform,
|
||||
private val compilerServices: PlatformDependentCompilerServices,
|
||||
private val lookupTracker: LookupTracker,
|
||||
private val supertypeLoopChecker: SupertypeLoopChecker,
|
||||
private val targetPlatformVersion: TargetPlatformVersion,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val delegationFilter: DelegationFilter,
|
||||
private val wrappedTypeFactory: WrappedTypeFactory
|
||||
@@ -81,7 +81,6 @@ class LocalClassifierAnalyzer(
|
||||
context.trace,
|
||||
platform,
|
||||
lookupTracker,
|
||||
targetPlatformVersion,
|
||||
languageVersionSettings,
|
||||
context.statementFilter,
|
||||
LocalClassDescriptorHolder(
|
||||
@@ -100,7 +99,8 @@ class LocalClassifierAnalyzer(
|
||||
SyntheticResolveExtension.getInstance(project),
|
||||
delegationFilter,
|
||||
wrappedTypeFactory
|
||||
)
|
||||
),
|
||||
compilerServices
|
||||
)
|
||||
|
||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
@@ -55,6 +56,7 @@ interface KotlinResolutionCallbacks {
|
||||
fun getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedAtom: ResolvedCallAtom): UnwrappedType?
|
||||
}
|
||||
|
||||
@DefaultImplementation(impl = SamConversionTransformer.Empty::class)
|
||||
interface SamConversionTransformer {
|
||||
fun getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType?
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.results
|
||||
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
@@ -30,7 +32,7 @@ interface SpecificityComparisonCallbacks {
|
||||
fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean
|
||||
}
|
||||
|
||||
interface TypeSpecificityComparator {
|
||||
interface TypeSpecificityComparator : PlatformSpecificExtension<TypeSpecificityComparator> {
|
||||
fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean
|
||||
|
||||
object NONE : TypeSpecificityComparator {
|
||||
@@ -38,6 +40,12 @@ interface TypeSpecificityComparator {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(dsavvinov): check that it's correct indeed
|
||||
class TypeSpecificityComparatorClashesResolver : PlatformExtensionsClashResolver.FallbackToDefault<TypeSpecificityComparator>(
|
||||
TypeSpecificityComparator.NONE,
|
||||
TypeSpecificityComparator::class.java
|
||||
)
|
||||
|
||||
class FlatSignature<out T> private constructor(
|
||||
val origin: T,
|
||||
val typeParameters: Collection<TypeParameterDescriptor>,
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
|
||||
object ExpectedActualResolver {
|
||||
// FIXME(dsavvinov): review clients, as they won't work properly in HMPP projects
|
||||
fun MemberDescriptor.findCompatibleActualForExpected(platformModule: ModuleDescriptor): List<MemberDescriptor> =
|
||||
findActualForExpected(this, platformModule)?.get(Compatible).orEmpty()
|
||||
|
||||
@@ -42,10 +43,14 @@ object ExpectedActualResolver {
|
||||
fun MemberDescriptor.findCompatibleExpectedForActual(commonModule: ModuleDescriptor): List<MemberDescriptor> =
|
||||
findExpectedForActual(this, commonModule)?.get(Compatible).orEmpty()
|
||||
|
||||
fun findActualForExpected(expected: MemberDescriptor, platformModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? {
|
||||
fun findActualForExpected(
|
||||
expected: MemberDescriptor,
|
||||
platformModule: ModuleDescriptor,
|
||||
moduleVisibilityFilter: ModuleFilter = onlyFromThisModule(platformModule)
|
||||
): Map<Compatibility, List<MemberDescriptor>>? {
|
||||
return when (expected) {
|
||||
is CallableMemberDescriptor -> {
|
||||
expected.findNamesakesFromModule(platformModule).filter { actual ->
|
||||
expected.findNamesakesFromModule(platformModule, moduleVisibilityFilter).filter { actual ->
|
||||
expected != actual && !actual.isExpect &&
|
||||
// TODO: support non-source definitions (e.g. from Java)
|
||||
actual.source.containingFile != SourceFile.NO_SOURCE_FILE
|
||||
@@ -54,7 +59,7 @@ object ExpectedActualResolver {
|
||||
}
|
||||
}
|
||||
is ClassDescriptor -> {
|
||||
expected.findClassifiersFromModule(platformModule).filter { actual ->
|
||||
expected.findClassifiersFromModule(platformModule, moduleVisibilityFilter).filter { actual ->
|
||||
expected != actual && !actual.isExpect &&
|
||||
actual.source.containingFile != SourceFile.NO_SOURCE_FILE
|
||||
}.groupBy { actual ->
|
||||
@@ -65,7 +70,11 @@ object ExpectedActualResolver {
|
||||
}
|
||||
}
|
||||
|
||||
fun findExpectedForActual(actual: MemberDescriptor, commonModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? {
|
||||
fun findExpectedForActual(
|
||||
actual: MemberDescriptor,
|
||||
commonModule: ModuleDescriptor,
|
||||
moduleFilter: (ModuleDescriptor) -> Boolean = onlyFromThisModule(commonModule)
|
||||
): Map<Compatibility, List<MemberDescriptor>>? {
|
||||
return when (actual) {
|
||||
is CallableMemberDescriptor -> {
|
||||
val container = actual.containingDeclaration
|
||||
@@ -73,10 +82,10 @@ object ExpectedActualResolver {
|
||||
is ClassifierDescriptorWithTypeParameters -> {
|
||||
// TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored
|
||||
val expectedClass =
|
||||
findExpectedForActual(container, commonModule)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor
|
||||
findExpectedForActual(container, commonModule, moduleFilter)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor
|
||||
expectedClass?.getMembers(actual.name)?.filterIsInstance<CallableMemberDescriptor>().orEmpty()
|
||||
}
|
||||
is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonModule)
|
||||
is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonModule, moduleFilter)
|
||||
else -> return null // do not report anything for incorrect code, e.g. 'actual' local function
|
||||
}
|
||||
|
||||
@@ -95,7 +104,7 @@ object ExpectedActualResolver {
|
||||
}
|
||||
}
|
||||
is ClassifierDescriptorWithTypeParameters -> {
|
||||
actual.findClassifiersFromModule(commonModule).filter { declaration ->
|
||||
actual.findClassifiersFromModule(commonModule, moduleFilter).filter { declaration ->
|
||||
actual != declaration &&
|
||||
declaration is ClassDescriptor && declaration.isExpect
|
||||
}.groupBy { expected ->
|
||||
@@ -106,14 +115,16 @@ object ExpectedActualResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.findNamesakesFromModule(module: ModuleDescriptor): Collection<CallableMemberDescriptor> {
|
||||
val containingDeclaration = containingDeclaration
|
||||
val scopes = when (containingDeclaration) {
|
||||
private fun CallableMemberDescriptor.findNamesakesFromModule(
|
||||
module: ModuleDescriptor,
|
||||
moduleFilter: (ModuleDescriptor) -> Boolean
|
||||
): Collection<CallableMemberDescriptor> {
|
||||
val scopes = when (val containingDeclaration = containingDeclaration) {
|
||||
is PackageFragmentDescriptor -> {
|
||||
listOf(module.getPackage(containingDeclaration.fqName).memberScope)
|
||||
}
|
||||
is ClassDescriptor -> {
|
||||
val classes = containingDeclaration.findClassifiersFromModule(module)
|
||||
val classes = containingDeclaration.findClassifiersFromModule(module, moduleFilter)
|
||||
.mapNotNull { if (it is TypeAliasDescriptor) it.classDescriptor else it }
|
||||
.filterIsInstance<ClassDescriptor>()
|
||||
if (this is ConstructorDescriptor) return classes.flatMap { it.constructors }
|
||||
@@ -124,15 +135,23 @@ object ExpectedActualResolver {
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is FunctionDescriptor -> scopes.flatMap { it.getContributedFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED) }
|
||||
is PropertyDescriptor -> scopes.flatMap { it.getContributedVariables(name, NoLookupLocation.FOR_ALREADY_TRACKED) }
|
||||
is FunctionDescriptor -> scopes.flatMap {
|
||||
it.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS, { it == name })
|
||||
.filter { it.name == name } as Collection<CallableMemberDescriptor>
|
||||
}
|
||||
|
||||
is PropertyDescriptor -> scopes.flatMap {
|
||||
it.getContributedDescriptors(DescriptorKindFilter.VARIABLES, { it == name })
|
||||
.filter { it.name == name } as Collection<CallableMemberDescriptor>
|
||||
}
|
||||
|
||||
else -> throw AssertionError("Unsupported declaration: $this")
|
||||
}.onlyFromThis(module)
|
||||
}.applyFilter(moduleFilter)
|
||||
}
|
||||
|
||||
private fun ClassifierDescriptorWithTypeParameters.findClassifiersFromModule(
|
||||
module: ModuleDescriptor,
|
||||
includeDependencies: Boolean = false
|
||||
moduleFilter: (ModuleDescriptor) -> Boolean
|
||||
): Collection<ClassifierDescriptorWithTypeParameters> {
|
||||
val classId = classId ?: return emptyList()
|
||||
|
||||
@@ -142,7 +161,7 @@ object ExpectedActualResolver {
|
||||
|
||||
val segments = classId.relativeClassName.pathSegments()
|
||||
var classifiers = module.getPackage(classId.packageFqName).memberScope.getAllClassifiers(segments.first())
|
||||
if (!includeDependencies) classifiers = classifiers.onlyFromThis(module)
|
||||
classifiers = classifiers.applyFilter(moduleFilter)
|
||||
|
||||
for (name in segments.subList(1, segments.size)) {
|
||||
classifiers = classifiers.mapNotNull { classifier ->
|
||||
@@ -155,9 +174,6 @@ object ExpectedActualResolver {
|
||||
return classifiers
|
||||
}
|
||||
|
||||
private fun <T : DeclarationDescriptor> Iterable<T>.onlyFromThis(module: ModuleDescriptor): List<T> =
|
||||
filter { it.module == module }
|
||||
|
||||
sealed class Compatibility {
|
||||
// For IncompatibilityKind.STRONG `actual` declaration is considered as overload and error reports on expected declaration
|
||||
enum class IncompatibilityKind {
|
||||
@@ -231,7 +247,9 @@ object ExpectedActualResolver {
|
||||
platformModule: ModuleDescriptor = b.module,
|
||||
parentSubstitutor: Substitutor? = null
|
||||
): Compatibility {
|
||||
assert(a.name == b.name) { "This function should be invoked only for declarations with the same name: $a, $b" }
|
||||
assert(a.name == b.name) {
|
||||
"This function should be invoked only for declarations with the same name: $a, $b"
|
||||
}
|
||||
assert(a.containingDeclaration is ClassifierDescriptorWithTypeParameters == b.containingDeclaration is ClassifierDescriptorWithTypeParameters) {
|
||||
"This function should be invoked only for declarations in the same kind of container (both members or both top level): $a, $b"
|
||||
}
|
||||
@@ -329,7 +347,7 @@ object ExpectedActualResolver {
|
||||
return expected is ClassifierDescriptorWithTypeParameters &&
|
||||
expected.isExpect &&
|
||||
actual is ClassifierDescriptorWithTypeParameters &&
|
||||
expected.findClassifiersFromModule(platformModule, includeDependencies = true).any { classifier ->
|
||||
expected.findClassifiersFromModule(platformModule, moduleFilter = ALL_MODULES).any { classifier ->
|
||||
// Note that it's fine to only check that this "actual typealias" expands to the expected class, without checking
|
||||
// whether the type arguments in the expansion are in the correct order or have the correct variance, because we only
|
||||
// allow simple cases like "actual typealias Foo<A, B> = FooImpl<A, B>", see DeclarationsChecker#checkActualTypeAlias
|
||||
@@ -537,3 +555,4 @@ object ExpectedActualResolver {
|
||||
(parent?.invoke(type) ?: type)?.asTypeProjection()?.let(typeSubstitutor::substitute)?.type
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.resolve.multiplatform
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
typealias ModuleFilter = (ModuleDescriptor) -> Boolean
|
||||
|
||||
fun onlyFromThisModule(module: ModuleDescriptor): ModuleFilter = { it == module }
|
||||
|
||||
val ALL_MODULES: ModuleFilter = { true }
|
||||
|
||||
fun <T : DeclarationDescriptor> Iterable<T>.applyFilter(filter: ModuleFilter): List<T> = filter { filter(it.module) }
|
||||
@@ -10,7 +10,7 @@ expect fun foo2(): Int
|
||||
|
||||
expect val s: String
|
||||
|
||||
expect open class <!JVM:PACKAGE_OR_CLASSIFIER_REDECLARATION!>Foo3<!>
|
||||
expect open class <!JVM:AMBIGUOUS_ACTUALS, JVM:PACKAGE_OR_CLASSIFIER_REDECLARATION!>Foo3<!>
|
||||
|
||||
// MODULE: m2-jvm(m1-common)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect fun foo()
|
||||
expect fun <!JS:AMBIGUOUS_ACTUALS, JVM:AMBIGUOUS_ACTUALS!>foo<!>()
|
||||
|
||||
// MODULE: m2-jvm(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.TestsCompilerError
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
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.createContainerForLazyResolveWithJava
|
||||
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
@@ -39,6 +39,11 @@ import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||
@@ -59,6 +64,7 @@ import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE_AL
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import java.lang.IllegalStateException
|
||||
import java.util.*
|
||||
import java.util.function.Predicate
|
||||
import java.util.regex.Pattern
|
||||
@@ -166,13 +172,13 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
val actualText = StringBuilder()
|
||||
for (testFile in files) {
|
||||
val module = testFile.module
|
||||
val isCommonModule = modules[module]!!.getMultiTargetPlatform() == MultiTargetPlatform.Common
|
||||
val isCommonModule = modules[module]!!.platform.isCommon()
|
||||
val implementingModules =
|
||||
if (!isCommonModule) emptyList()
|
||||
else modules.entries.filter { (testModule) -> module in testModule?.getDependencies().orEmpty() }
|
||||
val implementingModulesBindings = implementingModules.mapNotNull { (testModule, moduleDescriptor) ->
|
||||
val platform = moduleDescriptor.getCapability(MultiTargetPlatform.CAPABILITY)
|
||||
if (platform is MultiTargetPlatform.Specific) platform to moduleBindings[testModule]!!
|
||||
val platform = moduleDescriptor.platform
|
||||
if (platform != null && !platform.isCommon()) platform to moduleBindings[testModule]!!
|
||||
else null
|
||||
}
|
||||
val moduleDescriptor = modules[module]!!
|
||||
@@ -356,12 +362,11 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
|
||||
val moduleDescriptor = moduleContext.module as ModuleDescriptorImpl
|
||||
|
||||
val platform = moduleDescriptor.getMultiTargetPlatform()
|
||||
if (platform == MultiTargetPlatform.Common) {
|
||||
return CommonAnalyzerFacade.analyzeFiles(
|
||||
val platform = moduleDescriptor.platform
|
||||
if (platform.isCommon()) {
|
||||
return CommonResolverForModuleFactory.analyzeFiles(
|
||||
files, moduleDescriptor.name, true, languageVersionSettings,
|
||||
mapOf(
|
||||
MultiTargetPlatform.CAPABILITY to MultiTargetPlatform.Common,
|
||||
MODULE_FILES to files
|
||||
)
|
||||
) { _ ->
|
||||
@@ -376,18 +381,18 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
val moduleContentScope = GlobalSearchScope.allScope(moduleContext.project)
|
||||
val moduleClassResolver = SingleModuleClassResolver()
|
||||
|
||||
val container = createContainerForTopDownAnalyzerForJvm(
|
||||
val container = createContainerForLazyResolveWithJava(
|
||||
JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget), // TODO(dsavvinov): do not pass JvmTarget around
|
||||
moduleContext,
|
||||
moduleTrace,
|
||||
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
|
||||
moduleContentScope,
|
||||
LookupTracker.DO_NOTHING,
|
||||
moduleClassResolver,
|
||||
CompilerEnvironment, LookupTracker.DO_NOTHING,
|
||||
ExpectActualTracker.DoNothing,
|
||||
environment.createPackagePartProvider(moduleContentScope),
|
||||
moduleClassResolver,
|
||||
CompilerEnvironment,
|
||||
jvmTarget,
|
||||
languageVersionSettings
|
||||
languageVersionSettings,
|
||||
useBuiltInsProvider = true
|
||||
)
|
||||
|
||||
container.initJvmBuiltInsForTopDownAnalysis()
|
||||
@@ -417,7 +422,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
// E.g. "<!JVM:ACTUAL_WITHOUT_EXPECT!>...<!>
|
||||
val result = ArrayList<KtFile>(0)
|
||||
for (dependency in dependencies) {
|
||||
if (dependency.getCapability(MultiTargetPlatform.CAPABILITY) == MultiTargetPlatform.Common) {
|
||||
if (dependency.platform.isCommon()) {
|
||||
val files = dependency.getCapability(MODULE_FILES)
|
||||
?: error("MODULE_FILES should have been set for the common module: $dependency")
|
||||
result.addAll(files)
|
||||
@@ -585,16 +590,22 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
emptyList()
|
||||
|
||||
protected open fun createModule(moduleName: String, storageManager: StorageManager): ModuleDescriptorImpl {
|
||||
val nameSuffix = moduleName.substringAfterLast("-", "")
|
||||
val nameSuffix = moduleName.substringAfterLast("-", "").toUpperCase()
|
||||
val platform =
|
||||
if (nameSuffix.isEmpty()) null
|
||||
else if (nameSuffix == "common") MultiTargetPlatform.Common else MultiTargetPlatform.Specific(nameSuffix.toUpperCase())
|
||||
when {
|
||||
nameSuffix.isEmpty() -> null // TODO(dsavvinov): this leads to 'null'-platform in ModuleDescriptor
|
||||
nameSuffix == "COMMON" -> CommonPlatforms.defaultCommonPlatform
|
||||
nameSuffix == "JVM" -> JvmPlatforms.defaultJvmPlatform // TODO(dsavvinov): determine JvmTarget precisely
|
||||
nameSuffix == "JS" -> JsPlatforms.defaultJsPlatform
|
||||
nameSuffix == "NATIVE" -> KonanPlatforms.defaultKonanPlatform
|
||||
else -> throw IllegalStateException("Can't determine platform by name $nameSuffix")
|
||||
}
|
||||
val builtIns = JvmBuiltIns(storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER)
|
||||
return ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, builtIns, platform)
|
||||
}
|
||||
|
||||
protected open fun createSealedModule(storageManager: StorageManager): ModuleDescriptorImpl =
|
||||
createModule("test-module", storageManager).apply {
|
||||
createModule("test-module-jvm", storageManager).apply {
|
||||
setDependencies(this, builtIns.builtInsModule)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
|
||||
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.js.resolve.MODULE_KIND
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -84,7 +84,7 @@ abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractDiagnosticsTest() {
|
||||
override fun shouldSkipJvmSignatureDiagnostics(groupedByModule: Map<TestModule?, List<TestFile>>): Boolean = true
|
||||
|
||||
override fun createModule(moduleName: String, storageManager: StorageManager): ModuleDescriptorImpl =
|
||||
ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, JsPlatform.builtIns)
|
||||
ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, JsPlatformCompilerServices.builtIns)
|
||||
|
||||
override fun createSealedModule(storageManager: StorageManager): ModuleDescriptorImpl {
|
||||
val module = createModule("kotlin-js-test-module", storageManager)
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -223,7 +223,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
||||
|
||||
fun getActualText(
|
||||
bindingContext: BindingContext,
|
||||
implementingModulesBindings: List<Pair<MultiTargetPlatform, BindingContext>>,
|
||||
implementingModulesBindings: List<Pair<TargetPlatform, BindingContext>>,
|
||||
actualText: StringBuilder,
|
||||
skipJvmSignatureDiagnostics: Boolean,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
@@ -325,7 +325,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
||||
ktFile,
|
||||
filteredDiagnostics,
|
||||
diagnosticToExpectedDiagnostic,
|
||||
com.intellij.util.Function { file -> file.text },
|
||||
{ file -> file.text },
|
||||
uncheckedDiagnostics,
|
||||
withNewInferenceDirective,
|
||||
renderDiagnosticMessages
|
||||
|
||||
@@ -7,13 +7,16 @@ package org.jetbrains.kotlin.fir
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentCompilerServices
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformCompilerServices
|
||||
|
||||
class FirTestModuleInfo(
|
||||
override val name: Name = Name.identifier("TestModule"),
|
||||
val dependencies: MutableList<ModuleInfo> = mutableListOf(),
|
||||
override val platform: TargetPlatform = JvmPlatform
|
||||
override val platform: TargetPlatform = JvmPlatforms.defaultJvmPlatform,
|
||||
override val compilerServices: PlatformDependentCompilerServices = JvmPlatformCompilerServices
|
||||
) : ModuleInfo {
|
||||
override fun dependencies(): List<ModuleInfo> = dependencies
|
||||
}
|
||||
@@ -27,27 +27,33 @@ import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
|
||||
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentCompilerServices
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformCompilerServices
|
||||
|
||||
fun createResolveSessionForFiles(
|
||||
project: Project,
|
||||
syntheticFiles: Collection<KtFile>,
|
||||
addBuiltIns: Boolean
|
||||
): ResolveSession {
|
||||
val projectContext = ProjectContext(project)
|
||||
val testModule = TestModule(addBuiltIns)
|
||||
val projectContext = ProjectContext(project, "lazy resolve test utils")
|
||||
val testModule =
|
||||
TestModule(addBuiltIns)
|
||||
val platformParameters = JvmPlatformParameters(
|
||||
packagePartProviderFactory = { PackagePartProvider.Empty },
|
||||
moduleByJavaClass = { testModule }
|
||||
)
|
||||
val resolverForProject = ResolverForProjectImpl(
|
||||
"test",
|
||||
projectContext, listOf(testModule),
|
||||
{ ModuleContent(it, syntheticFiles, GlobalSearchScope.allScope(project)) },
|
||||
moduleLanguageSettingsProvider = LanguageSettingsProvider.Default,
|
||||
resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade },
|
||||
platformParameters = { _ ->
|
||||
JvmPlatformParameters(
|
||||
packagePartProviderFactory = { PackagePartProvider.Empty },
|
||||
moduleByJavaClass = { testModule }
|
||||
)
|
||||
resolverForModuleFactoryByPlatform = {
|
||||
JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform)
|
||||
}
|
||||
)
|
||||
return resolverForProject.resolverForModule(testModule).componentProvider.get<ResolveSession>()
|
||||
@@ -57,8 +63,14 @@ private class TestModule(val dependsOnBuiltIns: Boolean) : ModuleInfo {
|
||||
override val name: Name = Name.special("<Test module for lazy resolve>")
|
||||
override fun dependencies() = listOf(this)
|
||||
override fun dependencyOnBuiltIns() =
|
||||
if (dependsOnBuiltIns)
|
||||
ModuleInfo.DependencyOnBuiltIns.LAST
|
||||
else
|
||||
ModuleInfo.DependencyOnBuiltIns.NONE
|
||||
if (dependsOnBuiltIns)
|
||||
ModuleInfo.DependencyOnBuiltIns.LAST
|
||||
else
|
||||
ModuleInfo.DependencyOnBuiltIns.NONE
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = JvmPlatforms.defaultJvmPlatform
|
||||
|
||||
override val compilerServices: PlatformDependentCompilerServices
|
||||
get() = JvmPlatformCompilerServices
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope;
|
||||
import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.platform.TargetPlatformKt;
|
||||
import org.jetbrains.kotlin.renderer.*;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator;
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform;
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
@@ -243,7 +243,7 @@ public class RecursiveDescriptorComparator {
|
||||
|
||||
// 'expected' declarations do not belong to the platform-specific module, even though they participate in the analysis
|
||||
if (descriptor instanceof MemberDescriptor && ((MemberDescriptor) descriptor).isExpect() &&
|
||||
module.getCapability(MultiTargetPlatform.CAPABILITY) != MultiTargetPlatform.Common.INSTANCE) return false;
|
||||
!TargetPlatformKt.isCommon(module.getPlatform())) return false;
|
||||
|
||||
return module.equals(DescriptorUtils.getContainingModule(descriptor));
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.tests.di
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.getValue
|
||||
@@ -26,18 +25,24 @@ import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.frontend.di.configureModule
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.types.expressions.FakeCallResolver
|
||||
|
||||
fun createContainerForTests(project: Project, module: ModuleDescriptor): ContainerForTests {
|
||||
return ContainerForTests(createContainer("Tests", JvmPlatform) {
|
||||
configureModule(ModuleContext(module, project), JvmPlatform, JvmTarget.DEFAULT)
|
||||
useInstance(LanguageVersionSettingsImpl.DEFAULT)
|
||||
return ContainerForTests(createContainer("Tests", JvmPlatformCompilerServices) {
|
||||
configureModule(
|
||||
ModuleContext(module, project, "container for tests"),
|
||||
JvmPlatforms.defaultJvmPlatform,
|
||||
JvmPlatformCompilerServices,
|
||||
BindingTraceContext(),
|
||||
LanguageVersionSettingsImpl.DEFAULT
|
||||
)
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<ExpressionTypingServices>()
|
||||
useInstance(ModuleStructureOracle.SingleModule)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -34,11 +34,16 @@ import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentCompilerServices
|
||||
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
@@ -56,28 +61,34 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
|
||||
) : ModuleInfo {
|
||||
override fun dependencies() = _dependencies()
|
||||
override val name = Name.special("<$_name>")
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = JvmPlatforms.defaultJvmPlatform
|
||||
|
||||
override val compilerServices: PlatformDependentCompilerServices
|
||||
get() = JvmPlatformCompilerServices
|
||||
}
|
||||
|
||||
fun testJavaEntitiesBelongToCorrectModule() {
|
||||
val moduleDirs = File(PATH_TO_TEST_ROOT_DIR).listFiles { it -> it.isDirectory }!!
|
||||
val environment = createEnvironment(moduleDirs)
|
||||
val modules = setupModules(environment, moduleDirs)
|
||||
val projectContext = ProjectContext(environment.project)
|
||||
val projectContext = ProjectContext(environment.project, "MultiModuleJavaAnalysisTest")
|
||||
val builtIns = JvmBuiltIns(projectContext.storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER)
|
||||
val platformParameters = JvmPlatformParameters(
|
||||
packagePartProviderFactory = { PackagePartProvider.Empty },
|
||||
moduleByJavaClass = { javaClass ->
|
||||
val moduleName = javaClass.name.asString().toLowerCase().first().toString()
|
||||
modules.first { it._name == moduleName }
|
||||
}
|
||||
)
|
||||
val resolverForProject = ResolverForProjectImpl(
|
||||
"test",
|
||||
projectContext, modules,
|
||||
modulesContent = { module -> ModuleContent(module, module.kotlinFiles, module.javaFilesScope) },
|
||||
moduleLanguageSettingsProvider = LanguageSettingsProvider.Default,
|
||||
resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade },
|
||||
platformParameters = { _ ->
|
||||
JvmPlatformParameters(
|
||||
packagePartProviderFactory = { PackagePartProvider.Empty },
|
||||
moduleByJavaClass = { javaClass ->
|
||||
val moduleName = javaClass.name.asString().toLowerCase().first().toString()
|
||||
modules.first { it._name == moduleName }
|
||||
}
|
||||
)
|
||||
resolverForModuleFactoryByPlatform = {
|
||||
JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform)
|
||||
},
|
||||
builtIns = builtIns
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.facade.K2JSTranslator
|
||||
import org.jetbrains.kotlin.js.facade.MainCallParameters
|
||||
import org.jetbrains.kotlin.js.facade.TranslationResult
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||
import org.jetbrains.kotlin.serialization.AbstractVersionRequirementTest
|
||||
@@ -76,7 +76,10 @@ class JsVersionRequirementTest : AbstractVersionRequirementTest() {
|
||||
|
||||
private fun createModule(environment: KotlinCoreEnvironment): MutableModuleContext {
|
||||
val config = JsConfig(environment.project, environment.configuration)
|
||||
return ContextForNewModule(ProjectContext(environment.project), Name.special("<test>"), JsPlatform.builtIns, null).apply {
|
||||
return ContextForNewModule(
|
||||
ProjectContext(environment.project, "ProjectContext"),
|
||||
Name.special("<test>"), JsPlatformCompilerServices.builtIns, null
|
||||
).apply {
|
||||
setDependencies(listOf(module) + config.moduleDescriptors + module.builtIns.builtInsModule)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.TEST_PACKAGE_FQNAME
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil.readModuleAsProto
|
||||
@@ -94,7 +94,7 @@ class KotlinJavascriptSerializerTest : TestCaseWithTmpdir() {
|
||||
}
|
||||
|
||||
private fun deserialize(metaFile: File): ModuleDescriptorImpl {
|
||||
val module = KotlinTestUtils.createEmptyModule("<${KotlinTestUtils.TEST_MODULE_NAME}>", JsPlatform.builtIns)
|
||||
val module = KotlinTestUtils.createEmptyModule("<${KotlinTestUtils.TEST_MODULE_NAME}>", JsPlatformCompilerServices.builtIns)
|
||||
val metadata = KotlinJavascriptMetadataUtils.loadMetadata(metaFile).single()
|
||||
|
||||
val (header, packageFragmentProtos) = readModuleAsProto(metadata.body, metadata.version)
|
||||
|
||||
@@ -19,18 +19,23 @@ package org.jetbrains.kotlin.types;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformCompilerServices;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
|
||||
import org.jetbrains.kotlin.container.DslKt;
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer;
|
||||
import org.jetbrains.kotlin.context.ContextKt;
|
||||
import org.jetbrains.kotlin.context.ModuleContext;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.platform.CommonPlatforms;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorResolver;
|
||||
import org.jetbrains.kotlin.resolve.FunctionDescriptorResolver;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
|
||||
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
|
||||
import org.jetbrains.kotlin.resolve.scopes.*;
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind;
|
||||
@@ -39,10 +44,11 @@ import org.jetbrains.kotlin.test.KotlinTestWithEnvironment;
|
||||
import org.jetbrains.kotlin.tests.di.ContainerForTests;
|
||||
import org.jetbrains.kotlin.tests.di.InjectionKt;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.frontend.di.InjectionKt.createLazyResolveSession;
|
||||
import static org.jetbrains.kotlin.frontend.di.InjectionKt.createContainerForLazyResolve;
|
||||
|
||||
public class DefaultModalityModifiersTest extends KotlinTestWithEnvironment {
|
||||
private final DefaultModalityModifiersTestCase tc = new DefaultModalityModifiersTestCase();
|
||||
@@ -102,11 +108,21 @@ public class DefaultModalityModifiersTest extends KotlinTestWithEnvironment {
|
||||
}
|
||||
|
||||
private ClassDescriptorWithResolutionScopes createClassDescriptor(ClassKind kind, KtClass aClass) {
|
||||
ResolveSession resolveSession = createLazyResolveSession(
|
||||
ContextKt.ModuleContext(root, getProject()),
|
||||
Collections.singleton(aClass.getContainingKtFile())
|
||||
ModuleContext moduleContext = ContextKt.ModuleContext(root, getProject(), "DefaultModalityModifiersTest");
|
||||
Collection<KtFile> files = Collections.singleton(aClass.getContainingKtFile());
|
||||
|
||||
StorageComponentContainer container = createContainerForLazyResolve(
|
||||
moduleContext,
|
||||
new FileBasedDeclarationProviderFactory(moduleContext.getStorageManager(), files),
|
||||
new BindingTraceContext(),
|
||||
CommonPlatforms.INSTANCE.getDefaultCommonPlatform(),
|
||||
CommonPlatformCompilerServices.INSTANCE,
|
||||
CompilerEnvironment.INSTANCE,
|
||||
LanguageVersionSettingsImpl.DEFAULT
|
||||
);
|
||||
|
||||
ResolveSession resolveSession = DslKt.getService(container, ResolveSession.class);
|
||||
|
||||
return (ClassDescriptorWithResolutionScopes) resolveSession.getClassDescriptor(aClass, NoLookupLocation.FROM_TEST);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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.config
|
||||
|
||||
import org.jetbrains.kotlin.utils.DescriptionAware
|
||||
|
||||
interface TargetPlatformVersion : DescriptionAware {
|
||||
object NoVersion : TargetPlatformVersion {
|
||||
override val description = ""
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.components
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
interface SamConversionResolver {
|
||||
@DefaultImplementation(impl = SamConversionResolver.Empty::class)
|
||||
interface SamConversionResolver : PlatformSpecificExtension<SamConversionResolver> {
|
||||
object Empty : SamConversionResolver {
|
||||
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? = null
|
||||
}
|
||||
|
||||
fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType?
|
||||
}
|
||||
|
||||
class SamConversionResolverClashesResolver : PlatformExtensionsClashResolver.FallbackToDefault<SamConversionResolver>(
|
||||
SamConversionResolver.Empty,
|
||||
SamConversionResolver::class.java
|
||||
)
|
||||
@@ -6,20 +6,22 @@
|
||||
package org.jetbrains.kotlin.builtins;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@DefaultImplementation(impl = PlatformToKotlinClassMap.Default.class)
|
||||
public interface PlatformToKotlinClassMap {
|
||||
PlatformToKotlinClassMap EMPTY = new PlatformToKotlinClassMap() {
|
||||
@NotNull
|
||||
Collection<ClassDescriptor> mapPlatformClass(@NotNull ClassDescriptor classDescriptor);
|
||||
|
||||
class Default implements PlatformToKotlinClassMap {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<ClassDescriptor> mapPlatformClass(@NotNull ClassDescriptor classDescriptor) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
Collection<ClassDescriptor> mapPlatformClass(@NotNull ClassDescriptor classDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
interface ModuleDescriptor : DeclarationDescriptor {
|
||||
override fun getContainingDeclaration(): DeclarationDescriptor? = null
|
||||
@@ -30,6 +31,10 @@ interface ModuleDescriptor : DeclarationDescriptor {
|
||||
*/
|
||||
val stableName: Name?
|
||||
|
||||
// NB: this field should actually be non-null, but making it so implies a LOT of work, so we postpone it for a moment
|
||||
// TODO: make it non-null
|
||||
val platform: TargetPlatform?
|
||||
|
||||
fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean
|
||||
|
||||
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import java.lang.IllegalArgumentException
|
||||
@@ -34,8 +34,8 @@ class ModuleDescriptorImpl @JvmOverloads constructor(
|
||||
private val storageManager: StorageManager,
|
||||
override val builtIns: KotlinBuiltIns,
|
||||
// May be null in compiler context, should be not-null in IDE context
|
||||
multiTargetPlatform: MultiTargetPlatform? = null,
|
||||
capabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap(),
|
||||
override val platform: TargetPlatform? = null,
|
||||
private val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap(),
|
||||
override val stableName: Name? = null
|
||||
) : DeclarationDescriptorImpl(Annotations.EMPTY, moduleName), ModuleDescriptor {
|
||||
init {
|
||||
@@ -44,8 +44,6 @@ class ModuleDescriptorImpl @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val capabilities = capabilities + (multiTargetPlatform?.let { mapOf(MultiTargetPlatform.CAPABILITY to it) } ?: emptyMap())
|
||||
|
||||
private var dependencies: ModuleDependencies? = null
|
||||
private var packageFragmentProviderForModuleContent: PackageFragmentProvider? = null
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.platform
|
||||
|
||||
/**
|
||||
* Core abstraction of Platform API, represents a collection of platforms.
|
||||
*
|
||||
* This is the primarily abstraction intended to use in the most part of API, as, usually,
|
||||
* pretty much anything that may have a platform, may have a several platforms as well in the
|
||||
* context of multiplatform projects.
|
||||
*
|
||||
* Please, use it over the [SimplePlatform] unless you're absolutely sure what you're doing.
|
||||
*
|
||||
* NB. Even in cases, where some part of logic makes sense only for a particular platform (e.g., JVM),
|
||||
* it still can be applicable for [TargetPlatform]s with [componentPlatforms] > 1, e.g. when it consists
|
||||
* of two version of JDK, JDK and Android, several versions of Android API, etc.
|
||||
*/
|
||||
data class TargetPlatform(val componentPlatforms: Set<SimplePlatform>) : Collection<SimplePlatform> by componentPlatforms {
|
||||
init {
|
||||
if (componentPlatforms.isEmpty()) throw IllegalArgumentException("Don't instantiate TargetPlatform with empty set of platforms")
|
||||
}
|
||||
|
||||
override fun toString(): String = presentableDescription
|
||||
}
|
||||
|
||||
/**
|
||||
* Core abstraction of Platform API, represents exactly one platform.
|
||||
*
|
||||
* API guarantees:
|
||||
*
|
||||
* - direct inheritors are well-known and represent three major platforms supported at the moment (JVM, JS, Native)
|
||||
*
|
||||
* - exact enumeration of all inheritors isn't available at the compile time, see [DefaultBuiltInPlatforms]
|
||||
*
|
||||
* - each implementation should support equality in a broad sense of "absolutely the same platform"
|
||||
*
|
||||
* - it is _prohibited_ to create instances of [SimplePlatform] in the client's code, use [DefaultBuiltInPlatfroms] to get instances
|
||||
* of platforms
|
||||
*
|
||||
* Ideally, each specific subtype should be either a data class or singleton.
|
||||
*/
|
||||
abstract class SimplePlatform(val platformName: String) {
|
||||
override fun toString(): String = platformName
|
||||
|
||||
abstract val oldFashionedDescription: String
|
||||
|
||||
// FIXME(dsavvinov): hack to allow injection inject JvmTarget into container.
|
||||
// Proper fix would be to rewrite clients to get JdkPlatform from container, and pull JvmTarget from it
|
||||
// (this will also remove need in TargetPlatformVersion as the whole, and, in particular, ugly passing
|
||||
// of TargetPlatformVersion.NoVersion in non-JVM code)
|
||||
open val targetPlatformVersion: TargetPlatformVersion = TargetPlatformVersion.NoVersion
|
||||
}
|
||||
|
||||
interface TargetPlatformVersion {
|
||||
val description: String
|
||||
|
||||
object NoVersion : TargetPlatformVersion {
|
||||
override val description = ""
|
||||
}
|
||||
}
|
||||
|
||||
fun TargetPlatform?.isCommon(): Boolean = this != null && this.size > 1
|
||||
|
||||
fun SimplePlatform.toTargetPlatform(): TargetPlatform = TargetPlatform(setOf(this))
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.platform
|
||||
|
||||
inline fun <reified T : SimplePlatform> TargetPlatform.subplatformOfType(): T? = componentPlatforms.filterIsInstance<T>().singleOrNull()
|
||||
fun <T> TargetPlatform.subplatformOfType(klass: Class<T>): T? = componentPlatforms.filterIsInstance(klass).singleOrNull()
|
||||
|
||||
inline fun <reified T : SimplePlatform> TargetPlatform?.has(): Boolean = this != null && subplatformOfType<T>() != null
|
||||
fun <T> TargetPlatform?.has(klass: Class<T>): Boolean = this != null && subplatformOfType(klass) != null
|
||||
|
||||
|
||||
/**
|
||||
* Returns human-readable description, mapping multiplatform to 'Common (experimental)',
|
||||
* as well as maintaining some quirks of the previous representation (like trailing whitespaces).
|
||||
* It is needed mainly for backwards compatibility, because some subsystem actually
|
||||
* managed to rely on the format of that string (yes, facets, I'm looking at you).
|
||||
*
|
||||
* New clients are encouraged to use [presentableDescription] description instead, as it
|
||||
* also provides better description for multiplatforms.
|
||||
*/
|
||||
val TargetPlatform.oldFashionedDescription: String
|
||||
get() = if (this.isCommon()) "Common (experimental) " else this.single().oldFashionedDescription
|
||||
|
||||
|
||||
/**
|
||||
* Renders multiplatform in form
|
||||
* '$PLATFORM_1 / $PLATFORM_2 / ...'
|
||||
* e.g.
|
||||
* 'JVM (1.8) / JS / Native'
|
||||
*/
|
||||
val TargetPlatform.presentableDescription: String
|
||||
get() = componentPlatforms.joinToString(separator = "/")
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.getContainingClass
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
@@ -57,6 +58,9 @@ val DeclarationDescriptor.isExtension: Boolean
|
||||
val DeclarationDescriptor.module: ModuleDescriptor
|
||||
get() = DescriptorUtils.getContainingModule(this)
|
||||
|
||||
val DeclarationDescriptor.platform: TargetPlatform?
|
||||
get() = module.platform
|
||||
|
||||
fun ModuleDescriptor.resolveTopLevelClass(topLevelClassFqName: FqName, location: LookupLocation): ClassDescriptor? {
|
||||
assert(!topLevelClassFqName.isRoot)
|
||||
return getPackage(topLevelClassFqName.parent()).memberScope.getContributedClassifier(
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
sealed class MultiTargetPlatform : Comparable<MultiTargetPlatform> {
|
||||
object Common : MultiTargetPlatform() {
|
||||
override fun compareTo(other: MultiTargetPlatform): Int =
|
||||
if (other is Common) 0 else -1
|
||||
}
|
||||
|
||||
data class Specific(val platform: String) : MultiTargetPlatform() {
|
||||
override fun compareTo(other: MultiTargetPlatform): Int =
|
||||
when (other) {
|
||||
is Common -> 1
|
||||
is Specific -> platform.compareTo(other.platform)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CAPABILITY = ModuleDescriptor.Capability<MultiTargetPlatform>("MULTI_TARGET_PLATFORM")
|
||||
}
|
||||
}
|
||||
|
||||
fun ModuleDescriptor.getMultiTargetPlatform(): MultiTargetPlatform? =
|
||||
module.getCapability(MultiTargetPlatform.CAPABILITY)
|
||||
|
||||
fun MemberDescriptor.getMultiTargetPlatform(): String? =
|
||||
(module.getMultiTargetPlatform() as? MultiTargetPlatform.Specific)?.platform
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
@@ -95,6 +96,7 @@ interface SyntheticScope {
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultImplementation(impl = SyntheticScopes.Empty::class)
|
||||
interface SyntheticScopes {
|
||||
val scopes: Collection<SyntheticScope>
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
@@ -80,6 +81,12 @@ public class ErrorUtils {
|
||||
return Name.special("<ERROR MODULE>");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TargetPlatform getPlatform() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PackageViewDescriptor getPackage(@NotNull FqName fqName) {
|
||||
|
||||
@@ -128,7 +128,7 @@ fun KotlinType.isDefaultBound(): Boolean = KotlinBuiltIns.isDefaultBound(getSupe
|
||||
fun createProjection(type: KotlinType, projectionKind: Variance, typeParameterDescriptor: TypeParameterDescriptor?): TypeProjection =
|
||||
TypeProjectionImpl(if (typeParameterDescriptor?.variance == projectionKind) Variance.INVARIANT else projectionKind, type)
|
||||
|
||||
fun Collection<KotlinType>.closure(f: (KotlinType) -> Collection<KotlinType>): Collection<KotlinType> {
|
||||
fun <T> Collection<T>.closure(f: (T) -> Collection<T>): Collection<T> {
|
||||
if (size == 0) return this
|
||||
|
||||
val result = HashSet(this)
|
||||
@@ -136,7 +136,7 @@ fun Collection<KotlinType>.closure(f: (KotlinType) -> Collection<KotlinType>): C
|
||||
var oldSize = 0
|
||||
while (result.size > oldSize) {
|
||||
oldSize = result.size
|
||||
val toAdd = hashSetOf<KotlinType>()
|
||||
val toAdd = hashSetOf<T>()
|
||||
elementsToCheck.forEach { toAdd.addAll(f(it)) }
|
||||
result.addAll(toAdd)
|
||||
elementsToCheck = toAdd
|
||||
|
||||
@@ -17,22 +17,31 @@
|
||||
package org.jetbrains.kotlin.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions
|
||||
import org.jetbrains.kotlin.types.model.DynamicTypeMarker
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
open class DynamicTypesSettings {
|
||||
@DefaultImplementation(impl = DynamicTypesSettings::class)
|
||||
open class DynamicTypesSettings : PlatformSpecificExtension<DynamicTypesSettings> {
|
||||
open val dynamicTypesAllowed: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
class DynamicTypesAllowed: DynamicTypesSettings() {
|
||||
class DynamicTypesAllowed : DynamicTypesSettings() {
|
||||
override val dynamicTypesAllowed: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
class DynamicTypesSettingsClashesResolver : PlatformExtensionsClashResolver<DynamicTypesSettings>(DynamicTypesSettings::class.java) {
|
||||
override fun resolveExtensionsClash(extensions: List<DynamicTypesSettings>): DynamicTypesSettings =
|
||||
if (extensions.any { it.dynamicTypesAllowed }) DynamicTypesAllowed() else DynamicTypesSettings()
|
||||
}
|
||||
|
||||
fun KotlinType.isDynamic(): Boolean = unwrap() is DynamicType
|
||||
|
||||
fun createDynamicType(builtIns: KotlinBuiltIns) = DynamicType(builtIns, Annotations.EMPTY)
|
||||
|
||||
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.container
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/*Use to assist injection to provide a default implementation for a certain component and reduce boilerplate in injector code.
|
||||
* Argument class must be a non-abstract component class or a kotlin object implementing target interface.
|
||||
* Avoid using when there is no clear 'default' behaviour for a component.
|
||||
* */
|
||||
/**
|
||||
* Use to assist injection to provide a default implementation for a certain component and reduce boilerplate in injector code.
|
||||
* Argument class must be a non-abstract component class or a kotlin object implementing target interface.
|
||||
* Avoid using when there is no clear 'default' behaviour for a component.
|
||||
*
|
||||
* NB: DefaultImplementation are *discriminated* during resolution of components, meaning that if there are one non-default
|
||||
* implementations and several default, default will be chosen.
|
||||
* Such configurations may arise, for example, for multiplatform modules: consider analyzing JVM+JS module, where JS contributes
|
||||
* default implementation of some particular service, and JVM contributes non-default.
|
||||
**/
|
||||
annotation class DefaultImplementation(val impl: KClass<*>)
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.container
|
||||
|
||||
/**
|
||||
* This is a marker-interface for components which are needed for common resolve
|
||||
* facilities (like resolve, or deserialization), but are platform-specific.
|
||||
*
|
||||
* PlatformSpecificExtensions has to be present in the container in exactly one
|
||||
* instance (hence common pattern with providing no-op DEFAULT/EMPTY implementation
|
||||
* in the corresponding interface)
|
||||
*
|
||||
* In multiplatform modules such components require special treatment. Namely,
|
||||
* if several components of the same type are provided, then it's not an illegal state;
|
||||
* rather, we have to carefully resolve clash on case-by-case basis.
|
||||
* See [PlatformExtensionsClashResolver] also
|
||||
*
|
||||
* Example: [org.jetbrains.kotlin.resolve.IdentifierChecker]. It is used in platform-agnostic code,
|
||||
* which resolves and checks identifiers for correctness. Each platform has it's own rules
|
||||
* regarding identifier correctness. In MPP modules we can't choose only one IdentifierChecker;
|
||||
* instead, we have to provide a "composite" IdentifierChecker which will launch checks of *each*
|
||||
* platform.
|
||||
*/
|
||||
interface PlatformSpecificExtension<S : PlatformSpecificExtension<S>>
|
||||
|
||||
abstract class PlatformExtensionsClashResolver<E : PlatformSpecificExtension<E>>(val applicableTo: Class<E>) {
|
||||
abstract fun resolveExtensionsClash(extensions: List<E>): E
|
||||
|
||||
abstract class FallbackToDefault<E : PlatformSpecificExtension<E>>(
|
||||
private val defaultValue: E,
|
||||
applicableTo: Class<E>
|
||||
) : PlatformExtensionsClashResolver<E>(applicableTo) {
|
||||
|
||||
override fun resolveExtensionsClash(extensions: List<E>): E = defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,7 @@ import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest
|
||||
import org.jetbrains.kotlin.idea.index.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
|
||||
import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest
|
||||
import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiPlatformHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
|
||||
@@ -664,6 +661,10 @@ fun main(args: Array<String>) {
|
||||
model("multiModuleHighlighting/multiplatform/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractHierarchicalExpectActualTest> {
|
||||
model("multiModuleHighlighting/hierarchicalExpectActualMatching/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractQuickFixMultiModuleTest> {
|
||||
model("multiModuleQuickFix", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
@@ -48,10 +48,7 @@ import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest
|
||||
import org.jetbrains.kotlin.idea.index.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
|
||||
import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest
|
||||
import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiPlatformHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
|
||||
@@ -679,6 +676,10 @@ fun main(args: Array<String>) {
|
||||
model("multiModuleHighlighting/multiplatform/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractHierarchicalExpectActualTest> {
|
||||
model("multiModuleHighlighting/hierarchicalExpectActualMatching/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractQuickFixMultiModuleTest> {
|
||||
model("multiModuleQuickFix", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
@@ -40,10 +40,7 @@ import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest
|
||||
import org.jetbrains.kotlin.idea.index.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
|
||||
import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest
|
||||
import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiPlatformHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
|
||||
@@ -644,6 +641,10 @@ fun main(args: Array<String>) {
|
||||
model("multiModuleHighlighting/multiplatform/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractHierarchicalExpectActualTest> {
|
||||
model("multiModuleHighlighting/hierarchicalExpectActualMatching/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractQuickFixMultiModuleTest> {
|
||||
model("multiModuleQuickFix", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
@@ -40,10 +40,7 @@ import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest
|
||||
import org.jetbrains.kotlin.idea.index.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
|
||||
import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest
|
||||
import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiPlatformHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
|
||||
@@ -648,6 +645,10 @@ fun main(args: Array<String>) {
|
||||
model("multiModuleHighlighting/multiplatform/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractHierarchicalExpectActualTest> {
|
||||
model("multiModuleHighlighting/hierarchicalExpectActualMatching/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractQuickFixMultiModuleTest> {
|
||||
model("multiModuleQuickFix", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
@@ -40,10 +40,7 @@ import org.jetbrains.kotlin.idea.AbstractExpressionSelectionTest
|
||||
import org.jetbrains.kotlin.idea.index.AbstractKotlinTypeAliasByExpansionShortNameIndexTest
|
||||
import org.jetbrains.kotlin.idea.AbstractSmartSelectionTest
|
||||
import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeCompiledLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiModuleLineMarkerTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractMultiPlatformHighlightingTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractCodeInsightActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
|
||||
@@ -644,6 +641,10 @@ fun main(args: Array<String>) {
|
||||
model("multiModuleHighlighting/multiplatform/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractHierarchicalExpectActualTest> {
|
||||
model("multiModuleHighlighting/hierarchicalExpectActualMatching/", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractQuickFixMultiModuleTest> {
|
||||
model("multiModuleQuickFix", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
|
||||
|
||||
interface KotlinCacheService {
|
||||
@@ -31,8 +31,8 @@ interface KotlinCacheService {
|
||||
}
|
||||
|
||||
fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade
|
||||
fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade?
|
||||
fun getResolutionFacadeByFile(file: PsiFile): ResolutionFacade?
|
||||
|
||||
fun getSuppressionCache(): KotlinSuppressCache
|
||||
fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade?
|
||||
fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo): ResolutionFacade?
|
||||
}
|
||||
@@ -7,14 +7,18 @@ package org.jetbrains.kotlin.caches.resolve
|
||||
|
||||
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
|
||||
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
|
||||
import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind
|
||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||
|
||||
class CommonPlatformKindResolution : IdePlatformKindResolution {
|
||||
@@ -27,10 +31,15 @@ class CommonPlatformKindResolution : IdePlatformKindResolution {
|
||||
|
||||
override val kind get() = CommonIdePlatformKind
|
||||
|
||||
override val resolverForModuleFactory: ResolverForModuleFactory
|
||||
get() = CommonAnalyzerFacade
|
||||
|
||||
override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns {
|
||||
return DefaultBuiltIns.Instance
|
||||
}
|
||||
|
||||
// override fun createResolverForModuleFactory(
|
||||
// settings: PlatformAnalysisParameters,
|
||||
// environment: TargetEnvironment,
|
||||
// platform: TargetPlatform
|
||||
// ): ResolverForModuleFactory {
|
||||
// return CommonResolverForModuleFactory(settings as CommonAnalysisParameters, environment, platform)
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("Duplicates")
|
||||
|
||||
package org.jetbrains.kotlin.caches.resolve
|
||||
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.*
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformCompilerServices
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.*
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
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.configureCommonSpecificComponents
|
||||
import org.jetbrains.kotlin.frontend.di.configureModule
|
||||
import org.jetbrains.kotlin.frontend.di.configureStandardResolveComponents
|
||||
import org.jetbrains.kotlin.frontend.java.di.configureJavaSpecificComponents
|
||||
import org.jetbrains.kotlin.frontend.java.di.initializeJavaSpecificComponents
|
||||
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
|
||||
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolverImpl
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.has
|
||||
import org.jetbrains.kotlin.platform.idePlatformKind
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.platform.js.isJs
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatform
|
||||
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalMarkerDeclarationAnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||
import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
|
||||
class CompositeResolverForModuleFactory(
|
||||
private val commonAnalysisParameters: CommonAnalysisParameters,
|
||||
private val jvmAnalysisParameters: JvmPlatformParameters,
|
||||
private val targetPlatform: TargetPlatform,
|
||||
private val compilerServices: CompositeCompilerServices
|
||||
) : ResolverForModuleFactory() {
|
||||
override fun <M : ModuleInfo> createResolverForModule(
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
moduleContext: ModuleContext,
|
||||
moduleContent: ModuleContent<M>,
|
||||
resolverForProject: ResolverForProject<M>,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): ResolverForModule {
|
||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||
val project = moduleContext.project
|
||||
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
|
||||
project, moduleContext.storageManager, syntheticFiles,
|
||||
moduleContentScope,
|
||||
moduleInfo
|
||||
)
|
||||
|
||||
val metadataPartProvider = commonAnalysisParameters.metadataPartProviderFactory(moduleContent)
|
||||
val trace = CodeAnalyzerInitializer.getInstance(project).createTrace()
|
||||
|
||||
|
||||
val moduleClassResolver = ModuleClassResolverImpl { javaClass ->
|
||||
val referencedClassModule = jvmAnalysisParameters.moduleByJavaClass(javaClass)
|
||||
// We don't have full control over idea resolve api so we allow for a situation which should not happen in Kotlin.
|
||||
// For example, type in a java library can reference a class declared in a source root (is valid but rare case)
|
||||
// Providing a fallback strategy in this case can hide future problems, so we should at least log to be able to diagnose those
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val resolverForReferencedModule = referencedClassModule?.let { resolverForProject.tryGetResolverForModule(it as M) }
|
||||
|
||||
val resolverForModule = resolverForReferencedModule?.takeIf {
|
||||
referencedClassModule.platform.has<JvmPlatform>() || referencedClassModule.platform == null
|
||||
} ?: run {
|
||||
// in case referenced class lies outside of our resolver, resolve the class as if it is inside our module
|
||||
// this leads to java class being resolved several times
|
||||
resolverForProject.resolverForModule(moduleInfo)
|
||||
}
|
||||
resolverForModule.componentProvider.get<JavaDescriptorResolver>()
|
||||
}
|
||||
|
||||
val packagePartProvider = jvmAnalysisParameters.packagePartProviderFactory(moduleContent)
|
||||
|
||||
val container = createContainerForCompositePlatform(
|
||||
moduleContext, moduleContentScope, languageVersionSettings, targetPlatform,
|
||||
compilerServices, trace, declarationProviderFactory, metadataPartProvider,
|
||||
moduleClassResolver, packagePartProvider
|
||||
)
|
||||
|
||||
val packageFragmentProviders = sequence {
|
||||
yield(container.get<ResolveSession>().packageFragmentProvider)
|
||||
|
||||
yieldAll(getCommonProvidersIfAny(container))
|
||||
yieldAll(getJsProvidersIfAny(moduleInfo, moduleContext, moduleDescriptor, container))
|
||||
yieldAll(getJvmProvidersIfAny(container))
|
||||
yieldAll(getKonanProvidersIfAny(moduleInfo, container))
|
||||
}.toList()
|
||||
|
||||
return ResolverForModule(CompositePackageFragmentProvider(packageFragmentProviders), container)
|
||||
}
|
||||
|
||||
private fun getCommonProvidersIfAny(container: StorageComponentContainer): List<PackageFragmentProvider> =
|
||||
if (targetPlatform.isCommon()) listOf(container.get<MetadataPackageFragmentProvider>()) else emptyList()
|
||||
|
||||
private fun getJvmProvidersIfAny(container: StorageComponentContainer): List<PackageFragmentProvider> =
|
||||
if (targetPlatform.has<JvmPlatform>()) listOf(container.get<JavaDescriptorResolver>().packageFragmentProvider) else emptyList()
|
||||
|
||||
private fun getKonanProvidersIfAny(moduleInfo: ModuleInfo, container: StorageComponentContainer): List<PackageFragmentProvider> {
|
||||
if (!targetPlatform.has<KonanPlatform>()) return emptyList()
|
||||
val resolution = KonanPlatforms.defaultKonanPlatform.idePlatformKind.resolution
|
||||
|
||||
val konanProvider = resolution.createPlatformSpecificPackageFragmentProvider(
|
||||
moduleInfo,
|
||||
container.get<StorageManager>(),
|
||||
container.get<LanguageVersionSettings>(),
|
||||
container.get<ModuleDescriptor>()
|
||||
) ?: return emptyList()
|
||||
|
||||
return listOf(konanProvider)
|
||||
}
|
||||
|
||||
private fun getJsProvidersIfAny(
|
||||
moduleInfo: ModuleInfo,
|
||||
moduleContext: ModuleContext,
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
container: StorageComponentContainer
|
||||
): List<PackageFragmentProvider> {
|
||||
if (moduleInfo !is LibraryModuleInfo || !moduleInfo.platform.isJs()) return emptyList()
|
||||
|
||||
return moduleInfo.getLibraryRoots()
|
||||
.flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) }
|
||||
.filter { it.version.isCompatible() }
|
||||
.map { metadata ->
|
||||
val (header, packageFragmentProtos) =
|
||||
KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version)
|
||||
createKotlinJavascriptPackageFragmentProvider(
|
||||
moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, metadata.version,
|
||||
container.get(), LookupTracker.DO_NOTHING
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun createContainerForCompositePlatform(
|
||||
moduleContext: ModuleContext,
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
targetPlatform: TargetPlatform,
|
||||
compilerServices: CompositeCompilerServices,
|
||||
trace: BindingTrace,
|
||||
declarationProviderFactory: DeclarationProviderFactory,
|
||||
metadataPartProvider: MetadataPartProvider,
|
||||
// Guaranteed to be non-null for modules with JVM
|
||||
moduleClassResolver: ModuleClassResolver?,
|
||||
packagePartProvider: PackagePartProvider?
|
||||
): StorageComponentContainer = composeContainer("CompositePlatform") {
|
||||
// Shared by all PlatformConfigurators
|
||||
configureDefaultCheckers()
|
||||
|
||||
// Specific for each PlatformConfigurator
|
||||
for (configurator in compilerServices.services.map { it.platformConfigurator as PlatformConfiguratorBase }) {
|
||||
configurator.configureExtensionsAndCheckers(this)
|
||||
}
|
||||
|
||||
// Called by all normal containers set-ups
|
||||
configureModule(moduleContext, targetPlatform, compilerServices, trace, languageVersionSettings)
|
||||
configureStandardResolveComponents()
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(declarationProviderFactory)
|
||||
|
||||
// Probably, should be in StandardResolveComponents, but
|
||||
useInstance(VirtualFileFinderFactory.getInstance(moduleContext.project).create(moduleContentScope))
|
||||
useInstance(packagePartProvider!!)
|
||||
|
||||
// JVM-specific
|
||||
if (targetPlatform.has<JvmPlatform>()) {
|
||||
configureJavaSpecificComponents(
|
||||
moduleContext, moduleClassResolver!!, languageVersionSettings, configureJavaClassFinder = null,
|
||||
javaClassTracker = null,
|
||||
useBuiltInsProvider = false
|
||||
)
|
||||
// useInstance(packagePartProvider!!)
|
||||
}
|
||||
|
||||
// Common-specific
|
||||
if (targetPlatform.isCommon()) {
|
||||
configureCommonSpecificComponents()
|
||||
}
|
||||
|
||||
IdeaEnvironment.configure(this)
|
||||
}.apply {
|
||||
if (targetPlatform.has<JvmPlatform>()) {
|
||||
initializeJavaSpecificComponents(trace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CompositeCompilerServices(val services: List<PlatformDependentCompilerServices>) : PlatformDependentCompilerServices() {
|
||||
override val platformConfigurator: PlatformConfigurator = CompositePlatformConigurator(services.map { it.platformConfigurator })
|
||||
|
||||
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {
|
||||
val intersectionOfDefaultImports = services.map { service ->
|
||||
mutableListOf<ImportPath>()
|
||||
.apply { service.computePlatformSpecificDefaultImports(storageManager, this) }
|
||||
.toSet()
|
||||
}.safeIntersect()
|
||||
|
||||
result.addAll(intersectionOfDefaultImports)
|
||||
}
|
||||
|
||||
override val defaultLowPriorityImports: List<ImportPath> = services.map { it.defaultLowPriorityImports.toSet() }.safeIntersect()
|
||||
|
||||
override val excludedImports: List<FqName> = services.map { it.excludedImports.toSet() }.safeUnion()
|
||||
|
||||
private fun <T> List<Set<T>>.safeUnion(): List<T> =
|
||||
if (isEmpty()) emptyList() else reduce { first, second -> first.union(second) }.toList()
|
||||
|
||||
private fun <T> List<Set<T>>.safeIntersect(): List<T> =
|
||||
if (isEmpty()) emptyList() else reduce { first, second -> first.intersect(second) }.toList()
|
||||
}
|
||||
|
||||
class CompositePlatformConigurator(private val componentConfigurators: List<PlatformConfigurator>) : PlatformConfigurator {
|
||||
// TODO(dsavvinov): this is actually a hack. Review callers of that method, think about how to refactor it
|
||||
// Unfortunately, clients of that container will inject additional services into them,
|
||||
// without knowing about composite platform (see LocalClassifierAnalyzer), so we can't just use [createContainerForCompositePlatform]
|
||||
// here. Hopefully, platformSpecific container won't at least make things worse.
|
||||
override val platformSpecificContainer: StorageComponentContainer
|
||||
get() = CommonPlatformCompilerServices.platformConfigurator.platformSpecificContainer
|
||||
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
componentConfigurators.forEach { it.configureModuleComponents(container) }
|
||||
}
|
||||
|
||||
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
|
||||
// We (ab)use the fact that currently, platforms don't use that method, so the only injected compnent will be
|
||||
// ExperimentalMarkerDeclarationAnnotationChecker.
|
||||
// Unfortunately, it is declared in base class, so repeating call to 'configureModuleDependentCheckers' will lead
|
||||
// to multiple registrrations.
|
||||
container.useImpl<ExperimentalMarkerDeclarationAnnotationChecker>()
|
||||
container.useImpl<ExpectedActualDeclarationChecker>()
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user