Home | History | Annotate | Download | only in editor
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.classfile.editor;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.attribute.*;
     25 import proguard.classfile.attribute.visitor.AttributeVisitor;
     26 import proguard.classfile.constant.RefConstant;
     27 import proguard.classfile.constant.visitor.ConstantVisitor;
     28 import proguard.classfile.instruction.*;
     29 import proguard.classfile.instruction.visitor.InstructionVisitor;
     30 import proguard.classfile.util.SimplifiedVisitor;
     31 import proguard.classfile.visitor.MemberVisitor;
     32 
     33 /**
     34  * This MemberVisitor fixes all inappropriate bridge access flags of the
     35  * program methods that it visits, checking whether the methods to which they
     36  * bridge have the same name. Some compilers, like in Eclipse and in later
     37  * versions of JDK 1.6, complain if they can't find the method with the same
     38  * name.
     39  *
     40  * @author Eric Lafortune
     41  */
     42 public class BridgeMethodFixer
     43 extends      SimplifiedVisitor
     44 implements   MemberVisitor,
     45              AttributeVisitor,
     46              InstructionVisitor,
     47              ConstantVisitor
     48 {
     49     private static final boolean DEBUG = false;
     50 
     51 
     52     // Return values for the visitor methods.
     53     private String bridgedMethodName;
     54 
     55 
     56     // Implementations for MemberVisitor.
     57 
     58     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
     59     {
     60         if ((programMethod.getAccessFlags() & ClassConstants.ACC_BRIDGE) != 0)
     61         {
     62             programMethod.attributesAccept(programClass, this);
     63         }
     64     }
     65 
     66 
     67     // Implementations for AttributeVisitor.
     68 
     69     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
     70 
     71 
     72     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
     73     {
     74         // Go over the instructions of the bridge method.
     75         codeAttribute.instructionsAccept(clazz, method, this);
     76     }
     77 
     78 
     79     // Implementations for InstructionVisitor.
     80 
     81     public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
     82 
     83 
     84     public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
     85     {
     86         switch (constantInstruction.opcode)
     87         {
     88             case InstructionConstants.OP_INVOKEVIRTUAL:
     89             case InstructionConstants.OP_INVOKESPECIAL:
     90             case InstructionConstants.OP_INVOKESTATIC:
     91             case InstructionConstants.OP_INVOKEINTERFACE:
     92                 // Get the name of the bridged method.
     93                 clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
     94 
     95                 // Check if the name is different.
     96                 if (!method.getName(clazz).equals(bridgedMethodName))
     97                 {
     98                     if (DEBUG)
     99                     {
    100                         System.out.println("BridgeMethodFixer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] does not bridge to ["+bridgedMethodName+"]");
    101                     }
    102 
    103                     // Clear the bridge flag.
    104                     ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.ACC_BRIDGE;
    105                 }
    106                 break;
    107         }
    108     }
    109 
    110 
    111     // Implementations for ConstantVisitor.
    112 
    113     public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
    114     {
    115         bridgedMethodName = refConstant.getName(clazz);
    116     }
    117 }