public void visitConstructorCallExpression(ConstructorCallExpression call) {
    isSpecialConstructorCall = call.isSpecialCall();
    super.visitConstructorCallExpression(call);
    isSpecialConstructorCall = false;
    if (!call.isUsingAnonymousInnerClass()) return;

    pushState();
    InnerClassNode innerClass = (InnerClassNode) call.getType();
    innerClass.setVariableScope(currentScope);
    for (MethodNode method : innerClass.getMethods()) {
      Parameter[] parameters = method.getParameters();
      if (parameters.length == 0) parameters = null; // null means no implicit "it"
      ClosureExpression cl = new ClosureExpression(parameters, method.getCode());
      visitClosureExpression(cl);
    }

    for (FieldNode field : innerClass.getFields()) {
      final Expression expression = field.getInitialExpression();
      if (expression != null) {
        expression.visit(this);
      }
    }

    for (Statement statement : innerClass.getObjectInitializerStatements()) {
      statement.visit(this);
    }
    markClosureSharedVariables();
    popState();
  }
  /**
   * Adds the necessary field and methods to support resource locating.
   *
   * @param declaringClass the class to which we add the support field and methods
   */
  public static void apply(@Nonnull ClassNode declaringClass, @Nullable String beanName) {
    injectInterface(declaringClass, EVENT_PUBLISHER_CNODE);

    FieldNode epField =
        injectField(
            declaringClass, EVENT_ROUTER_FIELD_NAME, PRIVATE, EVENT_PUBLISHER_FIELD_CNODE, null);

    Parameter erParam = param(EVENT_ROUTER_CNODE, EVENT_ROUTER_PROPERTY);
    if (!isBlank(beanName)) {
      AnnotationNode namedAnnotation = new AnnotationNode(NAMED_TYPE);
      namedAnnotation.addMember("value", new ConstantExpression(beanName));
      erParam.addAnnotation(namedAnnotation);
    }

    MethodNode setter =
        new MethodNode(
            METHOD_SET_EVENT_ROUTER,
            PRIVATE,
            VOID_TYPE,
            params(erParam),
            NO_EXCEPTIONS,
            stmnt(call(field(epField), METHOD_SET_EVENT_ROUTER, args(var(EVENT_ROUTER_PROPERTY)))));
    setter.addAnnotation(new AnnotationNode(INJECT_TYPE));
    injectMethod(declaringClass, setter);

    addDelegateMethods(declaringClass, EVENT_PUBLISHER_CNODE, field(epField));
  }
  public void visit(ASTNode[] nodes, SourceUnit source) {
    if (nodes.length != 2
        || !(nodes[0] instanceof AnnotationNode)
        || !(nodes[1] instanceof AnnotatedNode)) {
      throw new RuntimeException(
          "Internal error: expecting [AnnotationNode, AnnotatedNode] but got: "
              + Arrays.asList(nodes));
    }

    AnnotationNode annotationNode = (AnnotationNode) nodes[0];
    ASTNode node = nodes[1];

    if (!(node instanceof MethodNode)) {
      addError("@NotYetImplemented must only be applied on test methods!", node);
      return;
    }

    MethodNode methodNode = (MethodNode) node;

    ArrayList<Statement> statements = new ArrayList<Statement>();
    Statement statement = methodNode.getCode();
    if (statement instanceof BlockStatement) {
      statements.addAll(((BlockStatement) statement).getStatements());
    }

    if (statements.size() == 0) return;

    BlockStatement rewrittenMethodCode = new BlockStatement();

    rewrittenMethodCode.addStatement(
        tryCatchAssertionFailedError(annotationNode, methodNode, statements));
    rewrittenMethodCode.addStatement(throwAssertionFailedError(annotationNode));

    methodNode.setCode(rewrittenMethodCode);
  }
