private List<FieldNode> getAnnotatedFieldOfClass(ClassNode target, ClassNode annotation) {
    List<FieldNode> result = new ArrayList<FieldNode>();

    for (FieldNode fieldNode : target.getFields())
      if (!fieldNode.getAnnotations(annotation).isEmpty()) result.add(fieldNode);

    return result;
  }
 /**
  * Adds the annotation to the internal target list if a match is found.
  *
  * @param node the node to be processed
  */
 public void visitAnnotations(AnnotatedNode node) {
   super.visitAnnotations(node);
   for (AnnotationNode annotation : node.getAnnotations()) {
     if (transforms.containsKey(annotation)) {
       targetNodes.add(new ASTNode[] {annotation, node});
     }
   }
 }
  /**
   * 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);
    }
  }
Ejemplo n.º 4
0
 private List<ClassNode> getSorted(int[] index, List<ClassNode> unsorted) {
   List<ClassNode> sorted = new ArrayList<ClassNode>(unsorted.size());
   for (int i = 0; i < unsorted.size(); i++) {
     int min = -1;
     for (int j = 0; j < unsorted.size(); j++) {
       if (index[j] == -1) continue;
       if (min == -1) {
         min = j;
       } else if (index[j] < index[min]) {
         min = j;
       }
     }
     if (min == -1) break;
     sorted.add(unsorted.get(min));
     index[min] = -1;
   }
   return sorted;
 }
  private Collection createPropertiesForBelongsToExpression(Expression e, ClassNode classNode) {
    List properties = new ArrayList();
    if (e instanceof MapExpression) {
      MapExpression me = (MapExpression) e;
      List mapEntries = me.getMapEntryExpressions();
      for (Iterator i = mapEntries.iterator(); i.hasNext(); ) {
        MapEntryExpression mme = (MapEntryExpression) i.next();
        String key = mme.getKeyExpression().getText();

        String type = mme.getValueExpression().getText();

        properties.add(
            new PropertyNode(
                key, Modifier.PUBLIC, ClassHelper.make(type), classNode, null, null, null));
      }
    }

    return properties;
  }
Ejemplo n.º 6
0
 /**
  * Dequeues any source units add through addSource and resets the compiler phase to
  * initialization.
  *
  * <p>Note: this does not mean a file is recompiled. If a SourceUnit has already passed a phase it
  * is skipped until a higher phase is reached.
  *
  * @return true if there was a queued source
  * @throws CompilationFailedException
  */
 protected boolean dequeued() throws CompilationFailedException {
   boolean dequeue = !queuedSources.isEmpty();
   while (!queuedSources.isEmpty()) {
     SourceUnit su = queuedSources.removeFirst();
     String name = su.getName();
     // GRECLIPSE: start
     if (iterating) {
       GroovyBugError gbe =
           new GroovyBugError(
               "Damaging 'names' whilst already iterating.  Name getting added is '"
                   + su.getName()
                   + "'");
       gbe.printStackTrace();
       throw gbe;
     }
     // end
     names.add(name);
     sources.put(name, su);
   }
   if (dequeue) {
     gotoPhase(Phases.INITIALIZATION);
   }
   return dequeue;
 }
  /**
   * Main loop entry.
   *
   * <p>First, it delegates to the super visitClass so we can collect the relevant annotations in an
   * AST tree walk.
   *
   * <p>Second, it calls the visit method on the transformation for each relevant annotation found.
   *
   * @param classNode the class to visit
   */
  public void visitClass(ClassNode classNode) {
    // only descend if we have annotations to look for
    Map<Class<? extends ASTTransformation>, Set<ASTNode>> baseTransforms =
        classNode.getTransforms(phase);
    if (!baseTransforms.isEmpty()) {
      final Map<Class<? extends ASTTransformation>, ASTTransformation> transformInstances =
          new HashMap<Class<? extends ASTTransformation>, ASTTransformation>();
      for (Class<? extends ASTTransformation> transformClass : baseTransforms.keySet()) {
        try {
          transformInstances.put(transformClass, transformClass.newInstance());
        } catch (InstantiationException e) {
          source
              .getErrorCollector()
              .addError(
                  new SimpleMessage(
                      "Could not instantiate Transformation Processor "
                          + transformClass, // + " declared by " +
                                            // annotation.getClassNode().getName(),
                      source));
        } catch (IllegalAccessException e) {
          source
              .getErrorCollector()
              .addError(
                  new SimpleMessage(
                      "Could not instantiate Transformation Processor "
                          + transformClass, // + " declared by " +
                                            // annotation.getClassNode().getName(),
                      source));
        }
      }

      // invert the map, is now one to many
      transforms = new HashMap<ASTNode, List<ASTTransformation>>();
      for (Map.Entry<Class<? extends ASTTransformation>, Set<ASTNode>> entry :
          baseTransforms.entrySet()) {
        for (ASTNode node : entry.getValue()) {
          List<ASTTransformation> list = transforms.get(node);
          if (list == null) {
            list = new ArrayList<ASTTransformation>();
            transforms.put(node, list);
          }
          list.add(transformInstances.get(entry.getKey()));
        }
      }

      targetNodes = new LinkedList<ASTNode[]>();

      // first pass, collect nodes
      super.visitClass(classNode);

      // second pass, call visit on all of the collected nodes
      for (ASTNode[] node : targetNodes) {
        for (ASTTransformation snt : transforms.get(node[0])) {
          if (snt instanceof CompilationUnitAware) {
            ((CompilationUnitAware) snt).setCompilationUnit(context.getCompilationUnit());
          }
          snt.visit(node, source);
        }
      }
    }
  }
