/** * Returns the type of a receiver of a method call expression. Precondition: the expressionTree * corresponds to a method call. * * <p>Examples: * * <pre>{@code * a.b.foo() ==> type of a.b * a.bar().foo() ==> type of a.bar() * this.foo() ==> type of this * foo() ==> type of this * TheClass.aStaticMethod() ==> TheClass * aStaticMethod() ==> type of class in which method is defined * }</pre> */ public static Type getReceiverType(ExpressionTree expressionTree) { if (expressionTree instanceof JCFieldAccess) { JCFieldAccess methodSelectFieldAccess = (JCFieldAccess) expressionTree; return methodSelectFieldAccess.selected.type; } else if (expressionTree instanceof JCIdent) { JCIdent methodCall = (JCIdent) expressionTree; return methodCall.sym.owner.type; } else if (expressionTree instanceof JCMethodInvocation) { return getReceiverType(((JCMethodInvocation) expressionTree).getMethodSelect()); } else if (expressionTree instanceof JCMemberReference) { return ((JCMemberReference) expressionTree).getQualifierExpression().type; } throw new IllegalArgumentException( "Expected a JCFieldAccess or JCIdent from expression " + expressionTree); }
Source src = context.source; JCTree.JCMemberReference memberReference = (JCTree.JCMemberReference) tree; JCTree.JCExpression expression = memberReference.getQualifierExpression(); com.sun.tools.javac.util.Name name = memberReference.getName(); String methodName = name.toString(); if (nonNull(expression)) { String s = memberReference.toString();
if (pt().hasTag(NONE)) { log.error(that.pos(), "unexpected.mref"); if (that.getMode() == JCMemberReference.ReferenceMode.NEW) { exprType = chk.checkConstructorRefType(that.expr, exprType); if (!exprType.isErroneous() && exprType.isRaw() && that.typeargs != null) { log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("mref.infer.and.explicit.params")); exprType = types.createErrorType(exprType); "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag); if (that.getMode() == ReferenceMode.INVOKE && TreeInfo.isStaticSelector(that.expr, names) && that.kind.isUnbound() && log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.mref.with.targs")); result = that.type = types.createErrorType(currentTarget); log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.bound.mref")); result = that.type = types.createErrorType(currentTarget); rs.checkNonAbstract(that.pos(), that.sym);
boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names); boolean shouldCheckForStaticness = isStaticSelector && referenceTree.getMode() == ReferenceMode.INVOKE; if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) { if (shouldCheckForStaticness) { Kinds.kindName(referenceTree.getMode()), diags.fragment(errorFragmentToPrint, Kinds.kindName(symToPrint), symToPrint));
boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names); boolean shouldCheckForStaticness = isStaticSelector && referenceTree.getMode() == ReferenceMode.INVOKE; if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) { if (shouldCheckForStaticness) { Kinds.kindName(referenceTree.getMode()), diags.fragment(errorFragmentToPrint, Kinds.kindName(symToPrint), symToPrint));
if (pt().hasTag(NONE)) { log.error(that.pos(), "unexpected.mref"); if (that.getMode() == JCMemberReference.ReferenceMode.NEW) { exprType = chk.checkConstructorRefType(that.expr, exprType); if (!exprType.isErroneous() && exprType.isRaw() && that.typeargs != null) { log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("mref.infer.and.explicit.params")); exprType = types.createErrorType(exprType); "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag); if (that.getMode() == ReferenceMode.INVOKE && TreeInfo.isStaticSelector(that.expr, names) && that.kind.isUnbound() && log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.mref.with.targs")); result = that.type = types.createErrorType(target); log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.bound.mref")); result = that.type = types.createErrorType(target); rs.checkNonAbstract(that.pos(), that.sym);
break; case BOUND: recType = tree.getQualifierExpression().type; break; case UNBOUND: JCExpression bridgeExpr = (tree.getMode() == ReferenceMode.INVOKE) ? bridgeExpressionInvoke(makeReceiver(rcvr)) : bridgeExpressionNew();
Type samDesc = localContext.bridgedRefSig(); List<Type> samPTypes = samDesc.getParameterTypes(); List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes(); case BOUND: rcvr = addParameter("rec$", tree.getQualifierExpression().type, false); receiverExpression = attr.makeNullCheck(tree.getQualifierExpression()); break; case UNBOUND:
init = tree.getQualifierExpression(); init = attr.makeNullCheck(init); break;
if (tree.getMode() == ReferenceMode.NEW && tree.kind != ReferenceKind.ARRAY_CTOR && tree.sym.owner.isLocal()) {
init = tree.getQualifierExpression(); init = attr.makeNullCheck(init); break;
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, attr.memberReferenceQualifierResult(tree)); ListBuffer<Type> argtypes = new ListBuffer<>();
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, attr.memberReferenceQualifierResult(tree)); ListBuffer<Type> argtypes = new ListBuffer<>();
switch (tree.getMode()) { case NEW: if (!tree.expr.type.isRaw()) {
switch (tree.getMode()) { case NEW: if (!tree.expr.type.isRaw()) {
/** * Returns the type of a receiver of a method call expression. Precondition: the expressionTree * corresponds to a method call. * * <p>Examples: * * <pre>{@code * a.b.foo() ==> type of a.b * a.bar().foo() ==> type of a.bar() * this.foo() ==> type of this * foo() ==> type of this * TheClass.aStaticMethod() ==> TheClass * aStaticMethod() ==> type of class in which method is defined * }</pre> */ public static Type getReceiverType(ExpressionTree expressionTree) { if (expressionTree instanceof JCFieldAccess) { JCFieldAccess methodSelectFieldAccess = (JCFieldAccess) expressionTree; return methodSelectFieldAccess.selected.type; } else if (expressionTree instanceof JCIdent) { JCIdent methodCall = (JCIdent) expressionTree; return methodCall.sym.owner.type; } else if (expressionTree instanceof JCMethodInvocation) { return getReceiverType(((JCMethodInvocation) expressionTree).getMethodSelect()); } else if (expressionTree instanceof JCMemberReference) { return ((JCMemberReference) expressionTree).getQualifierExpression().type; } throw new IllegalArgumentException( "Expected a JCFieldAccess or JCIdent from expression " + expressionTree); }
make.Type(types.elemtype(tree.getQualifierExpression().type)), List.of(make.Ident(params.first())), null); newArr.type = tree.getQualifierExpression().type; return newArr; } else { make.Type(tree.getQualifierExpression().type), convertArgs(tree.sym, args.toList(), tree.varargsElement), null); newClass.constructor = tree.sym; newClass.constructorType = tree.sym.erasure(types); newClass.type = tree.getQualifierExpression().type; setVarargsIfNeeded(newClass, tree.varargsElement); return newClass;
/** * Lambda body to use for a 'new'. */ private JCExpression expressionNew() { if (tree.kind == ReferenceKind.ARRAY_CTOR) { //create the array creation expression JCNewArray newArr = make.NewArray( make.Type(types.elemtype(tree.getQualifierExpression().type)), List.of(make.Ident(params.first())), null); newArr.type = tree.getQualifierExpression().type; return newArr; } else { //create the instance creation expression //note that method reference syntax does not allow an explicit //enclosing class (so the enclosing class is null) JCNewClass newClass = make.NewClass(null, List.<JCExpression>nil(), make.Type(tree.getQualifierExpression().type), convertArgs(tree.sym, args.toList(), tree.varargsElement), null); newClass.constructor = tree.sym; newClass.constructorType = tree.sym.erasure(types); newClass.type = tree.getQualifierExpression().type; setVarargsIfNeeded(newClass, tree.varargsElement); return newClass; } }
@Override public void visitReference(JCMemberReference tree) { //perform arity-based check Env<AttrContext> localEnv = env.dup(tree); JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, attr.memberReferenceQualifierResult(tree)); JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); mref2.expr = exprTree; Symbol res = rs.getMemberReference(tree, localEnv, mref2, exprTree.type, tree.name); tree.sym = res; if (res.kind >= Kinds.ERRONEOUS || res.type.hasTag(FORALL) || (res.flags() & Flags.VARARGS) != 0 || (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && exprTree.type.isRaw())) { tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED; } else { tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED; } //a method reference is always a poly expression result = ArgumentExpressionKind.POLY; }
/** * determine the receiver of the bridged method call - the receiver can * be either the synthetic receiver parameter or a type qualifier; the * original qualifier expression is never used here, as it might refer * to symbols not available in the static context of the bridge */ private JCExpression bridgeExpressionInvoke(JCExpression rcvr) { JCExpression qualifier = tree.sym.isStatic() ? make.Type(tree.sym.owner.type) : (rcvr != null) ? rcvr : tree.getQualifierExpression(); //create the qualifier expression JCFieldAccess select = make.Select(qualifier, tree.sym.name); select.sym = tree.sym; select.type = tree.sym.erasure(types); //create the method call expression JCExpression apply = make.Apply(List.<JCExpression>nil(), select, convertArgs(tree.sym, args.toList(), tree.varargsElement)). setType(tree.sym.erasure(types).getReturnType()); apply = transTypes.coerce(apply, localContext.generatedRefSig().getReturnType()); setVarargsIfNeeded(apply, tree.varargsElement); return apply; }