Java Code Examples for com.google.javascript.rhino.jstype.ObjectType#defineInferredProperty()

The following examples show how to use com.google.javascript.rhino.jstype.ObjectType#defineInferredProperty() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Closure_35_TypeInference_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Suppose X is an object with inferred properties.
 * Suppose also that X is used in a way where it would only type-check
 * correctly if some of those properties are widened.
 * Then we should be polite and automatically widen X's properties for him.
 *
 * For a concrete example, consider:
 * param x {{prop: (number|undefined)}}
 * function f(x) {}
 * f({});
 *
 * If we give the anonymous object an inferred property of (number|undefined),
 * then this code will type-check appropriately.
 */
private void inferPropertyTypesToMatchConstraint(
    JSType type, JSType constraint) {
  if (type == null || constraint == null) {
    return;
  }

  ObjectType constraintObj =
      ObjectType.cast(constraint.restrictByNotNullOrUndefined());
  if (constraintObj != null && constraintObj.isRecordType()) {
    ObjectType objType = ObjectType.cast(type.restrictByNotNullOrUndefined());
    if (objType != null) {
      for (String prop : constraintObj.getOwnPropertyNames()) {
        JSType propType = constraintObj.getPropertyType(prop);
        if (!objType.isPropertyTypeDeclared(prop)) {
          JSType typeToInfer = propType;
          if (!objType.hasProperty(prop)) {
            typeToInfer =
                getNativeType(VOID_TYPE).getLeastSupertype(propType);
          }
          objType.defineInferredProperty(prop, typeToInfer, null);
        }
      }
    }
  }
}
 
Example 2
Source File: Nopol2017_0027_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub declarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 3
Source File: TypedScopeCreator.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Resolve any stub declarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 4
Source File: Closure_125_TypeCheck_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * After a struct object is created, we can't add new properties to it, with
 * one exception. We allow creation of "static" properties like
 * Foo.prototype.bar = baz;
 * where Foo.prototype is a struct, if the assignment happens at the top level
 * and the constructor Foo is defined in the same file.
 */
private void checkPropCreation(NodeTraversal t, Node lvalue) {
  if (lvalue.isGetProp()) {
    Node obj = lvalue.getFirstChild();
    Node prop = lvalue.getLastChild();
    JSType objType = getJSType(obj);
    String pname = prop.getString();

    if (!objType.isStruct() || objType.hasProperty(pname)) {
      return;
    }
    Scope s = t.getScope();
    if (obj.isThis() && getJSType(s.getRootNode()).isConstructor()) {
      return;
    }
    // Prop created outside ctor, check that it's a static prop
    Node assgnExp = lvalue.getParent();
    Node assgnStm = assgnExp.getParent();
    if (objType instanceof ObjectType &&
        s.isGlobal() &&
        NodeUtil.isPrototypePropertyDeclaration(assgnStm)) {
      ObjectType instance =
          objType.toObjectType().getOwnerFunction().getInstanceType();
      String file = lvalue.getSourceFileName();
      Node ctor = instance.getConstructor().getSource();
      if (ctor != null && ctor.getSourceFileName().equals(file)) {
        JSType rvalueType = assgnExp.getLastChild().getJSType();
        instance.defineInferredProperty(pname, rvalueType, lvalue);
        return;
      }
    }
    report(t, prop, ILLEGAL_PROPERTY_CREATION);
  }
}
 
Example 5
Source File: Closure_125_TypeCheck_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * After a struct object is created, we can't add new properties to it, with
 * one exception. We allow creation of "static" properties like
 * Foo.prototype.bar = baz;
 * where Foo.prototype is a struct, if the assignment happens at the top level
 * and the constructor Foo is defined in the same file.
 */
