use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.
the class Es6TemplateLiterals method visitTaggedTemplateLiteral.
/**
* Converts tag`a\tb${bar}` to:
* // A global (module) scoped variable
* var $jscomp$templatelit$0 = ["a\tb"]; // cooked string array
* $jscomp$templatelit$0.raw = ["a\\tb"]; // raw string array
* ...
* // A call to the tagging function
* tag($jscomp$templatelit$0, bar);
*
* See template_literal_test.js for more examples.
*
* @param n A TAGGED_TEMPLATELIT node
*/
static void visitTaggedTemplateLiteral(NodeTraversal t, Node n, boolean addTypes) {
TypeIRegistry registry = t.getCompiler().getTypeIRegistry();
TypeI stringType = createType(addTypes, registry, JSTypeNative.STRING_TYPE);
TypeI arrayType = createGenericType(addTypes, registry, JSTypeNative.ARRAY_TYPE, stringType);
TypeI templateArrayType = createType(addTypes, registry, JSTypeNative.I_TEMPLATE_ARRAY_TYPE);
Node templateLit = n.getLastChild();
// Prepare the raw and cooked string arrays.
Node raw = createRawStringArray(templateLit, arrayType, stringType);
Node cooked = createCookedStringArray(templateLit, templateArrayType, stringType);
// Specify the type of the first argument to be ITemplateArray.
JSTypeExpression nonNullSiteObject = new JSTypeExpression(JsDocInfoParser.parseTypeString("!ITemplateArray"), "<Es6TemplateLiterals.java>");
JSDocInfoBuilder info = new JSDocInfoBuilder(false);
info.recordType(nonNullSiteObject);
Node siteObject = withType(IR.cast(cooked, info.build()), templateArrayType);
// Create a variable representing the template literal.
Node callsiteId = withType(IR.name(TEMPLATELIT_VAR + t.getCompiler().getUniqueNameIdSupplier().get()), templateArrayType);
Node var = IR.var(callsiteId, siteObject).useSourceInfoIfMissingFromForTree(n);
Node script = NodeUtil.getEnclosingScript(n);
script.addChildToFront(var);
t.reportCodeChange(var);
// Define the "raw" property on the introduced variable.
Node defineRaw = IR.exprResult(withType(IR.assign(withType(IR.getprop(callsiteId.cloneNode(), withType(IR.string("raw"), stringType)), arrayType), raw), arrayType)).useSourceInfoIfMissingFromForTree(n);
script.addChildAfter(defineRaw, var);
// Generate the call expression.
Node call = withType(IR.call(n.removeFirstChild(), callsiteId.cloneNode()), n.getTypeI());
for (Node child = templateLit.getFirstChild(); child != null; child = child.getNext()) {
if (!child.isString()) {
call.addChildToBack(child.removeFirstChild());
}
}
call.useSourceInfoIfMissingFromForTree(templateLit);
call.putBooleanProp(Node.FREE_CALL, !call.getFirstChild().isGetProp());
n.replaceWith(call);
t.reportCodeChange();
}
use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.
the class Es6TemplateLiterals method visitTemplateLiteral.
/**
* Converts `${a} b ${c} d ${e}` to (a + " b " + c + " d " + e)
*
* @param n A TEMPLATELIT node that is not prefixed with a tag
*/
static void visitTemplateLiteral(NodeTraversal t, Node n, boolean addTypes) {
TypeIRegistry registry = t.getCompiler().getTypeIRegistry();
TypeI stringType = createType(addTypes, registry, JSTypeNative.STRING_TYPE);
int length = n.getChildCount();
if (length == 0) {
n.replaceWith(withType(IR.string("\"\""), stringType));
} else {
Node first = n.removeFirstChild();
checkState(first.isString());
if (length == 1) {
n.replaceWith(first);
} else {
// Add the first string with the first substitution expression
Node add = withType(IR.add(first, n.removeFirstChild().removeFirstChild()), n.getTypeI());
// Process the rest of the template literal
for (int i = 2; i < length; i++) {
Node child = n.removeFirstChild();
if (child.isString()) {
if (child.getString().isEmpty()) {
continue;
} else if (i == 2 && first.getString().isEmpty()) {
// So that `${hello} world` gets translated into (hello + " world")
// instead of ("" + hello + " world").
add = add.getSecondChild().detach();
}
}
add = withType(IR.add(add, child.isString() ? child : child.removeFirstChild()), n.getTypeI());
}
n.replaceWith(add.useSourceInfoIfMissingFromForTree(n));
}
}
t.reportCodeChange();
}
use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.
the class ImplicitNullabilityCheck method visit.
/**
* Crawls the JSDoc of the given node to find any names in JSDoc
* that are implicitly null.
*/
@Override
public void visit(final NodeTraversal t, final Node n, final Node p) {
final JSDocInfo info = n.getJSDocInfo();
if (info == null) {
return;
}
final TypeIRegistry registry = compiler.getTypeIRegistry();
final List<Node> thrownTypes = transform(info.getThrownTypes(), new Function<JSTypeExpression, Node>() {
@Override
public Node apply(JSTypeExpression expr) {
return expr.getRoot();
}
});
final Scope scope = t.getScope();
for (Node typeRoot : info.getTypeNodes()) {
NodeUtil.visitPreOrder(typeRoot, new NodeUtil.Visitor() {
@Override
public void visit(Node node) {
if (!node.isString()) {
return;
}
if (thrownTypes.contains(node)) {
return;
}
Node parent = node.getParent();
if (parent != null) {
switch(parent.getToken()) {
case BANG:
case QMARK:
// The names inside function(this:Foo) and
case THIS:
case // function(new:Bar) are already non-null.
NEW:
return;
case PIPE:
{
// Inside a union
Node gp = parent.getParent();
if (gp != null && gp.getToken() == Token.QMARK) {
// Inside an explicitly nullable union
return;
}
for (Node child : parent.children()) {
if ((child.isString() && child.getString().equals("null")) || child.getToken() == Token.QMARK) {
// Inside a union that contains null or nullable type
return;
}
}
break;
}
default:
break;
}
}
String typeName = node.getString();
if (typeName.equals("null") || registry.getType(scope, typeName) == null) {
return;
}
TypeI type = registry.createTypeFromCommentNode(node);
if (type.isNullable()) {
reportWarning(t, node, typeName);
}
}
}, Predicates.alwaysTrue());
}
}
use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.
the class ProcessDefines method isValidDefineType.
/**
* Only defines of literal number, string, or boolean are supported.
*/
private boolean isValidDefineType(JSTypeExpression expression) {
TypeIRegistry registry = compiler.getTypeIRegistry();
TypeI type = registry.evaluateTypeExpressionInGlobalScope(expression);
return !type.isUnknownType() && type.isSubtypeOf(registry.getNativeType(NUMBER_STRING_BOOLEAN));
}
use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.
the class Es6ForOfConverter method visitForOf.
private void visitForOf(NodeTraversal t, Node node, Node parent) {
Node variable = node.removeFirstChild();
Node iterable = node.removeFirstChild();
Node body = node.removeFirstChild();
TypeI typeParam = unknownType;
if (addTypes) {
// TODO(sdh): This is going to be null if the iterable is nullable or unknown. We might want
// to consider some way of unifying rather than simply looking at the nominal type.
ObjectTypeI iterableType = iterable.getTypeI().autobox().toMaybeObjectType();
if (iterableType != null) {
TypeIRegistry registry = compiler.getTypeIRegistry();
TypeI iterableBaseType = registry.getNativeType(JSTypeNative.ITERABLE_TYPE);
typeParam = iterableType.getInstantiatedTypeArgument(iterableBaseType);
}
}
TypeI iteratorType = createGenericType(JSTypeNative.ITERATOR_TYPE, typeParam);
TypeI iIterableResultType = createGenericType(JSTypeNative.I_ITERABLE_RESULT_TYPE, typeParam);
TypeI iteratorNextType = addTypes ? iteratorType.toMaybeObjectType().getPropertyType("next") : null;
JSDocInfo varJSDocInfo = variable.getJSDocInfo();
Node iterName = withType(IR.name(ITER_BASE + compiler.getUniqueNameIdSupplier().get()), iteratorType);
iterName.makeNonIndexable();
Node getNext = withType(IR.call(withType(IR.getprop(iterName.cloneTree(), withStringType(IR.string("next"))), iteratorNextType)), iIterableResultType);
String variableName;
Token declType;
if (variable.isName()) {
declType = Token.NAME;
variableName = variable.getQualifiedName();
} else {
Preconditions.checkState(NodeUtil.isNameDeclaration(variable), "Expected var, let, or const. Got %s", variable);
declType = variable.getToken();
variableName = variable.getFirstChild().getQualifiedName();
}
Node iterResult = withType(IR.name(ITER_RESULT + variableName), iIterableResultType);
iterResult.makeNonIndexable();
Node call = Es6ToEs3Util.makeIterator(compiler, iterable);
if (addTypes) {
TypeI jscompType = t.getScope().getVar("$jscomp").getNode().getTypeI();
TypeI makeIteratorType = jscompType.toMaybeObjectType().getPropertyType("makeIterator");
call.getFirstChild().setTypeI(makeIteratorType);
call.getFirstFirstChild().setTypeI(jscompType);
}
Node init = IR.var(iterName.cloneTree(), withType(call, iteratorType));
Node initIterResult = iterResult.cloneTree();
initIterResult.addChildToFront(getNext.cloneTree());
init.addChildToBack(initIterResult);
Node cond = withBooleanType(IR.not(withBooleanType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("done"))))));
Node incr = withType(IR.assign(iterResult.cloneTree(), getNext.cloneTree()), iIterableResultType);
Node declarationOrAssign;
if (declType == Token.NAME) {
declarationOrAssign = withType(IR.assign(withType(IR.name(variableName).useSourceInfoFrom(variable), typeParam), withType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("value"))), typeParam)), typeParam);
declarationOrAssign.setJSDocInfo(varJSDocInfo);
declarationOrAssign = IR.exprResult(declarationOrAssign);
} else {
declarationOrAssign = new Node(declType, withType(IR.name(variableName).useSourceInfoFrom(variable.getFirstChild()), typeParam));
declarationOrAssign.getFirstChild().addChildToBack(withType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("value"))), typeParam));
declarationOrAssign.setJSDocInfo(varJSDocInfo);
}
Node newBody = IR.block(declarationOrAssign, body).useSourceInfoFrom(body);
Node newFor = IR.forNode(init, cond, incr, newBody);
newFor.useSourceInfoIfMissingFromForTree(node);
parent.replaceChild(node, newFor);
compiler.reportChangeToEnclosingScope(newFor);
}
Aggregations