KT-14274: resolve type alias constructors calls in supertypes list as type alias constructors.

Support @Deprecated for type aliases, including type alias constructors.
This commit is contained in:
Dmitry Petrov
2016-10-10 18:21:19 +03:00
parent bee0e783f8
commit 8d634f6003
25 changed files with 285 additions and 43 deletions
@@ -222,7 +222,7 @@ public interface BindingContext {
*/
WritableSlice<PsiElement, SimpleFunctionDescriptor> FUNCTION = Slices.createSimpleSlice();
WritableSlice<PsiElement, ConstructorDescriptor> CONSTRUCTOR = Slices.createSimpleSlice();
WritableSlice<ConstructorDescriptor, ResolvedCall<ClassConstructorDescriptor>> CONSTRUCTOR_RESOLVED_DELEGATION_CALL =
WritableSlice<ConstructorDescriptor, ResolvedCall<ConstructorDescriptor>> CONSTRUCTOR_RESOLVED_DELEGATION_CALL =
Slices.createSimpleSlice();
WritableSlice<PsiElement, VariableDescriptor> VARIABLE = Slices.createSimpleSlice();
WritableSlice<KtParameter, VariableDescriptor> VALUE_PARAMETER = Slices.createSimpleSlice();
@@ -222,7 +222,7 @@ public class BindingContextUtils {
}
@Nullable
public static ResolvedCall<ClassConstructorDescriptor> getDelegationConstructorCall(
public static ResolvedCall<ConstructorDescriptor> getDelegationConstructorCall(
@NotNull BindingContext bindingContext,
@NotNull ConstructorDescriptor constructorDescriptor
) {
@@ -231,7 +231,7 @@ public class BodyResolver {
@Nullable
private ConstructorDescriptor getDelegatedConstructor(@NotNull ConstructorDescriptor constructor) {
ResolvedCall<ClassConstructorDescriptor> call = trace.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor);
ResolvedCall<ConstructorDescriptor> call = trace.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor);
return call == null || !call.getStatus().isSuccess() ? null : call.getResultingDescriptor().getOriginal();
}
@@ -430,7 +430,7 @@ public class BodyResolver {
@NotNull ResolvedCall<?> call
) {
//noinspection unchecked
trace.record(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall<ClassConstructorDescriptor>) call);
trace.record(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall<ConstructorDescriptor>) call);
}
private void checkSupertypeList(
@@ -307,7 +307,7 @@ public class CallResolver {
return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
}
private OverloadResolutionResults<ClassConstructorDescriptor> resolveCallForConstructor(
private OverloadResolutionResults<ConstructorDescriptor> resolveCallForConstructor(
@NotNull BasicCallResolutionContext context,
@NotNull KtConstructorCalleeExpression expression
) {
@@ -340,17 +340,17 @@ public class CallResolver {
return checkArgumentTypesAndFail(context);
}
Pair<Collection<ResolutionCandidate<ClassConstructorDescriptor>>, BasicCallResolutionContext> candidatesAndContext =
Pair<Collection<ResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext> candidatesAndContext =
prepareCandidatesAndContextForConstructorCall(constructedType, context);
Collection<ResolutionCandidate<ClassConstructorDescriptor>> candidates = candidatesAndContext.getFirst();
Collection<ResolutionCandidate<ConstructorDescriptor>> candidates = candidatesAndContext.getFirst();
context = candidatesAndContext.getSecond();
return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates);
}
@Nullable
public OverloadResolutionResults<ClassConstructorDescriptor> resolveConstructorDelegationCall(
public OverloadResolutionResults<ConstructorDescriptor> resolveConstructorDelegationCall(
@NotNull BindingTrace trace, @NotNull LexicalScope scope, @NotNull DataFlowInfo dataFlowInfo,
@NotNull ClassConstructorDescriptor constructorDescriptor,
@NotNull KtConstructorDelegationCall call
@@ -380,7 +380,7 @@ public class CallResolver {
}
@NotNull
private OverloadResolutionResults<ClassConstructorDescriptor> resolveConstructorDelegationCall(
private OverloadResolutionResults<ConstructorDescriptor> resolveConstructorDelegationCall(
@NotNull BasicCallResolutionContext context,
@NotNull KtConstructorDelegationCall call,
@NotNull KtConstructorDelegationReferenceExpression calleeExpression,
@@ -420,9 +420,9 @@ public class CallResolver {
calleeConstructor.getContainingDeclaration().getDefaultType() :
DescriptorUtils.getSuperClassType(currentClassDescriptor);
Pair<Collection<ResolutionCandidate<ClassConstructorDescriptor>>, BasicCallResolutionContext> candidatesAndContext =
Pair<Collection<ResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext> candidatesAndContext =
prepareCandidatesAndContextForConstructorCall(superType, context);
Collection<ResolutionCandidate<ClassConstructorDescriptor>> candidates = candidatesAndContext.getFirst();
Collection<ResolutionCandidate<ConstructorDescriptor>> candidates = candidatesAndContext.getFirst();
context = candidatesAndContext.getSecond();
TracingStrategy tracing = call.isImplicit() ?
@@ -441,17 +441,15 @@ public class CallResolver {
}
@NotNull
private static Pair<Collection<ResolutionCandidate<ClassConstructorDescriptor>>, BasicCallResolutionContext> prepareCandidatesAndContextForConstructorCall(
private static Pair<Collection<ResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext> prepareCandidatesAndContextForConstructorCall(
@NotNull KotlinType superType,
@NotNull BasicCallResolutionContext context
) {
if (!(superType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
return new Pair<Collection<ResolutionCandidate<ClassConstructorDescriptor>>, BasicCallResolutionContext>(
Collections.<ResolutionCandidate<ClassConstructorDescriptor>>emptyList(), context);
return new Pair<Collection<ResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext>(
Collections.<ResolutionCandidate<ConstructorDescriptor>>emptyList(), context);
}
ClassDescriptor superClass = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
// If any constructor has type parameter (currently it only can be true for ones from Java), try to infer arguments for them
// Otherwise use NO_EXPECTED_TYPE and knownTypeParametersSubstitutor
boolean anyConstructorHasDeclaredTypeParameters =
@@ -462,10 +460,10 @@ public class CallResolver {
context = context.replaceExpectedType(superType);
}
Collection<ResolutionCandidate<ClassConstructorDescriptor>> candidates =
CallResolverUtilKt.createResolutionCandidatesForConstructors(context.scope, context.call, superClass, knownTypeParametersSubstitutor);
Collection<ResolutionCandidate<ConstructorDescriptor>> candidates =
CallResolverUtilKt.createResolutionCandidatesForConstructors(context.scope, context.call, superType, knownTypeParametersSubstitutor);
return new Pair<Collection<ResolutionCandidate<ClassConstructorDescriptor>>, BasicCallResolutionContext>(candidates, context);
return new Pair<Collection<ResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext>(candidates, context);
}
private static boolean anyConstructorHasDeclaredTypeParameters(@Nullable ClassifierDescriptor classDescriptor) {
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.coroutines.getExpectedTypeForCoroutineControllerHandleResult
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
@@ -200,9 +202,18 @@ fun getEffectiveExpectedType(parameterDescriptor: ValueParameterDescriptor, argu
fun createResolutionCandidatesForConstructors(
lexicalScope: LexicalScope,
call: Call,
classWithConstructors: ClassDescriptor,
typeWithConstructors: KotlinType,
knownSubstitutor: TypeSubstitutor? = null
): Collection<ResolutionCandidate<ClassConstructorDescriptor>> {
): Collection<ResolutionCandidate<ConstructorDescriptor>> {
val classWithConstructors = typeWithConstructors.constructor.declarationDescriptor as ClassDescriptor
val unwrappedType = typeWithConstructors.unwrap()
val typeAliasDescriptor =
if (unwrappedType is AbbreviatedType)
unwrappedType.abbreviation.constructor.declarationDescriptor as? TypeAliasDescriptor
else
null
val constructors = classWithConstructors.constructors
if (constructors.isEmpty()) return emptyList()
@@ -212,7 +223,7 @@ fun createResolutionCandidatesForConstructors(
if (classWithConstructors.isInner) {
val outerClassType = (classWithConstructors.containingDeclaration as? ClassDescriptor)?.defaultType ?: return emptyList()
val substitutedOuterClassType = knownSubstitutor?.let { it.substitute(outerClassType, Variance.INVARIANT) } ?: outerClassType
val substitutedOuterClassType = knownSubstitutor?.substitute(outerClassType, Variance.INVARIANT) ?: outerClassType
val receiver = lexicalScope.getImplicitReceiversHierarchy().firstOrNull {
KotlinTypeChecker.DEFAULT.isSubtypeOf(it.type, substitutedOuterClassType)
@@ -226,9 +237,22 @@ fun createResolutionCandidatesForConstructors(
dispatchReceiver = null
}
return constructors.map { ResolutionCandidate.create(call, it, dispatchReceiver, receiverKind, knownSubstitutor) }
return constructors.map {
val constructorDescriptor = it.getConstructorDescriptorForResolution(knownSubstitutor, typeAliasDescriptor)
ResolutionCandidate.create(call, constructorDescriptor, dispatchReceiver, receiverKind, knownSubstitutor)
}
}
private fun ClassConstructorDescriptor.getConstructorDescriptorForResolution(
knownSubstitutor: TypeSubstitutor?,
typeAliasDescriptor: TypeAliasDescriptor?
): ConstructorDescriptor =
if (typeAliasDescriptor != null)
TypeAliasConstructorDescriptorImpl.create(typeAliasDescriptor, this, knownSubstitutor ?: TypeSubstitutor.EMPTY)
?: throw AssertionError("Failed to create type alias constructor with substitutor: $knownSubstitutor")
else
this
fun KtLambdaExpression.getCorrespondingParameterForFunctionArgument(
bindingContext: BindingContext
): ValueParameterDescriptor? {
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
@@ -32,7 +33,13 @@ object ProtectedConstructorCallChecker : CallChecker {
val constructorOwner = descriptor.containingDeclaration.original
val scopeOwner = context.scope.ownerDescriptor
if (descriptor.visibility.normalize() != Visibilities.PROTECTED) return
val actualConstructor =
if (descriptor is TypeAliasConstructorDescriptor)
descriptor.underlyingConstructorDescriptor
else
descriptor
if (actualConstructor.visibility.normalize() != Visibilities.PROTECTED) return
// Error already reported
if (!Visibilities.isVisibleWithAnyReceiver(descriptor, scopeOwner)) return
@@ -52,7 +59,7 @@ object ProtectedConstructorCallChecker : CallChecker {
// And without ProtectedConstructorCallChecker such calls would be allowed only because they are performed within subclass
// of constructor owner
@Suppress("DEPRECATION")
if (Visibilities.findInvisibleMember(Visibilities.FALSE_IF_PROTECTED, descriptor, scopeOwner) == descriptor) {
if (Visibilities.findInvisibleMember(Visibilities.FALSE_IF_PROTECTED, descriptor, scopeOwner) == actualConstructor) {
context.trace.report(Errors.PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL.on(reportOn, descriptor))
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.FqName
@@ -137,6 +138,11 @@ private fun DeclarationDescriptor.getDeprecationByAnnotation(): DeprecatedByAnno
val classAnnotation = classDescriptor.getDeclaredDeprecatedAnnotation()
if (classAnnotation != null)
return DeprecatedByAnnotation(classAnnotation, classDescriptor)
if (this is TypeAliasConstructorDescriptor) {
val underlyingConstructorDeprecation = underlyingConstructorDescriptor.getDeprecationByAnnotation()
if (underlyingConstructorDeprecation != null)
return underlyingConstructorDeprecation
}
}
is PropertyAccessorDescriptor -> {
val propertyDescriptor = correspondingProperty