Annotated the return type of 'elvis' function with @Exact

fun <T> ELVIS(T?, T): @Exact T
This commit is contained in:
Svetlana Isakova
2015-10-20 18:52:17 +03:00
parent 7150be7c67
commit 06e90cf6a1
11 changed files with 78 additions and 12 deletions
@@ -127,6 +127,7 @@ public class AnnotationSplitter(
}
override fun isEmpty() = annotations.isEmpty()
override fun hasAnnotation(fqName: FqName) = annotations.hasAnnotation(fqName)
override fun findAnnotation(fqName: FqName) = annotations.findAnnotation(fqName)
override fun getUseSiteTargetedAnnotations() = annotations.getUseSiteTargetedAnnotations()
override fun getAllAnnotations() = annotations.getAllAnnotations()
@@ -63,6 +63,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.ResolveConstruct;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperKt;
@@ -830,7 +831,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
// See also CallExpressionResolver.getSimpleNameExpressionTypeInfo, .getQualifiedExpressionTypeInfo
Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Collections.singletonList(baseExpression));
components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
call, ResolveConstruct.EXCL_EXCL, Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null);
JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext());
if (ArgumentTypeResolver.isFunctionLiteralArgument(baseExpression, context)) {
@@ -1163,7 +1164,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
call, ResolveConstruct.ELVIS, Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
if (ArgumentTypeResolver.isFunctionLiteralArgument(left, context)) {
context.trace.report(USELESS_ELVIS_ON_FUNCTION_LITERAL.on(expression.getOperationReference()));
@@ -47,10 +47,12 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.descriptorUtil.AnnotationsForResolveKt;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.Variance;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import java.util.*;
@@ -61,6 +63,20 @@ import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Co
public class ControlStructureTypingUtils {
private static final Logger LOG = Logger.getInstance(ControlStructureTypingUtils.class);
public enum ResolveConstruct {
IF("if"), ELVIS("elvis"), EXCL_EXCL("ExclExcl");
private final String name;
ResolveConstruct(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
private final CallResolver callResolver;
private final DataFlowAnalyzer dataFlowAnalyzer;
private final ModuleDescriptor moduleDescriptor;
@@ -77,15 +93,15 @@ public class ControlStructureTypingUtils {
/*package*/ ResolvedCall<FunctionDescriptor> resolveSpecialConstructionAsCall(
@NotNull Call call,
@NotNull String constructionName,
@NotNull ResolveConstruct construct,
@NotNull List<String> argumentNames,
@NotNull List<Boolean> isArgumentNullable,
@NotNull ExpressionTypingContext context,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
) {
SimpleFunctionDescriptorImpl function = createFunctionDescriptorForSpecialConstruction(
constructionName.toUpperCase(), argumentNames, isArgumentNullable);
TracingStrategy tracing = createTracingForSpecialConstruction(call, constructionName, context);
construct, argumentNames, isArgumentNullable);
TracingStrategy tracing = createTracingForSpecialConstruction(call, construct.getName(), context);
ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(call, function);
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithKnownCandidate(
call, tracing, context, resolutionCandidate, dataFlowInfoForArguments);
@@ -94,12 +110,13 @@ public class ControlStructureTypingUtils {
}
private SimpleFunctionDescriptorImpl createFunctionDescriptorForSpecialConstruction(
@NotNull String constructionName,
@NotNull ResolveConstruct construct,
@NotNull List<String> argumentNames,
@NotNull List<Boolean> isArgumentNullable
) {
assert argumentNames.size() == isArgumentNullable.size();
String constructionName = construct.getName().toUpperCase();
Name specialFunctionName = Name.identifier("<SPECIAL-FUNCTION-FOR-" + constructionName + "-RESOLVE>");
SimpleFunctionDescriptorImpl function = SimpleFunctionDescriptorImpl.create(
@@ -126,12 +143,13 @@ public class ControlStructureTypingUtils {
);
valueParameters.add(valueParameter);
}
KotlinType returnType = construct != ResolveConstruct.ELVIS ? type : TypeUtilsKt.replaceAnnotations(type, AnnotationsForResolveKt.getExactInAnnotations());
function.initialize(
null,
null,
Lists.newArrayList(typeParameter),
valueParameters,
type,
returnType,
Modality.FINAL,
Visibilities.PUBLIC
);
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.types.CommonSupertypes;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.ResolveConstruct;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
@@ -128,7 +129,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
MutableDataFlowInfoForArguments dataFlowInfoForArguments =
createDataFlowInfoForArgumentsForIfCall(callForIf, thenInfo, elseInfo);
ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
callForIf, "If", Lists.newArrayList("thenBranch", "elseBranch"),
callForIf, ResolveConstruct.IF, Lists.newArrayList("thenBranch", "elseBranch"),
Lists.newArrayList(false, false),
contextWithExpectedType, dataFlowInfoForArguments);