mirror of https://github.com/golang/go.git
cmd/digraph: only print non-trivial sccs
In 'digraph sccs', do not print trivial single-node components.
This is more useful because it distinguishes nodes with self-loops (printed)
from nodes without (not printed).
Also remove an unnecessary TODO about map[string]bool vs map[string]struct{}.
The savings is at most 5% and if we really cared about storage we would probably
not use a map at all.
Change-Id: I6049b3c0f99a913c65f08c6c40e77ae99d1ba8c4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/396834
Reviewed-by: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
6fff1af1a8
commit
c862641ee9
|
|
@ -122,7 +122,8 @@ The support commands are:
|
|||
allpaths <node> <node>
|
||||
the set of nodes on all paths from the first node to the second
|
||||
sccs
|
||||
all strongly connected components (one per line)
|
||||
all non-trivial strongly connected components, one per line
|
||||
(single-node components are only printed for nodes with self-loops)
|
||||
scc <node>
|
||||
the set of nodes nodes strongly connected to the specified one
|
||||
focus <node>
|
||||
|
|
@ -158,7 +159,7 @@ func (l nodelist) println(sep string) {
|
|||
fmt.Fprintln(stdout)
|
||||
}
|
||||
|
||||
type nodeset map[string]bool // TODO(deklerk): change bool to struct to reduce memory footprint
|
||||
type nodeset map[string]bool
|
||||
|
||||
func (s nodeset) sort() nodelist {
|
||||
nodes := make(nodelist, len(s))
|
||||
|
|
@ -266,6 +267,9 @@ func (g graph) sccs() []nodeset {
|
|||
if !seen[top] {
|
||||
scc = make(nodeset)
|
||||
rvisit(top)
|
||||
if len(scc) == 1 && !g[top][top] {
|
||||
continue
|
||||
}
|
||||
sccs = append(sccs, scc)
|
||||
}
|
||||
}
|
||||
|
|
@ -365,7 +369,7 @@ func parse(rd io.Reader) (graph, error) {
|
|||
return g, nil
|
||||
}
|
||||
|
||||
// Overridable for testing purposes.
|
||||
// Overridable for redirection.
|
||||
var stdin io.Reader = os.Stdin
|
||||
var stdout io.Writer = os.Stdout
|
||||
|
||||
|
|
@ -485,9 +489,16 @@ func digraph(cmd string, args []string) error {
|
|||
if len(args) != 0 {
|
||||
return fmt.Errorf("usage: digraph sccs")
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
oldStdout := stdout
|
||||
stdout = buf
|
||||
for _, scc := range g.sccs() {
|
||||
scc.sort().println(" ")
|
||||
}
|
||||
lines := strings.SplitAfter(buf.String(), "\n")
|
||||
sort.Strings(lines)
|
||||
stdout = oldStdout
|
||||
io.WriteString(stdout, strings.Join(lines, ""))
|
||||
|
||||
case "scc":
|
||||
if len(args) != 1 {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ a b c
|
|||
b d
|
||||
c d
|
||||
d c
|
||||
e e
|
||||
`
|
||||
|
||||
for _, test := range []struct {
|
||||
|
|
@ -41,7 +42,7 @@ d c
|
|||
{"transpose", g1, "transpose", nil, "belt pants\njacket sweater\npants shorts\nshoes pants\nshoes socks\nsweater shirt\ntie shirt\n"},
|
||||
{"forward", g1, "forward", []string{"socks"}, "shoes\nsocks\n"},
|
||||
{"forward multiple args", g1, "forward", []string{"socks", "sweater"}, "jacket\nshoes\nsocks\nsweater\n"},
|
||||
{"scss", g2, "sccs", nil, "a\nb\nc d\n"},
|
||||
{"scss", g2, "sccs", nil, "c d\ne\n"},
|
||||
{"scc", g2, "scc", []string{"d"}, "c\nd\n"},
|
||||
{"succs", g2, "succs", []string{"a"}, "b\nc\n"},
|
||||
{"preds", g2, "preds", []string{"c"}, "a\nd\n"},
|
||||
|
|
|
|||
Loading…
Reference in New Issue