Java Code Examples for com.google.javascript.rhino.jstype.JSType#isStruct()

The following examples show how to use com.google.javascript.rhino.jstype.JSType#isStruct() . 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_125_TypeCheck_t.java    From coming with MIT License 6 votes vote down vote up
private void checkPropertyAccessHelper(JSType objectType, String propName,
    NodeTraversal t, Node n) {
  if (!objectType.isEmptyType() &&
      reportMissingProperties &&
      (!isPropertyTest(n) || objectType.isStruct())) {
    if (!typeRegistry.canPropertyBeDefined(objectType, propName)) {
      SuggestionPair pair =
          getClosestPropertySuggestion(objectType, propName);
      if (pair != null && pair.distance * 4 < propName.length()) {
        report(t, n, INEXISTENT_PROPERTY_WITH_SUGGESTION, propName,
            validator.getReadableJSTypeName(n.getFirstChild(), true),
            pair.suggestion);
      } else {
        report(t, n, INEXISTENT_PROPERTY, propName,
            validator.getReadableJSTypeName(n.getFirstChild(), true));
      }
    }
  }
}
 
Example 2
Source File: Nopol2017_0029_t.java    From coming with MIT License 5 votes vote down vote up
/** Check that we don't create new properties on structs. */
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)) {
      if (!(obj.isThis() &&
            getJSType(t.getScope().getRootNode()).isConstructor())) {
        report(t, prop, ILLEGAL_PROPERTY_CREATION);
      }
    }
  }
}
 
Example 3
Source File: Nopol2017_0029_s.java    From coming with MIT License 5 votes vote down vote up
/** Check that we don't create new properties on structs. */
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)) {
      if (!(obj.isThis() &&
            getJSType(t.getScope().getRootNode()).isConstructor())) {
        report(t, prop, ILLEGAL_PROPERTY_CREATION);
      }
    }
  }
}
 
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_2_TypeCheck_s.java    From coming with MIT License 5 votes vote down vote up
/** Check that we don't create new properties on structs. */
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)) {
      if (!(obj.isThis() &&
            getJSType(t.getScope().getRootNode()).isConstructor())) {
        report(t, prop, ILLEGAL_PROPERTY_CREATION);
      }
    }
  }
}
 
Example 7
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be addressed with GETELEM syntax,
 * and that the second type is the right type for an index into the
 * first type.
 *
 * @param t The node traversal.
 * @param n The GETELEM node to issue warnings on.
 * @param objType The type of the left side of the GETELEM.
 * @param indexType The type inside the brackets of the GETELEM.
 */
void expectIndexMatch(NodeTraversal t, Node n, JSType objType,
                      JSType indexType) {
  Preconditions.checkState(n.isGetElem());
  Node indexNode = n.getLastChild();
  if (objType.isStruct()) {
    report(JSError.make(t.getSourceName(), indexNode,
                        ILLEGAL_PROPERTY_ACCESS, "'[]'", "struct"));
  }
  if (objType.isUnknownType()) {
    expectStringOrNumber(t, indexNode, indexType, "property access");
  } else {
    ObjectType dereferenced = objType.dereference();
    if (dereferenced != null && dereferenced.getIndexType() != null) {
      expectCanAssignTo(t, indexNode, indexType, dereferenced.getIndexType(),
          "restricted index type");
    } else if (dereferenced != null && dereferenced.isArrayType()) {
      expectNumber(t, indexNode, indexType, "array access");
    } else if (objType.matchesObjectContext()) {
      expectString(t, indexNode, indexType, "property access");
    } else {
      mismatch(t, n, "only arrays or objects can be accessed",
          objType,
          typeRegistry.createUnionType(ARRAY_TYPE, OBJECT_TYPE));
    }
  }
}
 
Example 8
Source File: Closure_117_TypeValidator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be addressed with GETELEM syntax,
 * and that the second type is the right type for an index into the
 * first type.
 *
 * @param t The node traversal.
 * @param n The GETELEM node to issue warnings on.
 * @param objType The type of the left side of the GETELEM.
 * @param indexType The type inside the brackets of the GETELEM.
 */
void expectIndexMatch(NodeTraversal t, Node n, JSType objType,
                      JSType indexType) {
  Preconditions.checkState(n.isGetElem());
  Node indexNode = n.getLastChild();
  if (objType.isStruct()) {
    report(JSError.make(t.getSourceName(), indexNode,
                        ILLEGAL_PROPERTY_ACCESS, "'[]'", "struct"));
  }
  if (objType.isUnknownType()) {
    expectStringOrNumber(t, indexNode, indexType, "property access");
  } else {
    ObjectType dereferenced = objType.dereference();
    if (dereferenced != null && dereferenced
        .getTemplateTypeMap()
        .hasTemplateKey(typeRegistry.getObjectIndexKey())) {
      expectCanAssignTo(t, indexNode, indexType, dereferenced
          .getTemplateTypeMap().getTemplateType(typeRegistry.getObjectIndexKey()),
          "restricted index type");
    } else if (dereferenced != null && dereferenced.isArrayType()) {
      expectNumber(t, indexNode, indexType, "array access");
    } else if (objType.matchesObjectContext()) {
      expectString(t, indexNode, indexType, "property access");
    } else {
      mismatch(t, n, "only arrays or objects can be accessed",
          objType,
          typeRegistry.createUnionType(ARRAY_TYPE, OBJECT_TYPE));
    }
  }
}
 
