diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyFileScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyFileScope.kt index 74bf6bd9ac6..e48716f870d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyFileScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyFileScope.kt @@ -16,21 +16,15 @@ package org.jetbrains.kotlin.resolve.lazy -import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.JetCodeFragment -import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.JetImportDirective -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.NoSubpackagesInPackageScope -import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver import org.jetbrains.kotlin.resolve.scopes.ChainedScope +import org.jetbrains.kotlin.resolve.scopes.FileScope import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.storage.StorageManager -import org.jetbrains.kotlin.utils.sure -import java.util.ArrayList +import org.jetbrains.kotlin.utils.Printer class LazyFileScope( scopeChain: List, @@ -38,7 +32,19 @@ class LazyFileScope( private val allUnderImportResolver: LazyImportResolver, containingDeclaration: PackageFragmentDescriptor, debugName: String -) : ChainedScope(containingDeclaration, debugName, *scopeChain.toTypedArray()) { +) : ChainedScope(containingDeclaration, debugName, *scopeChain.toTypedArray()), FileScope { + override fun getDeclaredDescriptors() = emptyList() + + 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() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt new file mode 100644 index 00000000000..cf6b6ecb424 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt @@ -0,0 +1,155 @@ +/* + * 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.scopes.utils + +import com.intellij.util.SmartList +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor +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.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.FileScope +import org.jetbrains.kotlin.resolve.scopes.JetScope +import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.util.collectionUtils.concat +import org.jetbrains.kotlin.utils.Printer + +public fun LexicalScope.getFileScope(): FileScope { + var currentScope = this + while(currentScope.parent != null) { + currentScope = currentScope.parent!! + } + assert(currentScope is FileScope) { + "Not FileScope without parent: $currentScope" // todo improve debug message + } + return currentScope as FileScope +} + +/** + * Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first + */ +public fun LexicalScope.getImplicitReceiversHierarchy(): List = collectFromMeAndParent { it.implicitReceiver } + +public fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection = collectFromMeAndParent { + if (it.isOwnerDescriptorAccessibleByLabel && it.ownerDescriptor.name == labelName) { + it.ownerDescriptor + } else { + null + } +} + +@deprecated("Use getOwnProperties instead") +public fun LexicalScope.getLocalVariable(name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): VariableDescriptor? { + processForMeAndParent { + if (it !is FileScope) { // todo check this + it.getDeclaredVariables(name, location).singleOrNull()?.let { return it } + } + } + return null +} + +public fun LexicalScope.getClassifier(name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): ClassifierDescriptor? { + processForMeAndParent { + it.getDeclaredClassifier(name, location)?.let { return it } + } + return null +} + +public fun LexicalScope.asJetScope(): JetScope = LexicalToJetScopeAdapter(this) + +private class LexicalToJetScopeAdapter(val lexicalScope: LexicalScope): JetScope { + + override fun getClassifier(name: Name, location: LookupLocation) = lexicalScope.getClassifier(name, location) + + override fun getPackage(name: Name) = lexicalScope.getFileScope().getPackage(name) + + override fun getProperties(name: Name, location: LookupLocation) = lexicalScope.collectAllFromMeAndParent { + it.getDeclaredVariables(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, name: Name, location: LookupLocation) + = lexicalScope.getFileScope().getSyntheticExtensionProperties(receiverTypes, name, location) + + override fun getSyntheticExtensionFunctions(receiverTypes: Collection, name: Name, location: LookupLocation) + = lexicalScope.getFileScope().getSyntheticExtensionFunctions(receiverTypes, name, location) + + override fun getSyntheticExtensionProperties(receiverTypes: Collection) + = lexicalScope.getFileScope().getSyntheticExtensionProperties(receiverTypes) + + override fun getSyntheticExtensionFunctions(receiverTypes: Collection) + = lexicalScope.getFileScope().getSyntheticExtensionFunctions(receiverTypes) + + 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 FileScope) { + it.getDescriptors(kindFilter, nameFilter) + } else it.getDeclaredDescriptors() + } + + override fun getImplicitReceiversHierarchy() = lexicalScope.getImplicitReceiversHierarchy() + override fun printScopeStructure(p: Printer) = lexicalScope.printStructure(p) + override fun getOwnDeclaredDescriptors() = lexicalScope.getDeclaredDescriptors() +} + +private inline fun LexicalScope.processForMeAndParent(process: (LexicalScope) -> Unit) { + var currentScope = this + process(currentScope) + + while(currentScope.parent != null) { + currentScope = currentScope.parent!! + process(currentScope) + } +} + +private inline fun LexicalScope.collectFromMeAndParent( + collect: (LexicalScope) -> T? +): List { + var result: MutableList? = null + processForMeAndParent { + val element = collect(it) + if (element != null) { + if (result == null) { + result = SmartList() + return emptyList() + } + result!!.add(element) + } + } + return result ?: emptyList() +} + +private inline fun LexicalScope.collectAllFromMeAndParent( + collect: (LexicalScope) -> Collection +): Collection { + var result: Collection? = null + processForMeAndParent { result = result.concat(collect(it)) } + return result ?: emptySet() +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt new file mode 100644 index 00000000000..5f76c567dac --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt @@ -0,0 +1,71 @@ +/* + * 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.scopes + +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.types.JetType +import org.jetbrains.kotlin.utils.Printer + +// see ScopeUtils.kt in the frontend module + +public interface LexicalScope { + public val parent: LexicalScope? + + public val ownerDescriptor: DeclarationDescriptor + public val isOwnerDescriptorAccessibleByLabel: Boolean + + public val implicitReceiver: ReceiverParameterDescriptor? + + public fun getDeclaredDescriptors(): Collection + + public fun getDeclaredClassifier(name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): ClassifierDescriptor? + + // need collection here because there may be extension property foo and usual property foo + public fun getDeclaredVariables(name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): Collection + public fun getDeclaredFunctions(name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): Collection + + public fun printStructure(p: Printer) +} + +public interface FileScope: LexicalScope { + override val parent: LexicalScope? + get() = null + + override val isOwnerDescriptorAccessibleByLabel: Boolean + get() = false + + override val implicitReceiver: ReceiverParameterDescriptor? + get() = null + + // methods getDeclaredSmth for this scope will be delegated to importScope + + fun getPackage(name: Name): PackageViewDescriptor? + + public fun getSyntheticExtensionProperties(receiverTypes: Collection, name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): Collection + public fun getSyntheticExtensionFunctions(receiverTypes: Collection, name: Name, location: LookupLocation = NoLookupLocation.UNSORTED): Collection + + public fun getSyntheticExtensionProperties(receiverTypes: Collection): Collection + public fun getSyntheticExtensionFunctions(receiverTypes: Collection): Collection + + public fun getDescriptors( + kindFilter: DescriptorKindFilter = DescriptorKindFilter.ALL, + nameFilter: (Name) -> Boolean = JetScope.ALL_NAME_FILTER + ): Collection +}