@Override
 public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
   if (n.isScript()) {
     return NodeUtil.isModuleFile(n);
   }
   return true;
 }
    void visitSubtree(Node n, Node parent) {
      if (n.isCall()) {
        boolean isModuleDetected = codingConvention.extractIsModuleFile(n, parent);
        if (isModuleDetected) {
          this.isModuleFile = true;
        }

        String require = codingConvention.extractClassNameIfRequire(n, parent);
        if (require != null) {
          requires.add(require);
        }

        String provide = codingConvention.extractClassNameIfProvide(n, parent);
        if (provide != null) {
          provides.add(provide);
        }
        return;
      } else if (parent != null && !parent.isExprResult() && !parent.isScript()) {
        return;
      }

      for (Node child = n.getFirstChild(); child != null; child = child.getNext()) {
        visitSubtree(child, n);
      }
    }
 @Override
 public Node getAstRoot(AbstractCompiler compiler) {
   Node root = ast.getAstRoot(compiler);
   // The root maybe null if the AST can not be created.
   if (root != null) {
     Preconditions.checkState(root.isScript());
     Preconditions.checkNotNull(root.getInputId());
   }
   return root;
 }
 private static Boolean hasJ2cl(Node root) {
   for (Node script : root.children()) {
     Preconditions.checkState(script.isScript());
     if (script.getSourceFileName() != null
         && script.getSourceFileName().endsWith(".java.js")
         && script.getSourceFileName().contains(".js.zip!")) {
       return Boolean.TRUE;
     }
   }
   return Boolean.FALSE;
 }
  @Override
  void add(Node n, Context context) {
    Node parent = n.getParent();
    if (parent != null && (parent.isBlock() || parent.isScript())) {
      if (n.isFunction()) {
        add(getFunctionAnnotation(n));
      } else if (n.isExprResult() && n.getFirstChild().isAssign()) {
        Node rhs = n.getFirstChild().getLastChild();
        add(getTypeAnnotation(rhs));
      } else if (n.isVar() && n.getFirstChild().getFirstChild() != null) {
        add(getTypeAnnotation(n.getFirstChild().getFirstChild()));
      }
    }

    super.add(n, context);
  }
  /**
   * Updates the internal reference map based on the provided parameters. If {@code scriptRoot} is
   * not SCRIPT, it basically replaces the internal map with the new one, otherwise it replaces all
   * the information associated to the given script.
   *
   * @param refMapPatch The reference map result of a {@link ReferenceCollectingCallback} pass which
   *     might be collected from the whole AST or just a sub-tree associated to a SCRIPT node.
   * @param root AST sub-tree root on which reference collection was done.
   */
  void updateGlobalVarReferences(Map<Var, ReferenceCollection> refMapPatch, Node root) {
    if (refMap == null || !root.isScript()) {
      resetGlobalVarReferences(refMapPatch);
      return;
    }

    InputId inputId = root.getInputId();
    Preconditions.checkNotNull(inputId);
    // Note there are two assumptions here (i) the order of compiler inputs
    // has not changed and (ii) all references are in the order they appear
    // in AST (this is enforced in ReferenceCollectionCallback).
    removeScriptReferences(inputId);
    for (Entry<Var, ReferenceCollection> entry : refMapPatch.entrySet()) {
      Var var = entry.getKey();
      if (var.isGlobal()) {
        replaceReferences(var.getName(), inputId, entry.getValue());
      }
    }
  }
  private void maybeReplaceJqueryPrototypeAlias(Node n) {
    // Check to see if this is the assignment of the original alias.
    // If so, leave it intact.
    if (NodeUtil.isLValue(n)) {
      Node maybeAssign = n.getParent();
      while (!NodeUtil.isStatement(maybeAssign) && !maybeAssign.isAssign()) {
        maybeAssign = maybeAssign.getParent();
      }

      if (maybeAssign.isAssign()) {
        maybeAssign = maybeAssign.getParent();
        if (maybeAssign.isBlock() || maybeAssign.isScript() || NodeUtil.isStatement(maybeAssign)) {
          return;
        }
      }
    }

    Node fn = n.getLastChild();
    if (fn != null) {
      n.replaceChild(fn, IR.string("prototype").srcref(fn));
      compiler.reportCodeChange();
    }
  }
 @Override
 public final boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
   // Don't inspect extern files
   return !n.isScript() || !t.getInput().getSourceFile().isExtern();
 }
 @Override
 public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
   return parent == null || !parent.isScript() || !t.getInput().isExtern();
 }
  /**
   * Updates the initial assignment to a collapsible property at global scope by changing it to a
   * variable declaration (e.g. a.b = 1 -> var a$b = 1). The property's value may either be a
   * primitive or an object literal or function whose properties aren't collapsible.
   *
   * @param alias The flattened property name (e.g. "a$b")
   * @param refName The name for the reference being updated.
   * @param ref An object containing information about the assignment getting updated
   */
  private void updateSimpleDeclaration(String alias, Name refName, Ref ref) {
    Node rvalue = ref.node.getNext();
    Node parent = ref.node.getParent();
    Node grandparent = parent.getParent();
    Node greatGrandparent = grandparent.getParent();

    if (rvalue != null && rvalue.isFunction()) {
      checkForHosedThisReferences(rvalue, refName.docInfo, refName);
    }

    // Create the new alias node.
    Node nameNode =
        NodeUtil.newName(compiler, alias, grandparent.getFirstChild(), refName.getFullName());
    NodeUtil.copyNameAnnotations(ref.node.getLastChild(), nameNode);

    if (grandparent.isExprResult()) {
      // BEFORE: a.b.c = ...;
      //   exprstmt
      //     assign
      //       getprop
      //         getprop
      //           name a
      //           string b
      //         string c
      //       NODE
      // AFTER: var a$b$c = ...;
      //   var
      //     name a$b$c
      //       NODE

      // Remove the r-value (NODE).
      parent.removeChild(rvalue);
      nameNode.addChildToFront(rvalue);

      Node varNode = IR.var(nameNode);
      greatGrandparent.replaceChild(grandparent, varNode);
    } else {
      // This must be a complex assignment.
      Preconditions.checkNotNull(ref.getTwin());

      // BEFORE:
      // ... (x.y = 3);
      //
      // AFTER:
      // var x$y;
      // ... (x$y = 3);

      Node current = grandparent;
      Node currentParent = grandparent.getParent();
      for (;
          !currentParent.isScript() && !currentParent.isBlock();
          current = currentParent, currentParent = currentParent.getParent()) {}

      // Create a stub variable declaration right
      // before the current statement.
      Node stubVar = IR.var(nameNode.cloneTree()).useSourceInfoIfMissingFrom(nameNode);
      currentParent.addChildBefore(stubVar, current);

      parent.replaceChild(ref.node, nameNode);
    }

    compiler.reportCodeChange();
  }
 @Override
 protected ConformanceResult checkConformance(NodeTraversal t, Node n) {
   // Everything is ok.
   return n.isScript() ? ConformanceResult.VIOLATION : ConformanceResult.CONFORMANCE;
 }
  @Override
  public void visit(NodeTraversal t, Node n, Node parent) {
    JSDocInfo docInfo = n.getJSDocInfo();
    if (docInfo != null && docInfo.isExport()) {

      if (parent.isAssign() && (n.isFunction() || n.isClass())) {
        JSDocInfo parentInfo = parent.getJSDocInfo();
        if (parentInfo != null && parentInfo.isExport()) {
          // ScopedAliases produces export annotations on both the function/class
          // node and assign node, we only want to visit the assign node.
          return;
        }
      }

      String export = null;
      GenerateNodeContext context = null;

      switch (n.getType()) {
        case Token.FUNCTION:
        case Token.CLASS:
          if (parent.isScript()) {
            export = NodeUtil.getName(n);
            context = new GenerateNodeContext(n, Mode.EXPORT);
          }
          break;

        case Token.MEMBER_FUNCTION_DEF:
          export = n.getString();
          context = new GenerateNodeContext(n, Mode.EXPORT);
          break;

        case Token.ASSIGN:
          Node grandparent = parent.getParent();
          if (parent.isExprResult() && !n.getLastChild().isAssign()) {
            if (grandparent != null
                && grandparent.isScript()
                && n.getFirstChild().isQualifiedName()) {
              export = n.getFirstChild().getQualifiedName();
              context = new GenerateNodeContext(n, Mode.EXPORT);
            } else if (allowLocalExports && n.getFirstChild().isGetProp()) {
              Node target = n.getFirstChild();
              export = target.getLastChild().getString();
              context = new GenerateNodeContext(n, Mode.EXTERN);
            }
          }
          break;

        case Token.VAR:
        case Token.LET:
        case Token.CONST:
          if (parent.isScript()) {
            if (n.getFirstChild().hasChildren() && !n.getFirstChild().getFirstChild().isAssign()) {
              export = n.getFirstChild().getString();
              context = new GenerateNodeContext(n, Mode.EXPORT);
            }
          }
          break;

        case Token.GETPROP:
          if (allowLocalExports && parent.isExprResult()) {
            export = n.getLastChild().getString();
            context = new GenerateNodeContext(n, Mode.EXTERN);
          }
          break;

        case Token.STRING_KEY:
        case Token.GETTER_DEF:
        case Token.SETTER_DEF:
          if (allowLocalExports) {
            export = n.getString();
            context = new GenerateNodeContext(n, Mode.EXTERN);
          }
          break;
      }

      if (export != null) {
        exports.put(export, context);
      } else {
        // Don't produce extra warnings for functions values of object literals
        if (!n.isFunction() || !NodeUtil.isObjectLitKey(parent)) {
          if (allowLocalExports) {
            compiler.report(t.makeError(n, EXPORT_ANNOTATION_NOT_ALLOWED));
          } else {
            compiler.report(t.makeError(n, NON_GLOBAL_ERROR));
          }
        }
      }
    }
  }