-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class FieldDeclaration extends AbstractVariableDeclaration {
- public FieldBinding binding;
- boolean hasBeenResolved = false;
- public Javadoc javadoc;
-
- //allows to retrieve both the "type" part of the declaration (part1)
- //and also the part that decribe the name and the init and optionally
- //some other dimension ! ....
- //public int[] a, b[] = X, c ;
- //for b that would give for
- // - part1 : public int[]
- // - part2 : b[] = X,
-
- public int endPart1Position;
- public int endPart2Position;
-
- public FieldDeclaration() {
- // for subtypes or conversion
- }
-
- public FieldDeclaration(
- char[] name,
- int sourceStart,
- int sourceEnd) {
-
- this.name = name;
-
- //due to some declaration like
- // int x, y = 3, z , x ;
- //the sourceStart and the sourceEnd is ONLY on the name
- this.sourceStart = sourceStart;
- this.sourceEnd = sourceEnd;
- }
-
- public FlowInfo analyseCode(
- MethodScope initializationScope,
- FlowContext flowContext,
- FlowInfo flowInfo) {
-
- if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
- if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
- initializationScope.problemReporter().unusedPrivateField(this);
- }
- }
- // cannot define static non-constant field inside nested class
- if (this.binding != null
- && this.binding.isValidBinding()
- && this.binding.isStatic()
- && this.binding.constant == NotAConstant
- && this.binding.declaringClass.isNestedType()
- && this.binding.declaringClass.isClass()
- && !this.binding.declaringClass.isStatic()) {
- initializationScope.problemReporter().unexpectedStaticModifierForField(
- (SourceTypeBinding) this.binding.declaringClass,
- this);
- }
-
- if (this.initialization != null) {
- flowInfo =
- this.initialization
- .analyseCode(initializationScope, flowContext, flowInfo)
- .unconditionalInits();
- flowInfo.markAsDefinitelyAssigned(this.binding);
- }
- return flowInfo;
- }
-
- /**
- * Code generation for a field declaration:
- * standard assignment to a field
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- */
- public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
- if ((this.bits & IsReachableMASK) == 0) {
- return;
- }
- // do not generate initialization code if final and static (constant is then
- // recorded inside the field itself).
- int pc = codeStream.position;
- boolean isStatic;
- if (this.initialization != null
- && !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
- // non-static field, need receiver
- if (!isStatic)
- codeStream.aload_0();
- // generate initialization value
- this.initialization.generateCode(currentScope, codeStream, true);
- // store into field
- if (isStatic) {
- codeStream.putstatic(this.binding);
- } else {
- codeStream.putfield(this.binding);
- }
- }
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- }
-
- public TypeBinding getTypeBinding(Scope scope) {
-
- return this.type.getTypeBinding(scope);
- }
-
- public boolean isField() {
-
- return true;
- }
-
- public boolean isStatic() {
-
- if (this.binding != null)
- return this.binding.isStatic();
- return (this.modifiers & AccStatic) != 0;
- }
-
- public void resolve(MethodScope initializationScope) {
-
- // the two <constant = Constant.NotAConstant> could be regrouped into
- // a single line but it is clearer to have two lines while the reason of their
- // existence is not at all the same. See comment for the second one.
-
- //--------------------------------------------------------
- if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
-
- this.hasBeenResolved = true;
-
- // check if field is hiding some variable - issue is that field binding already got inserted in scope
- // thus must lookup separately in super type and outer context
- ClassScope classScope = initializationScope.enclosingClassScope();
-
- if (classScope != null) {
- SourceTypeBinding declaringType = classScope.enclosingSourceType();
- boolean checkLocal = true;
- if (declaringType.superclass != null) {
- Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this, false /*do not resolve hidden field*/);
- if (existingVariable != null && existingVariable.isValidBinding()){
- initializationScope.problemReporter().fieldHiding(this, existingVariable);
- checkLocal = false; // already found a matching field
- }
- }
- if (checkLocal) {
- Scope outerScope = classScope.parent;
- // only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
- // from outer scope. Subsequent static contexts are detected for free.
- Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
- if (existingVariable != null && existingVariable.isValidBinding()
- && (!(existingVariable instanceof FieldBinding)
- || ((FieldBinding) existingVariable).isStatic()
- || !declaringType.isStatic())) {
- initializationScope.problemReporter().fieldHiding(this, existingVariable);
- }
- }
- }
-
- this.type.resolvedType = this.binding.type; // update binding for type reference
-
- FieldBinding previousField = initializationScope.initializedField;
- int previousFieldID = initializationScope.lastVisibleFieldID;
- try {
- initializationScope.initializedField = this.binding;
- initializationScope.lastVisibleFieldID = this.binding.id;
-
- if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
- initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
- }
- // the resolution of the initialization hasn't been done
- if (this.initialization == null) {
- this.binding.constant = Constant.NotAConstant;
- } else {
- // break dead-lock cycles by forcing constant to NotAConstant
- this.binding.constant = Constant.NotAConstant;
-
- TypeBinding typeBinding = this.binding.type;
- TypeBinding initializationTypeBinding;
-
- if (this.initialization instanceof ArrayInitializer) {
-
- if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
- ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
- this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
- }
- } else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
-
- if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
- || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
-
- this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
-
- } else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
- this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
-
- } else {
- initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
- }
- if (this.binding.isFinal()){ // cast from constant actual type to variable type
- this.binding.constant =
- this.initialization.constant.castTo(
- (this.binding.type.id << 4) + this.initialization.constant.typeID());
- }
- } else {
- this.binding.constant = NotAConstant;
- }
- }
- // Resolve Javadoc comment if one is present
- if (this.javadoc != null) {
- /*
- if (classScope != null) {
- this.javadoc.resolve(classScope);
- }
- */
- this.javadoc.resolve(initializationScope);
- } else if (this.binding != null && this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
- initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
- }
- } finally {
- initializationScope.initializedField = previousField;
- initializationScope.lastVisibleFieldID = previousFieldID;
- if (this.binding.constant == null)
- this.binding.constant = Constant.NotAConstant;
- }
- }
- }
-
- public void traverse(ASTVisitor visitor, MethodScope scope) {
-
- if (visitor.visit(this, scope)) {
- this.type.traverse(visitor, scope);
- if (this.initialization != null)
- this.initialization.traverse(visitor, scope);
- }
- visitor.endVisit(this, scope);
- }
-}