Skip to content

Commit

Permalink
Allow non-public properties for Java 8 interface types.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Jul 24, 2016
1 parent 2f4fb85 commit e693a3c
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 26 deletions.
Expand Up @@ -1916,11 +1916,13 @@ public MethodVisitor visitMethod(int modifiers, String name, String descriptor,
constraint.assertMethod(name, constraint.assertMethod(name,
(modifiers & Opcodes.ACC_ABSTRACT) != 0, (modifiers & Opcodes.ACC_ABSTRACT) != 0,
(modifiers & Opcodes.ACC_PUBLIC) != 0, (modifiers & Opcodes.ACC_PUBLIC) != 0,
(modifiers & Opcodes.ACC_PRIVATE) != 0,
(modifiers & Opcodes.ACC_STATIC) != 0, (modifiers & Opcodes.ACC_STATIC) != 0,
!name.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME)
&& !name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
&& (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC)) == 0,
name.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME),
!descriptor.startsWith(NO_PARAMETERS) || descriptor.endsWith(RETURNS_VOID), !descriptor.startsWith(NO_PARAMETERS) || descriptor.endsWith(RETURNS_VOID),
name.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME)
|| name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
|| (modifiers & Opcodes.ACC_PRIVATE) != 0,
signature != null); signature != null);
return new ValidatingMethodVisitor(super.visitMethod(modifiers, name, descriptor, signature, exceptions), name); return new ValidatingMethodVisitor(super.visitMethod(modifiers, name, descriptor, signature, exceptions), name);
} }
Expand Down Expand Up @@ -1962,17 +1964,21 @@ protected interface Constraint {
* @param name The name of the method. * @param name The name of the method.
* @param isAbstract {@code true} if the method is abstract. * @param isAbstract {@code true} if the method is abstract.
* @param isPublic {@code true} if this method is public. * @param isPublic {@code true} if this method is public.
* @param isPrivate {@code true} if this method is private.
* @param isStatic {@code true} if this method is static. * @param isStatic {@code true} if this method is static.
* @param isVirtual {@code true} if this method is virtual.
* @param isConstructor {@code true} if this method is a constructor.
* @param isDefaultValueIncompatible {@code true} if a method's signature cannot describe an annotation property method. * @param isDefaultValueIncompatible {@code true} if a method's signature cannot describe an annotation property method.
* @param isNonStaticNonVirtual {@code true} if the method is non-virtual and non-static, i.e. a constructor, type initializer or private.
* @param isGeneric {@code true} if this method defines a generic signature. * @param isGeneric {@code true} if this method defines a generic signature.
*/ */
void assertMethod(String name, void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isVirtual,
boolean isConstructor,
boolean isDefaultValueIncompatible, boolean isDefaultValueIncompatible,
boolean isNonStaticNonVirtual,
boolean isGeneric); boolean isGeneric);


/** /**
Expand Down Expand Up @@ -2065,9 +2071,11 @@ public void assertField(String name, boolean isPublic, boolean isStatic, boolean
public void assertMethod(String name, public void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isVirtual,
boolean isConstructor,
boolean isDefaultValueIncompatible, boolean isDefaultValueIncompatible,
boolean isNonStaticNonVirtual,
boolean isGeneric) { boolean isGeneric) {
if (isAbstract && manifestType) { if (isAbstract && manifestType) {
throw new IllegalStateException("Cannot define abstract method '" + name + "' for non-abstract class"); throw new IllegalStateException("Cannot define abstract method '" + name + "' for non-abstract class");
Expand Down Expand Up @@ -2144,9 +2152,11 @@ public void assertField(String name, boolean isPublic, boolean isStatic, boolean
public void assertMethod(String name, public void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isDefaultValueIncompatible, boolean isVirtual,
boolean isNonStaticNonVirtual, boolean isConstructor,
boolean isNoDefaultValue,
boolean isGeneric) { boolean isGeneric) {
throw new IllegalStateException("Cannot define a method for a package description type"); throw new IllegalStateException("Cannot define a method for a package description type");
} }
Expand Down Expand Up @@ -2251,15 +2261,19 @@ public void assertField(String name, boolean isPublic, boolean isStatic, boolean
public void assertMethod(String name, public void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isVirtual,
boolean isConstructor,
boolean isDefaultValueIncompatible, boolean isDefaultValueIncompatible,
boolean isNonStaticNonVirtual,
boolean isGeneric) { boolean isGeneric) {
if (!name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) { if (!name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
if (!isPublic || isNonStaticNonVirtual) { if (isConstructor) {
throw new IllegalStateException("Cannot define non-public or non-virtual method '" + name + "' for interface type"); throw new IllegalStateException("Cannot define constructor for interface type");
} else if (classic && isStatic) { } else if (classic && !isPublic) {
throw new IllegalStateException("Cannot define static method '" + name + "' for a pre-Java 8 interface type"); throw new IllegalStateException("Cannot define non-public method '" + name + "' for interface type");
} else if (classic && !isVirtual) {
throw new IllegalStateException("Cannot define non-virtual method '" + name + "' for a pre-Java 8 interface type");
} else if (classic && !isAbstract) { } else if (classic && !isAbstract) {
throw new IllegalStateException("Cannot define default method '" + name + "' for pre-Java 8 interface type"); throw new IllegalStateException("Cannot define default method '" + name + "' for pre-Java 8 interface type");
} }
Expand All @@ -2278,7 +2292,7 @@ public void assertTypeAnnotation() {


@Override @Override
public void assertDefaultValue(String name) { public void assertDefaultValue(String name) {
/* do nothing */ throw new IllegalStateException("Cannot define default value for '" + name + "' for non-annotation type");
} }


