Search in sources :

Example 46 with JSTypeExpression

use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.

the class CheckMissingOverrideTypes method recordMissingParamAnnotations.

private void recordMissingParamAnnotations(Node fnNode, JSDocInfo jsDoc, FunctionType fnType, JSDocInfo.Builder builder) {
    checkState(fnNode.isFunction(), fnNode);
    Set<String> jsDocParamNames = jsDoc.getParameterNames();
    List<String> astParamNames = getFunctionParamNamesOrPlaceholder(fnNode);
    List<Parameter> fnTypeParams = fnType.getParameters();
    for (int paramIndex = 0; paramIndex < astParamNames.size(); paramIndex++) {
        String astName = astParamNames.get(paramIndex);
        if (jsDocParamNames.contains(astName)) {
            continue;
        }
        // missing annotation for `paramName`
        Parameter fnTypeParam = fnTypeParams.get(paramIndex);
        JSType paramType = fnTypeParam.getJSType();
        if (fnTypeParam.isOptional()) {
            paramType = paramType.restrictByNotUndefined();
        }
        Node paramTypeAst = typeToTypeAst(paramType);
        if (fnTypeParam.isOptional()) {
            paramTypeAst = new Node(Token.EQUALS, paramTypeAst);
        }
        builder.recordParameter(astName, new JSTypeExpression(paramTypeAst, JSDOC_FILE_NAME));
    }
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) Parameter(com.google.javascript.rhino.jstype.FunctionType.Parameter) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression)

Example 47 with JSTypeExpression

use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.

the class ClosureRewriteClass method mergeJsDocFor.

/**
 * Merges the JSDoc from the class and constructor into a single function-level JSDoc
 *
 * @param includeConstructorExport if false, disregards the @export JSDoc from the constructor, if
 *     any. This is a workaround for b/138324343.
 */
