/**
   * This method is used to add "bridge" methods for private methods of an inner/outer class, so
   * that the outer class is capable of calling them. It does basically the same job as access$000
   * like methods in Java.
   *
   * @param node an inner/outer class node for which to generate bridge methods
   */
  @SuppressWarnings("unchecked")
  private void addPrivateBridgeMethods(final ClassNode node) {
    Set<ASTNode> accessedMethods =
        (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS);
    if (accessedMethods == null) return;
    List<MethodNode> methods = new ArrayList<MethodNode>(node.getAllDeclaredMethods());
    Map<MethodNode, MethodNode> privateBridgeMethods =
        (Map<MethodNode, MethodNode>) node.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
    if (privateBridgeMethods != null) {
      // private bridge methods already added
      return;
    }
    privateBridgeMethods = new HashMap<MethodNode, MethodNode>();
    int i = -1;
    final int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC;
    for (MethodNode method : methods) {
      if (accessedMethods.contains(method)) {
        i++;
        Parameter[] methodParameters = method.getParameters();
        Parameter[] newParams = new Parameter[methodParameters.length + 1];
        System.arraycopy(methodParameters, 0, newParams, 1, methodParameters.length);
        newParams[0] = new Parameter(node.getPlainNodeReference(), "$that");
        Expression arguments;
        if (method.getParameters() == null || method.getParameters().length == 0) {
          arguments = ArgumentListExpression.EMPTY_ARGUMENTS;
        } else {
          List<Expression> args = new LinkedList<Expression>();
          for (Parameter parameter : methodParameters) {
            args.add(new VariableExpression(parameter));
          }
          arguments = new ArgumentListExpression(args);
        }
        Expression receiver =
            method.isStatic() ? new ClassExpression(node) : new VariableExpression(newParams[0]);
        MethodCallExpression mce = new MethodCallExpression(receiver, method.getName(), arguments);
        mce.setMethodTarget(method);

        ExpressionStatement returnStatement = new ExpressionStatement(mce);
        MethodNode bridge =
            node.addMethod(
                "access$" + i,
                access,
                method.getReturnType(),
                newParams,
                method.getExceptions(),
                returnStatement);
        privateBridgeMethods.put(method, bridge);
        bridge.addAnnotation(new AnnotationNode(COMPILESTATIC_CLASSNODE));
      }
    }
    if (!privateBridgeMethods.isEmpty()) {
      node.setNodeMetaData(PRIVATE_BRIDGE_METHODS, privateBridgeMethods);
    }
  }
Пример #2
0
 /**
  * If constructor does not define a call to super, then transform constructor to get String,int
  * parameters at beginning and add call super(String,int).
  */
 private void transformConstructor(ConstructorNode ctor, boolean isAic) {
   boolean chainedThisConstructorCall = false;
   ConstructorCallExpression cce = null;
   if (ctor.firstStatementIsSpecialConstructorCall()) {
     Statement code = ctor.getFirstStatement();
     cce = (ConstructorCallExpression) ((ExpressionStatement) code).getExpression();
     if (cce.isSuperCall()) return;
     // must be call to this(...)
     chainedThisConstructorCall = true;
   }
   // we need to add parameters
   Parameter[] oldP = ctor.getParameters();
   Parameter[] newP = new Parameter[oldP.length + 2];
   String stringParameterName = getUniqueVariableName("__str", ctor.getCode());
   newP[0] = new Parameter(ClassHelper.STRING_TYPE, stringParameterName);
   String intParameterName = getUniqueVariableName("__int", ctor.getCode());
   newP[1] = new Parameter(ClassHelper.int_TYPE, intParameterName);
   System.arraycopy(oldP, 0, newP, 2, oldP.length);
   ctor.setParameters(newP);
   VariableExpression stringVariable = new VariableExpression(newP[0]);
   VariableExpression intVariable = new VariableExpression(newP[1]);
   if (chainedThisConstructorCall) {
     TupleExpression args = (TupleExpression) cce.getArguments();
     List<Expression> argsExprs = args.getExpressions();
     argsExprs.add(0, stringVariable);
     argsExprs.add(1, intVariable);
   } else {
     // add a super call
     List<Expression> args = new ArrayList<Expression>();
     args.add(stringVariable);
     args.add(intVariable);
     if (isAic) {
       for (Parameter parameter : oldP) {
         args.add(new VariableExpression(parameter.getName()));
       }
     }
     cce = new ConstructorCallExpression(ClassNode.SUPER, new ArgumentListExpression(args));
     BlockStatement code = new BlockStatement();
     code.addStatement(new ExpressionStatement(cce));
     Statement oldCode = ctor.getCode();
     if (oldCode != null) code.addStatement(oldCode);
     ctor.setCode(code);
   }
 }