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

The following examples show how to use com.google.javascript.rhino.jstype.ObjectType#defineDeclaredProperty() . 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_112_TypeInference_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Declares a property on its owner, if necessary.
 * @return True if a property was declared.
 */
private boolean ensurePropertyDeclaredHelper(
    Node getprop, ObjectType objectType) {
  String propName = getprop.getLastChild().getString();
  String qName = getprop.getQualifiedName();
  if (qName != null) {
    Var var = syntacticScope.getVar(qName);
    if (var != null && !var.isTypeInferred()) {
      // Handle normal declarations that could not be addressed earlier.
      if (propName.equals("prototype") ||
      // Handle prototype declarations that could not be addressed earlier.
          (!objectType.hasOwnProperty(propName) &&
           (!objectType.isInstanceType() ||
               (var.isExtern() && !objectType.isNativeObjectType())))) {
        return objectType.defineDeclaredProperty(
            propName, var.getType(), getprop);
      }
    }
  }
  return false;
}
 
Example 2
Source File: Closure_25_TypeInference_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Declares a property on its owner, if necessary.
 * @return True if a property was declared.
 */
private boolean ensurePropertyDeclaredHelper(
    Node getprop, ObjectType objectType) {
  String propName = getprop.getLastChild().getString();
  String qName = getprop.getQualifiedName();
  if (qName != null) {
    Var var = syntacticScope.getVar(qName);
    if (var != null && !var.isTypeInferred()) {
      // Handle normal declarations that could not be addressed earlier.
      if (propName.equals("prototype") ||
      // Handle prototype declarations that could not be addressed earlier.
          (!objectType.hasOwnProperty(propName) &&
           (!objectType.isInstanceType() ||
               (var.isExtern() && !objectType.isNativeObjectType())))) {
        return objectType.defineDeclaredProperty(
            propName, var.getType(), getprop);
      }
    }
  }
  return false;
}
 
Example 3
Source File: Closure_25_TypeInference_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Declares a property on its owner, if necessary.
 * @return True if a property was declared.
 */
private boolean ensurePropertyDeclaredHelper(
    Node getprop, ObjectType objectType) {
  String propName = getprop.getLastChild().getString();
  String qName = getprop.getQualifiedName();
  if (qName != null) {
    Var var = syntacticScope.getVar(qName);
    if (var != null && !var.isTypeInferred()) {
      // Handle normal declarations that could not be addressed earlier.
      if (propName.equals("prototype") ||
      // Handle prototype declarations that could not be addressed earlier.
          (!objectType.hasOwnProperty(propName) &&
           (!objectType.isInstanceType() ||
               (var.isExtern() && !objectType.isNativeObjectType())))) {
        return objectType.defineDeclaredProperty(
            propName, var.getType(), getprop);
      }
    }
  }
  return false;
}
 
Example 4
Source File: TypeInferenceTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testPropertyInference2() {
  ObjectType thisType = registry.createAnonymousObjectType(null);
  thisType.defineDeclaredProperty("foo",
      createUndefinableType(STRING_TYPE), null);
  assumingThisType(thisType);
  inFunction("var y = 1; this.foo = 'x'; y = this.foo;");
  verify("y", STRING_TYPE);
}
 
Example 5
Source File: ConcreteTypeTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** Creates a fake instance with the given description. */
private ConcreteInstanceType createInstance(
    String name, String... propNames) {
  ObjectType objType = typeRegistry.createObjectType(name, null,
      typeRegistry.createObjectType(name + ".prototype", null, null));
  for (int i = 0; i < propNames.length; ++i) {
    objType.defineDeclaredProperty(propNames[i], unknownType, null);
  }
  return new ConcreteInstanceType(factory, objType);
}
 
Example 6
Source File: Closure_17_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 * @param declareOnOwner If true, declare properties on the objLitType as
 *     well. If false, the caller should take care of this.
 */
