pelletier / go-toml

Go library for the TOML file format
https://github.com/pelletier/go-toml
Other
1.67k stars 208 forks source link

Incorrect indentation for arrays of custom types #943

Closed daniel-weisse closed 2 months ago

daniel-weisse commented 2 months ago

Describe the bug Using the SetIndentTables(true) option does not correctly indent keys of arrays of custom types. It does work correctly if the custom type is not a slice. Example: If I have some data structure a.b.c I expect the generated TOML to look like the following:

# comment A
[A]
  # comment B
  [A.B]
    # comment C
    [A.B.C]

Assuming c is an array I would expect the following:

# comment A
[A]
  # comment B
  [A.B]
    # comment C
    [[A.B.C]]
      # Entry 1
    [[A.B.C]]
      # Entry 2

Instead, go-toml gives me something like the following:

# comment A
[A]
  # comment B
  [A.B]
    # comment C
[[A.B.C]]
      # Entry 1
[[A.B.C]]
      # Entry 2

To Reproduce

package main

import (
    "bytes"
    "fmt"

    toml "github.com/pelletier/go-toml/v2"
)

func main() {
    cfg := layer0{
        Value: "value",
        Layer1: []layer1{
            {
                Value: "value",
                Layer2: []layer2{
                    {
                        Value: "value",
                        Layer3: []layer3{
                            {
                                Value: "value",
                                CustomType: customType{
                                    Value: "value",
                                },
                            },
                        },
                    },
                },
            },
        },
    }

    buf := bytes.Buffer{}
    enc := toml.NewEncoder(&buf).
        SetIndentTables(true).
        SetIndentSymbol("+") // Using "+" as indent symbol for easier comparison
    if err := enc.Encode(cfg); err != nil {
        panic(err)
    }

    fmt.Println(buf.String())
}

type layer0 struct {
    Value  string   `toml:"value" comment:"value comment"`
    Layer1 []layer1 `toml:"layer1" comment:"layer1 comment"`
}

type layer1 struct {
    Value  string   `toml:"value" comment:"value comment"`
    Layer2 []layer2 `toml:"layer2" comment:"layer2 comment"`
}

type layer2 struct {
    Value  string   `toml:"value" comment:"value comment"`
    Layer3 []layer3 `toml:"layer3" comment:"layer3 comment"`
}

type layer3 struct {
    Value      string     `toml:"value" comment:"value comment"`
    CustomType customType `toml:"customType" comment:"customType comment"`
}

type customType struct {
    Value string `toml:"value" comment:"value comment"`
}

Expected behavior I'm expecting the generated TOML to look like the following, correctly indenting layer1.layer2 with + and layer1.layer2.layer3 with two ++:

$ go run ./
# value comment
value = 'value'

# layer1 comment
[[layer1]]
+# value comment
+value = 'value'

+# layer2 comment
+[[layer1.layer2]]
++# value comment
++value = 'value'

++# layer3 comment
++[[layer1.layer2.layer3]]
+++# value comment
+++value = 'value'

+++# customType comment
+++[layer1.layer2.layer3.customType]
++++# value comment
++++value = 'value'

In practice, only the comments for layer1.layer2 and layer1.layer2.layer3 are indented, the keys are not:

$ go run ./
# value comment
value = 'value'

# layer1 comment
[[layer1]]
+# value comment
+value = 'value'

+# layer2 comment
[[layer1.layer2]]
++# value comment
++value = 'value'

++# layer3 comment
[[layer1.layer2.layer3]]
+++# value comment
+++value = 'value'

+++# customType comment
+++[layer1.layer2.layer3.customType]
++++# value comment
++++value = 'value'

Versions

Additional context Add any other context about the problem here that you think may help to diagnose.

pelletier commented 2 months ago

Thank you for the detailed issue report!