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  }