Skip to content

Commit

Permalink
Merge pull request #271 from cucumber/broke-out-snippets-gen
Browse files Browse the repository at this point in the history
Broke out snippets gen and added sorting on method name
  • Loading branch information
lonnblad authored Mar 24, 2020
2 parents 5afad4d + 0d1fb60 commit 4d5024d
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 97 deletions.
12 changes: 6 additions & 6 deletions features/snippets.feature
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,17 @@ Feature: undefined step snippets
When I run feature suite
And the undefined step snippets should be:
"""
func thereIsAWhichCosts(arg1 string, arg2 int) error {
func iAddTheToTheBasket(arg1 string) error {
return godog.ErrPending
}
func iAddTheToTheBasket(arg1 string) error {
func thereIsAWhichCosts(arg1 string, arg2 int) error {
return godog.ErrPending
}
func FeatureContext(s *godog.Suite) {
s.Step(`^there is a "([^"]*)", which costs £(\d+)$`, thereIsAWhichCosts)
s.Step(`^I add the "([^"]*)" to the basket$`, iAddTheToTheBasket)
s.Step(`^there is a "([^"]*)", which costs £(\d+)$`, thereIsAWhichCosts)
}
"""

Expand All @@ -131,16 +131,16 @@ Feature: undefined step snippets
When I run feature suite
And the undefined step snippets should be:
"""
func whichCosts(arg1 string, arg2 int) error {
func godogs(arg1 int) error {
return godog.ErrPending
}
func godogs(arg1 int) error {
func whichCosts(arg1 string, arg2 int) error {
return godog.ErrPending
}
func FeatureContext(s *godog.Suite) {
s.Step(`^"([^"]*)", which costs £(\d+)$`, whichCosts)
s.Step(`^(\d+) godogs$`, godogs)
s.Step(`^"([^"]*)", which costs £(\d+)$`, whichCosts)
}
"""
91 changes: 7 additions & 84 deletions fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,17 @@ import (
"fmt"
"io"
"os"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"sync"
"text/template"
"time"
"unicode"

"github.com/cucumber/godog/colors"

"github.com/cucumber/messages-go/v10"
)

// some snippet formatting regexps
var snippetExprCleanup = regexp.MustCompile("([\\/\\[\\]\\(\\)\\\\^\\$\\.\\|\\?\\*\\+\\'])")
var snippetExprQuoted = regexp.MustCompile("(\\W|^)\"(?:[^\"]*)\"(\\W|$)")
var snippetMethodName = regexp.MustCompile("[^a-zA-Z\\_\\ ]")
var snippetNumbers = regexp.MustCompile("(\\d+)")

var snippetHelperFuncs = template.FuncMap{
"backticked": func(s string) string {
return "`" + s + "`"
},
}

var undefinedSnippetsTpl = template.Must(template.New("snippets").Funcs(snippetHelperFuncs).Parse(`
{{ range . }}func {{ .Method }}({{ .Args }}) error {
return godog.ErrPending
}
{{end}}func FeatureContext(s *godog.Suite) { {{ range . }}
s.Step({{ backticked .Expr }}, {{ .Method }}){{end}}
}
`))

type undefinedSnippet struct {
Method string
Expr string
argument *messages.PickleStepArgument
}
"github.com/cucumber/godog/colors"
)

type registeredFormatter struct {
name string
Expand Down Expand Up @@ -438,55 +408,6 @@ func (f *basefmt) Copy(cf ConcurrentFormatter) {
}
}

func (s *undefinedSnippet) Args() (ret string) {
var (
args []string
pos int
breakLoop bool
)
for !breakLoop {
part := s.Expr[pos:]
ipos := strings.Index(part, "(\\d+)")
spos := strings.Index(part, "\"([^\"]*)\"")
switch {
case spos == -1 && ipos == -1:
breakLoop = true
case spos == -1:
pos += ipos + len("(\\d+)")
args = append(args, reflect.Int.String())
case ipos == -1:
pos += spos + len("\"([^\"]*)\"")
args = append(args, reflect.String.String())
case ipos < spos:
pos += ipos + len("(\\d+)")
args = append(args, reflect.Int.String())
case spos < ipos:
pos += spos + len("\"([^\"]*)\"")
args = append(args, reflect.String.String())
}
}

if s.argument != nil {
if s.argument.GetDocString() != nil {
args = append(args, "*messages.PickleStepArgument_PickleDocString")
}
if s.argument.GetDataTable() != nil {
args = append(args, "*messages.PickleStepArgument_PickleTable")
}
}

var last string
for i, arg := range args {
if last == "" || last == arg {
ret += fmt.Sprintf("arg%d, ", i+1)
} else {
ret = strings.TrimRight(ret, ", ") + fmt.Sprintf(" %s, arg%d, ", last, i+1)
}
last = arg
}
return strings.TrimSpace(strings.TrimRight(ret, ", ") + " " + last)
}