private void checkPropCreation(NodeTraversal t, Node lvalue) {
  if (lvalue.isGetProp()) {
    Node obj = lvalue.getFirstChild();
    Node prop = lvalue.getLastChild();
    JSType objType = getJSType(obj);
    String pname = prop.getString();

    if (!objType.isStruct() || objType.hasProperty(pname)) {
      return;
    }
    Scope s = t.getScope();
    if (obj.isThis() && getJSType(s.getRootNode()).isConstructor()) {
      return;
    }
    // Prop created outside ctor, check that it's a static prop
    Node assgnExp = lvalue.getParent();
    Node assgnStm = assgnExp.getParent();
    if (objType instanceof ObjectType &&
        s.isGlobal() &&
        NodeUtil.isPrototypePropertyDeclaration(assgnStm)) {
      ObjectType instance =
          objType.toObjectType().getOwnerFunction().getInstanceType();
      String file = lvalue.getSourceFileName();
      Node ctor = instance.getConstructor().getSource();
      if (ctor != null && ctor.getSourceFileName().equals(file)) {
        JSType rvalueType = assgnExp.getLastChild().getJSType();
        instance.defineInferredProperty(pname, rvalueType, lvalue);
        return;
      }
    }
    report(t, prop, ILLEGAL_PROPERTY_CREATION);
  }
}
 
Example 6
Source File: Closure_95_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, isExtern);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 7
Source File: Closure_54_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 8
Source File: Closure_48_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 9
Source File: Closure_43_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 10
Source File: Closure_43_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 11
Source File: Closure_95_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, isExtern);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 12
Source File: Closure_54_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Resolve any stub delcarations to unknown types if we could not
 * find types for them during traversal.
 */
void resolveStubDeclarations() {
  for (StubDeclaration stub : stubDeclarations) {
    Node n = stub.node;
    Node parent = n.getParent();
    String qName = n.getQualifiedName();
    String propName = n.getLastChild().getString();
    String ownerName = stub.ownerName;
    boolean isExtern = stub.isExtern;

    if (scope.isDeclared(qName, false)) {
      continue;
    }

    // If we see a stub property, make sure to register this property
    // in the type registry.
    ObjectType ownerType = getObjectSlot(ownerName);
    ObjectType unknownType = typeRegistry.getNativeObjectType(UNKNOWN_TYPE);
    defineSlot(n, parent, unknownType, true);

    if (ownerType != null &&
        (isExtern || ownerType.isFunctionPrototypeType())) {
      // If this is a stub for a prototype, just declare it
      // as an unknown type. These are seen often in externs.
      ownerType.defineInferredProperty(
          propName, unknownType, n);
    } else {
      typeRegistry.registerPropertyOnType(
          propName, ownerType == null ? unknownType : ownerType);
    }
  }
}
 
Example 13
Source File: Closure_35_TypeInference_s.java    From coming with MIT License 4 votes vote down vote up
private FlowScope traverseObjectLiteral(Node n, FlowScope scope) {
  JSType type = n.getJSType();
  Preconditions.checkNotNull(type);

  for (Node name = n.getFirstChild(); name != null; name = name.getNext()) {
    scope = traverse(name.getFirstChild(), scope);
  }

  // Object literals can be reflected on other types, or changed with
  // type casts.
  // See CodingConvention#getObjectLiteralCase and goog.object.reflect.
  // Ignore these types of literals.
  // TODO(nicksantos): There should be an "anonymous object" type that
  // we can check for here.
  ObjectType objectType = ObjectType.cast(type);
  if (objectType == null) {
    return scope;
  }

  boolean hasLendsName = n.getJSDocInfo() != null &&
      n.getJSDocInfo().getLendsName() != null;
  if (objectType.hasReferenceName() && !hasLendsName) {
    return scope;
  }

  String qObjName = NodeUtil.getBestLValueName(
      NodeUtil.getBestLValue(n));
  for (Node name = n.getFirstChild(); name != null;
       name = name.getNext()) {
    Node value = name.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(name);
    if (memberName != null) {
      JSType rawValueType =  name.getFirstChild().getJSType();
      JSType valueType = NodeUtil.getObjectLitKeyTypeFromValueType(
          name, rawValueType);
      if (valueType == null) {
        valueType = getNativeType(UNKNOWN_TYPE);
      }
      objectType.defineInferredProperty(memberName, valueType, name);

      // Do normal flow inference if this is a direct property assignment.
      if (qObjName != null && name.isString()) {
        String qKeyName = qObjName + "." + memberName;
        Var var = syntacticScope.getVar(qKeyName);
        JSType oldType = var == null ? null : var.getType();
        if (var != null && var.isTypeInferred()) {
          var.setType(oldType == null ?
              valueType : oldType.getLeastSupertype(oldType));
        }

        scope.inferQualifiedSlot(name, qKeyName,
            oldType == null ? getNativeType(UNKNOWN_TYPE) : oldType,
            valueType);
      }
    } else {
      n.setJSType(getNativeType(UNKNOWN_TYPE));
    }
  }
  return scope;
}
 
