blob: aa180b038798d61675e9faa1f9629998c9215683 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.consts.LinkConstant;
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class FieldExprent extends Exprent {
private String name;
private String classname;
private boolean isStatic;
private Exprent instance;
private FieldDescriptor descriptor;
{
this.type = EXPRENT_FIELD;
}
public FieldExprent(LinkConstant cn, Exprent instance) {
this.instance = instance;
if (instance == null) {
isStatic = true;
}
classname = cn.classname;
name = cn.elementname;
descriptor = FieldDescriptor.parseDescriptor(cn.descriptor);
}
public FieldExprent(String name, String classname, boolean isStatic, Exprent instance, FieldDescriptor descriptor) {
this.name = name;
this.classname = classname;
this.isStatic = isStatic;
this.instance = instance;
this.descriptor = descriptor;
}
public VarType getExprType() {
return descriptor.type;
}
public int getExprentUse() {
if (instance == null) {
return Exprent.MULTIPLE_USES;
}
else {
return instance.getExprentUse() & Exprent.MULTIPLE_USES;
}
}
public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>();
if (instance != null) {
lst.add(instance);
}
return lst;
}
public Exprent copy() {
return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor);
}
public String toJava(int indent) {
StringBuilder buf = new StringBuilder();
if (isStatic) {
ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
if (node == null || !classname.equals(node.classStruct.qualifiedName)) {
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(classname)));
buf.append(".");
}
}
else {
String super_qualifier = null;
if (instance != null && instance.type == Exprent.EXPRENT_VAR) {
VarExprent instvar = (VarExprent)instance;
VarVersionPaar varpaar = new VarVersionPaar(instvar);
MethodWrapper current_meth = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
if (current_meth != null) { // FIXME: remove
String this_classname = current_meth.varproc.getThisvars().get(varpaar);
if (this_classname != null) {
if (!classname.equals(this_classname)) { // TODO: direct comparison to the super class?
super_qualifier = this_classname;
}
}
}
}
if (super_qualifier != null) {
StructClass current_class = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)).classStruct;
if (!super_qualifier.equals(current_class.qualifiedName)) {
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(super_qualifier)));
buf.append(".");
}
buf.append("super");
}
else {
StringBuilder buff = new StringBuilder();
boolean casted = ExprProcessor.getCastedExprent(instance, new VarType(CodeConstants.TYPE_OBJECT, 0, classname), buff, indent, true);
String res = buff.toString();
if (casted || instance.getPrecedence() > getPrecedence()) {
res = "(" + res + ")";
}
buf.append(res);
}
if (buf.toString().equals(
VarExprent.VAR_NAMELESS_ENCLOSURE)) { // FIXME: workaround for field access of an anonymous enclosing class. Find a better way.
buf.setLength(0);
}
else {
buf.append(".");
}
}
buf.append(name);
return buf.toString();
}
public boolean equals(Object o) {
if (o == this) return true;
if (o == null || !(o instanceof FieldExprent)) return false;
FieldExprent ft = (FieldExprent)o;
return InterpreterUtil.equalObjects(name, ft.getName()) &&
InterpreterUtil.equalObjects(classname, ft.getClassname()) &&
isStatic == ft.isStatic() &&
InterpreterUtil.equalObjects(instance, ft.getInstance()) &&
InterpreterUtil.equalObjects(descriptor, ft.getDescriptor());
}
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == instance) {
instance = newexpr;
}
}
public String getClassname() {
return classname;
}
public FieldDescriptor getDescriptor() {
return descriptor;
}
public Exprent getInstance() {
return instance;
}
public boolean isStatic() {
return isStatic;
}
public String getName() {
return name;
}
}