Mirror of the JODE repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
jode/jode/src/net/sf/jode/decompiler/FieldAnalyzer.java

199 lines
5.3 KiB

/* FieldAnalyzer Copyright (C) 1998-2002 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package net.sf.jode.decompiler;
import net.sf.jode.type.Type;
import net.sf.jode.bytecode.FieldInfo;
import net.sf.jode.expr.Expression;
import net.sf.jode.expr.ConstOperator;
import net.sf.jode.expr.OuterLocalOperator;
import java.lang.reflect.Modifier;
import java.io.IOException;
///#def COLLECTIONS java.util
import java.util.Set;
///#enddef
public class FieldAnalyzer implements Analyzer {
ClassAnalyzer clazz;
ImportHandler imports;
int modifiers;
Type type;
String fieldName;
Expression constant;
boolean isSynthetic;
boolean isDeprecated;
boolean analyzedSynthetic = false;
public FieldAnalyzer(ClassAnalyzer cla, FieldInfo fd,
ImportHandler i)
{
clazz = cla;
imports = i;
modifiers = fd.getModifiers();
type = Type.tType(cla.getClassPath(), fd.getType());
fieldName = fd.getName();
constant = null;
this.isSynthetic = fd.isSynthetic();
this.isDeprecated = fd.isDeprecated();
if (fd.getConstant() != null) {
constant = new ConstOperator(fd.getConstant());
constant.setType(type);
constant.makeInitializer(type);
}
}
public String getName() {
return fieldName;
}
public Type getType() {
return type;
}
public ClassAnalyzer getClassAnalyzer() {
return clazz;
}
public Expression getConstant() {
return constant;
}
public boolean isSynthetic() {
return isSynthetic;
}
public boolean isFinal() {
return Modifier.isFinal(modifiers);
}
public void analyzedSynthetic() {
analyzedSynthetic = true;
}
public boolean setInitializer(Expression expr) {
if (constant != null)
return constant.equals(expr);
/* This should check for isFinal(), but sadly, sometimes jikes
* doesn't make a val$ field final. I don't know when, or why,
* so I currently ignore isFinal.
*/
if (isSynthetic
&& (fieldName.startsWith("this$")
|| fieldName.startsWith("val$"))) {
if (fieldName.startsWith("val$") && fieldName.length() > 4
&& expr instanceof OuterLocalOperator) {
LocalInfo li = ((OuterLocalOperator) expr).getLocalInfo();
li.addHint(fieldName.substring(4), type);
}
analyzedSynthetic();
} else
expr.makeInitializer(type);
constant = expr;
return true;
}
public boolean setClassConstant(String clazzName) {
if (constant != null)
return false;
if (clazzName.charAt(0) == '[') {
if (clazzName.charAt(clazzName.length()-1) == ';')
clazzName = clazzName.substring(0, clazzName.length()-1);
if (fieldName.equals("array"+ (clazzName.replace('[', '$')
.replace('.', '$')))) {
analyzedSynthetic();
return true;
}
} else {
if (fieldName.equals("class$" + clazzName.replace('.', '$'))
|| fieldName.equals("class$L" + clazzName.replace('.', '$'))) {
analyzedSynthetic();
return true;
}
}
return false;
}
public void analyze() {
imports.useType(type);
}
public void makeDeclaration(Set done) {
if (constant != null) {
constant.makeDeclaration(done);
constant = constant.simplify();
}
}
public boolean skipWriting() {
return analyzedSynthetic;
}
public void dumpSource(TabbedPrintWriter writer) throws IOException
{
if (isDeprecated) {
writer.println("/**");
writer.println(" * @deprecated");
writer.println(" */");
}
if (isSynthetic)
writer.print("/*synthetic*/ ");
int modifiedModifiers = modifiers;
/*
* JLS-1.0, section 9.3:
*
* Every field declaration in the body of an interface is
* implicitly public, static, and final. It is permitted, but
* strongly discouraged as a matter of style, to redundantly
* specify any or all of these modifiers for such fields.
*
* But I personally don't like this style..., move the
* comment mark if you think different.
if (clazz.getClazz().isInterface())
modifiedModifiers &= ~(Modifier.PUBLIC
| Modifier.STATIC
| Modifier.FINAL);
*/
writer.startOp(TabbedPrintWriter.NO_PAREN, 0);
String modif = Modifier.toString(modifiedModifiers);
if (modif.length() > 0)
writer.print(modif+" ");
writer.printType(type);
writer.print(" " + fieldName);
if (constant != null) {
writer.breakOp();
writer.print(" = ");
constant.dumpExpression(TabbedPrintWriter.IMPL_PAREN, writer);
}
writer.endOp();
writer.println(";");
}
public String toString() {
return getClass().getName()+"["+clazz.getClazz()+"."+getName()+"]";
}
}