Example 9
Source File: TypeCheck.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** Check that we don't create new properties on structs. */
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)) {
      if (!(obj.isThis() &&
            getJSType(t.getScope().getRootNode()).isConstructor())) {
        report(t, prop, ILLEGAL_PROPERTY_CREATION);
      }
    }
  }
}
 
Example 10
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be addressed with GETELEM syntax,
 * and that the second type is the right type for an index into the
 * first type.
 *
 * @param t The node traversal.
 * @param n The GETELEM node to issue warnings on.
 * @param objType The type of the left side of the GETELEM.
 * @param indexType The type inside the brackets of the GETELEM.
 */
void expectIndexMatch(NodeTraversal t, Node n, JSType objType,
                      JSType indexType) {
  Preconditions.checkState(n.isGetElem());
  Node indexNode = n.getLastChild();
  if (objType.isStruct()) {
    report(JSError.make(t.getSourceName(), indexNode,
                        ILLEGAL_PROPERTY_ACCESS, "'[]'", "struct"));
  }
  if (objType.isUnknownType()) {
    expectStringOrNumber(t, indexNode, indexType, "property access");
  } else {
    ObjectType dereferenced = objType.dereference();
    if (dereferenced != null && dereferenced.getIndexType() != null) {
      expectCanAssignTo(t, indexNode, indexType, dereferenced.getIndexType(),
          "restricted index type");
    } else if (dereferenced != null && dereferenced.isArrayType()) {
      expectNumber(t, indexNode, indexType, "array access");
    } else if (objType.matchesObjectContext()) {
      expectString(t, indexNode, indexType, "property access");
    } else {
      mismatch(t, n, "only arrays or objects can be accessed",
          objType,
          typeRegistry.createUnionType(ARRAY_TYPE, OBJECT_TYPE));
    }
  }
}
 
Example 11
Source File: Closure_2_TypeCheck_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}
 
Example 12
Source File: TypeCheck.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}
 
Example 13
Source File: Closure_2_TypeCheck_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}
 
Example 14
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);
      }
    }
  }
}
 
Example 15
Source File: Closure_112_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();
  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);
      }
    }
  }
}
 
Example 16
Source File: TypeInference.java    From astor with GNU General Public License v2.0 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());
  if (objectType == null) {
    registry.registerPropertyOnType(propName, nodeType);
  } else {
    // Don't add the property to @struct objects outside a constructor
    if (nodeType.isStruct() && !objectType.hasProperty(propName)) {
      if (!(obj.isThis() &&
            getJSType(syntacticScope.getRootNode()).isConstructor())) {
        return;
      }
    }

    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 (obj.isThis() &&
                 getJSType(syntacticScope.getRootNode()).isConstructor()) {
        objectType.defineInferredProperty(propName, rightType, getprop);
      } else {
        registry.registerPropertyOnType(propName, objectType);
      }
    }
  }
}
 
Example 17
Source File: Closure_125_TypeCheck_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}
 
Example 18
Source File: Closure_125_TypeCheck_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}
 
Example 19
Source File: Nopol2017_0029_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}
 
Example 20
Source File: Nopol2017_0029_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Visits an object literal field definition <code>key : value</code>.
 *
 * If the <code>lvalue</code> is a prototype modification, we change the
 * schema of the object type it is referring to.
 *
 * @param t the traversal
 * @param key the assign node
 */
private void visitObjLitKey(
    NodeTraversal t, Node key, Node objlit, JSType litType) {
  // Do not validate object lit value types in externs. We don't really care,
  // and it makes it easier to generate externs.
  if (objlit.isFromExterns()) {
    ensureTyped(t, key);
    return;
  }

  // Structs must have unquoted keys and dicts must have quoted keys
  if (litType.isStruct() && key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "struct");
  } else if (litType.isDict() && !key.isQuotedString()) {
    report(t, key, ILLEGAL_OBJLIT_KEY, "dict");
  }

  // TODO(johnlenz): Validate get and set function declarations are valid
  // as is the functions can have "extraneous" bits.

  // For getter and setter property definitions the
  // r-value type != the property type.
  Node rvalue = key.getFirstChild();
  JSType rightType = NodeUtil.getObjectLitKeyTypeFromValueType(
      key, getJSType(rvalue));
  if (rightType == null) {
    rightType = getNativeType(UNKNOWN_TYPE);
  }

  Node owner = objlit;

  // Validate value is assignable to the key type.

  JSType keyType = getJSType(key);

  JSType allowedValueType = keyType;
  if (allowedValueType.isEnumElementType()) {
    allowedValueType =
        allowedValueType.toMaybeEnumElementType().getPrimitiveType();
  }

  boolean valid = validator.expectCanAssignToPropertyOf(t, key,
      rightType, allowedValueType,
      owner, NodeUtil.getObjectLitKeyName(key));
  if (valid) {
    ensureTyped(t, key, rightType);
  } else {
    ensureTyped(t, key);
  }

  // Validate that the key type is assignable to the object property type.
  // This is necessary as the objlit may have been cast to a non-literal
  // object type.
  // TODO(johnlenz): consider introducing a CAST node to the AST (or
  // perhaps a parentheses node).

  JSType objlitType = getJSType(objlit);
  ObjectType type = ObjectType.cast(
      objlitType.restrictByNotNullOrUndefined());
  if (type != null) {
    String property = NodeUtil.getObjectLitKeyName(key);
    if (type.hasProperty(property) &&
        !type.isPropertyTypeInferred(property) &&
        !propertyIsImplicitCast(type, property)) {
      validator.expectCanAssignToPropertyOf(
          t, key, keyType,
          type.getPropertyType(property), owner, property);
    }
    return;
  }
}