From 47f88eb1c118829398483d04ca7e9fd657240322 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Thu, 20 Aug 2015 02:11:06 +0300 Subject: [PATCH] Created LexicalChainedScope and LexicalScopeImpl --- .../resolve/scopes/LexicalChainedScope.kt | 63 +++++++++++++++ .../kotlin/resolve/scopes/LexicalScopeImpl.kt | 79 +++++++++++++++++++ .../kotlin/resolve/scopes/ChainedScope.kt | 41 +++------- .../{collectionUtils.kt => scopeUtils.kt} | 22 +++++- 4 files changed, 174 insertions(+), 31 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt rename core/descriptors/src/org/jetbrains/kotlin/util/{collectionUtils.kt => scopeUtils.kt} (63%) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt new file mode 100644 index 00000000000..5ff5b859865 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalChainedScope.kt @@ -0,0 +1,63 @@ +/* + * 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.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch +import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes +import org.jetbrains.kotlin.utils.Printer + +public class LexicalChainedScope( + override val parent: LexicalScope, + override val ownerDescriptor: DeclarationDescriptor, + override val isOwnerDescriptorAccessibleByLabel: Boolean, + override val implicitReceiver: ReceiverParameterDescriptor?, + private val debugName: String, + vararg memberScopes: JetScope // todo JetScope -> MemberScope +): LexicalScope { + private val scopeChain = memberScopes.clone() + + override fun getDeclaredDescriptors() = getFromAllScopes(scopeChain) { it.getAllDescriptors() } + + override fun getDeclaredClassifier(name: Name, location: LookupLocation) = getFirstMatch(scopeChain) { it.getClassifier(name, location) } + + override fun getDeclaredVariables(name: Name, location: LookupLocation) = getFromAllScopes(scopeChain) { it.getProperties(name, location) } + + override fun getDeclaredFunctions(name: Name, location: LookupLocation) = getFromAllScopes(scopeChain) { it.getFunctions(name, location) } + + override fun toString(): String = debugName + + override fun printStructure(p: Printer) { + p.println(javaClass.simpleName, ": ", debugName, "; for descriptor: ", ownerDescriptor.name, + " with implicitReceiver: ", implicitReceiver?.value, " {") + p.pushIndent() + + for (scope in scopeChain) { + scope.printScopeStructure(p) + } + + p.print("parent = ") + parent.printStructure(p.withholdIndentOnce()) + + p.popIndent() + p.println("}") + } + +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt new file mode 100644 index 00000000000..217c6c7e6d7 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/LexicalScopeImpl.kt @@ -0,0 +1,79 @@ +/* + * 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 com.intellij.util.SmartList +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.Printer + +public open class LexicalScopeImpl( + override val parent: LexicalScope, + override val ownerDescriptor: DeclarationDescriptor, + override val isOwnerDescriptorAccessibleByLabel: Boolean, + override val implicitReceiver: ReceiverParameterDescriptor?, + private val debugName: String, + initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {} +): LexicalScope, WritableScopeStorage { + override val addedDescriptors: MutableList = SmartList() + override val redeclarationHandler: RedeclarationHandler + get() = RedeclarationHandler.DO_NOTHING + + override var functionsByName: MutableMap? = null + override var variablesAndClassifiersByName: MutableMap? = null + + init { + InitializeHandler().initialize() + } + + override fun getDeclaredDescriptors(): Collection = addedDescriptors + + override fun getDeclaredClassifier(name: Name, location: LookupLocation) + = variableOrClassDescriptorByName(name) as? ClassifierDescriptor + + override fun getDeclaredVariables(name: Name, location: LookupLocation): Collection + = listOfNotNull(variableOrClassDescriptorByName(name) as? VariableDescriptor) + + override fun getDeclaredFunctions(name: Name, location: LookupLocation): Collection + = functionsByName(name) ?: emptyList() + + override fun toString(): String = debugName + + override fun printStructure(p: Printer) { + p.println(javaClass.simpleName, ": ", debugName, "; for descriptor: ", ownerDescriptor.name, + " with implicitReceiver: ", implicitReceiver?.value, " {") + p.pushIndent() + + p.print("parent = ") + parent.printStructure(p.withholdIndentOnce()) + + p.popIndent() + p.println("}") + } + + inner class InitializeHandler { + public fun addVariableDescriptor(variableDescriptor: VariableDescriptor): Unit + = this@LexicalScopeImpl.addVariableOrClassDescriptor(variableDescriptor) + + public fun addFunctionDescriptor(functionDescriptor: FunctionDescriptor): Unit + = this@LexicalScopeImpl.addFunctionDescriptor(functionDescriptor) + + public fun addClassifierDescriptor(classifierDescriptor: ClassifierDescriptor): Unit + = this@LexicalScopeImpl.addVariableOrClassDescriptor(classifierDescriptor) + } +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedScope.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedScope.kt index 169304642ca..7c87d7ed96a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedScope.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedScope.kt @@ -20,7 +20,8 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.util.collectionUtils.concat +import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch +import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes import org.jetbrains.kotlin.utils.Printer import java.util.ArrayList @@ -32,50 +33,32 @@ public open class ChainedScope( private val scopeChain = scopes.clone() private var implicitReceiverHierarchy: List? = null - private inline fun getFirstMatch(callback: (JetScope) -> T): T { - // NOTE: This is performance-sensitive; please don't replace with map().firstOrNull() - for (scope in scopeChain) { - val result = callback(scope) - if (result != null) return result - } - return null - } - - private inline fun getFromAllScopes(callback: (JetScope) -> Collection): Collection { - if (scopeChain.isEmpty()) return emptySet() - var result: Collection? = null - for (scope in scopeChain) { - result = result.concat(callback(scope)) - } - return result ?: emptySet() - } - override fun getClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? - = getFirstMatch { it.getClassifier(name, location) } + = getFirstMatch(scopeChain) { it.getClassifier(name, location) } override fun getPackage(name: Name): PackageViewDescriptor? - = getFirstMatch { it.getPackage(name) } + = getFirstMatch(scopeChain) { it.getPackage(name) } override fun getProperties(name: Name, location: LookupLocation): Collection - = getFromAllScopes { it.getProperties(name, location) } + = getFromAllScopes(scopeChain) { it.getProperties(name, location) } override fun getLocalVariable(name: Name): VariableDescriptor? - = getFirstMatch { it.getLocalVariable(name) } + = getFirstMatch(scopeChain) { it.getLocalVariable(name) } override fun getFunctions(name: Name, location: LookupLocation): Collection - = getFromAllScopes { it.getFunctions(name, location) } + = getFromAllScopes(scopeChain) { it.getFunctions(name, location) } override fun getSyntheticExtensionProperties(receiverTypes: Collection, name: Name, location: LookupLocation): Collection - = getFromAllScopes { it.getSyntheticExtensionProperties(receiverTypes, name, location) } + = getFromAllScopes(scopeChain) { it.getSyntheticExtensionProperties(receiverTypes, name, location) } override fun getSyntheticExtensionFunctions(receiverTypes: Collection, name: Name, location: LookupLocation): Collection - = getFromAllScopes { it.getSyntheticExtensionFunctions(receiverTypes, name, location) } + = getFromAllScopes(scopeChain) { it.getSyntheticExtensionFunctions(receiverTypes, name, location) } override fun getSyntheticExtensionProperties(receiverTypes: Collection): Collection - = getFromAllScopes { it.getSyntheticExtensionProperties(receiverTypes) } + = getFromAllScopes(scopeChain) { it.getSyntheticExtensionProperties(receiverTypes) } override fun getSyntheticExtensionFunctions(receiverTypes: Collection): Collection - = getFromAllScopes { it.getSyntheticExtensionFunctions(receiverTypes) } + = getFromAllScopes(scopeChain) { it.getSyntheticExtensionFunctions(receiverTypes) } override fun getImplicitReceiversHierarchy(): List { if (implicitReceiverHierarchy == null) { @@ -92,7 +75,7 @@ public open class ChainedScope( override fun getDeclarationsByLabel(labelName: Name) = scopeChain.flatMap { it.getDeclarationsByLabel(labelName) } override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) - = getFromAllScopes { it.getDescriptors(kindFilter, nameFilter) } + = getFromAllScopes(scopeChain) { it.getDescriptors(kindFilter, nameFilter) } override fun getOwnDeclaredDescriptors(): Collection { throw UnsupportedOperationException() diff --git a/core/descriptors/src/org/jetbrains/kotlin/util/collectionUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/util/scopeUtils.kt similarity index 63% rename from core/descriptors/src/org/jetbrains/kotlin/util/collectionUtils.kt rename to core/descriptors/src/org/jetbrains/kotlin/util/scopeUtils.kt index 41032c460f5..7b3d2354baa 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/util/collectionUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/util/scopeUtils.kt @@ -22,7 +22,7 @@ import java.util.* * Concatenates the contents of this collection with the given collection, avoiding allocations if possible. * Can modify `this` if it is a mutable collection. */ -fun Collection?.concat(collection: Collection): Collection? { +public fun Collection?.concat(collection: Collection): Collection? { if (collection.isEmpty()) { return this } @@ -39,7 +39,7 @@ fun Collection?.concat(collection: Collection): Collection? { return result } -fun concatInOrder(c1: Collection?, c2: Collection?): Collection { +public fun concatInOrder(c1: Collection?, c2: Collection?): Collection { val result = if (c1 == null || c1.isEmpty()) c2 else if (c2 == null || c2.isEmpty()) @@ -52,3 +52,21 @@ fun concatInOrder(c1: Collection?, c2: Collection?): Collection { } return result ?: emptySet() } + +public inline fun getFromAllScopes(scopes: Array, callback: (Scope) -> Collection): Collection { + if (scopes.isEmpty()) return emptySet() + var result: Collection? = null + for (scope in scopes) { + result = result.concat(callback(scope)) + } + return result ?: emptySet() +} + +public inline fun getFirstMatch(scopes: Array, callback: (Scope) -> T): T { + // NOTE: This is performance-sensitive; please don't replace with map().firstOrNull() + for (scope in scopes) { + val result = callback(scope) + if (result != null) return result + } + return null +} \ No newline at end of file