summaryrefslogtreecommitdiff
path: root/src/proguard/classfile/editor/MemberAdder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/classfile/editor/MemberAdder.java')
-rw-r--r--src/proguard/classfile/editor/MemberAdder.java147
1 files changed, 92 insertions, 55 deletions
diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java
index 5f939bb..811acae 100644
--- a/src/proguard/classfile/editor/MemberAdder.java
+++ b/src/proguard/classfile/editor/MemberAdder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -26,8 +26,9 @@ import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.MemberVisitor;
/**
- * This ConstantVisitor adds all class members that it visits to the given
- * target class.
+ * This MemberVisitor copies all class members that it visits to the given
+ * target class. Their visitor info is set to the class members from which they
+ * were copied.
*
* @author Eric Lafortune
*/
@@ -45,8 +46,9 @@ implements MemberVisitor
private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0];
- private final ProgramClass targetClass;
-// private final boolean addFields;
+ private final ProgramClass targetClass;
+// private final boolean addFields;
+ private final MemberVisitor extraMemberVisitor;
private final ConstantAdder constantAdder;
private final ClassEditor classEditor;
@@ -59,13 +61,30 @@ implements MemberVisitor
* @param targetClass the class to which all visited class members will be
* added.
*/
+ public MemberAdder(ProgramClass targetClass)
+ {
+ this(targetClass, null);
+ }
+
+
+ /**
+ * Creates a new MemberAdder that will copy methods into the given target
+ * class.
+ * @param targetClass the class to which all visited class members
+ * will be added.
+ * @param extraMemberVisitor an optional member visitor that visits each
+ * new member right after it has been added. This
+ * allows changing the visitor info, for instance.
+ */
// * @param addFields specifies whether fields should be added, or fused
// * with the present fields.
- public MemberAdder(ProgramClass targetClass)//),
-// boolean addFields)
+ public MemberAdder(ProgramClass targetClass,
+// boolean addFields,
+ MemberVisitor extraMemberVisitor)
{
- this.targetClass = targetClass;
-// this.addFields = addFields;
+ this.targetClass = targetClass;
+// this.addFields = addFields;
+ this.extraMemberVisitor = extraMemberVisitor;
constantAdder = new ConstantAdder(targetClass);
classEditor = new ClassEditor(targetClass);
@@ -77,51 +96,54 @@ implements MemberVisitor
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- String name = programField.getName(programClass);
- String descriptor = programField.getDescriptor(programClass);
+ //String name = programField.getName(programClass);
+ //String descriptor = programField.getDescriptor(programClass);
int accessFlags = programField.getAccessFlags();
- // Does the target class already have such a field?
- ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
- if (targetField != null)
- {
- // Is the field private or static?
- int targetAccessFlags = targetField.getAccessFlags();
- if ((targetAccessFlags &
- (ClassConstants.INTERNAL_ACC_PRIVATE |
- ClassConstants.INTERNAL_ACC_STATIC)) != 0)
- {
- if (DEBUG)
- {
- System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
- }
-
- // Rename the private or static field.
- targetField.u2nameIndex =
- constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
- }
-// else
-// {
-// // Keep the non-private and non-static field, but update its
-// // contents, in order to keep any references to it valid.
-// if (DEBUG)
-// {
-// System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
-// }
-//
-// // Combine the access flags.
-// targetField.u2accessFlags = accessFlags | targetAccessFlags;
-//
-// // Add and replace any attributes.
-// programField.attributesAccept(programClass,
-// new AttributeAdder(targetClass,
-// targetField,
-// true));
-//
-// // Don't add a new field.
-// return;
-// }
- }
+ // TODO: Handle field with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical field
+ // still causes confused field references.
+ //// Does the target class already have such a field?
+ //ProgramField targetField = (ProgramField)targetClass.findField(name, descriptor);
+ //if (targetField != null)
+ //{
+ // // Is the field private or static?
+ // int targetAccessFlags = targetField.getAccessFlags();
+ // if ((targetAccessFlags &
+ // (ClassConstants.INTERNAL_ACC_PRIVATE |
+ // ClassConstants.INTERNAL_ACC_STATIC)) != 0)
+ // {
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: renaming field ["+targetClass+"."+targetField.getName(targetClass)+" "+targetField.getDescriptor(targetClass)+"]");
+ // }
+ //
+ // // Rename the private or static field.
+ // targetField.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, targetClass.getName()));
+ // }
+ // else
+ // {
+ // // Keep the non-private and non-static field, but update its
+ // // contents, in order to keep any references to it valid.
+ // if (DEBUG)
+ // {
+ // System.out.println("MemberAdder: updating field ["+programClass+"."+programField.getName(programClass)+" "+programField.getDescriptor(programClass)+"] into ["+targetClass.getName()+"]");
+ // }
+ //
+ // // Combine the access flags.
+ // targetField.u2accessFlags = accessFlags | targetAccessFlags;
+ //
+ // // Add and replace any attributes.
+ // programField.attributesAccept(programClass,
+ // new AttributeAdder(targetClass,
+ // targetField,
+ // true));
+ //
+ // // Don't add a new field.
+ // return;
+ // }
+ //}
if (DEBUG)
{
@@ -150,6 +172,12 @@ implements MemberVisitor
// Add the completed field.
classEditor.addField(newProgramField);
+
+ // Visit the newly added field, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramField(targetClass, newProgramField);
+ }
}
@@ -206,9 +234,12 @@ implements MemberVisitor
System.out.println("MemberAdder: renaming method ["+targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
}
- // Rename the private (non-abstract) or static method.
- targetMethod.u2nameIndex =
- constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
+ // TODO: Handle non-abstract method with the same name and descriptor in the target class.
+ // We currently avoid this case, since renaming the identical method
+ // still causes confused method references.
+ //// Rename the private (non-abstract) or static method.
+ //targetMethod.u2nameIndex =
+ // constantPoolEditor.addUtf8Constant(newUniqueMemberName(name, descriptor));
}
if (DEBUG)
@@ -240,6 +271,12 @@ implements MemberVisitor
// Add the completed method.
classEditor.addMethod(newProgramMethod);
+
+ // Visit the newly added method, if necessary.
+ if (extraMemberVisitor != null)
+ {
+ extraMemberVisitor.visitProgramMethod(targetClass, newProgramMethod);
+ }
}