Example 14
Source File: TypeInference.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
private FlowScope traverseObjectLiteral(Node n, FlowScope scope) {
  JSType type = n.getJSType();
  Preconditions.checkNotNull(type);

  for (Node name = n.getFirstChild(); name != null; name = name.getNext()) {
    scope = traverse(name.getFirstChild(), scope);
  }

  // Object literals can be reflected on other types, or changed with
  // type casts.
  // See CodingConvention#getObjectLiteralCase and goog.object.reflect.
  // Ignore these types of literals.
  // TODO(nicksantos): There should be an "anonymous object" type that
  // we can check for here.
  ObjectType objectType = ObjectType.cast(type);
  if (objectType == null) {
    return scope;
  }

  boolean hasLendsName = n.getJSDocInfo() != null &&
      n.getJSDocInfo().getLendsName() != null;
  if (objectType.hasReferenceName() && !hasLendsName) {
    return scope;
  }

  String qObjName = NodeUtil.getBestLValueName(
      NodeUtil.getBestLValue(n));
  for (Node name = n.getFirstChild(); name != null;
       name = name.getNext()) {
    Node value = name.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(name);
    if (memberName != null) {
      JSType rawValueType =  name.getFirstChild().getJSType();
      JSType valueType = NodeUtil.getObjectLitKeyTypeFromValueType(
          name, rawValueType);
      if (valueType == null) {
        valueType = unknownType;
      }
      objectType.defineInferredProperty(memberName, valueType, name);

      // Do normal flow inference if this is a direct property assignment.
      if (qObjName != null && name.isStringKey()) {
        String qKeyName = qObjName + "." + memberName;
        Var var = syntacticScope.getVar(qKeyName);
        JSType oldType = var == null ? null : var.getType();
        if (var != null && var.isTypeInferred()) {
          var.setType(oldType == null ?
              valueType : oldType.getLeastSupertype(oldType));
        }

        scope.inferQualifiedSlot(name, qKeyName,
            oldType == null ? unknownType : oldType,
            valueType);
      }
    } else {
      n.setJSType(unknownType);
    }
  }
  return scope;
}
 
Example 15
Source File: Closure_25_TypeInference_t.java    From coming with MIT License 4 votes vote down vote up
private FlowScope traverseObjectLiteral(Node n, FlowScope scope) {
  JSType type = n.getJSType();
  Preconditions.checkNotNull(type);

  for (Node name = n.getFirstChild(); name != null; name = name.getNext()) {
    scope = traverse(name.getFirstChild(), scope);
  }

  // Object literals can be reflected on other types, or changed with
  // type casts.
  // See CodingConvention#getObjectLiteralCase and goog.object.reflect.
  // Ignore these types of literals.
  // TODO(nicksantos): There should be an "anonymous object" type that
  // we can check for here.
  ObjectType objectType = ObjectType.cast(type);
  if (objectType == null) {
    return scope;
  }

  boolean hasLendsName = n.getJSDocInfo() != null &&
      n.getJSDocInfo().getLendsName() != null;
  if (objectType.hasReferenceName() && !hasLendsName) {
    return scope;
  }

  String qObjName = NodeUtil.getBestLValueName(
      NodeUtil.getBestLValue(n));
  for (Node name = n.getFirstChild(); name != null;
       name = name.getNext()) {
    Node value = name.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(name);
    if (memberName != null) {
      JSType rawValueType =  name.getFirstChild().getJSType();
      JSType valueType = NodeUtil.getObjectLitKeyTypeFromValueType(
          name, rawValueType);
      if (valueType == null) {
        valueType = getNativeType(UNKNOWN_TYPE);
      }
      objectType.defineInferredProperty(memberName, valueType, name);

      // Do normal flow inference if this is a direct property assignment.
      if (qObjName != null && name.isStringKey()) {
        String qKeyName = qObjName + "." + memberName;
        Var var = syntacticScope.getVar(qKeyName);
        JSType oldType = var == null ? null : var.getType();
        if (var != null && var.isTypeInferred()) {
          var.setType(oldType == null ?
              valueType : oldType.getLeastSupertype(oldType));
        }

        scope.inferQualifiedSlot(name, qKeyName,
            oldType == null ? getNativeType(UNKNOWN_TYPE) : oldType,
            valueType);
      }
    } else {
      n.setJSType(getNativeType(UNKNOWN_TYPE));
    }
  }
  return scope;
}
 
