State on types level that forcing imports works only for non-default
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user