private void verifyCompilePhase(AnnotationNode annotation, Class<?> klass) {
    GroovyASTTransformation transformationClass =
        klass.getAnnotation(GroovyASTTransformation.class);
    if (transformationClass != null) {
      CompilePhase specifiedCompilePhase = transformationClass.phase();
      if (specifiedCompilePhase.getPhaseNumber()
          < CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) {
        source
            .getErrorCollector()
            .addError(
                new SimpleMessage(
                    annotation.getClassNode().getName()
                        + " is defined to be run in compile phase "
                        + specifiedCompilePhase
                        + ". Local AST transformations must run in "
                        + CompilePhase.SEMANTIC_ANALYSIS
                        + " or later!",
                    source));
      }

    } else {
      source
          .getErrorCollector()
          .addError(
              new SimpleMessage(
                  "AST transformation implementation classes must be annotated with "
                      + GroovyASTTransformation.class.getName()
                      + ". "
                      + klass.getName()
                      + " lacks this annotation.",
                  source));
    }
  }
  @SuppressWarnings("unused")
  private List<String> getTransformClassNames(
      AnnotationNode annotation, Annotation transformClassAnnotation) {
    List<String> result = new ArrayList<String>();

    try {
      Method valueMethod = transformClassAnnotation.getClass().getMethod("value");
      String[] names = (String[]) valueMethod.invoke(transformClassAnnotation);
      result.addAll(Arrays.asList(names));

      Method classesMethod = transformClassAnnotation.getClass().getMethod("classes");
      Class[] classes = (Class[]) classesMethod.invoke(transformClassAnnotation);
      for (Class klass : classes) {
        result.add(klass.getName());
      }

      if (names.length > 0 && classes.length > 0) {
        source
            .getErrorCollector()
            .addError(
                new SimpleMessage(
                    "@GroovyASTTransformationClass in "
                        + annotation.getClassNode().getName()
                        + " should specify transforms only by class names or by classes and not by both",
                    source));
      }
    } catch (Exception e) {
      source.addException(e);
    }

    return result;
  }
 /**
  * Snoops through the declaring class and all parents looking for methods
  *
  * <ul>
  *   <li><code>public String getMessage(java.lang.String)</code>
  *   <li><code>public String getMessage(java.lang.String, java.util.Locale)</code>
  *   <li><code>public String getMessage(java.lang.String, java.lang.Object[])</code>
  *   <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.util.Locale)
  *       </code>
  *   <li><code>public String getMessage(java.lang.String, java.util.List)</code>
  *   <li><code>public String getMessage(java.lang.String, java.util.List, java.util.Locale)</code>
  *   <li><code>public String getMessage(java.lang.String, java.util.Map)</code>
  *   <li><code>public String getMessage(java.lang.String, java.util.Map, java.util.Locale)</code>
  *   <li><code>public String getMessage(java.lang.String, java.lang.String)</code>
  *   <li><code>public String getMessage(java.lang.String, java.lang.String, java.util.Locale)
  *       </code>
  *   <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.lang.String)
  *       </code>
  *   <li><code>
  *       public String getMessage(java.lang.String, java.lang.Object[], java.lang.String, java.util.Locale)
  *       </code>
  *   <li><code>public String getMessage(java.lang.String, java.util.List, java.lang.String)</code>
  *   <li><code>
  *       public String getMessage(java.lang.String, java.util.List, java.lang.String, java.util.Locale)
  *       </code>
  *   <li><code>public String getMessage(java.lang.String, java.util.Map, java.lang.String)</code>
  *   <li><code>
  *       public String getMessage(java.lang.String, java.util.Map, java.lang.String, java.util.Locale)
  *       </code>
  * </ul>
  *
  * If any are defined all must be defined or a compilation error results.
  *
  * @param declaringClass the class to search
  * @param sourceUnit the source unit, for error reporting. {@code @NotNull}.
  * @return true if property change support should be added
  */
 protected static boolean needsMessageSource(ClassNode declaringClass, SourceUnit sourceUnit) {
   boolean found = false;
   ClassNode consideredClass = declaringClass;
   while (consideredClass != null) {
     for (MethodNode method : consideredClass.getMethods()) {
       // just check length, MOP will match it up
       found = method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 1;
       found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 2;
       found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 3;
       found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 4;
       if (found) return false;
     }
     consideredClass = consideredClass.getSuperClass();
   }
   if (found) {
     sourceUnit
         .getErrorCollector()
         .addErrorAndContinue(
             new SimpleMessage(
                 "@MessageSourceAware cannot be processed on "
                     + declaringClass.getName()
                     + " because some but not all of variants of getMessage() were declared in the current class or super classes.",
                 sourceUnit));
     return false;
   }
   return true;
 }
  private void addTransformsToClassNode(
      AnnotationNode annotation, String[] transformClassNames, Class[] transformClasses) {

    if (transformClassNames.length == 0 && transformClasses.length == 0) {
      source
          .getErrorCollector()
          .addError(
              new SimpleMessage(
                  "@GroovyASTTransformationClass in "
                      + annotation.getClassNode().getName()
                      + " does not specify any transform class names/classes",
                  source));
    }

    if (transformClassNames.length > 0 && transformClasses.length > 0) {
      source
          .getErrorCollector()
          .addError(
              new SimpleMessage(
                  "@GroovyASTTransformationClass in "
                      + annotation.getClassNode().getName()
                      + " should specify transforms only by class names or by classes and not by both",
                  source));
    }

    for (String transformClass : transformClassNames) {
      try {
        Class klass = transformLoader.loadClass(transformClass, false, true, false);
        verifyAndAddTransform(annotation, klass);

      } catch (ClassNotFoundException e) {
        source
            .getErrorCollector()
            .addErrorAndContinue(
                new SimpleMessage(
                    "Could not find class for Transformation Processor "
                        + transformClass
                        + " declared by "
                        + annotation.getClassNode().getName(),
                    source));
      }
    }
    for (Class klass : transformClasses) {
      verifyAndAddTransform(annotation, klass);
    }
  }
  private Class[] getTransformClasses(ClassNode classNode) {
    if (!classNode.hasClass()) {
      List<AnnotationNode> annotations = classNode.getAnnotations();
      AnnotationNode transformAnnotation = null;
      for (AnnotationNode anno : annotations) {
        if (anno.getClassNode().getName().equals(GroovyASTTransformationClass.class.getName())) {
          transformAnnotation = anno;
          break;
        }
      }
      if (transformAnnotation != null) {
        Expression expr = (Expression) transformAnnotation.getMember("classes");
        if (expr == null) {
          return NO_CLASSES;
        }
        Class<?>[] values = NO_CLASSES;
        // Will need to extract the classnames
        if (expr instanceof ListExpression) {
          List<Class<?>> loadedClasses = new ArrayList<Class<?>>();
          ListExpression expression = (ListExpression) expr;
          List<Expression> expressions = expression.getExpressions();
          for (Expression oneExpr : expressions) {
            String classname = ((ClassExpression) oneExpr).getType().getName();
            try {
              Class<?> clazz = Class.forName(classname, false, transformLoader);
              loadedClasses.add(clazz);
            } catch (ClassNotFoundException cnfe) {
              source
                  .getErrorCollector()
                  .addError(
                      new SimpleMessage(
                          "Ast transform processing, cannot find " + classname, source));
            }
          }
          if (loadedClasses.size() != 0) {
            values = loadedClasses.toArray(new Class<?>[loadedClasses.size()]);
          }
          return values;
        } else {

        }

        throw new RuntimeException(
            "nyi implemented in eclipse: need to support: "
                + expr
                + " (class="
                + expr.getClass()
                + ")");
      }
      return null;
    } else {
      Annotation transformClassAnnotation = getTransformClassAnnotation(classNode);
      if (transformClassAnnotation == null) {
        return null;
      }
      return getTransformClasses(transformClassAnnotation);
    }
  }
  private boolean addCollectedAnnotations(
      List<AnnotationNode> collected, AnnotationNode aliasNode, AnnotatedNode origin) {
    ClassNode classNode = aliasNode.getClassNode();
    boolean ret = false;
    for (AnnotationNode annotation : classNode.getAnnotations()) {
      if (annotation.getClassNode().getName().equals(AnnotationCollector.class.getName())) {
        Expression processorExp = annotation.getMember("processor");
        AnnotationCollectorTransform act = null;
        assertStringConstant(processorExp);
        if (processorExp != null) {
          String className = (String) ((ConstantExpression) processorExp).getValue();
          Class klass = loadTransformClass(className, aliasNode);
          if (klass != null) {
            try {
              act = (AnnotationCollectorTransform) klass.newInstance();
            } catch (InstantiationException e) {
              source.getErrorCollector().addErrorAndContinue(new ExceptionMessage(e, true, source));
            } catch (IllegalAccessException e) {
              source.getErrorCollector().addErrorAndContinue(new ExceptionMessage(e, true, source));
            }
          }
        } else {
          act = new AnnotationCollectorTransform();
        }
        if (act != null) {
          // GRECLIPSE edit
          // collected.addAll(act.visit(annotation, aliasNode, origin, source));
          // original annotation added to metadata to prevent import organizer from deleting its
          // import
          List<AnnotationNode> visitResult = act.visit(annotation, aliasNode, origin, source);
          for (AnnotationNode annotationNode : visitResult) {
            Set<AnnotationNode> aliases = annotationNode.getNodeMetaData("AnnotationCollector");
            if (aliases == null)
              annotationNode.setNodeMetaData("AnnotationCollector", (aliases = new HashSet(1)));

            aliases.add(aliasNode);
          }
          collected.addAll(visitResult);
          // GRECLIPSE end
        }
        ret = true;
      }
    }
    return ret;
  }