Example 16
Source File: Closure_25_TypeInference_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Defines a property if the property has not been defined yet.
 */
private void ensurePropertyDefined(Node getprop, JSType rightType) {
  String propName = getprop.getLastChild().getString();
  JSType nodeType = getJSType(getprop.getFirstChild());
  ObjectType objectType = ObjectType.cast(
      nodeType.restrictByNotNullOrUndefined());
  if (objectType == null) {
    registry.registerPropertyOnType(propName, nodeType);
  } else {
    if (ensurePropertyDeclaredHelper(getprop, objectType)) {
      return;
    }

    if (!objectType.isPropertyTypeDeclared(propName)) {
      // We do not want a "stray" assign to define an inferred property
      // for every object of this type in the program. So we use a heuristic
      // approach to determine whether to infer the property.
      //
      // 1) If the property is already defined, join it with the previously
      //    inferred type.
      // 2) If this isn't an instance object, define it.
      // 3) If the property of an object is being assigned in the constructor,
      //    define it.
      // 4) If this is a stub, define it.
      // 5) Otherwise, do not define the type, but declare it in the registry
      //    so that we can use it for missing property checks.
      if (objectType.hasProperty(propName) ||
          !objectType.isInstanceType()) {
        if ("prototype".equals(propName)) {
          objectType.defineDeclaredProperty(
              propName, rightType, getprop);
        } else {
          objectType.defineInferredProperty(
              propName, rightType, getprop);
        }
      } else {
        if (getprop.getFirstChild().isThis() &&
            getJSType(syntacticScope.getRootNode()).isConstructor()) {
          objectType.defineInferredProperty(
              propName, rightType, getprop);
        } else {
          registry.registerPropertyOnType(propName, objectType);
        }
      }
    }
  }
}
 
Example 17
Source File: Closure_112_TypeInference_s.java    From coming with MIT License 4 votes vote down vote up
private FlowScope traverseObjectLiteral(Node n, FlowScope scope) {
  JSType type = n.getJSType();
  Preconditions.checkNotNull(type);

  for (Node name = n.getFirstChild(); name != null; name = name.getNext()) {
    scope = traverse(name.getFirstChild(), scope);
  }

  // Object literals can be reflected on other types.
  // See CodingConvention#getObjectLiteralCast and goog.reflect.object
  // Ignore these types of literals.
  ObjectType objectType = ObjectType.cast(type);
  if (objectType == null
      || n.getBooleanProp(Node.REFLECTED_OBJECT)
      || objectType.isEnumType()) {
    return scope;
  }

  String qObjName = NodeUtil.getBestLValueName(
      NodeUtil.getBestLValue(n));
  for (Node name = n.getFirstChild(); name != null;
       name = name.getNext()) {
    String memberName = NodeUtil.getObjectLitKeyName(name);
    if (memberName != null) {
      JSType rawValueType =  name.getFirstChild().getJSType();
      JSType valueType = NodeUtil.getObjectLitKeyTypeFromValueType(
          name, rawValueType);
      if (valueType == null) {
        valueType = unknownType;
      }
      objectType.defineInferredProperty(memberName, valueType, name);

      // Do normal flow inference if this is a direct property assignment.
      if (qObjName != null && name.isStringKey()) {
        String qKeyName = qObjName + "." + memberName;
        Var var = syntacticScope.getVar(qKeyName);
        JSType oldType = var == null ? null : var.getType();
        if (var != null && var.isTypeInferred()) {
          var.setType(oldType == null ?
              valueType : oldType.getLeastSupertype(oldType));
        }

        scope.inferQualifiedSlot(name, qKeyName,
            oldType == null ? unknownType : oldType,
            valueType);
      }
    } else {
      n.setJSType(unknownType);
    }
  }
  return scope;
}
 
