예제 #1
0
  public static MarkerAnnotation createValAnnotation(
      AST ast, Annotation original, int start, int end) {
    MarkerAnnotation out = null;
    try {
      out = Reflection.markerAnnotationConstructor.newInstance(ast);
    } catch (InstantiationException e) {
      throw Lombok.sneakyThrow(e);
    } catch (IllegalAccessException e) {
      throw Lombok.sneakyThrow(e);
    } catch (InvocationTargetException e) {
      throw Lombok.sneakyThrow(e);
    }

    if (out != null) {
      SimpleName valName = ast.newSimpleName("val");
      valName.setSourceRange(start, end - start + 1);
      if (original.type instanceof SingleTypeReference) {
        out.setTypeName(valName);
        setIndex(valName, 1);
      } else {
        SimpleName lombokName = ast.newSimpleName("lombok");
        lombokName.setSourceRange(start, end - start + 1);
        setIndex(lombokName, 1);
        setIndex(valName, 2);
        QualifiedName fullName = ast.newQualifiedName(lombokName, valName);
        setIndex(fullName, 1);
        fullName.setSourceRange(start, end - start + 1);
        out.setTypeName(fullName);
      }
      out.setSourceRange(start, end - start + 1);
    }

    return out;
  }
예제 #2
0
 public static ASTNode getGeneratedBy(ASTNode node) {
   try {
     return (ASTNode) generatedByField.get(node);
   } catch (Exception t) {
     throw Lombok.sneakyThrow(t);
   }
 }
예제 #3
0
 static {
   try {
     generatedByField = ASTNode.class.getDeclaredField("$generatedBy");
   } catch (Throwable t) {
     throw Lombok.sneakyThrow(t);
   }
 }
예제 #4
0
  private void placePostCompileAndDontMakeForceRoundDummiesHook() {
    stopJavacProcessingEnvironmentFromClosingOurClassloader();

    forceMultipleRoundsInNetBeansEditor();
    Context context = processingEnv.getContext();
    disablePartialReparseInNetBeansEditor(context);
    try {
      Method keyMethod = Context.class.getDeclaredMethod("key", Class.class);
      keyMethod.setAccessible(true);
      Object key = keyMethod.invoke(context, JavaFileManager.class);
      Field htField = Context.class.getDeclaredField("ht");
      htField.setAccessible(true);
      @SuppressWarnings("unchecked")
      Map<Object, Object> ht = (Map<Object, Object>) htField.get(context);
      final JavaFileManager originalFiler = (JavaFileManager) ht.get(key);

      if (!(originalFiler instanceof InterceptingJavaFileManager)) {
        final Messager messager = processingEnv.getMessager();
        DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager);

        JavaFileManager newFiler = new InterceptingJavaFileManager(originalFiler, receiver);
        ht.put(key, newFiler);
        Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager");
        filerFileManagerField.setAccessible(true);
        filerFileManagerField.set(processingEnv.getFiler(), newFiler);
      }
    } catch (Exception e) {
      throw Lombok.sneakyThrow(e);
    }
  }
예제 #5
0
  public static ASTNode setGeneratedBy(ASTNode node, ASTNode source) {
    try {
      generatedByField.set(node, source);
    } catch (Exception t) {
      throw Lombok.sneakyThrow(t);
    }

    return node;
  }
예제 #6
0
  public static Modifier createModifier(AST ast, ModifierKeyword keyword, int start, int end) {
    Modifier modifier = null;
    try {
      modifier = Reflection.modifierConstructor.newInstance(ast);
    } catch (InstantiationException e) {
      throw Lombok.sneakyThrow(e);
    } catch (IllegalAccessException e) {
      throw Lombok.sneakyThrow(e);
    } catch (InvocationTargetException e) {
      throw Lombok.sneakyThrow(e);
    }

    if (modifier != null) {
      modifier.setKeyword(keyword);
      modifier.setSourceRange(start, end - start + 1);
    }
    return modifier;
  }
예제 #7
0
 private void forceMultipleRoundsInNetBeansEditor() {
   try {
     Field f = JavacProcessingEnvironment.class.getDeclaredField("isBackgroundCompilation");
     f.setAccessible(true);
     f.set(processingEnv, true);
   } catch (NoSuchFieldException e) {
     // only NetBeans has it
   } catch (Throwable t) {
     throw Lombok.sneakyThrow(t);
   }
 }
