On Mon, Oct 24, 2022 at 9:27 PM Tajmeet Singh <tjgurwar...@gmail.com> wrote:
> Thanks for looking at it :smile: > > Could you elaborate more on how the `SetLines` would work on a > `token.FileSet`? I thought that `SetLines` is only for the `os.File` types > :sweat: Do you mean that I should create offsets (using SetLines) before I > create the FileSet out of it? > Sure, so what I was thinking is that you'd use a different fileset than the one used to parse the AST, and only give it synthetic line-boundaries (the line-widths don't actually have to make sense), and then, when picking the token locations for the different elements in the CompositeLiteral, you'd override the locations of those tokens in the AST so nodes you want to appear on the same line will appear on the same line. (up to formatting constraints) Another other option (which is much simpler -- and I wish I had thought of before) is to pass the ast.FieldList <https://pkg.go.dev/go/ast#FieldList> from the StructType <https://pkg.go.dev/go/ast#StructType.Fields> instead of the slice of fields, then you can use the token.Pos from the Closing field <https://pkg.go.dev/go/ast#FieldList.Closing>. If you use Pos() <https://pkg.go.dev/go/ast#Field.Pos> for the field to set the `Colon <https://pkg.go.dev/go/ast#KeyValueExpr.Colon>` field on the KeyValueExpr <https://pkg.go.dev/go/ast#KeyValueExpr.Colon>, the formatter will see the line boundaries in between fields as appropriate and match the formatting of the struct definition. (AFAICT) > > reference code: > https://github.com/tjgurwara99/constr/blob/0e0f8952c652b7a7a10b7238daed90132b924084/construct.go#L31 > > On Tuesday, 25 October 2022 at 01:07:23 UTC+1 david....@gmail.com wrote: > >> On Sat, Oct 22, 2022 at 10:00 PM Tajmeet Singh <tjgur...@gmail.com> >> wrote: >> >>> Hello, >>> >>> I've been working on a utility to generate constructors for me when I >>> provide it with a path to the file containing the struct and it `Ident`. >>> The idea was that I would just create a ast.Node (FuncDecl) with all the >>> necessary fields but I'm not able to figure out the positioning of the >>> commas. >>> >>> The function that I'm working on looks something like this: >>> >>> ```Go >>> func generateConstructor(typeName string, fields ...*ast.Field) >>> *ast.FuncDecl { >>> var elts []ast.Expr >>> >>> for _, field := range fields { >>> elts = append(elts, &ast.KeyValueExpr{ >>> Key: field.Names[0], >>> Value: field.Names[0], >>> }) >>> } >>> return &ast.FuncDecl{ >>> Doc: nil, >>> Recv: nil, >>> Name: ast.NewIdent("New" + typeName), >>> Type: &ast.FuncType{ >>> TypeParams: nil, >>> Params: &ast.FieldList{ >>> List: fields, >>> }, >>> Results: nil, >>> }, >>> Body: &ast.BlockStmt{ >>> Lbrace: 1, >>> List: []ast.Stmt{ >>> &ast.ReturnStmt{ >>> Results: []ast.Expr{ >>> &ast.UnaryExpr{ >>> Op: token.AND, >>> X: &ast.CompositeLit{ >>> Type: ast.NewIdent(typeName), >>> Elts: elts, >>> Rbrace: 1, >>> }, >>> }, >>> }, >>> }, >>> }, >>> Rbrace: 2, >>> }, >>> } >>> } >>> ``` >>> >>> And when I provide it with a struct like this: >>> >>> ```Go >>> type Data struct { >>> something string >>> data string >>> dd int >>> } >>> ``` >>> I get this when I do `format.Node` on the generated node `functionDecl`. >>> >>> ```Go >>> func NewData(something string, >>> data string, >>> dd int) { >>> return &Data{something: something, >>> data: data, >>> dd: dd} >>> } >>> ``` >>> >>> However, I was thinking that it would look something like this. >>> >>> ```Go >>> func NewData(something string, >>> data string, >>> dd int, >>> ) { >>> return &Data{something: something, >>> data: data, >>> dd: dd, >>> } >>> } >>> ``` >>> (wishful thinking :joy:) >>> >>> Anyways, I tried to figure out how the `token.COMMA` is used in the >>> parser and how the ast is affected but I couldn't figure it out. Maybe it >>> is related to the `Lbrace` and `Rbrace` values which I'm deliberately >>> missing. Any help would be much appreciated :smile: :pray: >>> >> >> Looking at the code, I think you're on the right track with Rbrace's >> location being the determining factor when to insert a comma and move put >> the closing brace on a new line. >> My recommendation would be to use `SetLines` >> <https://pkg.go.dev/go/token@go1.19.2#File.SetLines> on the (hopefully >> clean) `token.FileSet` you're passing to `format.Node` to declare some >> new-line offsets. I don't think the offsets have to make sense as they >> would in a file that was parsed, but the formatter needs to see the last >> expression and close brace as being on different lines >> >> The type-switch line that handles CompositeLit's call handling >> insertions: >> https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/go/printer/nodes.go;l=1021;drc=7e72d384d66f48a78289edc6a7d1dc6ab878f990 >> The lines that handle making the decision about inserting a new line: >> https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/go/printer/nodes.go;l=297-299;drc=a1901f898bc05aac966edd247ff122f52fbb8d2e >> >>> >>> PS: I'm not aware of any utility out there so have to roll my own :joy: >>> and learn whilst at it; if people are aware of it, please let me know and >>> I'll inspect their code and figure things out :smile: >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/ffa312d0-5652-4c2d-9c71-c74bc4bfc56bn%40googlegroups.com >>> <https://groups.google.com/d/msgid/golang-nuts/ffa312d0-5652-4c2d-9c71-c74bc4bfc56bn%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/ca7fa4ed-247c-42fa-baa3-81a905ae1ecdn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/ca7fa4ed-247c-42fa-baa3-81a905ae1ecdn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CANrC0BiB0ytAnONsVc7R1kc%2Bey%2BOk2_sWOX2%3DS_uuK-7DjqC2A%40mail.gmail.com.