Exemple #4
0
 private void setMethodDefaultValue(MethodNode mn, Method m) {
   Object defaultValue = m.getDefaultValue();
   ConstantExpression cExp = ConstantExpression.NULL;
   if (defaultValue != null) cExp = new ConstantExpression(defaultValue);
   mn.setCode(new ReturnStatement(cExp));
   mn.setAnnotationDefault(true);
 }
  /*
   * @see ICpuModel#setCallersCalleesTarget(IMethodNode)
   */
  @Override
  public void setCallersCalleesTarget(IMethodNode targetMethod) {
    callers.clear();
    callees.clear();
    this.callersCalleesTarget = targetMethod;

    String thread = getThread(targetMethod);

    List<CallTreeNode> frameRootNodes = getFrameRootNodes(thread);
    if (frameRootNodes.isEmpty() || targetMethod == null) {
      notifyModelChanged(new CpuModelEvent(CpuModelState.CallersCalleesTargetChanged));
      return;
    }

    List<String> callerNames = new ArrayList<String>();
    List<String> calleeNames = new ArrayList<String>();
    refreshCallersCallees(callerNames, calleeNames, frameRootNodes, targetMethod.getName());

    List<MethodNode> methodNodes = getMethodNodes(thread);

    for (MethodNode methodNode : methodNodes) {
      if (callerNames.contains(methodNode.getName())) {
        callers.add(methodNode);
      }
      if (calleeNames.contains(methodNode.getName())) {
        callees.add(methodNode);
      }
    }

    notifyModelChanged(new CpuModelEvent(CpuModelState.CallersCalleesTargetChanged));
  }
 public void positionStmtsAfterEnumInitStmts(List<Statement> staticFieldStatements) {
   MethodNode method = getOrAddStaticConstructorNode();
   Statement statement = method.getCode();
   if (statement instanceof BlockStatement) {
     BlockStatement block = (BlockStatement) statement;
     // add given statements for explicitly declared static fields just after enum-special fields
     // are found - the $VALUES binary expression marks the end of such fields.
     List<Statement> blockStatements = block.getStatements();
     ListIterator<Statement> litr = blockStatements.listIterator();
     while (litr.hasNext()) {
       Statement stmt = litr.next();
       if (stmt instanceof ExpressionStatement
           && ((ExpressionStatement) stmt).getExpression() instanceof BinaryExpression) {
         BinaryExpression bExp = (BinaryExpression) ((ExpressionStatement) stmt).getExpression();
         if (bExp.getLeftExpression() instanceof FieldExpression) {
           FieldExpression fExp = (FieldExpression) bExp.getLeftExpression();
           if (fExp.getFieldName().equals("$VALUES")) {
             for (Statement tmpStmt : staticFieldStatements) {
               litr.add(tmpStmt);
             }
           }
         }
       }
     }
   }
 }
  public Map<String, MethodNode> getDeclaredMethodsMap() {
    // Start off with the methods from the superclass.
    ClassNode parent = getSuperClass();
    Map<String, MethodNode> result = null;
    if (parent != null) {
      result = parent.getDeclaredMethodsMap();
    } else {
      result = new HashMap<String, MethodNode>();
    }

    // add in unimplemented abstract methods from the interfaces
    for (ClassNode iface : getInterfaces()) {
      Map<String, MethodNode> ifaceMethodsMap = iface.getDeclaredMethodsMap();
      for (String methSig : ifaceMethodsMap.keySet()) {
        if (!result.containsKey(methSig)) {
          MethodNode methNode = ifaceMethodsMap.get(methSig);
          result.put(methSig, methNode);
        }
      }
    }

    // And add in the methods implemented in this class.
    for (MethodNode method : getMethods()) {
      String sig = method.getTypeDescriptor();
      result.put(sig, method);
    }
    return result;
  }
  public void addStaticInitializerStatements(List<Statement> staticStatements, boolean fieldInit) {
    MethodNode method = getOrAddStaticConstructorNode();
    BlockStatement block = null;
    Statement statement = method.getCode();
    if (statement == null) {
      block = new BlockStatement();
    } else if (statement instanceof BlockStatement) {
      block = (BlockStatement) statement;
    } else {
      block = new BlockStatement();
      block.addStatement(statement);
    }

    // while anything inside a static initializer block is appended
    // we don't want to append in the case we have a initialization
    // expression of a static field. In that case we want to add
    // before the other statements
    if (!fieldInit) {
      block.addStatements(staticStatements);
    } else {
      List<Statement> blockStatements = block.getStatements();
      staticStatements.addAll(blockStatements);
      blockStatements.clear();
      blockStatements.addAll(staticStatements);
    }
  }
  /**
   * Main entry point for the calling the TestForTransformation programmatically.
   *
   * @param classNode The class node that represents th test
   * @param ce The class expression that represents the class to test
   */
  public void testFor(ClassNode classNode, ClassExpression ce) {
    boolean junit3Test = isJunit3Test(classNode);

    // make sure the 'log' property is not the one from GroovyTestCase
    FieldNode log = classNode.getField("log");
    if (log == null || log.getDeclaringClass().equals(GROOVY_TEST_CASE_CLASS)) {
      LoggingTransformer.addLogField(classNode, classNode.getName());
    }
    boolean isSpockTest = isSpockTest(classNode);

    if (!isSpockTest && !junit3Test) {
      // assume JUnit 4
      Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap();
      for (String methodName : declaredMethodsMap.keySet()) {
        MethodNode methodNode = declaredMethodsMap.get(methodName);
        if (isCandidateMethod(methodNode) && methodNode.getName().startsWith("test")) {
          if (methodNode.getAnnotations().size() == 0) {
            methodNode.addAnnotation(TEST_ANNOTATION);
          }
        }
      }
    }

    final MethodNode methodToAdd = weaveMock(classNode, ce, true);
    if (methodToAdd != null && junit3Test) {
      addMethodCallsToMethod(classNode, SET_UP_METHOD, Arrays.asList(methodToAdd));
    }
  }
 protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
   visitAnnotations(node);
   visitClassCodeContainer(node.getCode());
   for (Parameter param : node.getParameters()) {
     visitAnnotations(param);
   }
 }
 /**
  * Finds a method matching the given name and parameters in this class or any parent class.
  *
  * @return the method matching the given name and parameters or null
  */
 public MethodNode getMethod(String name, Parameter[] parameters) {
   for (MethodNode method : getMethods(name)) {
     if (parametersEqual(method.getParameters(), parameters)) {
       return method;
     }
   }
   return null;
 }
 @Override
 public void visitToken(DetailAST aAST) {
   if (isOverridingMethod(aAST)) {
     mMethodStack.add(new MethodNode(aAST));
   } else if (isSuperCall(aAST)) {
     final MethodNode methodNode = mMethodStack.getLast();
     methodNode.setCallsSuper();
   }
 }
 private void checkMethodModifiers(MethodNode node) {
   // don't check volatile here as it overlaps with ACC_BRIDGE
   // additional modifiers not allowed for interfaces
   if ((this.currentClass.getModifiers() & ACC_INTERFACE) != 0) {
     checkMethodForModifier(node, isStrict(node.getModifiers()), "strictfp");
     checkMethodForModifier(node, isSynchronized(node.getModifiers()), "synchronized");
     checkMethodForModifier(node, isNative(node.getModifiers()), "native");
   }
 }
 public void addMethod(MethodNode node) {
   node.setDeclaringClass(this);
   ClassNode base = redirect();
   if (base.methodsList.isEmpty()) {
     base.methodsList = new ArrayList<MethodNode>();
   }
   base.methodsList.add(node);
   base.methods.put(node.getName(), node);
 }
 private void memorizeInitialExpressions(final MethodNode node) {
   // add node metadata for default parameters because they are erased by the Verifier
   if (node.getParameters() != null) {
     for (Parameter parameter : node.getParameters()) {
       parameter.putNodeMetaData(
           StaticTypesMarker.INITIAL_EXPRESSION, parameter.getInitialExpression());
     }
   }
 }
 private void visitMethodNode(MethodNode methodNode) {
   if (methodNode.isSyntheticPublic()) revertVisibility(methodNode);
   else
     throw new RuntimeException(
         "Can't use "
             + MY_TYPE_NAME
             + " for method '"
             + methodNode.getName()
             + "' which has explicit visibility.");
 }
 @Override
 public void leaveToken(DetailAST aAST) {
   if (isOverridingMethod(aAST)) {
     final MethodNode methodNode = mMethodStack.removeLast();
     if (!methodNode.getCallsSuper()) {
       final DetailAST methodAST = methodNode.getMethod();
       final DetailAST nameAST = methodAST.findFirstToken(TokenTypes.IDENT);
       log(nameAST.getLineNo(), nameAST.getColumnNo(), "missing.super.call", nameAST.getText());
     }
   }
 }
  /**
   * 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);
    }
  }
 public void visitMethod(MethodNode node) {
   inConstructor = false;
   inStaticConstructor = node.isStaticConstructor();
   checkAbstractDeclaration(node);
   checkRepetitiveMethod(node);
   checkOverloadingPrivateAndPublic(node);
   checkMethodModifiers(node);
   checkGenericsUsage(node, node.getParameters());
   checkGenericsUsage(node, node.getReturnType());
   super.visitMethod(node);
 }
 /**
  * Tests whether the ClassNode implements the specified method name
  *
  * @param classNode The ClassNode
  * @param methodName The method name
  * @param argTypes
  * @return True if it implements the method
  */
 private static boolean implementsMethod(
     ClassNode classNode, String methodName, Class[] argTypes) {
   List methods = classNode.getMethods();
   for (Iterator i = methods.iterator(); i.hasNext(); ) {
     MethodNode mn = (MethodNode) i.next();
     final boolean isZeroArg = (argTypes == null || argTypes.length == 0);
     boolean methodMatch = mn.getName().equals(methodName) && isZeroArg;
     if (methodMatch) return true;
     // TODO Implement further parameter analysis
   }
   return false;
 }
 /** Adds a synthetic method as part of the compilation process */
 public MethodNode addSyntheticMethod(
     String name,
     int modifiers,
     ClassNode returnType,
     Parameter[] parameters,
     ClassNode[] exceptions,
     Statement code) {
   MethodNode answer =
       addMethod(name, modifiers | ACC_SYNTHETIC, returnType, parameters, exceptions, code);
   answer.setSynthetic(true);
   return answer;
 }
 private void checkAbstractDeclaration(MethodNode methodNode) {
   if (!methodNode.isAbstract()) return;
   if (isAbstract(currentClass.getModifiers())) return;
   addError(
       "Can't have an abstract method in a non-abstract class."
           + " The "
           + getDescription(currentClass)
           + " must be declared abstract or the method '"
           + methodNode.getTypeDescriptor()
           + "' must not be abstract.",
       methodNode);
 }
 public MethodNode getSetterMethod(String setterName, boolean voidOnly) {
   for (MethodNode method : getDeclaredMethods(setterName)) {
     if (setterName.equals(method.getName())
         && (!voidOnly || ClassHelper.VOID_TYPE == method.getReturnType())
         && method.getParameters().length == 1) {
       return method;
     }
   }
   ClassNode parent = getSuperClass();
   if (parent != null) return parent.getSetterMethod(setterName, voidOnly);
   return null;
 }
 public MethodNode getGetterMethod(String getterName) {
   for (MethodNode method : getDeclaredMethods(getterName)) {
     if (getterName.equals(method.getName())
         && ClassHelper.VOID_TYPE != method.getReturnType()
         && method.getParameters().length == 0) {
       return method;
     }
   }
   ClassNode parent = getSuperClass();
   if (parent != null) return parent.getGetterMethod(getterName);
   return null;
 }
  /**
   * @return the list of abstract methods associated with this ClassNode or null if there are no
   *     such methods
   */
  public List<MethodNode> getAbstractMethods() {
    List<MethodNode> result = new ArrayList<MethodNode>(3);
    for (MethodNode method : getDeclaredMethodsMap().values()) {
      if (method.isAbstract()) {
        result.add(method);
      }
    }

    if (result.isEmpty()) {
      return null;
    } else {
      return result;
    }
  }
 private void visitDeprecation(AnnotatedNode node, AnnotationNode visited) {
   if (visited.getClassNode().isResolved()
       && visited.getClassNode().getName().equals("java.lang.Deprecated")) {
     if (node instanceof MethodNode) {
       MethodNode mn = (MethodNode) node;
       mn.setModifiers(mn.getModifiers() | Opcodes.ACC_DEPRECATED);
     } else if (node instanceof FieldNode) {
       FieldNode fn = (FieldNode) node;
       fn.setModifiers(fn.getModifiers() | Opcodes.ACC_DEPRECATED);
     } else if (node instanceof ClassNode) {
       ClassNode cn = (ClassNode) node;
       cn.setModifiers(cn.getModifiers() | Opcodes.ACC_DEPRECATED);
     }
   }
 }
