[fixes #2006] Delegate now excludes already implemented methods

This commit is contained in:
Rawi01 authored and Roel Spilker committed 2020-05-28 22:36:35 +02:00
1 parent 7d08af7d85
commit a2a194f32d
5 files changed
+194 -9

No files matched your search

@@ -48,6 +48,7 @@ import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Attribute.Compound;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ClassType;
@@ -175,14 +176,14 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
List<MethodSig> signaturesToExclude = new ArrayList<MethodSig>();
Set<String> banList = new HashSet<String>();
banList.addAll(METHODS_IN_OBJECT);
/* To exclude all methods in the class itself, try this:
for (Symbol member : ((JCClassDecl)typeNode.get()).sym.getEnclosedElements()) {
if (member instanceof MethodSymbol) {
MethodSymbol method = (MethodSymbol) member;
banList.add(printSig((ExecutableType) method.asType(), method.name, annotationNode.getTypesUtil()));
// Add already implemented methods to ban list
JavacNode typeNode = upToTypeNode(annotationNode);
for (Symbol m : ((JCClassDecl)typeNode.get()).sym.getEnclosedElements()) {
if (m instanceof MethodSymbol) {
banList.add(printSig((ExecutableType) m.asType(), m.name, annotationNode.getTypesUtil()));
}
}
*/
try {
for (Type t : toExclude) {
@@ -29,11 +29,14 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.core.AST.Kind;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAST;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.TransformEclipseAST;
@@ -67,6 +70,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
@@ -214,7 +218,7 @@ public class PatchDelegate {
addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet<String>(), field.name, ann);
}
Set<String> banList = new HashSet<String>();
Set<String> banList = findAlreadyImplementedMethods(decl);
for (BindingTuple excluded : methodsToExclude) banList.add(printSig(excluded.parameterized));
if (rawTypes.isEmpty()) {
@@ -283,8 +287,8 @@ public class PatchDelegate {
for (ClassLiteralAccess cla : excludedRawTypes) {
addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet<String>(), method.selector, ann);
}
Set<String> banList = new HashSet<String>();
Set<String> banList = findAlreadyImplementedMethods(decl);
for (BindingTuple excluded : methodsToExclude) banList.add(printSig(excluded.parameterized));
if (rawTypes.isEmpty()) {
@@ -764,6 +768,21 @@ public class PatchDelegate {
}
}
private static Set<String> findAlreadyImplementedMethods(TypeDeclaration decl) {
Set<String> sigs = new HashSet<String>();
for (AbstractMethodDeclaration md : decl.methods) {
if (md.isStatic()) continue;
if ((md.modifiers & ClassFileConstants.AccBridge) != 0) continue;
if (md.isConstructor()) continue;
if ((md.modifiers & ExtraCompilerModifiers.AccDefaultAbstract) != 0) continue;
if ((md.modifiers & ClassFileConstants.AccPublic) == 0) continue;
if ((md.modifiers & ClassFileConstants.AccSynthetic) != 0) continue;
sigs.add(printSig(md, decl.scope));
}
return sigs;
}
private static final char[] STRING_LOMBOK = new char[] {'l', 'o', 'm', 'b', 'o', 'k'};
private static final char[] STRING_EXPERIMENTAL = new char[] {'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l'};
private static final char[] STRING_DELEGATE = new char[] {'D', 'e', 'l', 'e', 'g', 'a', 't', 'e'};
@@ -839,6 +858,54 @@ public class PatchDelegate {
return signature.toString();
}
private static String printSig(AbstractMethodDeclaration md, ClassScope scope) {
StringBuilder signature = new StringBuilder();
signature.append(md.selector);
signature.append("(");
boolean first = true;
if (md.arguments != null) {
TypeParameter[] typeParameters = md.typeParameters();
Map<String, TypeParameter> typeParametersMap = new HashMap<String, TypeParameter>();
if (typeParameters != null) {
for (TypeParameter typeParameter : typeParameters) {
typeParametersMap.put(new String(typeParameter.name), typeParameter);
}
}
for (Argument argument : md.arguments) {
TypeBinding typeBinding = makeTypeBinding(argument.type, typeParametersMap, scope);
if (!first) signature.append(", ");
first = false;
signature.append(typeBindingToSignature(typeBinding));
}
}
signature.append(")");
return signature.toString();
}
private static TypeBinding makeTypeBinding(TypeReference typeReference, Map<String, TypeParameter> typeParametersMap, ClassScope scope) {
char[][] typeName = typeReference.getTypeName();
String typeNameString = Eclipse.toQualifiedName(typeName);
TypeParameter typeParameter = typeParametersMap.get(typeNameString);
if (typeParameter != null) {
if (typeParameter.type != null) {
typeName = typeParameter.type.getTypeName();
} else {
typeName = TypeConstants.JAVA_LANG_OBJECT;
}
}
TypeBinding typeBinding = scope.getType(typeName, typeName.length);
if (typeReference.dimensions() > 0) {
typeBinding = scope.createArrayType(typeBinding, typeReference.dimensions());
}
return typeBinding;
}
private static String typeBindingToSignature(TypeBinding binding) {
binding = binding.erasure();
if (binding != null && binding.isBaseType()) {
@@ -0,0 +1,43 @@
public class DelegateAlreadyImplemented<T> {
private A<Integer, T> a;
public void a() {
}
public void b(java.util.List<String> l) {
}
public void c(java.util.List<Integer> l, String[] a, Integer... varargs) {
}
public void d(String[][][][] d) {
}
public <Y> void e(Y x) {
}
@SuppressWarnings("unchecked")
public void f(T s, java.util.List<T> l, T[] a, T... varargs) {
}
public void g(Number g) {
}
}
interface A<T, T2> {
void a();
void b(java.util.List<T> l);
@SuppressWarnings("unchecked")
void c(java.util.List<T> l, String[] a, T... varargs);
void d(String[][][][] d);
<X> X e(X x);
@SuppressWarnings("unchecked")
void f(T2 s, java.util.List<T2> l, T2[] a, T2... varargs);
<G extends Number> void g(G g);
}
@@ -0,0 +1,29 @@
public class DelegateAlreadyImplemented<T> {
private @lombok.experimental.Delegate A<Integer, T> a;
public DelegateAlreadyImplemented() {
super();
}
public void a() {
}
public void b(java.util.List<String> l) {
}
public void c(java.util.List<Integer> l, String[] a, Integer... varargs) {
}
public void d(String[][][][] d) {
}
public <Y>void e(Y x) {
}
public @SuppressWarnings("unchecked") void f(T s, java.util.List<T> l, T[] a, T... varargs) {
}
public void g(Number g) {
}
}
interface A<T, T2> {
public void a();
public void b(java.util.List<T> l);
public @SuppressWarnings("unchecked") void c(java.util.List<T> l, String[] a, T... varargs);
public void d(String[][][][] d);
public <X>X e(X x);
public @SuppressWarnings("unchecked") void f(T2 s, java.util.List<T2> l, T2[] a, T2... varargs);
public <G extends Number>void g(G g);
}
@@ -0,0 +1,45 @@
public class DelegateAlreadyImplemented<T> {
@lombok.experimental.Delegate
private A<Integer, T> a;
public void a() {
}
public void b(java.util.List<String> l) {
}
public void c(java.util.List<Integer> l, String[] a, Integer... varargs) {
}
public void d(String[][][][] d) {
}
public <Y> void e(Y x) {
}
@SuppressWarnings("unchecked")
public void f(T s, java.util.List<T> l, T[] a, T... varargs) {
}
public void g(Number g) {
}
}
interface A<T, T2> {
public void a();
public void b(java.util.List<T> l);
@SuppressWarnings("unchecked")
public void c(java.util.List<T> l, String[] a, T... varargs);
public void d(String[][][][] d);
public <X> X e(X x);
@SuppressWarnings("unchecked")
public void f(T2 s, java.util.List<T2> l, T2[] a, T2... varargs);
public <G extends Number> void g(G g);
}