void processObjectLitProperties(
    Node objLit, ObjectType objLitType,
    boolean declareOnOwner) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType =
        getDeclaredType(keyNode.getSourceFileName(), info, keyNode, value);
    JSType keyType =  objLitType.isEnumType() ?
        objLitType.toMaybeEnumType().getElementsType() :
        NodeUtil.getObjectLitKeyTypeFromValueType(keyNode, valueType);

    // Try to declare this property in the current scope if it
    // has an authoritative name.
    String qualifiedName = NodeUtil.getBestLValueName(keyNode);
    if (qualifiedName != null) {
      boolean inferred = keyType == null;
      defineSlot(keyNode, objLit, qualifiedName, keyType, inferred);
    } else if (keyType != null) {
      setDeferredType(keyNode, keyType);
    }

    if (keyType != null && objLitType != null && declareOnOwner) {
      // Declare this property on its object literal.
      boolean isExtern = keyNode.isFromExterns();
      objLitType.defineDeclaredProperty(memberName, keyType, keyNode);
    }
  }
}
 
Example 7
Source File: Nopol2017_0027_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 * @param declareOnOwner If true, declare properties on the objLitType as
 *     well. If false, the caller should take care of this.
 */
void processObjectLitProperties(
    Node objLit, ObjectType objLitType,
    boolean declareOnOwner) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType =
        getDeclaredType(keyNode.getSourceFileName(), info, keyNode, value);
    JSType keyType =  objLitType.isEnumType() ?
        objLitType.toMaybeEnumType().getElementsType() :
        NodeUtil.getObjectLitKeyTypeFromValueType(keyNode, valueType);

    // Try to declare this property in the current scope if it
    // has an authoritative name.
    String qualifiedName = NodeUtil.getBestLValueName(keyNode);
    if (qualifiedName != null) {
      boolean inferred = keyType == null;
      defineSlot(keyNode, objLit, qualifiedName, keyType, inferred);
    } else if (keyType != null) {
      setDeferredType(keyNode, keyType);
    }

    if (keyType != null && objLitType != null && declareOnOwner) {
      // Declare this property on its object literal.
      boolean isExtern = keyNode.isFromExterns();
      objLitType.defineDeclaredProperty(memberName, keyType, keyNode);
    }
  }
}
 
Example 8
Source File: Closure_70_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 */
void processObjectLitProperties(
    NodeTraversal t, Node objLit, ObjectType objLitType) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType = getDeclaredType(
        t.getSourceName(), info, keyNode, value);
    JSType keyType = NodeUtil.getObjectLitKeyTypeFromValueType(
        keyNode, valueType);
    if (keyType != null) {
      // Try to declare this property in the current scope if it
      // has an authoritative name.
      String qualifiedName = getBestLValueName(keyNode);
      if (qualifiedName != null) {
        defineSlot(keyNode, objLit, qualifiedName, keyType, false);
      } else {
        setDeferredType(keyNode, keyType);
      }

      if (objLitType != null) {
        // Declare this property on its object literal.
        boolean isExtern = t.getInput() != null && t.getInput().isExtern();
        objLitType.defineDeclaredProperty(
            memberName, keyType, isExtern, keyNode);
      }
    }
  }
}
 
Example 9
Source File: BaseJSTypeTestCase.java    From ng-closure-runner with MIT License 5 votes vote down vote up
private static void addMethod(
    JSTypeRegistry registry, ObjectType receivingType, String methodName,
    JSType returnType) {
  receivingType.defineDeclaredProperty(methodName,
      new FunctionBuilder(registry).withReturnType(returnType).build(),
      null);
}
 
Example 10
Source File: Closure_48_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 * @param declareOnOwner If true, declare properties on the objLitType as
 *     well. If false, the caller should take crae of this.
 */
