Refactor FileScopeFactory

This commit is contained in:
Pavel V. Talanov
2017-03-01 18:24:13 +03:00
parent d7c1993194
commit 6f6a595fef
@@ -54,15 +54,12 @@ class FileScopeFactory(
private val defaultImportProvider: DefaultImportProvider, private val defaultImportProvider: DefaultImportProvider,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings
) { ) {
/* avoid constructing psi for default imports prematurely (time consuming in some scenarios) */
private val defaultImports by storageManager.createLazyValue { private val defaultImports by storageManager.createLazyValue {
ktImportsFactory.createImportDirectives(defaultImportProvider.defaultImports) ktImportsFactory.createImportDirectives(defaultImportProvider.defaultImports)
} }
fun createScopesForFile(file: KtFile, existingImports: ImportingScope? = null): FileScopes { fun createScopesForFile(file: KtFile, existingImports: ImportingScope? = null): FileScopes {
infix fun <T> Collection<T>.concat(other: Collection<T>?) =
if (other == null || other.isEmpty()) this else this + other
val packageView = moduleDescriptor.getPackage(file.packageFqName) val packageView = moduleDescriptor.getPackage(file.packageFqName)
val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.packageFqName) val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.packageFqName)
if (packageFragment == null) { if (packageFragment == null) {
@@ -71,21 +68,56 @@ class FileScopeFactory(
error("Could not find fragment ${file.packageFqName} for file ${file.name}") error("Could not find fragment ${file.packageFqName} for file ${file.name}")
} }
return FilesScopesBuilder(file, existingImports, packageFragment, packageView).result
}
private inner class FilesScopesBuilder(
private val file: KtFile,
private val existingImports: ImportingScope?,
private val packageFragment: PackageFragmentDescriptor,
private val packageView: PackageViewDescriptor
) {
val imports = file.importDirectives val imports = file.importDirectives
val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null } val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null }
val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace)
val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace) // TODO: should we count excludedImports here also?
val lazyImportingScope = object : ImportingScope by ImportingScope.Empty {
// avoid constructing the scope before we query it
override val parent: ImportingScope by storageManager.createLazyValue {
createImportingScope()
}
}
val lexicalScope = LexicalScope.Empty(lazyImportingScope, topLevelDescriptorProvider.getPackageFragment(file.packageFqName)!!)
val importResolver = object : ImportResolver {
override fun forceResolveAllImports() {
explicitImportResolver.forceResolveAllImports()
allUnderImportResolver.forceResolveAllImports()
}
override fun forceResolveImport(importDirective: KtImportDirective) {
if (importDirective.isAllUnder) {
allUnderImportResolver.forceResolveImport(importDirective)
}
else {
explicitImportResolver.forceResolveImport(importDirective)
}
}
}
val result = FileScopes(lexicalScope, lazyImportingScope, importResolver)
fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace, excludedImports: List<FqName>? = null) = fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace, excludedImports: List<FqName>? = null) =
LazyImportResolver( LazyImportResolver(
storageManager, qualifiedExpressionResolver, moduleDescriptor, platformToKotlinClassMap, languageVersionSettings, storageManager, qualifiedExpressionResolver, moduleDescriptor, platformToKotlinClassMap, languageVersionSettings,
indexedImports, aliasImportNames concat excludedImports, trace, packageFragment indexedImports, aliasImportNames concat excludedImports, trace, packageFragment
) )
val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace)
val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace) // TODO: should we count excludedImports here also?
val lazyImportingScope = object : ImportingScope by ImportingScope.Empty { fun createImportingScope(): LazyImportScope {
override val parent: ImportingScope by storageManager.createLazyValue {
val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve", false) val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve", false)
val extraImports = file.originalFile.virtualFile?.let { vFile -> val extraImports = file.originalFile.virtualFile?.let { vFile ->
@@ -131,31 +163,11 @@ class FileScopeFactory(
scope = currentPackageScope(packageView, aliasImportNames, dummyContainerDescriptor, FilteringKind.VISIBLE_CLASSES, scope) scope = currentPackageScope(packageView, aliasImportNames, dummyContainerDescriptor, FilteringKind.VISIBLE_CLASSES, scope)
LazyImportScope(scope, explicitImportResolver, LazyImportScope.FilteringKind.ALL, "Explicit imports in $debugName") return LazyImportScope(scope, explicitImportResolver, LazyImportScope.FilteringKind.ALL, "Explicit imports in $debugName")
}
} }
val lexicalScope = LexicalScope.Empty(lazyImportingScope, topLevelDescriptorProvider.getPackageFragment(file.packageFqName)!!) private infix fun <T> Collection<T>.concat(other: Collection<T>?) =
if (other == null || other.isEmpty()) this else this + other
val importResolver = object : ImportResolver {
override fun forceResolveAllImports() {
explicitImportResolver.forceResolveAllImports()
allUnderImportResolver.forceResolveAllImports()
}
override fun forceResolveImport(importDirective: KtImportDirective) {
if (importDirective.isAllUnder) {
allUnderImportResolver.forceResolveImport(importDirective)
}
else {
explicitImportResolver.forceResolveImport(importDirective)
}
}
}
return FileScopes(lexicalScope, lazyImportingScope, importResolver)
} }
private enum class FilteringKind { private enum class FilteringKind {