private JSDocInfo mergeJsDocFor(ClassDefinition cls, Node associatedNode, boolean includeConstructorExport) {
    // avoid null checks
    JSDocInfo classInfo = (cls.classInfo != null) ? cls.classInfo : JSDocInfo.builder().parseDocumentation().build(true);
    JSDocInfo ctorInfo = (cls.constructor.info != null) ? cls.constructor.info : JSDocInfo.builder().parseDocumentation().build(true);
    Node superNode = cls.superClass;
    // Start with a clone of the constructor info if there is one.
    JSDocInfo.Builder mergedInfo = cls.constructor.info != null ? JSDocInfo.Builder.copyFrom(ctorInfo) : JSDocInfo.builder().parseDocumentation();
    // TODO(b/138324343): remove this case (or, even better, just delete goog.defineClass support).
    if (!includeConstructorExport && ctorInfo.isExport()) {
        mergedInfo.removeExport();
    }
    // merge block description
    String blockDescription = Joiner.on("\n").skipNulls().join(classInfo.getBlockDescription(), ctorInfo.getBlockDescription());
    if (!blockDescription.isEmpty()) {
        mergedInfo.recordBlockDescription(blockDescription);
    }
    // merge suppressions
    Set<String> suppressions = new HashSet<>();
    suppressions.addAll(classInfo.getSuppressions());
    suppressions.addAll(ctorInfo.getSuppressions());
    if (!suppressions.isEmpty()) {
        mergedInfo.recordSuppressions(suppressions);
    }
    // Use class deprecation if set.
    if (classInfo.isDeprecated()) {
        mergedInfo.recordDeprecated();
    }
    String deprecationReason = null;
    if (classInfo.getDeprecationReason() != null) {
        deprecationReason = classInfo.getDeprecationReason();
        mergedInfo.recordDeprecationReason(deprecationReason);
    }
    // Use class visibility if specifically set
    Visibility visibility = classInfo.getVisibility();
    if (visibility != null && visibility != JSDocInfo.Visibility.INHERITED) {
        mergedInfo.recordVisibility(classInfo.getVisibility());
    }
    if (classInfo.isAbstract()) {
        mergedInfo.recordAbstract();
    }
    if (classInfo.isConstant()) {
        mergedInfo.recordConstancy();
    }
    if (classInfo.isExport()) {
        mergedInfo.recordExport();
    }
    // If @ngInject is on the ctor, it's already been copied above.
    if (classInfo.isNgInject()) {
        compiler.report(JSError.make(associatedNode, GOOG_CLASS_NG_INJECT_ON_CLASS));
        mergedInfo.recordNgInject(true);
    }
    if (classInfo.makesUnrestricted() || ctorInfo.makesUnrestricted()) {
        mergedInfo.recordUnrestricted();
    } else if (classInfo.makesDicts() || ctorInfo.makesDicts()) {
        mergedInfo.recordDict();
    } else {
        // @struct by default
        mergedInfo.recordStruct();
    }
    // @constructor is implied, @interface must be explicit
    boolean isInterface = classInfo.isInterface() || ctorInfo.isInterface();
    if (isInterface) {
        if (classInfo.usesImplicitMatch() || ctorInfo.usesImplicitMatch()) {
            mergedInfo.recordImplicitMatch();
        } else {
            mergedInfo.recordInterface();
        }
        List<JSTypeExpression> extendedInterfaces = null;
        if (classInfo.getExtendedInterfacesCount() > 0) {
            extendedInterfaces = classInfo.getExtendedInterfaces();
        } else if (ctorInfo.getExtendedInterfacesCount() == 0 && superNode != null) {
            extendedInterfaces = ImmutableList.of(getSuperclassFor(superNode));
        }
        if (extendedInterfaces != null) {
            for (JSTypeExpression extend : extendedInterfaces) {
                mergedInfo.recordExtendedInterface(extend);
            }
        }
    } else {
        // @constructor by default
        mergedInfo.recordConstructor();
        if (classInfo.getBaseType() != null) {
            mergedInfo.recordBaseType(classInfo.getBaseType());
        } else if (superNode != null) {
            // a "super" implies @extends, build a default.
            JSTypeExpression baseType = getSuperclassFor(superNode);
            mergedInfo.recordBaseType(baseType);
        }
        // @implements from the class if they exist
        List<JSTypeExpression> interfaces = classInfo.getImplementedInterfaces();
        for (JSTypeExpression implemented : interfaces) {
            mergedInfo.recordImplementedInterface(implemented);
        }
    }
    // merge @template types if they exist
    ImmutableMap<String, JSTypeExpression> classTemplates = classInfo.getTemplateTypes();
    ImmutableMap<String, JSTypeExpression> ctorTemplates = ctorInfo.getTemplateTypes();
    for (Map.Entry<String, JSTypeExpression> entry : classTemplates.entrySet()) {
        mergedInfo.recordTemplateTypeName(entry.getKey(), entry.getValue());
    }
    for (Map.Entry<String, JSTypeExpression> entry : ctorTemplates.entrySet()) {
        mergedInfo.recordTemplateTypeName(entry.getKey(), entry.getValue());
    }
    return mergedInfo.build();
}
Also used : Node(com.google.javascript.rhino.Node) JSDocInfo(com.google.javascript.rhino.JSDocInfo) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) Visibility(com.google.javascript.rhino.JSDocInfo.Visibility) ImmutableMap(com.google.common.collect.ImmutableMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 48 with JSTypeExpression

use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.

the class CheckGlobalThis method shouldTraverse.

/**
 * 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()) {
        // is the global "this", not an instance of Foo.
        if (n.isArrowFunction()) {
            return true;
        }
        // Don't traverse functions that are constructors or have the @this
        // or @override annotation.
        JSDocInfo jsDoc = NodeUtil.getBestJSDocInfo(n);
        if (jsDoc != null && (jsDoc.isConstructor() || jsDoc.isInterface() || jsDoc.hasThisType() || jsDoc.isOverride())) {
            return false;
        }
        if (jsDoc != null) {
            JSTypeExpression functionType = jsDoc.getType();
            if (functionType != null) {
                Node functionNode = functionType.getRoot();
                if (functionNode != null && functionNode.isFunction()) {
                    // function(this: ThisType, ...)
                    // `this:` is only allowed as the very first child of the
                    // FUNCTION node.
                    Node thisNode = functionNode.getFirstChild();
                    if (thisNode != null && thisNode.isThis()) {
                        // Type of `this` is specified, so no need to check further.
                        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() {}};
        Token pType = parent.getToken();
        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 grandparent = parent.getParent();
        if (NodeUtil.mayBeObjectLitKey(parent)) {
            JSDocInfo maybeLends = grandparent.getJSDocInfo();
            if (maybeLends != null && maybeLends.hasLendsName() && maybeLends.getLendsName().getRoot().getString().endsWith(".prototype")) {
                return false;
            }
        }
    }
    if (parent != null && parent.isAssign()) {
        Node lhs = parent.getFirstChild();
        if (n == lhs) {
            // assignLhsChild should not be overridden.
            if (assignLhsChild == null) {
                assignLhsChild = lhs;
            }
        } else {
            // property or subproperty.
            if (NodeUtil.isNormalGet(lhs)) {
                if (lhs.isGetProp() && lhs.getString().equals("prototype")) {
                    return false;
                }
                Node llhs = lhs.getFirstChild();
                if (llhs.isGetProp() && llhs.getString().equals("prototype")) {
                    return false;
                }
            }
        }
    }
    return true;
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) Token(com.google.javascript.rhino.Token) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Example 49 with JSTypeExpression

use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.

the class CheckMissingRequires method visitJsDocInfo.

private void visitJsDocInfo(NodeTraversal t, ModuleMetadata currentModule, JSDocInfo info) {
    // Collect template parameter names before checking, so that annotations on the same node that
    // reference the name are excluded from the check.
    templateParamNames.addAll(info.getTemplateTypeNames());
    templateParamNames.addAll(info.getTypeTransformations().keySet());
    if (info.hasType()) {
        visitJsDocExpr(t, currentModule, info.getType(), /* isStrongReference */
        false);
    }
    for (String param : info.getParameterNames()) {
        if (info.hasParameterType(param)) {
            visitJsDocExpr(t, currentModule, info.getParameterType(param), /* isStrongReference=*/
            false);
        }
    }
    if (info.hasReturnType()) {
        visitJsDocExpr(t, currentModule, info.getReturnType(), /* isStrongReference=*/
        false);
    }
    if (info.hasEnumParameterType()) {
        visitJsDocExpr(t, currentModule, info.getEnumParameterType(), /* isStrongReference=*/
        false);
    }
    if (info.hasTypedefType()) {
        visitJsDocExpr(t, currentModule, info.getTypedefType(), /* isStrongReference=*/
        false);
    }
    if (info.hasThisType()) {
        visitJsDocExpr(t, currentModule, info.getThisType(), /* isStrongReference=*/
        false);
    }
    if (info.hasBaseType()) {
        // Note that `@extends` requires a goog.require, not a goog.requireType.
        visitJsDocExpr(t, currentModule, info.getBaseType(), /* isStrongReference=*/
        true);
    }
    for (JSTypeExpression expr : info.getExtendedInterfaces()) {
        // Note that `@extends` requires a goog.require, not a goog.requireType.
        visitJsDocExpr(t, currentModule, expr, /* isStrongReference=*/
        true);
    }
    for (JSTypeExpression expr : info.getImplementedInterfaces()) {
        // Note that `@implements` requires a goog.require, not a goog.requireType.
        visitJsDocExpr(t, currentModule, expr, /* isStrongReference=*/
        true);
    }
}
Also used : JSTypeExpression(com.google.javascript.rhino.JSTypeExpression)