@Override @Override
Expand Down Expand Up @@ -2362,15 +2376,17 @@ public void assertField(String name, boolean isPublic, boolean isStatic, boolean
public void assertMethod(String name, public void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isVirtual,
boolean isConstructor,
boolean isDefaultValueIncompatible, boolean isDefaultValueIncompatible,
boolean isNonStaticNonVirtual,
boolean isGeneric) { boolean isGeneric) {
if (!name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) { if (!name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
if (!isPublic || isNonStaticNonVirtual) { if (isConstructor) {
throw new IllegalStateException("Cannot define non-public, non-abstract or non-virtual method '" + name + "' for annotation type"); throw new IllegalStateException("Cannot define constructor for interface type");
} else if (classic && isStatic) { } else if (classic && !isVirtual) {
throw new IllegalStateException("Cannot define static method '" + name + "' for a pre-Java 8 annotation type"); throw new IllegalStateException("Cannot define non-virtual method '" + name + "' for a pre-Java 8 annotation type");
} else if (!isStatic && isDefaultValueIncompatible) { } else if (!isStatic && isDefaultValueIncompatible) {
throw new IllegalStateException("Cannot define method '" + name + "' with the given signature as an annotation type method"); throw new IllegalStateException("Cannot define method '" + name + "' with the given signature as an annotation type method");
} }
Expand Down Expand Up @@ -2474,13 +2490,15 @@ public void assertField(String name, boolean isPublic, boolean isStatic, boolean
public void assertMethod(String name, public void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isVirtual,
boolean isConstructor,
boolean isDefaultValueIncompatible, boolean isDefaultValueIncompatible,
boolean isNonStaticNonVirtual,
boolean isGeneric) { boolean isGeneric) {
if (isGeneric && !classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) { if (isGeneric && !classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
throw new IllegalStateException("Cannot define generic method '" + name + "' for class file version " + classFileVersion); throw new IllegalStateException("Cannot define generic method '" + name + "' for class file version " + classFileVersion);
} else if ((isStatic || isNonStaticNonVirtual) && isAbstract) { } else if (!isVirtual && isAbstract) {
throw new IllegalStateException("Cannot define static or non-virtual method '" + name + "' to be abstract"); throw new IllegalStateException("Cannot define static or non-virtual method '" + name + "' to be abstract");
} }
} }
Expand Down Expand Up @@ -2602,17 +2620,21 @@ public void assertField(String name, boolean isPublic, boolean isStatic, boolean
public void assertMethod(String name, public void assertMethod(String name,
boolean isAbstract, boolean isAbstract,
boolean isPublic, boolean isPublic,
boolean isPrivate,
boolean isStatic, boolean isStatic,
boolean isVirtual,
boolean isConstructor,
boolean isDefaultValueIncompatible, boolean isDefaultValueIncompatible,
boolean isNonStaticNonVirtual,
boolean isGeneric) { boolean isGeneric) {
for (Constraint constraint : constraints) { for (Constraint constraint : constraints) {
constraint.assertMethod(name, constraint.assertMethod(name,
isAbstract, isAbstract,
isPublic, isPublic,
isPrivate,
isStatic, isStatic,
isVirtual,
isConstructor,
isDefaultValueIncompatible, isDefaultValueIncompatible,
isNonStaticNonVirtual,
isGeneric); isGeneric);
} }
} }
Expand Down
Expand Up @@ -7,6 +7,7 @@
import net.bytebuddy.description.field.FieldList; import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList; import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.modifier.ModifierConstributorObjectPropertiesTest;
import net.bytebuddy.description.modifier.Ownership; import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.TypeManifestation; import net.bytebuddy.description.modifier.TypeManifestation;
import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.description.modifier.Visibility;
Expand Down Expand Up @@ -171,7 +172,16 @@ public void testStaticFieldWithNonDefinableConstantValue() throws Exception {


@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void testNonPublicMethodOnInterfaceAssertion() throws Exception { public void testNonPublicMethodOnInterfaceAssertion() throws Exception {
new ByteBuddy() new ByteBuddy(ClassFileVersion.JAVA_V6)
.makeInterface()
.defineMethod(FOO, void.class)
.withoutCode()
.make();
}

@Test
public void testNonPublicMethodOnInterfaceAssertionJava8() throws Exception {
new ByteBuddy(ClassFileVersion.JAVA_V8)
.makeInterface() .makeInterface()
.defineMethod(FOO, void.class) .defineMethod(FOO, void.class)
.withoutCode() .withoutCode()
Expand Down Expand Up @@ -229,6 +239,7 @@ public void testStaticMethodOnInterfaceAssertionJava8() throws Exception {
public void testAnnotationDefaultValueOnClassAssertion() throws Exception { public void testAnnotationDefaultValueOnClassAssertion() throws Exception {
new ByteBuddy() new ByteBuddy()
.subclass(Object.class) .subclass(Object.class)
.merge(TypeManifestation.ABSTRACT)
.defineMethod(FOO, String.class) .defineMethod(FOO, String.class)
.defaultValue(BAR) .defaultValue(BAR)
.make(); .make();
Expand All @@ -237,8 +248,7 @@ public void testAnnotationDefaultValueOnClassAssertion() throws Exception {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void testAnnotationDefaultValueOnInterfaceClassAssertion() throws Exception { public void testAnnotationDefaultValueOnInterfaceClassAssertion() throws Exception {
new ByteBuddy() new ByteBuddy()
.subclass(Object.class) .makeInterface()
.modifiers(TypeManifestation.INTERFACE)
.defineMethod(FOO, String.class) .defineMethod(FOO, String.class)
.defaultValue(BAR) .defaultValue(BAR)
.make(); .make();
Expand Down

0 comments on commit e693a3c

Please sign in to comment.