Question: How to gofmt for injection artifacts?
huangjunwen opened this issue · comments
First thanks very much for this library, it saves me so much time ~
Then here is my question: I use AddGeneratorTemplateInjection
to generate fragments of output files, for example,
package {{ PackageName .File }}
// @@protoc_insertion_point(imports)
...
I have to generate the rest part of file to gather which external packages need to be imported before injecting the "import" part. But i found that gofmt
post processor does not work for injection artifacts. (this makes sense since it should apply to a whole file) . Is there any way to gofmt
the whole file for each output ?
Howdy! I'm glad it's helpful 😁
I explored this a bit initially but was unsuccessful, especially since a particular fragment has unknown indentation and the injected-into file might not even come from the same plugin. I'm not sure it's possible with just the injection body. You could explore using https://golang.org/pkg/go/format/#Node somehow to operate against a fragment.
Yes, I think it's not easy to do gofmt
at artifact's level. How about writing a PostProcessor
to gather all output files' path. Then do the gofmt
in the end, like this ?
func (c *fileCollector) Match(a pgs.Artifact) bool {
var n string
switch a := a.(type) {
case pgs.GeneratorFile:
n = a.Name
case pgs.GeneratorTemplateFile:
n = a.Name
case pgs.CustomFile:
n = a.Name
case pgs.CustomTemplateFile:
n = a.Name
...
}
// Is `n` the full path of the output file?
c.files = append(c.files, n)
return false
}
Well, I think this may not work too. Since files maybe not written to disk when the plugin is running.
I have found a workaround now, but only work for fragments that contains only top level declarations :
- For each fragment, run
parser.ParseFile(..., parser.PackageClauseOnly)
, if no error, then it should be a valid go file. Useformat.Source
directly. - Otherwise, insert a fake package clause at the beginning.
- Now it becomes valid,
format.Source
it. - Trim the package clause and return.