blob: f8307bc785ef8de5b397c5a73f7a9c8f6a357e75 [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* 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 com.google.gwt.dev.jjs.ast;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import java.io.Serializable;
/**
* Java field definition.
*/
public class JField extends JVariable implements CanBeStatic, HasEnclosingType {
/**
* Determines whether the variable is final, volatile, or neither.
*/
public static enum Disposition {
COMPILE_TIME_CONSTANT, FINAL, NONE, THIS_REF, VOLATILE;
public boolean isFinal() {
return this == COMPILE_TIME_CONSTANT || this == FINAL || this == THIS_REF;
}
public boolean isThisRef() {
return this == THIS_REF;
}
private boolean isCompileTimeConstant() {
return this == COMPILE_TIME_CONSTANT;
}
private boolean isVolatile() {
return this == VOLATILE;
}
}
private static class ExternalSerializedForm implements Serializable {
private final JDeclaredType enclosingType;
private final String signature;
public ExternalSerializedForm(JField field) {
enclosingType = field.getEnclosingType();
signature = field.getSignature();
}
private Object readResolve() {
String name = signature.substring(0, signature.indexOf(':'));
JField result =
new JField(SourceOrigin.UNKNOWN, name, enclosingType, JNullType.INSTANCE, false,
Disposition.NONE);
result.signature = signature;
return result;
}
}
private static class ExternalSerializedNullField implements Serializable {
public static final ExternalSerializedNullField INSTANCE = new ExternalSerializedNullField();
private Object readResolve() {
return NULL_FIELD;
}
}
public static final JField NULL_FIELD = new JField(SourceOrigin.UNKNOWN, "nullField", null,
JNullType.INSTANCE, false, Disposition.FINAL);
private final JDeclaredType enclosingType;
private final boolean isCompileTimeConstant;
private final boolean isStatic;
private final boolean isThisRef;
private boolean isVolatile;
private transient String signature;
public JField(SourceInfo info, String name, JDeclaredType enclosingType, JType type,
boolean isStatic, Disposition disposition) {
super(info, name, type, disposition.isFinal());
this.enclosingType = enclosingType;
this.isStatic = isStatic;
this.isCompileTimeConstant = disposition.isCompileTimeConstant();
this.isVolatile = disposition.isVolatile();
this.isThisRef = disposition.isThisRef();
// Disposition is not cached because we can be set final later.
}
public JDeclaredType getEnclosingType() {
return enclosingType;
}
public JValueLiteral getLiteralInitializer() {
JExpression initializer = getInitializer();
if (initializer instanceof JValueLiteral) {
return (JValueLiteral) initializer;
}
return null;
}
public String getSignature() {
if (signature == null) {
StringBuilder sb = new StringBuilder();
sb.append(getName());
sb.append(':');
sb.append(getType().getJsniSignatureName());
signature = sb.toString();
}
return signature;
}
public boolean isCompileTimeConstant() {
return isCompileTimeConstant;
}
public boolean isExternal() {
return getEnclosingType() != null && getEnclosingType().isExternal();
}
public boolean isStatic() {
return isStatic;
}
public boolean isThisRef() {
return isThisRef;
}
public boolean isVolatile() {
return isVolatile;
}
@Override
public void setFinal() {
if (isVolatile()) {
throw new IllegalStateException("Volatile fields cannot be set final");
}
super.setFinal();
}
public void setInitializer(JDeclarationStatement declStmt) {
this.declStmt = declStmt;
}
public void setVolatile() {
if (isFinal()) {
throw new IllegalStateException("Final fields cannot be set volatile");
}
isVolatile = true;
}
public void traverse(JVisitor visitor, Context ctx) {
if (visitor.visit(this, ctx)) {
// Do not visit declStmt, it gets visited within its own code block.
}
visitor.endVisit(this, ctx);
}
protected Object writeReplace() {
if (isExternal()) {
return new ExternalSerializedForm(this);
} else if (this == NULL_FIELD) {
return ExternalSerializedNullField.INSTANCE;
} else {
return this;
}
}
boolean replaces(JField originalField) {
if (this == originalField) {
return true;
}
return originalField.isExternal() && originalField.getSignature().equals(this.getSignature())
&& this.getEnclosingType().replaces(originalField.getEnclosingType());
}
}