private void checkClassForOtherModifiers(ClassNode node) {
   checkClassForModifier(node, isTransient(node.getModifiers()), "transient");
   checkClassForModifier(node, isVolatile(node.getModifiers()), "volatile");
   checkClassForModifier(node, isNative(node.getModifiers()), "native");
   if (!(node instanceof InnerClassNode)) {
     checkClassForModifier(node, isStatic(node.getModifiers()), "static");
   }
   // don't check synchronized here as it overlaps with ACC_SUPER
 }
 private void checkClassForAbstractAndFinal(ClassNode node) {
   if (!isAbstract(node.getModifiers())) return;
   if (!isFinal(node.getModifiers())) return;
   if (node.isInterface()) {
     addError(
         "The " + getDescription(node) + " must not be final. It is by definition abstract.",
         node);
   } else {
     addError("The " + getDescription(node) + " must not be both final and abstract.", node);
   }
 }
예제 #3
0
 /**
  * Tells if a class node is candidate for class literal bytecode optimization. If so, bytecode may
  * use LDC instructions instead of static constant Class fields to retrieve class literals.
  *
  * @param classNode the classnode for which we want to know if bytecode optimization is possible
  * @return true if the bytecode can be optimized
  */
 public static boolean isClassLiteralPossible(ClassNode classNode) {
   // the current implementation only checks for public modifier, because Groovy used to allow
   // handles on classes even if they are package protected and not in the same package.
   // There are situations where we could make more fine grained checks, but be careful of
   // potential breakage of existing code.
   return Modifier.isPublic(classNode.getModifiers());
 }
 private void checkClassForOverwritingFinal(ClassNode cn) {
   ClassNode superCN = cn.getSuperClass();
   if (superCN == null) return;
   if (!isFinal(superCN.getModifiers())) return;
   StringBuilder msg = new StringBuilder();
   msg.append("You are not allowed to overwrite the final ");
   msg.append(getDescription(superCN));
   msg.append(".");
   addError(msg.toString(), cn);
 }
  // GroovyClassVisitor interface
  // -------------------------------------------------------------------------
  public void visitClass(ClassNode classNode) {
    try {
      this.classNode = classNode;
      this.internalClassName = BytecodeHelper.getClassInternalName(classNode);

      // System.out.println("Generating class: " + classNode.getName());

      this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass());

      cv.visit(
          Opcodes.V1_3,
          classNode.getModifiers(),
          internalClassName,
          (String) null,
          internalBaseClassName,
          BytecodeHelper.getClassInternalNames(classNode.getInterfaces()));

      classNode.visitContents(this);

      for (Iterator iter = innerClasses.iterator(); iter.hasNext(); ) {
        ClassNode innerClass = (ClassNode) iter.next();
        ClassNode innerClassType = innerClass;
        String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassType);
        String outerClassName = internalClassName; // default for inner classes
        MethodNode enclosingMethod = innerClass.getEnclosingMethod();
        if (enclosingMethod != null) {
          // local inner classes do not specify the outer class name
          outerClassName = null;
        }
        cv.visitInnerClass(
            innerClassInternalName,
            outerClassName,
            innerClassType.getName(),
            innerClass.getModifiers());
      }
      cv.visitEnd();
    } catch (GroovyRuntimeException e) {
      e.setModule(classNode.getModule());
      throw e;
    }
  }
