github.com/getgauge/gauge@v1.6.9/api/lang/rename.go (about)

     1  /*----------------------------------------------------------------
     2   *  Copyright (c) ThoughtWorks, Inc.
     3   *  Licensed under the Apache License, Version 2.0
     4   *  See LICENSE in the project root for license information.
     5   *----------------------------------------------------------------*/
     6  
     7  package lang
     8  
     9  import (
    10  	"context"
    11  	"encoding/json"
    12  	"fmt"
    13  	"strings"
    14  
    15  	gm "github.com/getgauge/gauge-proto/go/gauge_messages"
    16  	"github.com/getgauge/gauge/gauge"
    17  	"github.com/getgauge/gauge/parser"
    18  	"github.com/getgauge/gauge/refactor"
    19  	"github.com/getgauge/gauge/util"
    20  	"github.com/sourcegraph/go-langserver/pkg/lsp"
    21  	"github.com/sourcegraph/jsonrpc2"
    22  )
    23  
    24  func rename(ctx context.Context, conn jsonrpc2.JSONRPC2, req *jsonrpc2.Request) (interface{}, error) {
    25  	if err := sendSaveFilesRequest(ctx, conn); err != nil {
    26  		return nil, err
    27  	}
    28  	return renameStep(req)
    29  }
    30  
    31  func renameStep(req *jsonrpc2.Request) (interface{}, error) {
    32  	var params lsp.RenameParams
    33  	var err error
    34  	if err = json.Unmarshal(*req.Params, &params); err != nil {
    35  		logDebug(req, "failed to parse rename request %s", err.Error())
    36  		return nil, err
    37  	}
    38  
    39  	step, err := getStepToRefactor(params)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	if step == nil {
    44  		return nil, fmt.Errorf("refactoring is supported for steps only")
    45  	}
    46  	newName := getNewStepName(params, step)
    47  
    48  	refactortingResult := refactor.GetRefactoringChanges(step.GetLineText(), newName, lRunner.runner, util.GetSpecDirs(), false)
    49  	for _, warning := range refactortingResult.Warnings {
    50  		logWarning(req, warning)
    51  	}
    52  	if !refactortingResult.Success {
    53  		return nil, fmt.Errorf("%s", strings.Join(refactortingResult.Errors, "\t"))
    54  	}
    55  	var result lsp.WorkspaceEdit
    56  	result.Changes = make(map[string][]lsp.TextEdit)
    57  	changes := append(refactortingResult.SpecsChanged, append(refactortingResult.ConceptsChanged, refactortingResult.RunnerFilesChanged...)...)
    58  	if err := addWorkspaceEdits(&result, changes); err != nil {
    59  		return nil, err
    60  	}
    61  	return result, nil
    62  }
    63  
    64  func getStepToRefactor(params lsp.RenameParams) (*gauge.Step, error) {
    65  	file := util.ConvertURItoFilePath(params.TextDocument.URI)
    66  	if util.IsSpec(file) {
    67  		spec, pResult := new(parser.SpecParser).ParseSpecText(getContent(params.TextDocument.URI), util.ConvertURItoFilePath(params.TextDocument.URI))
    68  		if !pResult.Ok {
    69  			return nil, fmt.Errorf("refactoring failed due to parse errors: \n%s", strings.Join(pResult.Errors(), "\n"))
    70  		}
    71  		for _, item := range spec.AllItems() {
    72  			if item.Kind() == gauge.StepKind && item.(*gauge.Step).LineNo-1 == params.Position.Line {
    73  				return item.(*gauge.Step), nil
    74  			}
    75  		}
    76  	}
    77  	if util.IsConcept(file) {
    78  		steps, _ := new(parser.ConceptParser).Parse(getContent(params.TextDocument.URI), file)
    79  		for _, conStep := range steps {
    80  			for _, step := range conStep.ConceptSteps {
    81  				if step.LineNo-1 == params.Position.Line {
    82  					return step, nil
    83  				}
    84  			}
    85  		}
    86  	}
    87  	return nil, nil
    88  }
    89  
    90  func getNewStepName(params lsp.RenameParams, step *gauge.Step) string {
    91  	newName := strings.TrimSpace(strings.TrimPrefix(params.NewName, "*"))
    92  	if step.HasInlineTable {
    93  		newName = fmt.Sprintf("%s <%s>", newName, gauge.TableArg)
    94  	}
    95  	return newName
    96  }
    97  
    98  func addWorkspaceEdits(result *lsp.WorkspaceEdit, filesChanges []*gm.FileChanges) error {
    99  	for _, fileChange := range filesChanges {
   100  		uri := util.ConvertPathToURI(fileChange.FileName)
   101  		for _, diff := range fileChange.Diffs {
   102  			textEdit := lsp.TextEdit{
   103  				NewText: diff.Content,
   104  				Range: lsp.Range{
   105  					Start: lsp.Position{Line: int(diff.Span.Start - 1), Character: int(diff.Span.StartChar)},
   106  					End:   lsp.Position{Line: int(diff.Span.End - 1), Character: int(diff.Span.EndChar)},
   107  				},
   108  			}
   109  			result.Changes[string(uri)] = append(result.Changes[string(uri)], textEdit)
   110  		}
   111  	}
   112  	return nil
   113  }