예제 #1
0
  static {
    getExtendsClause = getMethod(JCClassDecl.class, "getExtendsClause", new Class<?>[0]);
    getExtendsClause.setAccessible(true);

    if (getJavaCompilerVersion() < 8) {
      getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", java.util.Map.class);
      storeEnd = getMethod(java.util.Map.class, "put", Object.class, Object.class);
    } else {
      getEndPosition =
          getMethod(
              DiagnosticPosition.class, "getEndPosition", "com.sun.tools.javac.tree.EndPosTable");
      Method storeEndMethodTemp;
      Class<?> endPosTable;
      try {
        endPosTable = Class.forName("com.sun.tools.javac.tree.EndPosTable");
      } catch (ClassNotFoundException ex) {
        throw sneakyThrow(ex);
      }
      try {
        storeEndMethodTemp = endPosTable.getMethod("storeEnd", JCTree.class, int.class);
      } catch (NoSuchMethodException e) {
        try {
          endPosTable = Class.forName("com.sun.tools.javac.parser.JavacParser$AbstractEndPosTable");
          storeEndMethodTemp = endPosTable.getDeclaredMethod("storeEnd", JCTree.class, int.class);
        } catch (NoSuchMethodException ex) {
          throw sneakyThrow(ex);
        } catch (ClassNotFoundException ex) {
          throw sneakyThrow(ex);
        }
      }
      storeEnd = storeEndMethodTemp;
    }
    getEndPosition.setAccessible(true);
    storeEnd.setAccessible(true);
  }
예제 #2
0
 private static Method getMethod(Class<?> clazz, String name, String... paramTypes) {
   try {
     Class<?>[] c = new Class[paramTypes.length];
     for (int i = 0; i < paramTypes.length; i++) c[i] = Class.forName(paramTypes[i]);
     return clazz.getMethod(name, c);
   } catch (NoSuchMethodException e) {
     throw sneakyThrow(e);
   } catch (ClassNotFoundException e) {
     throw sneakyThrow(e);
   }
 }
예제 #3
0
 private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
   try {
     return clazz.getMethod(name, paramTypes);
   } catch (NoSuchMethodException e) {
     throw sneakyThrow(e);
   }
 }
예제 #4
0
  /**
   * Removes the annotation from javac's AST (it remains in lombok's AST), then removes any import
   * statement that imports this exact annotation (not star imports). Only does this if the
   * DeleteLombokAnnotations class is in the context.
   */
  public static void deleteAnnotationIfNeccessary(
      JavacNode annotation, Class<? extends Annotation> annotationType) {
    if (inNetbeansEditor(annotation)) return;
    if (!annotation.shouldDeleteLombokAnnotations()) return;
    JavacNode parentNode = annotation.directUp();
    switch (parentNode.getKind()) {
      case FIELD:
      case ARGUMENT:
      case LOCAL:
        JCVariableDecl variable = (JCVariableDecl) parentNode.get();
        variable.mods.annotations = filterList(variable.mods.annotations, annotation.get());
        break;
      case METHOD:
        JCMethodDecl method = (JCMethodDecl) parentNode.get();
        method.mods.annotations = filterList(method.mods.annotations, annotation.get());
        break;
      case TYPE:
        try {
          JCClassDecl type = (JCClassDecl) parentNode.get();
          type.mods.annotations = filterList(type.mods.annotations, annotation.get());
        } catch (ClassCastException e) {
          // something rather odd has been annotated. Better to just break only delombok instead of
          // everything.
        }
        break;
      default:
        // This really shouldn't happen, but if it does, better just break delombok instead of
        // breaking everything.
        return;
    }

    parentNode.getAst().setChanged();
    deleteImportFromCompilationUnit(annotation, annotationType.getName());
  }
예제 #5
0
  @SuppressWarnings("unchecked")
  private <T> T readObject(JCTree tree, String fieldName, T defaultValue) {
    Class<?> tClass = tree.getClass();
    Map<String, Field> c = reflectionCache.get(tClass);
    if (c == null) reflectionCache.put(tClass, c = new HashMap<String, Field>());
    Field f = c.get(fieldName);
    if (f == null) {
      try {
        f = tClass.getDeclaredField(fieldName);
      } catch (Exception e) {
        return defaultValue;
      }
      f.setAccessible(true);
      c.put(fieldName, f);
    }

    try {
      return (T) f.get(tree);
    } catch (Exception e) {
      return defaultValue;
    }
  }
예제 #6
0
  /**
   * Creates an instance of {@code AnnotationValues} for the provided AST Node.
   *
   * @param type An annotation class type, such as {@code lombok.Getter.class}.
   * @param node A Lombok AST node representing an annotation in source code.
   */
  public static <A extends Annotation> AnnotationValues<A> createAnnotation(
      Class<A> type, final JavacNode node) {
    Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
    JCAnnotation anno = (JCAnnotation) node.get();
    List<JCExpression> arguments = anno.getArguments();
    for (Method m : type.getDeclaredMethods()) {
      if (!Modifier.isPublic(m.getModifiers())) continue;
      String name = m.getName();
      java.util.List<String> raws = new ArrayList<String>();
      java.util.List<Object> guesses = new ArrayList<Object>();
      java.util.List<Object> expressions = new ArrayList<Object>();
      final java.util.List<DiagnosticPosition> positions = new ArrayList<DiagnosticPosition>();
      boolean isExplicit = false;

      for (JCExpression arg : arguments) {
        String mName;
        JCExpression rhs;

        if (arg instanceof JCAssign) {
          JCAssign assign = (JCAssign) arg;
          mName = assign.lhs.toString();
          rhs = assign.rhs;
        } else {
          rhs = arg;
          mName = "value";
        }

        if (!mName.equals(name)) continue;
        isExplicit = true;
        if (rhs instanceof JCNewArray) {
          List<JCExpression> elems = ((JCNewArray) rhs).elems;
          for (JCExpression inner : elems) {
            raws.add(inner.toString());
            expressions.add(inner);
            guesses.add(calculateGuess(inner));
            positions.add(inner.pos());
          }
        } else {
          raws.add(rhs.toString());
          expressions.add(rhs);
          guesses.add(calculateGuess(rhs));
          positions.add(rhs.pos());
        }
      }

      values.put(
          name,
          new AnnotationValue(node, raws, expressions, guesses, isExplicit) {
            @Override
            public void setError(String message, int valueIdx) {
              if (valueIdx < 0) node.addError(message);
              else node.addError(message, positions.get(valueIdx));
            }

            @Override
            public void setWarning(String message, int valueIdx) {
              if (valueIdx < 0) node.addWarning(message);
              else node.addWarning(message, positions.get(valueIdx));
            }
          });
    }

    return new AnnotationValues<A>(type, values, node);
  }
예제 #7
0
  /**
   * Checks if the given TypeReference node is likely to be a reference to the provided class.
   *
   * @param type An actual type. This method checks if {@code typeNode} is likely to be a reference
   *     to this type.
   * @param node A Lombok AST node. Any node in the appropriate compilation unit will do (used to
   *     get access to import statements).
   * @param typeNode A type reference to check.
   */
  public static boolean typeMatches(Class<?> type, JavacNode node, JCTree typeNode) {
    String typeName = typeNode.toString();

    TypeResolver resolver = new TypeResolver(node.getImportList());
    return resolver.typeMatches(node, type.getName(), typeName);
  }