diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index 2f2d50b1441..b0a01ac59d5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression @@ -39,6 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate +import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.resolve.scopes.collectSyntheticConstructors @@ -50,7 +50,6 @@ import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.contains -import org.jetbrains.kotlin.utils.addToStdlib.safeAs enum class ResolveArgumentsMode { RESOLVE_FUNCTION_ARGUMENTS, @@ -215,11 +214,6 @@ private fun shouldCheckAsArray( return argument.isNamed() && parameterDescriptor.isVararg && isArrayOrArrayLiteral(argument, context) } -fun isParameterOfAnnotation(parameterDescriptor: ValueParameterDescriptor): Boolean { - val constructedClass = parameterDescriptor.containingDeclaration.safeAs()?.constructedClass - return DescriptorUtils.isAnnotationClass(constructedClass) -} - fun isArrayOrArrayLiteral(argument: ValueArgument, context: ResolutionContext<*>): Boolean { val argumentExpression = argument.getArgumentExpression() ?: return false if (argumentExpression is KtCollectionLiteralExpression) return true diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AssigningNamedArgumentToVarargChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AssigningNamedArgumentToVarargChecker.kt index 5c71ff19f1f..a7b95dd095f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AssigningNamedArgumentToVarargChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AssigningNamedArgumentToVarargChecker.kt @@ -23,10 +23,10 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isArrayOrArrayLiteral -import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isParameterOfAnnotation import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation class AssigningNamedArgumentToVarargChecker : CallChecker { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/AdditionalDiagnosticReporter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/AdditionalDiagnosticReporter.kt index 2873a90c09d..a152c9e2942 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/AdditionalDiagnosticReporter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/AdditionalDiagnosticReporter.kt @@ -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().any { it.argument == argument diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt index 7be95c2bf9c..05fcce0bf3e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt @@ -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()?.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) +} diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 08e5090f1d9..a819a38daf2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -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)) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt index 25860fc4d70..415112d18f1 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt @@ -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( diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index 0d28dd951d8..f5366fb3e92 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2017 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. @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.SmartList +import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = companionObjectDescriptor ?: this @@ -433,3 +434,8 @@ fun MemberDescriptor.isEffectivelyExternal(): Boolean { val containingClass = getContainingClass(this) return containingClass != null && containingClass.isEffectivelyExternal() } + +fun isParameterOfAnnotation(parameterDescriptor: ParameterDescriptor): Boolean { + val constructedClass = parameterDescriptor.containingDeclaration.safeAs()?.constructedClass + return DescriptorUtils.isAnnotationClass(constructedClass) +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index 32b1ee9bf80..5c1e6025826 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2017 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.