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  }