use of com.google.javascript.rhino.JSDocInfoBuilder in project closure-compiler by google.
the class EarlyEs6ToEs3Converter method visitRestParam.
/**
* Processes a rest parameter
*/
private void visitRestParam(NodeTraversal t, Node restParam, Node paramList) {
Node functionBody = paramList.getNext();
int restIndex = paramList.getIndexOfChild(restParam);
String paramName = restParam.getFirstChild().getString();
Node nameNode = IR.name(paramName);
nameNode.setVarArgs(true);
nameNode.setJSDocInfo(restParam.getJSDocInfo());
paramList.replaceChild(restParam, nameNode);
// Make sure rest parameters are typechecked
JSTypeExpression type = null;
JSDocInfo info = restParam.getJSDocInfo();
JSDocInfo functionInfo = NodeUtil.getBestJSDocInfo(paramList.getParent());
if (info != null) {
type = info.getType();
} else {
if (functionInfo != null) {
type = functionInfo.getParameterType(paramName);
}
}
if (type != null && type.getRoot().getToken() != Token.ELLIPSIS) {
compiler.report(JSError.make(restParam, BAD_REST_PARAMETER_ANNOTATION));
}
if (!functionBody.hasChildren()) {
// If function has no body, we are done!
t.reportCodeChange();
return;
}
Node newBlock = IR.block().useSourceInfoFrom(functionBody);
Node name = IR.name(paramName);
Node let = IR.let(name, IR.name(REST_PARAMS)).useSourceInfoIfMissingFromForTree(functionBody);
newBlock.addChildToFront(let);
for (Node child : functionBody.children()) {
newBlock.addChildToBack(child.detach());
}
if (type != null) {
Node arrayType = IR.string("Array");
Node typeNode = type.getRoot();
Node memberType = typeNode.getToken() == Token.ELLIPSIS ? typeNode.getFirstChild().cloneTree() : typeNode.cloneTree();
if (functionInfo != null) {
memberType = replaceTypeVariablesWithUnknown(functionInfo, memberType);
}
arrayType.addChildToFront(new Node(Token.BLOCK, memberType).useSourceInfoIfMissingFrom(typeNode));
JSDocInfoBuilder builder = new JSDocInfoBuilder(false);
builder.recordType(new JSTypeExpression(new Node(Token.BANG, arrayType), restParam.getSourceFileName()));
name.setJSDocInfo(builder.build());
}
// TODO(b/74074478): Use a general utility method instead of an inlined loop.
Node newArr = IR.var(IR.name(REST_PARAMS), IR.arraylit());
functionBody.addChildToFront(newArr.useSourceInfoIfMissingFromForTree(restParam));
Node init = IR.var(IR.name(REST_INDEX), IR.number(restIndex));
Node cond = IR.lt(IR.name(REST_INDEX), IR.getprop(IR.name("arguments"), IR.string("length")));
Node incr = IR.inc(IR.name(REST_INDEX), false);
Node body = IR.block(IR.exprResult(IR.assign(IR.getelem(IR.name(REST_PARAMS), IR.sub(IR.name(REST_INDEX), IR.number(restIndex))), IR.getelem(IR.name("arguments"), IR.name(REST_INDEX)))));
functionBody.addChildAfter(IR.forNode(init, cond, incr, body).useSourceInfoIfMissingFromForTree(restParam), newArr);
functionBody.addChildToBack(newBlock);
compiler.reportChangeToEnclosingScope(newBlock);
// For now, we are running transpilation before type-checking, so we'll
// need to make sure changes don't invalidate the JSDoc annotations.
// Therefore we keep the parameter list the same length and only initialize
// the values if they are set to undefined.
}
use of com.google.javascript.rhino.JSDocInfoBuilder in project closure-compiler by google.
the class Es6ConvertSuper method addSyntheticConstructor.
private void addSyntheticConstructor(Node classNode) {
Node superClass = classNode.getSecondChild();
Node classMembers = classNode.getLastChild();
Node memberDef;
if (superClass.isEmpty()) {
Node function = NodeUtil.emptyFunction();
compiler.reportChangeToChangeScope(function);
memberDef = IR.memberFunctionDef("constructor", function);
} else {
if (!superClass.isQualifiedName()) {
// This will be reported as an error in Es6ToEs3Converter.
return;
}
Node body = IR.block();
// transpile, so don't generate it.
if (!classNode.isFromExterns() && !isInterface(classNode)) {
Node exprResult = IR.exprResult(IR.call(IR.getprop(IR.superNode(), IR.string("apply")), IR.thisNode(), IR.name("arguments")));
body.addChildToFront(exprResult);
}
Node constructor = IR.function(IR.name(""), IR.paramList(IR.name("var_args")), body);
compiler.reportChangeToChangeScope(constructor);
memberDef = IR.memberFunctionDef("constructor", constructor);
JSDocInfoBuilder info = new JSDocInfoBuilder(false);
info.recordParameter("var_args", new JSTypeExpression(new Node(Token.ELLIPSIS, new Node(Token.QMARK)), "<Es6ConvertSuper>"));
memberDef.setJSDocInfo(info.build());
}
memberDef.useSourceInfoIfMissingFromForTree(classNode);
memberDef.makeNonIndexableRecursive();
classMembers.addChildToFront(memberDef);
compiler.reportChangeToEnclosingScope(memberDef);
}
use of com.google.javascript.rhino.JSDocInfoBuilder in project closure-compiler by google.
the class JsDocInfoParserTest method testParseLicense.
public void testParseLicense() {
this.fileLevelJsDocBuilder = new JSDocInfoBuilder(false);
String comment = "@license Foo\nBar\n\nBaz*/";
parse(comment);
JSDocInfo info = this.fileLevelJsDocBuilder.build(true);
assertThat(info.getLicense()).isEqualTo(" Foo\nBar\n\nBaz");
}
use of com.google.javascript.rhino.JSDocInfoBuilder 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();
}
use of com.google.javascript.rhino.JSDocInfoBuilder in project closure-compiler by google.
the class DeclaredGlobalExternsOnWindow method addExtern.
private static void addExtern(Node node) {
String name = node.getString();
JSDocInfo oldJSDocInfo = NodeUtil.getBestJSDocInfo(node);
// TODO(tbreisacher): Consider adding externs to 'this' instead of 'window',
// for environments where the global object is not called 'window.'
Node window = IR.name("window");
Node string = IR.string(name);
Node getprop = IR.getprop(window, string);
Node newNode = getprop;
if (oldJSDocInfo != null) {
JSDocInfoBuilder builder;
if (oldJSDocInfo.isConstructorOrInterface() || oldJSDocInfo.hasEnumParameterType()) {
Node nameNode = IR.name(name);
newNode = IR.assign(getprop, nameNode);
builder = new JSDocInfoBuilder(false);
if (oldJSDocInfo.isConstructor()) {
builder.recordConstructor();
}
if (oldJSDocInfo.isInterface()) {
builder.recordInterface();
}
if (oldJSDocInfo.usesImplicitMatch()) {
builder.recordImplicitMatch();
}
if (oldJSDocInfo.hasEnumParameterType()) {
builder.recordEnumParameterType(oldJSDocInfo.getEnumParameterType());
}
} else {
if (NodeUtil.isNamespaceDecl(node)) {
newNode = IR.assign(getprop, IR.name(name));
} else {
Node rhs = NodeUtil.getRValueOfLValue(node);
// Type-aliasing definition
if (oldJSDocInfo.hasConstAnnotation() && rhs != null && rhs.isQualifiedName()) {
newNode = IR.assign(getprop, rhs.cloneTree());
}
}
builder = JSDocInfoBuilder.copyFrom(oldJSDocInfo);
}
// TODO(blickly): Remove these suppressions when all externs declarations on window are gone.
builder.recordSuppressions(ImmutableSet.of("const", "duplicate"));
JSDocInfo jsDocInfo = builder.build();
newNode.setJSDocInfo(jsDocInfo);
}
newNode.useSourceInfoFromForTree(node);
newNode.setOriginalName(name);
node.getGrandparent().addChildToBack(IR.exprResult(newNode));
}
Aggregations