this.transformDispatcher = new TransformDispatcher();
String restName = null; TypeDeclarationNode restType = null; if (checkParameters(tree.formalParameterList.parameters)) { for (ParseTree param : tree.formalParameterList.parameters) { TypeDeclarationNode type = null; break; case OPTIONAL_PARAMETER: maybeWarnTypeSyntax(param, Feature.OPTIONAL_PARAMETER); optionalParams.put( param.asOptionalParameter().param.asIdentifierExpression()
/** * Transforms the given node and then sets its type to Token.STRING if it * was Token.NAME. If its type was already Token.STRING, then quotes it. * Used for properties, as the old AST uses String tokens, while the new one * uses Name tokens for unquoted strings. For example, in * var o = {'a' : 1, b: 2}; * the string 'a' is quoted, while the name b is turned into a string, but * unquoted. */ private Node processObjectLitKeyAsString( com.google.javascript.jscomp.parsing.parser.Token token) { Node ret; if (token == null) { return createMissingExpressionNode(); } else if (token.type == TokenType.IDENTIFIER) { ret = processName(token.asIdentifier(), true); } else if (token.type == TokenType.NUMBER) { ret = transformNumberAsString(token.asLiteral()); ret.putBooleanProp(Node.QUOTED_PROP, true); } else { ret = processString(token.asLiteral()); ret.putBooleanProp(Node.QUOTED_PROP, true); } Preconditions.checkState(ret.isString()); return ret; }
Node newName; if (name != null) { newName = processNameWithInlineJSDoc(name); } else { if (isDeclaration || isMember) { newName = createMissingNameNode(); } else { newName = newStringNode(Token.NAME, ""); maybeProcessGenerics(node.getFirstChild(), functionTree.generics); node.addChildToBack(transform(functionTree.formalParameterList)); maybeProcessType(node, functionTree.returnType); bodyNode = IR.block(); parseDirectives(bodyNode); node.addChildToBack(bodyNode); member.addChildToBack(node); member.setStaticMember(functionTree.isStatic); maybeProcessAccessibilityModifier(functionTree, member, functionTree.access); node.setDeclaredTypeExpression(node.getDeclaredTypeExpression());
maybeWarnEs6Feature(functionTree, Feature.GENERATORS); maybeWarnEs6Feature(functionTree, Feature.MEMBER_DECLARATIONS); maybeWarnEs6Feature(functionTree, Feature.ARROW_FUNCTIONS); Node newName; if (name != null) { newName = processNameWithInlineJSDoc(name); } else { if (isDeclaration || isMember) { newName = createMissingNameNode(); } else { newName = newStringNode(Token.NAME, ""); maybeProcessGenerics(node.getFirstChild(), functionTree.generics); node.addChildToBack(transform(functionTree.formalParameterList)); maybeProcessType(node, functionTree.returnType); parseDirectives(bodyNode); node.addChildToBack(bodyNode); member.addChildToBack(node); member.setStaticMember(functionTree.isStatic); maybeProcessAccessibilityModifier(member, functionTree.access); node.setDeclaredTypeExpression(node.getDeclaredTypeExpression()); result = member;
String restName = null; TypeDeclarationNode restType = null; if (checkParameters(tree.formalParameterList.parameters)) { for (ParseTree param : tree.formalParameterList.parameters) { TypeDeclarationNode type = null; break; case OPTIONAL_PARAMETER: maybeWarnTypeSyntax(param, Feature.OPTIONAL_PARAMETER); optionalParams.put( param.asOptionalParameter().param.asIdentifierExpression()
Node processClassDeclaration(ClassDeclarationTree tree) { maybeWarnForFeature(tree, Feature.CLASSES); Node name = transformOrEmpty(tree.name, tree); maybeProcessGenerics(name, tree.generics); Node superClass = transformOrEmpty(tree.superClass, tree); if (!superClass.isEmpty()) { features = features.with(Feature.CLASS_EXTENDS); Node interfaces = transformListOrEmpty(Token.IMPLEMENTS, tree.interfaces); if (child.type == ParseTreeType.MEMBER_VARIABLE || child.type == ParseTreeType.COMPUTED_PROPERTY_MEMBER_VARIABLE) { maybeWarnTypeSyntax(child, Feature.MEMBER_VARIABLE_IN_CLASS); maybeWarnTypeSyntax(tree, Feature.IMPLEMENTS); classNode.putProp(Node.IMPLEMENTS, interfaces);
/** * Parse the directives, encode them in the AST, and remove their nodes. * * For information on ES5 directives, see section 14.1 of * ECMA-262, Edition 5. * * It would be nice if Rhino would eventually take care of this for * us, but right now their directive-processing is a one-off. */ private void parseDirectives(Node node) { // Remove all the directives, and encode them in the AST. ImmutableSet.Builder<String> directives = null; while (isDirective(node.getFirstChild())) { String directive = node.removeFirstChild().getFirstChild().getString(); if (directives == null) { directives = new ImmutableSet.Builder<String>(); } directives.add(directive); } if (directives != null) { ImmutableSet<String> result = directives.build(); if (result.size() == 1 && result.contains("use strict")) { // Use a shared set. result = USE_STRICT_ONLY; } node.setDirectives(result); } }
/** * Parse the directives, encode them in the AST, and remove their nodes. * * For information on ES5 directives, see section 14.1 of * ECMA-262, Edition 5. * * It would be nice if Rhino would eventually take care of this for * us, but right now their directive-processing is a one-off. */ private void parseDirectives(Node node) { // Remove all the directives, and encode them in the AST. ImmutableSet.Builder<String> directives = null; while (isDirective(node.getFirstChild())) { String directive = node.removeFirstChild().getFirstChild().getString(); if (directives == null) { directives = new ImmutableSet.Builder<>(); } directives.add(directive); } if (directives != null) { ImmutableSet<String> result = directives.build(); if (result.size() == 1 && result.contains("use strict")) { // Use a shared set. result = USE_STRICT_ONLY; } node.setDirectives(result); } }
/** * Transforms the given node and then sets its type to Token.STRING if it * was Token.NAME. If its type was already Token.STRING, then quotes it. * Used for properties, as the old AST uses String tokens, while the new one * uses Name tokens for unquoted strings. For example, in * var o = {'a' : 1, b: 2}; * the string 'a' is quoted, while the name b is turned into a string, but * unquoted. */ private Node processObjectLitKeyAsString( com.google.javascript.jscomp.parsing.parser.Token token) { Node ret; if (token == null) { return createMissingExpressionNode(); } else if (token.type == TokenType.IDENTIFIER) { ret = processName(token.asIdentifier(), true); } else if (token.type == TokenType.NUMBER) { ret = transformNumberAsString(token.asLiteral()); ret.putBooleanProp(Node.QUOTED_PROP, true); } else { ret = processString(token.asLiteral()); ret.putBooleanProp(Node.QUOTED_PROP, true); } checkState(ret.isString()); return ret; }
private IRFactory(String sourceString, StaticSourceFile sourceFile, Config config, ErrorReporter errorReporter, ImmutableList<Comment> comments) { this.sourceString = sourceString; this.nextCommentIter = comments.iterator(); this.currentComment = skipNonJsDoc(nextCommentIter); this.sourceFile = sourceFile; // The template node properties are applied to all nodes in this transform. this.templateNode = createTemplateNode(); this.fileLevelJsDocBuilder = new JSDocInfoBuilder(config.jsDocParsingMode().shouldParseDescriptions()); // Sometimes this will be null in tests. this.sourceName = sourceFile == null ? null : sourceFile.getName(); this.config = config; this.errorReporter = errorReporter; this.transformDispatcher = new TransformDispatcher(); if (config.strictMode().isStrict()) { reservedKeywords = ES5_STRICT_RESERVED_KEYWORDS; } else if (config.languageMode() == LanguageMode.ECMASCRIPT3) { reservedKeywords = null; // use TokenStream.isKeyword instead } else { reservedKeywords = ES5_RESERVED_KEYWORDS; } }
Node processFormalParameterList(FormalParameterListTree tree) { Node params = newNode(Token.PARAM_LIST); if (checkParameters(tree.parameters)) { for (ParseTree param : tree.parameters) { Node paramNode; if (param.type == ParseTreeType.DEFAULT_PARAMETER) { // processDefaultParameter() knows how to find and apply inline JSDoc to the right node paramNode = processDefaultParameter(param.asDefaultParameter()); } else { paramNode = transformNodeWithInlineJsDoc(param); } // Children must be simple names, default parameters, rest // parameters, or destructuring patterns. checkState( paramNode.isName() || paramNode.isRest() || paramNode.isArrayPattern() || paramNode.isObjectPattern() || paramNode.isDefaultValue()); params.addChildToBack(paramNode); } } return params; }
Node processClassDeclaration(ClassDeclarationTree tree) { maybeWarnEs6Feature(tree, Feature.CLASSES); Node name = transformOrEmpty(tree.name, tree); maybeProcessGenerics(name, tree.generics); Node superClass = transformOrEmpty(tree.superClass, tree); Node interfaces = transformListOrEmpty(Token.IMPLEMENTS, tree.interfaces); Node body = newNode(Token.CLASS_MEMBERS); setSourceInfo(body, tree); for (ParseTree child : tree.elements) { if (child.type == ParseTreeType.MEMBER_VARIABLE || child.type == ParseTreeType.COMPUTED_PROPERTY_MEMBER_VARIABLE) { maybeWarnTypeSyntax(child, Feature.MEMBER_VARIABLE_IN_CLASS); } body.addChildToBack(transform(child)); } Node classNode = newNode(Token.CLASS, name, superClass, body); if (!interfaces.isEmpty()) { maybeWarnTypeSyntax(tree, Feature.IMPLEMENTS); classNode.putProp(Node.IMPLEMENTS, interfaces); } return classNode; }
Node processIndexSignature(IndexSignatureTree tree) { maybeWarnTypeSyntax(tree, Feature.INDEX_SIGNATURE); Node name = transform(tree.name); Node indexType = name.getDeclaredTypeExpression(); if (indexType.getType() != Token.NUMBER_TYPE && indexType.getType() != Token.STRING_TYPE) { errorReporter.error( "Index signature parameter type must be 'string' or 'number'", sourceName, lineno(tree.name), charno(tree.name)); } Node signature = newNode(Token.INDEX_SIGNATURE, name); maybeProcessType(signature, tree.declaredType); return signature; }
Node processSetAccessor(SetAccessorTree tree) { Node key = processObjectLitKeyAsString(tree.propertyName); key.setType(Token.SETTER_DEF); Node body = transform(tree.body); Node dummyName = IR.name(""); setSourceInfo(dummyName, tree.propertyName); Node paramList = IR.paramList( safeProcessName(tree.parameter)); setSourceInfo(paramList, tree.parameter); maybeProcessType(paramList.getFirstChild(), tree.type); Node value = newNode(Token.FUNCTION, dummyName, paramList, body); setSourceInfo(value, tree.body); key.addChildToFront(value); key.setStaticMember(tree.isStatic); return key; }
Node processGetAccessor(GetAccessorTree tree) { Node key = processObjectLitKeyAsString(tree.propertyName); key.setType(Token.GETTER_DEF); Node body = transform(tree.body); Node dummyName = IR.name(""); setSourceInfo(dummyName, tree.body); Node paramList = IR.paramList(); setSourceInfo(paramList, tree.body); Node value = newNode(Token.FUNCTION, dummyName, paramList, body); setSourceInfo(value, tree.body); key.addChildToFront(value); maybeProcessType(value, tree.returnType); key.setStaticMember(tree.isStatic); return key; }
Node processFormalParameterList(FormalParameterListTree tree) { Node params = newNode(Token.PARAM_LIST); if (checkParameters(tree.parameters)) { for (ParseTree param : tree.parameters) { Node paramNode = transformNodeWithInlineJsDoc(param); // Children must be simple names, default parameters, rest // parameters, or destructuring patterns. Preconditions.checkState(paramNode.isName() || paramNode.isRest() || paramNode.isArrayPattern() || paramNode.isObjectPattern() || paramNode.isDefaultValue()); params.addChildToBack(paramNode); } } return params; }
Node processIndexSignature(IndexSignatureTree tree) { maybeWarnTypeSyntax(tree, Feature.INDEX_SIGNATURE); Node name = transform(tree.name); Node indexType = name.getDeclaredTypeExpression(); if (indexType.getToken() != Token.NUMBER_TYPE && indexType.getToken() != Token.STRING_TYPE) { errorReporter.error( "Index signature parameter type must be 'string' or 'number'", sourceName, lineno(tree.name), charno(tree.name)); } Node signature = newNode(Token.INDEX_SIGNATURE, name); maybeProcessType(signature, tree.declaredType); return signature; }
Node processGetAccessor(GetAccessorTree tree) { Node key = processObjectLitKeyAsString(tree.propertyName); key.setToken(Token.GETTER_DEF); Node body = transform(tree.body); Node dummyName = newStringNode(Token.NAME, ""); setSourceInfo(dummyName, tree.body); Node paramList = newNode(Token.PARAM_LIST); setSourceInfo(paramList, tree.body); Node value = newNode(Token.FUNCTION, dummyName, paramList, body); setSourceInfo(value, tree.body); key.addChildToFront(value); maybeProcessType(value, tree.returnType); key.setStaticMember(tree.isStatic); return key; }
Node processParenthesizedExpression(ParenExpressionTree exprNode) { checkParenthesizedExpression(exprNode); return transform(exprNode.expression); }