/
rename.go
122 lines (107 loc) · 4 KB
/
rename.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2018 ThoughtWorks, Inc.
// This file is part of Gauge.
// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Gauge. If not, see <http://www.gnu.org/licenses/>.
package lang
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/getgauge/gauge/gauge"
gm "github.com/getgauge/gauge/gauge_messages"
"github.com/getgauge/gauge/parser"
"github.com/getgauge/gauge/refactor"
"github.com/getgauge/gauge/util"
"github.com/sourcegraph/go-langserver/pkg/lsp"
"github.com/sourcegraph/jsonrpc2"
)
func rename(ctx context.Context, conn jsonrpc2.JSONRPC2, req *jsonrpc2.Request) (interface{}, error) {
if err := sendSaveFilesRequest(ctx, conn); err != nil {
return nil, err
}
return renameStep(req)
}
func renameStep(req *jsonrpc2.Request) (interface{}, error) {
var params lsp.RenameParams
var err error
if err = json.Unmarshal(*req.Params, ¶ms); err != nil {
logDebug(req, "failed to parse rename request %s", err.Error())
return nil, err
}
step, err := getStepToRefactor(params)
if step == nil {
return nil, fmt.Errorf("refactoring is supported for steps only")
}
newName := getNewStepName(params, step)
refactortingResult := refactor.GetRefactoringChanges(step.GetLineText(), newName, lRunner.runner, util.GetSpecDirs())
for _, warning := range refactortingResult.Warnings {
logWarning(req, warning)
}
if !refactortingResult.Success {
return nil, fmt.Errorf("%s", strings.Join(refactortingResult.Errors, "\t"))
}
var result lsp.WorkspaceEdit
result.Changes = make(map[string][]lsp.TextEdit, 0)
changes := append(refactortingResult.SpecsChanged, append(refactortingResult.ConceptsChanged, refactortingResult.RunnerFilesChanged...)...)
if err := addWorkspaceEdits(&result, changes); err != nil {
return nil, err
}
return result, nil
}
func getStepToRefactor(params lsp.RenameParams) (*gauge.Step, error) {
file := util.ConvertURItoFilePath(params.TextDocument.URI)
if util.IsSpec(file) {
spec, pResult := new(parser.SpecParser).ParseSpecText(getContent(params.TextDocument.URI), util.ConvertURItoFilePath(params.TextDocument.URI))
if !pResult.Ok {
return nil, fmt.Errorf("refactoring failed due to parse errors: \n%s", strings.Join(pResult.Errors(), "\n"))
}
for _, item := range spec.AllItems() {
if item.Kind() == gauge.StepKind && item.(*gauge.Step).LineNo-1 == params.Position.Line {
return item.(*gauge.Step), nil
}
}
}
if util.IsConcept(file) {
steps, _ := new(parser.ConceptParser).Parse(getContent(params.TextDocument.URI), file)
for _, conStep := range steps {
for _, step := range conStep.ConceptSteps {
if step.LineNo-1 == params.Position.Line {
return step, nil
}
}
}
}
return nil, nil
}
func getNewStepName(params lsp.RenameParams, step *gauge.Step) string {
newName := strings.TrimSpace(strings.TrimPrefix(params.NewName, "*"))
if step.HasInlineTable {
newName = fmt.Sprintf("%s <%s>", newName, gauge.TableArg)
}
return newName
}
func addWorkspaceEdits(result *lsp.WorkspaceEdit, filesChanges []*gm.FileChanges) error {
for _, fileChange := range filesChanges {
uri := util.ConvertPathToURI(fileChange.FileName)
for _, diff := range fileChange.Diffs {
textEdit := lsp.TextEdit{
NewText: diff.Content,
Range: lsp.Range{
Start: lsp.Position{Line: int(diff.Span.Start - 1), Character: int(diff.Span.StartChar)},
End: lsp.Position{Line: int(diff.Span.End - 1), Character: int(diff.Span.EndChar)},
},
}
result.Changes[string(uri)] = append(result.Changes[string(uri)], textEdit)
}
}
return nil
}