Exemple #27
0
 /**
  * Checks that this class node is compatible with the given ASM API version. This methods checks
  * that this node, and all its nodes recursively, do not contain elements that were introduced in
  * more recent versions of the ASM API than the given version.
  *
  * @param api an ASM API version. Must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
  */
 public void check(final int api) {
   if (api == Opcodes.ASM4) {
     if (visibleTypeAnnotations != null && visibleTypeAnnotations.size() > 0) {
       throw new RuntimeException();
     }
     if (invisibleTypeAnnotations != null && invisibleTypeAnnotations.size() > 0) {
       throw new RuntimeException();
     }
     for (FieldNode f : fields) {
       f.check(api);
     }
     for (MethodNode m : methods) {
       m.check(api);
     }
   }
 }
 private MethodNode generateIsBattleMode() {
   MethodNode mv = new MethodNode(ACC_PUBLIC, "isBattlemode", "()Z", null, null);
   mv.visitCode();
   Label l0 = new Label();
   mv.visitLabel(l0);
   mv.visitVarInsn(ALOAD, 0);
   mv.visitMethodInsn(
       INVOKESTATIC, UTILITY_CLASS, "isPlayerInBattlemode", "(L" + entityPlayerClassName + ";)Z");
   mv.visitInsn(IRETURN);
   Label l1 = new Label();
   mv.visitLabel(l1);
   mv.visitLocalVariable("this", "L" + entityPlayerClassName + ";", null, l0, l1, 0);
   mv.visitMaxs(1, 1);
   mv.visitEnd();
   return mv;
 }
  private String getPropertyName(MethodNode m) {
    String name = m.getName();
    if (!(name.startsWith("set") || name.startsWith("get"))) return null;
    String pname = name.substring(3);
    if (pname.length() == 0) return null;
    pname = java.beans.Introspector.decapitalize(pname);

    if (name.startsWith("get")
        && (m.getReturnType() == ClassHelper.VOID_TYPE || m.getParameters().length != 0)) {
      return null;
    }
    if (name.startsWith("set") && m.getParameters().length != 1) {
      return null;
    }
    return pname;
  }
  private int firePeacefulRegenEventAndStoreEventBefore(
      MethodNode method, AbstractInsnNode injectPoint, LabelNode endLabel) {
    // create  variable
    LabelNode peacefulRegenEventStart = new LabelNode();
    LocalVariableNode peacefulRegenEvent =
        new LocalVariableNode(
            "peacefulRegenEvent",
            Type.getDescriptor(HealthRegenEvent.PeacefulRegen.class),
            null,
            peacefulRegenEventStart,
            endLabel,
            method.maxLocals);
    method.maxLocals += 1;
    method.localVariables.add(peacefulRegenEvent);

    InsnList toInject = new InsnList();

    // HealthRegenEvent.PeacefulRegen peacefulRegenEvent = Hooks.firePeacefulRegenEvent(this);
    toInject.add(new VarInsnNode(ALOAD, 0));
    toInject.add(
        new MethodInsnNode(
            INVOKESTATIC,
            Type.getInternalName(Hooks.class),
            "firePeacefulRegenEvent",
            "(Lnet/minecraft/entity/player/EntityPlayer;)Lsqueek/applecore/api/hunger/HealthRegenEvent$PeacefulRegen;",
            false));
    toInject.add(new VarInsnNode(ASTORE, peacefulRegenEvent.index));
    toInject.add(peacefulRegenEventStart);

    method.instructions.insertBefore(injectPoint, toInject);

    return peacefulRegenEvent.index;
  }