diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/VariableAsFunctionResolvedCall.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/VariableAsFunctionResolvedCall.kt index 760e93356f7..ba220375959 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/VariableAsFunctionResolvedCall.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/VariableAsFunctionResolvedCall.kt @@ -27,10 +27,15 @@ public interface VariableAsFunctionResolvedCall { public val variableCall: ResolvedCall } +public interface VariableAsFunctionMutableResolvedCall : VariableAsFunctionResolvedCall { + override val functionCall: MutableResolvedCall + override val variableCall: MutableResolvedCall +} + class VariableAsFunctionResolvedCallImpl( override val functionCall: MutableResolvedCall, override val variableCall: MutableResolvedCall -) : VariableAsFunctionResolvedCall, MutableResolvedCall by functionCall { +) : VariableAsFunctionMutableResolvedCall, MutableResolvedCall by functionCall { override fun markCallAsCompleted() { functionCall.markCallAsCompleted() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/CandidateCallWithArgumentMapping.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/CandidateCallWithArgumentMapping.kt new file mode 100644 index 00000000000..75156c1d772 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/CandidateCallWithArgumentMapping.kt @@ -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 private constructor( + val resolvedCall: MutableResolvedCall, + private val argumentsToParameters: Map, + 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 + 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 create( + call: MutableResolvedCall, + resolvedArgumentToKeys: (ResolvedValueArgument) -> Collection + ): CandidateCallWithArgumentMapping { + val argumentsToParameters = hashMapOf() + 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) + } + } +} + diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt index d19d2916a94..312f8af24f8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt @@ -22,12 +22,18 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor 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.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.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.getSpecificityRelationTo +import org.jetbrains.kotlin.utils.addToStdlib.check class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { @@ -35,203 +41,233 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { candidates: Set>, discriminateGenericDescriptors: Boolean, checkArgumentsMode: CheckArgumentTypesMode - ): MutableResolvedCall? { - // Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects - - val maximallySpecific = THashSet(object : TObjectHashingStrategy> { - override fun equals(call1: MutableResolvedCall?, call2: MutableResolvedCall?): Boolean = - if (call1 == null) call2 == null - else call1.resultingDescriptor == call2!!.resultingDescriptor + ): MutableResolvedCall? = + if (candidates.size <= 1) + candidates.firstOrNull() + else when (checkArgumentsMode) { + CheckArgumentTypesMode.CHECK_CALLABLE_TYPE -> + uniquifyCandidatesSet(candidates).filter { + isMaxSpecific(it, candidates) { + call1, call2 -> + isNotLessSpecificCallableReference(call1.resultingDescriptor, call2.resultingDescriptor) + } + }.singleOrNull() - override fun computeHashCode(call: MutableResolvedCall?): Int = - call?.resultingDescriptor?.hashCode() ?: 0 - }) - - candidates.filterTo(maximallySpecific) { - isMaximallySpecific(it, candidates, discriminateGenericDescriptors, checkArgumentsMode) + CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS -> + findMaximallySpecificCall(candidates, discriminateGenericDescriptors) + } + + fun findMaximallySpecificVariableAsFunctionCalls( + candidates: Set>, + discriminateGenericDescriptors: Boolean + ): Set> { + val variableCalls = candidates.mapTo(newResolvedCallSet>(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>(2)) { + it.resultingVariableDescriptor == maxSpecificVariableCall.resultingDescriptor + } } - private fun isMaximallySpecific( - candidateCall: MutableResolvedCall, + private fun findMaximallySpecificCall( candidates: Set>, - discriminateGenericDescriptors: Boolean, - checkArgumentsMode: CheckArgumentTypesMode): Boolean { - val me = candidateCall.resultingDescriptor + discriminateGenericDescriptors: Boolean + ): MutableResolvedCall? { + val filteredCandidates = uniquifyCandidatesSet(candidates) - val isInvoke = candidateCall is VariableAsFunctionResolvedCall - val variable = (candidateCall as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor + if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull() - for (otherCall in candidates) { - val other = otherCall.resultingDescriptor - if (other === me) continue + val conflictingCandidates = filteredCandidates.map { + candidateCall -> + CandidateCallWithArgumentMapping.create(candidateCall) { it.arguments.filter { it.getArgumentExpression() != null } } + } - if (definitelyNotMaximallySpecific(me, other, discriminateGenericDescriptors, checkArgumentsMode)) { - if (!isInvoke) return false + val (varargCandidates, regularCandidates) = conflictingCandidates.partition { it.resultingDescriptor.hasVarargs } + 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 - if (definitelyNotMaximallySpecific(variable!!, otherVariableCall.resultingDescriptor, discriminateGenericDescriptors, checkArgumentsMode)) { - return false - } + private fun Collection>.selectMostSpecificCallsWithArgumentMapping( + discriminateGenericDescriptors: Boolean + ): Collection> = + this.mapNotNull { + candidate -> + candidate.check { + isMaxSpecific(candidate, this) { + call1, call2 -> + isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenericDescriptors) + } + }?.resolvedCall } + + private inline fun isMaxSpecific( + candidate: C, + candidates: Collection, + 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 isNotLessSpecificCallWithArgumentMapping( + call1: CandidateCallWithArgumentMapping, + call2: CandidateCallWithArgumentMapping, + 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 compareCallsWithArgumentMapping( + call1: CandidateCallWithArgumentMapping, + call2: CandidateCallWithArgumentMapping, + 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 } - private fun definitelyNotMaximallySpecific( - me: D, - other: D, - discriminateGenericDescriptors: Boolean, - checkArgumentsMode: CheckArgumentTypesMode): Boolean { - return !moreSpecific(me, other, discriminateGenericDescriptors, checkArgumentsMode) || - moreSpecific(other, me, discriminateGenericDescriptors, checkArgumentsMode) + /** + * 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 tryCompareDescriptorsFromScripts(d1: CallableDescriptor, d2: CallableDescriptor): Boolean? { + 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" - * Subtype < supertype - * Double < Float - * Int < Long - * Int < Short < Byte + * Returns `false` if `d1` is definitely less specific than `d2`, + * `null` if undecided. */ - private fun moreSpecific( - f: Descriptor, - g: Descriptor, - discriminateGenericDescriptors: Boolean, - 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 + private fun tryCompareExtensionReceiverType(type1: KotlinType?, type2: KotlinType?): Boolean? { + if (type1 != null && type2 != null) { + if (!typeNotLessSpecific(type1, type2)) + 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 gParams = g.valueParameters val fSize = fParams.size val gSize = gParams.size - val fIsVararg = isVariableArity(fParams) - val gIsVararg = isVariableArity(gParams) + if (fSize != gSize) return false - if (resolvingCallableReference && fIsVararg != gIsVararg) return false - if (!fIsVararg && gIsVararg) return true - if (fIsVararg && !gIsVararg) return false + for (i in 0..fSize - 1) { + val fParam = fParams[i] + val gParam = gParams[i] - if (!fIsVararg && !gIsVararg) { - if (resolvingCallableReference && fSize != gSize) return false - if (!resolvingCallableReference && fSize > gSize) return false + val fParamIsVararg = fParam.varargElementType != null + val gParamIsVararg = gParam.varargElementType != null - for (i in 0..fSize - 1) { - val fParam = fParams[i] - 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 - } + if (fParamIsVararg != gParamIsVararg) { + return false } - // Check the non-matching parameters of one function against the vararg parameter of the other function - // Example: - // f(vararg vf : T) - // g(a : A, vararg vg : T) - // here we check that typeOf(a) < elementTypeOf(vf) and elementTypeOf(vg) < elementTypeOf(vf) - 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 - } - } + val fParamType = getVarargElementTypeOrType(fParam) + val gParamType = getVarargElementTypeOrType(gParam) + + if (!typeNotLessSpecific(fParamType, gParamType)) { + return false } } 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 = parameterDescriptor.varargElementType ?: parameterDescriptor.type - private fun isVariableArity(fParams: List): Boolean = - fParams.lastOrNull()?.varargElementType != null + private val CallableDescriptor.hasVarargs: Boolean get() = + this.valueParameters.any { it.varargElementType != null } - private fun isGeneric(f: CallableDescriptor): Boolean = - f.original.typeParameters.isNotEmpty() - - private fun typeMoreSpecific(specific: KotlinType, general: KotlinType): Boolean { + private fun typeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean { val isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general) if (!isSubtype) return false val sThanG = specific.getSpecificityRelationTo(general) val gThanS = general.getSpecificityRelationTo(specific) - if (sThanG === Specificity.Relation.LESS_SPECIFIC && - gThanS !== Specificity.Relation.LESS_SPECIFIC) { + if (sThanG == Specificity.Relation.LESS_SPECIFIC && + gThanS != Specificity.Relation.LESS_SPECIFIC) { return false } @@ -261,4 +297,37 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { 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 uniquifyCandidatesSet(candidates: Collection>): Set> = + THashSet>(candidates.size, getCallHashingStrategy>()).apply { addAll(candidates) } + + @Suppress("CAST_NEVER_SUCCEEDS") + private fun newResolvedCallSet(expectedSize: Int): MutableSet = + THashSet(expectedSize, getCallHashingStrategy()) + + private object ResolvedCallHashingStrategy : TObjectHashingStrategy> { + 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 getCallHashingStrategy() = + ResolvedCallHashingStrategy as TObjectHashingStrategy + + } + } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java index 0d82f227cc4..c6563795763 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java @@ -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.CheckArgumentTypesMode; 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 java.util.Collection; @@ -193,6 +194,10 @@ public class ResolutionResultsHandler { return OverloadResolutionResultsImpl.success(candidates.iterator().next()); } + if (candidates.iterator().next() instanceof VariableAsFunctionResolvedCall) { + candidates = overloadingConflictResolver.findMaximallySpecificVariableAsFunctionCalls(candidates, discriminateGenerics); + } + Set> noOverrides = OverrideResolver.filterOutOverridden(candidates, MAP_TO_RESULT); if (noOverrides.size() == 1) { return OverloadResolutionResultsImpl.success(noOverrides.iterator().next()); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java index 2c892662c5d..2a37e2ca1b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.types; import com.google.common.base.Function; import com.google.common.collect.Collections2; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; @@ -53,6 +54,11 @@ public class BoundsSubstitutor { return substitutedFunction; } + @NotNull + public static TypeSubstitutor createUpperBoundsSubstitutor(@NotNull D callableDescriptor) { + return createUpperBoundsSubstitutor(callableDescriptor.getTypeParameters()); + } + @NotNull private static TypeSubstitutor createUpperBoundsSubstitutor(@NotNull List typeParameters) { Map mutableSubstitution = new HashMap(); diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt new file mode 100644 index 00000000000..ef9bf7b8da9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt @@ -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) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.txt new file mode 100644 index 00000000000..ad500f6b367 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.txt @@ -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 +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.kt new file mode 100644 index 00000000000..173d12fb8f1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: J.java +import java.util.* + +public class J { + public static > String foo(E e) { return ""; } + public static > String foo(E e1, E e2) { return ""; } + public static > String foo(E s1, E s2, E s3) { return ""; } + public static > int foo(E... ss) { return 0; } +} + +// FILE: test.kt +enum class X { A } +val a = X.A + +val test0: Int = J.foo() +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) diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.txt new file mode 100644 index 00000000000..cf68e449180 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/javaOverloadedVarargs.txt @@ -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 !> foo(/*0*/ e: E!): kotlin.String! + public open fun !> foo(/*0*/ e1: E!, /*1*/ e2: E!): kotlin.String! + public open fun !> foo(/*0*/ s1: E!, /*1*/ s2: E!, /*2*/ s3: E!): kotlin.String! + public open fun !> foo(/*0*/ vararg ss: E! /*kotlin.Array<(out) E!>!*/): kotlin.Int +} + +public final enum class X : kotlin.Enum { + 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 + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): X + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.kt new file mode 100644 index 00000000000..794be2d88fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.kt @@ -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 = "") + diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.txt new file mode 100644 index 00000000000..39fc3940923 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/numberOfDefaults.txt @@ -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 +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.kt new file mode 100644 index 00000000000..3f4980a13c6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.kt @@ -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 = 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("") diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.txt new file mode 100644 index 00000000000..f997e91aa6e --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/originalExamples.txt @@ -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 +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.kt new file mode 100644 index 00000000000..3991c9e26d9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.kt @@ -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("") diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.txt new file mode 100644 index 00000000000..dccd93a2ff5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargs.txt @@ -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*/): 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 +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.kt new file mode 100644 index 00000000000..7463310c55d --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.kt @@ -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) + diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.txt new file mode 100644 index 00000000000..3e3382363c2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsInDifferentPositions.txt @@ -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*/): X1 +public fun overloadedFun(/*0*/ arg: kotlin.String, /*1*/ vararg args: kotlin.String /*kotlin.Array*/, /*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 +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.kt new file mode 100644 index 00000000000..1ea59f6ac63 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.kt @@ -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 = overloadedFun5("") +val test2 = overloadedFun5("", "") +val test3: X2 = overloadedFun5(s = "", ss = "") +val test4: X1 = overloadedFun5(ss = "") \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.txt new file mode 100644 index 00000000000..5de5b1d6087 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/varargsMixed.txt @@ -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*/): X1 +public fun overloadedFun5(/*0*/ s: kotlin.String, /*1*/ vararg ss: kotlin.String /*kotlin.Array*/): 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index d33abb3c10b..38fcdc7a00f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/test/util/jetTestUtils.kt b/compiler/tests/org/jetbrains/kotlin/test/util/jetTestUtils.kt index 0450b9bca4d..cc218406a30 100644 --- a/compiler/tests/org/jetbrains/kotlin/test/util/jetTestUtils.kt +++ b/compiler/tests/org/jetbrains/kotlin/test/util/jetTestUtils.kt @@ -16,23 +16,23 @@ 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.psi.* import com.intellij.psi.util.PsiTreeUtil +import com.intellij.testFramework.fixtures.CodeInsightTestFixture 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.util.* public fun String.trimTrailingWhitespacesAndAddNewlineAtEOF(): String = this.split('\n').map { it.trimEnd() }.joinToString(separator = "\n").let { result -> if (result.endsWith("\n")) result else result + "\n" } -public fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraNameParts: String) { - configureWithExtraFile(path, *extraNameParts) +public fun CodeInsightTestFixture.configureWithExtraFileAbs(path: String, vararg extraNameParts: String) { + configureWithExtraFile(path, *extraNameParts, relativePaths = false) } public fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraNameParts: String = arrayOf(".Data"), relativePaths: Boolean = false) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/AbstractQuickDocProviderTest.java b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/AbstractQuickDocProviderTest.java index a26f7b633f8..12b47fc9cb7 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/AbstractQuickDocProviderTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/AbstractQuickDocProviderTest.java @@ -34,7 +34,7 @@ import java.util.List; public abstract class AbstractQuickDocProviderTest extends KotlinLightCodeInsightFixtureTestCase { 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()); assertNotNull("Can't find element at caret in file: " + path, element); diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt index 3b9c574ecaa..a6985cd4491 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt @@ -17,22 +17,18 @@ package org.jetbrains.kotlin.idea.resolve import com.google.common.collect.Lists -import com.google.common.collect.Ordering import com.intellij.psi.PsiPolyVariantReference import com.intellij.psi.PsiReference import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.UsefulTestCase 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.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.ReferenceUtils import org.jetbrains.kotlin.test.util.configureWithExtraFile import org.junit.Assert -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull import kotlin.test.assertTrue public abstract class AbstractReferenceResolveTest : KotlinLightPlatformCodeInsightFixtureTestCase() { diff --git a/idea/tests/org/jetbrains/kotlin/idea/structureView/AbstractKotlinFileStructureTest.kt b/idea/tests/org/jetbrains/kotlin/idea/structureView/AbstractKotlinFileStructureTest.kt index 143a6932c38..f5e5767eadd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/structureView/AbstractKotlinFileStructureTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/structureView/AbstractKotlinFileStructureTest.kt @@ -16,21 +16,20 @@ 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.util.FileStructurePopup 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.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.PluginTestCaseBase +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.util.configureWithExtraFile +import java.io.File public abstract class AbstractKotlinFileStructureTest : KotlinLightCodeInsightFixtureTestCase() { override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/structureView/fileStructure"