Browse Source

Merge branch 'master' into test/java9-jigsaw

tags/rel_3_22_0_cr1
chibash 7 years ago
parent
commit
5ea5b6695c

+ 4
- 3
src/main/javassist/CtClassType.java View File

@@ -1400,10 +1400,11 @@ class CtClassType extends CtClass {

int mod = m.getModifiers();
if ((getModifiers() & Modifier.INTERFACE) != 0) {
m.setModifiers(mod | Modifier.PUBLIC);
if ((mod & Modifier.ABSTRACT) == 0)
if (Modifier.isProtected(mod) || Modifier.isPrivate(mod))
throw new CannotCompileException(
"an interface method must be abstract: " + m.toString());
"an interface method must be public: " + m.toString());

m.setModifiers(mod | Modifier.PUBLIC);
}

getMembers().addMethod(m);

+ 26
- 0
src/main/javassist/bytecode/AnnotationsAttribute.java View File

@@ -213,6 +213,32 @@ public class AnnotationsAttribute extends AttributeInfo {
setAnnotations(newlist);
}

/**
* Removes an annotation by type.
* After removing an annotation, if {@link #numAnnotations()} returns 0,
* this annotations attribute has to be removed.
*
* @param type of annotation to remove
* @return whether an annotation with the given type has been removed
* @since 3.21
*/
public boolean removeAnnotation(String type) {
Annotation[] annotations = getAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].getTypeName().equals(type)) {
Annotation[] newlist = new Annotation[annotations.length - 1];
System.arraycopy(annotations, 0, newlist, 0, i);
if (i < annotations.length - 1) {
System.arraycopy(annotations, i + 1, newlist, i,
annotations.length - i - 1);
}
setAnnotations(newlist);
return true;
}
}
return false;
}

/**
* Parses the annotations and returns a data structure representing
* that parsed annotations. Note that changes of the node values of the

+ 8
- 3
src/main/javassist/bytecode/AttributeInfo.java View File

@@ -231,16 +231,21 @@ public class AttributeInfo {
return null; // no such attribute
}

static synchronized void remove(ArrayList list, String name) {
static synchronized AttributeInfo remove(ArrayList list, String name) {
if (list == null)
return;
return null;

AttributeInfo removed = null;
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
AttributeInfo ai = (AttributeInfo)iterator.next();
if (ai.getName().equals(name))
if (ai.getName().equals(name)) {
iterator.remove();
removed = ai;
}
}

return removed;
}

static void writeAll(ArrayList list, DataOutputStream out)

+ 16
- 0
src/main/javassist/bytecode/ClassFile.java View File

@@ -771,6 +771,11 @@ public final class ClassFile {
* Returns the attribute with the specified name. If there are multiple
* attributes with that name, this method returns either of them. It
* returns null if the specified attributed is not found.
*
* <p>An attribute name can be obtained by, for example,
* {@link AnnotationsAttribute#visibleTab} or
* {@link AnnotationsAttribute#invisibleTab}.
* </p>
*
* @param name attribute name
* @see #getAttributes()
@@ -787,6 +792,17 @@ public final class ClassFile {
return null;
}

/**
* Removes an attribute with the specified name.
*
* @param name attribute name.
* @return the removed attribute or null.
* @since 3.21
*/
public AttributeInfo removeAttribute(String name) {
return AttributeInfo.remove(attributes, name);
}

/**
* Appends an attribute. If there is already an attribute with the same
* name, the new one substitutes for it.

+ 16
- 0
src/main/javassist/bytecode/FieldInfo.java View File

@@ -231,6 +231,11 @@ public final class FieldInfo {
* Returns the attribute with the specified name.
* It returns null if the specified attribute is not found.
*
* <p>An attribute name can be obtained by, for example,
* {@link AnnotationsAttribute#visibleTab} or
* {@link AnnotationsAttribute#invisibleTab}.
* </p>
*
* @param name attribute name
* @see #getAttributes()
*/
@@ -238,6 +243,17 @@ public final class FieldInfo {
return AttributeInfo.lookup(attribute, name);
}

/**
* Removes an attribute with the specified name.
*
* @param name attribute name.
* @return the removed attribute or null.
* @since 3.21
*/
public AttributeInfo removeAttribute(String name) {
return AttributeInfo.remove(attribute, name);
}

/**
* Appends an attribute. If there is already an attribute with
* the same name, the new one substitutes for it.

+ 16
- 0
src/main/javassist/bytecode/MethodInfo.java View File

@@ -315,6 +315,11 @@ public class MethodInfo {
* Returns the attribute with the specified name. If it is not found, this
* method returns null.
*
* <p>An attribute name can be obtained by, for example,
* {@link AnnotationsAttribute#visibleTab} or
* {@link AnnotationsAttribute#invisibleTab}.
* </p>
*
* @param name attribute name
* @return an <code>AttributeInfo</code> object or null.
* @see #getAttributes()
@@ -323,6 +328,17 @@ public class MethodInfo {
return AttributeInfo.lookup(attribute, name);
}

/**
* Removes an attribute with the specified name.
*
* @param name attribute name.
* @return the removed attribute or null.
* @since 3.21
*/
public AttributeInfo removeAttribute(String name) {
return AttributeInfo.remove(attribute, name);
}

