mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 12:16:49 +00:00
Merge remote branch 'origin/master'
This commit is contained in:
commit
4689d2a9bf
16 files changed
+193
-18
No files matched your search
@@ -4,6 +4,7 @@ Lombok Changelog
|
||||
### v0.10.9 (edge)
|
||||
* FEATURE: The combination of `@Delegate` and `@Getter` or `@Data` will now delegate to the result of a generated getter. [Issue #328](http://code.google.com/p/projectlombok/issues/detail?id=328)
|
||||
* BUGFIX: When `@Delegate` would generate a method with type parameters of the type `T extends package.Class`, a dot would be prepended to the type name. [Issue #341](http://code.google.com/p/projectlombok/issues/detail?id=341)
|
||||
* BUGFIX: @Getter and @Setter now generate deprecated methods for deprecated fields. Fixes [Issue #342](http://code.google.com/p/projectlombok/issues/detail?id=342)
|
||||
* BUGFIX: Using `val` with a type like `Outer<TypeArgs>.Inner` now works. [Issue #343](http://code.google.com/p/projectlombok/issues/detail?id=343)
|
||||
* BUGFIX: `@Getter(lazy=true)` where the variable type is a primitive and the initializing expression is of a different primitive type that would type coerce implicitly, i.e. ints can be assigned to longs without a cast, didn't work before. [Issue #345](http://code.google.com/p/projectlombok/issues/detail?id=345)
|
||||
* BUGFIX: `val` is no longer legal inside basic for loops (the old kind, not the foreach kind). These variables should rarely be final, and in practice it wasn't possible to delombok this code properly. [Issue #346](http://code.google.com/p/projectlombok/issues/detail?id=346)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Project Lombok Authors.
|
||||
* Copyright (C) 2010-2012 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,6 +21,9 @@
|
||||
*/
|
||||
package lombok.bytecode;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
|
||||
@@ -36,6 +39,43 @@ class FixedClassWriter extends ClassWriter {
|
||||
return super.getCommonSuperClass(type1, type2);
|
||||
} catch (Exception e) {
|
||||
return "java/lang/Object";
|
||||
} catch (ClassFormatError e) {
|
||||
ClassLoader cl = this.getClass().getClassLoader();
|
||||
if (cl == null) cl = ClassLoader.getSystemClassLoader();
|
||||
String message = debugCheckClassFormatErrorIssue(cl, type1) +
|
||||
debugCheckClassFormatErrorIssue(cl, type2);
|
||||
throw new ClassFormatError(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This is debug-aiding code in an attempt to find the cause of issue:
|
||||
// http://code.google.com/p/projectlombok/issues/detail?id=339
|
||||
private static String debugCheckClassFormatErrorIssue(ClassLoader cl, String type) {
|
||||
try {
|
||||
Class.forName(type.replace('/', '.'), false, cl);
|
||||
return String.format("Class.forName debug on %s: no issues\n", type);
|
||||
} catch (ClassFormatError e) {
|
||||
// expected
|
||||
} catch (Throwable e) {
|
||||
return String.format("Class.forName debug on %s: Exception: %s\n", type, e);
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream in = cl.getResourceAsStream(type + ".class");
|
||||
if (in == null) return String.format("Class.forName debug on %s: Can't find resource %s\n", type, type + ".class");
|
||||
try {
|
||||
int[] firstBytes = new int[4];
|
||||
for (int i = 0; i < 4; i++) firstBytes[0] = in.read();
|
||||
if (firstBytes[0] == -1) return String.format("Class.forName debug on %s: file size is 0\n", type);
|
||||
if (firstBytes[3] == -1) return String.format("Class.forName debug on %s: Less than 4 bytes in class file\n", type);
|
||||
if (!Arrays.equals(new int[] {0xCA, 0xFE, 0xBA, 0xBE}, firstBytes)) return String.format("Class.forName debug on %s: no CAFEBABE: %s\n", type, Arrays.toString(firstBytes));
|
||||
return String.format("Class.forName debug on %s: No immediately obvious reason for failure found\n", type);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
return String.format("Class.forName debug on %s: Can't read as stream: %s\n", type, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ public class TypeResolver {
|
||||
Set<String> imports = new HashSet<String>();
|
||||
if (packageString != null) imports.add(packageString + ".*");
|
||||
imports.addAll(importStrings == null ? Collections.<String>emptySet() : importStrings);
|
||||
imports.add("java.lang.*");
|
||||
return imports;
|
||||
}
|
||||
|
||||
|
||||
@@ -245,6 +245,27 @@ public class EclipseHandlerUtil {
|
||||
return node;
|
||||
}
|
||||
|
||||
public static MarkerAnnotation generateDeprecatedAnnotation(ASTNode source) {
|
||||
QualifiedTypeReference qtr = new QualifiedTypeReference(new char[][] {
|
||||
{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'D', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd'}}, poss(source, 3));
|
||||
setGeneratedBy(qtr, source);
|
||||
return new MarkerAnnotation(qtr, source.sourceStart);
|
||||
}
|
||||
|
||||
public static boolean isFieldDeprecated(EclipseNode fieldNode) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
if ((field.modifiers & ClassFileConstants.AccDeprecated) != 0) {
|
||||
return true;
|
||||
}
|
||||
if (field.annotations == null) return false;
|
||||
for (Annotation annotation : field.annotations) {
|
||||
if (typeMatches(Deprecated.class, fieldNode, annotation.type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given TypeReference node is likely to be a reference to the provided class.
|
||||
*
|
||||
|
||||
@@ -212,14 +212,20 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
|
||||
}
|
||||
|
||||
MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), fieldNode, getterName, modifier, source, lazy);
|
||||
Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), findDelegatesAndMarkAsHandled(fieldNode));
|
||||
|
||||
Annotation[] deprecated = null;
|
||||
if (isFieldDeprecated(fieldNode)) {
|
||||
deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
|
||||
}
|
||||
|
||||
Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), findDelegatesAndMarkAsHandled(fieldNode), deprecated);
|
||||
if (copiedAnnotations.length != 0) {
|
||||
method.annotations = copiedAnnotations;
|
||||
}
|
||||
|
||||
injectMethod(fieldNode.up(), method);
|
||||
}
|
||||
|
||||
|
||||
private static Annotation[] findDelegatesAndMarkAsHandled(EclipseNode fieldNode) {
|
||||
List<Annotation> delegates = new ArrayList<Annotation>();
|
||||
for (EclipseNode child : fieldNode.down()) {
|
||||
|
||||
@@ -184,7 +184,9 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
method.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
|
||||
method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE;
|
||||
setGeneratedBy(method.returnType, source);
|
||||
method.annotations = null;
|
||||
if (isFieldDeprecated(fieldNode)) {
|
||||
method.annotations = new Annotation[] { generateDeprecatedAnnotation(source) };
|
||||
}
|
||||
Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL);
|
||||
param.sourceStart = pS; param.sourceEnd = pE;
|
||||
setGeneratedBy(param, source);
|
||||
|
||||
@@ -74,11 +74,9 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
|
||||
public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) {
|
||||
if (checkForTypeLevelGetter) {
|
||||
if (typeNode != null) for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (annotationTypeMatches(Getter.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
if (annotationTypeMatches(Getter.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,6 +242,9 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
|
||||
List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field);
|
||||
|
||||
List<JCAnnotation> annsOnMethod = nonNulls.appendList(nullables);
|
||||
if (isFieldDeprecated(field)) {
|
||||
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil()));
|
||||
}
|
||||
|
||||
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
|
||||
|
||||
@@ -208,6 +208,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
JCBlock methodBody = treeMaker.Block(0, statements);
|
||||
Name methodName = field.toName(toSetterName(fieldDecl));
|
||||
List<JCAnnotation> annsOnParam = nonNulls.appendList(nullables);
|
||||
|
||||
JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.FINAL, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
|
||||
//WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6.
|
||||
JCExpression methodType = treeMaker.Type(new JCNoType(getCtcInt(TypeTags.class, "VOID")));
|
||||
@@ -217,7 +218,11 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
List<JCExpression> throwsClauses = List.nil();
|
||||
JCExpression annotationMethodDefaultValue = null;
|
||||
|
||||
return recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, List.<JCAnnotation>nil()), methodName, methodType,
|
||||
List<JCAnnotation> annsOnMethod = List.nil();
|
||||
if (isFieldDeprecated(field)) {
|
||||
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(chainDots(field, "java", "lang", "Deprecated"), List.<JCExpression>nil()));
|
||||
}
|
||||
return recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2012 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -141,6 +141,24 @@ public class JavacHandlerUtil {
|
||||
return resolver.typeMatches(node, type.getName(), typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a field is marked deprecated, either by {@code @Deprecated} or in javadoc
|
||||
* @param field the field to check
|
||||
* @return {@code true} if a field is marked deprecated, either by {@code @Deprecated} or in javadoc, otherwise {@code false}
|
||||
*/
|
||||
public static boolean isFieldDeprecated(JavacNode field) {
|
||||
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
|
||||
if ((fieldNode.mods.flags & Flags.DEPRECATED) != 0) {
|
||||
return true;
|
||||
}
|
||||
for (JavacNode child : field.down()) {
|
||||
if (annotationTypeMatches(Deprecated.class, child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@code AnnotationValues} for the provided AST Node.
|
||||
*
|
||||
|
||||
@@ -51,11 +51,9 @@ import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Expression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
|
||||
@@ -613,11 +611,7 @@ public class PatchDelegate {
|
||||
}
|
||||
|
||||
if (isDeprecated) {
|
||||
QualifiedTypeReference qtr = new QualifiedTypeReference(new char[][] {
|
||||
{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'D', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd'}}, poss(source, 3));
|
||||
setGeneratedBy(qtr, source);
|
||||
MarkerAnnotation ann = new MarkerAnnotation(qtr, pS);
|
||||
method.annotations = new Annotation[] {ann};
|
||||
method.annotations = new Annotation[] { generateDeprecatedAnnotation(source) };
|
||||
}
|
||||
|
||||
method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
class GetterDeprecated {
|
||||
@Deprecated
|
||||
int annotation;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
int javadoc;
|
||||
@java.lang.Deprecated
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getAnnotation() {
|
||||
return this.annotation;
|
||||
}
|
||||
@java.lang.Deprecated
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getJavadoc() {
|
||||
return this.javadoc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
class SetterDeprecated {
|
||||
@Deprecated
|
||||
int annotation;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
int javadoc;
|
||||
@java.lang.Deprecated
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void setAnnotation(final int annotation) {
|
||||
this.annotation = annotation;
|
||||
}
|
||||
@java.lang.Deprecated
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void setJavadoc(final int javadoc) {
|
||||
this.javadoc = javadoc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import lombok.Getter;
|
||||
class GetterDeprecated {
|
||||
@Deprecated @Getter int annotation;
|
||||
@Getter int javadoc;
|
||||
public @java.lang.Deprecated @java.lang.SuppressWarnings("all") int getAnnotation() {
|
||||
return this.annotation;
|
||||
}
|
||||
public @java.lang.Deprecated @java.lang.SuppressWarnings("all") int getJavadoc() {
|
||||
return this.javadoc;
|
||||
}
|
||||
GetterDeprecated() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import lombok.Setter;
|
||||
class SetterDeprecated {
|
||||
@Deprecated @Setter int annotation;
|
||||
@Setter int javadoc;
|
||||
public @java.lang.Deprecated @java.lang.SuppressWarnings("all") void setAnnotation(final int annotation) {
|
||||
this.annotation = annotation;
|
||||
}
|
||||
public @java.lang.Deprecated @java.lang.SuppressWarnings("all") void setJavadoc(final int javadoc) {
|
||||
this.javadoc = javadoc;
|
||||
}
|
||||
SetterDeprecated() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import lombok.Getter;
|
||||
class GetterDeprecated {
|
||||
|
||||
@Deprecated
|
||||
@Getter int annotation;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Getter int javadoc;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import lombok.Setter;
|
||||
class SetterDeprecated {
|
||||
|
||||
@Deprecated
|
||||
@Setter int annotation;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Setter int javadoc;
|
||||
}
|
||||
Reference in new issue
Block a user