Ejemplo n.º 8
0
        public void call(SourceUnit source, GeneratorContext context, ClassNode classNode)
            throws CompilationFailedException {

          optimizer.visitClass(
              classNode, source); // GROOVY-4272: repositioned it here from staticImport

          if (!classNode.isSynthetic()) {
            GenericsVisitor genericsVisitor = new GenericsVisitor(source);
            genericsVisitor.visitClass(classNode);
          }
          //
          // Run the Verifier on the outer class
          //
          try {
            verifier.visitClass(classNode);
          } catch (GroovyRuntimeException rpe) {
            ASTNode node = rpe.getNode();
            getErrorCollector()
                .addError(
                    new SyntaxException(
                        rpe.getMessage(),
                        node.getLineNumber(),
                        node.getColumnNumber(),
                        node.getLastLineNumber(),
                        node.getLastColumnNumber()),
                    source);
          }

          LabelVerifier lv = new LabelVerifier(source);
          lv.visitClass(classNode);

          ClassCompletionVerifier completionVerifier = new ClassCompletionVerifier(source);
          completionVerifier.visitClass(classNode);

          ExtendedVerifier xverifier = new ExtendedVerifier(source);
          xverifier.visitClass(classNode);

          // because the class may be generated even if a error was found
          // and that class may have an invalid format we fail here if needed
          getErrorCollector().failIfErrors();

          //
          // Prep the generator machinery
          //
          ClassVisitor visitor = createClassVisitor();

          String sourceName =
              (source == null ? classNode.getModule().getDescription() : source.getName());
          // only show the file name and its extension like javac does in its stacktraces rather
          // than the full path
          // also takes care of both \ and / depending on the host compiling environment
          if (sourceName != null)
            sourceName =
                sourceName.substring(
                    Math.max(sourceName.lastIndexOf('\\'), sourceName.lastIndexOf('/')) + 1);
          AsmClassGenerator generator = new AsmClassGenerator(source, context, visitor, sourceName);

          //
          // Run the generation and create the class (if required)
          //
          // GRECLIPSE: if there are errors, don't generate code.
          // code gen can fail unexpectedly if there was an earlier error.
          if (!source.getErrorCollector().hasErrors()) {
            // end
            generator.visitClass(classNode);

            byte[] bytes = ((ClassWriter) visitor).toByteArray();
            /// GRECLIPSE: start: added classNode, sourceUnit
            /*old{
            generatedClasses.add(new GroovyClass(classNode.getName(), bytes));
            }*/
            // newcode
            generatedClasses.add(new GroovyClass(classNode.getName(), bytes, classNode, source));
            // end

            //
            // Handle any callback that's been set
            //
            if (CompilationUnit.this.classgenCallback != null) {
              classgenCallback.call(visitor, classNode);
            }

            //
            // Recurse for inner classes
            //
            LinkedList innerClasses = generator.getInnerClasses();
            while (!innerClasses.isEmpty()) {
              classgen.call(source, context, (ClassNode) innerClasses.removeFirst());
            }
            // GRECLIPSE: if there are errors, don't generate code
          }
          // end
        }