예제 #6
0
 @Override
 public void call(
     final SourceUnit source, final GeneratorContext context, final ClassNode classNode)
     throws CompilationFailedException {
   if ((classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0) {
     // does not apply on interfaces
     return;
   }
   if (!(classNode instanceof InnerClassNode)) {
     addTimeStamp(classNode);
   }
 }
예제 #7
0
  public static ClassNode getFurthestUnresolvedParent(ClassNode classNode) {
    ClassNode parent = classNode.getSuperClass();

    while (parent != null
        && !getFullName(parent).equals("java.lang.Object")
        && !parent.isResolved()
        && !Modifier.isAbstract(parent.getModifiers())) {
      classNode = parent;
      parent = parent.getSuperClass();
    }
    return classNode;
  }
 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);
 }
 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);
     }
   }
 }
 private void checkNoAbstractMethodsNonabstractClass(ClassNode node) {
   if (isAbstract(node.getModifiers())) return;
   List<MethodNode> abstractMethods = node.getAbstractMethods();
   if (abstractMethods == null) return;
   for (MethodNode method : abstractMethods) {
     addError(
         "Can't have an abstract method in a non-abstract class."
             + " The "
             + getDescription(node)
             + " must be declared abstract or"
             + " the "
             + getDescription(method)
             + " must be implemented.",
         node);
   }
 }
  public void generateClass(ClassNode classNode) throws FileNotFoundException {
    // Only attempt to render our self if our super-class is resolved, else wait for it
    if (requireSuperResolved && !classNode.getSuperClass().isResolved()) {
      return;
    }

    // owner should take care for us
    if (classNode instanceof InnerClassNode) return;

    // don't generate stubs for private classes, as they are only visible in the same file
    if ((classNode.getModifiers() & Opcodes.ACC_PRIVATE) != 0) return;

    String fileName = classNode.getName().replace('.', '/');
    mkdirs(outputPath, fileName);
    toCompile.add(fileName);

    File file = new File(outputPath, fileName + ".java");
    FileOutputStream fos = new FileOutputStream(file);
    PrintWriter out = new PrintWriter(fos);

    try {
      String packageName = classNode.getPackageName();
      if (packageName != null) {
        out.println("package " + packageName + ";\n");
      }

      printImports(out, classNode);
      printClassContents(out, classNode);

    } finally {
      try {
        out.close();
      } catch (Exception e) {
        // ignore
      }
      try {
        fos.close();
      } catch (IOException e) {
        // ignore
      }
    }
  }
 private void makeClassFinal(ClassNode cNode) {
   if ((cNode.getModifiers() & ACC_FINAL) == 0) {
     cNode.setModifiers(cNode.getModifiers() | ACC_FINAL);
   }
 }
