KT-9498 extension: now type can be inferred for getter with expression body
This commit is contained in:
@@ -355,7 +355,7 @@ public interface Errors {
|
||||
DiagnosticFactory2.create(ERROR, DECLARATION_NAME);
|
||||
|
||||
|
||||
DiagnosticFactory1<KtNamedDeclaration, Collection<KotlinType>> AMBIGUOUS_ANONYMOUS_TYPE_INFERRED =
|
||||
DiagnosticFactory1<KtDeclaration, Collection<KotlinType>> AMBIGUOUS_ANONYMOUS_TYPE_INFERRED =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
// Property-specific
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
|
||||
import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
@@ -53,6 +54,8 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
|
||||
import org.jetbrains.kotlin.storage.StorageManager;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -74,6 +77,7 @@ public class DescriptorResolver {
|
||||
@NotNull private final KotlinBuiltIns builtIns;
|
||||
@NotNull private final SupertypeLoopChecker supertypeLoopsResolver;
|
||||
@NotNull private final VariableTypeResolver variableTypeResolver;
|
||||
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
||||
|
||||
public DescriptorResolver(
|
||||
@NotNull AnnotationResolver annotationResolver,
|
||||
@@ -81,7 +85,8 @@ public class DescriptorResolver {
|
||||
@NotNull StorageManager storageManager,
|
||||
@NotNull TypeResolver typeResolver,
|
||||
@NotNull SupertypeLoopChecker supertypeLoopsResolver,
|
||||
@NotNull VariableTypeResolver variableTypeResolver
|
||||
@NotNull VariableTypeResolver variableTypeResolver,
|
||||
@NotNull ExpressionTypingServices expressionTypingServices
|
||||
) {
|
||||
this.annotationResolver = annotationResolver;
|
||||
this.builtIns = builtIns;
|
||||
@@ -89,6 +94,7 @@ public class DescriptorResolver {
|
||||
this.typeResolver = typeResolver;
|
||||
this.supertypeLoopsResolver = supertypeLoopsResolver;
|
||||
this.variableTypeResolver = variableTypeResolver;
|
||||
this.expressionTypingServices = expressionTypingServices;
|
||||
}
|
||||
|
||||
public List<KotlinType> resolveSupertypes(
|
||||
@@ -774,7 +780,7 @@ public class DescriptorResolver {
|
||||
@Nullable
|
||||
/*package*/ static KotlinType transformAnonymousTypeIfNeeded(
|
||||
@NotNull DeclarationDescriptorWithVisibility descriptor,
|
||||
@NotNull KtNamedDeclaration declaration,
|
||||
@NotNull KtDeclaration declaration,
|
||||
@NotNull KotlinType type,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
@@ -897,7 +903,7 @@ public class DescriptorResolver {
|
||||
KtTypeReference returnTypeReference = getter.getReturnTypeReference();
|
||||
if (returnTypeReference != null) {
|
||||
returnType = typeResolver.resolveType(scopeWithTypeParameters, returnTypeReference, trace, true);
|
||||
if (outType != null && !TypeUtils.equalTypes(returnType, outType)) {
|
||||
if (!TypeUtils.equalTypes(returnType, outType)) {
|
||||
trace.report(WRONG_GETTER_RETURN_TYPE.on(returnTypeReference, propertyDescriptor.getReturnType(), outType));
|
||||
}
|
||||
}
|
||||
@@ -908,6 +914,10 @@ public class DescriptorResolver {
|
||||
getter.hasBody(), false, getter.hasModifier(EXTERNAL_KEYWORD),
|
||||
CallableMemberDescriptor.Kind.DECLARATION, null, KotlinSourceElementKt
|
||||
.toSourceElement(getter));
|
||||
if (returnType.isError() && !getter.hasBlockBody() && getter.hasBody()) {
|
||||
returnType = inferReturnTypeFromExpressionBody(storageManager, expressionTypingServices, trace, scopeWithTypeParameters,
|
||||
DataFlowInfoFactory.EMPTY, getter, getterDescriptor);
|
||||
}
|
||||
getterDescriptor.initialize(returnType);
|
||||
trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor);
|
||||
}
|
||||
@@ -920,6 +930,27 @@ public class DescriptorResolver {
|
||||
return getterDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/*package*/ static DeferredType inferReturnTypeFromExpressionBody(
|
||||
@NotNull StorageManager storageManager,
|
||||
@NotNull final ExpressionTypingServices expressionTypingServices,
|
||||
@NotNull final BindingTrace trace,
|
||||
@NotNull final LexicalScope scope,
|
||||
@NotNull final DataFlowInfo dataFlowInfo,
|
||||
@NotNull final KtDeclarationWithBody function,
|
||||
@NotNull final FunctionDescriptor functionDescriptor
|
||||
) {
|
||||
return DeferredType.createRecursionIntolerant(storageManager, trace, new Function0<KotlinType>() {
|
||||
@Override
|
||||
public KotlinType invoke() {
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace);
|
||||
KotlinType type = expressionTypingServices.getBodyExpressionType(
|
||||
trace, scope, dataFlowInfo, function, functionDescriptor);
|
||||
return transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PropertyDescriptor resolvePrimaryConstructorParameterToAProperty(
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
|
||||
@@ -122,11 +122,8 @@ class FunctionDescriptorResolver(
|
||||
builtIns.unitType
|
||||
}
|
||||
else if (function.hasBody()) {
|
||||
DeferredType.createRecursionIntolerant(storageManager, trace) {
|
||||
PreliminaryDeclarationVisitor.createForDeclaration(function, trace);
|
||||
val type = expressionTypingServices.getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor)
|
||||
transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace)
|
||||
}
|
||||
inferReturnTypeFromExpressionBody(storageManager, expressionTypingServices, trace, scope,
|
||||
dataFlowInfo, function, functionDescriptor)
|
||||
}
|
||||
else {
|
||||
ErrorUtils.createErrorType("No type, no body")
|
||||
|
||||
Reference in New Issue
Block a user