private AnnotatedNode createMethodDeclaration(
      String finderName,
      String[] props,
      String[] comparators,
      String newPropName,
      String newComparator) {
    // need to determine number of parameters

    // first figure out how many properties we need to look at
    int numArgs = -1;
    if (newPropName != null) {
      for (int i = 0; i < props.length; i++) {
        if (props[i] == null) {
          props[i] = newPropName;
          numArgs = i + 1;
          break;
        }
      }
    }
    if (newComparator != null) {
      for (int i = 0; i < comparators.length; i++) {
        if (comparators[i] == null) {
          comparators[i] = newComparator;
          numArgs = i + 1;
          break;
        }
      }
    }

    List<Parameter> params = new ArrayList<Parameter>(2);
    // now go through each component and comparator.
    // determine the kind of parameters they require
    for (int i = 0; i < numArgs; i++) {
      ClassNode[] classNodes = COMPARATOR_ARGUMENT_MAP.get(comparators[i]);
      if (classNodes.length > 0) {
        String uncapitalized = uncapitalize(props[i]);
        params.add(new Parameter(classNodes[0], uncapitalized));
        if (classNodes.length == 2) {
          params.add(new Parameter(classNodes[1], uncapitalized + "1"));
        }
      }
    }

    MethodNode method =
        new MethodNode(
            finderName,
            Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC,
            createReturnType(finderName),
            params.toArray(new Parameter[params.size()]),
            NO_EXCEPTIONS,
            EMPTY_BLOCK);
    if (domain != null) {
      method.setDeclaringClass(domain.getGroovyClass());
    } else {
      method.setDeclaringClass(VariableScope.OBJECT_CLASS_NODE);
    }
    return method;
  }
 private MethodNode toMethod(ClassNode declaringType, ResolverCache resolver) {
   if (cachedRegularParameters == null) {
     cachedRegularParameters = initParams(params, resolver);
     cachedOptionalParameters = initParams(optionalParams, resolver);
     cachedNamedParameters = initParams(namedParams, resolver);
     if (cachedReturnType == null) {
       if (resolver != null) {
         cachedReturnType = resolver.resolve(returnType);
       } else {
         cachedReturnType = VariableScope.OBJECT_CLASS_NODE;
       }
     }
   }
   MethodNode meth =
       new NamedArgsMethodNode(
           methodName,
           opcode(),
           cachedReturnType,
           cachedRegularParameters,
           cachedNamedParameters,
           cachedOptionalParameters,
           NO_EXCEPTIONS,
           EMPTY_BLOCK);
   meth.setDeclaringClass(ensureDeclaringType(declaringType, resolver));
   return meth;
 }
  private boolean makeGetPropertyWithGetter(
      final Expression receiver,
      final ClassNode receiverType,
      final String methodName,
      final boolean safe,
      final boolean implicitThis) {
    // does a getter exists ?
    String getterName = "get" + MetaClassHelper.capitalize(methodName);
    MethodNode getterNode = receiverType.getGetterMethod(getterName);
    if (getterNode == null) {
      getterName = "is" + MetaClassHelper.capitalize(methodName);
      getterNode = receiverType.getGetterMethod(getterName);
    }
    if (getterNode != null
        && receiver instanceof ClassExpression
        && !CLASS_Type.equals(receiverType)
        && !getterNode.isStatic()) {
      return false;
    }

    // GROOVY-5561: if two files are compiled in the same source unit
    // and that one references the other, the getters for properties have not been
    // generated by the compiler yet (generated by the Verifier)
    PropertyNode propertyNode = receiverType.getProperty(methodName);
    if (propertyNode != null) {
      // it is possible to use a getter
      String prefix = "get";
      if (boolean_TYPE.equals(propertyNode.getOriginType())) {
        prefix = "is";
      }
      getterName = prefix + MetaClassHelper.capitalize(methodName);
      getterNode =
          new MethodNode(
              getterName,
              ACC_PUBLIC,
              propertyNode.getOriginType(),
              Parameter.EMPTY_ARRAY,
              ClassNode.EMPTY_ARRAY,
              EmptyStatement.INSTANCE);
      getterNode.setDeclaringClass(receiverType);
      if (propertyNode.isStatic()) getterNode.setModifiers(ACC_PUBLIC + ACC_STATIC);
    }
    if (getterNode != null) {
      MethodCallExpression call =
          new MethodCallExpression(receiver, getterName, ArgumentListExpression.EMPTY_ARGUMENTS);
      call.setSourcePosition(receiver);
      call.setMethodTarget(getterNode);
      call.setImplicitThis(implicitThis);
      call.setSafe(safe);
      call.visit(controller.getAcg());
      return true;
    }

    if (receiverType instanceof InnerClassNode && !receiverType.isStaticClass()) {
      if (makeGetPropertyWithGetter(
          receiver, receiverType.getOuterClass(), methodName, safe, implicitThis)) {
        return true;
      }
    }

    // go upper level
    ClassNode superClass = receiverType.getSuperClass();
    if (superClass != null) {
      return makeGetPropertyWithGetter(receiver, superClass, methodName, safe, implicitThis);
    }
    return false;
  }
 static {
   ARRAYLIST_CONSTRUCTOR =
       new ConstructorNode(
           ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
   ARRAYLIST_CONSTRUCTOR.setDeclaringClass(StaticCompilationVisitor.ARRAYLIST_CLASSNODE);
 }