[NI] Support assigning single array elements in named form to varargs
This commit is contained in:
@@ -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<ConstructorDescriptor>()?.constructedClass
|
||||
return DescriptorUtils.isAnnotationClass(constructedClass)
|
||||
}
|
||||
|
||||
fun isArrayOrArrayLiteral(argument: ValueArgument, context: ResolutionContext<*>): Boolean {
|
||||
val argumentExpression = argument.getArgumentExpression() ?: return false
|
||||
if (argumentExpression is KtCollectionLiteralExpression) return true
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
+28
-2
@@ -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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -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))
|
||||
}
|
||||
|
||||
+3
-1
@@ -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(
|
||||
|
||||
@@ -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<ConstructorDescriptor>()?.constructedClass
|
||||
return DescriptorUtils.isAnnotationClass(constructedClass)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user