diff --git a/cmd/cmd.go b/cmd/cmd.go index 4ef258c..35d2779 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -25,6 +25,7 @@ import ( "strconv" "strings" + "github.com/aymanbagabas/go-udiff" "github.com/google/keep-sorted/keepsorted" "github.com/rs/zerolog/log" flag "github.com/spf13/pflag" @@ -84,6 +85,7 @@ var ( operations = map[string]operation{ "lint": lint, "fix": fix, + "diff": diff, } ) @@ -269,6 +271,46 @@ func lint(fixer *keepsorted.Fixer, filenames []string, modifiedLines []keepsorte return false, nil } +func diff(fixer *keepsorted.Fixer, filenames []string, modifiedLines []keepsorted.LineRange) (ok bool, err error) { + ok = true + + for _, fn := range filenames { + contents, err := read(fn) + if err != nil { + return false, err + } + want, alreadyFixed, warnings := fixer.Fix(fn, contents, modifiedLines) + if !alreadyFixed { + ok = false + inName := fn + outName := fn + if fn == stdin { + inName = "stdin" + outName = "stdout" + } + if _, err := os.Stdout.WriteString(udiff.Unified(inName, outName, contents, want)); err != nil { + return false, err + } + } + + for _, warn := range warnings { + ok = false + log := log.Warn() + if warn.Path != stdin { + log = log.Str("file", warn.Path) + } + if warn.Lines.Start == warn.Lines.End { + log = log.Int("line", warn.Lines.Start) + } else { + log = log.Int("start", warn.Lines.Start).Int("end", warn.Lines.End) + } + log.Msg(warn.Message) + } + } + + return ok, nil +} + func read(fn string) (string, error) { if fn == stdin { b, err := io.ReadAll(os.Stdin) diff --git a/go.mod b/go.mod index fdaca38..0852f94 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ go 1.23.1 require ( github.com/Workiva/go-datastructures v1.0.53 + github.com/aymanbagabas/go-udiff v0.3.1 github.com/google/go-cmp v0.5.8 github.com/mattn/go-isatty v0.0.20 github.com/rs/zerolog v1.31.0 diff --git a/go.sum b/go.sum index bd75113..6901f1f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig= github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= +github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= +github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/goldens/block.diff b/goldens/block.diff new file mode 100644 index 0000000..d527113 --- /dev/null +++ b/goldens/block.diff @@ -0,0 +1,295 @@ +--- stdin ++++ stdout +@@ -1,157 +1,159 @@ + widgets := []widget{ + // keep-sorted-test start block=yes + { +- Name: "foo", ++ Name: "bar", + }, + { +- Name: "bar", ++ Name: "foo", + }, + // keep-sorted-test end + } + + withStickComments := []widget{ + // keep-sorted-test start block=yes sticky_comments=yes +- { ++ // Comment about bar. ++ { +- Name: "foo", ++ Name: "bar", +- SomeOtherField: 123, ++ SomeOtherField: 456, + }, +- // Comment about bar. +- { +- Name: "bar", +- SomeOtherField: 456, +- }, +- // keep-sorted-test end +-} +- +-strings := []string{ +- // Note: since we're sorting based on the entire line, a new line comes before the +- // closing quote and thus a-b-c is sorted before a-b. +- // keep-sorted-test start block=yes +- `a +- c`, +- `a +- b`, +- `a +- b +- c`, +- // keep-sorted-test end +-} +- +-noIncreasedIndentation := []widget{ +- // keep-sorted-test start block=yes +- { +- Name: "foo", +- }, +- { +- Name: "bar", +- }, +- { +- Name: "baz", +- }, +- // keep-sorted-test end +-} +- +-unbalancedCommentsDoNotMatter := []widget{ +- // keep-sorted-test start block=yes sticky_comments=yes +- // Unbalanced comment: { +- { +- Name: "bar", +- }, +- { +- Name: "foo", +- }, +- // Also unbalanced: ] +- { +- Name: "baz", +- }, +- // keep-sorted-test end +-} +- +-withOneLiners := []widget{ +- // keep-sorted-test start block=yes +- { +- Name: "foo", +- }, +- { +- Name: "baz", +- }, +- {Name: "bar"}, +- // keep-sorted-test end +-} +- +-// gcl style code: +-// keep-sorted-test start block=yes +-Group xyz = external_groups.acl_group { +- group_expansion = 'self' +-} +-Group ijk = external_groups.acl_group { +- group_expansion = """''' +- Nested triple quotes aren\'t uncommon +- '''""" +-} +-Group lmn = external_groups.acl_group { +- group_expansion = """ +- Including another " shouldn't break groups +- """ +-} +-Group abc = external_groups.acl_group { +- group_expansion = "It's the members" +-} +-// keep-sorted-test end +- +-// gcl style code with trailing comments: +-// keep-sorted-test start block=yes +-Experiment xyz = templates.ExperimentBase { +- name = "XYZ" // Should be the last one :( +- description = "A bunch of opening brackets [{[ here" +- percent = 10 +-} +-Experiment ikj = +- templates.ExperimentBaseWithTestAccounts { +- name = "IJK" +- description = "A single quote in a trailing comment" +- test_accounts = [ +- 123, // Bobby's test account +- ] +-} +-Experiment abc = templates.LAUNCHED { +- name = "ABC" +- description = "Simple block" +-} +-// keep-sorted-test end +- +-// BUILD rule style +-// keep-sorted-test start block=yes newline_separated=yes +-some_build_rule( +- name = "def", +- src = "some-source", +-) +- +-some_build_rule( +- name = "xyz", +- src = "another-source", +-) +- +-some_build_rule( +- name = "abc", +- src = "one-more-source", ++ { ++ Name: "foo", ++ SomeOtherField: 123, ++ }, ++ // keep-sorted-test end ++} ++ ++strings := []string{ ++ // Note: since we're sorting based on the entire line, a new line comes before the ++ // closing quote and thus a-b-c is sorted before a-b. ++ // keep-sorted-test start block=yes ++ `a ++ b ++ c`, ++ `a ++ b`, ++ `a ++ c`, ++ // keep-sorted-test end ++} ++ ++noIncreasedIndentation := []widget{ ++ // keep-sorted-test start block=yes ++ { ++ Name: "bar", ++ }, ++ { ++ Name: "baz", ++ }, ++ { ++ Name: "foo", ++ }, ++ // keep-sorted-test end ++} ++ ++unbalancedCommentsDoNotMatter := []widget{ ++ // keep-sorted-test start block=yes sticky_comments=yes ++ // Unbalanced comment: { ++ { ++ Name: "bar", ++ }, ++ // Also unbalanced: ] ++ { ++ Name: "baz", ++ }, ++ { ++ Name: "foo", ++ }, ++ // keep-sorted-test end ++} ++ ++withOneLiners := []widget{ ++ // keep-sorted-test start block=yes ++ {Name: "bar"}, ++ { ++ Name: "baz", ++ }, ++ { ++ Name: "foo", ++ }, ++ // keep-sorted-test end ++} ++ ++// gcl style code: ++// keep-sorted-test start block=yes ++Group abc = external_groups.acl_group { ++ group_expansion = "It's the members" ++} ++Group ijk = external_groups.acl_group { ++ group_expansion = """''' ++ Nested triple quotes aren\'t uncommon ++ '''""" ++} ++Group lmn = external_groups.acl_group { ++ group_expansion = """ ++ Including another " shouldn't break groups ++ """ ++} ++Group xyz = external_groups.acl_group { ++ group_expansion = 'self' ++} ++// keep-sorted-test end ++ ++// gcl style code with trailing comments: ++// keep-sorted-test start block=yes ++Experiment abc = templates.LAUNCHED { ++ name = "ABC" ++ description = "Simple block" ++} ++Experiment ikj = ++ templates.ExperimentBaseWithTestAccounts { ++ name = "IJK" ++ description = "A single quote in a trailing comment" ++ test_accounts = [ ++ 123, // Bobby's test account ++ ] ++} ++Experiment xyz = templates.ExperimentBase { ++ name = "XYZ" // Should be the last one :( ++ description = "A bunch of opening brackets [{[ here" ++ percent = 10 ++} ++// keep-sorted-test end ++ ++// BUILD rule style ++// keep-sorted-test start block=yes newline_separated=yes ++some_build_rule( ++ name = "abc", ++ src = "one-more-source", ++) ++ ++some_build_rule( ++ name = "def", ++ src = "some-source", ++) ++ ++some_build_rule( ++ name = "xyz", ++ src = "another-source", + ) + // keep-sorted-test end + + // BUILD rule style with newlines=2 + // keep-sorted-test start block=yes newline_separated=2 + some_build_rule( +- name = "def", ++ name = "abc", +- src = "some-source", ++ src = "one-more-source", +-) ++) ++ + + some_build_rule( +- name = "xyz", ++ name = "def", +- src = "another-source", ++ src = "some-source", +-) ++) ++ + + some_build_rule( +- name = "abc", ++ name = "xyz", +- src = "one-more-source", ++ src = "another-source", + ) + // keep-sorted-test end diff --git a/goldens/by_regex.diff b/goldens/by_regex.diff new file mode 100644 index 0000000..058f2f6 --- /dev/null +++ b/goldens/by_regex.diff @@ -0,0 +1,237 @@ +--- stdin ++++ stdout +@@ -1,127 +1,133 @@ + No capturing group + keep-sorted-test start by_regex=int|bool|long +- int baz +- bool foo ++ bool foo +- long bar ++ int baz ++ long bar + keep-sorted-test end + + Capturing group + keep-sorted-test start by_regex=['[^ ]+ (.*)'] +- int baz ++ long bar ++ int baz + bool foo +- long bar +- keep-sorted-test end ++ keep-sorted-test end + + Capturing group and non-capturing group + keep-sorted-test start by_regex=['(?:int|bool|long) (.*)'] +- int baz ++ long bar +- bool foo +- long bar +- keep-sorted-test end +- +-Numeric +- keep-sorted-test start by_regex=\d+ numeric=yes +- bar 40 +- foo 7 +- baz 01 +- keep-sorted-test end +- +-Case insensitive sorting +- keep-sorted-test start by_regex=\D+ case=no +- 1 FOO +- 2 bar +- 3 bAz +- keep-sorted-test end +- +-Prefix order +- // keep-sorted-test start by_regex=\w+_(\w+) prefix_order=INIT,,FINAL +- FOO_INIT, +- FOO_FINAL, +- BAR_INIT, +- BAR_FINAL, +- DO_STUFF, +- DO_MORE_STUFF, +- ZAP_THINGS +- // keep-sorted-test end +- +-Multiple regexes +- keep-sorted-test start by_regex=['(?:int|bool|long) (.*)', 'int|bool|long'] +- int baz +- long baz +- bool baz +- bool foo +- long foo +- int foo +- long bar +- bool bar +- int bar +- keep-sorted-test end +- +-One regex, multiple capturing groups +- keep-sorted-test start by_regex=(.*)_(.*) +- foo_bar +- foo_baz +- bar_baz +- baz_qux +- keep-sorted-test end +- +-Multiline blocks +- keep-sorted-test start block=yes newline_separated=yes by_regex=(\w+)\(\)\s+{ +- bool func2() { +- return true; +- } +- int func1() { +- return 1; +- } +- List +- func0() { +- return List.of(whatever); +- } +- keep-sorted-test end +- +-Multiline blocks with newlines=2 +- keep-sorted-test start block=yes newline_separated=2 by_regex=(\w+)\(\)\s+{ +- bool func2() { +- return true; +- } +- int func1() { +- return 1; +- } +- List +- func0() { +- return List.of(whatever); +- } +- keep-sorted-test end +- +-Regex doesn't match every line +- keep-sorted-test start by_regex=\d+ +- 3 +- baz +- 2 +- foo +- 1 ++ int baz ++ bool foo ++ keep-sorted-test end ++ ++Numeric ++ keep-sorted-test start by_regex=\d+ numeric=yes ++ baz 01 ++ foo 7 ++ bar 40 ++ keep-sorted-test end ++ ++Case insensitive sorting ++ keep-sorted-test start by_regex=\D+ case=no ++ 2 bar ++ 3 bAz ++ 1 FOO ++ keep-sorted-test end ++ ++Prefix order ++ // keep-sorted-test start by_regex=\w+_(\w+) prefix_order=INIT,,FINAL ++ BAR_INIT, ++ FOO_INIT, ++ DO_MORE_STUFF, ++ DO_STUFF, ++ ZAP_THINGS, ++ BAR_FINAL, ++ FOO_FINAL ++ // keep-sorted-test end ++ ++Multiple regexes ++ keep-sorted-test start by_regex=['(?:int|bool|long) (.*)', 'int|bool|long'] ++ bool bar ++ int bar ++ long bar ++ bool baz ++ int baz ++ long baz ++ bool foo ++ int foo ++ long foo ++ keep-sorted-test end ++ ++One regex, multiple capturing groups ++ keep-sorted-test start by_regex=(.*)_(.*) ++ bar_baz ++ baz_qux ++ foo_bar ++ foo_baz ++ keep-sorted-test end ++ ++Multiline blocks ++ keep-sorted-test start block=yes newline_separated=yes by_regex=(\w+)\(\)\s+{ ++ List ++ func0() { ++ return List.of(whatever); ++ } ++ ++ int func1() { ++ return 1; ++ } ++ ++ bool func2() { ++ return true; ++ } ++ keep-sorted-test end ++ ++Multiline blocks with newlines=2 ++ keep-sorted-test start block=yes newline_separated=2 by_regex=(\w+)\(\)\s+{ ++ List ++ func0() { ++ return List.of(whatever); ++ } ++ ++ ++ int func1() { ++ return 1; ++ } ++ ++ ++ bool func2() { ++ return true; ++ } ++ keep-sorted-test end ++ ++Regex doesn't match every line ++ keep-sorted-test start by_regex=\d+ ++ 1 ++ 2 ++ 3 ++ bar ++ baz +- bar ++ foo + keep-sorted-test end + + Invalid regex + keep-sorted-test start by_regex=* +- 2 ++ 1 +- 1 ++ 2 + 3 + keep-sorted-test end + + Cannot combine with ignore_prefixes + keep-sorted-test start by_regex=.* ignore_prefixes=foo,bar +- 2 ++ 1 +- 1 ++ 2 + 3 + keep-sorted-test end + + Template rewrites + keep-sorted-test start by_regex=['^(Jan|(Feb|Mar|(Apr|May|(Jun|(Jul|(Aug|Sep|(Oct|(Nov|(Dec))))))))) (?\d\d) (?\d\d:\d\d) (?\d\d\d\d) ': '${t_Y} ${9}A${8}A${7}A${6}A${5}A${4}A${3}A${2}A${1} ${t_d} ${t_R}'] +- Jun 23 09:00 2025 | nobody ++ Aug 26 09:00 2024 | nobody +- Aug 26 09:00 2024 | nobody ++ Sep 02 09:00 2024 | nobody +- Sep 02 09:00 2024 | nobody ++ Apr 14 09:00 2025 | nobody +- Apr 14 09:00 2025 | nobody ++ Jun 23 09:00 2025 | nobody + Jul 28 09:00 2025 | nobody + keep-sorted-test end diff --git a/goldens/case_insensitive.diff b/goldens/case_insensitive.diff new file mode 100644 index 0000000..06ee8f5 --- /dev/null +++ b/goldens/case_insensitive.diff @@ -0,0 +1,39 @@ +--- stdin ++++ stdout +@@ -1,27 +1,27 @@ + Case-insensitive sorting: + // keep-sorted-test start case=no + '/bar', +-'/quux', ++'/Baz', + '/foo', +-'/Baz', ++'/quux', + '/Quux/etc', + // keep-sorted-test end + + Case-insensitive sorting with mixed-case duplicates: + // keep-sorted-test start case=no + Bar +-baz +-foo ++bar + bAz +-bar ++baZ +-baZ ++baz ++foo + spam + // keep-sorted-test end + + Case-insensitive sorting with numeric sorting: + // keep-sorted-test start case=no numeric=yes + bar_1 +-bAR_5 ++bAR_5 ++bar_5 +-BAR_100 +-bar_5 ++BAR_100 + // keep-sorted-test end diff --git a/goldens/comments.diff b/goldens/comments.diff new file mode 100644 index 0000000..69640e6 --- /dev/null +++ b/goldens/comments.diff @@ -0,0 +1,116 @@ +--- stdin ++++ stdout +@@ -1,32 +1,32 @@ + Sticky comments: + // keep-sorted-test start sticky_comments=yes +-foo + // comment + bar + // multi line + // comment + baz ++foo + // keep-sorted-test end + + Sticky comments with different comment sequence: + # keep-sorted-test start sticky_comments=yes +-foo + # comment + bar ++foo + # keep-sorted-test end + + Sticky comments with wrong comment sequence: + # keep-sorted-test start sticky_comments=yes +-foo +-bar + // comment with wrong comment sequence ++bar ++foo + # keep-sorted-test end + + Trailing comments: + // keep-sorted-test start sticky_comments=yes +-foo + // comment + bar ++foo + // trailing + // comment + // keep-sorted-test end +@@ -39,54 +17,54 @@ + + Only non-sticky comments: + // keep-sorted-test start sticky_comments=no +-// only ++// comments +-// comments ++// only + // keep-sorted-test end + + Slash-star-style comments: +-/* keep-sorted-test start */ ++/* keep-sorted-test start */ ++1 +-2 +-1 ++2 + /* comment on 3 */ + 3 + /* keep-sorted-test end */ + + Dash-dash-style comments: +--- keep-sorted-test start ++-- keep-sorted-test start ++1 +-2 +-1 ++2 + -- comment on 3 + 3 + -- keep-sorted-test end + + Semicolon-style comments: +-; keep-sorted-test start ++; keep-sorted-test start ++1 +-2 +-1 ++2 + ; comment on 3 + 3 + ; keep-sorted-test end + + HTML-style comments: +- ++ ++1 +-2 +-1 ++2 + + 3 + + + Additional prefixes aren't counted as part of the comment: +-// some prefix (normally this is go/) keep-sorted-test start ++// some prefix (normally this is go/) keep-sorted-test start ++1 +-2 +-1 ++2 + // comment on 3 + 3 + // keep-sorted-test end + + Non-comment prefixes are still sorted: +-* keep-sorted-test start +-2 +-1 ++* keep-sorted-test start +-* not a comment on 3 ++* not a comment on 3 ++1 ++2 + 3 + * keep-sorted-test end diff --git a/goldens/duplicates.diff b/goldens/duplicates.diff new file mode 100644 index 0000000..9b59894 --- /dev/null +++ b/goldens/duplicates.diff @@ -0,0 +1,30 @@ +--- stdin ++++ stdout +@@ -1,23 +1,20 @@ + Remove duplicates: + // keep-sorted-test start remove_duplicates=yes +-foo + bar + foo + // keep-sorted-test end + + Remove duplicates with comments: + // keep-sorted-test start remove_duplicates=yes sticky_comments=yes +-foo +-bar +-// Foo again ++bar + foo + // Foo again + foo + // keep-sorted-test end + + Preserve duplicates: +-// keep-sorted-test start remove_duplicates=no +-foo ++// keep-sorted-test start remove_duplicates=no +-bar ++bar ++foo + foo + // keep-sorted-test end diff --git a/goldens/generate-goldens.sh b/goldens/generate-goldens.sh index f557d44..15def60 100755 --- a/goldens/generate-goldens.sh +++ b/goldens/generate-goldens.sh @@ -24,10 +24,14 @@ git_dir="$(git -C "${dir}" rev-parse --show-toplevel)" for i in "$@"; do out="${i%%in}out" err="${i%%in}err" + diff="${i%%in}diff" go run "${git_dir}" --id=keep-sorted-test --omit-timestamps - <"${i}" >"${out}" 2>"${err}" \ || true # Ignore any non-zero exit codes. if (( $(wc -l < "${err}") == 0 )); then rm "${err}" fi + + go run "${git_dir}" --id=keep-sorted-test --mode=diff --omit-timestamps - <"${i}" >"${diff}" 2>/dev/null \ + || true # Ignore any non-zero exit codes. done diff --git a/goldens/golden_test.go b/goldens/golden_test.go index 165b506..b3d354a 100644 --- a/goldens/golden_test.go +++ b/goldens/golden_test.go @@ -61,7 +61,7 @@ func TestGoldens(t *testing.T) { t.Fatalf("Did not find any golden files.") } - needsRegen := make(chan string, 2*len(tcs)) + needsRegen := make(chan string, 3*len(tcs)) // The outer t.Run doesn't return until all the parallel tests have completed. t.Run("parallelTests", func(t *testing.T) { for _, tc := range tcs { @@ -80,6 +80,12 @@ func TestGoldens(t *testing.T) { } t.Fatalf("Could not read .out file: %v", err) } + wantDiff, err := os.ReadFile(filepath.Join(dir, tc+".diff")) + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + t.Fatalf("Could not read .diff file: %v", err) + } + } wantErr, err := os.ReadFile(filepath.Join(dir, tc+".err")) if err != nil { if !errors.Is(err, os.ErrNotExist) { @@ -91,7 +97,7 @@ func TestGoldens(t *testing.T) { wantErr = []byte(strings.ReplaceAll(string(wantErr), "\r\n", "\n")) wantErr = []byte(strings.ReplaceAll(string(wantErr), "\r", "\n")) - gotOut, gotErr, exitCode, err := runKeepSorted(in) + gotOut, gotErr, exitCode, err := runKeepSorted(in, "fix") if err != nil { t.Errorf("Had trouble running keep-sorted: %v", err) } @@ -104,7 +110,20 @@ func TestGoldens(t *testing.T) { needsRegen <- inFile } - gotOut2, _, exitCode2, err := runKeepSorted(strings.NewReader(gotOut)) + _, err = in.Seek(0, 0) + if err != nil { + t.Fatalf("Had trouble seeking file: %v", err) + } + gotDiff, _, _, err := runKeepSorted(in, "diff") + if err != nil { + t.Errorf("Had trouble running keep-sorted --mode diff: %v", err) + } + if diff := cmp.Diff(string(wantDiff), gotDiff); diff != "" { + t.Errorf("keep-sorted --mode diff out diff (-want +got):\n%s", diff) + needsRegen <- inFile + } + + gotOut2, _, exitCode2, err := runKeepSorted(strings.NewReader(gotOut), "fix") if err != nil { t.Errorf("Had trouble running keep-sorted on keep-sorted output: %v", err) } @@ -134,8 +153,8 @@ func showTopLevel(dir string) (string, error) { return strings.TrimSpace(string(b)), err } -func runKeepSorted(stdin io.Reader) (stdout, stderr string, exitCode int, err error) { - cmd := exec.Command("go", "run", gitDir, "--id=keep-sorted-test", "--omit-timestamps", "-") +func runKeepSorted(stdin io.Reader, mode string) (stdout, stderr string, exitCode int, err error) { + cmd := exec.Command("go", "run", gitDir, "--id=keep-sorted-test", "--mode="+mode, "--omit-timestamps", "-") cmd.Stdin = stdin outPipe, err := cmd.StdoutPipe() if err != nil { diff --git a/goldens/group.diff b/goldens/group.diff new file mode 100644 index 0000000..443d724 --- /dev/null +++ b/goldens/group.diff @@ -0,0 +1,506 @@ +--- stdin ++++ stdout +@@ -1,264 +1,268 @@ + Group indented lines: + public class Foo { + // keep-sorted-test start group=yes +- private final Foo foo; +- private final Bar bar; ++ private final Bar bar; + private final Baz baz = + new Baz(); +- private final Qux qux; ++ private final Foo foo; +- // keep-sorted-test end +- } +- +-Same thing but it's tabs: +- public class Foo { +- // keep-sorted-test start group=yes +- private final Foo foo; +- private final Bar bar; +- private final Baz baz = +- new Baz(); +- private final Qux qux; +- // keep-sorted-test end +- } +- +-Do not count indent from empty lines: +- // keep-sorted-test start +- +- a +- c +- b +- // keep-sorted-test end +- +-Multiple indentions: +- public class Foo { +- // keep-sorted-test start group=yes +- private final Foo foo; +- private final Bar bar; +- private final Baz baz = +- new +- Baz(); +- private final Qux qux; +- // keep-sorted-test end +- } +- +-With sticky comments: +- public class Foo { +- // keep-sorted-test start group=yes sticky_comments=yes +- private final Foo foo; +- private final Bar bar; +- // What a long line! +- private final Baz baz = +- new Baz(); +- private final Qux qux; +- // keep-sorted-test end +- } +- +-Sorting doesn't take newline into account +- // keep-sorted-test start group=yes +- line 4 +- line +- 3 +- line +- 1 +- line 2 +- // keep-sorted-test end +- +-With list separator +- // keep-sorted-test start group=yes +- Foo foo, +- Bar bar, +- Baz +- baz +- // keep-sorted-test end +- +-Without whitespace on unbroken lines +- // keep-sorted-test start group=yes +- SomeLongEnumTypeNameWithLongValueNames.D_SHORT_VALUE +- SomeLongEnumTypeNameWithLongValueNames +- .C_SOME_LONG_ENUM_VALUE_THAT_REQUIRES_A_LINE_BREAK +- SomeLongEnumTypeNameWithLongValueNames.B_SHORT_VALUE +- SomeLongEnumTypeNameWithLongValueNames +- .A_SOME_LONG_ENUM_VALUE_THAT_REQUIRES_A_LINE_BREAK +- // keep-sorted-test end +- +-Without grouping: +- public class Foo { +- // keep-sorted-test start group=no +- private final Foo foo; +- private final Bar bar; +- private final Baz baz = +- new Baz(); +- private final Qux qux; +- // keep-sorted-test end +- } +- +-Indented markdown lists: +- +- +- * Foo +- * Wise insight +- * Bar +- * Baz +- * Philosophical conjecture +- +- +- +-Nested keep-sorted +- // keep-sorted-test start group=yes +- private static final List b = [ +- // keep-sorted-test start +- "x", +- "z", +- "y" +- // keep-sorted-test end +- ]; +- private static final List a = [ +- // keep-sorted-test start +- "3", +- "2", +- "1" +- // keep-sorted-test end +- ]; +- // keep-sorted-test end +- +-Nested keep-sorted, nested blocks change their number of lines. +- // keep-sorted-test start group=yes +- private static final List b = [ +- // keep-sorted-test start +- "x", +- "x", +- "y" +- // keep-sorted-test end +- ]; +- private static final List a = [ +- // keep-sorted-test start newline_separated=yes +- "3", +- "2", +- "1" +- // keep-sorted-test end +- ]; +- // keep-sorted-test end +- +-Nested keep-sorted, nested blocks with newlines=2. +- // keep-sorted-test start group=yes +- private static final List b = [ +- // keep-sorted-test start +- "x", +- "x", +- "y" +- // keep-sorted-test end +- ]; +- private static final List a = [ +- // keep-sorted-test start newline_separated=2 +- "3", +- "2", +- "1" +- // keep-sorted-test end +- ]; +- // keep-sorted-test end +- +- +-Nested keep-sorted without indentation +- // keep-sorted-test start group=yes newline_separated=yes +- +- // def +- // keep-sorted-test start +- 3 +- 1 +- 2 +- // keep-sorted-test end +- +- // abc +- // keep-sorted-test start +- b +- c +- a +- // keep-sorted-test end +- +- // keep-sorted-test end +- +-Nested keep-sorted without indentation, with newlines=3: +- // keep-sorted-test start group=yes newline_separated=3 +- +- // def +- // keep-sorted-test start +- 3 +- 1 +- 2 +- // keep-sorted-test end +- +- // abc +- // keep-sorted-test start +- b +- c +- a +- // keep-sorted-test end +- +- // keep-sorted-test end +- +-Sorting a switch statement with consecutive cases. +-Note: This doesn't actually work how I was hoping, but it does exercise an edge case. +- switch (foo) { +- // keep-sorted-test start group_prefixes=case +- case 2: +- return 2; +- case 6: +- return 6; +- case 4: +- return 4; +- case 3: +- case 1: +- case 5: +- return 10 +- // keep-sorted-test end +- +-Sorting a switch statement with consecutive cases using nested keep-sorted block +- switch (foo) { +- // keep-sorted-test start +- case 2: +- return 2; +- case 6: +- return 6; +- case 4: +- return 4; +- // keep-sorted-test start +- case 3: +- case 1: +- case 5: +- // keep-sorted-test end ++ private final Qux qux; ++ // keep-sorted-test end ++ } ++ ++Same thing but it's tabs: ++ public class Foo { ++ // keep-sorted-test start group=yes ++ private final Bar bar; ++ private final Baz baz = ++ new Baz(); ++ private final Foo foo; ++ private final Qux qux; ++ // keep-sorted-test end ++ } ++ ++Do not count indent from empty lines: ++ // keep-sorted-test start ++ ++ a ++ b ++ c ++ // keep-sorted-test end ++ ++Multiple indentions: ++ public class Foo { ++ // keep-sorted-test start group=yes ++ private final Bar bar; ++ private final Baz baz = ++ new ++ Baz(); ++ private final Foo foo; ++ private final Qux qux; ++ // keep-sorted-test end ++ } ++ ++With sticky comments: ++ public class Foo { ++ // keep-sorted-test start group=yes sticky_comments=yes ++ private final Bar bar; ++ // What a long line! ++ private final Baz baz = ++ new Baz(); ++ private final Foo foo; ++ private final Qux qux; ++ // keep-sorted-test end ++ } ++ ++Sorting doesn't take newline into account ++ // keep-sorted-test start group=yes ++ line ++ 1 ++ line 2 ++ line ++ 3 ++ line 4 ++ // keep-sorted-test end ++ ++With list separator ++ // keep-sorted-test start group=yes ++ Bar bar, ++ Baz ++ baz, ++ Foo foo ++ // keep-sorted-test end ++ ++Without whitespace on unbroken lines ++ // keep-sorted-test start group=yes ++ SomeLongEnumTypeNameWithLongValueNames ++ .A_SOME_LONG_ENUM_VALUE_THAT_REQUIRES_A_LINE_BREAK ++ SomeLongEnumTypeNameWithLongValueNames.B_SHORT_VALUE ++ SomeLongEnumTypeNameWithLongValueNames ++ .C_SOME_LONG_ENUM_VALUE_THAT_REQUIRES_A_LINE_BREAK ++ SomeLongEnumTypeNameWithLongValueNames.D_SHORT_VALUE ++ // keep-sorted-test end ++ ++Without grouping: ++ public class Foo { ++ // keep-sorted-test start group=no ++ new Baz(); ++ private final Bar bar; ++ private final Baz baz = ++ private final Foo foo; ++ private final Qux qux; ++ // keep-sorted-test end ++ } ++ ++Indented markdown lists: ++ ++ ++ * Bar ++ * Baz ++ * Philosophical conjecture ++ * Foo ++ * Wise insight ++ ++ ++ ++Nested keep-sorted ++ // keep-sorted-test start group=yes ++ private static final List a = [ ++ // keep-sorted-test start ++ "1", ++ "2", ++ "3" ++ // keep-sorted-test end ++ ]; ++ private static final List b = [ ++ // keep-sorted-test start ++ "x", ++ "y", ++ "z" ++ // keep-sorted-test end ++ ]; ++ // keep-sorted-test end ++ ++Nested keep-sorted, nested blocks change their number of lines. ++ // keep-sorted-test start group=yes ++ private static final List a = [ ++ // keep-sorted-test start newline_separated=yes ++ "1", ++ ++ "2", ++ ++ "3" ++ // keep-sorted-test end ++ ]; ++ private static final List b = [ ++ // keep-sorted-test start ++ "x", ++ "y" ++ // keep-sorted-test end ++ ]; ++ // keep-sorted-test end ++ ++Nested keep-sorted, nested blocks with newlines=2. ++ // keep-sorted-test start group=yes ++ private static final List a = [ ++ // keep-sorted-test start newline_separated=2 ++ "1", ++ ++ ++ "2", ++ ++ ++ "3" ++ // keep-sorted-test end ++ ]; ++ private static final List b = [ ++ // keep-sorted-test start ++ "x", ++ "y" ++ // keep-sorted-test end ++ ]; ++ // keep-sorted-test end ++ ++ ++Nested keep-sorted without indentation ++ // keep-sorted-test start group=yes newline_separated=yes ++ // def ++ // keep-sorted-test start ++ 1 ++ 2 ++ 3 ++ // keep-sorted-test end ++ ++ // abc ++ // keep-sorted-test start ++ a ++ b ++ c ++ // keep-sorted-test end ++ ++ // keep-sorted-test end ++ ++Nested keep-sorted without indentation, with newlines=3: ++ // keep-sorted-test start group=yes newline_separated=3 ++ // def ++ // keep-sorted-test start ++ 1 ++ 2 ++ 3 ++ // keep-sorted-test end ++ ++ ++ ++ // abc ++ // keep-sorted-test start ++ a ++ b ++ c ++ // keep-sorted-test end ++ ++ // keep-sorted-test end ++ ++Sorting a switch statement with consecutive cases. ++Note: This doesn't actually work how I was hoping, but it does exercise an edge case. ++ switch (foo) { ++ // keep-sorted-test start group_prefixes=case ++ case 2: ++ return 2; ++ case 6: ++ return 6; ++ case 4: ++ return 4; ++ case 3: ++ case 1: ++ case 5: ++ return 10 ++ // keep-sorted-test end ++ ++Sorting a switch statement with consecutive cases using nested keep-sorted block ++ switch (foo) { ++ // keep-sorted-test start ++ // keep-sorted-test start ++ case 1: ++ case 3: ++ case 5: ++ // keep-sorted-test end ++ return 10 ++ case 2: ++ return 2; ++ case 4: ++ return 4; ++ case 6: +- return 10 ++ return 6; + // keep-sorted-test end + + Sorting a switch statement with consecutive cases using nested keep-sorted block + where the nested keep-sorted block shouldn't be the first element. + switch (foo) { + // keep-sorted-test start +- case 5: ++ case 1: +- return 5; ++ return 1; + // keep-sorted-test start + case 2: +- case 6: ++ case 4: +- case 4: ++ case 6: + // keep-sorted-test end + return 10; + case 3: + return 3; +- case 1: ++ case 5: +- return 1; ++ return 5; + // keep-sorted-test end + + The same, except block=yes is also set. + switch (foo) { + // keep-sorted-test start block=yes +- case 5: ++ case 1: +- return 5; ++ return 1; + // keep-sorted-test start block=yes + case 2: +- case 6: ++ case 4: +- case 4: ++ case 6: + // keep-sorted-test end + return 10; + case 3: + return 3; +- case 1: ++ case 5: +- return 1; ++ return 5; + // keep-sorted-test end diff --git a/goldens/ignore_prefixes.diff b/goldens/ignore_prefixes.diff new file mode 100644 index 0000000..4bb7ce4 --- /dev/null +++ b/goldens/ignore_prefixes.diff @@ -0,0 +1,67 @@ +--- stdin ++++ stdout +@@ -8,18 +8,18 @@ + + Needs sorting: + // keep-sorted-test start ignore_prefixes=A,B +- zebra ++ Bar ++ Baz + Aoo +- Bar +- Baz ++ zebra + // keep-sorted-test end + + Case insensitive needs sorting: + // keep-sorted-test start case=no ignore_prefixes=a,b +- zebra ++ Bar ++ Baz + Aoo +- Bar +- Baz ++ zebra + // keep-sorted-test end + + More practical already sorted: +@@ -32,24 +26,24 @@ + More practical needs sorting: + // keep-sorted-test start ignore_prefixes=fs.setBoolFlag,fs.setIntFlag + fs.setBoolFlag("nvme_paws_with_cute_toebeans", true) +- fs.setBoolFlag("nvme_whiskered_adorable_dog", true) +- fs.setIntFlag("nvme_pretty_whiskered_kitten", 6) +- // keep-sorted-test end +- +-Combine with numerical: +- # keep-sorted-test start numeric=yes ignore_prefixes=R2D2,C3PO,R4 +- R2D2_BOLTS_5_MM, +- R2D2_BOLTS_10_MM, +- R2D2_PROJECTOR, +- C3PO_ARM_L, +- C3PO_ARM_R, ++ fs.setIntFlag("nvme_pretty_whiskered_kitten", 6) ++ fs.setBoolFlag("nvme_whiskered_adorable_dog", true) ++ // keep-sorted-test end ++ ++Combine with numerical: ++ # keep-sorted-test start numeric=yes ignore_prefixes=R2D2,C3PO,R4 ++ C3PO_ARM_L, ++ C3PO_ARM_R, ++ R2D2_BOLTS_5_MM, ++ R2D2_BOLTS_10_MM, + C3PO_HEAD, +- R4_MOTIVATOR, ++ R4_MOTIVATOR, ++ R2D2_PROJECTOR, + # keep-sorted-test end + + Prefixes with spaces: +- # keep-sorted-test start ignore_prefixes=['*', '* ['] +- * foo ++ # keep-sorted-test start ignore_prefixes=['*', '* ['] + * bar +- * [baz](path/to/baz) ++ * [baz](path/to/baz) ++ * foo + # keep-sorted-test end diff --git a/goldens/numeric.diff b/goldens/numeric.diff new file mode 100644 index 0000000..382973e --- /dev/null +++ b/goldens/numeric.diff @@ -0,0 +1,89 @@ +--- stdin ++++ stdout +@@ -1,46 +1,46 @@ + Numeric sorting: + // keep-sorted-test start numeric=yes +-FOO_100 +-FOO_2 +-FOO_3 + BAR_1 + BAR_2 +-BAR_10 +-BAR_00000000000000000000000000000000000000000000009 ++BAR_00000000000000000000000000000000000000000000009 +-BAR_99999999999999999999999999999999999999999999999 ++BAR_10 ++BAR_99999999999999999999999999999999999999999999999 +-// keep-sorted-test end +- +- +-Mixed numeric and preference sorting with sticky comments: +-deployment_state = [ +- // keep-sorted-test start numeric=yes prefix_order=INIT,ROLLOUT,COMPLETE +- // All done. +- COMPLETE, +- // Start initialisation +- INIT_1, +- INIT_5, +- INIT_10, +- // Only deploy to 0.1% +- ROLLOUT_0_1, +- // just one percent. +- ROLLOUT_1, +- // Nearly done... +- ROLLOUT_100, +- ROLLOUT_10, +- ROLLOUT_5, +- ROLLOUT_50, +- // keep-sorted-test end +-] +- +-Prefix containing a number with numeric sorting: +-droid_components = [ +- // keep-sorted-test start numeric=yes prefix_order=R2,C3 +- C3PO_HEAD, +- C3PO_ARM_L, +- R4_MOTIVATOR, +- C3PO_ARM_R, +- R2D2_BOLTS_10_MM, ++FOO_2 ++FOO_3 ++FOO_100 ++// keep-sorted-test end ++ ++ ++Mixed numeric and preference sorting with sticky comments: ++deployment_state = [ ++ // keep-sorted-test start numeric=yes prefix_order=INIT,ROLLOUT,COMPLETE ++ // Start initialisation ++ INIT_1, ++ INIT_5, ++ INIT_10, ++ // Only deploy to 0.1% ++ ROLLOUT_0_1, ++ // just one percent. ++ ROLLOUT_1, ++ ROLLOUT_5, ++ ROLLOUT_10, ++ ROLLOUT_50, ++ // Nearly done... ++ ROLLOUT_100, ++ // All done. ++ COMPLETE, ++ // keep-sorted-test end ++] ++ ++Prefix containing a number with numeric sorting: ++droid_components = [ ++ // keep-sorted-test start numeric=yes prefix_order=R2,C3 ++ R2D2_BOLTS_5_MM, ++ R2D2_BOLTS_10_MM, ++ R2D2_PROJECTOR, ++ C3PO_ARM_L, ++ C3PO_ARM_R, +- R2D2_PROJECTOR, ++ C3PO_HEAD, +- R2D2_BOLTS_5_MM, ++ R4_MOTIVATOR, + // keep-sorted-test end + ] diff --git a/goldens/prefixes.diff b/goldens/prefixes.diff new file mode 100644 index 0000000..78a1807 --- /dev/null +++ b/goldens/prefixes.diff @@ -0,0 +1,94 @@ +--- stdin ++++ stdout +@@ -1,9 +1,9 @@ + preferred prefixes putting 'build_target' before 'branch_name': + build_specs { + # keep-sorted-test start prefix_order=build_target,branch_name +- build_target: "//foo/baz" +- branch_name: "dev" ++ build_target: "//foo/bar" +- build_target: "//foo/bar" ++ build_target: "//foo/baz" ++ branch_name: "dev" + branch_name: "prod" + # keep-sorted-test end + } +@@ -11,42 +11,42 @@ + Put the specified prefixes at the end: + items = [ + # keep-sorted-test start prefix_order=,FOO,BAR +- FOO, +- DING, +- BAR +- BATS, +- # keep-sorted-test end +- ] +- +-Case insensitive put the specified prefixes at the end: +- items = [ +- # keep-sorted-test start case=no prefix_order=,foo,bar +- FOO, +- DING, +- BAR +- BATS, +- # keep-sorted-test end +- ] +- +-Put a group of items in the beginning, another group at the end: +- // keep-sorted-test start prefix_order=INIT_,,FINAL_ +- INIT_FOO, +- FINAL_FOO, +- INIT_BAR, +- FINAL_BAR, +- DO_STUFF, +- DO_MORE_STUFF, +- ZAP_THINGS +- // keep-sorted-test end +- +-preferred prefixes with comments: +- build_specs { +- # keep-sorted-test start prefix_order=build_target,branch_name +- build_target: "//foo/baz" +- # required for development. +- branch_name: "dev" ++ BATS, ++ DING, ++ FOO, ++ BAR ++ # keep-sorted-test end ++ ] ++ ++Case insensitive put the specified prefixes at the end: ++ items = [ ++ # keep-sorted-test start case=no prefix_order=,foo,bar ++ BATS, ++ DING, ++ FOO, ++ BAR ++ # keep-sorted-test end ++ ] ++ ++Put a group of items in the beginning, another group at the end: ++ // keep-sorted-test start prefix_order=INIT_,,FINAL_ ++ INIT_BAR, ++ INIT_FOO, ++ DO_MORE_STUFF, ++ DO_STUFF, ++ ZAP_THINGS, ++ FINAL_BAR, ++ FINAL_FOO ++ // keep-sorted-test end ++ ++preferred prefixes with comments: ++ build_specs { ++ # keep-sorted-test start prefix_order=build_target,branch_name ++ # raise the bar! ++ build_target: "//foo/bar" ++ build_target: "//foo/baz" ++ # required for development. +- # raise the bar! +- build_target: "//foo/bar" ++ branch_name: "dev" + branch_name: "prod" + # keep-sorted-test end + } diff --git a/goldens/separator.diff b/goldens/separator.diff new file mode 100644 index 0000000..2932386 --- /dev/null +++ b/goldens/separator.diff @@ -0,0 +1,26 @@ +--- stdin ++++ stdout +@@ -1,17 +1,17 @@ + Comma separator: + static class Foo { + // keep-sorted-test start +- "Foo", ++ "Bar", +- "Bar", ++ "Baz", +- "Baz" ++ "Foo" + // keep-sorted-test end + } + + Comma separator with comments: +-// keep-sorted-test start sticky_comments=yes +-"Foo", ++// keep-sorted-test start sticky_comments=yes + // Sticky comment + "Bar", +-"Baz" ++"Baz", ++"Foo" + // Trailing comments + // keep-sorted-test end diff --git a/goldens/simple.diff b/goldens/simple.diff new file mode 100644 index 0000000..33db1ed --- /dev/null +++ b/goldens/simple.diff @@ -0,0 +1,177 @@ +--- stdin ++++ stdout +@@ -17,122 +17,123 @@ + + Needs sorting: + // keep-sorted-test start +-Foo + Bar + Baz ++Foo + // keep-sorted-test end + + Maintains indent: + static class Foo { + // keep-sorted-test start +- "Foo", ++ "Bar", +- "Bar", ++ "Baz", +- "Baz", ++ "Foo", + // keep-sorted-test end + } + + Empty line at end: + // keep-sorted-test start +-Foo + Bar + Baz +- ++Foo ++ + // keep-sorted-test end + + Multiple empty lines at end: + // keep-sorted-test start +-Foo + Bar + Baz +- ++Foo + ++ + // keep-sorted-test end + + Empty lines at start (duplicate lines discarded): + // keep-sorted-test start + +- +-Foo + Bar + Baz ++Foo + // keep-sorted-test end + + Empty lines at both: + // keep-sorted-test start + +-Foo +-Bar +-Baz +- +-// keep-sorted-test end +- +-"Empty" lines that are trailing indentation: +- // keep-sorted-test start +- +- Foo +- Bar +- Baz +- +- // keep-sorted-test end +- +-Same thing, but it's tabs. +- // keep-sorted-test start +- +- Foo ++Bar ++Baz ++Foo ++ ++// keep-sorted-test end ++ ++"Empty" lines that are trailing indentation: ++ // keep-sorted-test start ++ ++ Bar ++ Baz ++ Foo ++ ++ // keep-sorted-test end ++ ++Same thing, but it's tabs. ++ // keep-sorted-test start ++ + Bar +- Baz ++ Baz ++ Foo + + // keep-sorted-test end + + b/153572902 mdformat around lists: +- +- ++ +- * Foo ++ + * Bar +- * Baz ++ * Baz ++ * Foo + + + +-// keep-sorted-test start newline_separated=yes +-C +- ++// keep-sorted-test start newline_separated=yes + A + +-B ++B ++ ++C + // keep-sorted-test end + +-// keep-sorted-test start newline_separated=2 ++// keep-sorted-test start newline_separated=2 ++A ++ +-C ++ +- ++B +-A ++ + +-B ++C + // keep-sorted-test end + + Invalid option + keep-sorted-test start group=yes skip_lines=-1 foo=bar +- 2 ++ 1 +- 1 ++ 2 + 3 + keep-sorted-test end + + Invalid YAML + keep-sorted-test start allow_yaml_lists=yes ignore_prefixes=[abc, foo +- 2 ++ 1 +- 1 ++ 2 + 3 + keep-sorted-test end + + Ascending order (default): + // keep-sorted-test start +-c ++a + b +-a ++c + // keep-sorted-test end + + Descending order: + // keep-sorted-test start order=desc +-a ++c + b +-c ++a + // keep-sorted-test end diff --git a/goldens/skip_lines.diff b/goldens/skip_lines.diff new file mode 100644 index 0000000..ca98bf6 --- /dev/null +++ b/goldens/skip_lines.diff @@ -0,0 +1,85 @@ +--- stdin ++++ stdout +@@ -6,9 +6,9 @@ + // keep-sorted-test start skip_lines=2 + foo + bar +-c ++a + b +-a ++c + // keep-sorted-test end + + Number of skipped lines is greater than block size, so block is ignored: +@@ -21,42 +20,42 @@ + Skipping lines with nested blocks: + + This line should not be sorted. +-### Table 2 ++### Table 1 +- ++ + Name | Value + ------- | ----- +- Bravo | Foxtrot ++ Alpha | Foo ++ Bravo | Bar +- Alpha | Romeo ++ Charlie | Baz +- +-### Table 1 +- +- Name | Value +- ------- | ----- +- Delta | Qux +- Bravo | Bar +- Alpha | Foo +- Charlie | Baz +- +- +- +-Skip lines with group_prefixes: +-// keep-sorted-test start skip_lines=2 group_prefixes=: +-| birds | +-| ------------ | +-| blue footed | +-: booby | +-| crested | +-: bobwhite | +-| anhinga | ++ Delta | Qux ++ ++### Table 2 ++ ++ Name | Value ++ ------- | ----- ++ Alpha | Romeo ++ Bravo | Foxtrot ++ ++ ++ ++Skip lines with group_prefixes: ++// keep-sorted-test start skip_lines=2 group_prefixes=: ++| birds | ++| ------------ | ++| anhinga | ++| blue footed | ++: booby | ++| crested | ++: bobwhite | + // keep-sorted-test end + + Skip lines with group_prefixes indented: + // keep-sorted-test start skip_lines=2 group_prefixes=: + | birds | +- | ------------ | ++ | ------------ | ++ | anhinga | + | blue footed | + : booby | + | crested | +- : bobwhite | +- | anhinga | ++ : bobwhite | + // keep-sorted-test end diff --git a/goldens/sticky_prefixes.diff b/goldens/sticky_prefixes.diff new file mode 100644 index 0000000..71e4480 --- /dev/null +++ b/goldens/sticky_prefixes.diff @@ -0,0 +1,93 @@ +--- stdin ++++ stdout +@@ -1,49 +1,49 @@ + Sort these lines with various comments: + Flags( + // keep-sorted-test start sticky_prefixes=/**,@ +- /** Flag to do important things */ +- FLAG_OF_IMPORTANCE, +- @Deprecated +- DEPRECATED_FLAG, +- ALPHABETICALLY_FIRST_FLAG, +- // keep-sorted-test end +-) +- +-Multiple sticky prefixes per item: +-// keep-sorted-test start sticky_prefixes=@1,@2 +-@1 zulu +-@2 zulu +-Zulu +-@1 whiskey +-Whiskey +-@1 alpha +-@2 alpha +-Alpha +-// keep-sorted-test end +- +-With grouping: +-public class Foo { +- // keep-sorted-test start group=yes sticky_prefixes=@1,@2 +- private final Foo foo; +- private final Bar bar; +- @2 baz +- private final Baz baz = +- @1 new baz +- new Baz(); +- private final Qux qux; +- // keep-sorted-test end +-} +- +-Without sticky comment: +-// keep-sorted-test start sticky_comments=no sticky_prefixes=@1,@2 +-// Will go second. +-@1 delta +-Delta +-Charlie ++ ALPHABETICALLY_FIRST_FLAG, ++ @Deprecated ++ DEPRECATED_FLAG, ++ /** Flag to do important things */ ++ FLAG_OF_IMPORTANCE, ++ // keep-sorted-test end ++) ++ ++Multiple sticky prefixes per item: ++// keep-sorted-test start sticky_prefixes=@1,@2 ++@1 alpha ++@2 alpha ++Alpha ++@1 whiskey ++Whiskey ++@1 zulu ++@2 zulu ++Zulu ++// keep-sorted-test end ++ ++With grouping: ++public class Foo { ++ // keep-sorted-test start group=yes sticky_prefixes=@1,@2 ++ private final Bar bar; ++ @2 baz ++ private final Baz baz = ++ @1 new baz ++ new Baz(); ++ private final Foo foo; ++ private final Qux qux; ++ // keep-sorted-test end ++} ++ ++Without sticky comment: ++// keep-sorted-test start sticky_comments=no sticky_prefixes=@1,@2 ++// Always goes first ++// Will go second. + @1 bravo + @2 bravo +-Bravo ++Bravo ++Charlie +-// Always goes first ++@1 delta ++Delta + // keep-sorted-test end + + Dangling sticky items: diff --git a/goldens/trailing_commas.diff b/goldens/trailing_commas.diff new file mode 100644 index 0000000..e62921e --- /dev/null +++ b/goldens/trailing_commas.diff @@ -0,0 +1,47 @@ +--- stdin ++++ stdout +@@ -1,31 +1,31 @@ + Trailing comma except for last + keep-sorted-test start +- 3, ++ 1, +- 1, ++ 2, +- 2 ++ 3 + keep-sorted-test end + + + Trailing comma and a comment + TODO: https://github.com/google/keep-sorted/issues/33 - Fix this + keep-sorted-test start +- 3, # three ++ 1, ++ 2 ++ 3, # three +- 1, +- 2 +- keep-sorted-test end ++ keep-sorted-test end + + Trailing comma except for last, last has a comment + TODO: https://github.com/google/keep-sorted/issues/33 - Fix this + keep-sorted-test start +- 3, +- 1, ++ 1, +- 2 # two ++ 2 # two, ++ 3 + keep-sorted-test end + + Trailing comma and a comment, last has a comment + TODO: https://github.com/google/keep-sorted/issues/33 - Fix this +- keep-sorted-test start +- 3, # three ++ keep-sorted-test start + 1, +- 2 # two ++ 2 # two ++ 3, # three + keep-sorted-test end