Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func main() {
out = flag.String("out", "", "file to save output to instead of stdout")
pkgName = flag.String("pkg", "", "package name for generated files")
genTag = flag.String("tag", "", "build tag that is stripped from output")
private = flag.Bool("private", false, "don't export the generated type")
prefix = "https://github.com/metabition/gennylib/raw/master/"
)
flag.Parse()
Expand Down Expand Up @@ -84,23 +85,23 @@ func main() {
}
r.Body.Close()
br := bytes.NewReader(b)
err = gen(*in, outputFilename, *pkgName, *genTag, br, typeSets, outWriter)
err = gen(*in, outputFilename, *pkgName, *genTag, br, typeSets, outWriter, *private)
} else if len(*in) > 0 {
var file *os.File
file, err = os.Open(*in)
if err != nil {
fatal(exitcodeSourceFileInvalid, err)
}
defer file.Close()
err = gen(*in, outputFilename, *pkgName, *genTag, file, typeSets, outWriter)
err = gen(*in, outputFilename, *pkgName, *genTag, file, typeSets, outWriter, *private)
} else {
var source []byte
source, err = ioutil.ReadAll(os.Stdin)
if err != nil {
fatal(exitcodeStdinFailed, err)
}
reader := bytes.NewReader(source)
err = gen("stdin", outputFilename, *pkgName, *genTag, reader, typeSets, outWriter)
err = gen("stdin", outputFilename, *pkgName, *genTag, reader, typeSets, outWriter, *private)
}

// do the work
Expand Down Expand Up @@ -144,12 +145,12 @@ func fatal(code int, a ...interface{}) {
}

