Search in sources :

Example 66 with JSTypeExpression

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

the class ClosureRewriteClass method mergeJsDocFor.

private JSDocInfo mergeJsDocFor(ClassDefinition cls, Node associatedNode) {
    // avoid null checks
    JSDocInfo classInfo = (cls.classInfo != null) ? cls.classInfo : new JSDocInfoBuilder(true).build(true);
    JSDocInfo ctorInfo = (cls.constructor.info != null) ? cls.constructor.info : new JSDocInfoBuilder(true).build(true);
    Node superNode = cls.superClass;
    // Start with a clone of the constructor info if there is one.
    JSDocInfoBuilder mergedInfo = cls.constructor.info != null ? JSDocInfoBuilder.copyFrom(ctorInfo) : new JSDocInfoBuilder(true);
    // 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(new JSTypeExpression(new Node(Token.BANG, IR.string(superNode.getQualifiedName())), VIRTUAL_FILE));
        }
        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 = new JSTypeExpression(new Node(Token.BANG, IR.string(superNode.getQualifiedName())), VIRTUAL_FILE);
            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
    List<String> templateNames = new ArrayList<>();
    templateNames.addAll(classInfo.getTemplateTypeNames());
    templateNames.addAll(ctorInfo.getTemplateTypeNames());
    for (String typeName : templateNames) {
        mergedInfo.recordTemplateTypeName(typeName);
    }
    return mergedInfo.build();
}
Also used : Node(com.google.javascript.rhino.Node) ArrayList(java.util.ArrayList) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) Visibility(com.google.javascript.rhino.JSDocInfo.Visibility) JSDocInfo(com.google.javascript.rhino.JSDocInfo) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder) HashSet(java.util.HashSet)

Example 67 with JSTypeExpression

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

the class Es6RewriteClass method visitNonMethodMember.

/**
 * Visits class members other than simple methods: Getters, setters, and computed properties.
 */
private void visitNonMethodMember(Node member, ClassDeclarationMetadata metadata) {
    if (member.isComputedProp() && member.isStaticMember()) {
        cannotConvertYet(member, "Static computed property");
        return;
    }
    if (member.isComputedProp() && !member.getFirstChild().isQualifiedName()) {
        cannotConvert(member.getFirstChild(), "Computed property with non-qualified-name key");
        return;
    }
    JSTypeExpression typeExpr = getTypeFromGetterOrSetter(member);
    addToDefinePropertiesObject(metadata, member);
    Map<String, JSDocInfo> membersToDeclare;
    String memberName;
    if (member.isComputedProp()) {
        checkState(!member.isStaticMember());
        membersToDeclare = metadata.prototypeComputedPropsToDeclare;
        memberName = member.getFirstChild().getQualifiedName();
    } else {
        membersToDeclare = member.isStaticMember() ? metadata.classMembersToDeclare : metadata.prototypeMembersToDeclare;
        memberName = member.getString();
    }
    JSDocInfo existingJSDoc = membersToDeclare.get(memberName);
    JSTypeExpression existingType = existingJSDoc == null ? null : existingJSDoc.getType();
    if (existingType != null && typeExpr != null && !existingType.equals(typeExpr)) {
        compiler.report(JSError.make(member, CONFLICTING_GETTER_SETTER_TYPE, memberName));
    } else {
        JSDocInfoBuilder jsDoc = new JSDocInfoBuilder(false);
        if (member.getJSDocInfo() != null && member.getJSDocInfo().isExport()) {
            jsDoc.recordExport();
            jsDoc.recordVisibility(Visibility.PUBLIC);
        }
        if (member.getJSDocInfo() != null && member.getJSDocInfo().isOverride()) {
            jsDoc.recordOverride();
        } else if (typeExpr == null) {
            typeExpr = new JSTypeExpression(new Node(Token.QMARK), member.getSourceFileName());
        }
        if (typeExpr != null) {
            jsDoc.recordType(typeExpr.copy());
        }
        if (member.isStaticMember() && !member.isComputedProp()) {
            jsDoc.recordNoCollapse();
        }
        membersToDeclare.put(memberName, jsDoc.build());
    }
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfo(com.google.javascript.rhino.JSDocInfo) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder)

Example 68 with JSTypeExpression

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

the class FunctionTypeBuilder method inferInheritance.

/**
 * Infer the role of the function (whether it's a constructor or interface)
 * and what it inherits from in JSDocInfo.
 */