Example 18
Source File: Closure_35_TypeInference_t.java    From coming with MIT License 4 votes vote down vote up
private FlowScope traverseObjectLiteral(Node n, FlowScope scope) {
  JSType type = n.getJSType();
  Preconditions.checkNotNull(type);

  for (Node name = n.getFirstChild(); name != null; name = name.getNext()) {
    scope = traverse(name.getFirstChild(), scope);
  }

  // Object literals can be reflected on other types, or changed with
  // type casts.
  // See CodingConvention#getObjectLiteralCase and goog.object.reflect.
  // Ignore these types of literals.
  // TODO(nicksantos): There should be an "anonymous object" type that
  // we can check for here.
  ObjectType objectType = ObjectType.cast(type);
  if (objectType == null) {
    return scope;
  }

  boolean hasLendsName = n.getJSDocInfo() != null &&
      n.getJSDocInfo().getLendsName() != null;
  if (objectType.hasReferenceName() && !hasLendsName) {
    return scope;
  }

  String qObjName = NodeUtil.getBestLValueName(
      NodeUtil.getBestLValue(n));
  for (Node name = n.getFirstChild(); name != null;
       name = name.getNext()) {
    Node value = name.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(name);
    if (memberName != null) {
      JSType rawValueType =  name.getFirstChild().getJSType();
      JSType valueType = NodeUtil.getObjectLitKeyTypeFromValueType(
          name, rawValueType);
      if (valueType == null) {
        valueType = getNativeType(UNKNOWN_TYPE);
      }
      objectType.defineInferredProperty(memberName, valueType, name);

      // Do normal flow inference if this is a direct property assignment.
      if (qObjName != null && name.isString()) {
        String qKeyName = qObjName + "." + memberName;
        Var var = syntacticScope.getVar(qKeyName);
        JSType oldType = var == null ? null : var.getType();
        if (var != null && var.isTypeInferred()) {
          var.setType(oldType == null ?
              valueType : oldType.getLeastSupertype(oldType));
        }

        scope.inferQualifiedSlot(name, qKeyName,
            oldType == null ? getNativeType(UNKNOWN_TYPE) : oldType,
            valueType);
      }
    } else {
      n.setJSType(getNativeType(UNKNOWN_TYPE));
    }
  }
  return scope;
}
 