예제 #8
0
 private void stopJavacProcessingEnvironmentFromClosingOurClassloader() {
   try {
     Field f = JavacProcessingEnvironment.class.getDeclaredField("processorClassLoader");
     f.setAccessible(true);
     ClassLoader unwrapped = (ClassLoader) f.get(processingEnv);
     ClassLoader wrapped = new WrappingClassLoader(unwrapped);
     f.set(processingEnv, wrapped);
   } catch (NoSuchFieldException e) {
     // Some versions of javac have this (and call close on it), some don't. I guess this one
     // doesn't have it.
   } catch (Throwable t) {
     throw Lombok.sneakyThrow(t);
   }
 }
예제 #9
0
 private void disablePartialReparseInNetBeansEditor(Context context) {
   try {
     Class<?> cancelServiceClass = Class.forName("com.sun.tools.javac.util.CancelService");
     Method cancelServiceInstace = cancelServiceClass.getDeclaredMethod("instance", Context.class);
     Object cancelService = cancelServiceInstace.invoke(null, context);
     if (cancelService == null) return;
     Field parserField = cancelService.getClass().getDeclaredField("parser");
     parserField.setAccessible(true);
     Object parser = parserField.get(cancelService);
     Field supportsReparseField = parser.getClass().getDeclaredField("supportsReparse");
     supportsReparseField.setAccessible(true);
     supportsReparseField.set(parser, false);
   } catch (ClassNotFoundException e) {
     // only NetBeans has it
   } catch (NoSuchFieldException e) {
     // only NetBeans has it
   } catch (Throwable t) {
     throw Lombok.sneakyThrow(t);
   }
 }
예제 #10
0
  public static void addFinalAndValAnnotationToModifierList(
      Object converter, List<IExtendedModifier> modifiers, AST ast, LocalDeclaration in) {
    // First check that 'in' has the final flag on, and a @val / @lombok.val annotation.
    if ((in.modifiers & ClassFileConstants.AccFinal) == 0) return;
    if (in.annotations == null) return;
    boolean found = false;
    Annotation valAnnotation = null;

    for (Annotation ann : in.annotations) {
      if (PatchVal.couldBeVal(ann.type)) {
        found = true;
        valAnnotation = ann;
        break;
      }
    }

    if (!found) return;

    // Now check that 'out' is missing either of these.

    if (modifiers == null)
      return; // This is null only if the project is 1.4 or less. Lombok doesn't work in that.
    boolean finalIsPresent = false;
    boolean valIsPresent = false;

    for (Object present : modifiers) {
      if (present instanceof Modifier) {
        ModifierKeyword keyword = ((Modifier) present).getKeyword();
        if (keyword == null) continue;
        if (keyword.toFlagValue() == Modifier.FINAL) finalIsPresent = true;
      }

      if (present instanceof org.eclipse.jdt.core.dom.Annotation) {
        Name typeName = ((org.eclipse.jdt.core.dom.Annotation) present).getTypeName();
        if (typeName != null) {
          String fullyQualifiedName = typeName.getFullyQualifiedName();
          if ("val".equals(fullyQualifiedName) || "lombok.val".equals(fullyQualifiedName)) {
            valIsPresent = true;
          }
        }
      }
    }

    if (!finalIsPresent) {
      modifiers.add(
          createModifier(
              ast,
              ModifierKeyword.FINAL_KEYWORD,
              valAnnotation.sourceStart,
              valAnnotation.sourceEnd));
    }

    if (!valIsPresent) {
      MarkerAnnotation newAnnotation =
          createValAnnotation(
              ast, valAnnotation, valAnnotation.sourceStart, valAnnotation.sourceEnd);
      try {
        Reflection.astConverterRecordNodes.invoke(converter, newAnnotation, valAnnotation);
        Reflection.astConverterRecordNodes.invoke(
            converter, newAnnotation.getTypeName(), valAnnotation.type);
      } catch (IllegalAccessException e) {
        throw Lombok.sneakyThrow(e);
      } catch (InvocationTargetException e) {
        throw Lombok.sneakyThrow(e.getCause());
      }
      modifiers.add(newAnnotation);
    }
  }