FunctionTypeBuilder inferInheritance(@Nullable JSDocInfo info) {
    if (info != null) {
        isConstructor = info.isConstructor();
        isInterface = info.isInterface();
        isAbstract = info.isAbstract();
        makesStructs = info.makesStructs();
        makesDicts = info.makesDicts();
        if (makesStructs && !(isConstructor || isInterface)) {
            reportWarning(CONSTRUCTOR_REQUIRED, "@struct", formatFnName());
        } else if (makesDicts && !isConstructor) {
            reportWarning(CONSTRUCTOR_REQUIRED, "@dict", formatFnName());
        }
        // TODO(b/74253232): maybeGetNativeTypesOfBuiltin should also handle cases where a local type
        // declaration shadows a templatized native type.
        ImmutableList<TemplateType> nativeClassTemplateTypeNames = typeRegistry.maybeGetTemplateTypesOfBuiltin(fnName);
        ImmutableList<String> infoTemplateTypeNames = info.getTemplateTypeNames();
        // Preconditions check. It currently fails for "var symbol" in the externs.
        if (nativeClassTemplateTypeNames != null && infoTemplateTypeNames.size() == nativeClassTemplateTypeNames.size()) {
            classTemplateTypeNames = nativeClassTemplateTypeNames;
            typeRegistry.setTemplateTypeNames(classTemplateTypeNames);
        } else {
            // Otherwise, create new template type for
            // the template values of the constructor/interface
            // Class template types, which can be used in the scope of a constructor
            // definition.
            ImmutableList<String> typeParameters = info.getTemplateTypeNames();
            if (!typeParameters.isEmpty() && (isConstructor || isInterface)) {
                ImmutableList.Builder<TemplateType> builder = ImmutableList.builder();
                for (String typeParameter : typeParameters) {
                    builder.add(typeRegistry.createTemplateType(typeParameter));
                }
                classTemplateTypeNames = builder.build();
                typeRegistry.setTemplateTypeNames(classTemplateTypeNames);
            }
        }
        // base type
        if (info.hasBaseType()) {
            if (isConstructor) {
                JSType maybeBaseType = info.getBaseType().evaluate(scope, typeRegistry);
                if (maybeBaseType != null && maybeBaseType.setValidator(new ExtendedTypeValidator())) {
                    baseType = (ObjectType) maybeBaseType;
                }
            } else {
                reportWarning(EXTENDS_WITHOUT_TYPEDEF, formatFnName());
            }
        }
        // Implemented interfaces (for constructors only).
        if (info.getImplementedInterfaceCount() > 0) {
            if (isConstructor) {
                implementedInterfaces = new ArrayList<>();
                Set<JSType> baseInterfaces = new HashSet<>();
                for (JSTypeExpression t : info.getImplementedInterfaces()) {
                    JSType maybeInterType = t.evaluate(scope, typeRegistry);
                    if (maybeInterType != null && maybeInterType.setValidator(new ImplementedTypeValidator())) {
                        // Disallow implementing the same base (not templatized) interface
                        // type more than once.
                        JSType baseInterface = maybeInterType;
                        if (baseInterface.toMaybeTemplatizedType() != null) {
                            baseInterface = baseInterface.toMaybeTemplatizedType().getReferencedType();
                        }
                        if (!baseInterfaces.add(baseInterface)) {
                            reportWarning(SAME_INTERFACE_MULTIPLE_IMPLEMENTS, baseInterface.toString());
                        }
                        implementedInterfaces.add((ObjectType) maybeInterType);
                    }
                }
            } else if (isInterface) {
                reportWarning(TypeCheck.CONFLICTING_IMPLEMENTED_TYPE, formatFnName());
            } else {
                reportWarning(CONSTRUCTOR_REQUIRED, "@implements", formatFnName());
            }
        }
        // We've already emitted a warning if this is not an interface.
        if (isInterface) {
            extendedInterfaces = new ArrayList<>();
            for (JSTypeExpression t : info.getExtendedInterfaces()) {
                JSType maybeInterfaceType = t.evaluate(scope, typeRegistry);
                if (maybeInterfaceType != null && maybeInterfaceType.setValidator(new ExtendedTypeValidator())) {
                    extendedInterfaces.add((ObjectType) maybeInterfaceType);
                }
            }
        }
    }
    return this;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) ImmutableList(com.google.common.collect.ImmutableList) TemplateType(com.google.javascript.rhino.jstype.TemplateType) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) HashSet(java.util.HashSet)

Example 69 with JSTypeExpression

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

the class PolymerClassRewriter method rewritePolymerClassDeclaration.

/**
 * Rewrites a class which extends Polymer.Element to a set of declarations and assignments which
 * can be understood by the compiler.
 *
 * @param clazz The class node
 * @param cls The extracted {@link PolymerClassDefinition} for the Polymer element created by this
 *     call.
 */
