Compare commits

...

52 Commits

Author SHA1 Message Date
Dmitry Savvinov
a2b57bf3a3 Accept Iterable<IdentifierChecker> from injection 2019-05-14 12:04:42 +03:00
Dmitry Savvinov
2a9cd58de8 [Injection] Use @DefaultImplementation in all services
- Introduce default implementations where necessary
- Properly annotate all default implementations with @DefaultImplementation
- Drop injecting default instances explicitly (DI will do it
implicitly), removing a lot of boilerplate in containers configuration
- Drop ClashResolvers which were just discriminating default instances
(DI will do it implicitly)
2019-05-14 12:04:42 +03:00
Dmitry Savvinov
97098143a5 [Injection] Discriminate default instances during clashes resolution
The idea is to try to resolve the dependency without considering default
instances first.

This makes containers more composable, e.g., it is now possible to put
several containers together as long as all except one provide default
implemenetation for some particular service (non-default implementation
will be automatically chosen, and all defaults will be discarded).
2019-05-14 12:04:41 +03:00
Dmitry Savvinov
7ecfaf8be1 !fixup platform-api 2019-05-14 12:04:41 +03:00
Dmitry Savvinov
9693b1734f !fixup platform-api 2019-05-14 12:04:41 +03:00
Dmitry Savvinov
dea1308ac3 !fixup removeIdePlatform 2019-05-14 12:04:40 +03:00
Dmitry Savvinov
2ddc897ff2 !fixup platform-api 2019-05-14 12:04:40 +03:00
Dmitry Savvinov
b64e8c380c Get rid of IdePlatformKind.IDE_KINDS_BY_COMPILER_PLATFORM 2019-05-14 12:04:40 +03:00
Dmitry Savvinov
900346fa0b !fixup Remove .resolverForModuleFactory 2019-05-14 12:04:39 +03:00
Dmitry Savvinov
af7b28ae8e [Resolve] Make ResolverForModuleFacotries non-static 2019-05-14 12:04:39 +03:00
Dmitry Savvinov
c07711d3e1 [Resolve] Remove IdePlatformKindTooling.resolverForModule 2019-05-14 12:04:39 +03:00
Dmitry Savvinov
1fa892b436 [Resolve] CompositeResolver 2019-05-14 12:04:38 +03:00
Dmitry Savvinov
363ca3b902 [Resolve] publish 'PlatformConfiguratorBase.computeDefaultImports' 2019-04-30 20:03:33 +03:00
Dmitry Savvinov
a4a54179a8 [Resolve] Make ResolverForModuleFacotries non-static 2019-04-30 20:03:32 +03:00
Dmitry Savvinov
fc0855e004 [Resolve] Remove platform from PlatformAnalysisSettings (effectively removes separate universes for different platforms) 2019-04-30 20:03:32 +03:00
Dmitry Savvinov
7437f29656 [Resolve] Collect all moduleInfos from IDEA model (instead of per-platform)
Then, use all modules in resolvers, rather than only specific for some
platform.

Along with removal of per-platform GlobalFacade, this allows analyzing
sources in MPP platform together.

Note that it brings issues with scopes back.
2019-04-30 20:03:32 +03:00
Dmitry Savvinov
34abbdf72d [Resolve] Remove CombinedModuleInfo. On to the new world!
TODO: fix commit message ;)
2019-04-30 20:03:31 +03:00
Dmitry Savvinov
86b4d3a311 [Expect/Actual] Add testdata on hierarchical expect/actual matching 2019-04-30 20:03:31 +03:00
Dmitry Savvinov
c57cdb12b3 [Expect/Actual] Adjust old testdata after introduction of new diagnostics 2019-04-30 20:03:31 +03:00
Dmitry Savvinov
0fbe8d7725 [Expect/Actual] Support matching of expect/actual in hierarchical MPP 2019-04-30 20:03:30 +03:00
Dmitry Savvinov
811b31342c [Expect/Actual] Introduce ModuleStructureOracle 2019-04-30 20:03:30 +03:00
Dmitry Savvinov
62908efbfc [Expect/Actual] Inject ExpectActualChecker and related services instead of instantiating them ad hoc 2019-04-30 20:03:30 +03:00
Dmitry Savvinov
df5b935a38 [Expect/Actual] Remove PlatformExpectedAnnotator 2019-04-30 20:00:01 +03:00
Dmitry Savvinov
365b3908ea Minor: extract method in ExpectedActualDeclarationChecker for clarity 2019-04-30 20:00:00 +03:00
Dmitry Savvinov
bb5287f127 [Testing] Introduce ProjectResolveModel and parsing it from txt 2019-04-30 20:00:00 +03:00
Dmitry Savvinov
b85556df61 [Testing] Remove duplicate logic, clean-up CheckerTestUtil 2019-04-30 20:00:00 +03:00
Dmitry Savvinov
344f7a4b27 [Testing] Add more flexiblity to AbstractMultiModuleTest
- Preserve root names
- Provide an ability to transform copied file
- Allow passing several implemented modules in AbstractMultiModuleTest
2019-04-30 19:59:59 +03:00
Dmitry Savvinov
bf8e523d0d [Testing] Minor: fix typos in docs for DependenciesTxt 2019-04-30 19:59:59 +03:00
Dmitry Savvinov
62f7d6fa6a [Importing stub] Temporary hack for HMPP until proper importing will be ready 2019-04-30 19:59:59 +03:00
Dmitry Savvinov
20571b974e [Importing stub] Provide an ability to get all implemented modules rather than immediate ones 2019-04-30 19:59:59 +03:00
Dmitry Savvinov
b22fa28491 [Misc] Minor: generalize TypeUtils.closure 2019-04-30 19:59:58 +03:00
Dmitry Savvinov
51e3141c24 Imitate old comparison behaviour when collecting dependencies
This is needed, because previously such code were not distinguishing
between different flavours of JVM or Common. Now we do, and, for
example, JdkPlatform(1.6) != JdkPlatform(1.8), which causes such
dependencies to be erroneously dropped
2019-04-30 19:59:58 +03:00
Dmitry Savvinov
e68fca80da [Misc] Provide meaningful debugName for StorageManager everywhere 2019-04-30 19:59:58 +03:00
Dmitry Savvinov
9514079c4a [Injection] Make component containers composition more granular and flexible
Previously, containers set-up was performed by calls to static functions
like 'createContainerForLazyResolve', which would set-up whole container
from scratch.