/**
* Appends an attribute. If there is already an attribute with the same
* name, the new one substitutes for it.

+ 7
- 2
src/main/javassist/bytecode/analysis/ControlFlow.java View File

@@ -71,6 +71,8 @@ public class ControlFlow {
return new Block[size];
}
}.make(minfo);
if (basicBlocks == null)
basicBlocks = new Block[0];
int size = basicBlocks.length;
int[] counters = new int[size];
for (int i = 0; i < size; i++) {
@@ -97,6 +99,9 @@ public class ControlFlow {

/**
* Returns all the basic blocks in the method body.
*
* @return an array of basic blocks, the array has length 0 if
* the method doesn't have code.
*/
public Block[] basicBlocks() {
return basicBlocks;
@@ -133,7 +138,7 @@ public class ControlFlow {
* For every array element <code>node</code>, its index in the
* array is equivalent to <code>node.block().index()</code>.
*
* @return an array of the tree nodes, or null if the method is abstract.
* @return an array of the tree nodes, or null if the method doesn't have code.
* @see Node#block()
* @see Block#index()
*/
@@ -179,7 +184,7 @@ public class ControlFlow {
* For every array element <code>node</code>, its index in the
* array is equivalent to <code>node.block().index()</code>.
*
* @return an array of the tree nodes, or null if the method is abstract.
* @return an array of the tree nodes, or null if the method doesn't have code.
* @see Node#block()
* @see Block#index()
*/

+ 2
- 1
src/test/javassist/JvstTest3.java View File

@@ -1086,7 +1086,8 @@ public class JvstTest3 extends JvstTestRoot {
CtMethod m3 = CtMethod.make("public void foo3() {}", cc);
try {
cc.addMethod(m3);
fail();
if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_8)
fail();
}
catch (CannotCompileException e) {
// System.out.println(e);

+ 48
- 0
src/test/javassist/JvstTest5.java View File

@@ -4,6 +4,7 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.TypeVariable;

import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.AttributeInfo;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.InnerClassesAttribute;
@@ -241,5 +242,52 @@ public class JvstTest5 extends JvstTestRoot {
cp.appendClassPath(new LoaderClassPath(new Loader()));
assertNotNull(cp.get(Object.class.getName()));
assertNotNull(cp.get(this.getClass().getName()));

public void testAddDefaultMethod() throws Exception {
CtClass cc = sloader.makeInterface("test5.AddDefaultMethod");
cc.addMethod(CtNewMethod.make("static int foo() { return 1; }", cc));
cc.addMethod(CtNewMethod.make("public static int foo1() { return 1; }", cc));
cc.addMethod(CtNewMethod.make("public int foo2() { return 1; }", cc));
cc.addMethod(CtNewMethod.make("int foo3() { return 1; }", cc));
try {
cc.addMethod(CtNewMethod.make("private int foo4() { return 1; }", cc));
fail();
} catch (CannotCompileException e) {}
try {
cc.addMethod(CtNewMethod.make("private static int foo5() { return 1; }", cc));
fail();
} catch (CannotCompileException e) {}
}

public void testRemoveAnnotatino() throws Exception {
CtClass cc = sloader.get("test5.RemoveAnnotation");
AnnotationsAttribute aa
= (AnnotationsAttribute)cc.getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
assertTrue(aa.removeAnnotation("test5.RemoveAnno1"));
AttributeInfo ai = cc.getClassFile().removeAttribute(AnnotationsAttribute.invisibleTag);
assertEquals(ai.getName(), AnnotationsAttribute.invisibleTag);

CtMethod foo = cc.getDeclaredMethod("foo");
AnnotationsAttribute aa2 = (AnnotationsAttribute)foo.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag);
assertTrue(aa2.removeAnnotation("test5.RemoveAnno1"));

CtMethod bar = cc.getDeclaredMethod("bar");
AnnotationsAttribute aa3 = (AnnotationsAttribute)bar.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag);
assertFalse(aa3.removeAnnotation("test5.RemoveAnno1"));
assertTrue(aa3.removeAnnotation("test5.RemoveAnno2"));
AttributeInfo ai2 = bar.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
assertEquals(ai2.getName(), AnnotationsAttribute.invisibleTag);

CtMethod run = cc.getDeclaredMethod("run");
AttributeInfo ai3 = run.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
assertNull(ai3);

CtField baz = cc.getDeclaredField("baz");
AttributeInfo ai4 = baz.getFieldInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
assertEquals(ai4.getName(), AnnotationsAttribute.invisibleTag);

cc.writeFile();
Object obj = make(cc.getName());
assertEquals(3, invoke(obj, "run"));
}
}

+ 20
- 0
src/test/test5/RemoveAnnotation.java View File

@@ -0,0 +1,20 @@
package test5;

@interface RemoveAnno1 {}

@interface RemoveAnno2 {
int foo() default 3;
}

@RemoveAnno1 public class RemoveAnnotation {
@RemoveAnno1 @RemoveAnno2(foo=4)
int foo() { return 1; }

@RemoveAnno2
int bar() { return 2; }

@RemoveAnno1
int baz = 10;

public int run() { return foo() + bar(); }
}

Loading…
Cancel
Save