code: func (wr *Wrapper) tarjan() [][]*PackageInfo {
  	index := 1
  	sccs := [][]*PackageInfo{}
  	s := []*PackageInfo{}
  
  	var strongConnect func(*PackageInfo)
  	strongConnect = func(v *PackageInfo) {
  		// Set the depth index for v to the smallest unused index.
  		v.index = index
  		v.lowlink = index
  		index++
  		s = append(s, v)
  		v.onStack = true
  
  		// Consider successors of v.
  		for _, wName := range v.ImportedPackageComputedNames() {
  			w, ok := wr.allPackages[wName]
  			if !ok {
  				panic(fmt.Sprintf("%q not found in %v", wName, wr.allPackages))
  			}
  			if w.index == 0 {
  				// Successor w has not yet been visited; recurse on it
  				strongConnect(w)
  				if w.lowlink < v.lowlink {
  					v.lowlink = w.lowlink
  				}
  			} else {
  				if w.onStack {
  					// Successor w is in stack s and hence in the current SCC
  					if w.index < v.lowlink {
  						v.lowlink = w.index
  					}
  				}
  			}
  		}
  
  		// If v is a root node, pop the stack and generate an SCC
  		if v.lowlink == v.index {
  			scc := []*PackageInfo{}
  			var w *PackageInfo
  			for w != v {
  				w = s[len(s)-1]
  				s = s[:len(s)-1]
  				w.onStack = false
  				scc = append(scc, w)
  			}
  			sccs = append(sccs, scc)
  		}
  	}
  
  	for _, pkg := range wr.packagesInOrder() {
  		if pkg.index == 0 {
  			strongConnect(pkg)
  		}
  	}
  
  	return sccs
  }
docs: // https://en.wikipedia.org/wiki/Tarjan%27s_SCC_algorithm