Move sources to resolution module

This commit is contained in:
Stanislav Erokhin
2016-02-25 17:56:08 +03:00
parent 5bb1f3b2ea
commit 7a43d62408
26 changed files with 127 additions and 105 deletions
@@ -1,100 +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.calls.smartcasts
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
/**
* This class describes an arbitrary object which has some value in data flow analysis.
* In general case it's some r-value.
*/
class DataFlowValue(val id: Any?, val type: KotlinType, val kind: DataFlowValue.Kind, val immanentNullability: Nullability) {
enum class Kind(private val str: String, val description: String = str) {
// Local value, or parameter, or private / internal member value without open / custom getter,
// or protected / public member value from the same module without open / custom getter
// Smart casts are completely safe
STABLE_VALUE("stable"),
// Block, or if / else, or when, or (in future) some other complex expression
STABLE_COMPLEX_EXPRESSION("complex expression", ""),
// Member value with open / custom getter
// Smart casts are not safe
PROPERTY_WITH_GETTER("custom getter", "property that has open or custom getter"),
// Protected / public member value from another module
// Smart casts are not safe
ALIEN_PUBLIC_PROPERTY("alien public", "public API property declared in different module"),
// Local variable not yet captured by a changing closure
// Smart casts are safe but possible changes in loops / closures ahead must be taken into account
PREDICTABLE_VARIABLE("predictable", "local variable that can be changed since the check in a loop"),
// Local variable already captured by a changing closure
// Smart casts are not safe
UNPREDICTABLE_VARIABLE("unpredictable", "local variable that is captured by a changing closure"),
// Member variable regardless of its visibility
// Smart casts are not safe
MUTABLE_PROPERTY("member", "mutable property that could have been changed by this time"),
// Some complex expression
// Smart casts are not safe
OTHER("other", "complex expression");
override fun toString() = str
fun isStable() = this == STABLE_VALUE
}
/**
* Both stable values and predictable local variables are considered "predictable".
* Predictable means here we do not expect some sudden change of their values,
* like accessing mutable properties in another thread, so smart casts can be used safely.
*/
val isPredictable = (kind == Kind.STABLE_VALUE || kind == Kind.STABLE_COMPLEX_EXPRESSION || kind == Kind.PREDICTABLE_VARIABLE)
@JvmName("isPredictable") get
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is DataFlowValue) return false
if (kind.isStable() != other.kind.isStable()) return false
if (id != other.id) return false
if (type != other.type) return false
return true
}
override fun toString(): String {
return kind.toString() + " " + id?.toString() + " " + immanentNullability
}
override fun hashCode(): Int {
var result = if (kind.isStable()) 1 else 0
result = 31 * result + type.hashCode()
result = 31 * result + (id?.hashCode() ?: 0)
return result
}
companion object {
@JvmStatic
fun nullValue(builtIns: KotlinBuiltIns) = DataFlowValue(
Object(), builtIns.nullableNothingType, Kind.OTHER, Nullability.NULL
)
@JvmField
val ERROR = DataFlowValue(Object(), ErrorUtils.createErrorType("Error type for data flow"), Kind.OTHER, Nullability.IMPOSSIBLE)
}
}
@@ -1,96 +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.calls.smartcasts;
import org.jetbrains.annotations.NotNull;
public enum Nullability {
NULL(true, false),
NOT_NULL(false, true),
UNKNOWN(true, true),
IMPOSSIBLE(false, false);
@NotNull
public static Nullability fromFlags(boolean canBeNull, boolean canBeNonNull) {
if (!canBeNull && !canBeNonNull) return IMPOSSIBLE;
if (!canBeNull && canBeNonNull) return NOT_NULL;
if (canBeNull && !canBeNonNull) return NULL;
return UNKNOWN;
}
private final boolean canBeNull;
private final boolean canBeNonNull;
Nullability(boolean canBeNull, boolean canBeNonNull) {
this.canBeNull = canBeNull;
this.canBeNonNull = canBeNonNull;
}
public boolean canBeNull() {
return canBeNull;
}
public boolean canBeNonNull() {
return canBeNonNull;
}
@NotNull
public Nullability refine(@NotNull Nullability other) {
switch (this) {
case UNKNOWN:
return other;
case IMPOSSIBLE:
return other;
case NULL:
switch (other) {
case NOT_NULL: return NOT_NULL;
default: return NULL;
}
case NOT_NULL:
switch (other) {
case NULL: return NOT_NULL;
default: return NOT_NULL;
}
}
throw new IllegalStateException();
}
@NotNull
public Nullability invert() {
switch (this) {
case NULL:
return NOT_NULL;
case NOT_NULL:
return UNKNOWN;
case UNKNOWN:
return UNKNOWN;
case IMPOSSIBLE:
return UNKNOWN;
}
throw new IllegalStateException();
}
@NotNull
public Nullability and(@NotNull Nullability other) {
return fromFlags(this.canBeNull && other.canBeNull, this.canBeNonNull && other.canBeNonNull);
}
@NotNull
public Nullability or(@NotNull Nullability other) {
return fromFlags(this.canBeNull || other.canBeNull, this.canBeNonNull || other.canBeNonNull);
}
}
@@ -1,36 +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.calls.tasks;
public enum ExplicitReceiverKind {
EXTENSION_RECEIVER,
DISPATCH_RECEIVER,
NO_EXPLICIT_RECEIVER,
// A very special case.
// In a call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' function 'invoke' has two explicit receivers:
// 'b' (as extension receiver) and 'foo' (as dispatch receiver).
BOTH_RECEIVERS;
public boolean isExtensionReceiver() {
return this == EXTENSION_RECEIVER || this == BOTH_RECEIVERS;
}
public boolean isDispatchReceiver() {
return this == DISPATCH_RECEIVER || this == BOTH_RECEIVERS;
}
}
@@ -1,108 +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.calls.tasks
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind.Function
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collection<FunctionDescriptor> {
val result = ArrayList<FunctionDescriptor>(1)
for (invoke in functions) {
if (invoke !is FunctionInvokeDescriptor || invoke.getValueParameters().isEmpty()) continue
val synthesized = if ((invoke.getContainingDeclaration() as? FunctionClassDescriptor)?.functionKind == Function) {
createSynthesizedFunctionWithFirstParameterAsReceiver(invoke)
}
else {
val invokeDeclaration = invoke.getOverriddenDescriptors().single()
val synthesizedSuperFun = createSynthesizedFunctionWithFirstParameterAsReceiver(invokeDeclaration)
val fakeOverride = synthesizedSuperFun.copy(
invoke.getContainingDeclaration(),
synthesizedSuperFun.modality,
synthesizedSuperFun.visibility,
CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
/* copyOverrides = */ false
)
fakeOverride.setSingleOverridden(synthesizedSuperFun)
fakeOverride
}
result.add(synthesized.substitute(TypeSubstitutor.create(invoke.getDispatchReceiverParameter()!!.type)))
}
return result
}
private fun createSynthesizedFunctionWithFirstParameterAsReceiver(descriptor: FunctionDescriptor): FunctionDescriptor {
val result = SimpleFunctionDescriptorImpl.create(
descriptor.containingDeclaration,
descriptor.annotations,
descriptor.name,
CallableMemberDescriptor.Kind.SYNTHESIZED,
descriptor.source
)
val original = descriptor.original
result.initialize(
original.valueParameters.first().type,
original.dispatchReceiverParameter,
original.typeParameters,
original.valueParameters.drop(1).map { p ->
ValueParameterDescriptorImpl(
result, null, p.index - 1, p.annotations, Name.identifier("p${p.index + 1}"), p.type,
p.declaresDefaultValue(), p.isCrossinline, p.isNoinline, p.varargElementType, p.source
)
},
original.returnType,
original.modality,
original.visibility
)
result.isOperator = original.isOperator
result.isInfix = original.isInfix
result.isExternal = original.isExternal
result.isInline = original.isInline
result.isTailrec = original.isTailrec
result.setHasStableParameterNames(false);
result.setHasSynthesizedParameterNames(true);
return result
}
fun isSynthesizedInvoke(descriptor: DeclarationDescriptor): Boolean {
if (descriptor.name != OperatorNameConventions.INVOKE || descriptor !is FunctionDescriptor) return false
var real: FunctionDescriptor = descriptor
while (!real.kind.isReal) {
// You can't override two different synthesized invokes at the same time
real = real.overriddenDescriptors.singleOrNull() ?: return false
}
return real.kind == CallableMemberDescriptor.Kind.SYNTHESIZED &&
real.containingDeclaration is FunctionClassDescriptor
}
@@ -1,183 +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.calls.tower
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
internal abstract class AbstractInvokeTowerProcessor<C>(
protected val functionContext: TowerContext<C>,
private val variableProcessor: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> {
// todo optimize it
private val previousData = ArrayList<TowerData>()
private val invokeProcessors: MutableList<Collection<VariableInvokeProcessor>> = ArrayList()
private inner class VariableInvokeProcessor(val variableCandidate: C): ScopeTowerProcessor<C> {
val invokeProcessor: ScopeTowerProcessor<C> = createInvokeProcessor(variableCandidate)
override fun process(data: TowerData)
= invokeProcessor.process(data).map { candidateGroup ->
candidateGroup.map { functionContext.transformCandidate(variableCandidate, it) }
}
}
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>
override fun process(data: TowerData): List<Collection<C>> {
previousData.add(data)
val candidateGroups = ArrayList<Collection<C>>(0)
for (processorsGroup in invokeProcessors) {
candidateGroups.addAll(processorsGroup.processVariableGroup(data))
}
for (variableCandidates in variableProcessor.process(data)) {
val successfulVariables = variableCandidates.filter {
functionContext.getStatus(it).resultingApplicability.isSuccess
}
if (successfulVariables.isNotEmpty()) {
val variableProcessors = successfulVariables.map { VariableInvokeProcessor(it) }
invokeProcessors.add(variableProcessors)
for (oldData in previousData) {
candidateGroups.addAll(variableProcessors.processVariableGroup(oldData))
}
}
}
return candidateGroups
}
private fun Collection<VariableInvokeProcessor>.processVariableGroup(data: TowerData): List<Collection<C>> {
return when (size) {
0 -> emptyList()
1 -> single().process(data)
// overload on variables see KT-10093 Resolve depends on the order of declaration for variable with implicit invoke
else -> listOf(this.flatMap { it.process(data).flatten() })
}
}
}
// todo KT-9522 Allow invoke convention for synthetic property
internal class InvokeTowerProcessor<C>(
functionContext: TowerContext<C>,
private val explicitReceiver: Receiver?
) : AbstractInvokeTowerProcessor<C>(
functionContext,
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
) {
// todo filter by operator
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
?: return KnownResultProcessor(emptyList())
return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions)
}
}
internal class InvokeExtensionTowerProcessor<C>(
functionContext: TowerContext<C>,
private val explicitReceiver: ReceiverValue?
) : AbstractInvokeTowerProcessor<C>(
functionContext,
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
) {
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
?: return KnownResultProcessor(emptyList())
val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
?: return KnownResultProcessor(emptyList())
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
}
}
private class InvokeExtensionScopeTowerProcessor<C>(
context: TowerContext<C>,
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
private val explicitReceiver: ReceiverValue?
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
if (explicitReceiver != null && data == TowerData.Empty) {
return listOf(context.createCandidate(invokeCandidateDescriptor, ExplicitReceiverKind.BOTH_RECEIVERS, explicitReceiver))
}
if (explicitReceiver == null && data is TowerData.OnlyImplicitReceiver) {
return listOf(context.createCandidate(invokeCandidateDescriptor, ExplicitReceiverKind.DISPATCH_RECEIVER, data.implicitReceiver))
}
return emptyList()
}
}
// todo debug info
private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
extensionFunctionReceiver: ReceiverValue
): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? {
if (!KotlinBuiltIns.isExactExtensionFunctionType(extensionFunctionReceiver.type)) return null
val invokeDescriptor = extensionFunctionReceiver.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
val synthesizedInvoke = createSynthesizedInvokes(listOf(invokeDescriptor)).single()
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
return CandidateWithBoundDispatchReceiverImpl(extensionFunctionReceiver, synthesizedInvoke, listOf())
}
// case 1.(foo())() or (foo())()
internal fun <C> createCallTowerProcessorForExplicitInvoke(
contextForInvoke: TowerContext<C>,
expressionForInvoke: ReceiverValue,
explicitReceiver: ReceiverValue?
): ScopeTowerProcessor<C> {
val invokeExtensionDescriptor = contextForInvoke.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
if (explicitReceiver != null) {
if (invokeExtensionDescriptor == null) {
// case 1.(foo())(), where foo() isn't extension function
return KnownResultProcessor(emptyList())
}
else {
return InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
}
}
else {
val usualInvoke = ExplicitReceiverScopeTowerProcessor(contextForInvoke, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
if (invokeExtensionDescriptor == null) {
return usualInvoke
}
else {
return CompositeScopeTowerProcessor(
usualInvoke,
InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = null)
)
}
}
}
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.tasks.*
import org.jetbrains.kotlin.resolve.isHiddenInResolution
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
@@ -339,4 +340,17 @@ class NewResolveOldInference(
}
}
@Deprecated("Temporary error")
internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel)
@Deprecated("Temporary error")
internal fun createPreviousResolveError(status: ResolutionStatus): PreviousResolutionError? {
val level = when (status) {
ResolutionStatus.SUCCESS, ResolutionStatus.INCOMPLETE_TYPE_INFERENCE -> return null
ResolutionStatus.UNSAFE_CALL_ERROR -> ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR
else -> ResolutionCandidateApplicability.INAPPLICABLE
}
return PreviousResolutionError(level)
}
@@ -1,107 +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.calls.tower
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
interface ScopeTower {
/**
* Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first
* Doesn't include receivers with error types
*/
val implicitReceivers: List<ReceiverValue>
val lexicalScope: LexicalScope
val dynamicScope: MemberScope
val syntheticScopes: SyntheticScopes
val location: LookupLocation
val dataFlowInfo: DataFlowDecorator
}
interface DataFlowDecorator {
fun getDataFlowValue(receiver: ReceiverValue): DataFlowValue
fun isStableReceiver(receiver: ReceiverValue): Boolean
// doesn't include receiver.type
fun getSmartCastTypes(receiver: ReceiverValue): Set<KotlinType>
}
interface ScopeTowerLevel {
fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
}
interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> {
val descriptor: D
val diagnostics: List<ResolutionDiagnostic>
val dispatchReceiver: ReceiverValue?
}
data class ResolutionCandidateStatus(val diagnostics: List<ResolutionDiagnostic>) {
val resultingApplicability: ResolutionCandidateApplicability = diagnostics.asSequence().map { it.candidateLevel }.max()
?: ResolutionCandidateApplicability.RESOLVED
}
enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
RESOLVED_SYNTHESIZED, // todo remove it (need for SAM adapters which created inside some MemberScope)
RESOLVED_LOW_PRIORITY,
CONVENTION_ERROR, // missing infix, operator etc
MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast
RUNTIME_ERROR, // problems with visibility
IMPOSSIBLE_TO_GENERATE, // access to outer class from nested
INAPPLICABLE, // arguments not matched
HIDDEN, // removed from resolve
// todo wrong receiver
}
abstract class ResolutionDiagnostic(val candidateLevel: ResolutionCandidateApplicability)
// todo error for this access from nested class
class VisibilityError(val invisibleMember: DeclarationDescriptorWithVisibility): ResolutionDiagnostic(ResolutionCandidateApplicability.RUNTIME_ERROR)
class NestedClassViaInstanceReference(val classDescriptor: ClassDescriptor): ResolutionDiagnostic(ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE)
class InnerClassViaStaticReference(val classDescriptor: ClassDescriptor): ResolutionDiagnostic(ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE)
class UnsupportedInnerClassCall(val message: String): ResolutionDiagnostic(ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE)
class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED)
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED) // todo discuss and change to INAPPLICABLE
object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY)
object SynthesizedDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY)
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR)
object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
object HiddenDescriptor: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
object InvokeConventionCallNoOperatorModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
object InfixCallNoInfixModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
object DeprecatedUnaryPlusAsPlus : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 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.
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
@@ -32,12 +31,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.*
internal class CandidateWithBoundDispatchReceiverImpl<D : CallableDescriptor>(
override val dispatchReceiver: ReceiverValue?,
override val descriptor: D,
override val diagnostics: List<ResolutionDiagnostic>
) : CandidateWithBoundDispatchReceiver<D>
internal class ScopeTowerImpl(
resolutionContext: ResolutionContext<*>,
override val dynamicScope: MemberScope,
@@ -50,7 +43,7 @@ internal class ScopeTowerImpl(
override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy().
mapNotNull { it.value.check { !it.type.containsError() } }
val isDebuggerContext = resolutionContext.isDebuggerContext
override val isDebuggerContext = resolutionContext.isDebuggerContext
}
private class DataFlowDecoratorImpl(private val resolutionContext: ResolutionContext<*>): DataFlowDecorator {
@@ -1,140 +0,0 @@
/*
* Copyright 2010-2016 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.calls.tower
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.utils.addToStdlib.check
internal class KnownResultProcessor<C>(
val result: Collection<C>
): ScopeTowerProcessor<C> {
override fun process(data: TowerData)
= if (data == TowerData.Empty) listOfNotNull(result.check { it.isNotEmpty() }) else emptyList()
}
internal class CompositeScopeTowerProcessor<C>(
vararg val processors: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> {
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
}
internal abstract class AbstractSimpleScopeTowerProcessor<C>(
val context: TowerContext<C>
) : ScopeTowerProcessor<C> {
protected val name: Name get() = context.name
protected abstract fun simpleProcess(data: TowerData): Collection<C>
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() })
}
internal class ExplicitReceiverScopeTowerProcessor<C>(
context: TowerContext<C>,
val explicitReceiver: ReceiverValue,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
): AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
return when (data) {
TowerData.Empty -> resolveAsMember()
is TowerData.TowerLevel -> resolveAsExtension(data.level)
else -> emptyList()
}
}
private fun resolveAsMember(): Collection<C> {
val members = ReceiverScopeTowerLevel(context.scopeTower, explicitReceiver)
.collectCandidates(name, null).filter { !it.requiresExtensionReceiver }
return members.map { context.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) }
}
private fun resolveAsExtension(level: ScopeTowerLevel): Collection<C> {
val extensions = level.collectCandidates(name, explicitReceiver).filter { it.requiresExtensionReceiver }
return extensions.map { context.createCandidate(it, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver) }
}
}
private class QualifierScopeTowerProcessor<C>(
context: TowerContext<C>,
val qualifier: QualifierReceiver,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
): AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> {
if (data != TowerData.Empty) return emptyList()
val staticMembers = QualifierScopeTowerLevel(context.scopeTower, qualifier).collectCandidates(name, null)
.filter { !it.requiresExtensionReceiver }
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
return staticMembers
}
}
private class NoExplicitReceiverScopeTowerProcessor<C>(
context: TowerContext<C>,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
) : AbstractSimpleScopeTowerProcessor<C>(context) {
override fun simpleProcess(data: TowerData): Collection<C>
= when(data) {
is TowerData.TowerLevel -> {
data.level.collectCandidates(name, null).filter { !it.requiresExtensionReceiver }.map {
context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null)
}
}
is TowerData.BothTowerLevelAndImplicitReceiver -> {
data.level.collectCandidates(name, data.implicitReceiver).filter { it.requiresExtensionReceiver }.map {
context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = data.implicitReceiver)
}
}
else -> emptyList()
}
}
private fun <C> createSimpleProcessor(
context: TowerContext<C>,
explicitReceiver: Receiver?,
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
) : ScopeTowerProcessor<C> {
if (explicitReceiver is ReceiverValue) {
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
}
else if (explicitReceiver is QualifierReceiver) {
val qualifierProcessor = QualifierScopeTowerProcessor(context, explicitReceiver, collectCandidates)
// todo enum entry, object.
val classValue = explicitReceiver.classValueReceiver ?: return qualifierProcessor
return CompositeScopeTowerProcessor(
qualifierProcessor,
ExplicitReceiverScopeTowerProcessor(context, classValue, collectCandidates)
)
}
else {
assert(explicitReceiver == null) {
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!.javaClass.simpleName})"
}
return NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
}
}
internal fun <C> createVariableProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getVariables)
internal fun <C> createFunctionProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions)
@@ -1,258 +0,0 @@
/*
* Copyright 2010-2016 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.calls.tower
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.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.hasHidesMembersAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables
import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
internal abstract class AbstractScopeTowerLevel(
protected val scopeTower: ScopeTower
): ScopeTowerLevel {
protected val location: LookupLocation get() = scopeTower.location
protected fun <D : CallableDescriptor> createCandidateDescriptor(
descriptor: D,
dispatchReceiver: ReceiverValue?,
specialError: ResolutionDiagnostic? = null,
dispatchReceiverSmartCastType: KotlinType? = null
): CandidateWithBoundDispatchReceiver<D> {
val diagnostics = SmartList<ResolutionDiagnostic>()
diagnostics.addIfNotNull(specialError)
if (ErrorUtils.isError(descriptor)) {
diagnostics.add(ErrorDescriptorDiagnostic)
}
else {
if (descriptor.hasLowPriorityInOverloadResolution()) diagnostics.add(LowPriorityDescriptorDiagnostic)
if (descriptor.isSynthesized) diagnostics.add(SynthesizedDescriptorDiagnostic)
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
val shouldSkipVisibilityCheck = scopeTower is ScopeTowerImpl && scopeTower.isDebuggerContext
if (!shouldSkipVisibilityCheck) {
Visibilities.findInvisibleMember(
dispatchReceiver, descriptor,
scopeTower.lexicalScope.ownerDescriptor
)?.let { diagnostics.add(VisibilityError(it)) }
}
}
return CandidateWithBoundDispatchReceiverImpl(dispatchReceiver, descriptor, diagnostics)
}
}
// todo KT-9538 Unresolved inner class via subclass reference
// todo add static methods & fields with error
internal class ReceiverScopeTowerLevel(
scopeTower: ScopeTower,
val dispatchReceiver: ReceiverValue
): AbstractScopeTowerLevel(scopeTower) {
private fun <D : CallableDescriptor> collectMembers(
getMembers: ResolutionScope.(KotlinType?) -> Collection<D>
): Collection<CandidateWithBoundDispatchReceiver<D>> {
val result = ArrayList<CandidateWithBoundDispatchReceiver<D>>(0)
dispatchReceiver.type.memberScope.getMembers(dispatchReceiver.type).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver)
}
val smartCastPossibleTypes = scopeTower.dataFlowInfo.getSmartCastTypes(dispatchReceiver)
val unstableError = if (scopeTower.dataFlowInfo.isStableReceiver(dispatchReceiver)) null else UnstableSmartCastDiagnostic
val unstableCandidates = if (unstableError != null) ArrayList<CandidateWithBoundDispatchReceiver<D>>(0) else null
for (possibleType in smartCastPossibleTypes) {
possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) {
createCandidateDescriptor(it, dispatchReceiver.smartCastReceiver(possibleType), unstableError, dispatchReceiverSmartCastType = possibleType)
}
}
if (smartCastPossibleTypes.isNotEmpty()) {
if (unstableCandidates == null) {
result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor })
}
else {
result.addAll(unstableCandidates.selectMostSpecificInEachOverridableGroup { descriptor })
}
}
if (dispatchReceiver.type.isDynamic()) {
scopeTower.dynamicScope.getMembers(null).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic)
}
}
return result
}
private fun ReceiverValue.smartCastReceiver(targetType: KotlinType)
= if (this is ImplicitClassReceiver) CastImplicitClassReceiver(this.classDescriptor, targetType) else this
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
return collectMembers { getContributedVariables(name, location) }
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
return collectMembers {
getContributedFunctions(name, location) + it.getInnerConstructors(name, location)
}
}
}
internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope
.getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope
.getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
// KT-3335 Creating imported super class' inner class fails in codegen
internal open class ScopeBasedTowerLevel protected constructor(
scopeTower: ScopeTower,
private val resolutionScope: ResolutionScope
) : AbstractScopeTowerLevel(scopeTower) {
internal constructor(scopeTower: ScopeTower, lexicalScope: LexicalScope): this(scopeTower, lexicalScope as ResolutionScope)
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
= resolutionScope.getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
= resolutionScope.getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
internal class ImportingScopeBasedTowerLevel(
scopeTower: ScopeTower,
private val importingScope: ImportingScope
): ScopeBasedTowerLevel(scopeTower, importingScope)
internal class SyntheticScopeBasedTowerLevel(
scopeTower: ScopeTower,
private val syntheticScopes: SyntheticScopes
): AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
if (extensionReceiver == null) return emptyList()
val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver)
return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiverTypes, name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
if (extensionReceiver == null) return emptyList()
val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver)
return syntheticScopes.collectSyntheticExtensionFunctions(extensionReceiverTypes, name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
}
internal class HidesMembersTowerLevel(scopeTower: ScopeTower): AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValue?)
= getCandidates(name, extensionReceiver, LexicalScope::collectVariables)
override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?)
= getCandidates(name, extensionReceiver, LexicalScope::collectFunctions)
private fun <T: CallableDescriptor> getCandidates(
name: Name,
extensionReceiver: ReceiverValue?,
collectCandidates: LexicalScope.(Name, LookupLocation) -> Collection<T>
): Collection<CandidateWithBoundDispatchReceiver<T>> {
if (extensionReceiver == null || name !in HIDES_MEMBERS_NAME_LIST) return emptyList()
return scopeTower.lexicalScope.collectCandidates(name, location).filter {
it.extensionReceiverParameter != null && it.hasHidesMembersAnnotation()
}.map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
}
private fun KotlinType.getClassifierFromMeAndSuperclasses(name: Name, location: LookupLocation): ClassifierDescriptor? {
var superclass: KotlinType? = this
while (superclass != null) {
superclass.memberScope.getContributedClassifier(name, location)?.let { return it }
superclass = superclass.getImmediateSuperclassNotAny()
}
return null
}
private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
val classifierDescriptor = getClassWithConstructors(this?.getClassifierFromMeAndSuperclasses(name, location))
return classifierDescriptor?.constructors?.filter { it.dispatchReceiverParameter != null } ?: emptyList()
}
private fun ResolutionScope.getContributedFunctionsAndConstructors(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
val classWithConstructors = getClassWithConstructors(getContributedClassifier(name, location))
return getContributedFunctions(name, location) +
(classWithConstructors?.constructors?.filter { it.dispatchReceiverParameter == null } ?: emptyList())
}
private fun ResolutionScope.getContributedVariablesAndObjects(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
val objectDescriptor = getFakeDescriptorForObject(getContributedClassifier(name, location))
return getContributedVariables(name, location) + listOfNotNull(objectDescriptor)
}
private fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeCallableDescriptorForObject? {
if (classifier !is ClassDescriptor || !classifier.hasClassValueDescriptor) return null // todo
return FakeCallableDescriptorForObject(classifier)
}
private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? {
if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier)
// Constructors of singletons shouldn't be callable from the code
|| classifier.kind.isSingleton) {
return null
}
else {
return classifier
}
}
@@ -1,236 +0,0 @@
/*
* Copyright 2010-2016 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.calls.tower
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.*
interface TowerContext<C> {
val name: Name
val scopeTower: ScopeTower
fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver<*>,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValue?
): C
fun getStatus(candidate: C): ResolutionCandidateStatus
fun transformCandidate(variable: C, invoke: C): C
fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<C>
// foo() -> ReceiverValue(foo), context for invoke
// null means that there is no invoke on variable
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>?
}
internal sealed class TowerData {
object Empty : TowerData()
class OnlyImplicitReceiver(val implicitReceiver: ReceiverValue): TowerData()
class TowerLevel(val level: ScopeTowerLevel) : TowerData()
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData()
}
internal interface ScopeTowerProcessor<C> {
// Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel)
// Candidates in one groups have same priority, first group has highest priority.
fun process(data: TowerData): List<Collection<C>>
}
class TowerResolver {
internal fun <C> runResolve(
context: TowerContext<C>,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean
): Collection<C> = run(context.scopeTower.createTowerDataList(), processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder)
internal fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C>
= run(context.scopeTower.createTowerDataList(), processor, AllCandidatesCollector { context.getStatus(it) }, false)
private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
val result = ArrayList<ScopeTowerLevel>()
lexicalScope.parentsWithSelf.forEach { scope ->
if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) result.add(ScopeBasedTowerLevel(this, scope))
scope.implicitReceiver?.let { result.add(ReceiverScopeTowerLevel(this, it.value)) }
}
else {
result.add(ImportingScopeBasedTowerLevel(this, scope as ImportingScope))
}
}
return result
}
private fun ScopeTower.createTowerDataList(): List<TowerData> {
val result = ArrayList<TowerData>()
operator fun TowerData.unaryPlus() = result.add(this)
val localLevels = lexicalScope.parentsWithSelf.
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors }.
map { ScopeBasedTowerLevel(this@createTowerDataList, it) }
val nonLocalLevels = createNonLocalLevels()
val hidesMembersLevel = HidesMembersTowerLevel(this)
val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes)
// hides members extensions for explicit receiver
+ TowerData.TowerLevel(hidesMembersLevel)
// possibly there is explicit member
+ TowerData.Empty
// synthetic member for explicit receiver
+ TowerData.TowerLevel(syntheticLevel)
// local non-extensions or extension for explicit receiver
for (localLevel in localLevels) {
+ TowerData.TowerLevel(localLevel)
}
for (scope in this.lexicalScope.parentsWithSelf) {
if (scope is LexicalScope) {
// statics
if (!scope.kind.withLocalDescriptors) {
+ TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope))
}
val implicitReceiver = scope.implicitReceiver?.value
if (implicitReceiver != null) {
// hides members extensions
+ TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver)
// members of implicit receiver or member extension for explicit receiver
+ TowerData.TowerLevel(ReceiverScopeTowerLevel(this, implicitReceiver))
// synthetic members
+ TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver)
// invokeExtension on local variable
+ TowerData.OnlyImplicitReceiver(implicitReceiver)
// local extensions for implicit receiver
for (localLevel in localLevels) {
+ TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver)
}
// extension for implicit receiver
for (nonLocalLevel in nonLocalLevels) {
+ TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver)
}
}
}
else {
// functions with no receiver or extension for explicit receiver
+ TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope))
}
}
return result
}
internal fun <C> run(
towerDataList: List<TowerData>,
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
): Collection<C> {
for (towerData in towerDataList) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val candidatesGroups = if (useOrder) {
processor.process(towerData)
}
else {
listOf(processor.process(towerData).flatMap { it })
}
for (candidatesGroup in candidatesGroups) {
resultCollector.pushCandidates(candidatesGroup)
resultCollector.getSuccessfulCandidates()?.let { return it }
}
}
return resultCollector.getFinalCandidates()
}
internal abstract class ResultCollector<C>(protected val getStatus: (C) -> ResolutionCandidateStatus) {
abstract fun getSuccessfulCandidates(): Collection<C>?
abstract fun getFinalCandidates(): Collection<C>
fun pushCandidates(candidates: Collection<C>) {
val filteredCandidates = candidates.filter {
getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN
}
if (filteredCandidates.isNotEmpty()) addCandidates(filteredCandidates)
}
protected abstract fun addCandidates(candidates: Collection<C>)
}
internal class AllCandidatesCollector<C>(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector<C>(getStatus) {
private val allCandidates = ArrayList<C>()
override fun getSuccessfulCandidates(): Collection<C>? = null
override fun getFinalCandidates(): Collection<C> = allCandidates
override fun addCandidates(candidates: Collection<C>) {
allCandidates.addAll(candidates)
}
}
internal class SuccessfulResultCollector<C>(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector<C>(getStatus) {
private var currentCandidates: Collection<C> = emptyList()
private var currentLevel: ResolutionCandidateApplicability? = null
override fun getSuccessfulCandidates(): Collection<C>? = getResolved() ?: getResolvedSynthetic()
fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
fun getResolvedSynthetic() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
fun getResolvedLowPriority() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY }
fun getErrors() = currentCandidates.check {
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
}
override fun getFinalCandidates() = getResolved() ?: getResolvedSynthetic() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList()
override fun addCandidates(candidates: Collection<C>) {
val minimalLevel = candidates.map { getStatus(it).resultingApplicability }.min()!!
if (currentLevel == null || currentLevel!! > minimalLevel) {
currentLevel = minimalLevel
currentCandidates = candidates.filter { getStatus(it).resultingApplicability == minimalLevel }
}
}
}
}
@@ -1,47 +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.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@Deprecated("Temporary error")
internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel)
@Deprecated("Temporary error")
internal fun createPreviousResolveError(status: ResolutionStatus): PreviousResolutionError? {
val level = when (status) {
ResolutionStatus.SUCCESS, ResolutionStatus.INCOMPLETE_TYPE_INFERENCE -> return null
ResolutionStatus.UNSAFE_CALL_ERROR -> ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR
else -> ResolutionCandidateApplicability.INAPPLICABLE
}
return PreviousResolutionError(level)
}
internal val ResolutionCandidateApplicability.isSuccess: Boolean
get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
internal val CallableDescriptor.isSynthesized: Boolean
get() = (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED)
internal val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean
get() = descriptor.extensionReceiverParameter != null
internal fun DataFlowDecorator.getAllPossibleTypes(receiver: ReceiverValue) = getSmartCastTypes(receiver) + receiver.type
@@ -1,66 +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.calls.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.resolve.descriptorUtil.getClassObjectReferenceTarget
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
import org.jetbrains.kotlin.types.KotlinType
import java.util.Collections
class FakeCallableDescriptorForObject(
val classDescriptor: ClassDescriptor
) : DeclarationDescriptorWithVisibility by classDescriptor.getClassObjectReferenceTarget(), VariableDescriptor {
init {
assert(classDescriptor.hasClassValueDescriptor) {
"FakeCallableDescriptorForObject can be created only for objects, classes with companion object or enum entries: $classDescriptor"
}
}
fun getReferencedDescriptor(): ClassDescriptor = classDescriptor.getClassObjectReferenceTarget()
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = null
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null
override fun getTypeParameters(): List<TypeParameterDescriptor> = Collections.emptyList()
override fun getValueParameters(): List<ValueParameterDescriptor> = Collections.emptyList()
override fun getReturnType(): KotlinType? = type
override fun hasSynthesizedParameterNames() = false
override fun hasStableParameterNames() = false
override fun getOverriddenDescriptors(): Set<CallableDescriptor> = Collections.emptySet()
override fun getType(): KotlinType = classDescriptor.classValueType!!
override fun isVar() = false
override fun getOriginal(): CallableDescriptor = this
override fun getCompileTimeInitializer() = null
override fun getSource(): SourceElement = classDescriptor.source
override fun isConst(): Boolean = false
}
@@ -1,48 +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.scopes
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Printer
class FilteringScope(private val workerScope: MemberScope, private val predicate: (DeclarationDescriptor) -> Boolean) : MemberScope {
override fun getContributedFunctions(name: Name, location: LookupLocation) = workerScope.getContributedFunctions(name, location).filter(predicate)
private fun <D : DeclarationDescriptor> filterDescriptor(descriptor: D?): D?
= if (descriptor != null && predicate(descriptor)) descriptor else null
override fun getContributedClassifier(name: Name, location: LookupLocation) = filterDescriptor(workerScope.getContributedClassifier(name, location))
override fun getContributedVariables(name: Name, location: LookupLocation) = workerScope.getContributedVariables(name, location).filter(predicate)
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean) = workerScope.getContributedDescriptors(kindFilter, nameFilter).filter(predicate)
override fun printScopeStructure(p: Printer) {
p.println(javaClass.simpleName, " {")
p.pushIndent()
p.print("workerScope = ")
workerScope.printScopeStructure(p.withholdIndentOnce())
p.popIndent()
p.println("}")
}
}
@@ -1,67 +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.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.resolve.scopes.utils.takeSnapshot
import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
import org.jetbrains.kotlin.utils.Printer
class LexicalChainedScope @JvmOverloads constructor(
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val kind: LexicalScopeKind,
private val memberScopes: List<MemberScope>,
@Deprecated("This value is temporary hack for resolve -- don't use it!")
val isStaticScope: Boolean = false
): LexicalScope {
override val parent = parent.takeSnapshot()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= getFromAllScopes(memberScopes) { it.getContributedDescriptors() }
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstMatch(memberScopes) { it.getContributedClassifier(name, location) }
override fun getContributedVariables(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }
override fun getContributedFunctions(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedFunctions(name, location) }
override fun toString(): String = kind.toString()
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {")
p.pushIndent()
for (scope in memberScopes) {
scope.printScopeStructure(p)
}
p.print("parent = ")
parent.printStructure(p.withholdIndentOnce())
p.popIndent()
p.println("}")
}
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2016 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.utils.Printer
class LexicalScopeImpl @JvmOverloads constructor(
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val kind: LexicalScopeKind,
redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING,
initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {}
): LexicalScope, LexicalScopeStorage(parent, redeclarationChecker) {
init {
InitializeHandler().initialize()
}
override fun toString(): String = kind.toString()
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {")
p.pushIndent()
p.print("parent = ")
parent.printStructure(p.withholdIndentOnce())
p.popIndent()
p.println("}")
}
inner class InitializeHandler() {
fun addVariableDescriptor(variableDescriptor: VariableDescriptor): Unit
= this@LexicalScopeImpl.addVariableOrClassDescriptor(variableDescriptor)
fun addFunctionDescriptor(functionDescriptor: FunctionDescriptor): Unit
= this@LexicalScopeImpl.addFunctionDescriptorInternal(functionDescriptor)
fun addClassifierDescriptor(classifierDescriptor: ClassifierDescriptor): Unit
= this@LexicalScopeImpl.addVariableOrClassDescriptor(classifierDescriptor)
}
}
@@ -1,118 +0,0 @@
/*
* Copyright 2010-2016 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.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
import java.util.*
abstract class LexicalScopeStorage(
parent: HierarchicalScope,
val redeclarationChecker: LocalRedeclarationChecker
): LexicalScope {
override val parent = parent.takeSnapshot()
protected val addedDescriptors: MutableList<DeclarationDescriptor> = SmartList()
private var functionsByName: MutableMap<Name, IntList>? = null
private var variablesAndClassifiersByName: MutableMap<Name, IntList>? = null
override fun getContributedClassifier(name: Name, location: LookupLocation) = variableOrClassDescriptorByName(name) as? ClassifierDescriptor
override fun getContributedVariables(name: Name, location: LookupLocation) = listOfNotNull(variableOrClassDescriptorByName(name) as? VariableDescriptor)
override fun getContributedFunctions(name: Name, location: LookupLocation) = functionsByName(name)
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= addedDescriptors
protected fun addVariableOrClassDescriptor(descriptor: DeclarationDescriptor) {
val name = descriptor.name
val descriptorIndex = addDescriptor(descriptor)
if (variablesAndClassifiersByName == null) {
variablesAndClassifiersByName = HashMap()
}
//TODO: could not use += because of KT-8050
variablesAndClassifiersByName!![name] = variablesAndClassifiersByName!![name] + descriptorIndex
}
protected fun addFunctionDescriptorInternal(functionDescriptor: FunctionDescriptor) {
val name = functionDescriptor.name
val descriptorIndex = addDescriptor(functionDescriptor)
if (functionsByName == null) {
functionsByName = HashMap(1)
}
//TODO: could not use += because of KT-8050
functionsByName!![name] = functionsByName!![name] + descriptorIndex
}
protected fun variableOrClassDescriptorByName(name: Name, descriptorLimit: Int = addedDescriptors.size): DeclarationDescriptor? {
if (descriptorLimit == 0) return null
var list = variablesAndClassifiersByName?.get(name)
while (list != null) {
val descriptorIndex = list.last
if (descriptorIndex < descriptorLimit) {
return descriptorIndex.descriptorByIndex()
}
list = list.prev
}
return null
}
protected fun functionsByName(name: Name, descriptorLimit: Int = addedDescriptors.size): List<FunctionDescriptor> {
if (descriptorLimit == 0) return emptyList()
var list = functionsByName?.get(name)
while (list != null) {
if (list.last < descriptorLimit) {
return list.toDescriptors<FunctionDescriptor>()
}
list = list.prev
}
return emptyList()
}
private fun addDescriptor(descriptor: DeclarationDescriptor): Int {
redeclarationChecker.checkBeforeAddingToScope(this, descriptor)
addedDescriptors.add(descriptor)
return addedDescriptors.size - 1
}
private class IntList(val last: Int, val prev: IntList?)
private fun Int.descriptorByIndex() = addedDescriptors[this]
private operator fun IntList?.plus(value: Int) = IntList(value, this)
private fun <TDescriptor: DeclarationDescriptor> IntList.toDescriptors(): List<TDescriptor> {
val result = ArrayList<TDescriptor>(1)
var rest: IntList? = this
do {
result.add(rest!!.last.descriptorByIndex() as TDescriptor)
rest = rest.prev
} while (rest != null)
return result
}
}
@@ -1,99 +0,0 @@
/*
* Copyright 2010-2016 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.name.Name
import org.jetbrains.kotlin.utils.Printer
class LexicalWritableScope(
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceiver: ReceiverParameterDescriptor?,
redeclarationChecker: LocalRedeclarationChecker,
override val kind: LexicalScopeKind
) : LexicalScopeStorage(parent, redeclarationChecker) {
private var canWrite: Boolean = true
private var lastSnapshot: Snapshot? = null
fun freeze() {
canWrite = false
}
fun takeSnapshot(): LexicalScope {
if (lastSnapshot == null || lastSnapshot!!.descriptorLimit != addedDescriptors.size) {
lastSnapshot = Snapshot(addedDescriptors.size)
}
return lastSnapshot!!
}
fun addVariableDescriptor(variableDescriptor: VariableDescriptor) {
checkMayWrite()
addVariableOrClassDescriptor(variableDescriptor)
}
fun addFunctionDescriptor(functionDescriptor: FunctionDescriptor) {
checkMayWrite()
addFunctionDescriptorInternal(functionDescriptor)
}
fun addClassifierDescriptor(classifierDescriptor: ClassifierDescriptor) {
checkMayWrite()
addVariableOrClassDescriptor(classifierDescriptor)
}
private fun checkMayWrite() {
if (!canWrite) {
throw IllegalStateException("Cannot write into freezed scope:" + toString())
}
}
private inner class Snapshot(val descriptorLimit: Int) : LexicalScope by this {
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= addedDescriptors.subList(0, descriptorLimit)
override fun getContributedClassifier(name: Name, location: LookupLocation) = variableOrClassDescriptorByName(name, descriptorLimit) as? ClassifierDescriptor
override fun getContributedVariables(name: Name, location: LookupLocation) = listOfNotNull(variableOrClassDescriptorByName(name, descriptorLimit) as? VariableDescriptor)
override fun getContributedFunctions(name: Name, location: LookupLocation) = functionsByName(name, descriptorLimit)
override fun toString(): String = "Snapshot($descriptorLimit) for $kind"
override fun printStructure(p: Printer) {
p.println("Snapshot with descriptorLimit = $descriptorLimit for scope:")
this@LexicalWritableScope.printStructure(p)
}
}
override fun toString(): String = kind.toString()
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName, ": ", kind, "; for descriptor: ", ownerDescriptor.name,
" with implicitReceiver: ", implicitReceiver?.value ?: "NONE", " {")
p.pushIndent()
p.print("parent = ")
parent.printStructure(p.withholdIndentOnce())
p.popIndent()
p.println("}")
}
}
@@ -24,13 +24,6 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverloadUtil
interface LocalRedeclarationChecker {
fun checkBeforeAddingToScope(scope: LexicalScope, newDescriptor: DeclarationDescriptor)
object DO_NOTHING : LocalRedeclarationChecker {
override fun checkBeforeAddingToScope(scope: LexicalScope, newDescriptor: DeclarationDescriptor) {}
}
}
abstract class AbstractLocalRedeclarationChecker : LocalRedeclarationChecker {
override fun checkBeforeAddingToScope(scope: LexicalScope, newDescriptor: DeclarationDescriptor) {
@@ -1,94 +0,0 @@
/*
* Copyright 2010-2016 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 kotlin.Unit;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.utils.Printer;
public final class ScopeUtils {
private ScopeUtils() {}
@NotNull
public static MemberScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) {
MemberScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope();
return new FilteringScope(innerClassesScope, new Function1<DeclarationDescriptor, Boolean>() {
@Override
public Boolean invoke(DeclarationDescriptor descriptor) {
return descriptor instanceof ClassDescriptor && !((ClassDescriptor) descriptor).isInner();
}
});
}
public static LexicalScope makeScopeForPropertyHeader(
@NotNull LexicalScope parent,
@NotNull final PropertyDescriptor propertyDescriptor
) {
return new LexicalScopeImpl(parent, propertyDescriptor, false, null, LexicalScopeKind.PROPERTY_HEADER,
// redeclaration on type parameters should be reported early, see: DescriptorResolver.resolvePropertyDescriptor()
LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {
@Override
public Unit invoke(LexicalScopeImpl.InitializeHandler handler) {
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
handler.addClassifierDescriptor(typeParameterDescriptor);
}
return Unit.INSTANCE;
}
});
}
@NotNull
public static LexicalScope makeScopeForPropertyInitializer(
@NotNull LexicalScope propertyHeader,
@NotNull PropertyDescriptor propertyDescriptor
) {
return new LexicalScopeImpl(propertyHeader, propertyDescriptor, false, null, LexicalScopeKind.PROPERTY_INITIALIZER_OR_DELEGATE);
}
@NotNull
public static LexicalScope makeScopeForDelegateConventionFunctions(
@NotNull LexicalScope parent,
@NotNull PropertyDescriptor propertyDescriptor
) {
// todo: very strange scope!
return new LexicalScopeImpl(parent, propertyDescriptor, true, propertyDescriptor.getExtensionReceiverParameter(),
LexicalScopeKind.PROPERTY_DELEGATE_METHOD
);
}
@TestOnly
@NotNull
public static String printStructure(@Nullable MemberScope scope) {
StringBuilder out = new StringBuilder();
Printer p = new Printer(out);
if (scope == null) {
p.println("null");
}
else {
scope.printScopeStructure(p);
}
return out.toString();
}
}
@@ -1,136 +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.scopes
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Printer
// see utils/ScopeUtils.kt
interface HierarchicalScope : ResolutionScope {
val parent: HierarchicalScope?
fun printStructure(p: Printer)
}
interface LexicalScope: HierarchicalScope {
override val parent: HierarchicalScope
val ownerDescriptor: DeclarationDescriptor
val isOwnerDescriptorAccessibleByLabel: Boolean
val implicitReceiver: ReceiverParameterDescriptor?
val kind: LexicalScopeKind
companion object {
fun empty(parent: HierarchicalScope, ownerDescriptor: DeclarationDescriptor): BaseLexicalScope {
return object : BaseLexicalScope(parent, ownerDescriptor) {
override val kind: LexicalScopeKind get() = LexicalScopeKind.EMPTY
override fun printStructure(p: Printer) {
p.println("Empty lexical scope with owner = $ownerDescriptor and parent = ${parent}.")
}
}
}
}
}
enum class LexicalScopeKind(val withLocalDescriptors: Boolean) {
EMPTY(false),
THROWING(false),
CLASS_HEADER(false),
CLASS_INHERITANCE(false),
CONSTRUCTOR_HEADER(false),
CLASS_STATIC_SCOPE(false),
CLASS_MEMBER_SCOPE(false),
CLASS_INITIALIZER(true),
DEFAULT_VALUE(true),
PROPERTY_HEADER(false),
PROPERTY_INITIALIZER_OR_DELEGATE(true),
PROPERTY_ACCESSOR_BODY(true),
PROPERTY_DELEGATE_METHOD(false),
FUNCTION_HEADER(false),
FUNCTION_INNER_SCOPE(true),
CODE_BLOCK(true),
LEFT_BOOLEAN_EXPRESSION(true),
RIGHT_BOOLEAN_EXPRESSION(true),
THEN(true),
ELSE(true),
DO_WHILE_BODY(true),
CATCH(true),
FOR(true),
WHILE_BODY(true),
WHEN(true),
CALLABLE_REFERENCE(false),
// for tests, KDoc & IDE
SYNTHETIC(false)
}
interface ImportingScope : HierarchicalScope {
override val parent: ImportingScope?
fun getContributedPackage(name: Name): PackageViewDescriptor?
object Empty : BaseImportingScope(null) {
override fun printStructure(p: Printer) {
p.println("ImportingScope.Empty")
}
}
}
abstract class BaseHierarchicalScope(override val parent: HierarchicalScope?) : HierarchicalScope {
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> = emptyList()
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> = emptyList()
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> = emptyList()
}
abstract class BaseLexicalScope(
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor
): BaseHierarchicalScope(parent), LexicalScope {
override val parent: HierarchicalScope
get() = super.parent!!
override val isOwnerDescriptorAccessibleByLabel: Boolean
get() = false
override val implicitReceiver: ReceiverParameterDescriptor?
get() = null
}
abstract class BaseImportingScope(parent: ImportingScope?) : BaseHierarchicalScope(parent), ImportingScope {
override val parent: ImportingScope?
get() = super.parent as ImportingScope?
override fun getContributedPackage(name: Name): PackageViewDescriptor? = null
}
@@ -1,35 +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.scopes
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Printer
class SubpackagesImportingScope(
override val parent: ImportingScope?,
moduleDescriptor: ModuleDescriptor,
fqName: FqName
) : SubpackagesScope(moduleDescriptor, fqName), ImportingScope by ImportingScope.Empty {
override fun getContributedPackage(name: Name): PackageViewDescriptor? = getPackage(name)
override fun printStructure(p: Printer) = printScopeStructure(p)
}
@@ -16,7 +16,10 @@
package org.jetbrains.kotlin.resolve.scopes.receivers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector
@@ -26,14 +29,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
interface QualifierReceiver : Receiver {
val descriptor: DeclarationDescriptor
val staticScope: MemberScope
val classValueReceiver: ReceiverValue?
}
interface Qualifier : QualifierReceiver {
val referenceExpression: KtSimpleNameExpression
}
@@ -1,250 +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.scopes.utils
import com.intellij.util.SmartList
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.scopes.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.collectionUtils.concat
import org.jetbrains.kotlin.utils.Printer
val HierarchicalScope.parentsWithSelf: Sequence<HierarchicalScope>
get() = generateSequence(this) { it.parent }
val HierarchicalScope.parents: Sequence<HierarchicalScope>
get() = parentsWithSelf.drop(1)
/**
* Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first
*/
fun LexicalScope.getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> = collectFromMeAndParent {
(it as? LexicalScope)?.implicitReceiver
}
fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = collectAllFromMeAndParent {
if (it is LexicalScope && it.isOwnerDescriptorAccessibleByLabel && it.ownerDescriptor.name == labelName) {
listOf(it.ownerDescriptor)
}
else {
listOf()
}
}
// Result is guaranteed to be filtered by kind and name.
fun HierarchicalScope.collectDescriptorsFiltered(
kindFilter: DescriptorKindFilter = DescriptorKindFilter.ALL,
nameFilter: (Name) -> Boolean = { true }
): Collection<DeclarationDescriptor> {
if (kindFilter.kindMask == 0) return listOf()
return collectAllFromMeAndParent { it.getContributedDescriptors(kindFilter, nameFilter) }
.filter { kindFilter.accepts(it) && nameFilter(it.name) }
}
@Deprecated("Use getOwnProperties instead") fun LexicalScope.findLocalVariable(name: Name): VariableDescriptor? {
return findFirstFromMeAndParent {
when {
it is LexicalScopeWrapper -> it.delegate.findLocalVariable(name)
it !is ImportingScope && it !is LexicalChainedScope -> it.getContributedVariables(name, NoLookupLocation.WHEN_GET_LOCAL_VARIABLE).singleOrNull() /* todo check this*/
else -> null
}
}
}
fun HierarchicalScope.findClassifier(name: Name, location: LookupLocation): ClassifierDescriptor?
= findFirstFromMeAndParent { it.getContributedClassifier(name, location) }
fun HierarchicalScope.findPackage(name: Name): PackageViewDescriptor?
= findFirstFromImportingScopes { it.getContributedPackage(name) }
fun HierarchicalScope.collectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor>
= collectAllFromMeAndParent { it.getContributedVariables(name, location) }
fun HierarchicalScope.collectFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor>
= collectAllFromMeAndParent { it.getContributedFunctions(name, location) }
fun HierarchicalScope.findVariable(name: Name, location: LookupLocation, predicate: (VariableDescriptor) -> Boolean = { true }): VariableDescriptor? {
processForMeAndParent {
it.getContributedVariables(name, location).firstOrNull(predicate)?.let { return it }
}
return null
}
fun HierarchicalScope.findFunction(name: Name, location: LookupLocation, predicate: (FunctionDescriptor) -> Boolean = { true }): FunctionDescriptor? {
processForMeAndParent {
it.getContributedFunctions(name, location).firstOrNull(predicate)?.let { return it }
}
return null
}
fun HierarchicalScope.takeSnapshot(): HierarchicalScope = if (this is LexicalWritableScope) takeSnapshot() else this
@JvmOverloads fun MemberScope.memberScopeAsImportingScope(parentScope: ImportingScope? = null): ImportingScope = MemberScopeToImportingScopeAdapter(parentScope, this)
private class MemberScopeToImportingScopeAdapter(override val parent: ImportingScope?, val memberScope: MemberScope) : ImportingScope {
override fun getContributedPackage(name: Name): PackageViewDescriptor? = null
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= memberScope.getContributedDescriptors(kindFilter, nameFilter)
override fun getContributedClassifier(name: Name, location: LookupLocation) = memberScope.getContributedClassifier(name, location)
override fun getContributedVariables(name: Name, location: LookupLocation) = memberScope.getContributedVariables(name, location)
override fun getContributedFunctions(name: Name, location: LookupLocation) = memberScope.getContributedFunctions(name, location)
override fun equals(other: Any?) = other is MemberScopeToImportingScopeAdapter && other.memberScope == memberScope
override fun hashCode() = memberScope.hashCode()
override fun toString() = "${javaClass.simpleName} for $memberScope"
override fun printStructure(p: Printer) {
p.println(javaClass.simpleName)
p.pushIndent()
memberScope.printScopeStructure(p.withholdIndentOnce())
p.popIndent()
p.println("}")
}
}
inline fun HierarchicalScope.processForMeAndParent(process: (HierarchicalScope) -> Unit) {
var currentScope = this
while (true) {
process(currentScope)
currentScope = currentScope.parent ?: break
}
}
private inline fun <T: Any> HierarchicalScope.collectFromMeAndParent(
collect: (HierarchicalScope) -> T?
): List<T> {
var result: MutableList<T>? = null
processForMeAndParent {
val element = collect(it)
if (element != null) {
if (result == null) {
result = SmartList()
}
result!!.add(element)
}
}
return result ?: emptyList()
}
inline fun <T: Any> HierarchicalScope.collectAllFromMeAndParent(
collect: (HierarchicalScope) -> Collection<T>
): Collection<T> {
var result: Collection<T>? = null
processForMeAndParent { result = result.concat(collect(it)) }
return result ?: emptySet()
}
inline fun <T: Any> HierarchicalScope.findFirstFromMeAndParent(fetch: (HierarchicalScope) -> T?): T? {
processForMeAndParent { fetch(it)?.let { return it } }
return null
}
inline fun <T: Any> HierarchicalScope.collectAllFromImportingScopes(
collect: (ImportingScope) -> Collection<T>
): Collection<T> {
return collectAllFromMeAndParent { if (it is ImportingScope) collect(it) else emptyList() }
}
inline fun <T: Any> HierarchicalScope.findFirstFromImportingScopes(fetch: (ImportingScope) -> T?): T? {
return findFirstFromMeAndParent { if (it is ImportingScope) fetch(it) else null }
}
fun LexicalScope.addImportingScopes(importScopes: List<ImportingScope>): LexicalScope {
val lastLexicalScope = parentsWithSelf.last { it is LexicalScope }
val firstImporting = lastLexicalScope.parent as ImportingScope
val newFirstImporting = chainImportingScopes(importScopes, firstImporting)
return LexicalScopeWrapper(this, newFirstImporting!!)
}
fun LexicalScope.addImportingScope(importScope: ImportingScope): LexicalScope
= addImportingScopes(listOf(importScope))
fun ImportingScope.withParent(newParent: ImportingScope?): ImportingScope {
return object: ImportingScope by this {
override val parent: ImportingScope?
get() = newParent
}
}
fun LexicalScope.replaceImportingScopes(importingScopeChain: ImportingScope?): LexicalScope {
return LexicalScopeWrapper(this, importingScopeChain ?: ImportingScope.Empty)
}
private class LexicalScopeWrapper(val delegate: LexicalScope, val newImportingScopeChain: ImportingScope): LexicalScope by delegate {
override val parent: HierarchicalScope by lazy(LazyThreadSafetyMode.NONE) {
assert(delegate !is ImportingScope)
val parent = delegate.parent
if (parent is LexicalScope) {
LexicalScopeWrapper(parent, newImportingScopeChain)
}
else {
newImportingScopeChain
}
}
}
fun chainImportingScopes(scopes: List<ImportingScope>, tail: ImportingScope? = null): ImportingScope? {
return scopes.asReversed()
.fold(tail) { current, scope ->
assert(scope.parent == null)
scope.withParent(current)
}
}
class ThrowingLexicalScope : LexicalScope {
override val parent: HierarchicalScope
get() = throw IllegalStateException()
override val ownerDescriptor: DeclarationDescriptor
get() = throw IllegalStateException()
override val isOwnerDescriptorAccessibleByLabel: Boolean
get() = throw IllegalStateException()
override val implicitReceiver: ReceiverParameterDescriptor?
get() = throw IllegalStateException()
override val kind: LexicalScopeKind
get() = LexicalScopeKind.THROWING
override fun printStructure(p: Printer) =
throw IllegalStateException()
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
throw IllegalStateException()
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> =
throw IllegalStateException()
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> =
throw IllegalStateException()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> =
throw IllegalStateException()
}