This has several issues:
- complicates code re-use and encourages copy-paste of one and the same
set-up logic
- complicates composition of multiplatform containers (because each
set-up method relies on the fact that it should take an empty
container and compose it completely)

The idea of this commit is to split set-up methods into smaller ones,
with finer areas of responsibility, which allows to re-use them
in various scenarios (and, in particularly motivating composition
of multiplatform container)
2019-04-30 19:59:57 +03:00
Dmitry Savvinov
78597c5904 [Injection] Provide more debug info in InvalidCardinalityException 2019-04-30 19:59:57 +03:00
Dmitry Savvinov
690d940b98 [Injection] Introduce PlatformSpecificExtensions and PlatformExtensionsClashResolver
This commit introduces the ability to register a PlatformExtensionClashResolver
in a container. Each PlatformExtensionClashResolver has a corresponding
PlatformSpecificExtensions.

If, during container composition, several instances of
PlatformSpecificExtensions were registred, instead of throwing
InvalidCardinalityException, corresponding PlatformExtensionClashResolver
will be asked to resolve clash.

This allows to make injection more composable and less coupled across
different contributors of service, providing a basis for such motivating
cases as composing containers with both JS and JVM services (for analysis
of multiplatform modules).
Previously, that would be impossible:
a) JS would inject default instances for some services which would clash
with non-default JVM services (like SyntheticScopes)
b) Also, there are a very few services for which *both* platforms provide
non-default implementations, so they should be merged manually on
case-by-case basis (e.g., IdentifierChecker)
2019-04-30 19:59:56 +03:00
Dmitry Savvinov
465577ac63 [Injection] Minor: remove explicit injection of ExpressionTypingServices
They will be injected automatically anyways
2019-04-26 15:14:00 +03:00
Dmitry Savvinov
674fd627f3 [Injection] Pull languageVersionSettings injection to 'configureModule' 2019-04-26 15:14:00 +03:00
Dmitry Savvinov
f0f9f1061e [Injection] Minor: inline createLazyResolveSession 2019-04-26 15:14:00 +03:00
Dmitry Savvinov
9bba5cf291 [Injection] Minor: inline configureModule overload without trace 2019-04-26 15:13:59 +03:00
Dmitry Savvinov
f28e5e193f [Injection] Minor: inline createContainerForTopDownAnalyzerForJvm
Essentially, this function was used solely for setting
'useBuiltInsProvider' to 'true'; otherwise it were just delegating to
createContainerForLazyResolveWithJava, which were just increasing the
noise.
2019-04-26 15:13:59 +03:00
Dmitry Savvinov
e236e94e8a [Injection] Minor: inline configureJavaTopDownAnalysis
It was used called only once, and hasn't provided any useful
abstraction.

