@Override public void visitTypeCast( JCTypeCast tree ) { super.visitTypeCast( tree ); if( _tp.isGenerate() && !shouldProcessForGeneration() ) { eraseCompilerGeneratedCast( tree ); // Don't process tree during GENERATE, unless the tree was generated e.g., a bridge method return; } if( TypeUtil.isStructuralInterface( _tp, tree.type.tsym ) ) { tree.expr = replaceCastExpression( tree.getExpression(), tree.type ); tree.type = getObjectClass().type; } result = tree; }
protected int diffTypeCast(JCTypeCast oldT, JCTypeCast newT, int[] bounds) { int localPointer = bounds[0]; // indexed int[] clazzBounds = getBounds(oldT.clazz); copyTo(localPointer, clazzBounds[0]); localPointer = diffTree(oldT.clazz, newT.clazz, clazzBounds); // expression int[] exprBounds = getBounds(oldT.expr); exprBounds[0] = copyUpTo(localPointer, exprBounds[0]); localPointer = diffTree(oldT.expr, newT.expr, exprBounds); localPointer = copyUpTo(localPointer, bounds[1]); return localPointer; }
private void eraseCompilerGeneratedCast( JCTypeCast tree ) { // the javac compiler generates casts e.g., for a generic call such as List#get() if( TypeUtil.isStructuralInterface( _tp, tree.type.tsym ) && !isConstructProxyCall( tree.getExpression() ) ) { tree.type = getObjectClass().type; TreeMaker make = _tp.getTreeMaker(); tree.clazz = make.Type( getObjectClass().type ); } }
private boolean isConstructProxyCall( JCExpression expression ) { if( expression instanceof JCTree.JCMethodInvocation ) { // don't erase cast if we generated it here e.g.., for structural call cast on constructProxy JCExpression meth = ((JCTree.JCMethodInvocation)expression).meth; return meth instanceof JCTree.JCFieldAccess && ((JCTree.JCFieldAccess)meth).getIdentifier().toString().equals( "constructProxy" ); } return expression instanceof JCTypeCast && isConstructProxyCall( ((JCTypeCast)expression).getExpression() ); }
private JCExpression replaceCastExpression( JCExpression expression, Type type ) { TreeMaker make = _tp.getTreeMaker(); Symtab symbols = _tp.getSymtab(); Names names = Names.instance( _tp.getContext() ); JavacElements elementUtils = JavacElements.instance( _tp.getContext() ); Symbol.ClassSymbol reflectMethodClassSym = elementUtils.getTypeElement( getClass().getName() ); Symbol.MethodSymbol makeInterfaceProxyMethod = resolveMethod( expression.pos(), names.fromString( "assignStructuralIdentity" ), reflectMethodClassSym.type, List.from( new Type[]{symbols.objectType, symbols.classType} ) ); JavacElements javacElems = _tp.getElementUtil(); ArrayList<JCExpression> newArgs = new ArrayList<>(); newArgs.add( expression ); JCTree.JCFieldAccess ifaceClassExpr = (JCTree.JCFieldAccess)memberAccess( make, javacElems, type.tsym.getQualifiedName().toString() + ".class" ); ifaceClassExpr.type = symbols.classType; ifaceClassExpr.sym = symbols.classType.tsym; assignTypes( ifaceClassExpr.selected, type.tsym ); newArgs.add( ifaceClassExpr ); JCTree.JCMethodInvocation makeProxyCall = make.Apply( List.nil(), memberAccess( make, javacElems, ExtensionTransformer.class.getName() + ".assignStructuralIdentity" ), List.from( newArgs ) ); makeProxyCall.type = symbols.objectType; JCTree.JCFieldAccess newMethodSelect = (JCTree.JCFieldAccess)makeProxyCall.getMethodSelect(); newMethodSelect.sym = makeInterfaceProxyMethod; newMethodSelect.type = makeInterfaceProxyMethod.type; assignTypes( newMethodSelect.selected, reflectMethodClassSym ); JCTypeCast castCall = make.TypeCast( symbols.objectType, makeProxyCall ); castCall.type = symbols.objectType; return castCall; }
public void doAssignmentCheck0(JavacNode node, JCTree statement, Name name) { if (statement instanceof JCAssign) doAssignmentCheck0(node, ((JCAssign)statement).rhs, name); if (statement instanceof JCExpressionStatement) doAssignmentCheck0(node, ((JCExpressionStatement)statement).expr, name); if (statement instanceof JCVariableDecl) doAssignmentCheck0(node, ((JCVariableDecl)statement).init, name); if (statement instanceof JCTypeCast) doAssignmentCheck0(node, ((JCTypeCast)statement).expr, name); if (statement instanceof JCIdent) { if (((JCIdent)statement).name.contentEquals(name)) { JavacNode problemNode = node.getNodeFor(statement); if (problemNode != null) problemNode.addWarning( "You're assigning an auto-cleanup variable to something else. This is a bad idea."); } } }
public void visitTypeCast(JCTypeCast that) { try { print("JCTypeCast:"); } catch (Exception e) { } super.visitTypeCast(that); }
public void visitTypeCast(JCTypeCast tree) { try { open(prec, TreeInfo.prefixPrec); print("("); printExpr(tree.clazz); print(")"); printExpr(tree.expr, TreeInfo.prefixPrec); close(prec, TreeInfo.prefixPrec); } catch (IOException e) { throw new UncheckedIOException(e); } }
@Override public Choice<State<JCTypeCast>> visitTypeCast(final TypeCastTree node, State<?> state) { return chooseSubtrees( state, s -> unifyExpression(node.getExpression(), s), expr -> maker().TypeCast((JCTree) node.getType(), expr)); }
public void visitTypeCast(JCTypeCast tree) { Type clazztype = attribType(tree.clazz, env); chk.validate(tree.clazz, env, false); //a fresh environment is required for 292 inference to work properly --- //see Infer.instantiatePolymorphicSignatureInstance() Env<AttrContext> localEnv = env.dup(tree); Type exprtype = attribExpr(tree.expr, localEnv, Infer.anyPoly); Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype); if (exprtype.constValue() != null) owntype = cfolder.coerce(exprtype, owntype); result = check(tree, capture(owntype), VAL, pkind, pt); }
private void doAssignmentCheck0(JavacNode node, JCTree statement, Name name) { if (statement instanceof JCAssign) doAssignmentCheck0(node, ((JCAssign)statement).rhs, name); if (statement instanceof JCExpressionStatement) doAssignmentCheck0(node, ((JCExpressionStatement)statement).expr, name); if (statement instanceof JCVariableDecl) doAssignmentCheck0(node, ((JCVariableDecl)statement).init, name); if (statement instanceof JCTypeCast) doAssignmentCheck0(node, ((JCTypeCast)statement).expr, name); if (statement instanceof JCIdent) { if (((JCIdent)statement).name.contentEquals(name)) { JavacNode problemNode = node.getNodeFor(statement); if (problemNode != null) problemNode.addWarning( "You're assigning an auto-cleanup variable to something else. This is a bad idea."); } } }
private boolean matchTypeCast(JCTypeCast t1, JCTypeCast t2) { return treesMatch(t1.clazz, t2.clazz) && treesMatch(t1.expr, t2.expr); }
/** * Compute a synthetic method type corresponding to the requested polymorphic * method signature. The target return type is computed from the immediately * enclosing scope surrounding the polymorphic-signature call. */ Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, Type site, Name name, MethodSymbol spMethod, // sig. poly. method or null if none List<Type> argtypes) { final Type restype; //The return type for a polymorphic signature call is computed from //the enclosing tree E, as follows: if E is a cast, then use the //target type of the cast expression as a return type; if E is an //expression statement, the return type is 'void' - otherwise the //return type is simply 'Object'. A correctness check ensures that //env.next refers to the lexically enclosing environment in which //the polymorphic signature call environment is nested. switch (env.next.tree.getTag()) { case JCTree.TYPECAST: JCTypeCast castTree = (JCTypeCast)env.next.tree; restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ? castTree.clazz.type : syms.objectType; break; case JCTree.EXEC: JCTree.JCExpressionStatement execTree = (JCTree.JCExpressionStatement)env.next.tree; restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ? syms.voidType : syms.objectType; break; default: restype = syms.objectType; } List<Type> paramtypes = Type.map(argtypes, implicitArgType); List<Type> exType = spMethod != null ? spMethod.getThrownTypes() : List.of(syms.throwableType); // make it throw all exceptions MethodType mtype = new MethodType(paramtypes, restype, exType, syms.methodClass); return mtype; }
/** * Compute a synthetic method type corresponding to the requested polymorphic * method signature. The target return type is computed from the immediately * enclosing scope surrounding the polymorphic-signature call. */ Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, MethodSymbol spMethod, // sig. poly. method or null if none Resolve.MethodResolutionContext resolveContext, List<Type> argtypes) { final Type restype; //The return type for a polymorphic signature call is computed from //the enclosing tree E, as follows: if E is a cast, then use the //target type of the cast expression as a return type; if E is an //expression statement, the return type is 'void' - otherwise the //return type is simply 'Object'. A correctness check ensures that //env.next refers to the lexically enclosing environment in which //the polymorphic signature call environment is nested. switch (env.next.tree.getTag()) { case TYPECAST: JCTypeCast castTree = (JCTypeCast)env.next.tree; restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ? castTree.clazz.type : syms.objectType; break; case EXEC: JCTree.JCExpressionStatement execTree = (JCTree.JCExpressionStatement)env.next.tree; restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ? syms.voidType : syms.objectType; break; default: restype = syms.objectType; } List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step)); List<Type> exType = spMethod != null ? spMethod.getThrownTypes() : List.of(syms.throwableType); // make it throw all exceptions MethodType mtype = new MethodType(paramtypes, restype, exType, syms.methodClass); return mtype; }
/** * Compute a synthetic method type corresponding to the requested polymorphic * method signature. The target return type is computed from the immediately * enclosing scope surrounding the polymorphic-signature call. */ Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, MethodSymbol spMethod, // sig. poly. method or null if none Resolve.MethodResolutionContext resolveContext, List<Type> argtypes) { final Type restype; if (spMethod == null || types.isSameType(spMethod.getReturnType(), syms.objectType, true)) { // The return type of the polymorphic signature is polymorphic, // and is computed from the enclosing tree E, as follows: // if E is a cast, then use the target type of the cast expression // as a return type; if E is an expression statement, the return // type is 'void'; otherwise // the return type is simply 'Object'. A correctness check ensures // that env.next refers to the lexically enclosing environment in // which the polymorphic signature call environment is nested. switch (env.next.tree.getTag()) { case TYPECAST: JCTypeCast castTree = (JCTypeCast)env.next.tree; restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ? castTree.clazz.type : syms.objectType; break; case EXEC: JCTree.JCExpressionStatement execTree = (JCTree.JCExpressionStatement)env.next.tree; restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ? syms.voidType : syms.objectType; break; default: restype = syms.objectType; } } else { // The return type of the polymorphic signature is fixed // (not polymorphic) restype = spMethod.getReturnType(); } List<Type> paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step)); List<Type> exType = spMethod != null ? spMethod.getThrownTypes() : List.of(syms.throwableType); // make it throw all exceptions MethodType mtype = new MethodType(paramtypes, restype, exType, syms.methodClass); return mtype; }
private JCTree replaceStructuralCall( JCTree.JCMethodInvocation theCall ) { JCExpression methodSelect = theCall.getMethodSelect(); if( methodSelect instanceof JCTree.JCFieldAccess ) { Symtab symbols = _tp.getSymtab(); Names names = Names.instance( _tp.getContext() ); JavacElements elementUtils = JavacElements.instance( _tp.getContext() ); Symbol.ClassSymbol reflectMethodClassSym = elementUtils.getTypeElement( getClass().getName() ); Symbol.MethodSymbol makeInterfaceProxyMethod = resolveMethod( theCall.pos(), names.fromString( "constructProxy" ), reflectMethodClassSym.type, List.from( new Type[]{symbols.objectType, symbols.classType} ) ); JCTree.JCFieldAccess m = (JCTree.JCFieldAccess)methodSelect; TreeMaker make = _tp.getTreeMaker(); JavacElements javacElems = _tp.getElementUtil(); JCExpression thisArg = m.selected; ArrayList<JCExpression> newArgs = new ArrayList<>(); newArgs.add( thisArg ); JCTree.JCFieldAccess ifaceClassExpr = (JCTree.JCFieldAccess)memberAccess( make, javacElems, thisArg.type.tsym.getQualifiedName().toString() + ".class" ); ifaceClassExpr.type = symbols.classType; ifaceClassExpr.sym = symbols.classType.tsym; assignTypes( ifaceClassExpr.selected, thisArg.type.tsym ); newArgs.add( ifaceClassExpr ); JCTree.JCMethodInvocation makeProxyCall = make.Apply( List.nil(), memberAccess( make, javacElems, ExtensionTransformer.class.getName() + ".constructProxy" ), List.from( newArgs ) ); makeProxyCall.setPos( theCall.pos ); makeProxyCall.type = thisArg.type; JCTree.JCFieldAccess newMethodSelect = (JCTree.JCFieldAccess)makeProxyCall.getMethodSelect(); newMethodSelect.sym = makeInterfaceProxyMethod; newMethodSelect.type = makeInterfaceProxyMethod.type; assignTypes( newMethodSelect.selected, reflectMethodClassSym ); JCTypeCast cast = make.TypeCast( thisArg.type, makeProxyCall ); cast.type = thisArg.type; ((JCTree.JCFieldAccess)theCall.meth).selected = cast; return theCall; } return null; }
public JCTypeCast TypeCast(JCTree expr, JCExpression type) { return invoke(TypeCast, expr, type); }
@Override public void visitTypeCast(JCTypeCast tree) { print("("); print(tree.clazz); print(") "); print(tree.expr); }
public AJCTypeCast(JCTypeCast ltree) { super(ltree.clazz, ltree.expr); }
public AJCTypeCast(JCTypeCast ltree, String lcomment) { this(ltree); setComment(lcomment); }
/** * Returns the precedence level appropriate for unambiguously printing * leaf as a subexpression of its parent. */ private static int getPrecedence(JCTree leaf, Context context) { JCCompilationUnit comp = context.get(JCCompilationUnit.class); JCTree parent = TreeInfo.pathFor(leaf, comp).get(1); // In general, this should match the logic in com.sun.tools.javac.tree.Pretty. // // TODO(mdempsky): There are probably cases where we could omit parentheses // by tweaking the returned precedence, but they need careful review. // For example, consider a template to replace "add(a, b)" with "a + b", // which applied to "x + add(y, z)" would result in "x + (y + z)". // In most cases, we'd likely prefer "x + y + z" instead, but those aren't // always equivalent: "0L + (Integer.MIN_VALUE + Integer.MIN_VALUE)" yields // a different value than "0L + Integer.MIN_VALUE + Integer.MIN_VALUE" due // to integer promotion rules. if (parent instanceof JCConditional) { // This intentionally differs from Pretty, because Pretty appears buggy: // http://mail.openjdk.java.net/pipermail/compiler-dev/2013-September/007303.html JCConditional conditional = (JCConditional) parent; return TreeInfo.condPrec + ((conditional.cond == leaf) ? 1 : 0); } else if (parent instanceof JCAssign) { JCAssign assign = (JCAssign) parent; return TreeInfo.assignPrec + ((assign.lhs == leaf) ? 1 : 0); } else if (parent instanceof JCAssignOp) { JCAssignOp assignOp = (JCAssignOp) parent; return TreeInfo.assignopPrec + ((assignOp.lhs == leaf) ? 1 : 0); } else if (parent instanceof JCUnary) { return TreeInfo.opPrec(parent.getTag()); } else if (parent instanceof JCBinary) { JCBinary binary = (JCBinary) parent; return TreeInfo.opPrec(parent.getTag()) + ((binary.rhs == leaf) ? 1 : 0); } else if (parent instanceof JCTypeCast) { JCTypeCast typeCast = (JCTypeCast) parent; return (typeCast.expr == leaf) ? TreeInfo.prefixPrec : TreeInfo.noPrec; } else if (parent instanceof JCInstanceOf) { JCInstanceOf instanceOf = (JCInstanceOf) parent; return TreeInfo.ordPrec + ((instanceOf.clazz == leaf) ? 1 : 0); } else if (parent instanceof JCArrayAccess) { JCArrayAccess arrayAccess = (JCArrayAccess) parent; return (arrayAccess.indexed == leaf) ? TreeInfo.postfixPrec : TreeInfo.noPrec; } else if (parent instanceof JCFieldAccess) { JCFieldAccess fieldAccess = (JCFieldAccess) parent; return (fieldAccess.selected == leaf) ? TreeInfo.postfixPrec : TreeInfo.noPrec; } else { return TreeInfo.noPrec; } }
@Override public JCTypeCast inline(Inliner inliner) throws CouldNotResolveImportException { return inliner.maker().TypeCast(getType().inline(inliner), getExpression().inline(inliner)); }
@Override public void visitTypeCast(JCTypeCast tree) { printNode(tree); child("clazz", tree.clazz); child("expr", tree.expr); indent--; }
@Override public void visitTypeCast(JCTypeCast node) { Cast cast = new Cast(); cast.rawOperand(toTree(node.getExpression())); cast.rawTypeReference(toTree(node.getType(), FlagKey.TYPE_REFERENCE)); set(node, cast); }
/** * Returns the precedence level appropriate for unambiguously printing leaf as a subexpression of * its parent. */ private static int getPrecedence(JCTree leaf, Context context) { JCCompilationUnit comp = context.get(JCCompilationUnit.class); JCTree parent = TreeInfo.pathFor(leaf, comp).get(1); // In general, this should match the logic in com.sun.tools.javac.tree.Pretty. // // TODO(mdempsky): There are probably cases where we could omit parentheses // by tweaking the returned precedence, but they need careful review. // For example, consider a template to replace "add(a, b)" with "a + b", // which applied to "x + add(y, z)" would result in "x + (y + z)". // In most cases, we'd likely prefer "x + y + z" instead, but those aren't // always equivalent: "0L + (Integer.MIN_VALUE + Integer.MIN_VALUE)" yields // a different value than "0L + Integer.MIN_VALUE + Integer.MIN_VALUE" due // to integer promotion rules. if (parent instanceof JCConditional) { // This intentionally differs from Pretty, because Pretty appears buggy: // http://mail.openjdk.java.net/pipermail/compiler-dev/2013-September/007303.html JCConditional conditional = (JCConditional) parent; return TreeInfo.condPrec + ((conditional.cond == leaf) ? 1 : 0); } else if (parent instanceof JCAssign) { JCAssign assign = (JCAssign) parent; return TreeInfo.assignPrec + ((assign.lhs == leaf) ? 1 : 0); } else if (parent instanceof JCAssignOp) { JCAssignOp assignOp = (JCAssignOp) parent; return TreeInfo.assignopPrec + ((assignOp.lhs == leaf) ? 1 : 0); } else if (parent instanceof JCUnary) { return TreeInfo.opPrec(parent.getTag()); } else if (parent instanceof JCBinary) { JCBinary binary = (JCBinary) parent; return TreeInfo.opPrec(parent.getTag()) + ((binary.rhs == leaf) ? 1 : 0); } else if (parent instanceof JCTypeCast) { JCTypeCast typeCast = (JCTypeCast) parent; return (typeCast.expr == leaf) ? TreeInfo.prefixPrec : TreeInfo.noPrec; } else if (parent instanceof JCInstanceOf) { JCInstanceOf instanceOf = (JCInstanceOf) parent; return TreeInfo.ordPrec + ((instanceOf.clazz == leaf) ? 1 : 0); } else if (parent instanceof JCArrayAccess) { JCArrayAccess arrayAccess = (JCArrayAccess) parent; return (arrayAccess.indexed == leaf) ? TreeInfo.postfixPrec : TreeInfo.noPrec; } else if (parent instanceof JCFieldAccess) { JCFieldAccess fieldAccess = (JCFieldAccess) parent; return (fieldAccess.selected == leaf) ? TreeInfo.postfixPrec : TreeInfo.noPrec; } else { return TreeInfo.noPrec; } }