cheekybits / genny

Elegant generics for Go
MIT License
1.71k stars 167 forks source link

bug fix: pass the output filename instead of the input filename to goimports package #56

Closed zwcn closed 5 years ago

zwcn commented 5 years ago

In parse.go, we have the following call to infer what packages should be imported for the generated file, where filename represents the input file name.

output, err = imports.Process(filename, output, nil)

Passing the input filename might cause some packages not being imported in the output. For example, say, we have the following dir structure (the buggy code can be downloaded here):

github.com/zwcn/genny-test
|- in.template.go
|- util
     |- util.go

in.template.go:


//go:generate genny -in=$GOFILE -out=out.go gen ValueType=float64

package pkg

import (
    "github.com/cheekybits/genny/generic"
    "github.com/zwcn/genny-test/util"
)

type ValueType = generic.Type

func GetValueTypeData() string {
    return util.Foo()
}

util.go:

package util

func foo() string {
    return "foo"
}

After running go generate, the github.com/zwcn/genny-test/util is missing in out.go. It's missing because imports.Process uses all go files (except the filename) in the dir in which the filename is to infer the set of imported packages. For details, please see https://github.com/golang/tools/blob/16909d206f00da7d0d5ba28cd9dc7fb223648ecf/imports/fix.go#L472.

Since we passed in.template.go as the filename in our case, imports.Process ignores it during the inference procedure and thus can't infer the util package.

The PR fixes this bug by passing the output file name to imports.Process instead. In this case, imports.Process can exploit the information collected from in.template.go to add the util package to the out.go.