github.com/v2fly/tools@v0.100.0/internal/lsp/cmd/test/call_hierarchy.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cmdtest 6 7 import ( 8 "fmt" 9 "sort" 10 "strings" 11 "testing" 12 13 "github.com/v2fly/tools/internal/lsp/protocol" 14 "github.com/v2fly/tools/internal/lsp/tests" 15 "github.com/v2fly/tools/internal/span" 16 ) 17 18 func (r *runner) CallHierarchy(t *testing.T, spn span.Span, expectedCalls *tests.CallHierarchyResult) { 19 collectCallSpansString := func(callItems []protocol.CallHierarchyItem) string { 20 var callSpans []string 21 for _, call := range callItems { 22 mapper, err := r.data.Mapper(call.URI.SpanURI()) 23 if err != nil { 24 t.Fatal(err) 25 } 26 callSpan, err := mapper.Span(protocol.Location{URI: call.URI, Range: call.Range}) 27 if err != nil { 28 t.Fatal(err) 29 } 30 callSpans = append(callSpans, fmt.Sprint(callSpan)) 31 } 32 // to make tests deterministic 33 sort.Strings(callSpans) 34 return r.Normalize(strings.Join(callSpans, "\n")) 35 } 36 37 expectIn, expectOut := collectCallSpansString(expectedCalls.IncomingCalls), collectCallSpansString(expectedCalls.OutgoingCalls) 38 expectIdent := r.Normalize(fmt.Sprint(spn)) 39 40 uri := spn.URI() 41 filename := uri.Filename() 42 target := filename + fmt.Sprintf(":%v:%v", spn.Start().Line(), spn.Start().Column()) 43 44 got, stderr := r.NormalizeGoplsCmd(t, "call_hierarchy", target) 45 if stderr != "" { 46 t.Fatalf("call_hierarchy failed for %s: %s", target, stderr) 47 } 48 49 gotIn, gotIdent, gotOut := cleanCallHierarchyCmdResult(got) 50 if expectIn != gotIn { 51 t.Errorf("incoming calls call_hierarchy failed for %s expected:\n%s\ngot:\n%s", target, expectIn, gotIn) 52 } 53 if expectIdent != gotIdent { 54 t.Errorf("call_hierarchy failed for %s expected:\n%s\ngot:\n%s", target, expectIdent, gotIdent) 55 } 56 if expectOut != gotOut { 57 t.Errorf("outgoing calls call_hierarchy failed for %s expected:\n%s\ngot:\n%s", target, expectOut, gotOut) 58 } 59 60 } 61 62 // parses function URI and Range from call hierarchy cmd output to 63 // incoming, identifier and outgoing calls (returned in that order) 64 // ex: "identifier: function d at .../callhierarchy/callhierarchy.go:19:6-7" -> ".../callhierarchy/callhierarchy.go:19:6-7" 65 func cleanCallHierarchyCmdResult(output string) (incoming, ident, outgoing string) { 66 var incomingCalls, outgoingCalls []string 67 for _, out := range strings.Split(output, "\n") { 68 if out == "" { 69 continue 70 } 71 72 callLocation := out[strings.LastIndex(out, " ")+1:] 73 if strings.HasPrefix(out, "caller") { 74 incomingCalls = append(incomingCalls, callLocation) 75 } else if strings.HasPrefix(out, "callee") { 76 outgoingCalls = append(outgoingCalls, callLocation) 77 } else { 78 ident = callLocation 79 } 80 } 81 sort.Strings(incomingCalls) 82 sort.Strings(outgoingCalls) 83 incoming, outgoing = strings.Join(incomingCalls, "\n"), strings.Join(outgoingCalls, "\n") 84 return 85 }