Skip to content

Commit

Permalink
Create 'Iterable' built-in type.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188253818
  • Loading branch information
tbreisacher authored and lauraharker committed Mar 9, 2018
1 parent b13f1a3 commit 900e214
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 39 deletions.
29 changes: 23 additions & 6 deletions src/com/google/javascript/jscomp/FunctionTypeBuilder.java
Expand Up @@ -725,12 +725,7 @@ FunctionType buildAndRegister() {
if (isConstructor) { if (isConstructor) {
fnType = getOrCreateConstructor(); fnType = getOrCreateConstructor();
} else if (isInterface) { } else if (isInterface) {
fnType = typeRegistry.createInterfaceType( fnType = getOrCreateInterface();
fnName, contents.getSourceNode(), classTemplateTypeNames, makesStructs);
if (getScopeDeclaredIn().isGlobal() && !fnName.isEmpty()) {
typeRegistry.declareType(fnName, fnType.getInstanceType());
}
maybeSetBaseType(fnType);
} else { } else {
fnType = fnType =
new FunctionBuilder(typeRegistry) new FunctionBuilder(typeRegistry)
Expand Down Expand Up @@ -827,6 +822,28 @@ private FunctionType getOrCreateConstructor() {
return fnType; return fnType;
} }


private FunctionType getOrCreateInterface() {
FunctionType fnType = null;

JSType type = typeRegistry.getType(fnName);
if (type != null && type.isInstanceType()) {
FunctionType ctor = type.toMaybeObjectType().getConstructor();
if (ctor.isInterface()) {
fnType = ctor;
fnType.setSource(contents.getSourceNode());
}
}

if (fnType == null) {
fnType = typeRegistry.createInterfaceType(
fnName, contents.getSourceNode(), classTemplateTypeNames, makesStructs);
if (getScopeDeclaredIn().isGlobal() && !fnName.isEmpty()) {
typeRegistry.declareType(fnName, fnType.getInstanceType());
}
maybeSetBaseType(fnType);
}
return fnType;
}
private void reportWarning(DiagnosticType warning, String ... args) { private void reportWarning(DiagnosticType warning, String ... args) {
compiler.report(JSError.make(errorRoot, warning, args)); compiler.report(JSError.make(errorRoot, warning, args));
} }
Expand Down
2 changes: 2 additions & 0 deletions src/com/google/javascript/jscomp/TypedScopeCreator.java
Expand Up @@ -29,6 +29,7 @@
import static com.google.javascript.rhino.jstype.JSTypeNative.EVAL_ERROR_FUNCTION_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.EVAL_ERROR_FUNCTION_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.FUNCTION_FUNCTION_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.FUNCTION_FUNCTION_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.GLOBAL_THIS; import static com.google.javascript.rhino.jstype.JSTypeNative.GLOBAL_THIS;
import static com.google.javascript.rhino.jstype.JSTypeNative.ITERABLE_FUNCTION_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NO_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.NO_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NULL_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.NULL_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NUMBER_OBJECT_FUNCTION_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.NUMBER_OBJECT_FUNCTION_TYPE;
Expand Down Expand Up @@ -402,6 +403,7 @@ TypedScope createInitialScope(Node root) {
declareNativeFunctionType(s, ERROR_FUNCTION_TYPE); declareNativeFunctionType(s, ERROR_FUNCTION_TYPE);
declareNativeFunctionType(s, EVAL_ERROR_FUNCTION_TYPE); declareNativeFunctionType(s, EVAL_ERROR_FUNCTION_TYPE);
declareNativeFunctionType(s, FUNCTION_FUNCTION_TYPE); declareNativeFunctionType(s, FUNCTION_FUNCTION_TYPE);
declareNativeFunctionType(s, ITERABLE_FUNCTION_TYPE);
declareNativeFunctionType(s, NUMBER_OBJECT_FUNCTION_TYPE); declareNativeFunctionType(s, NUMBER_OBJECT_FUNCTION_TYPE);
declareNativeFunctionType(s, OBJECT_FUNCTION_TYPE); declareNativeFunctionType(s, OBJECT_FUNCTION_TYPE);
declareNativeFunctionType(s, RANGE_ERROR_FUNCTION_TYPE); declareNativeFunctionType(s, RANGE_ERROR_FUNCTION_TYPE);
Expand Down
78 changes: 46 additions & 32 deletions src/com/google/javascript/rhino/jstype/FunctionType.java
Expand Up @@ -77,7 +77,7 @@
public class FunctionType extends PrototypeObjectType implements FunctionTypeI { public class FunctionType extends PrototypeObjectType implements FunctionTypeI {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;


private enum Kind { enum Kind {
ORDINARY, ORDINARY,
CONSTRUCTOR, CONSTRUCTOR,
INTERFACE INTERFACE
Expand Down Expand Up @@ -154,6 +154,7 @@ private enum PropAccess { ANY, STRUCT, DICT }
private List<FunctionTypeI> subTypes; private List<FunctionTypeI> subTypes;


/** Creates an instance for a function that might be a constructor. */ /** Creates an instance for a function that might be a constructor. */
@Deprecated
FunctionType( FunctionType(
JSTypeRegistry registry, JSTypeRegistry registry,
String name, String name,
Expand All @@ -164,6 +165,29 @@ private enum PropAccess { ANY, STRUCT, DICT }
boolean isConstructor, boolean isConstructor,
boolean nativeType, boolean nativeType,
boolean isAbstract) { boolean isAbstract) {
this(
registry,
name,
source,
arrowType,
typeOfThis,
templateTypeMap,
isConstructor ? Kind.CONSTRUCTOR : Kind.ORDINARY,
nativeType,
isAbstract);
}

/** Creates an instance for a function that might be a constructor. */
FunctionType(
JSTypeRegistry registry,
String name,
Node source,
ArrowType arrowType,
JSType typeOfThis,
TemplateTypeMap templateTypeMap,
Kind kind,
boolean nativeType,
boolean isAbstract) {
super(registry, name, super(registry, name,
registry.getNativeObjectType(JSTypeNative.FUNCTION_INSTANCE_TYPE), registry.getNativeObjectType(JSTypeNative.FUNCTION_INSTANCE_TYPE),
nativeType, templateTypeMap); nativeType, templateTypeMap);
Expand All @@ -172,45 +196,35 @@ private enum PropAccess { ANY, STRUCT, DICT }
checkArgument(source == null || Token.FUNCTION == source.getToken()); checkArgument(source == null || Token.FUNCTION == source.getToken());
checkNotNull(arrowType); checkNotNull(arrowType);
this.source = source; this.source = source;
if (isConstructor) { this.kind = kind;
this.kind = Kind.CONSTRUCTOR; switch (kind) {
this.propAccess = PropAccess.ANY; case CONSTRUCTOR:
this.typeOfThis = typeOfThis != null ? this.propAccess = PropAccess.ANY;
typeOfThis : new InstanceObjectType(registry, this, nativeType); this.typeOfThis =
} else { typeOfThis != null ? typeOfThis : new InstanceObjectType(registry, this, nativeType);
this.kind = Kind.ORDINARY; break;
this.typeOfThis = typeOfThis != null ? case ORDINARY:
typeOfThis : this.typeOfThis =
registry.getNativeObjectType(JSTypeNative.UNKNOWN_TYPE); typeOfThis != null
? typeOfThis
: registry.getNativeObjectType(JSTypeNative.UNKNOWN_TYPE);
break;
case INTERFACE:
this.typeOfThis =
typeOfThis != null ? typeOfThis : new InstanceObjectType(registry, this, nativeType);
break;
} }
this.call = arrowType; this.call = arrowType;
this.isStructuralInterface = false; this.isStructuralInterface = false;
this.isAbstract = isAbstract; this.isAbstract = isAbstract;
} }


/** Creates an instance for a function that is an interface. */
private FunctionType(JSTypeRegistry registry, String name, Node source,
TemplateTypeMap typeParameters) {
super(registry, name,
registry.getNativeObjectType(JSTypeNative.FUNCTION_INSTANCE_TYPE),
false, typeParameters);
setPrettyPrint(true);

checkArgument(source == null || Token.FUNCTION == source.getToken());
checkArgument(name != null);
this.source = source;
this.call = new ArrowType(registry, new Node(Token.PARAM_LIST), null);
this.kind = Kind.INTERFACE;
this.typeOfThis = new InstanceObjectType(registry, this);
this.isStructuralInterface = false;
this.isAbstract = false;
}

/** Creates an instance for a function that is an interface. */ /** Creates an instance for a function that is an interface. */
static FunctionType forInterface( static FunctionType forInterface(
JSTypeRegistry registry, String name, Node source, JSTypeRegistry registry, String name, Node source, TemplateTypeMap typeParameters) {
TemplateTypeMap typeParameters) { ArrowType arrowType = new ArrowType(registry, new Node(Token.PARAM_LIST), null);
return new FunctionType(registry, name, source, typeParameters); return new FunctionType(
registry, name, source, arrowType, null, typeParameters, Kind.INTERFACE, false, false);
} }


@Override @Override
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/rhino/jstype/JSTypeNative.java
Expand Up @@ -98,6 +98,7 @@ public enum JSTypeNative {
GENERATOR_TYPE, GENERATOR_TYPE,


I_ITERABLE_RESULT_TYPE, I_ITERABLE_RESULT_TYPE,
ITERABLE_FUNCTION_TYPE,
ITERABLE_TYPE, ITERABLE_TYPE,
ITERATOR_TYPE, ITERATOR_TYPE,


Expand Down
27 changes: 27 additions & 0 deletions src/com/google/javascript/rhino/jstype/JSTypeRegistry.java
Expand Up @@ -68,6 +68,7 @@
import com.google.javascript.rhino.TypeI; import com.google.javascript.rhino.TypeI;
import com.google.javascript.rhino.TypeIEnv; import com.google.javascript.rhino.TypeIEnv;
import com.google.javascript.rhino.TypeIRegistry; import com.google.javascript.rhino.TypeIRegistry;
import com.google.javascript.rhino.jstype.FunctionType.Kind;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
Expand Down Expand Up @@ -104,6 +105,9 @@ public class JSTypeRegistry implements TypeIRegistry {
private TemplateType iObjectElementTemplateKey; private TemplateType iObjectElementTemplateKey;
private static final String I_OBJECT_ELEMENT_TEMPLATE = "IObject#VALUE"; private static final String I_OBJECT_ELEMENT_TEMPLATE = "IObject#VALUE";


/** The template variable corresponding to the VALUE type in {@code Iterable<VALUE>} */
private TemplateType iterableTemplate;

/** /**
* The template variable in {@code Array<T>} * The template variable in {@code Array<T>}
*/ */
Expand Down Expand Up @@ -268,6 +272,8 @@ public ImmutableList<TemplateType> getTemplateTypesOfBuiltin(String fnName) {
return ImmutableList.of(iObjectIndexTemplateKey, iObjectElementTemplateKey); return ImmutableList.of(iObjectIndexTemplateKey, iObjectElementTemplateKey);
case "Array": case "Array":
return ImmutableList.of(arrayElementTemplateKey); return ImmutableList.of(arrayElementTemplateKey);
case "Iterable":
return ImmutableList.of(iterableTemplate);
default: default:
return null; return null;
} }
Expand Down Expand Up @@ -321,6 +327,7 @@ private void initializeBuiltInTypes() {
iObjectIndexTemplateKey = new TemplateType(this, "IObject#KEY1"); iObjectIndexTemplateKey = new TemplateType(this, "IObject#KEY1");
iObjectElementTemplateKey = new TemplateType(this, I_OBJECT_ELEMENT_TEMPLATE); iObjectElementTemplateKey = new TemplateType(this, I_OBJECT_ELEMENT_TEMPLATE);
arrayElementTemplateKey = new TemplateType(this, "T"); arrayElementTemplateKey = new TemplateType(this, "T");
iterableTemplate = new TemplateType(this, "VALUE");


// Top Level Prototype (the One) // Top Level Prototype (the One)
// The initializations of TOP_LEVEL_PROTOTYPE and OBJECT_FUNCTION_TYPE // The initializations of TOP_LEVEL_PROTOTYPE and OBJECT_FUNCTION_TYPE
Expand Down Expand Up @@ -408,6 +415,20 @@ private void initializeBuiltInTypes() {
ObjectType ARRAY_TYPE = ARRAY_FUNCTION_TYPE.getInstanceType(); ObjectType ARRAY_TYPE = ARRAY_FUNCTION_TYPE.getInstanceType();
registerNativeType(JSTypeNative.ARRAY_TYPE, ARRAY_TYPE); registerNativeType(JSTypeNative.ARRAY_TYPE, ARRAY_TYPE);


FunctionType iterableFunctionType =
new FunctionType(
this,
"Iterable",
null,
createArrowType(),
null,
createTemplateTypeMap(ImmutableList.of(iterableTemplate), null),
Kind.INTERFACE,
true,
false);
registerNativeType(JSTypeNative.ITERABLE_FUNCTION_TYPE, iterableFunctionType);
registerNativeType(JSTypeNative.ITERABLE_TYPE, iterableFunctionType.getInstanceType());

// Boolean // Boolean
FunctionType BOOLEAN_OBJECT_FUNCTION_TYPE = FunctionType BOOLEAN_OBJECT_FUNCTION_TYPE =
new FunctionType( new FunctionType(
Expand Down Expand Up @@ -759,6 +780,7 @@ private void initializeRegistry() {
register(getNativeType(JSTypeNative.ARRAY_TYPE)); register(getNativeType(JSTypeNative.ARRAY_TYPE));
register(getNativeType(JSTypeNative.BOOLEAN_OBJECT_TYPE)); register(getNativeType(JSTypeNative.BOOLEAN_OBJECT_TYPE));
register(getNativeType(JSTypeNative.BOOLEAN_TYPE)); register(getNativeType(JSTypeNative.BOOLEAN_TYPE));
register(getNativeType(JSTypeNative.ITERABLE_TYPE));
register(getNativeType(JSTypeNative.DATE_TYPE)); register(getNativeType(JSTypeNative.DATE_TYPE));
register(getNativeType(JSTypeNative.NULL_TYPE)); register(getNativeType(JSTypeNative.NULL_TYPE));
register(getNativeType(JSTypeNative.NULL_TYPE), "Null"); register(getNativeType(JSTypeNative.NULL_TYPE), "Null");
Expand Down Expand Up @@ -1510,6 +1532,11 @@ ArrowType createArrowType(Node parametersNode) {
return new ArrowType(this, parametersNode, null); return new ArrowType(this, parametersNode, null);
} }


/** Creates an arrow type with no parameters and an unknown return type. */
ArrowType createArrowType() {
return new ArrowType(this, new Node(Token.PARAM_LIST), null);
}

/** /**
* Creates a function type. * Creates a function type.
* *
Expand Down
Expand Up @@ -42,6 +42,7 @@
import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_OBJECT_FUNCTION_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_OBJECT_FUNCTION_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_OBJECT_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_OBJECT_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.ITERABLE_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NULL_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.NULL_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NULL_VOID; import static com.google.javascript.rhino.jstype.JSTypeNative.NULL_VOID;
import static com.google.javascript.rhino.jstype.JSTypeNative.NUMBER_TYPE; import static com.google.javascript.rhino.jstype.JSTypeNative.NUMBER_TYPE;
Expand All @@ -60,11 +61,16 @@
public class JSTypeRegistryTest extends TestCase { public class JSTypeRegistryTest extends TestCase {
// TODO(user): extend this class with more tests, as JSTypeRegistry is // TODO(user): extend this class with more tests, as JSTypeRegistry is
// now much larger // now much larger
public void testGetBuiltInType() { public void testGetBuiltInType_boolean() {
JSTypeRegistry typeRegistry = new JSTypeRegistry(null); JSTypeRegistry typeRegistry = new JSTypeRegistry(null);
assertTypeEquals(typeRegistry.getNativeType(BOOLEAN_TYPE), typeRegistry.getType("boolean")); assertTypeEquals(typeRegistry.getNativeType(BOOLEAN_TYPE), typeRegistry.getType("boolean"));
} }


public void testGetBuiltInType_iterable() {
JSTypeRegistry typeRegistry = new JSTypeRegistry(null);
assertTypeEquals(typeRegistry.getNativeType(ITERABLE_TYPE), typeRegistry.getType("Iterable"));
}

public void testGetDeclaredType() { public void testGetDeclaredType() {
JSTypeRegistry typeRegistry = new JSTypeRegistry(null); JSTypeRegistry typeRegistry = new JSTypeRegistry(null);
JSType type = typeRegistry.createAnonymousObjectType(null); JSType type = typeRegistry.createAnonymousObjectType(null);
Expand Down

0 comments on commit 900e214

Please sign in to comment.