com.google.javascript.rhino.jstype.ObjectType Maven / Gradle / Ivy
Show all versions of closure-compiler-unshaded Show documentation
/*
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Rhino code, released
* May 6, 1999.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1997-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bob Jervis
* Google Inc.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which
* case the provisions of the GPL are applicable instead of those above. If
* you wish to allow use of your version of this file only under the terms of
* the GPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replacing
* them with the notice and other provisions required by the GPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*
* ***** END LICENSE BLOCK ***** */
package com.google.javascript.rhino.jstype;
import static com.google.javascript.rhino.jstype.ObjectType.PropertyOptionality.VOIDABLE_PROPS_ARE_OPTIONAL;
import static com.google.javascript.rhino.jstype.TernaryValue.FALSE;
import static com.google.javascript.rhino.jstype.TernaryValue.UNKNOWN;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.jstype.Property.OwnedProperty;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.Nullable;
/**
* Object type.
*
* In JavaScript, all object types have properties, and each of those
* properties has a type. Property types may be DECLARED, INFERRED, or
* UNKNOWN.
*
* DECLARED properties have an explicit type annotation, as in:
*
* /xx @type {number} x/
* Foo.prototype.bar = 1;
*
* This property may only hold number values, and an assignment to any
* other type of value is an error.
*
* INFERRED properties do not have an explicit type annotation. Rather,
* we try to find all the possible types that this property can hold.
*
* Foo.prototype.bar = 1;
*
* If the programmer assigns other types of values to this property,
* the property will take on the union of all these types.
*
* UNKNOWN properties are properties on the UNKNOWN type. The UNKNOWN
* type has all properties, but we do not know whether they are
* declared or inferred.
*
*/
public abstract class ObjectType extends JSType implements Serializable {
private boolean visited;
private JSDocInfo docInfo = null;
private boolean unknown = true;
ObjectType(JSTypeRegistry registry) {
super(registry);
}
ObjectType(JSTypeRegistry registry, TemplateTypeMap templateTypeMap) {
super(registry, templateTypeMap);
}
/**
* Returns the property map that manages the set of properties for an object.
*/
PropertyMap getPropertyMap() {
return PropertyMap.immutableEmptyMap();
}
/**
* Default getSlot implementation. This gets overridden by FunctionType
* for lazily-resolved prototypes.
*/
public Property getSlot(String name) {
OwnedProperty property = getPropertyMap().findClosest(name);
return property == null ? null : property.getValue();
}
public final Property getOwnSlot(String name) {
return getPropertyMap().getOwnProperty(name);
}
public JSType getTypeOfThis() {
return null;
}
/**
* Gets the declared default element type.
*
* @see TemplatizedType
*/
public ImmutableList getTemplateTypes() {
return null;
}
/**
* Gets the docInfo for this type.
*/
@Override
public JSDocInfo getJSDocInfo() {
return docInfo;
}
/**
* Sets the docInfo for this type from the given
* {@link JSDocInfo}. The {@code JSDocInfo} may be {@code null}.
*/
public void setJSDocInfo(JSDocInfo info) {
docInfo = info;
}
/**
* Detects a cycle in the implicit prototype chain. This method accesses
* the {@link #getImplicitPrototype()} method and must therefore be
* invoked only after the object is sufficiently initialized to respond to
* calls to this method.
*
* @return True iff an implicit prototype cycle was detected.
*/
final boolean detectImplicitPrototypeCycle() {
// detecting cycle
this.visited = true;
ObjectType p = getImplicitPrototype();
while (p != null) {
if (p.visited) {
return true;
} else {
p.visited = true;
}
p = p.getImplicitPrototype();
}
// clean up
p = this;
do {
p.visited = false;
p = p.getImplicitPrototype();
} while (p != null);
return false;
}
/**
* Detects cycles in either the implicit prototype chain, or the implemented/extended
* interfaces.
*
* @return True iff a cycle was detected.
*/
final boolean detectInheritanceCycle() {
if (detectImplicitPrototypeCycle()
|| Iterables.contains(this.getCtorImplementedInterfaces(), this)) {
return true;
}
FunctionType fnType = this.getConstructor();
return fnType != null && fnType.checkExtendsLoop() != null;
}
/**
* Gets the reference name for this object. This includes named types like constructors,
* prototypes, and enums. It notably does not include literal types like strings and booleans and
* structural types.
*
*
Returning an empty string means something different than returning null. An empty string may
* indicate an anonymous constructor, which we treat differently than a literal type without a
* reference name. e.g. in {@link InstanceObjectType#appendTo(StringBuilder, boolean)}
*
* @return the object's name or {@code null} if this is an anonymous object
*/
@Nullable
public abstract String getReferenceName();
/**
* INVARIANT: {@code hasReferenceName()} is true if and only if {@code getReferenceName()} returns
* a non-null string.
*
* @return true if the object is named, false if it is anonymous
*/
public final boolean hasReferenceName() {
return getReferenceName() != null;
}
/**
* Due to the complexity of some of our internal type systems, sometimes
* we have different types constructed by the same constructor.
* In other parts of the type system, these are called delegates.
* We construct these types by appending suffixes to the constructor name.
*
* The normalized reference name does not have these suffixes, and as such,
* recollapses these implicit types back to their real type. Note that
* suffixes such as ".prototype" can be added after the delegate
* suffix, so anything after the parentheses must still be retained.
*/
@Nullable
public final String getNormalizedReferenceName() {
String name = getReferenceName();
if (name != null) {
int start = name.indexOf('(');
if (start != -1) {
int end = name.lastIndexOf(')');
String prefix = name.substring(0, start);
return end + 1 % name.length() == 0 ? prefix : prefix + name.substring(end + 1);
}
}
return name;
}
@Override
public String getDisplayName() {
return getNormalizedReferenceName();
}
/**
* Creates a suffix for a proxy delegate.
* @see #getNormalizedReferenceName
*/
public static String createDelegateSuffix(String suffix) {
return "(" + suffix + ")";
}
public boolean isAmbiguousObject() {
return !hasReferenceName();
}
public final ObjectType getRawType() {
TemplatizedType t = toMaybeTemplatizedType();
return t == null ? this : t.getReferencedType();
}
@Override
public TernaryValue testForEquality(JSType that) {
// super
TernaryValue result = super.testForEquality(that);
if (result != null) {
return result;
}
// TODO: consider tighten "testForEquality" for subtypes of Object: if Foo and Bar
// are not related we don't want to allow "==" on them (similiarly we should disallow
// number == for non-number context values, etc).
if (that.isUnknownType()
|| that.isSubtypeOf(getNativeType(JSTypeNative.OBJECT_TYPE))
|| that.isSubtypeOf(getNativeType(JSTypeNative.NUMBER_TYPE))
|| that.isSubtypeOf(getNativeType(JSTypeNative.STRING_TYPE))
|| that.isSubtypeOf(getNativeType(JSTypeNative.BOOLEAN_TYPE))
|| that.isSubtypeOf(getNativeType(JSTypeNative.SYMBOL_TYPE))) {
return UNKNOWN;
}
return FALSE;
}
/**
* Gets this object's constructor.
* @return this object's constructor or {@code null} if it is a native
* object (constructed natively v.s. by instantiation of a function)
*/
public abstract FunctionType getConstructor();
public FunctionType getSuperClassConstructor() {
ObjectType iproto = getImplicitPrototype();
if (iproto == null) {
return null;
}
iproto = iproto.getImplicitPrototype();
return iproto == null ? null : iproto.getConstructor();
}
/**
* Returns the top most type that defines the property.
*
*
Note: if you are doing type validation, you are probably looking for the closest definition
* of the property which could be resolved by {@link #getClosestDefiningType}.
*/
public final ObjectType getTopMostDefiningType(String propertyName) {
OwnedProperty property = getPropertyMap().findTopMost(propertyName);
return property == null ? null : property.getOwner();
}
/** Returns the closest ancestor that defines the property including this type itself. */
public final ObjectType getClosestDefiningType(String propertyName) {
OwnedProperty property = getPropertyMap().findClosest(propertyName);
return property == null ? null : property.getOwner();
}
/** Returns the closest definition of the property including this type itself. */
public final OwnedProperty findClosestDefinition(String propertyName) {
return getPropertyMap().findClosest(propertyName);
}
/**
* Gets the implicit prototype (a.k.a. the {@code [[Prototype]]} property).
*/
public abstract ObjectType getImplicitPrototype();
/**
* Returns a lazy, dynamic {@link Iterable} for the types forming the implicit prototype chain of
* this type.
*
*
The chain is iterated bottom to top; from the nearest ancestor to the most distant.
* Iteration stops when the next ancestor would be a {@code null} reference.
*
*
The created {@link Iterator}s will not reflect changes to the prototype chain of elements it
* has already iterated past, but will reflect those of upcoming elements. Neither the {@link
* Iterable} nor its {@link Iterator} support mutation.
*/
public final Iterable getImplicitPrototypeChain() {
final ObjectType self = this;
return () ->
new AbstractIterator() {
private ObjectType next = self; // We increment past this type before first access.
@Override
public ObjectType computeNext() {
next = next.getImplicitPrototype();
return (next != null) ? next : endOfData();
}
};
}
/**
* Defines a property whose type is explicitly declared by the programmer.
* @param propertyName the property's name
* @param type the type
* @param propertyNode the node corresponding to the declaration of property
* which might later be accessed using {@code getPropertyNode}.
*/
public final boolean defineDeclaredProperty(String propertyName,
JSType type, Node propertyNode) {
boolean result = defineProperty(propertyName, type, false, propertyNode);
// All property definitions go through this method
// or defineInferredProperty. Because the properties defined an an
// object can affect subtyping, it's slightly more efficient
// to register this after defining the property.
registry.registerPropertyOnType(propertyName, this);
return result;
}
/**
* Defines a property whose type is on a synthesized object. These objects
* don't actually exist in the user's program. They're just used for
* bookkeeping in the type system.
*/
public final boolean defineSynthesizedProperty(String propertyName,
JSType type, Node propertyNode) {
return defineProperty(propertyName, type, false, propertyNode);
}
/**
* Defines a property whose type is inferred.
* @param propertyName the property's name
* @param type the type
* @param propertyNode the node corresponding to the inferred definition of
* property that might later be accessed using {@code getPropertyNode}.
*/
public final boolean defineInferredProperty(String propertyName,
JSType type, Node propertyNode) {
if (hasProperty(propertyName)) {
if (isPropertyTypeDeclared(propertyName)) {
// We never want to hide a declared property with an inferred property.
return true;
}
JSType originalType = getPropertyType(propertyName);
type = originalType == null ? type : originalType.getLeastSupertype(type);
}
boolean result = defineProperty(propertyName, type, true,
propertyNode);
// All property definitions go through this method
// or defineDeclaredProperty. Because the properties defined an an
// object can affect subtyping, it's slightly more efficient
// to register this after defining the property.
registry.registerPropertyOnType(propertyName, this);
return result;
}
/**
* Defines a property.
*
* For clarity, callers should prefer {@link #defineDeclaredProperty} and
* {@link #defineInferredProperty}.
*
* @param propertyName the property's name
* @param type the type
* @param inferred {@code true} if this property's type is inferred
* @param propertyNode the node that represents the definition of property.
* Depending on the actual sub-type the node type might be different.
* The general idea is to have an estimate of where in the source code
* this property is defined.
* @return True if the property was registered successfully, false if this
* conflicts with a previous property type declaration.
*/
abstract boolean defineProperty(String propertyName, JSType type,
boolean inferred, Node propertyNode);
/**
* Removes the declared or inferred property from this ObjectType.
*
* @param propertyName the property's name
* @return true if the property was removed successfully. False if the
* property did not exist, or could not be removed.
*/
public boolean removeProperty(String propertyName) {
return false;
}
/**
* Gets the node corresponding to the definition of the specified property.
* This could be the node corresponding to declaration of the property or the
* node corresponding to the first reference to this property, e.g.,
* "this.propertyName" in a constructor. Note this is mainly intended to be
* an estimate of where in the source code a property is defined. Sometime
* the returned node is not even part of the global AST but in the AST of the
* JsDoc that defines a type.
*
* @param propertyName the name of the property
* @return the {@code Node} corresponding to the property or null.
*/
public final Node getPropertyNode(String propertyName) {
Property p = getSlot(propertyName);
return p == null ? null : p.getNode();
}
public final Node getPropertyDefSite(String propertyName) {
return getPropertyNode(propertyName);
}
public final JSDocInfo getPropertyJSDocInfo(String propertyName) {
Property p = getSlot(propertyName);
return p == null ? null : p.getJSDocInfo();
}
/**
* Gets the docInfo on the specified property on this type. This should not
* be implemented recursively, as you generally need to know exactly on
* which type in the prototype chain the JSDocInfo exists.
*/
public final JSDocInfo getOwnPropertyJSDocInfo(String propertyName) {
Property p = getOwnSlot(propertyName);
return p == null ? null : p.getJSDocInfo();
}
public final Node getOwnPropertyDefSite(String propertyName) {
Property p = getOwnSlot(propertyName);
return p == null ? null : p.getNode();
}
/**
* Sets the docInfo for the specified property from the
* {@link JSDocInfo} on its definition.
* @param info {@code JSDocInfo} for the property definition. May be
* {@code null}.
*/
public void setPropertyJSDocInfo(String propertyName, JSDocInfo info) {
// by default, do nothing
}
/** Sets the node where the property was defined. */
public void setPropertyNode(String propertyName, Node defSite) {
// by default, do nothing
}
@Override
protected JSType findPropertyTypeWithoutConsideringTemplateTypes(String propertyName) {
return hasProperty(propertyName) ? getPropertyType(propertyName) : null;
}
/**
* Gets the property type of the property whose name is given. If the
* underlying object does not have this property, the Unknown type is
* returned to indicate that no information is available on this property.
*
* This gets overridden by FunctionType for lazily-resolved call() and
* bind() functions.
*
* @return the property's type or {@link UnknownType}. This method never
* returns {@code null}.
*/
public JSType getPropertyType(String propertyName) {
StaticTypedSlot slot = getSlot(propertyName);
if (slot == null) {
if (isNoResolvedType() || isCheckedUnknownType()) {
return getNativeType(JSTypeNative.CHECKED_UNKNOWN_TYPE);
} else if (isEmptyType()) {
return getNativeType(JSTypeNative.NO_TYPE);
}
return getNativeType(JSTypeNative.UNKNOWN_TYPE);
}
return slot.getType();
}
@Override
public HasPropertyKind getPropertyKind(String propertyName, boolean autobox) {
// Unknown types have all properties.
return HasPropertyKind.of(isEmptyType() || isUnknownType() || getSlot(propertyName) != null);
}
/**
* Checks whether the property whose name is given is present directly on
* the object. Returns false even if it is declared on a supertype.
*/
public final HasPropertyKind getOwnPropertyKind(String propertyName) {
return getOwnSlot(propertyName) != null
? HasPropertyKind.KNOWN_PRESENT
: HasPropertyKind.ABSENT;
}
/**
* Checks whether the property whose name is given is present directly on
* the object. Returns false even if it is declared on a supertype.
*/
public final boolean hasOwnProperty(String propertyName) {
return !getOwnPropertyKind(propertyName).equals(HasPropertyKind.ABSENT);
}
/**
* Returns the names of all the properties directly on this type.
*
* Overridden by FunctionType to add "prototype".
*/
public Set getOwnPropertyNames() {
// TODO(sdh): ObjectType specifies that this should include prototype properties,
// but currently it does not. Check if this is a constructor and add them, but
// this could possibly break things so it should be done separately.
return getPropertyMap().getOwnPropertyNames();
}
/**
* Checks whether the property's type is inferred.
*/
public final boolean isPropertyTypeInferred(String propertyName) {
StaticTypedSlot slot = getSlot(propertyName);
return slot == null ? false : slot.isTypeInferred();
}
/**
* Checks whether the property's type is declared.
*/
public final boolean isPropertyTypeDeclared(String propertyName) {
StaticTypedSlot slot = getSlot(propertyName);
return slot == null ? false : !slot.isTypeInferred();
}
@Override
public boolean isStructuralType() {
FunctionType constructor = this.getConstructor();
return constructor != null && constructor.isStructuralInterface();
}
/**
* Whether the given property is declared on this object.
*/
final boolean hasOwnDeclaredProperty(String name) {
return hasOwnProperty(name) && isPropertyTypeDeclared(name);
}
/** Checks whether the property was defined in the externs. */
public final boolean isPropertyInExterns(String propertyName) {
Property p = getSlot(propertyName);
return p == null ? false : p.isFromExterns();
}
/**
* Gets the number of properties of this object.
*/
public final int getPropertiesCount() {
return getPropertyMap().getPropertiesCount();
}
/**
* Check for structural equivalence with {@code that}.
* (e.g. two @record types with the same prototype properties)
*/
final boolean checkStructuralEquivalenceHelper(
ObjectType otherObject, EquivalenceMethod eqMethod, EqCache eqCache) {
if (this.isTemplatizedType() && this.toMaybeTemplatizedType().wrapsSameRawType(otherObject)) {
return this.getTemplateTypeMap().checkEquivalenceHelper(
otherObject.getTemplateTypeMap(), eqMethod, eqCache, SubtypingMode.NORMAL);
}
MatchStatus result = eqCache.checkCache(this, otherObject);
if (result != null) {
return result.subtypeValue();
}
Set keySet = getPropertyNames();
Set otherKeySet = otherObject.getPropertyNames();
if (!otherKeySet.equals(keySet)) {
eqCache.updateCache(this, otherObject, MatchStatus.NOT_MATCH);
return false;
}
for (String key : keySet) {
if (!otherObject.getPropertyType(key).checkEquivalenceHelper(
getPropertyType(key), eqMethod, eqCache)) {
eqCache.updateCache(this, otherObject, MatchStatus.NOT_MATCH);
return false;
}
}
eqCache.updateCache(this, otherObject, MatchStatus.MATCH);
return true;
}
static boolean isStructuralSubtypeHelper(
ObjectType subtype,
ObjectType supertype,
ImplCache implicitImplCache,
SubtypingMode subtypingMode,
PropertyOptionality optionality) {
MatchStatus cachedResult = implicitImplCache.checkCache(subtype, supertype);
if (cachedResult != null) {
return cachedResult.subtypeValue();
}
// subtype is a subtype of record type supertype iff:
// 1) subtype has all the non-optional properties declared in supertype.
// 2) And for each property of supertype, its type must be
// a super type of the corresponding property of subtype.
Iterable props =
// NOTE: Inline record literal types always have Object as a supertype. In these cases, we
// really only care about the properties explicitly declared in the record literal, and not
// about any properties inherited from Object.prototype. On the other hand, @record types
// allow inheritance and we need to match against inherited properties as well.
supertype.isRecordType() ? supertype.getOwnPropertyNames() : supertype.getPropertyNames();
boolean result = true;
for (String property : props) {
JSType supertypeProp = supertype.getPropertyType(property);
if (subtype.hasProperty(property)) {
JSType subtypeProp = subtype.getPropertyType(property);
if (!subtypeProp.isSubtype(supertypeProp, implicitImplCache, subtypingMode)) {
result = false;
break;
}
} else if (!optionality.isOptional(supertypeProp)) {
// Currently, any type that explicitly includes undefined (eg, `?|undefined`) is optional.
result = false;
break;
}
}
return implicitImplCache.updateCache(subtype, supertype, MatchStatus.valueOf(result));
}
/** How to treat explicitly voidable properties for structural subtype checking. */
enum PropertyOptionality {
/** Explicitly voidable properties are treated as optional. */
VOIDABLE_PROPS_ARE_OPTIONAL,
/** All properties are always required, even if explicitly voidable. */
ALL_PROPS_ARE_REQUIRED;
boolean isOptional(JSType propType) {
return this == VOIDABLE_PROPS_ARE_OPTIONAL && propType.isExplicitlyVoidable();
}
}
/**
* Returns a list of properties defined or inferred on this type and any of
* its supertypes.
*/
public final Set getPropertyNames() {
Set props = new TreeSet<>();
collectPropertyNames(props);
return props;
}
/**
* Adds any properties defined on this type or its supertypes to the set.
*/
final void collectPropertyNames(Set props) {
getPropertyMap().collectPropertyNames(props);
}
@Override
public T visit(Visitor visitor) {
return visitor.caseObjectType(this);
}
@Override T visit(RelationshipVisitor visitor, JSType that) {
return visitor.caseObjectType(this, that);
}
/**
* Returns whether {@code this} is on the implicit prototype chain of {@code other}.
*
* {@code this} need not be the immediate prototype of {@code other}.
*/
final boolean isImplicitPrototypeOf(ObjectType other) {
ObjectType unwrappedThis = deeplyUnwrap(this);
for (other = deeplyUnwrap(other);
other != null;
other = deeplyUnwrap(other.getImplicitPrototype())) {
// The prototype should match exactly.
// NOTE: the use of "==" here rather than isEquivalentTo is deliberate. This method
// is very hot in the type checker and relying on identity improves performance of both
// type checking/type inferrence and property disambiguation.
if (JSType.areIdentical(unwrappedThis, other)) {
return true;
}
}
return false;
}
/**
* Recursively unwraps all {@link ProxyObjectType}s, including unwrapping the raw type out of a
* templatized type.
*
*
Guaranteed to return a non-proxy type (exception: will return an unresolved NamedType).
*/
static ObjectType deeplyUnwrap(ObjectType original) {
ObjectType current = original;
while (current instanceof ProxyObjectType) {
if (current.isTemplatizedType()) {
current = current.toMaybeTemplatizedType().getReferencedType();
} else if (current.isNamedType()) {
if (!current.isSuccessfullyResolved()) {
break;
}
current = current.toMaybeNamedType().getReferencedObjTypeInternal();
} else {
// TODO(lharker): remove this case and instead fail. Only the Rhino unit tests are
// triggering this by creating new ProxyObjectTypes.
current = ((ProxyObjectType) current).getReferencedObjTypeInternal();
}
}
return current;
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.TRUE;
}
/**
* We treat this as the unknown type if any of its implicit prototype
* properties is unknown.
*/
@Override
public boolean isUnknownType() {
// If the object is unknown now, check the supertype again,
// because it might have been resolved since the last check.
if (unknown) {
ObjectType implicitProto = getImplicitPrototype();
if (implicitProto == null || implicitProto.isNativeObjectType()) {
unknown = false;
for (ObjectType interfaceType : getCtorExtendedInterfaces()) {
if (interfaceType.isUnknownType()) {
unknown = true;
break;
}
}
} else {
unknown = implicitProto.isUnknownType();
}
}
return unknown;
}
@Override
public boolean isObject() {
return true;
}
/**
* Returns true if any cached values have been set for this type. If true,
* then the prototype chain should not be changed, as it might invalidate the
* cached values.
*/
public boolean hasCachedValues() {
return !unknown;
}
/**
* Clear cached values. Should be called before making changes to a prototype
* that may have been changed since creation.
*/
public void clearCachedValues() {
unknown = true;
}
/** Whether this is a built-in object. */
public boolean isNativeObjectType() {
return false;
}
/**
* A null-safe version of JSType#toObjectType.
*/
public static ObjectType cast(JSType type) {
return type == null ? null : type.toObjectType();
}
@Override
public final boolean isFunctionPrototypeType() {
return getOwnerFunction() != null;
}
public FunctionType getOwnerFunction() {
return null;
}
/** Sets the owner function. By default, does nothing. */
void setOwnerFunction(FunctionType type) {}
/**
* Gets the interfaces implemented by the ctor associated with this type.
* Intended to be overridden by subclasses.
*/
public Iterable getCtorImplementedInterfaces() {
return ImmutableSet.of();
}
/**
* Gets the interfaces extended by the interface associated with this type.
* Intended to be overridden by subclasses.
*/
public Iterable getCtorExtendedInterfaces() {
return ImmutableSet.of();
}
/**
* get the map of properties to types covered in an object type
* @return a Map that maps the property's name to the property's type */
public Map getPropertyTypeMap() {
ImmutableMap.Builder propTypeMap = ImmutableMap.builder();
for (String name : this.getPropertyNames()) {
propTypeMap.put(name, this.getPropertyType(name));
}
return propTypeMap.build();
}
public JSType getEnumeratedTypeOfEnumObject() {
return null;
}
}