// gen performs the generic generation.
func gen(filename, outputFilename, pkgName, tag string, in io.ReadSeeker, typesets []map[string]string, out io.Writer) error {
func gen(filename, outputFilename, pkgName, tag string, in io.ReadSeeker, typesets []map[string]string, out io.Writer, private bool) error {

var output []byte
var err error

output, err = parse.Generics(filename, outputFilename, pkgName, tag, in, typesets)
output, err = parse.Generics(filename, outputFilename, pkgName, tag, in, typesets, private)
if err != nil {
return err
}
Expand Down
33 changes: 19 additions & 14 deletions parse/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,35 @@ var unwantedLinePrefixes = [][]byte{
[]byte("//go:generate genny "),
}

func subIntoLiteral(lit, typeTemplate, specificType string) string {
func subIntoLiteral(lit, typeTemplate, specificType string, private bool) string {
if lit == typeTemplate {
return specificType
}
if !strings.Contains(lit, typeTemplate) {
idx := strings.Index(lit, typeTemplate)
if idx < 0 {
return lit
}
specificLg := wordify(specificType, true)
specificSm := wordify(specificType, false)
specificLg := wordify(specificType, true, private && (idx == 0))
specificSm := wordify(specificType, false, private && (idx == 0))
result := strings.Replace(lit, typeTemplate, specificLg, -1)

if strings.HasPrefix(result, specificLg) && !isExported(lit) {
return strings.Replace(result, specificLg, specificSm, 1)
}
return result
}

func subTypeIntoComment(line, typeTemplate, specificType string) string {
func subTypeIntoComment(line, typeTemplate, specificType string, private bool) string {
var subbed string
for _, w := range strings.Fields(line) {
subbed = subbed + subIntoLiteral(w, typeTemplate, specificType) + " "
subbed = subbed + subIntoLiteral(w, typeTemplate, specificType, private) + " "
}
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(line, typeTemplate, specificType string) string {
func subTypeIntoLine(line, typeTemplate, specificType string, private bool) string {
src := []byte(line)
var s scanner.Scanner
fset := token.NewFileSet()
Expand All @@ -76,10 +78,10 @@ func subTypeIntoLine(line, typeTemplate, specificType string) string {
if tok == token.EOF {
break
} else if tok == token.COMMENT {
subbed := subTypeIntoComment(lit, typeTemplate, specificType)
subbed := subTypeIntoComment(lit, typeTemplate, specificType, private)
output = output + subbed + " "
} else if tok.IsLiteral() {
subbed := subIntoLiteral(lit, typeTemplate, specificType)
subbed := subIntoLiteral(lit, typeTemplate, specificType, private)
output = output + subbed + " "
} else {
output = output + tok.String() + " "
Expand All @@ -89,7 +91,7 @@ func subTypeIntoLine(line, typeTemplate, specificType string) string {
}

// typeSet looks like "KeyType: int, ValueType: string"
func generateSpecific(filename string, in io.ReadSeeker, typeSet map[string]string) ([]byte, error) {
func generateSpecific(filename string, in io.ReadSeeker, typeSet map[string]string, private bool) ([]byte, error) {

// ensure we are at the beginning of the file
in.Seek(0, os.SEEK_SET)
Expand Down Expand Up @@ -143,7 +145,7 @@ func generateSpecific(filename string, in io.ReadSeeker, typeSet map[string]stri

for t, specificType := range typeSet {
if strings.Contains(line, t) {
newLine := subTypeIntoLine(line, t, specificType)
newLine := subTypeIntoLine(line, t, specificType, private)
line = newLine
}
}
Expand Down Expand Up @@ -171,7 +173,7 @@ func generateSpecific(filename string, in io.ReadSeeker, typeSet map[string]stri

// Generics parses the source file and generates the bytes replacing the
// generic types for the keys map with the specific types (its value).
func Generics(filename, outputFilename, pkgName, tag string, in io.ReadSeeker, typeSets []map[string]string) ([]byte, error) {
func Generics(filename, outputFilename, pkgName, tag string, in io.ReadSeeker, typeSets []map[string]string, private bool) ([]byte, error) {
var localUnwantedLinePrefixes [][]byte
localUnwantedLinePrefixes = append(localUnwantedLinePrefixes, unwantedLinePrefixes...)

Expand All @@ -184,7 +186,7 @@ func Generics(filename, outputFilename, pkgName, tag string, in io.ReadSeeker, t
for _, typeSet := range typeSets {

// generate the specifics
parsed, err := generateSpecific(filename, in, typeSet)
parsed, err := generateSpecific(filename, in, typeSet, private)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -266,10 +268,13 @@ func isAlphaNumeric(r rune) bool {

// wordify turns a type into a nice word for function and type
// names etc.
func wordify(s string, exported bool) string {
func wordify(s string, exported, private bool) string {
s = strings.TrimRight(s, "{}")
s = strings.TrimLeft(s, "*&")
s = strings.Replace(s, ".", "", -1)
if private {
return strings.ToLower(string(s[0])) + s[1:]
}
if !exported {
return s
}
Expand Down
16 changes: 15 additions & 1 deletion parse/parse_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,21 @@ func TestWordify(t *testing.T) {
"pack.type": "Packtype",
"*pack.type": "Packtype",
} {
assert.Equal(t, wordified, wordify(word, true))
assert.Equal(t, wordified, wordify(word, true, false))
}

// Test non exported name generation
for word, wordified := range map[string]string{
"int": "int",
"*int": "int",
"string": "string",
"*MyType": "myType",
"*myType": "myType",
"interface{}": "interface",
"pack.type": "packtype",
"*pack.type": "packtype",
} {
assert.Equal(t, wordified, wordify(word, true, true))
}

}
10 changes: 9 additions & 1 deletion parse/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var tests = []struct {
in string
tag string
types []map[string]string
private bool

// expectations
expectedOut string
Expand All @@ -36,6 +37,13 @@ var tests = []struct {
types: []map[string]string{{"Something": "int"}},
expectedOut: `test/queue/changed/int_queue.go`,
},
{
filename: "generic_queue.go",
in: `test/queue/generic_queue.go`,
types: []map[string]string{{"Something": "int64"}},
expectedOut: `test/queue/int_queue_private.go`,
private: true,
},
{
filename: "generic_queue.go",
in: `test/queue/generic_queue.go`,
Expand Down Expand Up @@ -134,7 +142,7 @@ func TestParse(t *testing.T) {
test.in = contents(test.in)
test.expectedOut = contents(test.expectedOut)

bytes, err := parse.Generics(test.filename, test.outputFilename, test.pkgName, test.tag, strings.NewReader(test.in), test.types)
bytes, err := parse.Generics(test.filename, test.outputFilename, test.pkgName, test.tag, strings.NewReader(test.in), test.types, test.private)

// check the error
if test.expectedErr == nil {
Expand Down
22 changes: 22 additions & 0 deletions parse/test/queue/int_queue_private.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny

package queue

// int64Queue is a queue of int64s.
type int64Queue struct {
items []int64
}

func NewInt64Queue() *int64Queue {
return &int64Queue{items: make([]int64, 0)}
}
func (q *int64Queue) Push(item int64) {
q.items = append(q.items, item)
}
func (q *int64Queue) Pop() int64 {
item := q.items[0]
q.items = q.items[1:]
return item
}