Java Code Examples for com.google.javascript.rhino.JSDocInfo#isOverride()

The following examples show how to use com.google.javascript.rhino.JSDocInfo#isOverride() . 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: DeclarationGenerator.java    From clutz with MIT License 4 votes vote down vote up
/**
 * Closure has an experimental feature - Type Transformation Expression (TTE) - used to type
 * functions like Promise.then and Promise.all. The feature is rarely used and impossible to
 * translate to TS, so we just hard code some type signature. Yuk!
 *
 * <p>This is a hack and won't scale, but I hope TTE will have very limited usage.
 *
 * <p>Returns whether this was a TTE function and handled specially.
 */
private boolean handleSpecialTTEFunctions(
    JSType type, String propName, boolean isStatic, List<String> classTemplateTypeNames) {
  FunctionType ftype = type.toMaybeFunctionType();
  if (ftype == null) return false;

  boolean hasTTE = false;
  for (TemplateType templateKey : ftype.getTemplateTypeMap().getTemplateKeys()) {
    if (templateKey.getTypeTransformation() != null) {
      hasTTE = true;
      break;
    }
  }

  // Horrible hack.  goog.async.Deferred has an @override of a TTE function, but because we
  // run with partial inputs we can't see that.  Identify it by grabbing:
  // 1) functions named .then()
  // 2) that use @override
  // 3) that have no declared parameters/return type.
  boolean horribleHackForOverrides = false;
  JSDocInfo info = type.getJSDocInfo();
  if (info != null) {
    boolean isUntypedOverride =
        info.isOverride() && info.getParameterCount() == 0 && info.getReturnType() == null;
    if (isUntypedOverride && propName.equals("then")) {
      horribleHackForOverrides = true;
    }
  }

  if (!horribleHackForOverrides && !hasTTE) return false;

  // The same signature can be found in a number of classes - es6 Promise, angular.$q.Promise,
  // custom Thenable classes, etc. While the class names differ the implementations are close
  // enough that we use the same signature for all of them.
  // Only customization needed is plugging in the correct class name.
  String templateTypeSig =
      isStatic
          ? getSignatureForStaticTTEFn(propName, ftype)
          : getSignatureForInstanceTTEFn(propName, classTemplateTypeNames, ftype);
  if (templateTypeSig == null) {
    emit("/* function had TTE, but not a known translation. Emitted type is likely wrong. */");
    emitBreak();
    return false;
  }
  emit(templateTypeSig);
  emitBreak();
  return true;
}
 
Example 2
Source File: Closure_99_CheckGlobalThis_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Since this pass reports errors only when a global {@code this} keyword
 * is encountered, there is no reason to traverse non global contexts.
 */
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.getType() == Token.FUNCTION) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.isInterface() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN)) {
      return false;
    }
  }

  if (parent != null && parent.getType() == Token.ASSIGN) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();
    
    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
      if (NodeUtil.isGet(lhs)) {
        if (lhs.getType() == Token.GETPROP &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        Node llhs = lhs.getFirstChild();
        if (llhs.getType() == Token.GETPROP &&
            llhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
      }
    }
  }

  return true;
}
 
Example 3
Source File: Closure_99_CheckGlobalThis_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Since this pass reports errors only when a global {@code this} keyword
 * is encountered, there is no reason to traverse non global contexts.
 */
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.getType() == Token.FUNCTION) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN)) {
      return false;
    }
  }

  if (parent != null && parent.getType() == Token.ASSIGN) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();
    
    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
        if (lhs.getType() == Token.GETPROP &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        if (lhs.getQualifiedName() != null && lhs.getQualifiedName().contains(".prototype.")) {
          return false;
        }
    }
  }

  return true;
}
 
Example 4
Source File: Closure_91_CheckGlobalThis_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Since this pass reports errors only when a global {@code this} keyword
 * is encountered, there is no reason to traverse non global contexts.
 */
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.getType() == Token.FUNCTION) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.isInterface() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {}; // or
    // var a = {x: function() {}};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN ||

          // object literal keys
          pType == Token.STRING ||
          pType == Token.NUMBER)) {
      return false;
    }

    // Don't traverse functions that are getting lent to a prototype.
    Node gramps = parent.getParent();
    if (NodeUtil.isObjectLitKey(parent, gramps)) {
      JSDocInfo maybeLends = gramps.getJSDocInfo();
      if (maybeLends != null &&
          maybeLends.getLendsName() != null &&
          maybeLends.getLendsName().endsWith(".prototype")) {
        return false;
      }
    }
  }

  if (parent != null && parent.getType() == Token.ASSIGN) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();

    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
      if (NodeUtil.isGet(lhs)) {
        if (lhs.getType() == Token.GETPROP &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        Node llhs = lhs.getFirstChild();
        if (llhs.getType() == Token.GETPROP &&
            llhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
      }
    }
  }

  return true;
}
 
