diff --git a/patch.go b/patch.go index 16bcbf6..86b04e5 100644 --- a/patch.go +++ b/patch.go @@ -119,7 +119,12 @@ func parsePatch(patch []byte) ([]patchOperation, error) { } op.from = m.Value.Value.(Literal).String() case "value": - m.Value.BeforeExtra = obj.beforeExtraAt(j + 0).extractLeadingComments(true) + leading := obj.beforeExtraAt(j + 0).extractLeadingComments(true) + // Comments between the colon and value belong to the value too. + if m.Value.BeforeExtra.hasComment() { + leading = append(leading, m.Value.BeforeExtra...) + } + m.Value.BeforeExtra = leading m.Value.AfterExtra = obj.beforeExtraAt(j + 1).extractTrailingcomments(true) op.value = m.Value } diff --git a/patch_test.go b/patch_test.go index 4808d6b..d32c6ea 100644 --- a/patch_test.go +++ b/patch_test.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "reflect" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -519,3 +520,41 @@ func TestPatch(t *testing.T) { }) } } + +func TestPatchCommentsAfterValueColon(t *testing.T) { + for _, tt := range []struct{ name, input, op, path, want string }{ + {"array add", `[]`, "add", "/-", `[42]`}, + {"object add", `{}`, "add", "/item", `{"item":42}`}, + {"array replace", `[0]`, "replace", "/0", `[42]`}, + {"object replace", `{"item":0}`, "replace", "/item", `{"item":42}`}, + {"root add", `null`, "add", "", `42`}, + } { + for _, comment := range []string{"/* after colon */", "\n// after colon\n"} { + t.Run(tt.name+comment, func(t *testing.T) { + v, err := Parse([]byte(tt.input)) + if err != nil { + t.Fatal(err) + } + patch := fmt.Sprintf(`[{"op":%q,"path":%q, +// before value member +"value":%s 42}]`, tt.op, tt.path, comment) + if err := v.Patch([]byte(patch)); err != nil { + t.Fatal(err) + } + v.Format() + got := string(v.Pack()) + if !strings.Contains(got, "after colon") || !strings.Contains(got, "before value member") { + t.Fatalf("lost patch comments: %s", got) + } + v.Standardize() + want, err := Parse([]byte(tt.want)) + if err != nil { + t.Fatal(err) + } + if !equalValue(v, want) { + t.Fatalf("patched value = %s; want %s", v.Pack(), tt.want) + } + }) + } + } +}