func (f *basefmt) findStepResults(status stepResultStatus) (res []*stepResult) {
for _, feat := range f.features {
for _, pr := range feat.pickleResults {
Expand All @@ -508,7 +429,7 @@ func (f *basefmt) snippets() string {
}

var index int
var snips []*undefinedSnippet
var snips []undefinedSnippet
// build snippets
for _, u := range undefinedStepResults {
steps := []string{u.step.Text}
Expand Down Expand Up @@ -550,11 +471,13 @@ func (f *basefmt) snippets() string {
}
}
if !found {
snips = append(snips, &undefinedSnippet{Method: name, Expr: expr, argument: arg})
snips = append(snips, undefinedSnippet{Method: name, Expr: expr, argument: arg})
}
}
}

sort.Sort(snippetSortByMethod(snips))

var buf bytes.Buffer
if err := undefinedSnippetsTpl.Execute(&buf, snips); err != nil {
panic(err)
Expand Down
14 changes: 7 additions & 7 deletions fmt_progress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ func TestProgressFormatterOutput(t *testing.T) {
You can implement step definitions for undefined steps with these snippets:
func undefined() error {
func nextUndefined() error {
return godog.ErrPending
}
func nextUndefined() error {
func undefined() error {
return godog.ErrPending
}
func FeatureContext(s *godog.Suite) {
s.Step(` + "`^undefined$`" + `, undefined)
s.Step(` + "`^next undefined$`" + `, nextUndefined)
s.Step(` + "`^undefined$`" + `, undefined)
}
`
Expand Down Expand Up @@ -237,22 +237,22 @@ func TestProgressFormatterMultistepTemplates(t *testing.T) {
You can implement step definitions for undefined steps with these snippets:
func undef() error {
func three() error {
return godog.ErrPending
}
func unavailableCost(arg1 string, arg2 int) error {
return godog.ErrPending
}
func three() error {
func undef() error {
return godog.ErrPending
}
func FeatureContext(s *godog.Suite) {
s.Step(` + "`^undef$`" + `, undef)
s.Step(` + "`^unavailable \"([^\"]*)\" cost (\\d+)$`" + `, unavailableCost)
s.Step(` + "`^three$`" + `, three)
s.Step(` + "`^unavailable \"([^\"]*)\" cost (\\d+)$`" + `, unavailableCost)
s.Step(` + "`^undef$`" + `, undef)
}
`
Expand Down
108 changes: 108 additions & 0 deletions undefined_snippets_gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package godog

import (
"fmt"
"reflect"
"regexp"
"strings"
"text/template"

"github.com/cucumber/messages-go/v10"
)

// some snippet formatting regexps
var snippetExprCleanup = regexp.MustCompile("([\\/\\[\\]\\(\\)\\\\^\\$\\.\\|\\?\\*\\+\\'])")
var snippetExprQuoted = regexp.MustCompile("(\\W|^)\"(?:[^\"]*)\"(\\W|$)")
var snippetMethodName = regexp.MustCompile("[^a-zA-Z\\_\\ ]")
var snippetNumbers = regexp.MustCompile("(\\d+)")

var snippetHelperFuncs = template.FuncMap{
"backticked": func(s string) string {
return "`" + s + "`"
},
}

var undefinedSnippetsTpl = template.Must(template.New("snippets").Funcs(snippetHelperFuncs).Parse(`
{{ range . }}func {{ .Method }}({{ .Args }}) error {
return godog.ErrPending
}
{{end}}func FeatureContext(s *godog.Suite) { {{ range . }}
s.Step({{ backticked .Expr }}, {{ .Method }}){{end}}
}
`))

type undefinedSnippet struct {
Method string
Expr string
argument *messages.PickleStepArgument
}

func (s undefinedSnippet) Args() (ret string) {
var (
args []string
pos int
breakLoop bool
)

for !breakLoop {
part := s.Expr[pos:]
ipos := strings.Index(part, "(\\d+)")
spos := strings.Index(part, "\"([^\"]*)\"")

switch {
case spos == -1 && ipos == -1:
breakLoop = true
case spos == -1:
pos += ipos + len("(\\d+)")
args = append(args, reflect.Int.String())
case ipos == -1:
pos += spos + len("\"([^\"]*)\"")
args = append(args, reflect.String.String())
case ipos < spos:
pos += ipos + len("(\\d+)")
args = append(args, reflect.Int.String())
case spos < ipos:
pos += spos + len("\"([^\"]*)\"")
args = append(args, reflect.String.String())
}
}

if s.argument != nil {
if s.argument.GetDocString() != nil {
args = append(args, "*messages.PickleStepArgument_PickleDocString")
}

if s.argument.GetDataTable() != nil {
args = append(args, "*messages.PickleStepArgument_PickleTable")
}
}

var last string

for i, arg := range args {
if last == "" || last == arg {
ret += fmt.Sprintf("arg%d, ", i+1)
} else {
ret = strings.TrimRight(ret, ", ") + fmt.Sprintf(" %s, arg%d, ", last, i+1)
}

last = arg
}

return strings.TrimSpace(strings.TrimRight(ret, ", ") + " " + last)
}

type snippetSortByMethod []undefinedSnippet

func (s snippetSortByMethod) Len() int {
return len(s)
}

func (s snippetSortByMethod) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}

func (s snippetSortByMethod) Less(i, j int) bool {
return s[i].Method < s[j].Method
}

0 comments on commit 4d5024d

Please sign in to comment.