
最后我们来到了第三部分featureCommands,也是所有命令的大头,这里一共初始化了23个命令。我们首先看下第一个callHierarchy
type callHierarchy struct {
app *Application
}func (c *callHierarchy) Run(ctx context.Context, args ...string) error {
if len(args) != 1 {
return tool.CommandLineErrorf("call_hierarchy expects 1 argument (position)")
}
conn, err := c.app.connect(ctx)
if err != nil {
return err
}
defer conn.terminate(ctx)
from := parseSpan(args[0])
file, err := conn.openFile(ctx, from.URI())
if err != nil {
return err
}
loc, err := file.spanLocation(from)
if err != nil {
return err
}
p := protocol.CallHierarchyPrepareParams{
TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
}
callItems, err := conn.PrepareCallHierarchy(ctx, &p)
if err != nil {
return err
}
if len(callItems) == 0 {
return fmt.Errorf("function declaration identifier not found at %v", args[0])
}
for _, item := range callItems {
incomingCalls, err := conn.IncomingCalls(ctx, &protocol.CallHierarchyIncomingCallsParams{Item: item})
if err != nil {
return err
}
for i, call := range incomingCalls {
// From the spec: CallHierarchyIncomingCall.FromRanges is relative to
// the caller denoted by CallHierarchyIncomingCall.from.
printString, err := callItemPrintString(ctx, conn, call.From, call.From.URI, call.FromRanges)
if err != nil {
return err
}
fmt.Printf("caller[%d]: %s\n", i, printString)
}
printString, err := callItemPrintString(ctx, conn, item, "", nil)
if err != nil {
return err
}
fmt.Printf("identifier: %s\n", printString)
outgoingCalls, err := conn.OutgoingCalls(ctx, &protocol.CallHierarchyOutgoingCallsParams{Item: item})
if err != nil {
return err
}
for i, call := range outgoingCalls {
// From the spec: CallHierarchyOutgoingCall.FromRanges is the range
// relative to the caller, e.g the item passed to
printString, err := callItemPrintString(ctx, conn, call.To, item.URI, call.FromRanges)
if err != nil {
return err
}
fmt.Printf("callee[%d]: %s\n", i, printString)
}
}
return nil
}首先调用application的connect方法获取连接
// connect creates and initializes a new in-process gopls session.
func (app *Application) connect(ctx context.Context) (*connection, error) {
client := newClient(app)
var svr protocol.Server
if app.Remote == "" {
// local
options := settings.DefaultOptions(app.options)
svr = server.New(cache.NewSession(ctx, cache.New(nil)), client, options)
ctx = protocol.WithClient(ctx, client)
} else {
// remote
netConn, err := lsprpc.ConnectToRemote(ctx, app.Remote)
if err != nil {
return nil, err
}
stream := jsonrpc2.NewHeaderStream(netConn)
jsonConn := jsonrpc2.NewConn(stream)
svr = protocol.ServerDispatcher(jsonConn)
ctx = protocol.WithClient(ctx, client)
jsonConn.Go(ctx,
protocol.Handlers(
protocol.ClientHandler(client, jsonrpc2.MethodNotFound)))
}
conn := newConnection(svr, client)
return conn, conn.initialize(ctx, app.options)
}然后解析参数,从其中获得uri并打开,获取loc数据,然后组装调用层级参数
type CallHierarchyPrepareParams struct {
TextDocumentPositionParams
WorkDoneProgressParams
}type WorkDoneProgressParams struct {
// An optional token that a server can use to report work done progress.
WorkDoneToken ProgressToken `json:"workDoneToken,omitempty"`
}type TextDocumentPositionParams struct {
// The text document.
TextDocument TextDocumentIdentifier `json:"textDocument"`
// The position inside the text document.
Position Position `json:"position"`
}然后调用了server的PrepareCallHierarchy方法得到item列表,然后针对每一个item调用IncomingCalls方法,得到列表后继续遍历。最后调用OutgoingCalls,做同样的处理。
本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!