]> source.dussan.org Git - javassist.git/commitdiff
enables removal of attributes 108/head
authorchibash <chiba@javassist.org>
Sun, 18 Sep 2016 14:49:43 +0000 (23:49 +0900)
committerchibash <chiba@javassist.org>
Sun, 18 Sep 2016 14:49:43 +0000 (23:49 +0900)
src/main/javassist/bytecode/AnnotationsAttribute.java
src/main/javassist/bytecode/AttributeInfo.java
src/main/javassist/bytecode/ClassFile.java
src/main/javassist/bytecode/FieldInfo.java
src/main/javassist/bytecode/MethodInfo.java
src/test/javassist/JvstTest5.java
src/test/test5/RemoveAnnotation.java [new file with mode: 0644]

index c4d5f3deaa6ff06f13553548ae3a1fba0a01d8c3..be69fe8b76fbd888f6bd219c05b37bc37034aff6 100644 (file)
@@ -215,9 +215,12 @@ public class AnnotationsAttribute extends AttributeInfo {
 
     /**
      * 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();
index 9a1ac16c69c1377e15a30250e3e3898d84ae259a..5fd73281a21354eb8060d36cd1b59e6d442e3876 100644 (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)
index 887ec7a32a79bbccfd49baede69a1306445e91e9..f53ff149c51482727b07434779f7e5d4f0d54193 100644 (file)
@@ -761,6 +761,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()
@@ -777,6 +782,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.
index cbba0a85792475a953ece7d455ec734603fa27ff..0e2f76a5582f4cb223ab33477e6a3b1510e88ddc 100644 (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.
index 4b8c1c4de616eb315c43e9c37638dd7fc1253012..72642268fa94a3ea75f3a0a924babf2c77c6dcd3 100644 (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.
index 779df525a40ade9f9e43b24dc1964018399f7a42..c20a85f2cc5074228242a33c543678ebe2e7c604 100644 (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;
@@ -251,4 +252,36 @@ public class JvstTest5 extends JvstTestRoot {
             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"));
+    }
 }
diff --git a/src/test/test5/RemoveAnnotation.java b/src/test/test5/RemoveAnnotation.java
new file mode 100644 (file)
index 0000000..97f7525
--- /dev/null
@@ -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(); }
+}