Example 5
Source File: Closure_91_CheckGlobalThis_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Since this pass reports errors only when a global {@code this} keyword
 * is encountered, there is no reason to traverse non global contexts.
 */
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.getType() == Token.FUNCTION) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.isInterface() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {}; // or
    // var a = {x: function() {}};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN ||

          // object literal keys
          pType == Token.STRING ||
          pType == Token.NUMBER)) {
      return false;
    }

    // Don't traverse functions that are getting lent to a prototype.
  }

  if (parent != null && parent.getType() == Token.ASSIGN) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();

    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
      if (NodeUtil.isGet(lhs)) {
        if (lhs.getType() == Token.GETPROP &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        Node llhs = lhs.getFirstChild();
        if (llhs.getType() == Token.GETPROP &&
            llhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
      }
    }
  }

  return true;
}
 
Example 6
Source File: Closure_96_TypeCheck_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Given a constructor type and a property name, check that the property has
 * the JSDoc annotation @override iff the property is declared on a
 * superclass. Several checks regarding inheritance correctness are also
 * performed.
 */
private void checkDeclaredPropertyInheritance(
    NodeTraversal t, Node n, FunctionType ctorType, String propertyName,
    JSDocInfo info, JSType propertyType) {
  // TODO(user): We're not 100% confident that type-checking works,
  // so we return quietly if the unknown type is a superclass of this type.
  // Remove this check as we become more confident. We should flag a warning
  // when the unknown type is on the inheritance chain, as it is likely
  // because of a programmer error.
  if (ctorType.hasUnknownSupertype()) {
    return;
  }

  FunctionType superClass = ctorType.getSuperClassConstructor();
  boolean superClassHasProperty = superClass != null &&
      superClass.getPrototype().hasProperty(propertyName);
  boolean declaredOverride = info != null && info.isOverride();

  boolean foundInterfaceProperty = false;
  if (ctorType.isConstructor()) {
    for (JSType implementedInterface : ctorType.getImplementedInterfaces()) {
      if (implementedInterface.isUnknownType()) {
        continue;
      }
      FunctionType interfaceType =
          implementedInterface.toObjectType().getConstructor();
      boolean interfaceHasProperty =
          interfaceType.getPrototype().hasProperty(propertyName);
      foundInterfaceProperty = foundInterfaceProperty || interfaceHasProperty;
      if (reportMissingOverride.isOn() && !declaredOverride &&
          interfaceHasProperty) {
        // @override not present, but the property does override an interface
        // property
        compiler.report(t.makeError(n, reportMissingOverride,
            HIDDEN_INTERFACE_PROPERTY, propertyName,
            interfaceType.getTopMostDefiningType(propertyName).toString()));
      }
      if (!declaredOverride) {
        continue;
      }
      // @override is present and we have to check that it is ok
      if (interfaceHasProperty) {
        JSType interfacePropType =
            interfaceType.getPrototype().getPropertyType(propertyName);
        if (!propertyType.canAssignTo(interfacePropType)) {
          compiler.report(t.makeError(n,
              HIDDEN_INTERFACE_PROPERTY_MISMATCH, propertyName,
              interfaceType.getTopMostDefiningType(propertyName).toString(),
              interfacePropType.toString(), propertyType.toString()));
        }
      }
    }
  }

  if (!declaredOverride && !superClassHasProperty) {
    // nothing to do here, it's just a plain new property
    return;
  }

  JSType topInstanceType = superClassHasProperty ?
      superClass.getTopMostDefiningType(propertyName) : null;
  if (reportMissingOverride.isOn() && ctorType.isConstructor() &&
      !declaredOverride && superClassHasProperty) {
    // @override not present, but the property does override a superclass
    // property
    compiler.report(t.makeError(n, reportMissingOverride,
        HIDDEN_SUPERCLASS_PROPERTY, propertyName,
        topInstanceType.toString()));
  }
  if (!declaredOverride) {
    // there's no @override to check
    return;
  }
  // @override is present and we have to check that it is ok
  if (superClassHasProperty) {
    // there is a superclass implementation
    JSType superClassPropType =
        superClass.getPrototype().getPropertyType(propertyName);
    if (!propertyType.canAssignTo(superClassPropType)) {
      compiler.report(
          t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY_MISMATCH,
              propertyName, topInstanceType.toString(),
              superClassPropType.toString(), propertyType.toString()));
    }
  } else if (!foundInterfaceProperty) {
    // there is no superclass nor interface implementation
    compiler.report(
        t.makeError(n, UNKNOWN_OVERRIDE,
            propertyName, ctorType.getInstanceType().toString()));
  }
}
 
