.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / lsp / source / fix.go
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 source
6
7 import (
8         "context"
9         "fmt"
10         "go/ast"
11         "go/token"
12         "go/types"
13
14         "golang.org/x/tools/go/analysis"
15         "golang.org/x/tools/internal/lsp/analysis/fillstruct"
16         "golang.org/x/tools/internal/lsp/analysis/undeclaredname"
17         "golang.org/x/tools/internal/lsp/protocol"
18         "golang.org/x/tools/internal/span"
19         errors "golang.org/x/xerrors"
20 )
21
22 // SuggestedFixFunc is a function used to get the suggested fixes for a given
23 // gopls command, some of which are provided by go/analysis.Analyzers. Some of
24 // the analyzers in internal/lsp/analysis are not efficient enough to include
25 // suggested fixes with their diagnostics, so we have to compute them
26 // separately. Such analyzers should provide a function with a signature of
27 // SuggestedFixFunc.
28 type SuggestedFixFunc func(fset *token.FileSet, rng span.Range, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error)
29
30 const (
31         FillStruct      = "fill_struct"
32         UndeclaredName  = "undeclared_name"
33         ExtractVariable = "extract_variable"
34         ExtractFunction = "extract_function"
35 )
36
37 // suggestedFixes maps a suggested fix command id to its handler.
38 var suggestedFixes = map[string]SuggestedFixFunc{
39         FillStruct:      fillstruct.SuggestedFix,
40         UndeclaredName:  undeclaredname.SuggestedFix,
41         ExtractVariable: extractVariable,
42         ExtractFunction: extractFunction,
43 }
44
45 func SuggestedFixFromCommand(cmd protocol.Command) SuggestedFix {
46         return SuggestedFix{
47                 Title:   cmd.Title,
48                 Command: &cmd,
49         }
50 }
51
52 // ApplyFix applies the command's suggested fix to the given file and
53 // range, returning the resulting edits.
54 func ApplyFix(ctx context.Context, fix string, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) ([]protocol.TextDocumentEdit, error) {
55         handler, ok := suggestedFixes[fix]
56         if !ok {
57                 return nil, fmt.Errorf("no suggested fix function for %s", fix)
58         }
59         fset, rng, src, file, m, pkg, info, err := getAllSuggestedFixInputs(ctx, snapshot, fh, pRng)
60         if err != nil {
61                 return nil, err
62         }
63         suggestion, err := handler(fset, rng, src, file, pkg, info)
64         if err != nil {
65                 return nil, err
66         }
67         if suggestion == nil {
68                 return nil, nil
69         }
70
71         var edits []protocol.TextDocumentEdit
72         for _, edit := range suggestion.TextEdits {
73                 rng := span.NewRange(fset, edit.Pos, edit.End)
74                 spn, err := rng.Span()
75                 if err != nil {
76                         return nil, err
77                 }
78                 clRng, err := m.Range(spn)
79                 if err != nil {
80                         return nil, err
81                 }
82                 edits = append(edits, protocol.TextDocumentEdit{
83                         TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
84                                 Version: fh.Version(),
85                                 TextDocumentIdentifier: protocol.TextDocumentIdentifier{
86                                         URI: protocol.URIFromSpanURI(fh.URI()),
87                                 },
88                         },
89                         Edits: []protocol.TextEdit{
90                                 {
91                                         Range:   clRng,
92                                         NewText: string(edit.NewText),
93                                 },
94                         },
95                 })
96         }
97         return edits, nil
98 }
99
100 // getAllSuggestedFixInputs is a helper function to collect all possible needed
101 // inputs for an AppliesFunc or SuggestedFixFunc.
102 func getAllSuggestedFixInputs(ctx context.Context, snapshot Snapshot, fh FileHandle, pRng protocol.Range) (*token.FileSet, span.Range, []byte, *ast.File, *protocol.ColumnMapper, *types.Package, *types.Info, error) {
103         pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
104         if err != nil {
105                 return nil, span.Range{}, nil, nil, nil, nil, nil, errors.Errorf("getting file for Identifier: %w", err)
106         }
107         rng, err := pgf.Mapper.RangeToSpanRange(pRng)
108         if err != nil {
109                 return nil, span.Range{}, nil, nil, nil, nil, nil, err
110         }
111         return snapshot.FileSet(), rng, pgf.Src, pgf.File, pgf.Mapper, pkg.GetTypes(), pkg.GetTypesInfo(), nil
112 }