| /* |
| * 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()); |
| } |
| } |