void rewritePolymerClassDeclaration(Node clazz, final PolymerClassDefinition cls, boolean isInGlobalScope) {
    if (cls.descriptor != null) {
        addTypesToFunctions(cls.descriptor, cls.target.getQualifiedName(), cls.defType);
    }
    PolymerPassStaticUtils.switchDollarSignPropsToBrackets(NodeUtil.getClassMembers(clazz), compiler);
    for (MemberDefinition prop : cls.props) {
        if (prop.value.isObjectLit()) {
            PolymerPassStaticUtils.switchDollarSignPropsToBrackets(prop.value, compiler);
        }
    }
    // For simplicity add everything into a block, before adding it to the AST.
    Node block = IR.block();
    appendPropertiesToBlock(cls, block, cls.target.getQualifiedName() + ".prototype.");
    ImmutableList<MemberDefinition> readOnlyProps = parseReadOnlyProperties(cls, block);
    ImmutableList<MemberDefinition> attributeReflectedProps = parseAttributeReflectedProperties(cls);
    addInterfaceExterns(cls, readOnlyProps, attributeReflectedProps);
    // If an external interface is required, mark the class as implementing it
    if (!readOnlyProps.isEmpty() || !attributeReflectedProps.isEmpty()) {
        JSDocInfoBuilder classInfo = JSDocInfoBuilder.maybeCopyFrom(clazz.getJSDocInfo());
        String interfaceName = getInterfaceName(cls);
        JSTypeExpression interfaceType = new JSTypeExpression(new Node(Token.BANG, IR.string(interfaceName)), VIRTUAL_FILE);
        classInfo.recordImplementedInterface(interfaceType);
        clazz.setJSDocInfo(classInfo.build());
    }
    if (block.hasChildren()) {
        removePropertyDocs(cls.descriptor, cls.defType);
        Node stmt = NodeUtil.getEnclosingStatement(clazz);
        stmt.getParent().addChildrenAfter(block.removeChildren(), stmt);
        compiler.reportChangeToEnclosingScope(stmt);
    }
    addReturnTypeIfMissing(cls, "is", new JSTypeExpression(IR.string("string"), VIRTUAL_FILE));
    Node type = new Node(Token.BANG);
    Node array = IR.string("Array");
    type.addChildToBack(array);
    Node arrayTemplateType = new Node(Token.BLOCK, IR.string("string"));
    array.addChildToBack(arrayTemplateType);
    addReturnTypeIfMissing(cls, "observers", new JSTypeExpression(type, VIRTUAL_FILE));
    addReturnTypeIfMissing(cls, "properties", new JSTypeExpression(IR.string(POLYMER_ELEMENT_PROP_CONFIG), VIRTUAL_FILE));
    // with the class members.
    if (propertyRenamingEnabled && cls.descriptor != null) {
        addObjectReflectionCall(cls, cls.descriptor);
    }
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

Example 70 with JSTypeExpression

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

the class PolymerClassRewriter method addInterfaceExterns.

/**
 * Adds an interface for the given ClassDefinition to externs. This allows generated setter
 * functions for read-only properties to avoid renaming altogether.
 *
 * @see https://www.polymer-project.org/0.8/docs/devguide/properties.html#read-only
 */
private void addInterfaceExterns(final PolymerClassDefinition cls, List<MemberDefinition> readOnlyProps, List<MemberDefinition> attributeReflectedProps) {
    Node block = IR.block();
    String interfaceName = getInterfaceName(cls);
    Node fnNode = NodeUtil.emptyFunction();
    compiler.reportChangeToChangeScope(fnNode);
    Node varNode = IR.var(NodeUtil.newQName(compiler, interfaceName), fnNode);
    JSDocInfoBuilder info = new JSDocInfoBuilder(true);
    info.recordInterface();
    varNode.setJSDocInfo(info.build());
    block.addChildToBack(varNode);
    if (polymerVersion == 1) {
        // For Polymer 1, all declared properties are non-renameable
        appendPropertiesToBlock(cls, block, interfaceName + ".prototype.");
    } else {
        List<MemberDefinition> interfaceProperties = new ArrayList<>();
        interfaceProperties.addAll(readOnlyProps);
        if (attributeReflectedProps != null) {
            interfaceProperties.addAll(attributeReflectedProps);
        }
        // For Polymer 2, only read-only properties and reflectToAttribute properties are
        // non-renameable. Other properties follow the ALL_UNQUOTED renaming rules.
        PolymerClassDefinition tmpDef = new PolymerClassDefinition(cls.defType, cls.definition, cls.target, cls.descriptor, null, null, null, interfaceProperties, null, null);
        // disallow renaming of readonly properties
        appendPropertiesToBlock(tmpDef, block, interfaceName + ".prototype.");
    }
    for (MemberDefinition prop : readOnlyProps) {
        // Add all _set* functions to avoid renaming.
        String propName = prop.name.getString();
        String setterName = "_set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
        Node setterExprNode = IR.exprResult(NodeUtil.newQName(compiler, interfaceName + ".prototype." + setterName));
        JSDocInfoBuilder setterInfo = new JSDocInfoBuilder(true);
        JSTypeExpression propType = PolymerPassStaticUtils.getTypeFromProperty(prop, compiler);
        setterInfo.recordParameter(propName, propType);
        setterExprNode.getFirstChild().setJSDocInfo(setterInfo.build());
        block.addChildToBack(setterExprNode);
    }
    block.useSourceInfoIfMissingFromForTree(polymerElementExterns);
    Node scopeRoot = polymerElementExterns;
    if (!scopeRoot.isScript()) {
        scopeRoot = scopeRoot.getParent();
    }
    Node stmts = block.removeChildren();
    scopeRoot.addChildrenToBack(stmts);
    compiler.reportChangeToEnclosingScope(stmts);
}
Also used : Node(com.google.javascript.rhino.Node) ArrayList(java.util.ArrayList) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

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