예제 #7
0
 /**
  * Generates a fatal compilation error
  *
  * @param sourceUnit the SourceUnit
  * @param astNode the ASTNode which caused the error
  * @param message The error message
  * @param fatal indicates if this is a fatal error
  */
 public static void error(
     final SourceUnit sourceUnit,
     final ASTNode astNode,
     final String message,
     final boolean fatal) {
   final SyntaxException syntaxException =
       new SyntaxException(message, astNode.getLineNumber(), astNode.getColumnNumber());
   final SyntaxErrorMessage syntaxErrorMessage =
       new SyntaxErrorMessage(syntaxException, sourceUnit);
   sourceUnit.getErrorCollector().addError(syntaxErrorMessage, fatal);
 }
 private void verifyClass(AnnotationNode annotation, Class klass) {
   if (!ASTTransformation.class.isAssignableFrom(klass)) {
     source
         .getErrorCollector()
         .addError(
             new SimpleMessage(
                 "Not an ASTTransformation: "
                     + klass.getName()
                     + " declared by "
                     + annotation.getClassNode().getName(),
                 source));
   }
 }
 private void assertStringConstant(Expression exp) {
   if (exp == null) return;
   if (!(exp instanceof ConstantExpression)) {
     source
         .getErrorCollector()
         .addErrorAndContinue(
             new SyntaxErrorMessage(
                 new SyntaxException(
                     "Expected a String constant.", exp.getLineNumber(), exp.getColumnNumber()),
                 source));
   }
   ConstantExpression ce = (ConstantExpression) exp;
   if (!(ce.getValue() instanceof String)) {
     source
         .getErrorCollector()
         .addErrorAndContinue(
             new SyntaxErrorMessage(
                 new SyntaxException(
                     "Expected a String constant.", exp.getLineNumber(), exp.getColumnNumber()),
                 source));
   }
 }
 // GRECLIPSE start
 protected void addTypeError(String msg, ClassNode expr) {
   int line = expr.getLineNumber();
   int col = expr.getColumnNumber();
   SourceUnit source = getSourceUnit();
   source
       .getErrorCollector()
       .addErrorAndContinue(
           // GRECLIPSE: start
           new SyntaxErrorMessage(
               new PreciseSyntaxException(
                   msg + '\n', line, col, expr.getNameStart(), expr.getNameEnd()),
               source)
           // end
           );
 }
 private Class loadTransformClass(String transformClass, AnnotationNode annotation) {
   try {
     return transformLoader.loadClass(transformClass, false, true, false);
   } catch (ClassNotFoundException e) {
     source
         .getErrorCollector()
         .addErrorAndContinue(
             new SimpleMessage(
                 "Could not find class for Transformation Processor "
                     + transformClass
                     + " declared by "
                     + annotation.getClassNode().getName(),
                 source));
   }
   return null;
 }
 public void visitClass(ClassNode node) {
   ClassNode oldClass = currentClass;
   currentClass = node;
   checkImplementsAndExtends(node);
   if (source != null && !source.getErrorCollector().hasErrors()) {
     checkClassForIncorrectModifiers(node);
     checkInterfaceMethodVisibility(node);
     checkClassForOverwritingFinal(node);
     checkMethodsForIncorrectModifiers(node);
     checkMethodsForWeakerAccess(node);
     checkMethodsForOverridingFinal(node);
     checkNoAbstractMethodsNonabstractClass(node);
     checkGenericsUsage(node, node.getUnresolvedInterfaces());
     checkGenericsUsage(node, node.getUnresolvedSuperClass());
   }
   super.visitClass(node);
   currentClass = oldClass;
 }
  protected void addError(String msg, ASTNode expr) {
    int line = expr.getLineNumber();
    int col = expr.getColumnNumber();
    // GRECLIPSE
    int start = expr.getStart();
    int end = expr.getEnd() - 1;
    if (expr instanceof ClassNode) {
      // assume we have a class declaration
      ClassNode cn = (ClassNode) expr;
      if (cn.getNameEnd() > 0) {
        start = cn.getNameStart();
        end = cn.getNameEnd();
      } else if (cn.getComponentType() != null) {
        // avoid extra whitespace after closing ]
        end--;
      }

    } else if (expr instanceof DeclarationExpression) {
      // assume that we just want to underline the variable declaration
      DeclarationExpression decl = (DeclarationExpression) expr;
      Expression lhs = decl.getLeftExpression();
      start = lhs.getStart();
      // avoid extra space before = if a variable
      end =
          lhs instanceof VariableExpression ? start + lhs.getText().length() - 1 : lhs.getEnd() - 1;
    }
    // end

    SourceUnit source = getSourceUnit();
    source
        .getErrorCollector()
        .addErrorAndContinue(
            // GRECLIPSE: start
            new SyntaxErrorMessage(
                new PreciseSyntaxException(msg + '\n', line, col, start, end), source)
            // end
            );
  }
 protected static boolean needsMybatisContribution(
     ClassNode declaringClass, SourceUnit sourceUnit) {
   boolean found1 = false, found2 = false, found3 = false, found4 = false;
   ClassNode consideredClass = declaringClass;
   while (consideredClass != null) {
     for (MethodNode method : consideredClass.getMethods()) {
       // just check length, MOP will match it up
       found1 =
           method.getName().equals(METHOD_WITH_SQL_SESSION) && method.getParameters().length == 1;
       found2 =
           method.getName().equals(METHOD_WITH_SQL_SESSION) && method.getParameters().length == 2;
       found3 =
           method.getName().equals(METHOD_SET_MYBATIS_PROVIDER)
               && method.getParameters().length == 1;
       found4 =
           method.getName().equals(METHOD_GET_MYBATIS_PROVIDER)
               && method.getParameters().length == 0;
       if (found1 && found2 && found3 && found4) {
         return false;
       }
     }
     consideredClass = consideredClass.getSuperClass();
   }
   if (found1 || found2 || found3 || found4) {
     sourceUnit
         .getErrorCollector()
         .addErrorAndContinue(
             new SimpleMessage(
                 "@MybatisAware cannot be processed on "
                     + declaringClass.getName()
                     + " because some but not all of methods from "
                     + MybatisContributionHandler.class.getName()
                     + " were declared in the current class or super classes.",
                 sourceUnit));
     return false;
   }
   return true;
 }
예제 #15
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
        }
  /**
   * 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);
        }
      }
    }
  }