109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)package org.chromium.devtools.jsdoc.checks;
209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.common.base.Preconditions;
4197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.rhino.JSTypeExpression;
5197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.rhino.Node;
6197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport com.google.javascript.rhino.Token;
7197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
8197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport java.util.ArrayList;
9197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport java.util.Collections;
10197021e6b966cfb06891637935ef33fff06433d1Ben Murdochimport java.util.List;
1109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public class AstUtil {
1309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    private static final String PROTOTYPE_SUFFIX = ".prototype";
1509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static Node parentOfType(Node node, int tokenType) {
17197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Node parent = node.getParent();
18aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        return (parent == null || parent.getType() != tokenType) ? null : parent;
1909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
2009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
21197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    /**
22197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch     * Based on NodeUtil#getFunctionNameNode(Node).
23197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch     */
24197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static Node getFunctionNameNode(Node node) {
25197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Preconditions.checkState(node.isFunction());
2609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
27197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Node parent = node.getParent();
28197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (parent != null) {
29197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            switch (parent.getType()) {
30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            case Token.NAME:
31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                // var name = function() ...
32197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                // var name2 = function name1() ...
33197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return parent;
34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            // FIXME: Enable the setter and getter checks.
35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // case Token.SETTER_DEF:
36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // case Token.GETTER_DEF:
37197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            case Token.STRING_KEY:
38197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return parent;
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            case Token.NUMBER:
40197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return parent;
41f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            case Token.ASSIGN:
42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                int nameType = parent.getFirstChild().getType();
43c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                // We only consider these types of name nodes as acceptable.
44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                return nameType == Token.NAME || nameType == Token.GETPROP
45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    ? parent.getFirstChild()
46c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    : null;
47f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            case Token.VAR:
48197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return parent.getFirstChild();
49f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            default:
50c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                Node funNameNode = node.getFirstChild();
51c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                // Don't return the name node for anonymous functions
52c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                return funNameNode.getString().isEmpty() ? null : funNameNode;
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            }
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
55aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return null;
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static String getTypeNameFromPrototype(String value) {
6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return value.substring(0, value.length() - PROTOTYPE_SUFFIX.length());
6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    static boolean isPrototypeName(String typeName) {
6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return typeName.endsWith(PROTOTYPE_SUFFIX);
6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static Node getAssignedTypeNameNode(Node assignment) {
68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Preconditions.checkState(assignment.isAssign() || assignment.isVar());
69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Node typeNameNode = assignment.getFirstChild();
7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (typeNameNode.getType() != Token.GETPROP && typeNameNode.getType() != Token.NAME) {
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return null;
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return typeNameNode;
7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static List<Node> getArguments(Node functionCall) {
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        int childCount = functionCall.getChildCount();
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (childCount == 1) {
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return Collections.emptyList();
8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
81197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        List<Node> arguments = new ArrayList<>(childCount - 1);
82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        for (int i = 1; i < childCount; ++i) {
83197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            arguments.add(functionCall.getChildAtIndex(i));
8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
85197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return arguments;
86197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
87aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
88197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static String getAnnotationTypeString(JSTypeExpression expression) {
89197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return expression.getRoot().getFirstChild().getString();
9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    private AstUtil() {}
9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
94