Delete DefaultImportProvider, refactor TargetPlatform.defaultImports

This commit is contained in:
Alexander Udalov
2018-06-28 14:34:49 +02:00
parent 1f0fb4823f
commit ce34deb9af
9 changed files with 82 additions and 109 deletions
@@ -20,35 +20,25 @@ import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import java.util.*
import org.jetbrains.kotlin.storage.StorageManager
object JvmPlatform : TargetPlatform("JVM") {
private val defaultImports = LockBasedStorageManager().let { storageManager ->
storageManager.createMemoizedFunction<Boolean, List<ImportPath>> { includeKotlinComparisons ->
ArrayList<ImportPath>().apply {
addAll(Common.getDefaultImports(includeKotlinComparisons))
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {
result.add(ImportPath.fromString("kotlin.jvm.*"))
add(ImportPath.fromString("kotlin.jvm.*"))
fun addAllClassifiersFromScope(scope: MemberScope) {
for (descriptor in scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER)) {
add(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false))
}
}
for (builtinPackageFragment in JvmBuiltIns(storageManager).builtInsPackageFragmentsImportedByDefault) {
addAllClassifiersFromScope(builtinPackageFragment.getMemberScope())
}
fun addAllClassifiersFromScope(scope: MemberScope) {
for (descriptor in scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER)) {
result.add(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false))
}
}
for (builtinPackageFragment in JvmBuiltIns(storageManager).builtInsPackageFragmentsImportedByDefault) {
addAllClassifiersFromScope(builtinPackageFragment.getMemberScope())
}
}
override val defaultLowPriorityImports: List<ImportPath> = listOf(ImportPath.fromString("java.lang.*"))
override fun getDefaultImports(includeKotlinComparisons: Boolean): List<ImportPath> = defaultImports(includeKotlinComparisons)
override val platformConfigurator: PlatformConfigurator = JvmPlatformConfigurator
override val multiTargetPlatform = MultiTargetPlatform.Specific(platformName)
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.builtins.PlatformToKotlinClassMap
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.composeContainer
import org.jetbrains.kotlin.container.useInstance
@@ -17,43 +19,61 @@ import org.jetbrains.kotlin.resolve.checkers.*
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.DynamicTypesSettings
import java.util.*
abstract class TargetPlatform(val platformName: String) {
private data class DefaultImportsKey(val includeKotlinComparisons: Boolean, val includeLowPriorityImports: Boolean)
private val defaultImports = LockBasedStorageManager().let { storageManager ->
storageManager.createMemoizedFunction<DefaultImportsKey, List<ImportPath>> { (includeKotlinComparisons, includeLowPriorityImports) ->
ArrayList<ImportPath>().apply {
listOf(
"kotlin.*",
"kotlin.annotation.*",
"kotlin.collections.*",
"kotlin.ranges.*",
"kotlin.sequences.*",
"kotlin.text.*",
"kotlin.io.*"
).forEach { add(ImportPath.fromString(it)) }
if (includeKotlinComparisons) {
add(ImportPath.fromString("kotlin.comparisons.*"))
}
computePlatformSpecificDefaultImports(storageManager, this)
if (includeLowPriorityImports) {
addAll(defaultLowPriorityImports)
}
}
}
}
override fun toString() = platformName
abstract val platformConfigurator: PlatformConfigurator
open val defaultLowPriorityImports: List<ImportPath> get() = emptyList()
abstract fun getDefaultImports(includeKotlinComparisons: Boolean): List<ImportPath>
fun getDefaultImports(languageVersionSettings: LanguageVersionSettings, includeLowPriorityImports: Boolean): List<ImportPath> =
defaultImports(
DefaultImportsKey(
languageVersionSettings.supportsFeature(LanguageFeature.DefaultImportOfPackageKotlinComparisons),
includeLowPriorityImports
)
)
protected abstract fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>)
open val excludedImports: List<FqName> get() = emptyList()
abstract val multiTargetPlatform: MultiTargetPlatform
object Common : TargetPlatform("Default") {
private val defaultImports =
LockBasedStorageManager().createMemoizedFunction<Boolean, List<ImportPath>> { includeKotlinComparisons ->
ArrayList<ImportPath>().apply {
listOf(
"kotlin.*",
"kotlin.annotation.*",
"kotlin.collections.*",
"kotlin.ranges.*",
"kotlin.sequences.*",
"kotlin.text.*",
"kotlin.io.*"
).forEach { add(ImportPath.fromString(it)) }
if (includeKotlinComparisons) {
add(ImportPath.fromString("kotlin.comparisons.*"))
}
}
}
override fun getDefaultImports(includeKotlinComparisons: Boolean): List<ImportPath> = defaultImports(includeKotlinComparisons)
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {}
override val platformConfigurator =
object : PlatformConfigurator(
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2016 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.lazy
import org.jetbrains.kotlin.config.LanguageFeature.DefaultImportOfPackageKotlinComparisons
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.SinceKotlinAccessibility
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
class DefaultImportProvider(
storageManager: StorageManager,
private val targetPlatform: TargetPlatform,
private val languageVersionSettings: LanguageVersionSettings
) {
val defaultImports: List<ImportPath> by storageManager.createLazyValue {
targetPlatform.getDefaultImports(languageVersionSettings.supportsFeature(DefaultImportOfPackageKotlinComparisons))
}
val allDefaultImports: List<ImportPath> by storageManager.createLazyValue {
defaultImports + targetPlatform.defaultLowPriorityImports
}
}
@@ -44,14 +44,15 @@ class FileScopeFactory(
private val bindingTrace: BindingTrace,
private val ktImportsFactory: KtImportsFactory,
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
private val defaultImportProvider: DefaultImportProvider,
private val targetPlatform: TargetPlatform,
private val languageVersionSettings: LanguageVersionSettings,
private val deprecationResolver: DeprecationResolver
) {
/* avoid constructing psi for default imports prematurely (time consuming in some scenarios) */
private val defaultImports by storageManager.createLazyValue {
ktImportsFactory.createImportDirectivesNotCached(defaultImportProvider.defaultImports)
ktImportsFactory.createImportDirectivesNotCached(
targetPlatform.getDefaultImports(languageVersionSettings, includeLowPriorityImports = false)
)
}
private val defaultLowPriorityImports by storageManager.createLazyValue {
@@ -27,7 +27,6 @@ import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult.*
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
@@ -259,8 +258,8 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName:
private fun KtFile.getDefaultImports(): List<ImportPath> {
val moduleInfo = getNullableModuleInfo() ?: return emptyList()
val versionSettings = IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project)
val platform = TargetPlatformDetector.getPlatform(this)
return platform.getDefaultImports(versionSettings.supportsFeature(LanguageFeature.DefaultImportOfPackageKotlinComparisons)) +
platform.defaultLowPriorityImports
return TargetPlatformDetector.getPlatform(this).getDefaultImports(
IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project),
includeLowPriorityImports = true
)
}
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.psi.KtUserType
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.lazy.DefaultImportProvider
import org.jetbrains.kotlin.resolve.lazy.descriptors.ClassResolutionScopesSupport
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.utils.chainImportingScopes
@@ -74,9 +73,9 @@ object ReplaceWithAnnotationAnalyzer {
val module = resolutionFacade.moduleDescriptor
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
val defaultImportsScopes = buildDefaultImportsScopes(resolutionFacade, module)
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val defaultImportsScopes = buildDefaultImportsScopes(resolutionFacade, module, languageVersionSettings)
val languageVersionSettings = resolutionFacade.getFrontendService(LanguageVersionSettings::class.java)
val scope = getResolutionScope(
symbolDescriptor, symbolDescriptor,
listOf(explicitImportsScope), defaultImportsScopes, languageVersionSettings
@@ -106,12 +105,10 @@ object ReplaceWithAnnotationAnalyzer {
val module = resolutionFacade.moduleDescriptor
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
val defaultImportScopes = buildDefaultImportsScopes(resolutionFacade, module)
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val defaultImportScopes = buildDefaultImportsScopes(resolutionFacade, module, languageVersionSettings)
val scope = getResolutionScope(
symbolDescriptor,
symbolDescriptor,
listOf(explicitImportsScope), defaultImportScopes,
resolutionFacade.getFrontendService(LanguageVersionSettings::class.java)
symbolDescriptor, symbolDescriptor, listOf(explicitImportsScope), defaultImportScopes, languageVersionSettings
) ?: return null
val typeResolver = resolutionFacade.getFrontendService(TypeResolver::class.java)
@@ -138,9 +135,14 @@ object ReplaceWithAnnotationAnalyzer {
return typeReference.typeElement as KtUserType
}
private fun buildDefaultImportsScopes(resolutionFacade: ResolutionFacade, module: ModuleDescriptor): List<ImportingScope> {
val (allUnderImports, aliasImports) =
resolutionFacade.frontendService<DefaultImportProvider>().allDefaultImports.partition { it.isAllUnder }
private fun buildDefaultImportsScopes(
resolutionFacade: ResolutionFacade,
module: ModuleDescriptor,
languageVersionSettings: LanguageVersionSettings
): List<ImportingScope> {
val allDefaultImports =
resolutionFacade.frontendService<TargetPlatform>().getDefaultImports(languageVersionSettings, includeLowPriorityImports = true)
val (allUnderImports, aliasImports) = allDefaultImports.partition { it.isAllUnder }
// this solution doesn't support aliased default imports with a different alias
// TODO: Create import directives from ImportPath, create ImportResolver, create LazyResolverScope, see FileScopeProviderImpl
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.util
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
@@ -38,7 +39,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.DefaultImportProvider
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -59,9 +59,10 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
get() = ImportPathComparator
override fun isImportedWithDefault(importPath: ImportPath, contextFile: KtFile): Boolean {
val defaultImportProvider = contextFile.getResolutionFacade().frontendService<DefaultImportProvider>()
val languageVersionSettings = contextFile.getResolutionFacade().frontendService<LanguageVersionSettings>()
val platform = TargetPlatformDetector.getPlatform(contextFile)
return importPath.isImported(defaultImportProvider.allDefaultImports, platform.excludedImports)
val allDefaultImports = platform.getDefaultImports(languageVersionSettings, includeLowPriorityImports = true)
return importPath.isImported(allDefaultImports, platform.excludedImports)
}
override fun isImportedWithLowPriorityDefaultImport(importPath: ImportPath, contextFile: KtFile): Boolean {
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.j2k.ast.Import
@@ -163,7 +162,8 @@ private fun renderImportName(fqName: FqName, isOnDemand: Boolean)
private val DEFAULT_IMPORTS_SET: Set<FqName> = JvmPlatform.getDefaultImports(
// TODO: use the correct LanguageVersionSettings instance here
LanguageVersionSettingsImpl.DEFAULT.supportsFeature(LanguageFeature.DefaultImportOfPackageKotlinComparisons)
).plus(JvmPlatform.defaultLowPriorityImports).filter { it.isAllUnder }.map { it.fqName }.toSet()
LanguageVersionSettingsImpl.DEFAULT,
includeLowPriorityImports = true
).filter { it.isAllUnder }.map { it.fqName }.toSet()
private fun isImportedByDefault(c: KtLightClass) = c.qualifiedName?.let { FqName(it).parent() } in DEFAULT_IMPORTS_SET
@@ -23,15 +23,13 @@ import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
import org.jetbrains.kotlin.resolve.PlatformConfigurator
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
object JsPlatform : TargetPlatform("JS") {
private val defaultImports = LockBasedStorageManager().createMemoizedFunction<Boolean, List<ImportPath>> { includeKotlinComparisons ->
Common.getDefaultImports(includeKotlinComparisons) + ImportPath.fromString("kotlin.js.*")
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {
result.add(ImportPath.fromString("kotlin.js.*"))
}
override fun getDefaultImports(includeKotlinComparisons: Boolean): List<ImportPath> = defaultImports(includeKotlinComparisons)
override val platformConfigurator: PlatformConfigurator = JsPlatformConfigurator
val builtIns: KotlinBuiltIns
@@ -39,5 +37,6 @@ object JsPlatform : TargetPlatform("JS") {
override val multiTargetPlatform = MultiTargetPlatform.Specific(platformName)
override val excludedImports: List<FqName> = listOf("Promise", "Date", "Console", "Math", "RegExp", "RegExpMatch", "Json", "json").map { FqName("kotlin.js.$it") }
override val excludedImports: List<FqName> =
listOf("Promise", "Date", "Console", "Math", "RegExp", "RegExpMatch", "Json", "json").map { FqName("kotlin.js.$it") }
}