KT-9498 extension: now type can be inferred for getter with expression body

This commit is contained in:
Mikhail Glukhikh
2016-02-17 13:09:20 +03:00
parent 405c21a17e
commit 883e2e4d2b
13 changed files with 108 additions and 9 deletions
@@ -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")