Refactoring FileScope into a chain of ImportingScope's (all compiler tests pass)

This commit is contained in:
Valentin Kipyatkov
2015-10-23 21:02:41 +03:00
parent 712e294eac
commit 9eeb051bd4
44 changed files with 266 additions and 258 deletions
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.asJetScope
import org.jetbrains.kotlin.resolve.scopes.utils.asKtScope
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
@@ -80,7 +80,7 @@ public fun BindingTrace.recordScope(scope: LexicalScope, element: KtElement?) {
// todo: remove it later
if (element is KtExpression) {
record(BindingContext.RESOLUTION_SCOPE, element, scopeToRecord.asJetScope())
record(BindingContext.RESOLUTION_SCOPE, element, scopeToRecord.asKtScope())
}
}
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
import org.jetbrains.kotlin.resolve.lazy.TopLevelDescriptorProvider
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.keysToMap
import java.util.HashSet
import java.util.*
public class DeclarationResolver(
private val annotationResolver: AnnotationResolver,
@@ -43,7 +43,7 @@ public class DeclarationResolver(
) {
public fun resolveAnnotationsOnFiles(c: TopDownAnalysisContext, scopeProvider: FileScopeProvider) {
val filesToScope = c.getFiles().keysToMap { scopeProvider.getFileScope(it) }
val filesToScope = c.getFiles().keysToMap { scopeProvider.getFileScopeChain(it) }
for ((file, fileScope) in filesToScope) {
annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getAnnotationEntries(), trace)
annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getDanglingAnnotations(), trace)
@@ -556,7 +556,7 @@ public class DescriptorResolver {
Name name = nameExpression.getReferencedNameAsName();
ClassifierDescriptor classifier = ScopeUtilsKt.asJetScope(scope).getClassifier(name, NoLookupLocation.UNSORTED);
ClassifierDescriptor classifier = ScopeUtilsKt.asKtScope(scope).getClassifier(name, NoLookupLocation.UNSORTED);
if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == descriptor) continue;
if (classifier != null) {
@@ -21,10 +21,7 @@ import com.google.common.collect.Multimap
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_OBJECT
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_INTERFACE
import org.jetbrains.kotlin.diagnostics.Errors.MANY_COMPANION_OBJECTS
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
@@ -33,7 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker
import java.util.ArrayList
import java.util.*
public class LazyTopDownAnalyzer(
private val trace: BindingTrace,
@@ -100,8 +97,8 @@ public class LazyTopDownAnalyzer(
}
override fun visitImportDirective(importDirective: KtImportDirective) {
val fileScope = fileScopeProvider.getFileScope(importDirective.getContainingJetFile())
fileScope.forceResolveImport(importDirective)
val importResolver = fileScopeProvider.getImportResolver(importDirective.getContainingJetFile())
importResolver.forceResolveImport(importDirective)
}
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.psi.KtScript;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.kotlin.resolve.lazy.LazyImportingScope;
import org.jetbrains.kotlin.resolve.lazy.ImportResolver;
import java.util.Arrays;
import java.util.Collection;
@@ -89,8 +89,8 @@ public class LazyTopDownAnalyzerForTopLevel {
}
private static void resolveAndCheckImports(@NotNull KtFile file, @NotNull KotlinCodeAnalyzer resolveSession) {
LazyImportingScope fileScope = resolveSession.getFileScopeProvider().getFileScope(file);
fileScope.forceResolveAllImports();
ImportResolver importResolver = resolveSession.getFileScopeProvider().getImportResolver(file);
importResolver.forceResolveAllImports();
}
}
@@ -43,7 +43,7 @@ import org.jetbrains.kotlin.resolve.calls.util.CallMaker
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsFileScope
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.FunctionPlaceholders
import org.jetbrains.kotlin.types.KotlinType
@@ -102,7 +102,7 @@ public fun resolvePossiblyAmbiguousCallableReference(
fun resolveInScope(traceTitle: String, staticScope: KtScope): OverloadResolutionResults<CallableDescriptor> {
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache).replaceScope(staticScope.memberScopeAsFileScope())
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache).replaceScope(staticScope.memberScopeAsImportingScope())
val results = resolvePossiblyAmbiguousCallableReference(reference, ReceiverValue.NO_RECEIVER, newContext, resolutionMode, callResolver)
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
return results
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.LibrarySourceHacks
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.kotlin.resolve.scopes.LexicalChainedScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
@@ -93,7 +94,7 @@ private object FunctionCollector : CallableDescriptorCollector<FunctionDescripto
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
return lexicalScope.collectAllFromMeAndParent {
if (it.ownerDescriptor is FunctionDescriptor) {
if (it !is ImportingScope && it.ownerDescriptor is FunctionDescriptor) {
it.getDeclaredFunctions(name, location).filter { it.extensionReceiverParameter == null } +
getConstructors(it.getDeclaredClassifier(name, location))
}
@@ -44,9 +44,9 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER
import org.jetbrains.kotlin.resolve.scopes.utils.asJetScope
import org.jetbrains.kotlin.resolve.scopes.utils.asKtScope
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsFileScope
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.resolve.validation.InfixValidator
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.ErrorUtils
@@ -74,7 +74,7 @@ public class TaskPrioritizer(
if (explicitReceiver is QualifierReceiver) {
val qualifierReceiver: QualifierReceiver = explicitReceiver
val receiverScope = qualifierReceiver.getNestedClassesAndPackageMembersScope().memberScopeAsFileScope()
val receiverScope = qualifierReceiver.getNestedClassesAndPackageMembersScope().memberScopeAsImportingScope()
doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(receiverScope))
computeTasksForClassObjectReceiver(qualifierReceiver, taskPrioritizerContext)
}
@@ -205,7 +205,7 @@ public class TaskPrioritizer(
//extensions
c.result.addCandidates {
val extensions = callableDescriptorCollector.getExtensionsByName(
c.scope.asJetScope(), c.name, explicitReceiver.types, createLookupLocation(c))
c.scope.asKtScope(), c.name, explicitReceiver.types, createLookupLocation(c))
val filteredExtensions = if (filter == null) extensions else extensions.filter(filter)
convertWithImpliedThis(
@@ -326,7 +326,7 @@ public class TaskPrioritizer(
//nonlocals
c.callableDescriptorCollectors.forEach {
c.result.addCandidates {
val descriptors = it.getNonExtensionsByName(c.scope.asJetScope(), c.name, lookupLocation)
val descriptors = it.getNonExtensionsByName(c.scope.asKtScope(), c.name, lookupLocation)
.filter { !ExpressionTypingUtils.isLocal(c.scope.ownerDescriptor, it) }
convertWithImpliedThisAndNoReceiver(c.scope, descriptors, c.context.call)
}
@@ -55,7 +55,7 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
}
if (parentDeclaration == null) {
return fileScopeProvider.getFileScope((KtFile) elementOfDeclaration.getContainingFile());
return fileScopeProvider.getFileScopeChain((KtFile) elementOfDeclaration.getContainingFile());
}
if (parentDeclaration instanceof KtClassOrObject) {
@@ -17,15 +17,16 @@
package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.KtScope
public interface FileScopeProvider {
fun getFileScope(file: KtFile): LazyImportingScope
fun getFileScopeChain(file: KtFile): ImportingScope
fun getImportResolver(file: KtFile): ImportResolver
public object ThrowException : FileScopeProvider {
override fun getFileScope(file: KtFile): LazyImportingScope {
throw UnsupportedOperationException("Should not be called")
}
override fun getFileScopeChain(file: KtFile) = throw UnsupportedOperationException("Should not be called")
override fun getImportResolver(file: KtFile) = throw UnsupportedOperationException("Should not be called")
}
public interface AdditionalScopes {
@@ -33,3 +34,4 @@ public interface FileScopeProvider {
}
}
@@ -19,19 +19,20 @@ package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtImportsFactory
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtImportsFactory
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.NoSubpackagesInPackageScope
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.sure
import java.util.*
public class FileScopeProviderImpl(
private val topLevelDescriptorProvider: TopLevelDescriptorProvider,
@@ -47,11 +48,15 @@ public class FileScopeProviderImpl(
ktImportsFactory.createImportDirectives(moduleDescriptor.defaultImports)
}
private val fileScopes = storageManager.createMemoizedFunction { file: KtFile -> createFileScope(file) }
private data class FileData(val scopeChain: ImportingScope, val importResolver: ImportResolver)
override fun getFileScope(file: KtFile) = fileScopes(file)
private val cache = storageManager.createMemoizedFunction { file: KtFile -> createScopeChainAndImportResolver(file) }
private fun createFileScope(file: KtFile): LazyImportingScope {
override fun getFileScopeChain(file: KtFile) = cache(file).scopeChain
override fun getImportResolver(file: KtFile) = cache(file).importResolver
private fun createScopeChainAndImportResolver(file: KtFile): FileData {
val debugName = "LazyFileScope for file " + file.getName()
val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve")
@@ -72,25 +77,51 @@ public class FileScopeProviderImpl(
val defaultAliasImportResolver = createImportResolver(AliasImportsIndexed(defaultImports), tempTrace)
val defaultAllUnderImportResolver = createImportResolver(AllUnderImportsIndexed(defaultImports), tempTrace)
val scopeChain = ArrayList<KtScope>()
var scope: ImportingScope
scopeChain.add(LazyImportScope(packageFragment, aliasImportResolver, LazyImportScope.FilteringKind.ALL, "Alias imports in $debugName"))
scope = LazyImportScope(null, packageFragment, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
"Default all under imports in $debugName (invisible classes only)")
scopeChain.add(NoSubpackagesInPackageScope(packageView)) //TODO: problems with visibility too
scopeChain.add(SubpackagesScope(moduleDescriptor, FqName.ROOT))
scope = LazyImportScope(scope, packageFragment, allUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
"All under imports in $debugName (invisible classes only)")
scopeChain.add(LazyImportScope(packageFragment, defaultAliasImportResolver, LazyImportScope.FilteringKind.ALL, "Default alias imports in $debugName"))
for (additionalScope in additionalScopes.flatMap { it.scopes }) {
scope = additionalScope.memberScopeAsImportingScope(scope)
}
scopeChain.add(LazyImportScope(packageFragment, allUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES, "All under imports in $debugName (visible classes)"))
scopeChain.add(LazyImportScope(packageFragment, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES, "Default all under imports in $debugName (visible classes)"))
scope = LazyImportScope(scope, packageFragment, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
"Default all under imports in $debugName (visible classes)")
scopeChain.addAll(additionalScopes.flatMap { it.scopes })
scope = LazyImportScope(scope, packageFragment, allUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
"All under imports in $debugName (visible classes)")
scopeChain.add(LazyImportScope(packageFragment, allUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES, "All under imports in $debugName (invisible classes only)"))
scopeChain.add(LazyImportScope(packageFragment, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES, "Default all under imports in $debugName (invisible classes only)"))
scope = LazyImportScope(scope, packageFragment, defaultAliasImportResolver, LazyImportScope.FilteringKind.ALL,
"Default alias imports in $debugName")
val lazyFileScope = LazyImportingScope(scopeChain, aliasImportResolver, allUnderImportResolver, packageFragment, debugName)
bindingTrace.recordScope(lazyFileScope, file)
return lazyFileScope
scope = SubpackagesScope(moduleDescriptor, FqName.ROOT).memberScopeAsImportingScope(scope)
scope = NoSubpackagesInPackageScope(packageView).memberScopeAsImportingScope(scope) //TODO: problems with visibility too
scope = LazyImportScope(scope, packageFragment, aliasImportResolver, LazyImportScope.FilteringKind.ALL, "Alias imports in $debugName")
bindingTrace.recordScope(scope, file)
val importResolver = object : ImportResolver {
override fun forceResolveAllImports() {
aliasImportResolver.forceResolveAllImports()
allUnderImportResolver.forceResolveAllImports()
}
override fun forceResolveImport(importDirective: KtImportDirective) {
if (importDirective.isAllUnder) {
allUnderImportResolver.forceResolveImport(importDirective)
}
else {
aliasImportResolver.forceResolveImport(importDirective)
}
}
}
return FileData(scope, importResolver)
}
}
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.PlatformTypesMappedToKotlinChecker
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.storage.StorageManager
@@ -66,6 +67,11 @@ class AliasImportsIndexed(allImports: Collection<KtImportDirective>) : IndexedIm
override fun importsForName(name: Name) = nameToDirectives.get(name)
}
interface ImportResolver {
fun forceResolveAllImports()
fun forceResolveImport(importDirective: KtImportDirective)
}
class LazyImportResolver(
val storageManager: StorageManager,
val qualifiedExpressionResolver: QualifiedExpressionResolver,
@@ -73,7 +79,7 @@ class LazyImportResolver(
val indexedImports: IndexedImports,
private val traceForImportResolve: BindingTrace,
private val packageFragment: PackageFragmentDescriptor
) {
) : ImportResolver {
private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues {
directive: KtImportDirective ->
val directiveImportScope = qualifiedExpressionResolver.processImportReference(
@@ -87,10 +93,10 @@ class LazyImportResolver(
directiveImportScope
}
public fun forceResolveAllContents() {
override fun forceResolveAllImports() {
val explicitClassImports = HashMultimap.create<String, KtImportDirective>()
for (importDirective in indexedImports.imports) {
forceResolveImportDirective(importDirective)
forceResolveImport(importDirective)
val scope = importedScopesProvider(importDirective)
val alias = KtPsiUtil.getAliasName(importDirective)?.identifier
@@ -115,7 +121,7 @@ class LazyImportResolver(
}
}
public fun forceResolveImportDirective(importDirective: KtImportDirective) {
override fun forceResolveImport(importDirective: KtImportDirective) {
getImportScope(importDirective)
}
@@ -158,11 +164,12 @@ class LazyImportResolver(
}
class LazyImportScope(
private val containingDeclaration: DeclarationDescriptor,
override val parent: ImportingScope?,
override val ownerDescriptor: DeclarationDescriptor,
private val importResolver: LazyImportResolver,
private val filteringKind: LazyImportScope.FilteringKind,
private val debugName: String
) : KtScope {
) : ImportingScope {
enum class FilteringKind {
ALL,
@@ -178,7 +185,7 @@ class LazyImportScope(
return Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, importResolver.moduleDescriptor) == includeVisible
}
override fun getClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
override fun getDeclaredClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
return importResolver.selectSingleFromImports(name) { scope, name ->
val descriptor = scope.getClassifier(name, location)
if (descriptor != null && isClassVisible(descriptor as ClassDescriptor/*no type parameter can be imported*/)) descriptor else null
@@ -190,14 +197,12 @@ class LazyImportScope(
return importResolver.selectSingleFromImports(name) { scope, name -> scope.getPackage(name) }
}
override fun getProperties(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
override fun getDeclaredVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
if (filteringKind == FilteringKind.INVISIBLE_CLASSES) return listOf()
return importResolver.collectFromImports(name) { scope, name -> scope.getProperties(name, location) }
}
override fun getLocalVariable(name: Name) = null
override fun getFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
override fun getDeclaredFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
if (filteringKind == FilteringKind.INVISIBLE_CLASSES) return listOf()
return importResolver.collectFromImports(name) { scope, name -> scope.getFunctions(name, location) }
}
@@ -234,8 +239,6 @@ class LazyImportScope(
}
}
override fun getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = listOf()
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
// we do not perform any filtering by visibility here because all descriptors from both visible/invisible filter scopes are to be added anyway
if (filteringKind == FilteringKind.INVISIBLE_CLASSES) return listOf()
@@ -253,19 +256,13 @@ class LazyImportScope(
}
}
override fun getImplicitReceiversHierarchy() = listOf<ReceiverParameterDescriptor>()
override fun getOwnDeclaredDescriptors() = listOf<DeclarationDescriptor>()
override fun getContainingDeclaration() = containingDeclaration
override fun toString() = "LazyImportScope: " + debugName
override fun printScopeStructure(p: Printer) {
override fun printStructure(p: Printer) {
p.println(javaClass.getSimpleName(), ": ", debugName, " {")
p.pushIndent()
p.println("containingDeclaration = ", containingDeclaration)
p.println("ownerDescriptor = ", ownerDescriptor)
p.popIndent()
p.println("}")
@@ -1,65 +0,0 @@
/*
* Copyright 2010-2015 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.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.kotlin.utils.Printer
class LazyImportingScope(
scopeChain: List<KtScope>,
private val aliasImportResolver: LazyImportResolver,
private val allUnderImportResolver: LazyImportResolver,
containingDeclaration: PackageFragmentDescriptor,
debugName: String
) : ChainedScope(containingDeclaration, debugName, *scopeChain.toTypedArray()), ImportingScope {
override val parent: ImportingScope?
get() = null
override fun getDeclaredDescriptors() = emptyList<DeclarationDescriptor>()
override fun printStructure(p: Printer) = printScopeStructure(p)
override val ownerDescriptor: DeclarationDescriptor
get() = getContainingDeclaration()
override fun getDeclaredClassifier(name: Name, location: LookupLocation) = getClassifier(name, location)
override fun getDeclaredVariables(name: Name, location: LookupLocation) = getProperties(name, location)
override fun getDeclaredFunctions(name: Name, location: LookupLocation) = getFunctions(name, location)
public fun forceResolveAllImports() {
aliasImportResolver.forceResolveAllContents()
allUnderImportResolver.forceResolveAllContents()
}
public fun forceResolveImport(importDirective: KtImportDirective) {
if (importDirective.isAllUnder()) {
allUnderImportResolver.forceResolveImportDirective(importDirective)
}
else {
aliasImportResolver.forceResolveImportDirective(importDirective)
}
}
}
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.kotlin.resolve.scopes.ImportingScope;
import org.jetbrains.kotlin.resolve.scopes.KtScope;
import org.jetbrains.kotlin.storage.*;
@@ -207,7 +208,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
}
private LazyAnnotations createAnnotations(KtFile file, List<KtAnnotationEntry> annotationEntries) {
LazyImportingScope scope = fileScopeProvider.getFileScope(file);
ImportingScope scope = fileScopeProvider.getFileScopeChain(file);
LazyAnnotationsContextImpl lazyAnnotationContext =
new LazyAnnotationsContextImpl(annotationResolve, storageManager, trace, scope);
return new LazyAnnotations(lazyAnnotationContext, annotationEntries);
@@ -37,7 +37,7 @@ public class LazyPackageMemberScope(
override fun getPackage(name: Name): PackageViewDescriptor? = null
override fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration)
= resolveSession.getFileScopeProvider().getFileScope(declaration.getContainingJetFile())
= resolveSession.getFileScopeProvider().getFileScopeChain(declaration.getContainingJetFile())
override fun getNonDeclaredFunctions(name: Name, result: MutableSet<FunctionDescriptor>) {
// No extra functions
@@ -95,7 +95,7 @@ public class LazyScriptDescriptor(
override fun getScriptCodeDescriptor() = scriptCodeDescriptor()
override fun getScopeForBodyResolution(): LexicalScope {
return LexicalScopeImpl(resolveSession.fileScopeProvider.getFileScope(jetScript.getContainingJetFile()),
return LexicalScopeImpl(resolveSession.fileScopeProvider.getFileScopeChain(jetScript.getContainingJetFile()),
this, false, implicitReceiver, "Scope for body resolution for " + this) {
for (valueParameterDescriptor in getScriptCodeDescriptor().valueParameters) {
addVariableDescriptor(valueParameterDescriptor)
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
import org.jetbrains.kotlin.resolve.scopes.FilteringScope
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.kotlin.resolve.scopes.utils.asJetScope
import org.jetbrains.kotlin.resolve.scopes.utils.asKtScope
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
@@ -128,7 +128,7 @@ fun createQualifier(
context: ExpressionTypingContext
): QualifierReceiver? {
val receiverScope = when {
!receiver.exists() -> context.scope.asJetScope()
!receiver.exists() -> context.scope.asKtScope()
receiver is QualifierReceiver -> receiver.scope
else -> receiver.getType().getMemberScope()
}
@@ -21,13 +21,13 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.lazy.LazyImportingScope
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.collectionUtils.concat
import org.jetbrains.kotlin.utils.Printer
public fun LexicalScope.getFileScope(): ImportingScope {
@Deprecated("We probably don't need it at all")
public fun LexicalScope.getImportingScopeChain(): ImportingScope {
var currentScope = this
while(currentScope.parent != null) {
currentScope = currentScope.parent!!
@@ -77,13 +77,8 @@ public fun LexicalScope.getDescriptorsFiltered(
nameFilter: (Name) -> Boolean = { true }
): Collection<DeclarationDescriptor> {
if (kindFilter.kindMask == 0) return listOf()
return collectAllFromMeAndParent {
if (it is ImportingScope) {
it.getDescriptors(kindFilter, nameFilter)
} else {
it.getDeclaredDescriptors()
}
}.filter { kindFilter.accepts(it) && nameFilter(it.name) }
return collectAllFromMeAndParent { it.getDescriptors(kindFilter, nameFilter) }
.filter { kindFilter.accepts(it) && nameFilter(it.name) }
}
@@ -91,13 +86,10 @@ public fun LexicalScope.getDescriptorsFiltered(
public fun LexicalScope.getLocalVariable(name: Name): VariableDescriptor? {
processForMeAndParent {
if (it is LexicalScopeWrapper) {
return it.delegate.getLocalVariable(name)
}
else if (it is LazyImportingScope) {
return it.getLocalVariable(name) // todo: remove hack for repl interpreter
it.delegate.getLocalVariable(name)?.let { return it }
}
else if (it is MemberScopeToImportingScopeAdapter) { // todo remove hack
return it.memberScope.getLocalVariable(name)
it.memberScope.getLocalVariable(name)?.let { return it }
}
else if (it !is ImportingScope && it !is LexicalChainedScope) { // todo check this
it.getDeclaredVariables(name, NoLookupLocation.UNSORTED).singleOrNull()?.let { return it }
@@ -115,76 +107,86 @@ public fun LexicalScope.getClassifier(name: Name, location: LookupLocation): Cla
public fun LexicalScope.takeSnapshot(): LexicalScope = if (this is LexicalWritableScope) takeSnapshot() else this
public fun LexicalScope.asJetScope(): KtScope {
public fun LexicalScope.asKtScope(): KtScope {
if (this is KtScope) return this
if (this is MemberScopeToImportingScopeAdapter) return this.memberScope
return LexicalToJetScopeAdapter(this)
return LexicalToKtScopeAdapter(this)
}
public fun KtScope.memberScopeAsFileScope(): ImportingScope = MemberScopeToImportingScopeAdapter(this)
@JvmOverloads
public fun KtScope.memberScopeAsImportingScope(parentScope: ImportingScope? = null): ImportingScope = MemberScopeToImportingScopeAdapter(parentScope, this)
@Deprecated("Remove this method after scope refactoring")
public fun KtScope.asLexicalScope(): LexicalScope
= if (this is LexicalToJetScopeAdapter) {
= if (this is LexicalToKtScopeAdapter) {
lexicalScope
}
else {
memberScopeAsFileScope()
memberScopeAsImportingScope()
}
private class LexicalToJetScopeAdapter(lexicalScope: LexicalScope): KtScope {
private class LexicalToKtScopeAdapter(lexicalScope: LexicalScope): KtScope {
val lexicalScope = lexicalScope.takeSnapshot()
override fun getClassifier(name: Name, location: LookupLocation) = lexicalScope.getClassifier(name, location)
override fun getPackage(name: Name) = lexicalScope.getFileScope().getPackage(name)
override fun getPackage(name: Name): PackageViewDescriptor? {
lexicalScope.processForMeAndParent {
(it as? ImportingScope)?.getPackage(name)?.let { return it }
}
return null
}
override fun getProperties(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
val fileScope = lexicalScope.getFileScope()
if (fileScope is MemberScopeToImportingScopeAdapter) {
return fileScope.memberScope.getProperties(name, location)
}
else {
return fileScope.getDeclaredVariables(name, location)
}
return lexicalScope.collectAllFromMeAndParent { (it as? ImportingScope)?.getDeclaredVariables(name, location) ?: emptyList() }
}
override fun getFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
return lexicalScope.collectAllFromMeAndParent { it.getDeclaredFunctions(name, location) }
}
override fun getLocalVariable(name: Name) = lexicalScope.getLocalVariable(name)
override fun getFunctions(name: Name, location: LookupLocation) = lexicalScope.collectAllFromMeAndParent {
it.getDeclaredFunctions(name, location)
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
return lexicalScope.collectAllFromMeAndParent {
(it as? ImportingScope)?.getSyntheticExtensionProperties(receiverTypes, name, location) ?: emptyList()
}
}
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation)
= lexicalScope.getFileScope().getSyntheticExtensionProperties(receiverTypes, name, location)
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
return lexicalScope.collectAllFromMeAndParent {
(it as? ImportingScope)?.getSyntheticExtensionFunctions(receiverTypes, name, location) ?: emptyList()
}
}
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation)
= lexicalScope.getFileScope().getSyntheticExtensionFunctions(receiverTypes, name, location)
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> {
return lexicalScope.collectAllFromMeAndParent {
(it as? ImportingScope)?.getSyntheticExtensionProperties(receiverTypes) ?: emptyList()
}
}
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>)
= lexicalScope.getFileScope().getSyntheticExtensionProperties(receiverTypes)
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>)
= lexicalScope.getFileScope().getSyntheticExtensionFunctions(receiverTypes)
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
return lexicalScope.collectAllFromMeAndParent {
(it as? ImportingScope)?.getSyntheticExtensionFunctions(receiverTypes) ?: emptyList()
}
}
override fun getContainingDeclaration() = lexicalScope.ownerDescriptor
override fun getDeclarationsByLabel(labelName: Name) = lexicalScope.getDeclarationsByLabel(labelName)
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = lexicalScope.collectAllFromMeAndParent {
if (it is ImportingScope) {
it.getDescriptors(kindFilter, nameFilter)
} else it.getDeclaredDescriptors()
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
return lexicalScope.collectAllFromMeAndParent { it.getDescriptors(kindFilter, nameFilter) }
}
override fun getImplicitReceiversHierarchy() = lexicalScope.getImplicitReceiversHierarchy()
override fun getOwnDeclaredDescriptors() = lexicalScope.getDeclaredDescriptors()
override fun equals(other: Any?) = other is LexicalToJetScopeAdapter && other.lexicalScope == this.lexicalScope
override fun equals(other: Any?) = other is LexicalToKtScopeAdapter && other.lexicalScope == this.lexicalScope
override fun hashCode() = lexicalScope.hashCode()
override fun toString() = "LexicalToJetScopeAdapter for $lexicalScope"
override fun toString() = "LexicalToKtScopeAdapter for $lexicalScope"
override fun printScopeStructure(p: Printer) {
p.println(javaClass.simpleName)
@@ -197,10 +199,7 @@ private class LexicalToJetScopeAdapter(lexicalScope: LexicalScope): KtScope {
}
}
private class MemberScopeToImportingScopeAdapter(val memberScope: KtScope) : ImportingScope {
override val parent: ImportingScope?
get() = null
private class MemberScopeToImportingScopeAdapter(override val parent: ImportingScope?, val memberScope: KtScope) : ImportingScope {
override fun getPackage(name: Name): PackageViewDescriptor? = memberScope.getPackage(name)
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation)
@@ -233,7 +232,7 @@ private class MemberScopeToImportingScopeAdapter(val memberScope: KtScope) : Imp
override fun hashCode() = memberScope.hashCode()
override fun toString() = "MemberScopeToFileScopeAdapter for $memberScope"
override fun toString() = "${javaClass.simpleName} for $memberScope"
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName)
@@ -281,19 +280,20 @@ internal inline fun <T: Any> LexicalScope.collectAllFromMeAndParent(
}
public fun LexicalScope.addImportScope(importScope: KtScope): LexicalScope {
val fileScope = getFileScope()
val fileScope = getImportingScopeChain()
val scopeWithAdditionImport =
LexicalChainedScope(fileScope, fileScope.ownerDescriptor, false, null, "Scope with addition import", importScope)
return replaceFileScope(scopeWithAdditionImport)
}
//TODO!!!
public fun LexicalScope.replaceFileScope(fileScopeReplace: LexicalScope): LexicalScope {
if (this is ImportingScope) return fileScopeReplace
return LexicalScopeWrapper(this, fileScopeReplace)
}
public fun LexicalScope.withNoFileScope(): LexicalScope = replaceFileScope(MemberScopeToImportingScopeAdapter(KtScope.Empty))
public fun LexicalScope.withNoFileScope(): LexicalScope = replaceFileScope(MemberScopeToImportingScopeAdapter(null, KtScope.Empty))
private class LexicalScopeWrapper(val delegate: LexicalScope, val fileScopeReplace: LexicalScope): LexicalScope by delegate {
override val parent: LexicalScope? by lazy(LazyThreadSafetyMode.NONE) {
@@ -185,7 +185,7 @@ public class ExpressionTypingServices {
scope.changeLockLevel(WritableScope.LockLevel.READING);
if (containingDescriptor instanceof ScriptDescriptor) {
context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, ScopeUtilsKt.asJetScope(scope));
context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, ScopeUtilsKt.asKtScope(scope));
}
return r;