Actually, this "cosmetic" refactoring makes similarities with other
platform-specific container set-ups cleare, which allows to make further
generalizations and simplifications.
2019-04-26 15:13:59 +03:00
Dmitry Savvinov
e2b64245c1 [Injection] Minor: reformat injection.kt 2019-04-26 15:13:59 +03:00
Dmitry Savvinov
7672d2b0a9 [Platform API] Make 'ModuleInfo.platform' non-nullable 2019-04-26 15:13:59 +03:00
Dmitry Savvinov
1d26c389f7 [Platform API] Remove IdePlatform, use TargetPlatform instead 2019-04-26 15:13:59 +03:00
Dmitry Savvinov
0f9da30a64 Add platform suffix to the name of created module in tests
This is needed because platform of the module is determined by the
suffix after last '-' in 'createModule', and for string 'test-module'
that would be 'module', which obviously doesn't make any sense.

Howwever, due to how MultiTargetPlatform was implemented, it was
possible to create platform with such name, and everything was fine
as long as no one actually tried to switch on such a malformed
"platform".

After switching to more strict TargetPlatform representation, some tests
that had been trying to create platforms with such names started failing.

Seems that it was purely a mistake introduced in the
af1264a46d, so this commit fixes it by
specifying proper module name
2019-04-26 15:13:59 +03:00
Dmitry Savvinov
b921dd9e4d [Platform API] Introduce fundamental abstraction of Platform
This is a large commit, which introduces general API for working with
abstraction of Platform.

- Add new abstraction to 'core' - SimplePlatform - which represents
exactly one platform
  - Clients are strongly prohibited to create instances of SimplePlatform
  by hand, instead, corresponding *Platforms abstraction should be used
  (e.g. JvmPlatforms, JsPlatforms, KonanPlatforms)

- Move TargetPlatform to 'core', it represents now a collection of
SimplePlatforms
  - Clients are strongly encouraged to use TargetPlatform
    (not SimplePlatform) in API, to enforce checks for multiplatform

- Provide a helper-extensions to work with TargetPlatform
(in particular, for getting a specific component platform)

- Remove MultiTargetPlatform in favour of TargetPlatform
  - Notably, this commit leaves another widely used duplicated abstraction,
    namely, IdePlatform. For the sake sanity, removal of IdePlatform is
    extracted in the separate commit.
2019-04-26 15:13:59 +03:00
Dmitry Savvinov
f43738bf8d [Platform API] Minor: move some classes to separate files 2019-04-26 15:13:59 +03:00
Dmitry Savvinov
811a5b4d1e [Platform API] Split TargetPlatform into lightweight TargetPlatform and CompilerServices
This decouples simple data (TargetPlatform) from other subsystem-specific
logic (like default imports, built-ins, etc.).

Aside from purely aesthetic improvements, it also makes it easier
to move 'TargetPlatform' into core (see next commits)
2019-04-26 15:13:59 +03:00
Dmitry Savvinov
09d1603304 [Platform API] Clean-up some usages of Platform
Mostly unused imports. Also, in some places,
TargetPlatform/MultiTargetPlatform were just passed around without
actually using (e.g. in deserialization)
2019-04-26 15:13:58 +03:00
Dmitry Savvinov
66547f9c6c Remove internal API method which was deprecated in 1.3.0 2019-04-26 15:13:58 +03:00
Dmitry Savvinov
e424f06b7c Rename *AnalyzerFacade to *ResolverForModuleFactory to prevent confusion with other similar names 2019-04-26 15:13:58 +03:00
348 changed files with 3898 additions and 2009 deletions

View File

@@ -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) }

View File

@@ -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)
}
}
}

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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()

View File

@@ -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)
}

View File

@@ -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
}
}
}

View File

@@ -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}"

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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(

View File

@@ -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
}

View File

@@ -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 }

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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>())
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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>()
}
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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)
}
}
}

View File

@@ -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()

View File

@@ -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())
}
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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) }}"
}
}

View File

@@ -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>(

View File

@@ -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>()
}

View File

@@ -27,5 +27,6 @@ object CompilerEnvironment : TargetEnvironment("Compiler") {
container.useInstance(BodyResolveCache.ThrowException)
container.useImpl<CompilerLocalDescriptorResolver>()
container.useImpl<BasicAbsentDescriptorHandler>()
container.useInstance(ModuleStructureOracle.SingleModule)
}
}

View File

@@ -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,

View File

@@ -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)
}

View File

@@ -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) }
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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())
}

View File

@@ -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>

View File

@@ -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>) {

View File

@@ -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

View File

@@ -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)

View File

@@ -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!!)

View File

@@ -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
}
}
}

View File

@@ -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))
}
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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 ->

View File

@@ -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);

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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(

View File

@@ -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?

View File

@@ -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>,

View File

@@ -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
}
}

View File

@@ -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) }

View File

@@ -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)

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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));
}

View File

@@ -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)
})
}

View File

@@ -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
)

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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 = ""
}
}

View File

@@ -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
)

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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))

View File

@@ -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 = "/")

View File

@@ -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(

View File

@@ -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

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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

View File

@@ -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)

View File

@@ -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<*>)

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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?
}

View File

@@ -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)
// }
}

View File

@@ -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