Ejemplo n.º 9
0
  private List getPrimaryClassNodes(boolean sort) {
    if (sort == true) {
      List<ModuleNode> sortedModules = this.ast.getSortedModules();
      if (sortedModules != null) {
        return sortedModules;
      }
    }
    // FIXASC (groovychange) rewritten
    /*old{
    List unsorted = new ArrayList();
    Iterator modules = this.ast.getModules().iterator();
    while (modules.hasNext()) {
        ModuleNode module = (ModuleNode) modules.next();

        Iterator classNodes = module.getClasses().iterator();
        while (classNodes.hasNext()) {
            ClassNode classNode = (ClassNode) classNodes.next();
            unsorted.add(classNode);
        }
    }
    */
    // new
    List<ClassNode> unsorted = new ArrayList<ClassNode>();
    for (ModuleNode module : this.ast.getModules()) {
      unsorted.addAll(module.getClasses());
    }
    // FIXASC (groovychange) end

    if (!sort) return unsorted;

    // GRECLIPSE: start: rewritten sort algorithm
    /*old{
            int[] indexClass = new int[unsorted.size()];
            int[] indexInterface = new int[unsorted.size()];
            {
                int i = 0;
                for (Iterator<ClassNode> iter = unsorted.iterator(); iter.hasNext(); i++) {
                    ClassNode element = iter.next();
                    if (element.isInterface()) {
                        indexInterface[i] = getSuperInterfaceCount(element);
                        indexClass[i] = -1;
                    } else {
                        indexClass[i] = getSuperClassCount(element);
                        indexInterface[i] = -1;
                    }
                }
            }

            List<ClassNode> sorted = getSorted(indexInterface, unsorted);
            sorted.addAll(getSorted(indexClass, unsorted));
    */
    // newcode:
    // Sort them by how many types are in their hierarchy, but all interfaces first.
    // Algorithm:
    // Create a list of integers.  Each integer captures the index into the unsorted
    // list (bottom 16bits) and the count of how many types are in that types
    // hierarchy (top 16bits).  For classes the count is augmented by 2000 so that
    // when sorting the classes will come out after the interfaces.
    // This list of integers is sorted.  We then just go through it and for the
    // lower 16bits of each entry (0xffff) that is the index of the next value to
    // pull from the unsorted list and put into the sorted list.
    // Will break down if more than 2000 interfaces in the type hierarchy for an
    // individual type, or a project contains > 65535 files... but if you've got
    // that kind of setup, you have other problems...
    List<Integer> countIndexPairs = new ArrayList<Integer>();
    {
      int i = 0;
      for (Iterator iter = unsorted.iterator(); iter.hasNext(); i++) {
        ClassNode node = (ClassNode) iter.next();
        if (node.isInterface()) {
          countIndexPairs.add((getSuperInterfaceCount(node) << 16) + i);
        } else {
          countIndexPairs.add(((getSuperClassCount(node) + 2000) << 16) + i);
        }
      }
    }
    Collections.sort(countIndexPairs);
    List sorted = new ArrayList();
    for (int i : countIndexPairs) {
      sorted.add(unsorted.get(i & 0xffff));
    }
    this.ast.setSortedModules(sorted);
    // end
    return sorted;
  }
 private void addAssociationForKey(String key, List properties, ClassNode classNode) {
   properties.add(
       new PropertyNode(
           key, Modifier.PUBLIC, new ClassNode(Set.class), classNode, null, null, null));
 }