Example 7
Source File: Closure_96_TypeCheck_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Given a constructor type and a property name, check that the property has
 * the JSDoc annotation @override iff the property is declared on a
 * superclass. Several checks regarding inheritance correctness are also
 * performed.
 */
private void checkDeclaredPropertyInheritance(
    NodeTraversal t, Node n, FunctionType ctorType, String propertyName,
    JSDocInfo info, JSType propertyType) {
  // TODO(user): We're not 100% confident that type-checking works,
  // so we return quietly if the unknown type is a superclass of this type.
  // Remove this check as we become more confident. We should flag a warning
  // when the unknown type is on the inheritance chain, as it is likely
  // because of a programmer error.
  if (ctorType.hasUnknownSupertype()) {
    return;
  }

  FunctionType superClass = ctorType.getSuperClassConstructor();
  boolean superClassHasProperty = superClass != null &&
      superClass.getPrototype().hasProperty(propertyName);
  boolean declaredOverride = info != null && info.isOverride();

  boolean foundInterfaceProperty = false;
  if (ctorType.isConstructor()) {
    for (JSType implementedInterface : ctorType.getImplementedInterfaces()) {
      if (implementedInterface.isUnknownType()) {
        continue;
      }
      FunctionType interfaceType =
          implementedInterface.toObjectType().getConstructor();
      boolean interfaceHasProperty =
          interfaceType.getPrototype().hasProperty(propertyName);
      foundInterfaceProperty = foundInterfaceProperty || interfaceHasProperty;
      if (reportMissingOverride.isOn() && !declaredOverride &&
          interfaceHasProperty) {
        // @override not present, but the property does override an interface
        // property
        compiler.report(t.makeError(n, reportMissingOverride,
            HIDDEN_INTERFACE_PROPERTY, propertyName,
            interfaceType.getTopMostDefiningType(propertyName).toString()));
      }
      if (!declaredOverride) {
        continue;
      }
      // @override is present and we have to check that it is ok
      if (interfaceHasProperty) {
        JSType interfacePropType =
            interfaceType.getPrototype().getPropertyType(propertyName);
        if (!propertyType.canAssignTo(interfacePropType)) {
          compiler.report(t.makeError(n,
              HIDDEN_INTERFACE_PROPERTY_MISMATCH, propertyName,
              interfaceType.getTopMostDefiningType(propertyName).toString(),
              interfacePropType.toString(), propertyType.toString()));
        }
      }
    }
  }

  if (!declaredOverride && !superClassHasProperty) {
    // nothing to do here, it's just a plain new property
    return;
  }

  JSType topInstanceType = superClassHasProperty ?
      superClass.getTopMostDefiningType(propertyName) : null;
  if (reportMissingOverride.isOn() && ctorType.isConstructor() &&
      !declaredOverride && superClassHasProperty) {
    // @override not present, but the property does override a superclass
    // property
    compiler.report(t.makeError(n, reportMissingOverride,
        HIDDEN_SUPERCLASS_PROPERTY, propertyName,
        topInstanceType.toString()));
  }
  if (!declaredOverride) {
    // there's no @override to check
    return;
  }
  // @override is present and we have to check that it is ok
  if (superClassHasProperty) {
    // there is a superclass implementation
    JSType superClassPropType =
        superClass.getPrototype().getPropertyType(propertyName);
    if (!propertyType.canAssignTo(superClassPropType)) {
      compiler.report(
          t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY_MISMATCH,
              propertyName, topInstanceType.toString(),
              superClassPropType.toString(), propertyType.toString()));
    }
  } else if (!foundInterfaceProperty) {
    // there is no superclass nor interface implementation
    compiler.report(
        t.makeError(n, UNKNOWN_OVERRIDE,
            propertyName, ctorType.getInstanceType().toString()));
  }
}
 
Example 8
Source File: CheckGlobalThis.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Since this pass reports errors only when a global {@code this} keyword
 * is encountered, there is no reason to traverse non global contexts.
 */
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.isFunction()) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.isInterface() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {}; // or
    // var a = {x: function() {}};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN ||

          // object literal keys
          pType == Token.STRING_KEY)) {
      return false;
    }

    // Don't traverse functions that are getting lent to a prototype.
    Node gramps = parent.getParent();
    if (NodeUtil.isObjectLitKey(parent, gramps)) {
      JSDocInfo maybeLends = gramps.getJSDocInfo();
      if (maybeLends != null &&
          maybeLends.getLendsName() != null &&
          maybeLends.getLendsName().endsWith(".prototype")) {
        return false;
      }
    }
  }

  if (parent != null && parent.isAssign()) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();

    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
      if (NodeUtil.isGet(lhs)) {
        if (lhs.isGetProp() &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        Node llhs = lhs.getFirstChild();
        if (llhs.isGetProp() &&
            llhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
      }
    }
  }

  return true;
}