@Override
  protected void performInjectionInternal(
      String apiInstanceProperty, SourceUnit source, ClassNode classNode) {
    List<PropertyNode> tags = findTags(classNode);

    PropertyNode namespaceProperty = classNode.getProperty(NAMESPACE_PROPERTY);
    String namespace = GroovyPage.DEFAULT_NAMESPACE;
    if (namespaceProperty != null && namespaceProperty.isStatic()) {
      Expression initialExpression = namespaceProperty.getInitialExpression();
      if (initialExpression instanceof ConstantExpression) {
        namespace = initialExpression.getText();
      }
    }

    addGetTagLibNamespaceMethod(classNode, namespace);

    MethodCallExpression tagLibraryLookupMethodCall =
        new MethodCallExpression(
            new VariableExpression(apiInstanceProperty, ClassHelper.make(TagLibraryApi.class)),
            "getTagLibraryLookup",
            ZERO_ARGS);
    for (PropertyNode tag : tags) {
      String tagName = tag.getName();
      addAttributesAndBodyMethod(classNode, tagLibraryLookupMethodCall, tagName);
      addAttributesAndStringBodyMethod(classNode, tagName);
      addAttributesAndBodyMethod(classNode, tagLibraryLookupMethodCall, tagName, false);
      addAttributesAndBodyMethod(classNode, tagLibraryLookupMethodCall, tagName, true, false);
      addAttributesAndBodyMethod(classNode, tagLibraryLookupMethodCall, tagName, false, false);
    }
  }
 public static List<FieldNode> getInstancePropertyFields(ClassNode cNode) {
   final List<FieldNode> result = new ArrayList<FieldNode>();
   for (PropertyNode pNode : cNode.getProperties()) {
     if (!pNode.isStatic()) {
       result.add(pNode.getField());
     }
   }
   return result;
 }
 private boolean hasStaticProperty(ClassNode staticImportType, String propName) {
   ClassNode classNode = staticImportType;
   while (classNode != null) {
     for (PropertyNode pn : classNode.getProperties()) {
       if (pn.getName().equals(propName) && pn.isStatic()) return true;
     }
     classNode = classNode.getSuperClass();
   }
   return false;
 }
 public static List<FieldNode> getSuperPropertyFields(ClassNode cNode) {
   final List<FieldNode> result;
   if (cNode == ClassHelper.OBJECT_TYPE) {
     result = new ArrayList<FieldNode>();
   } else {
     result = getSuperPropertyFields(cNode.getSuperClass());
   }
   for (PropertyNode pNode : cNode.getProperties()) {
     if (!pNode.isStatic()) {
       result.add(pNode.getField());
     }
   }
   return result;
 }
  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;
  }
 public void visitProperty(PropertyNode node) {
   pushState(node.isStatic());
   super.visitProperty(node);
   popState();
 }