Select most specific overloaded function/property by explicitly used arguments only.

Major rewrite of OverloadingConflictResolver.
This commit is contained in:
Dmitry Petrov
2015-12-15 16:20:09 +03:00
parent 52f0e0bc93
commit 09f53ea0bb
24 changed files with 689 additions and 172 deletions
@@ -27,10 +27,15 @@ public interface VariableAsFunctionResolvedCall {
public val variableCall: ResolvedCall<VariableDescriptor> public val variableCall: ResolvedCall<VariableDescriptor>
} }
public interface VariableAsFunctionMutableResolvedCall : VariableAsFunctionResolvedCall {
override val functionCall: MutableResolvedCall<FunctionDescriptor>
override val variableCall: MutableResolvedCall<VariableDescriptor>
}
class VariableAsFunctionResolvedCallImpl( class VariableAsFunctionResolvedCallImpl(
override val functionCall: MutableResolvedCall<FunctionDescriptor>, override val functionCall: MutableResolvedCall<FunctionDescriptor>,
override val variableCall: MutableResolvedCall<VariableDescriptor> override val variableCall: MutableResolvedCall<VariableDescriptor>
) : VariableAsFunctionResolvedCall, MutableResolvedCall<FunctionDescriptor> by functionCall { ) : VariableAsFunctionMutableResolvedCall, MutableResolvedCall<FunctionDescriptor> by functionCall {
override fun markCallAsCompleted() { override fun markCallAsCompleted() {
functionCall.markCallAsCompleted() functionCall.markCallAsCompleted()
@@ -0,0 +1,101 @@
/*
* 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.results
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.types.BoundsSubstitutor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constructor(
val resolvedCall: MutableResolvedCall<D>,
private val argumentsToParameters: Map<K, ValueParameterDescriptor>,
val parametersWithDefaultValuesCount: Int
) {
override fun toString(): String =
"${resolvedCall.call}: $parametersWithDefaultValuesCount defaults in ${resolvedCall.candidateDescriptor}"
val resultingDescriptor: D
get() = resolvedCall.resultingDescriptor
val argumentsCount: Int
get() = argumentsToParameters.size
val argumentKeys: Collection<K>
get() = argumentsToParameters.keys
val callElement: KtElement
get() = resolvedCall.call.callElement
val isGeneric: Boolean = resolvedCall.resultingDescriptor.original.typeParameters.isNotEmpty()
private val upperBoundsSubstitutor =
BoundsSubstitutor.createUpperBoundsSubstitutor(resolvedCall.resultingDescriptor)
fun getExtensionReceiverType(substituteUpperBounds: Boolean): KotlinType? =
resultingDescriptor.extensionReceiverParameter?.type?.let {
extensionReceiverType ->
if (substituteUpperBounds)
upperBoundsSubstitutor.substitute(extensionReceiverType, Variance.INVARIANT)
else
extensionReceiverType
}
/**
* Returns the type of a value that can be used in place of the corresponding parameter.
*/
fun getValueParameterType(argumentKey: K, substituteUpperBounds: Boolean): KotlinType? =
argumentsToParameters[argumentKey]?.let {
valueParameterDescriptor ->
val valueParameterType = valueParameterDescriptor.varargElementType ?: valueParameterDescriptor.type
if (substituteUpperBounds)
upperBoundsSubstitutor.substitute(valueParameterType, Variance.INVARIANT)
else
valueParameterType
}
companion object {
fun <D : CallableDescriptor, K> create(
call: MutableResolvedCall<D>,
resolvedArgumentToKeys: (ResolvedValueArgument) -> Collection<K>
): CandidateCallWithArgumentMapping<D, K> {
val argumentsToParameters = hashMapOf<K, ValueParameterDescriptor>()
var parametersWithDefaultValuesCount = 0
for ((valueParameterDescriptor, resolvedValueArgument) in call.valueArguments.entries) {
if (resolvedValueArgument is DefaultValueArgument) {
parametersWithDefaultValuesCount++
}
else {
val keys = resolvedArgumentToKeys(resolvedValueArgument)
for (argumentKey in keys) {
argumentsToParameters[argumentKey] = valueParameterDescriptor
}
}
}
return CandidateCallWithArgumentMapping(call, argumentsToParameters, parametersWithDefaultValuesCount)
}
}
}
@@ -22,12 +22,18 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ScriptDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.OverrideResolver import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionMutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Specificity
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.getSpecificityRelationTo
import org.jetbrains.kotlin.utils.addToStdlib.check
class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
@@ -35,203 +41,233 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
candidates: Set<MutableResolvedCall<D>>, candidates: Set<MutableResolvedCall<D>>,
discriminateGenericDescriptors: Boolean, discriminateGenericDescriptors: Boolean,
checkArgumentsMode: CheckArgumentTypesMode checkArgumentsMode: CheckArgumentTypesMode
): MutableResolvedCall<D>? { ): MutableResolvedCall<D>? =
// Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects if (candidates.size <= 1)
candidates.firstOrNull()
val maximallySpecific = THashSet(object : TObjectHashingStrategy<MutableResolvedCall<D>> { else when (checkArgumentsMode) {
override fun equals(call1: MutableResolvedCall<D>?, call2: MutableResolvedCall<D>?): Boolean = CheckArgumentTypesMode.CHECK_CALLABLE_TYPE ->
if (call1 == null) call2 == null uniquifyCandidatesSet(candidates).filter {
else call1.resultingDescriptor == call2!!.resultingDescriptor isMaxSpecific(it, candidates) {
call1, call2 ->
isNotLessSpecificCallableReference(call1.resultingDescriptor, call2.resultingDescriptor)
}
}.singleOrNull()
override fun computeHashCode(call: MutableResolvedCall<D>?): Int = CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
call?.resultingDescriptor?.hashCode() ?: 0 findMaximallySpecificCall(candidates, discriminateGenericDescriptors)
}) }
candidates.filterTo(maximallySpecific) { fun <D : CallableDescriptor> findMaximallySpecificVariableAsFunctionCalls(
isMaximallySpecific(it, candidates, discriminateGenericDescriptors, checkArgumentsMode) candidates: Set<MutableResolvedCall<D>>,
discriminateGenericDescriptors: Boolean
): Set<MutableResolvedCall<D>> {
val variableCalls = candidates.mapTo(newResolvedCallSet<MutableResolvedCall<VariableDescriptor>>(candidates.size)) {
if (it is VariableAsFunctionMutableResolvedCall)
it.variableCall
else
throw AssertionError("Regular call among variable-as-function calls: $it")
} }
return if (maximallySpecific.size == 1) maximallySpecific.first() else null val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, discriminateGenericDescriptors) ?: return emptySet()
return candidates.filterTo(newResolvedCallSet<MutableResolvedCall<D>>(2)) {
it.resultingVariableDescriptor == maxSpecificVariableCall.resultingDescriptor
}
} }
private fun <D : CallableDescriptor> isMaximallySpecific( private fun <D : CallableDescriptor> findMaximallySpecificCall(
candidateCall: MutableResolvedCall<D>,
candidates: Set<MutableResolvedCall<D>>, candidates: Set<MutableResolvedCall<D>>,
discriminateGenericDescriptors: Boolean, discriminateGenericDescriptors: Boolean
checkArgumentsMode: CheckArgumentTypesMode): Boolean { ): MutableResolvedCall<D>? {
val me = candidateCall.resultingDescriptor val filteredCandidates = uniquifyCandidatesSet(candidates)
val isInvoke = candidateCall is VariableAsFunctionResolvedCall if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
val variable = (candidateCall as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor
for (otherCall in candidates) { val conflictingCandidates = filteredCandidates.map {
val other = otherCall.resultingDescriptor candidateCall ->
if (other === me) continue CandidateCallWithArgumentMapping.create(candidateCall) { it.arguments.filter { it.getArgumentExpression() != null } }
}
if (definitelyNotMaximallySpecific(me, other, discriminateGenericDescriptors, checkArgumentsMode)) { val (varargCandidates, regularCandidates) = conflictingCandidates.partition { it.resultingDescriptor.hasVarargs }
if (!isInvoke) return false val mostSpecificRegularCandidates = regularCandidates.selectMostSpecificCallsWithArgumentMapping(discriminateGenericDescriptors)
assert(otherCall is VariableAsFunctionResolvedCall) { "'invoke' candidate goes with usual one: " + candidateCall + otherCall } return when {
mostSpecificRegularCandidates.size > 1 ->
null
mostSpecificRegularCandidates.size == 1 ->
mostSpecificRegularCandidates.single()
else ->
varargCandidates.selectMostSpecificCallsWithArgumentMapping(discriminateGenericDescriptors).singleOrNull()
}
}
val otherVariableCall = (otherCall as VariableAsFunctionResolvedCall).variableCall private fun <D : CallableDescriptor, K> Collection<CandidateCallWithArgumentMapping<D, K>>.selectMostSpecificCallsWithArgumentMapping(
if (definitelyNotMaximallySpecific(variable!!, otherVariableCall.resultingDescriptor, discriminateGenericDescriptors, checkArgumentsMode)) { discriminateGenericDescriptors: Boolean
return false ): Collection<MutableResolvedCall<D>> =
} this.mapNotNull {
candidate ->
candidate.check {
isMaxSpecific(candidate, this) {
call1, call2 ->
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenericDescriptors)
}
}?.resolvedCall
} }
private inline fun <C> isMaxSpecific(
candidate: C,
candidates: Collection<C>,
isNotLessSpecific: (C, C) -> Boolean
): Boolean =
candidates.all {
other ->
candidate === other ||
isNotLessSpecific(candidate, other) && !isNotLessSpecific(other, candidate)
}
/**
* `call1` is not less specific than `call2`
*/
private fun <D : CallableDescriptor, K> isNotLessSpecificCallWithArgumentMapping(
call1: CandidateCallWithArgumentMapping<D, K>,
call2: CandidateCallWithArgumentMapping<D, K>,
discriminateGenericDescriptors: Boolean
): Boolean {
return tryCompareDescriptorsFromScripts(call1.resultingDescriptor, call2.resultingDescriptor) ?:
compareCallsWithArgumentMapping(call1, call2, discriminateGenericDescriptors)
}
/**
* Returns `true` if `d1` is definitely not less specific than `d2`,
* `false` if `d1` is definitely less specific than `d2` or undecided.
*/
private fun <D : CallableDescriptor, K> compareCallsWithArgumentMapping(
call1: CandidateCallWithArgumentMapping<D, K>,
call2: CandidateCallWithArgumentMapping<D, K>,
discriminateGenericDescriptors: Boolean
): Boolean {
val substituteParameterTypes =
if (discriminateGenericDescriptors) {
if (!call1.isGeneric && call2.isGeneric) return true
if (call1.isGeneric && !call2.isGeneric) return false
call1.isGeneric && call2.isGeneric
}
else false
val extensionReceiverType1 = call1.getExtensionReceiverType(substituteParameterTypes)
val extensionReceiverType2 = call2.getExtensionReceiverType(substituteParameterTypes)
tryCompareExtensionReceiverType(extensionReceiverType1, extensionReceiverType2)?.let {
return it
}
assert(call1.argumentsCount == call2.argumentsCount) {
"$call1 and $call2 have different number of explicit arguments"
}
for (argumentKey in call1.argumentKeys) {
val type1 = call1.getValueParameterType(argumentKey, substituteParameterTypes) ?: continue
val type2 = call2.getValueParameterType(argumentKey, substituteParameterTypes) ?: continue
if (!typeNotLessSpecific(type1, type2)) {
return false
}
}
if (call1.parametersWithDefaultValuesCount > call2.parametersWithDefaultValuesCount) {
return false
} }
return true return true
} }
private fun <D : CallableDescriptor> definitelyNotMaximallySpecific( /**
me: D, * Returns `true` if `d1` is definitely not less specific than `d2`,
other: D, * `false` if `d1` is definitely less specific than `d2`,
discriminateGenericDescriptors: Boolean, * `null` if undecided.
checkArgumentsMode: CheckArgumentTypesMode): Boolean { */
return !moreSpecific(me, other, discriminateGenericDescriptors, checkArgumentsMode) || private fun tryCompareDescriptorsFromScripts(d1: CallableDescriptor, d2: CallableDescriptor): Boolean? {
moreSpecific(other, me, discriminateGenericDescriptors, checkArgumentsMode) val containingDeclaration1 = d1.containingDeclaration
val containingDeclaration2 = d2.containingDeclaration
if (containingDeclaration1 is ScriptDescriptor && containingDeclaration2 is ScriptDescriptor) {
when {
containingDeclaration1.priority > containingDeclaration2.priority -> return true
containingDeclaration1.priority < containingDeclaration2.priority -> return false
}
}
return null
} }
/** /**
* Let < mean "more specific" * Returns `false` if `d1` is definitely less specific than `d2`,
* Subtype < supertype * `null` if undecided.
* Double < Float
* Int < Long
* Int < Short < Byte
*/ */
private fun <Descriptor : CallableDescriptor> moreSpecific( private fun tryCompareExtensionReceiverType(type1: KotlinType?, type2: KotlinType?): Boolean? {
f: Descriptor, if (type1 != null && type2 != null) {
g: Descriptor, if (!typeNotLessSpecific(type1, type2))
discriminateGenericDescriptors: Boolean, return false
checkArgumentsMode: CheckArgumentTypesMode): Boolean {
val resolvingCallableReference = checkArgumentsMode == CheckArgumentTypesMode.CHECK_CALLABLE_TYPE
if (f.containingDeclaration is ScriptDescriptor && g.containingDeclaration is ScriptDescriptor) {
val fs = f.containingDeclaration as ScriptDescriptor
val gs = g.containingDeclaration as ScriptDescriptor
if (fs.priority != gs.priority) {
return fs.priority > gs.priority
}
}
val isGenericF = isGeneric(f)
val isGenericG = isGeneric(g)
if (discriminateGenericDescriptors) {
if (!isGenericF && isGenericG) return true
if (isGenericF && !isGenericG) return false
if (isGenericF && isGenericG) {
return moreSpecific(BoundsSubstitutor.substituteBounds(f),
BoundsSubstitutor.substituteBounds(g),
false, checkArgumentsMode)
}
}
if (OverrideResolver.overrides(f, g)) return true
if (OverrideResolver.overrides(g, f)) return false
val receiverOfF = f.extensionReceiverParameter
val receiverOfG = g.extensionReceiverParameter
if (receiverOfF != null && receiverOfG != null) {
if (!typeMoreSpecific(receiverOfF.type, receiverOfG.type)) return false
} }
return null
}
/**
* Returns `true` if `d1` is definitely not less specific than `d2`,
* `false` if `d1` is definitely less specific than `d2`,
* `null` if undecided.
*/
private fun compareFunctionParameterTypes(f: CallableDescriptor, g: CallableDescriptor): Boolean {
val fParams = f.valueParameters val fParams = f.valueParameters
val gParams = g.valueParameters val gParams = g.valueParameters
val fSize = fParams.size val fSize = fParams.size
val gSize = gParams.size val gSize = gParams.size
val fIsVararg = isVariableArity(fParams) if (fSize != gSize) return false
val gIsVararg = isVariableArity(gParams)
if (resolvingCallableReference && fIsVararg != gIsVararg) return false for (i in 0..fSize - 1) {
if (!fIsVararg && gIsVararg) return true val fParam = fParams[i]
if (fIsVararg && !gIsVararg) return false val gParam = gParams[i]
if (!fIsVararg && !gIsVararg) { val fParamIsVararg = fParam.varargElementType != null
if (resolvingCallableReference && fSize != gSize) return false val gParamIsVararg = gParam.varargElementType != null
if (!resolvingCallableReference && fSize > gSize) return false
for (i in 0..fSize - 1) { if (fParamIsVararg != gParamIsVararg) {
val fParam = fParams[i] return false
val gParam = gParams[i]
val fParamType = fParam.type
val gParamType = gParam.type
if (!typeMoreSpecific(fParamType, gParamType)) {
return false
}
}
}
if (fIsVararg && gIsVararg) {
// Check matching parameters
val minSize = Math.min(fSize, gSize)
for (i in 0..minSize - 1 - 1) {
val fParam = fParams[i]
val gParam = gParams[i]
val fParamType = fParam.type
val gParamType = gParam.type
if (!typeMoreSpecific(fParamType, gParamType)) {
return false
}
} }
// Check the non-matching parameters of one function against the vararg parameter of the other function val fParamType = getVarargElementTypeOrType(fParam)
// Example: val gParamType = getVarargElementTypeOrType(gParam)
// f(vararg vf : T)
// g(a : A, vararg vg : T) if (!typeNotLessSpecific(fParamType, gParamType)) {
// here we check that typeOf(a) < elementTypeOf(vf) and elementTypeOf(vg) < elementTypeOf(vf) return false
if (fSize < gSize) {
val fParam = fParams[fSize - 1]
val fParamType = fParam.varargElementType
assert(fParamType != null) { "fIsVararg guarantees this" }
for (i in fSize - 1..gSize - 1) {
val gParam = gParams[i]
if (!typeMoreSpecific(fParamType!!, getVarargElementTypeOrType(gParam))) {
return false
}
}
}
else {
val gParam = gParams[gSize - 1]
val gParamType = gParam.varargElementType
assert(gParamType != null) { "gIsVararg guarantees this" }
for (i in gSize - 1..fSize - 1) {
val fParam = fParams[i]
if (!typeMoreSpecific(getVarargElementTypeOrType(fParam), gParamType!!)) {
return false
}
}
} }
} }
return true return true
} }
private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean =
// TODO should we "discriminate generic descriptors" for callable references?
tryCompareDescriptorsFromScripts(f, g) ?:
// TODO compare functional types for 'f' and 'g'
tryCompareExtensionReceiverType(f.extensionReceiverType, g.extensionReceiverType) ?:
compareFunctionParameterTypes(f, g)
private fun getVarargElementTypeOrType(parameterDescriptor: ValueParameterDescriptor): KotlinType = private fun getVarargElementTypeOrType(parameterDescriptor: ValueParameterDescriptor): KotlinType =
parameterDescriptor.varargElementType ?: parameterDescriptor.type parameterDescriptor.varargElementType ?: parameterDescriptor.type
private fun isVariableArity(fParams: List<ValueParameterDescriptor>): Boolean = private val CallableDescriptor.hasVarargs: Boolean get() =
fParams.lastOrNull()?.varargElementType != null this.valueParameters.any { it.varargElementType != null }
private fun isGeneric(f: CallableDescriptor): Boolean = private fun typeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
f.original.typeParameters.isNotEmpty()
private fun typeMoreSpecific(specific: KotlinType, general: KotlinType): Boolean {
val isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general) val isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general)
if (!isSubtype) return false if (!isSubtype) return false
val sThanG = specific.getSpecificityRelationTo(general) val sThanG = specific.getSpecificityRelationTo(general)
val gThanS = general.getSpecificityRelationTo(specific) val gThanS = general.getSpecificityRelationTo(specific)
if (sThanG === Specificity.Relation.LESS_SPECIFIC && if (sThanG == Specificity.Relation.LESS_SPECIFIC &&
gThanS !== Specificity.Relation.LESS_SPECIFIC) { gThanS != Specificity.Relation.LESS_SPECIFIC) {
return false return false
} }
@@ -261,4 +297,37 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
return false return false
} }
private val CallableDescriptor.extensionReceiverType: KotlinType?
get() = extensionReceiverParameter?.type
companion object {
// Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
@Suppress("CAST_NEVER_SUCCEEDS")
private fun <D : CallableDescriptor> uniquifyCandidatesSet(candidates: Collection<MutableResolvedCall<D>>): Set<MutableResolvedCall<D>> =
THashSet<MutableResolvedCall<D>>(candidates.size, getCallHashingStrategy<MutableResolvedCall<D>>()).apply { addAll(candidates) }
@Suppress("CAST_NEVER_SUCCEEDS")
private fun <C> newResolvedCallSet(expectedSize: Int): MutableSet<C> =
THashSet<C>(expectedSize, getCallHashingStrategy<C>())
private object ResolvedCallHashingStrategy : TObjectHashingStrategy<ResolvedCall<*>> {
override fun equals(call1: ResolvedCall<*>?, call2: ResolvedCall<*>?): Boolean =
if (call1 != null && call2 != null)
call1.resultingDescriptor == call2.resultingDescriptor
else
call1 == call2
override fun computeHashCode(call: ResolvedCall<*>?): Int =
call?.resultingDescriptor?.hashCode() ?: 0
}
private val MutableResolvedCall<*>.resultingVariableDescriptor: VariableDescriptor
get() = (this as VariableAsFunctionResolvedCall).variableCall.resultingDescriptor
@Suppress("UNCHECKED_CAST", "CAST_NEVER_SUCCEEDS")
private fun <C> getCallHashingStrategy() =
ResolvedCallHashingStrategy as TObjectHashingStrategy<C>
}
} }
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext; import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode; import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy; import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import java.util.Collection; import java.util.Collection;
@@ -193,6 +194,10 @@ public class ResolutionResultsHandler {
return OverloadResolutionResultsImpl.success(candidates.iterator().next()); return OverloadResolutionResultsImpl.success(candidates.iterator().next());
} }
if (candidates.iterator().next() instanceof VariableAsFunctionResolvedCall) {
candidates = overloadingConflictResolver.findMaximallySpecificVariableAsFunctionCalls(candidates, discriminateGenerics);
}
Set<MutableResolvedCall<D>> noOverrides = OverrideResolver.filterOutOverridden(candidates, MAP_TO_RESULT); Set<MutableResolvedCall<D>> noOverrides = OverrideResolver.filterOutOverridden(candidates, MAP_TO_RESULT);
if (noOverrides.size() == 1) { if (noOverrides.size() == 1) {
return OverloadResolutionResultsImpl.success(noOverrides.iterator().next()); return OverloadResolutionResultsImpl.success(noOverrides.iterator().next());
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.types;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
@@ -53,6 +54,11 @@ public class BoundsSubstitutor {
return substitutedFunction; return substitutedFunction;
} }
@NotNull
public static <D extends CallableDescriptor> TypeSubstitutor createUpperBoundsSubstitutor(@NotNull D callableDescriptor) {
return createUpperBoundsSubstitutor(callableDescriptor.getTypeParameters());
}
@NotNull @NotNull
private static TypeSubstitutor createUpperBoundsSubstitutor(@NotNull List<TypeParameterDescriptor> typeParameters) { private static TypeSubstitutor createUpperBoundsSubstitutor(@NotNull List<TypeParameterDescriptor> typeParameters) {
Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>(); Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>();
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object Right
object Wrong
interface IA
interface IB : IA
fun IA.foo(vararg x: Int) = Wrong
fun IB.foo(vararg x: Int) = Right
class CC : IB
val test7 = CC().foo(1, 2, 3)
@@ -0,0 +1,38 @@
package
public val test7: Right
public fun IA.foo(/*0*/ vararg x: kotlin.Int /*kotlin.IntArray*/): Wrong
public fun IB.foo(/*0*/ vararg x: kotlin.Int /*kotlin.IntArray*/): Right
public final class CC : IB {
public constructor CC()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface IA {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface IB : IA {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Right {
private constructor Right()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Wrong {
private constructor Wrong()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,21 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: J.java
import java.util.*
public class J {
public static <E extends Enum<E>> String foo(E e) { return ""; }
public static <E extends Enum<E>> String foo(E e1, E e2) { return ""; }
public static <E extends Enum<E>> String foo(E s1, E s2, E s3) { return ""; }
public static <E extends Enum<E>> int foo(E... ss) { return 0; }
}
// FILE: test.kt
enum class X { A }
val a = X.A
val test0: Int = J.foo<X>()
val test1: String = J.foo(a)
val test2: String = J.foo(a, a)
val test3: String = J.foo(a, a, a)
val test4: Int = J.foo(a, a, a, a)
val test5: Int = J.foo(a, a, a, a, a)
@@ -0,0 +1,40 @@
package
public val a: X
public val test0: kotlin.Int
public val test1: kotlin.String
public val test2: kotlin.String
public val test3: kotlin.String
public val test4: kotlin.Int
public val test5: kotlin.Int
public open class J {
public constructor J()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ E : kotlin.Enum<E!>!> foo(/*0*/ e: E!): kotlin.String!
public open fun </*0*/ E : kotlin.Enum<E!>!> foo(/*0*/ e1: E!, /*1*/ e2: E!): kotlin.String!
public open fun </*0*/ E : kotlin.Enum<E!>!> foo(/*0*/ s1: E!, /*1*/ s2: E!, /*2*/ s3: E!): kotlin.String!
public open fun </*0*/ E : kotlin.Enum<E!>!> foo(/*0*/ vararg ss: E! /*kotlin.Array<(out) E!>!*/): kotlin.Int
}
public final enum class X : kotlin.Enum<X> {
enum entry A
private constructor X()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: X): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
@kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Use 'values()' function instead", replaceWith = kotlin.ReplaceWith(expression = "this.values()", imports = {})) public final /*synthesized*/ val values: kotlin.Array<X>
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): X
public final /*synthesized*/ fun values(): kotlin.Array<X>
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object Right
object Wrong
fun overloadedFun(c: Any = "", b: String = "", f: Any = "") = Right
fun overloadedFun(b: Any = "", c: Any = "", e: String = "", x: String = "", y: String = "") = Wrong
val test: Right = overloadedFun(b = "")
@@ -0,0 +1,19 @@
package
public val test: Right
public fun overloadedFun(/*0*/ b: kotlin.Any = ..., /*1*/ c: kotlin.Any = ..., /*2*/ e: kotlin.String = ..., /*3*/ x: kotlin.String = ..., /*4*/ y: kotlin.String = ...): Wrong
public fun overloadedFun(/*0*/ c: kotlin.Any = ..., /*1*/ b: kotlin.String = ..., /*2*/ f: kotlin.Any = ...): Right
public object Right {
private constructor Right()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Wrong {
private constructor Wrong()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,20 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object Right
object Wrong
fun overloadedFun1(c: Any = "", b: String = "", f: Any = "") = Right
fun overloadedFun1(b: Any = "", c: Any = "", e: String = "") = Wrong
val test1: Right = overloadedFun1(b = "")
val test1a: Wrong = <!TYPE_MISMATCH!>overloadedFun1(b = "")<!>
fun overloadedFun2(a: String, b: Any = "") = Right
fun overloadedFun2(a: Any, b: String = "") = Wrong
val test2: Right = overloadedFun2("")
fun overloadedFun2a(a: Any, b: String = "") = Wrong
fun overloadedFun2a(a: String, b: Any = "") = Right
val test2a: Right = overloadedFun2a("")
@@ -0,0 +1,26 @@
package
public val test1: Right
public val test1a: Wrong
public val test2: Right
public val test2a: Right
public fun overloadedFun1(/*0*/ b: kotlin.Any = ..., /*1*/ c: kotlin.Any = ..., /*2*/ e: kotlin.String = ...): Wrong
public fun overloadedFun1(/*0*/ c: kotlin.Any = ..., /*1*/ b: kotlin.String = ..., /*2*/ f: kotlin.Any = ...): Right
public fun overloadedFun2(/*0*/ a: kotlin.Any, /*1*/ b: kotlin.String = ...): Wrong
public fun overloadedFun2(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Any = ...): Right
public fun overloadedFun2a(/*0*/ a: kotlin.Any, /*1*/ b: kotlin.String = ...): Wrong
public fun overloadedFun2a(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Any = ...): Right
public object Right {
private constructor Right()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Wrong {
private constructor Wrong()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object Right
object Wrong
fun overloadedFun6(s1: String) = Right
fun overloadedFun6(s1: String, s2: String) = Wrong
fun overloadedFun6(s1: String, s2: String, s3: String) = Wrong
fun overloadedFun6(s: String, vararg ss: String) = Wrong
val test6: Right = overloadedFun6("")
@@ -0,0 +1,21 @@
package
public val test6: Right
public fun overloadedFun6(/*0*/ s1: kotlin.String): Right
public fun overloadedFun6(/*0*/ s: kotlin.String, /*1*/ vararg ss: kotlin.String /*kotlin.Array<out kotlin.String>*/): Wrong
public fun overloadedFun6(/*0*/ s1: kotlin.String, /*1*/ s2: kotlin.String): Wrong
public fun overloadedFun6(/*0*/ s1: kotlin.String, /*1*/ s2: kotlin.String, /*2*/ s3: kotlin.String): Wrong
public object Right {
private constructor Right()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Wrong {
private constructor Wrong()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object X1
object X2
fun overloadedFun(arg: String, vararg args: String) = X1
fun overloadedFun(arg: String, vararg args: String, flag: Boolean = true) = X2
val test1a: X1 = overloadedFun("", "")
val test1b: X1 = overloadedFun("", args = "")
val test1c: X2 = overloadedFun("", "", "", flag = true)
@@ -0,0 +1,21 @@
package
public val test1a: X1
public val test1b: X1
public val test1c: X2
public fun overloadedFun(/*0*/ arg: kotlin.String, /*1*/ vararg args: kotlin.String /*kotlin.Array<out kotlin.String>*/): X1
public fun overloadedFun(/*0*/ arg: kotlin.String, /*1*/ vararg args: kotlin.String /*kotlin.Array<out kotlin.String>*/, /*2*/ flag: kotlin.Boolean = ...): X2
public object X1 {
private constructor X1()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object X2 {
private constructor X2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object X1
object X2
fun overloadedFun5(vararg ss: String) = X1
fun overloadedFun5(s: String, vararg ss: String) = X2
val test1: X1 = <!OVERLOAD_RESOLUTION_AMBIGUITY!>overloadedFun5<!>("")
val test2 = <!OVERLOAD_RESOLUTION_AMBIGUITY!>overloadedFun5<!>("", "")
val test3: X2 = overloadedFun5(s = "", ss = "")
val test4: X1 = overloadedFun5(ss = "")
@@ -0,0 +1,22 @@
package
public val test1: X1
public val test2: [ERROR : Type for overloadedFun5("", "")]
public val test3: X2
public val test4: X1
public fun overloadedFun5(/*0*/ vararg ss: kotlin.String /*kotlin.Array<out kotlin.String>*/): X1
public fun overloadedFun5(/*0*/ s: kotlin.String, /*1*/ vararg ss: kotlin.String /*kotlin.Array<out kotlin.String>*/): X2
public object X1 {
private constructor X1()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object X2 {
private constructor X2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -13731,6 +13731,57 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
} }
} }
@TestMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class OverloadConflicts extends AbstractDiagnosticsTest {
public void testAllFilesPresentInOverloadConflicts() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/resolve/overloadConflicts"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("extensionReceiverAndVarargs.kt")
public void testExtensionReceiverAndVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt");
doTest(fileName);
}
@TestMetadata("javaOverloadedVarargs.kt")
public void testJavaOverloadedVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.kt");
doTest(fileName);
}
@TestMetadata("numberOfDefaults.kt")
public void testNumberOfDefaults() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.kt");
doTest(fileName);
}
@TestMetadata("originalExamples.kt")
public void testOriginalExamples() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.kt");
doTest(fileName);
}
@TestMetadata("varargs.kt")
public void testVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.kt");
doTest(fileName);
}
@TestMetadata("varargsInDifferentPositions.kt")
public void testVarargsInDifferentPositions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.kt");
doTest(fileName);
}
@TestMetadata("varargsMixed.kt")
public void testVarargsMixed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/resolve/specialConstructions") @TestMetadata("compiler/testData/diagnostics/tests/resolve/specialConstructions")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -16,23 +16,23 @@
package org.jetbrains.kotlin.test.util package org.jetbrains.kotlin.test.util
import com.intellij.codeInspection.SmartHashMap
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import com.intellij.util.SmartFMap import com.intellij.util.SmartFMap
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtPackageDirective
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
import java.io.File import java.io.File
import java.util.*
public fun String.trimTrailingWhitespacesAndAddNewlineAtEOF(): String = public fun String.trimTrailingWhitespacesAndAddNewlineAtEOF(): String =
this.split('\n').map { it.trimEnd() }.joinToString(separator = "\n").let { this.split('\n').map { it.trimEnd() }.joinToString(separator = "\n").let {
result -> if (result.endsWith("\n")) result else result + "\n" result -> if (result.endsWith("\n")) result else result + "\n"
} }
public fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraNameParts: String) { public fun CodeInsightTestFixture.configureWithExtraFileAbs(path: String, vararg extraNameParts: String) {
configureWithExtraFile(path, *extraNameParts) configureWithExtraFile(path, *extraNameParts, relativePaths = false)
} }
public fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraNameParts: String = arrayOf(".Data"), relativePaths: Boolean = false) { public fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraNameParts: String = arrayOf(".Data"), relativePaths: Boolean = false) {
@@ -34,7 +34,7 @@ import java.util.List;
public abstract class AbstractQuickDocProviderTest extends KotlinLightCodeInsightFixtureTestCase { public abstract class AbstractQuickDocProviderTest extends KotlinLightCodeInsightFixtureTestCase {
public void doTest(@NotNull String path) throws Exception { public void doTest(@NotNull String path) throws Exception {
JetTestUtilsKt.configureWithExtraFile(myFixture, path, "_Data"); JetTestUtilsKt.configureWithExtraFileAbs(myFixture, path, "_Data");
PsiElement element = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()); PsiElement element = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset());
assertNotNull("Can't find element at caret in file: " + path, element); assertNotNull("Can't find element at caret in file: " + path, element);
@@ -17,22 +17,18 @@
package org.jetbrains.kotlin.idea.resolve package org.jetbrains.kotlin.idea.resolve
import com.google.common.collect.Lists import com.google.common.collect.Lists
import com.google.common.collect.Ordering
import com.intellij.psi.PsiPolyVariantReference import com.intellij.psi.PsiPolyVariantReference
import com.intellij.psi.PsiReference import com.intellij.psi.PsiReference
import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.PathUtil import com.intellij.util.PathUtil
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinLightPlatformCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinLightPlatformCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.ReferenceUtils import org.jetbrains.kotlin.test.ReferenceUtils
import org.jetbrains.kotlin.test.util.configureWithExtraFile import org.jetbrains.kotlin.test.util.configureWithExtraFile
import org.junit.Assert import org.junit.Assert
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
public abstract class AbstractReferenceResolveTest : KotlinLightPlatformCodeInsightFixtureTestCase() { public abstract class AbstractReferenceResolveTest : KotlinLightPlatformCodeInsightFixtureTestCase() {
@@ -16,21 +16,20 @@
package org.jetbrains.kotlin.idea.structureView package org.jetbrains.kotlin.idea.structureView
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import com.intellij.util.ui.tree.TreeUtil
import com.intellij.openapi.util.io.FileUtil
import java.io.File
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure
import com.intellij.ide.util.FileStructurePopup
import com.intellij.ide.actions.ViewStructureAction import com.intellij.ide.actions.ViewStructureAction
import com.intellij.ide.util.FileStructurePopup
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import com.intellij.openapi.ui.Queryable.PrintInfo import com.intellij.openapi.ui.Queryable.PrintInfo
import com.intellij.testFramework.LightProjectDescriptor import com.intellij.openapi.util.io.FileUtil
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure
import com.intellij.util.ui.tree.TreeUtil
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.configureWithExtraFile import org.jetbrains.kotlin.test.util.configureWithExtraFile
import java.io.File
public abstract class AbstractKotlinFileStructureTest : KotlinLightCodeInsightFixtureTestCase() { public abstract class AbstractKotlinFileStructureTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/structureView/fileStructure" override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/structureView/fileStructure"