/** * Gives the return type of an ExpressionTree that represents a method select. * * <p>TODO(eaftan): Are there other places this could be used? */ public static Type getReturnType(ExpressionTree expressionTree) { if (expressionTree instanceof JCFieldAccess) { JCFieldAccess methodCall = (JCFieldAccess) expressionTree; return methodCall.type.getReturnType(); } else if (expressionTree instanceof JCIdent) { JCIdent methodCall = (JCIdent) expressionTree; return methodCall.type.getReturnType(); } else if (expressionTree instanceof JCMethodInvocation) { return getReturnType(((JCMethodInvocation) expressionTree).getMethodSelect()); } else if (expressionTree instanceof JCMemberReference) { return ((JCMemberReference) expressionTree).sym.type.getReturnType(); } throw new IllegalArgumentException("Expected a JCFieldAccess or JCIdent"); }
/** * Returns the type that this expression tree will evaluate to. If its a literal, an identifier, * or a member select this is the actual type, if its a method invocation then its the return type * of the method (after instantiating generic types), if its a constructor then its the type of * the returned class. * * <p>TODO(andrewrice) consider replacing {@code getReturnType} with this method * * @param expressionTree the tree to evaluate * @return the result type of this tree or null if unable to resolve it */ @Nullable public static Type getResultType(ExpressionTree expressionTree) { Type type = ASTHelpers.getType(expressionTree); return type == null ? null : Optional.ofNullable(type.getReturnType()).orElse(type); }
@Override public Type visitLambdaExpression(LambdaExpressionTree lambdaExpressionTree, Void unused) { return state.getTypes().findDescriptorType(getType(lambdaExpressionTree)).getReturnType(); }
/** * Checks that the return value of a functional interface is void. Note, we do not use * ASTHelpers.isVoidType here, return values of Void are actually type-checked. Only * void-returning functions silently ignore return values of any type. */ private static boolean functionalInterfaceReturnsExactlyVoid( Type interfaceType, VisitorState state) { return state.getTypes().findDescriptorType(interfaceType).getReturnType().getKind() == TypeKind.VOID; }
@Override public Type visitMemberReference(MemberReferenceTree node, Void aVoid) { return state.getTypes().findDescriptorType(getType(node)).getReturnType(); }
private static Type getMethodOrLambdaReturnType(VisitorState state) { for (Tree tree : state.getPath()) { switch (tree.getKind()) { case LAMBDA_EXPRESSION: return state.getTypes().findDescriptorType(ASTHelpers.getType(tree)).getReturnType(); case METHOD: return ASTHelpers.getType(tree).getReturnType(); case CLASS: return null; default: // fall out } } return null; }
/** * Checks that the return value of a functional interface is void. Note, we do not use * ASTHelpers.isVoidType here, return values of Void are actually type-checked. Only * void-returning functions silently ignore return values of any type. */ private static boolean functionalInterfaceReturnsExactlyVoid(Type interfaceType, VisitorState state) { return state.getTypes().findDescriptorType(interfaceType).getReturnType().getKind() == TypeKind.VOID; }
private static String functionalInterfaceSignature(VisitorState state, Type type) { Types types = state.getTypes(); if (!maybeFunctionalInterface(type, types, state)) { return Signatures.descriptor(type, types); } Type descriptorType = types.findDescriptorType(type); List<Type> fiparams = descriptorType.getParameterTypes(); // Implicitly typed block-statement-bodied lambdas are potentially compatible with // void-returning and value-returning functional interface types, so we don't consider return // types in general. The except is nullary functional interfaces, since the lambda parameters // will never be implicitly typed. String result = fiparams.isEmpty() ? Signatures.descriptor(descriptorType.getReturnType(), types) : "_"; return String.format( "(%s)->%s", fiparams.stream().map(t -> Signatures.descriptor(t, types)).collect(joining(",")), result); }
actualTypes); unifier.putBinding( var.key(), TypeWithExpression.create(instantiationForVar.getReturnType()));
/** * Checks that the return value of a functional interface is void. Note, we do not use * ASTHelpers.isVoidType here, return values of Void are actually type-checked. Only * void-returning functions silently ignore return values of any type. */ private static boolean functionalInterfaceReturnsObject(Type interfaceType, VisitorState state) { Type objectType = state.getTypeFromString("java.lang.Object"); return ASTHelpers.isSubtype( objectType, ASTHelpers.getUpperBound( state.getTypes().findDescriptorType(interfaceType).getReturnType(), state.getTypes()), state); }
/** * Extracts the {@link Type} of the return value for {@link MethodInvocationTree} or {@link * MemberReferenceTree}, then checks it against {@link #capturedTypeAllowed(Type, VisitorState)}. */ private boolean isValidReturnValueType(ExpressionTree tree, VisitorState state) { Type returnType = null; if (tree instanceof MethodInvocationTree) { returnType = getReturnType(((JCMethodInvocation) tree).getMethodSelect()); } else if (tree instanceof MemberReferenceTree) { // Get the return type of the target referenced interface returnType = state.getTypes().findDescriptorType(((JCMemberReference) tree).type).getReturnType(); } if (returnType != null) { return capturedTypeAllowed(returnType, state); } return true; }
return Description.NO_MATCH; Type instantiatedReturnType = types.erasure(call.meth.type.getReturnType()); if (instantiatedReturnType == null) { return Description.NO_MATCH; return Description.NO_MATCH; Type uninstantiatedReturnType = types.erasure(methodSym.type.getReturnType()); if (uninstantiatedReturnType == null) { return Description.NO_MATCH;
type = type.getReturnType();
@Override public Description matchReturn(ReturnTree tree, VisitorState state) { if (tree.getExpression() == null) { return NO_MATCH; } Type type = null; outer: for (Tree parent : state.getPath()) { switch (parent.getKind()) { case METHOD: type = ASTHelpers.getType(((MethodTree) parent).getReturnType()); break outer; case LAMBDA_EXPRESSION: type = state.getTypes().findDescriptorType(ASTHelpers.getType(parent)).getReturnType(); break outer; default: // fall out } } if (type == null) { return NO_MATCH; } return check(type, tree.getExpression()); }
static Type getTargetType(VisitorState state) { Tree parent = state.getPath().getParentPath().getLeaf(); Type type; if (parent instanceof VariableTree || parent instanceof AssignmentTree) { type = ASTHelpers.getType(parent); } else if (parent instanceof ReturnTree || parent instanceof LambdaExpressionTree) { type = getMethodOrLambdaReturnType(state); } else if (parent instanceof MethodInvocationTree) { MethodInvocationTree tree = (MethodInvocationTree) parent; int idx = tree.getArguments().indexOf(state.getPath().getLeaf()); if (idx == -1) { return null; } Type methodType = ASTHelpers.getType(tree.getMethodSelect()); if (idx >= methodType.getParameterTypes().size()) { return null; } return methodType.getParameterTypes().get(idx); } else { return null; } Tree tree = state.getPath().getLeaf(); if (tree instanceof MemberReferenceTree) { type = state.getTypes().findDescriptorType(ASTHelpers.getType(tree)).getReturnType(); } return type; }
Type streamType = state.getTypeFromString(Stream.class.getName()); if (isSubtype(sym.enclClass().asType(), streamType, state) && isSameType(type.getReturnType(), streamType, state)) {
/** * Checks that the return value of a functional interface is void. Note, we do not use * ASTHelpers.isVoidType here, return values of Void are actually type-checked. Only * void-returning functions silently ignore return values of any type. */ private static boolean functionalInterfaceReturnsExactlyVoid( Type interfaceType, VisitorState state) { return state.getTypes().findDescriptorType(interfaceType).getReturnType().getKind() == TypeKind.VOID; }
private MethodType typeToMethodType(Type mt) { Type type = types.erasure(mt); return new MethodType(type.getParameterTypes(), type.getReturnType(), type.getThrownTypes(), syms.methodClass); }
/** Emit an invokedynamic instruction. */ public void emitInvokedynamic(int desc, Type mtype) { int argsize = width(mtype.getParameterTypes()); emitop(invokedynamic); if (!alive) return; emit2(desc); emit2(0); state.pop(argsize); state.push(mtype.getReturnType()); }
/** Emit an invokeinterface instruction. */ public void emitInvokeinterface(int meth, Type mtype) { int argsize = width(mtype.getParameterTypes()); emitop(invokeinterface); if (!alive) return; emit2(meth); emit1(argsize + 1); emit1(0); state.pop(argsize + 1); state.push(mtype.getReturnType()); }