diff --git a/parse/parse.go b/parse/parse.go index f0475f4..f5f4d67 100644 --- a/parse/parse.go +++ b/parse/parse.go @@ -40,44 +40,40 @@ var unwantedLinePrefixes = [][]byte{ []byte("//go:generate genny "), } -func subIntoLiteral(lit, t, specificType string) string { +func subIntoLiteral(lit, typeTemplate, specificType string) string { var i int - var newLine string - for { - i = strings.Index(lit[i:], t) // find out where - - if i <= -1 { - newLine = newLine + lit - break - } - - // if this isn't an exact match... That is, if t exists after - // the start or ends before the end of the literal - if i > 0 || i < len(lit)-len(t) { - // replace the literal with a capitalized version - cap := wordify(specificType, unicode.IsUpper(rune(lit[0]))) - lit = strings.Replace(lit, t, cap, 1) - } else { - // replace the literal as is - lit = strings.Replace(lit, t, specificType, 1) - } + i = strings.Index(lit[i:], typeTemplate) // find out where + if i <= -1 { + return lit + } + if i == 0 && len(typeTemplate) == len(lit) { + // If we're at the start of the word and it's an exact match + // of the literal and typeTemplate, don't wordify the replacement: + // subIntoLiteral("Something", "Something", "int") -> int + + return strings.Replace(lit, typeTemplate, specificType, 1) + } else { + // Otherwise, wordify every replacement: + // subIntoLiteral("SomethingMap", "Something", int) -> IntMap + // subIntoLiteral("MySomething", "Something", int) -> MyInt + cap := wordify(specificType, unicode.IsUpper(rune(lit[0]))) + return strings.Replace(lit, typeTemplate, cap, -1) } - return newLine } -func subTypeIntoComment(l, t, specificType string) string { +func subTypeIntoComment(line, typeTemplate, specificType string) string { var subbed string - for _, w := range strings.Fields(l) { - subbed = subbed + subIntoLiteral(w, t, specificType) + " " + for _, w := range strings.Fields(line) { + subbed = subbed + subIntoLiteral(w, typeTemplate, specificType) + " " } return subbed } // Does the heavy lifting of taking a line of our code and // sbustituting a type into there for our generic type -func subTypeIntoLine(l, t, specificType string) string { - src := []byte(l) +func subTypeIntoLine(line, typeTemplate, specificType string) string { + src := []byte(line) var s scanner.Scanner fset := token.NewFileSet() file := fset.AddFile("", fset.Base(), len(src)) @@ -88,10 +84,10 @@ func subTypeIntoLine(l, t, specificType string) string { if tok == token.EOF { break } else if tok == token.COMMENT { - subbed := subTypeIntoComment(lit, t, specificType) + subbed := subTypeIntoComment(lit, typeTemplate, specificType) output = output + subbed + " " } else if tok.IsLiteral() { - subbed := subIntoLiteral(lit, t, specificType) + subbed := subIntoLiteral(lit, typeTemplate, specificType) output = output + subbed + " " } else { output = output + tok.String() + " " @@ -145,37 +141,36 @@ func generateSpecific(filename string, in io.ReadSeeker, typeSet map[string]stri scanner := bufio.NewScanner(in) for scanner.Scan() { - l := scanner.Text() + line := scanner.Text() // does this line contain generic.Type? - if strings.Contains(l, genericType) || strings.Contains(l, genericNumber) { + if strings.Contains(line, genericType) || strings.Contains(line, genericNumber) { comment = "" continue } for t, specificType := range typeSet { - - if strings.Contains(l, t) { - newLine := subTypeIntoLine(l, t, specificType) - l = newLine + if strings.Contains(line, t) { + newLine := subTypeIntoLine(line, t, specificType) + line = newLine } } if comment != "" { - buf.WriteString(line(comment)) + buf.WriteString(makeLine(comment)) comment = "" } // is this line a comment? // TODO: should we handle /* */ comments? - if strings.HasPrefix(l, "//") { + if strings.HasPrefix(line, "//") { // record this line to print later - comment = l + comment = line continue } // write the line - buf.WriteString(line(l)) + buf.WriteString(makeLine(line)) } // write it out @@ -241,7 +236,7 @@ func Generics(filename, pkgName string, in io.ReadSeeker, typeSets []map[string] continue } - cleanOutputLines = append(cleanOutputLines, line(scanner.Text())) + cleanOutputLines = append(cleanOutputLines, makeLine(scanner.Text())) } cleanOutput := strings.Join(cleanOutputLines, "") @@ -262,7 +257,7 @@ func Generics(filename, pkgName string, in io.ReadSeeker, typeSets []map[string] return output, nil } -func line(s string) string { +func makeLine(s string) string { return fmt.Sprintln(strings.TrimRight(s, linefeed)) } diff --git a/parse/test/bugreports/generic_new_and_make_slice.go b/parse/test/bugreports/generic_new_and_make_slice.go index 9a91d03..b111614 100644 --- a/parse/test/bugreports/generic_new_and_make_slice.go +++ b/parse/test/bugreports/generic_new_and_make_slice.go @@ -1,7 +1,8 @@ package bugreports -import "github.com/justnoise/genny/generic" +import "github.com/cheekybits/genny/generic" +// Tests for issues raised in github issues #36 and #49 type NumberType generic.Number type ObjNumberType struct {