예제 #13
0
  @Override
  public void visit(ASTNode[] astNodes, SourceUnit source) {
    if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof AnnotatedNode)) {
      throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
    }

    AnnotatedNode parent = (AnnotatedNode) astNodes[1];
    AnnotationNode node = (AnnotationNode) astNodes[0];
    if (!MY_TYPE.equals(node.getClassNode()) || !(parent instanceof ClassNode)) {
      return;
    }

    ClassNode classNode = (ClassNode) parent;
    if (classNode.isInterface() || Modifier.isAbstract(classNode.getModifiers())) {
      return;
    }

    boolean junit3Test = isJunit3Test(classNode);
    boolean spockTest = isSpockTest(classNode);
    boolean isJunit = classNode.getName().endsWith("Tests");

    if (!junit3Test && !spockTest && !isJunit) return;

    Expression value = node.getMember("value");
    ClassExpression ce;
    if (value instanceof ClassExpression) {
      ce = (ClassExpression) value;
      testFor(classNode, ce);
    } else {
      if (!junit3Test) {
        List<AnnotationNode> annotations = classNode.getAnnotations(MY_TYPE);
        if (annotations.size() > 0)
          return; // bail out, in this case it was already applied as a local transform
        // no explicit class specified try by convention
        String fileName = source.getName();
        String className = GrailsResourceUtils.getClassName(new FileSystemResource(fileName));
        if (className != null) {
          boolean isSpock = className.endsWith("Spec");
          String targetClassName = null;

          if (isJunit) {
            targetClassName = className.substring(0, className.indexOf("Tests"));
          } else if (isSpock) {
            targetClassName = className.substring(0, className.indexOf("Spec"));
          }

          if (targetClassName != null) {
            Resource targetResource =
                getResourceLocator().findResourceForClassName(targetClassName);
            if (targetResource != null) {
              try {
                if (GrailsResourceUtils.isDomainClass(targetResource.getURL())) {
                  testFor(
                      classNode,
                      new ClassExpression(
                          new ClassNode(targetClassName, 0, ClassHelper.OBJECT_TYPE)));
                } else {
                  for (String artefactType : artefactTypeToTestMap.keySet()) {
                    if (targetClassName.endsWith(artefactType)) {
                      testFor(
                          classNode,
                          new ClassExpression(
                              new ClassNode(targetClassName, 0, ClassHelper.OBJECT_TYPE)));
                      break;
                    }
                  }
                }
              } catch (IOException e) {
                // ignore
              }
            }
          }
        }
      }
    }
  }
 private void revertVisibility(ClassNode cNode) {
   cNode.setModifiers(cNode.getModifiers() & ~ACC_PUBLIC);
 }
 @SuppressWarnings("BooleanMethodIsAlwaysInverted")
 private boolean isFinal(ClassNode classNode) {
   return (classNode.getModifiers() & ACC_FINAL) != 0;
 }
  private void printClassContents(PrintWriter out, ClassNode classNode)
      throws FileNotFoundException {
    if (classNode instanceof InnerClassNode && ((InnerClassNode) classNode).isAnonymous()) {
      // if it is an anonymous inner class, don't generate the stub code for it.
      return;
    }
    try {
      Verifier verifier =
          new Verifier() {
            public void addCovariantMethods(ClassNode cn) {}

            protected void addTimeStamp(ClassNode node) {}

            protected void addInitialization(ClassNode node) {}

            protected void addPropertyMethod(MethodNode method) {
              doAddMethod(method);
            }

            protected void addReturnIfNeeded(MethodNode node) {}

            protected void addMethod(
                ClassNode node,
                boolean shouldBeSynthetic,
                String name,
                int modifiers,
                ClassNode returnType,
                Parameter[] parameters,
                ClassNode[] exceptions,
                Statement code) {
              doAddMethod(
                  new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
            }

            protected void addConstructor(
                Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode node) {
              if (code instanceof ExpressionStatement) { // GROOVY-4508
                Statement temp = code;
                code = new BlockStatement();
                ((BlockStatement) code).addStatement(temp);
              }
              ConstructorNode ctrNode =
                  new ConstructorNode(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
              ctrNode.setDeclaringClass(node);
              constructors.add(ctrNode);
            }

            protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) {
              final Parameter[] parameters = method.getParameters();
              final Expression[] saved = new Expression[parameters.length];
              for (int i = 0; i < parameters.length; i++) {
                if (parameters[i].hasInitialExpression())
                  saved[i] = parameters[i].getInitialExpression();
              }
              super.addDefaultParameters(action, method);
              for (int i = 0; i < parameters.length; i++) {
                if (saved[i] != null) parameters[i].setInitialExpression(saved[i]);
              }
            }

            private void doAddMethod(MethodNode method) {
              String sig = method.getTypeDescriptor();

              if (propertyMethodsWithSigs.containsKey(sig)) return;

              propertyMethods.add(method);
              propertyMethodsWithSigs.put(sig, method);
            }

            @Override
            protected void addDefaultConstructor(ClassNode node) {
              // not required for stub generation
            }
          };
      verifier.visitClass(classNode);
      currentModule = classNode.getModule();

      boolean isInterface = classNode.isInterface();
      boolean isEnum = (classNode.getModifiers() & Opcodes.ACC_ENUM) != 0;
      boolean isAnnotationDefinition = classNode.isAnnotationDefinition();
      printAnnotations(out, classNode);
      printModifiers(
          out,
          classNode.getModifiers()
              & ~(isInterface ? Opcodes.ACC_ABSTRACT : 0)
              & ~(isEnum ? Opcodes.ACC_FINAL : 0));

      if (isInterface) {
        if (isAnnotationDefinition) {
          out.print("@");
        }
        out.print("interface ");
      } else if (isEnum) {
        out.print("enum ");
      } else {
        out.print("class ");
      }

      String className = classNode.getNameWithoutPackage();
      if (classNode instanceof InnerClassNode)
        className = className.substring(className.lastIndexOf("$") + 1);
      out.println(className);
      printGenericsBounds(out, classNode, true);

      ClassNode superClass = classNode.getUnresolvedSuperClass(false);

      if (!isInterface && !isEnum) {
        out.print("  extends ");
        printType(out, superClass);
      }

      ClassNode[] interfaces = classNode.getInterfaces();
      if (interfaces != null && interfaces.length > 0 && !isAnnotationDefinition) {
        if (isInterface) {
          out.println("  extends");
        } else {
          out.println("  implements");
        }
        for (int i = 0; i < interfaces.length - 1; ++i) {
          out.print("    ");
          printType(out, interfaces[i]);
          out.print(",");
        }
        out.print("    ");
        printType(out, interfaces[interfaces.length - 1]);
      }
      out.println(" {");

      printFields(out, classNode);
      printMethods(out, classNode, isEnum);

      for (Iterator<InnerClassNode> inner = classNode.getInnerClasses(); inner.hasNext(); ) {
        // GROOVY-4004: Clear the methods from the outer class so that they don't get duplicated in
        // inner ones
        propertyMethods.clear();
        propertyMethodsWithSigs.clear();
        constructors.clear();
        printClassContents(out, inner.next());
      }

      out.println("}");
    } finally {
      propertyMethods.clear();
      propertyMethodsWithSigs.clear();
      constructors.clear();
      currentModule = null;
    }
  }