void processObjectLitProperties(
    NodeTraversal t, Node objLit, ObjectType objLitType,
    boolean declareOnOwner) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType =
        getDeclaredType(t.getSourceName(), info, keyNode, value);
    JSType keyType =  objLitType.isEnumType() ?
        objLitType.toMaybeEnumType().getElementsType() :
        NodeUtil.getObjectLitKeyTypeFromValueType(keyNode, valueType);
    if (keyType != null) {
      // Try to declare this property in the current scope if it
      // has an authoritative name.
      String qualifiedName = NodeUtil.getBestLValueName(keyNode);
      if (qualifiedName != null) {
        defineSlot(keyNode, objLit, qualifiedName, keyType, false);
      } else {
        setDeferredType(keyNode, keyType);
      }

      if (objLitType != null && declareOnOwner) {
        // Declare this property on its object literal.
        boolean isExtern = t.getInput() != null && t.getInput().isExtern();
        objLitType.defineDeclaredProperty(memberName, keyType, keyNode);
      }
    }
  }
}
 
Example 11
Source File: Closure_43_TypedScopeCreator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 * @param declareOnOwner If true, declare properties on the objLitType as
 *     well. If false, the caller should take crae of this.
 */
void processObjectLitProperties(
    Node objLit, ObjectType objLitType,
    boolean declareOnOwner) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType =
        getDeclaredType(keyNode.getSourceFileName(), info, keyNode, value);
    JSType keyType =  objLitType.isEnumType() ?
        objLitType.toMaybeEnumType().getElementsType() :
        NodeUtil.getObjectLitKeyTypeFromValueType(keyNode, valueType);

    // Try to declare this property in the current scope if it
    // has an authoritative name.
    String qualifiedName = NodeUtil.getBestLValueName(keyNode);
    if (qualifiedName != null) {
      boolean inferred = keyType == null;
      defineSlot(keyNode, objLit, qualifiedName, keyType, inferred);
    } else if (keyType != null) {
      setDeferredType(keyNode, keyType);
    }

    if (keyType != null && objLitType != null && declareOnOwner) {
      // Declare this property on its object literal.
      boolean isExtern = keyNode.isFromExterns();
      objLitType.defineDeclaredProperty(memberName, keyType, keyNode);
    }
  }
}
 
Example 12
Source File: TypeInferenceTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testPropertyInference3() {
  ObjectType thisType = registry.createAnonymousObjectType(null);
  thisType.defineDeclaredProperty("foo",
      createUndefinableType(STRING_TYPE), null);
  assumingThisType(thisType);
  inFunction("var y = 1; this.foo = x; y = this.foo;");
  verify("y", CHECKED_UNKNOWN_TYPE);
}
 
Example 13
Source File: TypedScopeCreator.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 * @param declareOnOwner If true, declare properties on the objLitType as
 *     well. If false, the caller should take care of this.
 */
void processObjectLitProperties(
    Node objLit, ObjectType objLitType,
    boolean declareOnOwner) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType =
        getDeclaredType(keyNode.getSourceFileName(), info, keyNode, value);
    JSType keyType =  objLitType.isEnumType() ?
        objLitType.toMaybeEnumType().getElementsType() :
        NodeUtil.getObjectLitKeyTypeFromValueType(keyNode, valueType);

    // Try to declare this property in the current scope if it
    // has an authoritative name.
    String qualifiedName = NodeUtil.getBestLValueName(keyNode);
    if (qualifiedName != null) {
      boolean inferred = keyType == null;
      defineSlot(keyNode, objLit, qualifiedName, keyType, inferred);
    } else if (keyType != null) {
      setDeferredType(keyNode, keyType);
    }

    if (keyType != null && objLitType != null && declareOnOwner) {
      // Declare this property on its object literal.
      boolean isExtern = keyNode.isFromExterns();
      objLitType.defineDeclaredProperty(memberName, keyType, keyNode);
    }
  }
}
 
Example 14
Source File: Closure_54_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Process an object literal and all the types on it.
 * @param objLit The OBJECTLIT node.
 * @param objLitType The type of the OBJECTLIT node. This might be a named
 *     type, because of the lends annotation.
 */
