package dyvil.tools.compiler.ast.external;

import dyvil.tools.compiler.ast.annotation.IAnnotation;
import dyvil.tools.compiler.ast.classes.IClass;
import dyvil.tools.compiler.ast.context.CombiningContext;
import dyvil.tools.compiler.ast.context.IContext;
import dyvil.tools.compiler.ast.expression.IValue;
import dyvil.tools.compiler.ast.field.Field;
import dyvil.tools.compiler.ast.modifiers.ModifierSet;
import dyvil.tools.compiler.ast.structure.Package;
import dyvil.tools.compiler.ast.type.IType;
import dyvil.tools.parsing.Name;
import dyvil.tools.parsing.marker.MarkerList;

public final class ExternalField extends Field
{
	private static final int ANNOTATIONS    = 1;
	private static final int RETURN_TYPE    = 1 << 1;
	private static final int CONSTANT_VALUE = 1 << 2;

	private int    resolved;
	private Object constantValue;

	public ExternalField(IClass iclass, Name name, String desc, IType type, ModifierSet modifierSet)
	{
		super(iclass, name, type, modifierSet);
		this.descriptor = desc;
	}

	public Object getConstantValue()
	{
		return this.constantValue;
	}

	public void setConstantValue(Object constantValue)
	{
		this.constantValue = constantValue;
	}

	private IContext getCombiningContext()
	{
		return new CombiningContext(this.enclosingClass, Package.rootPackage);
	}

	private void resolveAnnotations()
	{
		this.resolved |= ANNOTATIONS;
		if (this.annotations != null)
		{
			this.annotations.resolveTypes(null, this.getCombiningContext(), this);
		}
	}

	private void resolveReturnType()
	{
		this.resolved |= RETURN_TYPE;
		this.type = this.type.resolveType(null, this.getCombiningContext());
	}

	private void resolveConstantValue()
	{
		if ((this.resolved & RETURN_TYPE) == 0)
		{
			this.resolveReturnType();
		}

		this.resolved |= CONSTANT_VALUE;

		final IValue value = IValue.fromObject(this.constantValue);
		if (value != null)
		{
			this.value = value.withType(this.type, null, null, this.getCombiningContext());
		}
	}

	@Override
	public IType getType()
	{
		if ((this.resolved & RETURN_TYPE) == 0)
		{
			this.resolveReturnType();
		}
		return this.type;
	}

	@Override
	public IAnnotation getAnnotation(IClass type)
	{
		if (this.annotations == null)
		{
			return null;
		}

		if ((this.resolved & ANNOTATIONS) == 0)
		{
			this.resolveAnnotations();
		}
		return this.annotations.getAnnotation(type);
	}

	@Override
	public IValue getValue()
	{
		if ((this.resolved & CONSTANT_VALUE) == 0)
		{
			this.resolveConstantValue();
		}
		return super.getValue();
	}

	@Override
	public void resolveTypes(MarkerList markers, IContext context)
	{
	}

	@Override
	public void resolve(MarkerList markers, IContext context)
	{
	}

	@Override
	public void checkTypes(MarkerList markers, IContext context)
	{
	}

	@Override
	public void check(MarkerList markers, IContext context)
	{
	}

	@Override
	public void foldConstants()
	{
	}
}

@@ -790,19 +790,16 @@
 int 
-   
 resolved
 ;%0A%09p
@@ -794,16 +794,33 @@
 resolved
+ = CONSTANT_VALUE
 ;%0A%09priva
@@ -1177,24 +1177,60 @@
 stantValue;%0A
+%09%09this.resolved &= ~CONSTANT_VALUE;%0A
 %09%7D%0A%0A%09private

Fix const Fields without Constant Value