blob: 442273aaac91a49dc11a59828a851715fd3b3440 [file] [log] [blame]
package org.eclipse.dltk.internal.javascript.ti;
import java.util.StringTokenizer;
import org.eclipse.dltk.internal.javascript.validation.JavaScriptValidations;
import org.eclipse.dltk.javascript.typeinference.IValueCollection;
import org.eclipse.dltk.javascript.typeinference.IValueReference;
import org.eclipse.dltk.javascript.typeinference.ReferenceKind;
import org.eclipse.dltk.javascript.typeinfo.IRClassType;
import org.eclipse.dltk.javascript.typeinfo.IRType;
import org.eclipse.dltk.javascript.typeinfo.RTypes;
import org.eclipse.dltk.javascript.typeinfo.model.Type;
public class LazyTypeReference extends AbstractReference {
final class LazyTypeValue extends Value implements ILazyValue {
boolean resolved = false;
private boolean finalResolve;
private boolean doResolve = true;
private boolean resolving;
public void resolve() {
if (!resolved && doResolve && !resolving) {
resolving = true;
doResolve();
resolving = false;
}
}
private void doResolve() {
IValueReference createChild = collection.getChild(className);
if (createChild.exists()
&& createChild.getAttribute(IReferenceAttributes.RESOLVING) == null) {
final IRType childType = JavaScriptValidations
.typeOf(createChild);
if (childType != null && childType instanceof IRClassType) {
final Type target = ((IRClassType) childType).getTarget();
if (target != null) {
setDeclaredType(RTypes.simple(context, target));
resolved = true;
return;
}
}
IValueCollection collection = (IValueCollection) createChild
.getAttribute(IReferenceAttributes.FUNCTION_SCOPE);
if (collection != null && collection.getThis() != null) {
addValue(((IValueProvider) collection.getThis()).getValue());
} else {
IValue src = ((IValueProvider) createChild).getValue();
if (src != null) {
addValue(src);
}
}
setKind(ReferenceKind.TYPE);
setDeclaredType(RTypes.localType(className, createChild));
resolved = true;
} else if (className.indexOf('.') != -1) {
StringTokenizer st = new StringTokenizer(className, ".");
IValueReference child = null;
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (child == null) {
child = collection.getChild(token);
} else {
child = child.getChild(token);
}
if (!child.exists()) {
child = null;
break;
}
}
if (child != null) {
IValue src = ((IValueProvider) child).getValue();
if (src != null) {
// this is a type so try to get the this of the
// function if this resolves to a function object.
IValueCollection collection = (IValueCollection) src
.getAttribute(
IReferenceAttributes.FUNCTION_SCOPE,
true);
if (collection != null)
addValue(((IValueProvider) collection.getThis())
.getValue());
else
addValue(src);
setDeclaredType(RTypes.localType(className, child));
}
setKind(ReferenceKind.TYPE);
resolved = true;
}
} else {
doResolve = !finalResolve;
}
}
public String getLazyName() {
return className;
}
public boolean isResolved() {
return resolved;
}
public void setFinalResolve() {
finalResolve = true;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof LazyTypeValue)
return ((LazyTypeValue) obj).getLazyName().equals(className);
return super.equals(obj);
}
@Override
public int hashCode() {
return className.hashCode();
}
}
private final LazyTypeValue value = new LazyTypeValue();
final ITypeInferenceContext context;
final String className;
final IValueCollection collection;
public LazyTypeReference(ITypeInferenceContext context, String className,
IValueCollection collection) {
this.context = context;
this.className = className;
this.collection = collection;
}
@Override
public IValueReference getChild(String name) {
if (name.equals(IValueReference.FUNCTION_OP))
return this;
return super.getChild(name);
}
public IValueReference getParent() {
return null;
}
public String getName() {
return className;
}
public void delete(boolean force) {
}
public boolean isReference() {
return true;
}
@Override
public IValue getValue() {
value.resolve();
return value;
}
@Override
public boolean exists() {
value.resolve();
return value.isResolved();
}
@Override
public IValue createValue() {
return getValue();
}
}