State on types level that forcing imports works only for non-default

This commit is contained in:
Denis Zharkov
2018-07-19 15:52:28 +03:00
parent 79e776e9d7
commit 0b2fde3886
7 changed files with 141 additions and 111 deletions
@@ -222,7 +222,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
val lastLineImports = lexicalScopeAfterLastLine.parentsWithSelf.first { it is ImportingScope } as ImportingScope
val scopesForThisLine = fileScopeFactory.createScopesForFile(lineInfo.linePsi, lastLineImports)
val combinedLexicalScopes = lexicalScopeAfterLastLine.replaceImportingScopes(scopesForThisLine.importingScope)
return FileScopes(combinedLexicalScopes, scopesForThisLine.importingScope, scopesForThisLine.importResolver)
return FileScopes(combinedLexicalScopes, scopesForThisLine.importingScope, scopesForThisLine.importForceResolver)
}
}
}
@@ -247,7 +247,7 @@ class LazyTopDownAnalyzer(
}
fun resolveImportsInFile(file: KtFile) {
fileScopeProvider.getImportResolver(file).forceResolveAllImports()
fileScopeProvider.getImportResolver(file).forceResolveNonDefaultImports()
}
private fun createTypeAliasDescriptors(
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtImportInfo
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.scopes.*
@@ -33,7 +34,7 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
data class FileScopes(val lexicalScope: LexicalScope, val importingScope: ImportingScope, val importResolver: ImportResolver)
data class FileScopes(val lexicalScope: LexicalScope, val importingScope: ImportingScope, val importForceResolver: ImportForceResolver)
class FileScopeFactory(
private val topLevelDescriptorProvider: TopLevelDescriptorProvider,
@@ -69,13 +70,13 @@ class FileScopeFactory(
}
private data class DefaultImportResolvers(
val explicit: LazyImportResolver,
val allUnder: LazyImportResolver,
val lowPriority: LazyImportResolver
val explicit: LazyImportResolver<DefaultImportImpl>,
val allUnder: LazyImportResolver<DefaultImportImpl>,
val lowPriority: LazyImportResolver<DefaultImportImpl>
)
private fun createDefaultImportResolvers(
extraImports: Collection<KtImportInfo>,
extraImports: Collection<DefaultImportImpl>,
aliasImportNames: Collection<FqName>
): DefaultImportResolvers {
val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve", false)
@@ -87,20 +88,20 @@ class FileScopeFactory(
allImplicitImports.filter { it.isAllUnder || it.importedFqName !in aliasImportNames }
}
val explicit = createImportResolver(
val explicit = createDefaultImportResolver(
ExplicitImportsIndexed(defaultImportsFiltered),
tempTrace,
packageFragment = null,
aliasImportNames = aliasImportNames
)
val allUnder = createImportResolver(
val allUnder = createDefaultImportResolver(
AllUnderImportsIndexed(defaultImportsFiltered),
tempTrace,
packageFragment = null,
aliasImportNames = aliasImportNames,
excludedImports = targetPlatform.excludedImports
)
val lowPriority = createImportResolver(
val lowPriority = createDefaultImportResolver(
AllUnderImportsIndexed(defaultLowPriorityImports.also { imports ->
assert(imports.all { it.isAllUnder }) { "All low priority imports must be all-under: $imports" }
}),
@@ -116,8 +117,8 @@ class FileScopeFactory(
createDefaultImportResolvers(emptyList(), emptyList())
}
private fun createImportResolver(
indexedImports: IndexedImports,
private fun createDefaultImportResolver(
indexedImports: IndexedImports<DefaultImportImpl>,
trace: BindingTrace,
aliasImportNames: Collection<FqName>,
packageFragment: PackageFragmentDescriptor?,
@@ -128,6 +129,17 @@ class FileScopeFactory(
deprecationResolver
)
private fun createImportResolver(
indexedImports: IndexedImports<KtImportDirective>,
trace: BindingTrace,
aliasImportNames: Collection<FqName>,
packageFragment: PackageFragmentDescriptor?,
excludedImports: List<FqName>? = null
) = LazyImportResolverForKtImportDirective(
storageManager, qualifiedExpressionResolver, moduleDescriptor, platformToKotlinClassMap, languageVersionSettings,
indexedImports, aliasImportNames concat excludedImports, trace, packageFragment,
deprecationResolver
)
private inner class FilesScopesBuilder(
private val file: KtFile,
@@ -156,13 +168,13 @@ class FileScopeFactory(
val lexicalScope =
LexicalScope.Base(lazyImportingScope, topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(file.packageFqName, file))
val importResolver = object : ImportResolver {
override fun forceResolveAllImports() {
explicitImportResolver.forceResolveAllImports()
allUnderImportResolver.forceResolveAllImports()
val importResolver = object : ImportForceResolver {
override fun forceResolveNonDefaultImports() {
explicitImportResolver.forceResolveNonDefaultImports()
allUnderImportResolver.forceResolveNonDefaultImports()
}
override fun forceResolveImport(importDirective: KtImportInfo) {
override fun forceResolveImport(importDirective: KtImportDirective) {
if (importDirective.isAllUnder) {
allUnderImportResolver.forceResolveImport(importDirective)
} else {
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.storage.StorageManager
@DefaultImplementation(FileScopeProviderImpl::class)
interface FileScopeProvider {
fun getFileResolutionScope(file: KtFile): LexicalScope = getFileScopes(file).lexicalScope
fun getImportResolver(file: KtFile): ImportResolver = getFileScopes(file).importResolver
fun getImportResolver(file: KtFile): ImportForceResolver = getFileScopes(file).importForceResolver
fun getFileScopes(file: KtFile): FileScopes
@@ -57,4 +57,4 @@ interface FileScopesCustomizer {
fun createFileScopes(fileScopeFactory: FileScopeFactory): FileScopes
}
var KtFile.fileScopesCustomizer: FileScopesCustomizer? by UserDataProperty(Key.create("FILE_SCOPES_CUSTOMIZER"))
var KtFile.fileScopesCustomizer: FileScopesCustomizer? by UserDataProperty(Key.create("FILE_SCOPES_CUSTOMIZER"))
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtImportDirective
@@ -42,21 +41,21 @@ import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
import org.jetbrains.kotlin.utils.ifEmpty
interface IndexedImports {
val imports: List<KtImportInfo>
fun importsForName(name: Name): Collection<KtImportInfo>
interface IndexedImports<I : KtImportInfo> {
val imports: List<I>
fun importsForName(name: Name): Collection<I>
}
class AllUnderImportsIndexed(allImports: Collection<KtImportInfo>) : IndexedImports {
class AllUnderImportsIndexed<I : KtImportInfo>(allImports: Collection<I>) : IndexedImports<I> {
override val imports = allImports.filter { it.isAllUnder }
override fun importsForName(name: Name) = imports
}
class ExplicitImportsIndexed(allImports: Collection<KtImportInfo>) : IndexedImports {
class ExplicitImportsIndexed<I : KtImportInfo>(allImports: Collection<I>) : IndexedImports<I> {
override val imports = allImports.filter { !it.isAllUnder }
private val nameToDirectives: ListMultimap<Name, KtImportInfo> by lazy {
val builder = ImmutableListMultimap.builder<Name, KtImportInfo>()
private val nameToDirectives: ListMultimap<Name, I> by lazy {
val builder = ImmutableListMultimap.builder<Name, I>()
for (directive in imports) {
val importedName = directive.importedName ?: continue // parse error
@@ -69,100 +68,29 @@ class ExplicitImportsIndexed(allImports: Collection<KtImportInfo>) : IndexedImpo
override fun importsForName(name: Name) = nameToDirectives.get(name)
}
interface ImportResolver {
fun forceResolveAllImports()
fun forceResolveImport(importDirective: KtImportInfo)
interface ImportForceResolver {
fun forceResolveNonDefaultImports()
fun forceResolveImport(importDirective: KtImportDirective)
}
class LazyImportResolver(
open class LazyImportResolver<I : KtImportInfo>(
val storageManager: StorageManager,
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
val moduleDescriptor: ModuleDescriptor,
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
val languageVersionSettings: LanguageVersionSettings,
val indexedImports: IndexedImports,
val indexedImports: IndexedImports<I>,
excludedImportNames: Collection<FqName>,
private val traceForImportResolve: BindingTrace,
protected val traceForImportResolve: BindingTrace,
private val packageFragment: PackageFragmentDescriptor?,
val deprecationResolver: DeprecationResolver
) : ImportResolver {
) {
private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues { directive: KtImportInfo ->
qualifiedExpressionResolver.processImportReference(
directive, moduleDescriptor, traceForImportResolve, excludedImportNames, packageFragment
)
}
private val forceResolveImportDirective = storageManager.createMemoizedFunction { directive: KtImportInfo ->
val scope = importedScopesProvider(directive)
if (scope is LazyExplicitImportScope) {
val allDescriptors = scope.storeReferencesToDescriptors()
if (directive is KtImportDirective) {
PlatformClassesMappedToKotlinChecker.checkPlatformClassesMappedToKotlin(
platformToKotlinClassMap, traceForImportResolve, directive, allDescriptors
)
}
}
Unit
}
private val forceResolveAllImportsTask: NotNullLazyValue<Unit> = storageManager.createLazyValue {
val explicitClassImports = HashMultimap.create<String, KtImportInfo>()
for (importDirective in indexedImports.imports) {
forceResolveImport(importDirective)
val scope = importedScopesProvider(importDirective)
val alias = importDirective.importedName
if (scope != null && alias != null) {
val lookupLocation = when (importDirective) {
is KtImportDirective -> KotlinLookupLocation(importDirective)
else -> NoLookupLocation.FOR_DEFAULT_IMPORTS
}
if (scope.getContributedClassifier(alias, lookupLocation) != null) {
explicitClassImports.put(alias.asString(), importDirective)
}
}
checkResolvedImportDirective(importDirective)
}
for ((alias, import) in explicitClassImports.entries()) {
if (import !is KtImportDirective) continue
if (alias.all { it == '_' }) {
traceForImportResolve.report(Errors.UNDERSCORE_IS_RESERVED.on(import))
}
}
for (alias in explicitClassImports.keySet()) {
val imports = explicitClassImports.get(alias)
if (imports.size > 1) {
imports.filterIsInstance<KtImportDirective>().forEach {
traceForImportResolve.report(Errors.CONFLICTING_IMPORT.on(it, alias))
}
}
}
}
override fun forceResolveAllImports() {
forceResolveAllImportsTask()
}
private fun checkResolvedImportDirective(importDirective: KtImportInfo) {
if (importDirective !is KtImportDirective) return
val importedReference = KtPsiUtil.getLastReference(importDirective.importedReference ?: return) ?: return
val importedDescriptor = traceForImportResolve.bindingContext.get(BindingContext.REFERENCE_TARGET, importedReference) ?: return
val aliasName = importDirective.aliasName
if (importedDescriptor is FunctionDescriptor && importedDescriptor.isOperator &&
aliasName != null && OperatorConventions.isConventionName(Name.identifier(aliasName))) {
traceForImportResolve.report(Errors.OPERATOR_RENAMED_ON_IMPORT.on(importedReference))
}
}
override fun forceResolveImport(importDirective: KtImportInfo) {
forceResolveImportDirective(importDirective)
}
fun <D : DeclarationDescriptor> selectSingleFromImports(
name: Name,
descriptorSelector: (ImportingScope, Name) -> D?
@@ -214,10 +142,100 @@ class LazyImportResolver(
}
}
class LazyImportResolverForKtImportDirective(
storageManager: StorageManager,
qualifiedExpressionResolver: QualifiedExpressionResolver,
moduleDescriptor: ModuleDescriptor,
platformToKotlinClassMap: PlatformToKotlinClassMap,
languageVersionSettings: LanguageVersionSettings,
indexedImports: IndexedImports<KtImportDirective>,
excludedImportNames: Collection<FqName>,
traceForImportResolve: BindingTrace,
packageFragment: PackageFragmentDescriptor?,
deprecationResolver: DeprecationResolver
) : LazyImportResolver<KtImportDirective>(
storageManager,
qualifiedExpressionResolver,
moduleDescriptor,
platformToKotlinClassMap,
languageVersionSettings,
indexedImports,
excludedImportNames,
traceForImportResolve,
packageFragment,
deprecationResolver
), ImportForceResolver {
private val forceResolveImportDirective = storageManager.createMemoizedFunction { directive: KtImportDirective ->
val scope = getImportScope(directive)
if (scope is LazyExplicitImportScope) {
val allDescriptors = scope.storeReferencesToDescriptors()
PlatformClassesMappedToKotlinChecker.checkPlatformClassesMappedToKotlin(
platformToKotlinClassMap, traceForImportResolve, directive, allDescriptors
)
}
Unit
}
private val forceResolveNonDefaultImportsTask: NotNullLazyValue<Unit> = storageManager.createLazyValue {
val explicitClassImports = HashMultimap.create<String, KtImportDirective>()
for (importInfo in indexedImports.imports) {
forceResolveImport(importInfo)
val scope = getImportScope(importInfo)
val alias = importInfo.importedName
if (alias != null) {
val lookupLocation = KotlinLookupLocation(importInfo)
if (scope.getContributedClassifier(alias, lookupLocation) != null) {
explicitClassImports.put(alias.asString(), importInfo)
}
}
checkResolvedImportDirective(importInfo)
}
for ((alias, import) in explicitClassImports.entries()) {
if (alias.all { it == '_' }) {
traceForImportResolve.report(Errors.UNDERSCORE_IS_RESERVED.on(import))
}
}
for (alias in explicitClassImports.keySet()) {
val imports = explicitClassImports.get(alias)
if (imports.size > 1) {
imports.forEach {
traceForImportResolve.report(Errors.CONFLICTING_IMPORT.on(it, alias))
}
}
}
}
override fun forceResolveNonDefaultImports() {
forceResolveNonDefaultImportsTask()
}
private fun checkResolvedImportDirective(importDirective: KtImportInfo) {
if (importDirective !is KtImportDirective) return
val importedReference = KtPsiUtil.getLastReference(importDirective.importedReference ?: return) ?: return
val importedDescriptor = traceForImportResolve.bindingContext.get(BindingContext.REFERENCE_TARGET, importedReference) ?: return
val aliasName = importDirective.aliasName
if (importedDescriptor is FunctionDescriptor && importedDescriptor.isOperator &&
aliasName != null && OperatorConventions.isConventionName(Name.identifier(aliasName))) {
traceForImportResolve.report(Errors.OPERATOR_RENAMED_ON_IMPORT.on(importedReference))
}
}
override fun forceResolveImport(importDirective: KtImportDirective) {
forceResolveImportDirective(importDirective)
}
}
class LazyImportScope(
override val parent: ImportingScope?,
private val importResolver: LazyImportResolver,
private val secondaryImportResolver: LazyImportResolver?,
private val importResolver: LazyImportResolver<*>,
private val secondaryImportResolver: LazyImportResolver<*>?,
private val filteringKind: LazyImportScope.FilteringKind,
private val debugName: String
) : ImportingScope {
@@ -228,7 +246,7 @@ class LazyImportScope(
INVISIBLE_CLASSES
}
private fun LazyImportResolver.isClassifierVisible(descriptor: ClassifierDescriptor): Boolean {
private fun LazyImportResolver<*>.isClassifierVisible(descriptor: ClassifierDescriptor): Boolean {
if (filteringKind == FilteringKind.ALL) return true
if (deprecationResolver.isHiddenInResolution(descriptor)) return false
@@ -243,7 +261,7 @@ class LazyImportScope(
return importResolver.getClassifier(name, location) ?: secondaryImportResolver?.getClassifier(name, location)
}
private fun LazyImportResolver.getClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
private fun LazyImportResolver<*>.getClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
return selectSingleFromImports(name) { scope, _ ->
val descriptor = scope.getContributedClassifier(name, location)
if ((descriptor is ClassDescriptor || descriptor is TypeAliasDescriptor) && isClassifierVisible(descriptor))
@@ -77,6 +77,6 @@ class ReplState {
val lastLineImports = lexicalScopeAfterLastLine.parentsWithSelf.firstIsInstance<ImportingScope>()
val scopesForThisLine = fileScopeFactory.createScopesForFile(lineInfo.linePsi, lastLineImports)
val combinedLexicalScopes = lexicalScopeAfterLastLine.replaceImportingScopes(scopesForThisLine.importingScope)
return FileScopes(combinedLexicalScopes, scopesForThisLine.importingScope, scopesForThisLine.importResolver)
return FileScopes(combinedLexicalScopes, scopesForThisLine.importingScope, scopesForThisLine.importForceResolver)
}
}
@@ -371,7 +371,7 @@ class ResolveElementCache(
is KtImportList -> {
val resolver = resolveSession.fileScopeProvider.getImportResolver(resolveElement.getContainingKtFile())
resolver.forceResolveAllImports()
resolver.forceResolveNonDefaultImports()
resolveSession.trace
}