From 174ef569913edba5b41986563d00f04c0427bba4 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Wed, 10 Apr 2019 10:48:08 +0300 Subject: [PATCH] [Expect/Actual] Remove PlatformExpectedAnnotator --- .../common/CommonResolverForModuleFactory.kt | 136 ++++++++++-------- .../jetbrains/kotlin/frontend/di/injection.kt | 8 ++ .../resolve/CommonPlatformKindResolution.kt | 2 +- .../platform/CommonIdePlatformKindTooling.kt | 2 +- idea/resources/META-INF/plugin-common.xml | 1 - .../highlighter/PlatformExpectedAnnotator.kt | 74 ---------- 6 files changed, 83 insertions(+), 140 deletions(-) delete mode 100644 idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt index 8ad6b71ddfe..e3fc88018d3 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/analyzer/common/CommonResolverForModuleFactory.kt @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService @@ -54,67 +55,7 @@ class CommonAnalysisParameters( * A facade that is used to analyze common (platform-independent) modules in multi-platform projects. * See [CommonPlatform] */ -object CommonResolverForModuleFactory : ResolverForModuleFactory() { - private class SourceModuleInfo( - override val name: Name, - override val capabilities: Map, 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 analyzerServices: PlatformDependentAnalyzerServices - get() = CommonPlatformAnalyzerServices - } - - fun analyzeFiles( - files: Collection, moduleName: Name, dependOnBuiltIns: Boolean, languageVersionSettings: LanguageVersionSettings, - capabilities: Map, Any?> = emptyMap(), - metadataPartProviderFactory: (ModuleContent) -> 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 }, - platformParameters = { _ -> CommonAnalysisParameters(metadataPartProviderFactory) } - ) - - val moduleDescriptor = resolver.descriptorForModule(moduleInfo) - val container = resolver.resolverForModule(moduleInfo).componentProvider - - container.get().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files) - - return AnalysisResult.success(container.get().bindingContext, moduleDescriptor) - } +class CommonResolverForModuleFactory(private val shouldCheckExpectActual: Boolean) : ResolverForModuleFactory() { override fun createResolverForModule( moduleDescriptor: ModuleDescriptorImpl, @@ -137,7 +78,7 @@ object CommonResolverForModuleFactory : ResolverForModuleFactory() { val trace = CodeAnalyzerInitializer.getInstance(project).createTrace() val container = createContainerToResolveCommonCode( moduleContext, trace, declarationProviderFactory, moduleContentScope, targetEnvironment, metadataPartProvider, - languageVersionSettings, CommonPlatforms.defaultCommonPlatform, CommonPlatformAnalyzerServices + languageVersionSettings, CommonPlatforms.defaultCommonPlatform, CommonPlatformAnalyzerServices, shouldCheckExpectActual ) val packageFragmentProviders = listOf( @@ -147,6 +88,70 @@ object CommonResolverForModuleFactory : ResolverForModuleFactory() { return ResolverForModule(CompositePackageFragmentProvider(packageFragmentProviders), container) } + + companion object { + private class SourceModuleInfo( + override val name: Name, + override val capabilities: Map, 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 analyzerServices: PlatformDependentAnalyzerServices + get() = CommonPlatformAnalyzerServices + } + + fun analyzeFiles( + files: Collection, moduleName: Name, dependOnBuiltIns: Boolean, languageVersionSettings: LanguageVersionSettings, + capabilities: Map, Any?> = emptyMap(), + shouldCheckExpectActual: Boolean = false, + metadataPartProviderFactory: (ModuleContent) -> 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(shouldCheckExpectActual) }, + platformParameters = { _ -> CommonAnalysisParameters(metadataPartProviderFactory) } + ) + + val moduleDescriptor = resolver.descriptorForModule(moduleInfo) + val container = resolver.resolverForModule(moduleInfo).componentProvider + + container.get().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files) + + return AnalysisResult.success(container.get().bindingContext, moduleDescriptor) + } + } } private fun createContainerToResolveCommonCode( @@ -158,7 +163,8 @@ private fun createContainerToResolveCommonCode( metadataPartProvider: MetadataPartProvider, languageVersionSettings: LanguageVersionSettings, platform: TargetPlatform, - analyzerServices: PlatformDependentAnalyzerServices + analyzerServices: PlatformDependentAnalyzerServices, + shouldCheckExpectActual: Boolean ): StorageComponentContainer = createContainer("ResolveCommonCode", analyzerServices) { configureModule(moduleContext, platform, analyzerServices, bindingTrace, languageVersionSettings) @@ -179,6 +185,10 @@ private fun createContainerToResolveCommonCode( useInstance(metadataFinderFactory.create(moduleContentScope)) targetEnvironment.configure(this) + + if (shouldCheckExpectActual) { + useImpl() + } } fun StorageComponentContainer.configureCommonSpecificComponents() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 39e371332fe..94b73474206 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -27,10 +27,12 @@ import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.platform.TargetPlatformVersion +import org.jetbrains.kotlin.platform.isCommon 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 @@ -140,6 +142,12 @@ fun createContainerForLazyBodyResolve( useImpl() useImpl() useInstance(moduleStructureOracle) + + // All containers except common inject ExpectedActualDeclarationChecker, so for common we do that + // explicitly. + // Note that it is not possible to move this code to [CommonPlatformConfigurator], because during + // compilation of common-module to metadata we should skip those checks + if (platform.isCommon()) useImpl() } fun createContainerForLazyLocalClassifierAnalyzer( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt index 661ecb25f8f..0aa9fd12753 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CommonPlatformKindResolution.kt @@ -28,7 +28,7 @@ class CommonPlatformKindResolution : IdePlatformKindResolution { override val kind get() = CommonIdePlatformKind override val resolverForModuleFactory: ResolverForModuleFactory - get() = CommonResolverForModuleFactory + get() = CommonResolverForModuleFactory(shouldCheckExpectActual = true) override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext): KotlinBuiltIns { return DefaultBuiltIns.Instance diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/platform/CommonIdePlatformKindTooling.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/platform/CommonIdePlatformKindTooling.kt index 36db142639c..abc446db8d8 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/platform/CommonIdePlatformKindTooling.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/platform/CommonIdePlatformKindTooling.kt @@ -34,7 +34,7 @@ object CommonIdePlatformKindTooling : IdePlatformKindTooling() { override fun compilerArgumentsForProject(project: Project): CommonCompilerArguments? = null - override val resolverForModuleFactory = CommonResolverForModuleFactory + override val resolverForModuleFactory = CommonResolverForModuleFactory(true) override val mavenLibraryIds = listOf(MAVEN_COMMON_STDLIB_ID) override val gradlePluginId = "kotlin-platform-common" diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index e4f83738640..77801fe6c81 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -594,7 +594,6 @@ - diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt deleted file mode 100644 index f95aef38fec..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/PlatformExpectedAnnotator.kt +++ /dev/null @@ -1,74 +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.idea.highlighter - -import com.intellij.lang.annotation.AnnotationHolder -import com.intellij.lang.annotation.Annotator -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.caches.resolve.KotlinCacheService -import org.jetbrains.kotlin.descriptors.MemberDescriptor -import org.jetbrains.kotlin.idea.caches.project.implementingDescriptors -import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor -import org.jetbrains.kotlin.idea.core.toDescriptor -import org.jetbrains.kotlin.idea.project.TargetPlatformDetector -import org.jetbrains.kotlin.incremental.components.ExpectActualTracker -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtPsiUtil -import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier -import org.jetbrains.kotlin.resolve.BindingTraceContext -import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker -import org.jetbrains.kotlin.resolve.diagnostics.SimpleDiagnostics -import org.jetbrains.kotlin.platform.isCommon -import org.jetbrains.kotlin.resolve.jvm.multiplatform.JavaActualAnnotationArgumentExtractor - -class PlatformExpectedAnnotator : Annotator { - override fun annotate(element: PsiElement, holder: AnnotationHolder) { - val declaration = element as? KtNamedDeclaration ?: return - if (!isExpectedDeclaration(declaration)) return - - if (!TargetPlatformDetector.getPlatform(declaration.containingKtFile).isCommon()) return - - val implementingModules = declaration.findModuleDescriptor().implementingDescriptors - if (implementingModules.isEmpty()) return - - val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return - if (!descriptor.isExpect) return - - // TODO: obtain the list of annotation argument extractors from platform somehow - val checker = ExpectedActualDeclarationChecker(listOf(JavaActualAnnotationArgumentExtractor())) - - val trace = BindingTraceContext() - for (module in implementingModules) { - checker.checkExpectedDeclarationHasActual(declaration, descriptor, trace, module, ExpectActualTracker.DoNothing) - } - - val suppressionCache = KotlinCacheService.getInstance(declaration.project).getSuppressionCache() - val filteredList = trace.bindingContext.diagnostics.filter { diagnostic -> - !suppressionCache.isSuppressed(declaration, diagnostic.factory.name, diagnostic.severity) - } - if (filteredList.isEmpty()) return - - KotlinPsiChecker().annotateElement(declaration, holder, SimpleDiagnostics(filteredList)) - } - - private fun isExpectedDeclaration(declaration: KtDeclaration): Boolean { - return declaration.hasExpectModifier() || - declaration is KtClassOrObject && KtPsiUtil.getOutermostClassOrObject(declaration)?.hasExpectModifier() == true - } -}