| /* |
| * 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; |
| |
| /** |
| * Java field reference expression. |
| */ |
| public class JFieldRef extends JVariableRef implements HasEnclosingType { |
| |
| /** |
| * The enclosing type of this reference. |
| */ |
| private final JDeclaredType enclosingType; |
| |
| /** |
| * This can only be null if the referenced field is static. |
| */ |
| private JExpression instance; |
| |
| /** |
| * An overridden type for this reference. Normally the type of a field |
| * reference is the same as the type of the field itself. That default can be |
| * overridden by setting this field. |
| */ |
| private final JType overriddenType; |
| |
| public JFieldRef(SourceInfo info, JExpression instance, JField field, JDeclaredType enclosingType) { |
| this(info, instance, field, enclosingType, null); |
| } |
| |
| public JFieldRef(SourceInfo info, JExpression instance, JField field, |
| JDeclaredType enclosingType, JType overriddenType) { |
| super(info, field); |
| assert (instance != null || field.isStatic()); |
| assert (enclosingType != null); |
| this.instance = instance; |
| this.enclosingType = enclosingType; |
| this.overriddenType = overriddenType; |
| } |
| |
| @Override |
| public JDeclaredType getEnclosingType() { |
| return enclosingType; |
| } |
| |
| public JField getField() { |
| return (JField) getTarget(); |
| } |
| |
| public JExpression getInstance() { |
| return instance; |
| } |
| |
| @Override |
| public JType getType() { |
| if (overriddenType != null) { |
| return overriddenType; |
| } |
| return super.getType(); |
| } |
| |
| public boolean hasClinit() { |
| JField field = getField(); |
| // A cross-class reference to a static, non constant field forces clinit |
| if (!field.isStatic()) { |
| return false; |
| } |
| if (field.isFinal() && field.isCompileTimeConstant()) { |
| return false; |
| } |
| return getEnclosingType().checkClinitTo(field.getEnclosingType()); |
| } |
| |
| @Override |
| public boolean hasSideEffects() { |
| if (hasClinit()) { |
| return true; |
| } |
| JExpression expr = instance; |
| if (expr == null) { |
| return false; |
| } |
| return expr.hasSideEffects(); |
| } |
| |
| /** |
| * Resolve an external reference during AST stitching. |
| */ |
| public void resolve(JField newField) { |
| assert newField.replaces(getField()); |
| target = newField; |
| } |
| |
| @Override |
| public void traverse(JVisitor visitor, Context ctx) { |
| if (visitor.visit(this, ctx)) { |
| if (instance != null) { |
| instance = visitor.accept(instance); |
| } |
| } |
| visitor.endVisit(this, ctx); |
| } |
| } |