[NI] Support assigning single array elements in named form to varargs

This commit is contained in:
Mikhail Zarechenskiy
2017-11-07 12:34:48 +03:00
parent fe2499b47f
commit 519e5c33d8
8 changed files with 46 additions and 16 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.*
@@ -25,7 +26,7 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
// very initial state of component
// todo: handle all diagnostic inside DiagnosticReporterByTrackingStrategy
// move it to frontend module
class AdditionalDiagnosticReporter {
class AdditionalDiagnosticReporter(private val languageVersionSettings: LanguageVersionSettings) {
fun reportAdditionalDiagnostics(
candidate: ResolvedCallAtom,
@@ -79,7 +80,8 @@ class AdditionalDiagnosticReporter {
for (parameter in resultingDescriptor.valueParameters) {
for (argument in candidate.argumentMappingByOriginal[parameter.original]?.arguments ?: continue) {
val smartCastDiagnostic = createSmartCastDiagnostic(candidate, argument, argument.getExpectedType(parameter)) ?: continue
val effectiveExpectedType = argument.getExpectedType(parameter, languageVersionSettings)
val smartCastDiagnostic = createSmartCastDiagnostic(candidate, argument, effectiveExpectedType) ?: continue
val thereIsUnstableSmartCastError = candidate.diagnostics.filterIsInstance<UnstableSmartCast>().any {
it.argument == argument
@@ -16,9 +16,15 @@
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
@@ -42,8 +48,8 @@ internal val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
return intersectWrappedTypes(possibleTypes + receiverValue.type)
}
internal fun KotlinCallArgument.getExpectedType(parameter: ParameterDescriptor) =
if (this.isSpread) {
internal fun KotlinCallArgument.getExpectedType(parameter: ParameterDescriptor, languageVersionSettings: LanguageVersionSettings) =
if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) {
parameter.type.unwrap()
}
else {
@@ -51,3 +57,23 @@ internal fun KotlinCallArgument.getExpectedType(parameter: ParameterDescriptor)
}
val ValueParameterDescriptor.isVararg: Boolean get() = varargElementType != null
val ParameterDescriptor.isVararg: Boolean get() = this.safeAs<ValueParameterDescriptor>()?.isVararg ?: false
private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation(
parameter: ParameterDescriptor,
languageVersionSettings: LanguageVersionSettings
): Boolean {
if (!languageVersionSettings.supportsFeature(LanguageFeature.AssigningArraysToVarargsInNamedFormInAnnotations)) return false
if (this.argumentName == null || !parameter.isVararg) return false
return isParameterOfAnnotation(parameter) && this.isArrayOrArrayLiteral()
}
private fun KotlinCallArgument.isArrayOrArrayLiteral(): Boolean {
if (this is CollectionLiteralKotlinCallArgument) return true
if (this !is SimpleKotlinCallArgument) return false
val type = this.receiver.receiverValue.type
return KotlinBuiltIns.isArrayOrPrimitiveArray(type)
}
@@ -225,7 +225,7 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
isReceiver: Boolean
) {
val expectedType = candidateParameter?.let {
resolvedCall.substitutor.substituteKeepAnnotations(argument.getExpectedType(candidateParameter))
resolvedCall.substitutor.substituteKeepAnnotations(argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings))
}
addResolvedKtPrimitive(resolveKtPrimitive(csBuilder, argument, expectedType, this, isReceiver))
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.calls.components.*
@@ -40,7 +41,8 @@ class KotlinCallComponents(
val typeArgumentsToParametersMapper: TypeArgumentsToParametersMapper,
val constraintInjector: ConstraintInjector,
val reflectionTypes: ReflectionTypes,
val builtIns: KotlinBuiltIns
val builtIns: KotlinBuiltIns,
val languageVersionSettings: LanguageVersionSettings
)
class SimpleCandidateFactory(