void processObjectLitProperties(
    NodeTraversal t, Node objLit, ObjectType objLitType) {
  for (Node keyNode = objLit.getFirstChild(); keyNode != null;
       keyNode = keyNode.getNext()) {
    Node value = keyNode.getFirstChild();
    String memberName = NodeUtil.getObjectLitKeyName(keyNode);
    JSDocInfo info = keyNode.getJSDocInfo();
    JSType valueType = getDeclaredType(
        t.getSourceName(), info, keyNode, value);
    JSType keyType = NodeUtil.getObjectLitKeyTypeFromValueType(
        keyNode, valueType);
    if (keyType != null) {
      // Try to declare this property in the current scope if it
      // has an authoritative name.
      String qualifiedName = NodeUtil.getBestLValueName(keyNode);
      if (qualifiedName != null) {
        defineSlot(keyNode, objLit, qualifiedName, keyType, false);
      } else {
        setDeferredType(keyNode, keyType);
      }

      if (objLitType != null) {
        // Declare this property on its object literal.
        boolean isExtern = t.getInput() != null && t.getInput().isExtern();
        objLitType.defineDeclaredProperty(
            memberName, keyType, keyNode);
      }
    }
  }
}
 
Example 15
Source File: Closure_95_TypedScopeCreator_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Defines a typed variable. The defining node will be annotated with the
 * variable's type of {@link JSTypeNative#UNKNOWN_TYPE} if its type is
 * inferred.
 *
 * Slots may be any variable or any qualified name in the global scope.
 *
 * @param n the defining NAME or GETPROP node.
 * @param parent the {@code n}'s parent.
 * @param type the variable's type. It may be {@code null} if
 *     {@code inferred} is {@code true}.
 */
void defineSlot(Node n, Node parent, JSType type, boolean inferred) {
  Preconditions.checkArgument(inferred || type != null);

  // Only allow declarations of NAMEs and qualfied names.
  boolean shouldDeclareOnGlobalThis = false;
  if (n.getType() == Token.NAME) {
    Preconditions.checkArgument(
        parent.getType() == Token.FUNCTION ||
        parent.getType() == Token.VAR ||
        parent.getType() == Token.LP ||
        parent.getType() == Token.CATCH);
    shouldDeclareOnGlobalThis = scope.isGlobal() &&
        (parent.getType() == Token.VAR ||
         parent.getType() == Token.FUNCTION);
  } else {
    Preconditions.checkArgument(
        n.getType() == Token.GETPROP &&
        (parent.getType() == Token.ASSIGN ||
         parent.getType() == Token.EXPR_RESULT));
  }
  String variableName = n.getQualifiedName();
  Preconditions.checkArgument(!variableName.isEmpty());

  // If n is a property, then we should really declare it in the
  // scope where the root object appears. This helps out people
  // who declare "global" names in an anonymous namespace.
  Scope scopeToDeclareIn = scope;

    // don't try to declare in the global scope if there's
    // already a symbol there with this name.

  // declared in closest scope?
  if (scopeToDeclareIn.isDeclared(variableName, false)) {
    Var oldVar = scopeToDeclareIn.getVar(variableName);
    validator.expectUndeclaredVariable(
        sourceName, n, parent, oldVar, variableName, type);
  } else {
    if (!inferred) {
      setDeferredType(n, type);
    }
    CompilerInput input = compiler.getInput(sourceName);
    scopeToDeclareIn.declare(variableName, n, type, input, inferred);

    if (shouldDeclareOnGlobalThis) {
      ObjectType globalThis =
          typeRegistry.getNativeObjectType(JSTypeNative.GLOBAL_THIS);
      boolean isExtern = input.isExtern();
      if (inferred) {
        globalThis.defineInferredProperty(variableName,
            type == null ?
                getNativeType(JSTypeNative.NO_TYPE) :
                type,
            isExtern);
      } else {
        globalThis.defineDeclaredProperty(variableName, type, isExtern);
      }
    }

    // If we're in the global scope, also declare var.prototype
    // in the scope chain.
    if (scopeToDeclareIn.isGlobal() && type instanceof FunctionType) {
      FunctionType fnType = (FunctionType) type;
      if (fnType.isConstructor() || fnType.isInterface()) {
        FunctionType superClassCtor = fnType.getSuperClassConstructor();
        scopeToDeclareIn.declare(variableName + ".prototype", n,
            fnType.getPrototype(), compiler.getInput(sourceName),
            /* declared iff there's an explicit supertype */
            superClassCtor == null ||
            superClassCtor.getInstanceType().equals(
                getNativeType(OBJECT_TYPE)));
      }
    }
  }
}
 
