github.com/tiagovtristao/plz@v13.4.0+incompatible/tools/build_langserver/langserver/signature.go (about) 1 package langserver 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/thought-machine/please/tools/build_langserver/lsp" 8 9 "github.com/sourcegraph/jsonrpc2" 10 ) 11 12 const signatureMethod = "textDocument/signatureHelp" 13 14 func (h *LsHandler) handleSignature(ctx context.Context, req *jsonrpc2.Request) (result interface{}, err error) { 15 params, err := h.getParamFromTDPositionReq(req, signatureMethod) 16 if err != nil { 17 return nil, err 18 } 19 documentURI := params.TextDocument.URI 20 21 h.mu.Lock() 22 defer h.mu.Unlock() 23 signatures := h.getSignatures(ctx, documentURI, params.Position) 24 log.Info("signatures, %s", signatures) 25 26 return signatures, nil 27 } 28 29 func (h *LsHandler) getSignatures(ctx context.Context, uri lsp.DocumentURI, pos lsp.Position) *lsp.SignatureHelp { 30 fileContent := h.workspace.documents[uri].textInEdit 31 lineContent := h.ensureLineContent(uri, pos) 32 33 log.Info("Signature help lineContent: %s", lineContent) 34 35 if isEmpty(lineContent, pos) { 36 return nil 37 } 38 39 lineContent = lineContent[:pos.Character] 40 41 stmts := h.analyzer.AspStatementFromContent(JoinLines(fileContent, true)) 42 43 call := h.analyzer.CallFromAST(stmts, pos) 44 if call == nil { 45 return nil 46 } 47 48 subincludes := h.analyzer.GetSubinclude(ctx, stmts, uri) 49 builtRule := h.analyzer.GetBuildRuleByName(call.Name, subincludes) 50 51 if builtRule == nil { 52 log.Info("rule %s not present, exit", call.Name) 53 return nil 54 } 55 label := builtRule.Header[strings.Index(builtRule.Header, builtRule.Name)+len(builtRule.Name):] 56 57 sigInfo := lsp.SignatureInformation{ 58 Label: label, 59 Documentation: builtRule.Docstring, 60 Parameters: paramsFromRuleDef(builtRule), 61 } 62 return &lsp.SignatureHelp{ 63 Signatures: []lsp.SignatureInformation{sigInfo}, 64 ActiveSignature: 0, 65 ActiveParameter: getActiveParam(call, builtRule), 66 } 67 } 68 69 func paramsFromRuleDef(def *RuleDef) []lsp.ParameterInformation { 70 71 var params []lsp.ParameterInformation 72 73 for _, arg := range def.Arguments { 74 if !arg.IsPrivate && (arg.Name != "self" || def.Object == "") { 75 param := lsp.ParameterInformation{ 76 Label: def.ArgMap[arg.Name].Repr, 77 } 78 params = append(params, param) 79 } 80 } 81 return params 82 } 83 84 func getActiveParam(callIdent *Call, def *RuleDef) int { 85 callArgs := callIdent.Arguments 86 if len(callArgs) == 0 { 87 return 0 88 } 89 90 for i, defArg := range def.Arguments { 91 if callArgs[len(callArgs)-1].Name == defArg.Name { 92 return i + 1 93 } 94 } 95 return len(callArgs) 96 }