首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >golang源码分析 :gopls(9)

golang源码分析 :gopls(9)

作者头像
golangLeetcode
发布2026-03-18 18:22:33
发布2026-03-18 18:22:33
800
举报

最后我们来到了第三部分featureCommands,也是所有命令的大头,这里一共初始化了23个命令。我们首先看下第一个callHierarchy

代码语言:javascript
复制
type callHierarchy struct {
    app *Application
}
代码语言:javascript
复制
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方法获取连接

代码语言:javascript
复制
// 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数据,然后组装调用层级参数

代码语言:javascript
复制
type CallHierarchyPrepareParams struct {
    TextDocumentPositionParams
    WorkDoneProgressParams
}
代码语言:javascript
复制
type WorkDoneProgressParams struct {
    // An optional token that a server can use to report work done progress.
    WorkDoneToken ProgressToken `json:"workDoneToken,omitempty"`
}
代码语言:javascript
复制
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,做同样的处理。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档