code: void inferAllScopes(Node node) {
      // Type analysis happens in two major phases.
      // 1) Finding all the symbols.
      // 2) Propagating all the inferred types.
      //
      // The order of this analysis is non-obvious. In a complete inference
      // system, we may need to backtrack arbitrarily far. But the compile-time
      // costs would be unacceptable.
      //
      // We do one pass where we do typed scope creation for all scopes
      // in pre-order.
      //
      // Then we do a second pass where we do all type inference
      // (type propagation) in pre-order.
      //
      // We use a memoized scope creator so that we never create a scope
      // more than once.
      //
      // This will allow us to handle cases like:
      // var ns = {};
      // (function() { /** JSDoc */ ns.method = function() {}; })();
      // ns.method();
      // In this code, we need to build the symbol table for the inner scope in
      // order to propagate the type of ns.method in the outer scope.
      (new NodeTraversal(
          compiler, new FirstScopeBuildingCallback(), scopeCreator))
          .traverseWithScope(node, topScope);
  
      scopeCreator.resolveTypes();
  
      (new NodeTraversal(
          compiler, new SecondScopeBuildingCallback(), scopeCreator))
          .traverseWithScope(node, topScope);
  
      // Resolve any new type names found during the inference.
      // This runs for nested block scopes after infer runs on the CFG root.
      compiler.getTypeRegistry().resolveTypes();
    }
docs: Entry point for type inference when running over part of the tree.