Example 50 with JSTypeExpression

use of com.google.javascript.rhino.JSTypeExpression in project closure-compiler by google.

the class CheckJSDocStyle method checkInlineParams.

/**
 * Checks that the inline type annotations are correct.
 */
private void checkInlineParams(NodeTraversal t, Node function, JSDocInfo fnJSDoc) {
    Node paramList = NodeUtil.getFunctionParameters(function);
    for (Node param = paramList.getFirstChild(); param != null; param = param.getNext()) {
        JSDocInfo jsDoc = param.isDefaultValue() ? param.getFirstChild().getJSDocInfo() : param.getJSDocInfo();
        if (jsDoc == null) {
            compiler.report(JSError.make(param, MISSING_PARAMETER_JSDOC, fnJSDoc != null && fnJSDoc.isOverride() ? "" : ""));
            return;
        } else {
            JSTypeExpression paramType = jsDoc.getType();
            checkNotNull(paramType, "Inline JSDoc info should always have a type");
            checkParam(t, param, null, paramType);
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Aggregations

JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)101 Node (com.google.javascript.rhino.Node)67 JSDocInfo (com.google.javascript.rhino.JSDocInfo)58 Test (org.junit.Test)26 JSDocInfoBuilder (com.google.javascript.rhino.JSDocInfoBuilder)18 MemberDefinition (com.google.javascript.jscomp.PolymerPass.MemberDefinition)9 JSType (com.google.javascript.rhino.jstype.JSType)9 ArrayList (java.util.ArrayList)8 TypeDeclarationNode (com.google.javascript.rhino.Node.TypeDeclarationNode)7 Map (java.util.Map)6 NodeSubject.assertNode (com.google.javascript.jscomp.testing.NodeSubject.assertNode)4 HashMap (java.util.HashMap)4 HashSet (java.util.HashSet)4 ImmutableList (com.google.common.collect.ImmutableList)3 ImmutableMap (com.google.common.collect.ImmutableMap)3 Visibility (com.google.javascript.rhino.JSDocInfo.Visibility)3 LinkedHashMap (java.util.LinkedHashMap)3 ImmutableSet (com.google.common.collect.ImmutableSet)2 Name (com.google.javascript.jscomp.GlobalNamespace.Name)2 Ref (com.google.javascript.jscomp.GlobalNamespace.Ref)2