/** * 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<String, JSType> getPropertyTypeMap() { ImmutableMap.Builder<String, JSType> propTypeMap = ImmutableMap.builder(); for (String name : this.getPropertyNames()) { propTypeMap.put(name, this.getPropertyType(name)); } return propTypeMap.build(); }
@Override public JSType findPropertyType(String propertyName) { return hasProperty(propertyName) ? getPropertyType(propertyName) : null; }
/** * 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<String, JSType> getPropertyTypeMap() { ImmutableMap.Builder<String, JSType> propTypeMap = ImmutableMap.builder(); for (String name : this.getPropertyNames()) { propTypeMap.put(name, this.getPropertyType(name)); } return propTypeMap.build(); } }
@Override protected JSType findPropertyTypeWithoutConsideringTemplateTypes(String propertyName) { return hasProperty(propertyName) ? getPropertyType(propertyName) : null; }
/** * Returns the type of the property with the given name if declared. Otherwise returns unknown. */ private JSType getPropertyTypeIfDeclared(@Nullable ObjectType objectType, String propertyName) { if (objectType != null && objectType.hasProperty(propertyName) && !objectType.isPropertyTypeInferred(propertyName)) { return objectType.getPropertyType(propertyName); } return getNativeType(UNKNOWN_TYPE); }
/** * Merges a list of record types. * Example * {r:{s:string, n:number}} and {a:boolean} * is transformed into {r:{s:string, n:number}, a:boolean} */ private JSType joinRecordTypes(ImmutableList<ObjectType> recTypes) { Map<String, JSType> props = new LinkedHashMap<>(); for (ObjectType recType : recTypes) { for (String newPropName : recType.getOwnPropertyNames()) { JSType newPropValue = recType.getPropertyType(newPropName); // Put the new property depending if it already exists in the map putNewPropInPropertyMap(props, newPropName, newPropValue); } } return createRecordType(ImmutableMap.copyOf(props)); }
@Override public Set<String> caseObjectType(ObjectType type) { // Record types. // {a: T1, b: T2}. if (type.isRecordType()) { for (String propertyName : type.getOwnPropertyNames()) { // After type inference it is possible that some nodes in externs // can have types which are defined in non-extern code. To avoid // bleeding property names of such types into externs we check that // the node for each property was defined in externs. if (type.getPropertyNode(propertyName).isFromExterns()) { externProperties.add(propertyName); visitOnce(type.getPropertyType(propertyName)); } } } return externProperties; }
/** * When a class has a stub for a property, and the property exists on a super interface, * use that type. */ private JSType getInheritedInterfacePropertyType(ObjectType obj, String propName) { if (obj != null && obj.isFunctionPrototypeType()) { FunctionType f = obj.getOwnerFunction(); for (ObjectType i : f.getImplementedInterfaces()) { if (i.hasProperty(propName)) { return i.getPropertyType(propName); } } } return null; }
private void checkPropertyInheritance( NodeTraversal t, Node key, String propertyName, FunctionType ctorType, ObjectType type) { if (ctorType != null && (ctorType.isConstructor() || ctorType.isInterface())) { checkDeclaredPropertyInheritance( t, key.getFirstChild(), ctorType, propertyName, key.getJSDocInfo(), type.getPropertyType(propertyName)); } }
/** Determines if typeA is a subtype of typeB */ private static boolean isSubtype(ObjectType typeA, RecordType typeB, ImplCache implicitImplCache, SubtypingMode subtypingMode) { // typeA is a subtype of record type typeB iff: // 1) typeA has all the properties declared in typeB. // 2) And for each property of typeB, its type must be // a super type of the corresponding property of typeA. for (String property : typeB.getOwnPropertyNames()) { if (!typeA.hasProperty(property)) { return false; } JSType propA = typeA.getPropertyType(property); JSType propB = typeB.getPropertyType(property); if (!propA.isSubtype(propB, implicitImplCache, subtypingMode)) { return false; } } return true; }
/** Determines if typeA is a subtype of typeB */ static boolean isSubtype(ObjectType typeA, RecordType typeB, ImplCache implicitImplCache) { // typeA is a subtype of record type typeB iff: // 1) typeA has all the properties declared in typeB. // 2) And for each property of typeB, its type must be // a super type of the corresponding property of typeA. for (String property : typeB.getOwnPropertyNames()) { if (!typeA.hasProperty(property)) { return false; } JSType propA = typeA.getPropertyType(property); JSType propB = typeB.getPropertyType(property); if (!propA.isSubtype(propB, implicitImplCache)) { return false; } } return true; }
private void aggregateFieldsFromClass(Set<String> fields, ObjectType superType) { // visit instance properties. for (String field : superType.getOwnPropertyNames()) { if (!superType.getPropertyType(field).isFunctionType()) { fields.add(field); } } // visit prototype properties. if (superType.getConstructor() != null && superType.getConstructor().getPrototype() != null && superType.getConstructor().getPrototype().getOwnPropertyNames() != null) { for (String field : superType.getConstructor().getPrototype().getOwnPropertyNames()) { // getPropertyType works with non-owned property names, i.e. names from the prototype // chain. if (!superType.getPropertyType(field).isFunctionType()) { fields.add(field); } } } }
/** * Given the name of a native object property, checks whether the property is * present on the object and different from the native one. */ private boolean hasOverriddenNativeProperty(String propertyName) { if (isNativeObjectType()) { return false; } JSType propertyType = getPropertyType(propertyName); ObjectType nativeType = isFunctionType() ? registry.getNativeObjectType(JSTypeNative.FUNCTION_PROTOTYPE) : registry.getNativeObjectType(JSTypeNative.OBJECT_PROTOTYPE); JSType nativePropertyType = nativeType.getPropertyType(propertyName); return propertyType != nativePropertyType; }
/** Creates node that access a specified field of the current context. */ Node getContextField(Node sourceNode, String fieldName) { return withType( IR.getprop( getJsContextNameNode(sourceNode), IR.string(fieldName).useSourceInfoFrom(sourceNode)), shouldAddTypes ? contextType.getPropertyType(fieldName) : null) .useSourceInfoFrom(sourceNode); }
/** * Given the name of a native object property, checks whether the property is * present on the object and different from the native one. */ private boolean hasOverridenNativeProperty(String propertyName) { if (isNativeObjectType()) { return false; } JSType propertyType = getPropertyType(propertyName); ObjectType nativeType = isFunctionType() ? registry.getNativeObjectType(JSTypeNative.FUNCTION_PROTOTYPE) : registry.getNativeObjectType(JSTypeNative.OBJECT_PROTOTYPE); JSType nativePropertyType = nativeType.getPropertyType(propertyName); return propertyType != nativePropertyType; }
public void matchRecordTypeConstraint(ObjectType constraintObj) { for (String prop : constraintObj.getOwnPropertyNames()) { JSType propType = constraintObj.getPropertyType(prop); if (!isPropertyTypeDeclared(prop)) { JSType typeToInfer = propType; if (!hasProperty(prop)) { typeToInfer = getNativeType(JSTypeNative.VOID_TYPE) .getLeastSupertype(propType); } defineInferredProperty(prop, typeToInfer, null); } } }
private JSType evalPropType(Node ttlAst, NameResolver nameResolver) { JSType type = evalInternal(getCallArgument(ttlAst, 1), nameResolver); ObjectType objType = type.toMaybeObjectType(); if (objType == null) { reportWarning(ttlAst, PROPTYPE_INVALID, type.toString()); return getUnknownType(); } JSType propType = objType.getPropertyType(getCallArgument(ttlAst, 0).getString()); return firstNonNull(propType, getUnknownType()); }
public void matchRecordTypeConstraint(ObjectType constraintObj) { for (String prop : constraintObj.getOwnPropertyNames()) { JSType propType = constraintObj.getPropertyType(prop); if (!isPropertyTypeDeclared(prop)) { JSType typeToInfer = propType; if (!hasProperty(prop)) { typeToInfer = getNativeType(JSTypeNative.VOID_TYPE) .getLeastSupertype(propType); } defineInferredProperty(prop, typeToInfer, null); } } }
private JSType evalPropType(Node ttlAst, NameResolver nameResolver) { JSType type = evalInternal(getCallArgument(ttlAst, 1), nameResolver); ObjectType objType = type.toObjectType(); if (objType == null) { reportWarning(ttlAst, PROPTYPE_INVALID, type.toString()); return getUnknownType(); } return objType.getPropertyType(getCallArgument(ttlAst, 0).getString()); }
/** * @param constructor A constructor function defined by a call, which may be a mixin application. * The constructor implements at least one interface. If the constructor is missing some * properties of the inherited interfaces, this method declares these properties. */ private static void addMissingInterfaceProperties(JSType constructor) { if (constructor != null && constructor.isConstructor()) { FunctionType f = constructor.toMaybeFunctionType(); ObjectType proto = f.getPrototype(); for (ObjectType interf : f.getImplementedInterfaces()) { for (String pname : interf.getPropertyNames()) { if (!proto.hasProperty(pname)) { proto.defineDeclaredProperty(pname, interf.getPropertyType(pname), null); } } } } }