Example 16
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 17
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 18
Source File: Closure_25_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();
  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 19
Source File: Closure_95_TypedScopeCreator_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Defines a typed variable. The defining node will be annotated with the
 * variable's type of {@link JSTypeNative#UNKNOWN_TYPE} if its type is
 * inferred.
 *
 * Slots may be any variable or any qualified name in the global scope.
 *
 * @param n the defining NAME or GETPROP node.
 * @param parent the {@code n}'s parent.
 * @param type the variable's type. It may be {@code null} if
 *     {@code inferred} is {@code true}.
 */
void defineSlot(Node n, Node parent, JSType type, boolean inferred) {
  Preconditions.checkArgument(inferred || type != null);

  // Only allow declarations of NAMEs and qualfied names.
  boolean shouldDeclareOnGlobalThis = false;
  if (n.getType() == Token.NAME) {
    Preconditions.checkArgument(
        parent.getType() == Token.FUNCTION ||
        parent.getType() == Token.VAR ||
        parent.getType() == Token.LP ||
        parent.getType() == Token.CATCH);
    shouldDeclareOnGlobalThis = scope.isGlobal() &&
        (parent.getType() == Token.VAR ||
         parent.getType() == Token.FUNCTION);
  } else {
    Preconditions.checkArgument(
        n.getType() == Token.GETPROP &&
        (parent.getType() == Token.ASSIGN ||
         parent.getType() == Token.EXPR_RESULT));
  }
  String variableName = n.getQualifiedName();
  Preconditions.checkArgument(!variableName.isEmpty());

  // If n is a property, then we should really declare it in the
  // scope where the root object appears. This helps out people
  // who declare "global" names in an anonymous namespace.
  Scope scopeToDeclareIn = scope;
  if (n.getType() == Token.GETPROP && !scope.isGlobal() &&
      isQnameRootedInGlobalScope(n)) {
    Scope globalScope = scope.getGlobalScope();

    // don't try to declare in the global scope if there's
    // already a symbol there with this name.
    if (!globalScope.isDeclared(variableName, false)) {
      scopeToDeclareIn = scope.getGlobalScope();
    }
  }

  // declared in closest scope?
  if (scopeToDeclareIn.isDeclared(variableName, false)) {
    Var oldVar = scopeToDeclareIn.getVar(variableName);
    validator.expectUndeclaredVariable(
        sourceName, n, parent, oldVar, variableName, type);
  } else {
    if (!inferred) {
      setDeferredType(n, type);
    }
    CompilerInput input = compiler.getInput(sourceName);
    scopeToDeclareIn.declare(variableName, n, type, input, inferred);

    if (shouldDeclareOnGlobalThis) {
      ObjectType globalThis =
          typeRegistry.getNativeObjectType(JSTypeNative.GLOBAL_THIS);
      boolean isExtern = input.isExtern();
      if (inferred) {
        globalThis.defineInferredProperty(variableName,
            type == null ?
                getNativeType(JSTypeNative.NO_TYPE) :
                type,
            isExtern);
      } else {
        globalThis.defineDeclaredProperty(variableName, type, isExtern);
      }
    }

    // If we're in the global scope, also declare var.prototype
    // in the scope chain.
    if (scopeToDeclareIn.isGlobal() && type instanceof FunctionType) {
      FunctionType fnType = (FunctionType) type;
      if (fnType.isConstructor() || fnType.isInterface()) {
        FunctionType superClassCtor = fnType.getSuperClassConstructor();
        scopeToDeclareIn.declare(variableName + ".prototype", n,
            fnType.getPrototype(), compiler.getInput(sourceName),
            /* declared iff there's an explicit supertype */
            superClassCtor == null ||
            superClassCtor.getInstanceType().equals(
                getNativeType(OBJECT_TYPE)));
      }
    }
  }
}
 
Example 20
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);
      }
    }
  }
}