// deeper reports whether block x is lexically deeper than y. func deeper(x, y *types.Scope) bool { if x == y || x == nil { return false } else if y == nil { return true } else { return deeper(x.Parent(), y.Parent()) } }
func (g *Grapher) scopeLabel(s *types.Scope) (path []string) { node, present := g.scopeNodes[s] if !present { // TODO(sqs): diagnose why this happens. See https://github.com/sourcegraph/sourcegraph.com/issues/163. // log.Printf("no node found for scope (giving a dummy label); scope is: %s", s.String()) return []string{fmt.Sprintf("ERROR%d", rand.Intn(10000))} } switch n := node.(type) { case *ast.File: return []string{} case *ast.Package: return []string{} case *ast.FuncType: // get func name _, astPath, _ := g.program.PathEnclosingInterval(n.Pos(), n.End()) if false { log.Printf("----------") for i, n := range astPath { log.Printf("%d. %T %+v", i, n, n) } } if f, ok := astPath[0].(*ast.FuncDecl); ok { var path []string if f.Recv != nil { path = []string{derefNode(f.Recv.List[0].Type).(*ast.Ident).Name} } var uniqName string if f.Name.Name == "init" { // init function can appear multiple times in each file and // package, so need to uniquify it uniqName = f.Name.Name + uniqID(g.program.Fset.Position(f.Name.Pos())) } else { uniqName = f.Name.Name } path = append(path, uniqName) return path } } // get this scope's index in parent // TODO(sqs): is it necessary to uniquify this here now that we're handling // init above? p := s.Parent() var prefix []string if fs, ok := g.scopeNodes[p].(*ast.File); ok { // avoid file scope collisions by using file index as well filename := g.program.Fset.Position(fs.Name.Pos()).Filename prefix = []string{fmt.Sprintf("$%s", strippedFilename(filename))} } for i := 0; i < p.NumChildren(); i++ { if p.Child(i) == s { filename := g.program.Fset.Position(node.Pos()).Filename return append(prefix, fmt.Sprintf("$%s%d", strippedFilename(filename), i)) } } panic("unreachable") }