Example 19
Source File: Closure_112_TypeInference_t.java    From coming with MIT License 4 votes vote down vote up
private FlowScope traverseObjectLiteral(Node n, FlowScope scope) {
  JSType type = n.getJSType();
  Preconditions.checkNotNull(type);

  for (Node name = n.getFirstChild(); name != null; name = name.getNext()) {
    scope = traverse(name.getFirstChild(), scope);
  }

  // Object literals can be reflected on other types.
  // See CodingConvention#getObjectLiteralCast and goog.reflect.object
  // Ignore these types of literals.
  ObjectType objectType = ObjectType.cast(type);
  if (objectType == null
      || n.getBooleanProp(Node.REFLECTED_OBJECT)
      || objectType.isEnumType()) {
    return scope;
  }

  String qObjName = NodeUtil.getBestLValueName(
      NodeUtil.getBestLValue(n));
  for (Node name = n.getFirstChild(); name != null;
       name = name.getNext()) {
    String memberName = NodeUtil.getObjectLitKeyName(name);
    if (memberName != null) {
      JSType rawValueType =  name.getFirstChild().getJSType();
      JSType valueType = NodeUtil.getObjectLitKeyTypeFromValueType(
          name, rawValueType);
      if (valueType == null) {
        valueType = unknownType;
      }
      objectType.defineInferredProperty(memberName, valueType, name);

      // Do normal flow inference if this is a direct property assignment.
      if (qObjName != null && name.isStringKey()) {
        String qKeyName = qObjName + "." + memberName;
        Var var = syntacticScope.getVar(qKeyName);
        JSType oldType = var == null ? null : var.getType();
        if (var != null && var.isTypeInferred()) {
          var.setType(oldType == null ?
              valueType : oldType.getLeastSupertype(oldType));
        }

        scope.inferQualifiedSlot(name, qKeyName,
            oldType == null ? unknownType : oldType,
            valueType);
      }
    } else {
      n.setJSType(unknownType);
    }
  }
  return scope;
}
 
Example 20
Source File: Closure_112_TypeInference_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Defines a property if the property has not been defined yet.
 */
private void ensurePropertyDefined(Node getprop, JSType rightType) {
  String propName = getprop.getLastChild().getString();
  Node obj = getprop.getFirstChild();
  JSType nodeType = getJSType(obj);
  ObjectType objectType = ObjectType.cast(
      nodeType.restrictByNotNullOrUndefined());
  boolean propCreationInConstructor = obj.isThis() &&
      getJSType(syntacticScope.getRootNode()).isConstructor();

  if (objectType == null) {
    registry.registerPropertyOnType(propName, nodeType);
  } else {
    if (nodeType.isStruct() && !objectType.hasProperty(propName)) {
      // In general, we don't want to define a property on a struct object,
      // b/c TypeCheck will later check for improper property creation on
      // structs. There are two exceptions.
      // 1) If it's a property created inside the constructor, on the newly
      //    created instance, allow it.
      // 2) If it's a prototype property, allow it. For example:
      //    Foo.prototype.bar = baz;
      //    where Foo.prototype is a struct and the assignment happens at the
      //    top level and the constructor Foo is defined in the same file.
      boolean staticPropCreation = false;
      Node maybeAssignStm = getprop.getParent().getParent();
      if (syntacticScope.isGlobal() &&
          NodeUtil.isPrototypePropertyDeclaration(maybeAssignStm)) {
        String propCreationFilename = maybeAssignStm.getSourceFileName();
        Node ctor = objectType.getOwnerFunction().getSource();
        if (ctor != null &&
            ctor.getSourceFileName().equals(propCreationFilename)) {
          staticPropCreation = true;
        }
      }
      if (!propCreationInConstructor && !staticPropCreation) {
        return; // Early return to avoid creating the property below.
      }
    }

    if (ensurePropertyDeclaredHelper(getprop, objectType)) {
      return;
    }

    if (!objectType.isPropertyTypeDeclared(propName)) {
      // We do not want a "stray" assign to define an inferred property
      // for every object of this type in the program. So we use a heuristic
      // approach to determine whether to infer the property.
      //
      // 1) If the property is already defined, join it with the previously
      //    inferred type.
      // 2) If this isn't an instance object, define it.
      // 3) If the property of an object is being assigned in the constructor,
      //    define it.
      // 4) If this is a stub, define it.
      // 5) Otherwise, do not define the type, but declare it in the registry
      //    so that we can use it for missing property checks.
      if (objectType.hasProperty(propName) || !objectType.isInstanceType()) {
        if ("prototype".equals(propName)) {
          objectType.defineDeclaredProperty(propName, rightType, getprop);
        } else {
          objectType.defineInferredProperty(propName, rightType, getprop);
        }
      } else if (propCreationInConstructor) {
        objectType.defineInferredProperty(propName, rightType, getprop);
      } else {
        registry.registerPropertyOnType(propName, objectType);
      }
    }
  }
}