1b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang/*
2b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *             of Java bytecode.
4b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *
5b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
6b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *
7b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This program is free software; you can redistribute it and/or modify it
8b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * under the terms of the GNU General Public License as published by the Free
9b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Software Foundation; either version 2 of the License, or (at your option)
10b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * any later version.
11b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *
12b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This program is distributed in the hope that it will be useful, but WITHOUT
13b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * more details.
16b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *
17b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * You should have received a copy of the GNU General Public License along
18b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * with this program; if not, write to the Free Software Foundation, Inc.,
19b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */
21b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
22b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangpackage proguard.shrink;
23b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
24b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.*;
25b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.attribute.*;
26b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.attribute.visitor.*;
27b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.constant.Constant;
28b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.constant.visitor.ConstantVisitor;
29b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.util.SimplifiedVisitor;
30b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.visitor.ClassVisitor;
31b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
32b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang/**
33b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This AttributeVisitor recursively marks all information that points to used
34b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * classes, in the LocalVariableTable and LocalVariableTypeTable attributes that
35b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * it visits.
36b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *
37b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @see UsageMarker
38b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang *
39b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @author Eric Lafortune
40b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */
41b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangpublic class LocalVariableTypeUsageMarker
42b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangextends      SimplifiedVisitor
43b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimplements   AttributeVisitor,
44b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             LocalVariableInfoVisitor,
45b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             LocalVariableTypeInfoVisitor,
46b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             ClassVisitor,
47b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             ConstantVisitor
48b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang{
49b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private final UsageMarker usageMarker;
50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
51b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Fields acting as a return parameters for several methods.
52b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private boolean tableUsed;
53b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private boolean variableInfoUsed;
54b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
55b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
56b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
57b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Creates a new LocalVariableTypeUsageMarker.
58b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * @param usageMarker the usage marker that is used to mark the classes
59b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     *                    and class members.
60b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
61b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public LocalVariableTypeUsageMarker(UsageMarker usageMarker)
62b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
63b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this.usageMarker = usageMarker;
64b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
65b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
66b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
67b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Implementations for AttributeVisitor.
68b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
69b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
70b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
71b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
72b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
73b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
74b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Check and mark the individual entries.
75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        tableUsed = false;
76b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
78b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Mark the table if any of the entries is marked.
79b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (tableUsed)
80b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
81b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            usageMarker.markAsUsed(localVariableTableAttribute);
82b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
83b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
84b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
85b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
86b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
87b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
88b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
89b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
90b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Check and mark the individual entries.
91b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        tableUsed = false;
92b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
93b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
94b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Mark the table if any of the entries is marked.
95b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (tableUsed)
96b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
97b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            usageMarker.markAsUsed(localVariableTypeTableAttribute);
98b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
99b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
100b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
101b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
102b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
103b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
104b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Implementations for LocalVariableInfoVisitor.
105b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
106b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
107b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
108b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Only keep the local variable info if all of its classes are used.
109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        variableInfoUsed = true;
110b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        localVariableInfo.referencedClassAccept(this);
111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (variableInfoUsed)
113b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
114b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // We got a positive used flag, so the local variable info is useful.
115b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            usageMarker.markAsUsed(localVariableInfo);
116b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
117b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            markConstant(clazz, localVariableInfo.u2nameIndex);
118b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            markConstant(clazz, localVariableInfo.u2descriptorIndex);
119b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
120b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            tableUsed = true;
121b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
122b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
123b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
124b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
125b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Implementations for LocalVariableTypeInfoVisitor.
126b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
127b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
128b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
129b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Only keep the local variable info if all of its classes are used.
130b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        variableInfoUsed = true;
131b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        localVariableTypeInfo.referencedClassesAccept(this);
132b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
133b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (variableInfoUsed)
134b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
135b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // We got a positive used flag, so the local variable info is useful.
136b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            usageMarker.markAsUsed(localVariableTypeInfo);
137b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
138b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            markConstant(clazz, localVariableTypeInfo.u2nameIndex);
139b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
140b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
141b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            tableUsed = true;
142b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
143b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
144b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
145b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
146b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Implementations for ClassVisitor.
147b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
148b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitLibraryClass(LibraryClass libraryClass) {}
149b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
150b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
151b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitProgramClass(ProgramClass programClass)
152b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
153b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Don't keep the local variable info if one of its classes is not used.
154b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        if (!usageMarker.isUsed(programClass))
155b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        {
156b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            variableInfoUsed = false;
157b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        }
158b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
159b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
160b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
161b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Implementations for ConstantVisitor.
162b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
163b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitAnyConstant(Clazz clazz, Constant constant)
164b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
165b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        usageMarker.markAsUsed(constant);
166b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
167b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
168b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
169b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    // Small utility methods.
170b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
171b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
172b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Marks the given constant pool entry of the given class.
173b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
174b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private void markConstant(Clazz clazz, int index)
175b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
176b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang         clazz.constantPoolEntryAccept(index, this);
177b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
178b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang}
179