@owenlamont/ryl 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/.github/CODEOWNERS +1 -0
  2. package/.github/dependabot.yml +13 -0
  3. package/.github/workflows/ci.yml +107 -0
  4. package/.github/workflows/release.yml +613 -0
  5. package/.github/workflows/update_dependencies.yml +61 -0
  6. package/.github/workflows/update_linters.yml +56 -0
  7. package/.pre-commit-config.yaml +87 -0
  8. package/.yamllint +4 -0
  9. package/AGENTS.md +200 -0
  10. package/Cargo.lock +908 -0
  11. package/Cargo.toml +32 -0
  12. package/LICENSE +21 -0
  13. package/README.md +230 -0
  14. package/bin/ryl.js +1 -0
  15. package/clippy.toml +1 -0
  16. package/docs/config-presets.md +100 -0
  17. package/img/benchmark-5x5-5runs.svg +2176 -0
  18. package/package.json +28 -0
  19. package/pyproject.toml +42 -0
  20. package/ruff.toml +107 -0
  21. package/rumdl.toml +20 -0
  22. package/rust-toolchain.toml +3 -0
  23. package/rustfmt.toml +3 -0
  24. package/scripts/benchmark_perf_vs_yamllint.py +400 -0
  25. package/scripts/coverage-missing.ps1 +80 -0
  26. package/scripts/coverage-missing.sh +60 -0
  27. package/src/bin/discover_config_bin.rs +24 -0
  28. package/src/cli_support.rs +33 -0
  29. package/src/conf/mod.rs +85 -0
  30. package/src/config.rs +2099 -0
  31. package/src/decoder.rs +326 -0
  32. package/src/discover.rs +31 -0
  33. package/src/lib.rs +19 -0
  34. package/src/lint.rs +558 -0
  35. package/src/main.rs +535 -0
  36. package/src/migrate.rs +233 -0
  37. package/src/rules/anchors.rs +517 -0
  38. package/src/rules/braces.rs +77 -0
  39. package/src/rules/brackets.rs +77 -0
  40. package/src/rules/colons.rs +475 -0
  41. package/src/rules/commas.rs +372 -0
  42. package/src/rules/comments.rs +299 -0
  43. package/src/rules/comments_indentation.rs +243 -0
  44. package/src/rules/document_end.rs +175 -0
  45. package/src/rules/document_start.rs +84 -0
  46. package/src/rules/empty_lines.rs +152 -0
  47. package/src/rules/empty_values.rs +255 -0
  48. package/src/rules/float_values.rs +259 -0
  49. package/src/rules/flow_collection.rs +562 -0
  50. package/src/rules/hyphens.rs +104 -0
  51. package/src/rules/indentation.rs +803 -0
  52. package/src/rules/key_duplicates.rs +218 -0
  53. package/src/rules/key_ordering.rs +303 -0
  54. package/src/rules/line_length.rs +326 -0
  55. package/src/rules/mod.rs +25 -0
  56. package/src/rules/new_line_at_end_of_file.rs +23 -0
  57. package/src/rules/new_lines.rs +95 -0
  58. package/src/rules/octal_values.rs +121 -0
  59. package/src/rules/quoted_strings.rs +577 -0
  60. package/src/rules/span_utils.rs +37 -0
  61. package/src/rules/trailing_spaces.rs +65 -0
  62. package/src/rules/truthy.rs +420 -0
  63. package/tests/brackets_carriage_return.rs +114 -0
  64. package/tests/build_global_cfg_error.rs +23 -0
  65. package/tests/cli_anchors_rule.rs +143 -0
  66. package/tests/cli_braces_rule.rs +104 -0
  67. package/tests/cli_brackets_rule.rs +104 -0
  68. package/tests/cli_colons_rule.rs +65 -0
  69. package/tests/cli_commas_rule.rs +104 -0
  70. package/tests/cli_comments_indentation_rule.rs +61 -0
  71. package/tests/cli_comments_rule.rs +67 -0
  72. package/tests/cli_config_data_error.rs +30 -0
  73. package/tests/cli_config_flags.rs +66 -0
  74. package/tests/cli_config_migrate.rs +229 -0
  75. package/tests/cli_document_end_rule.rs +92 -0
  76. package/tests/cli_document_start_rule.rs +92 -0
  77. package/tests/cli_empty_lines_rule.rs +87 -0
  78. package/tests/cli_empty_values_rule.rs +68 -0
  79. package/tests/cli_env_config.rs +34 -0
  80. package/tests/cli_exit_and_errors.rs +41 -0
  81. package/tests/cli_file_encoding.rs +203 -0
  82. package/tests/cli_float_values_rule.rs +64 -0
  83. package/tests/cli_format_options.rs +316 -0
  84. package/tests/cli_global_cfg_relaxed.rs +20 -0
  85. package/tests/cli_hyphens_rule.rs +104 -0
  86. package/tests/cli_indentation_rule.rs +65 -0
  87. package/tests/cli_invalid_project_config.rs +39 -0
  88. package/tests/cli_key_duplicates_rule.rs +104 -0
  89. package/tests/cli_key_ordering_rule.rs +59 -0
  90. package/tests/cli_line_length_rule.rs +85 -0
  91. package/tests/cli_list_files.rs +29 -0
  92. package/tests/cli_new_line_rule.rs +141 -0
  93. package/tests/cli_new_lines_rule.rs +119 -0
  94. package/tests/cli_octal_values_rule.rs +60 -0
  95. package/tests/cli_quoted_strings_rule.rs +47 -0
  96. package/tests/cli_toml_config.rs +119 -0
  97. package/tests/cli_trailing_spaces_rule.rs +77 -0
  98. package/tests/cli_truthy_rule.rs +83 -0
  99. package/tests/cli_yaml_files_negation.rs +45 -0
  100. package/tests/colons_rule.rs +303 -0
  101. package/tests/common/compat.rs +114 -0
  102. package/tests/common/fake_env.rs +93 -0
  103. package/tests/common/mod.rs +1 -0
  104. package/tests/conf_builtin.rs +9 -0
  105. package/tests/config_anchors.rs +84 -0
  106. package/tests/config_braces.rs +121 -0
  107. package/tests/config_brackets.rs +127 -0
  108. package/tests/config_commas.rs +79 -0
  109. package/tests/config_comments.rs +65 -0
  110. package/tests/config_comments_indentation.rs +20 -0
  111. package/tests/config_deep_merge_nonstring_key.rs +24 -0
  112. package/tests/config_document_end.rs +54 -0
  113. package/tests/config_document_start.rs +55 -0
  114. package/tests/config_empty_lines.rs +48 -0
  115. package/tests/config_empty_values.rs +35 -0
  116. package/tests/config_env_errors.rs +23 -0
  117. package/tests/config_env_invalid_inline.rs +15 -0
  118. package/tests/config_env_missing.rs +63 -0
  119. package/tests/config_env_shim.rs +301 -0
  120. package/tests/config_explicit_file_parse_error.rs +55 -0
  121. package/tests/config_extended_features.rs +225 -0
  122. package/tests/config_extends_inline.rs +185 -0
  123. package/tests/config_extends_sequence.rs +18 -0
  124. package/tests/config_find_project_home_boundary.rs +54 -0
  125. package/tests/config_find_project_two_files_in_cwd.rs +47 -0
  126. package/tests/config_float_values.rs +34 -0
  127. package/tests/config_from_yaml_paths.rs +32 -0
  128. package/tests/config_hyphens.rs +51 -0
  129. package/tests/config_ignore_errors.rs +243 -0
  130. package/tests/config_ignore_overrides.rs +83 -0
  131. package/tests/config_indentation.rs +65 -0
  132. package/tests/config_invalid_globs.rs +16 -0
  133. package/tests/config_invalid_types.rs +19 -0
  134. package/tests/config_key_duplicates.rs +34 -0
  135. package/tests/config_key_ordering.rs +70 -0
  136. package/tests/config_line_length.rs +65 -0
  137. package/tests/config_locale.rs +111 -0
  138. package/tests/config_merge.rs +26 -0
  139. package/tests/config_new_lines.rs +89 -0
  140. package/tests/config_octal_values.rs +33 -0
  141. package/tests/config_quoted_strings.rs +195 -0
  142. package/tests/config_rule_level.rs +147 -0
  143. package/tests/config_rules_non_string_keys.rs +23 -0
  144. package/tests/config_scalar_overrides.rs +27 -0
  145. package/tests/config_to_toml.rs +110 -0
  146. package/tests/config_toml_coverage.rs +80 -0
  147. package/tests/config_toml_discovery.rs +304 -0
  148. package/tests/config_trailing_spaces.rs +152 -0
  149. package/tests/config_truthy.rs +77 -0
  150. package/tests/config_yaml_files.rs +62 -0
  151. package/tests/config_yaml_files_all_non_string.rs +15 -0
  152. package/tests/config_yaml_files_empty.rs +30 -0
  153. package/tests/coverage_commas.rs +46 -0
  154. package/tests/decoder_decode.rs +338 -0
  155. package/tests/discover_config_bin_all.rs +66 -0
  156. package/tests/discover_config_bin_env_invalid_yaml.rs +26 -0
  157. package/tests/discover_config_bin_project_config_parse_error.rs +24 -0
  158. package/tests/discover_config_bin_user_global_error.rs +26 -0
  159. package/tests/discover_module.rs +30 -0
  160. package/tests/discover_per_file_dir.rs +10 -0
  161. package/tests/discover_per_file_project_config_error.rs +21 -0
  162. package/tests/float_values.rs +43 -0
  163. package/tests/lint_multi_errors.rs +32 -0
  164. package/tests/main_yaml_ok_filtering.rs +30 -0
  165. package/tests/migrate_module.rs +259 -0
  166. package/tests/resolve_ctx_empty_parent.rs +16 -0
  167. package/tests/rule_anchors.rs +442 -0
  168. package/tests/rule_braces.rs +258 -0
  169. package/tests/rule_brackets.rs +217 -0
  170. package/tests/rule_commas.rs +205 -0
  171. package/tests/rule_comments.rs +197 -0
  172. package/tests/rule_comments_indentation.rs +127 -0
  173. package/tests/rule_document_end.rs +118 -0
  174. package/tests/rule_document_start.rs +60 -0
  175. package/tests/rule_empty_lines.rs +96 -0
  176. package/tests/rule_empty_values.rs +102 -0
  177. package/tests/rule_float_values.rs +109 -0
  178. package/tests/rule_hyphens.rs +65 -0
  179. package/tests/rule_indentation.rs +455 -0
  180. package/tests/rule_key_duplicates.rs +76 -0
  181. package/tests/rule_key_ordering.rs +207 -0
  182. package/tests/rule_line_length.rs +200 -0
  183. package/tests/rule_new_lines.rs +51 -0
  184. package/tests/rule_octal_values.rs +53 -0
  185. package/tests/rule_quoted_strings.rs +290 -0
  186. package/tests/rule_trailing_spaces.rs +41 -0
  187. package/tests/rule_truthy.rs +236 -0
  188. package/tests/user_global_invalid_yaml.rs +32 -0
  189. package/tests/yamllint_compat_anchors.rs +280 -0
  190. package/tests/yamllint_compat_braces.rs +411 -0
  191. package/tests/yamllint_compat_brackets.rs +364 -0
  192. package/tests/yamllint_compat_colons.rs +298 -0
  193. package/tests/yamllint_compat_colors.rs +80 -0
  194. package/tests/yamllint_compat_commas.rs +375 -0
  195. package/tests/yamllint_compat_comments.rs +167 -0
  196. package/tests/yamllint_compat_comments_indentation.rs +281 -0
  197. package/tests/yamllint_compat_config.rs +170 -0
  198. package/tests/yamllint_compat_document_end.rs +243 -0
  199. package/tests/yamllint_compat_document_start.rs +136 -0
  200. package/tests/yamllint_compat_empty_lines.rs +117 -0
  201. package/tests/yamllint_compat_empty_values.rs +179 -0
  202. package/tests/yamllint_compat_float_values.rs +216 -0
  203. package/tests/yamllint_compat_hyphens.rs +223 -0
  204. package/tests/yamllint_compat_indentation.rs +398 -0
  205. package/tests/yamllint_compat_key_duplicates.rs +139 -0
  206. package/tests/yamllint_compat_key_ordering.rs +170 -0
  207. package/tests/yamllint_compat_line_length.rs +375 -0
  208. package/tests/yamllint_compat_list.rs +127 -0
  209. package/tests/yamllint_compat_new_line.rs +133 -0
  210. package/tests/yamllint_compat_newline_types.rs +185 -0
  211. package/tests/yamllint_compat_octal_values.rs +172 -0
  212. package/tests/yamllint_compat_quoted_strings.rs +154 -0
  213. package/tests/yamllint_compat_syntax.rs +200 -0
  214. package/tests/yamllint_compat_trailing_spaces.rs +162 -0
  215. package/tests/yamllint_compat_truthy.rs +130 -0
  216. package/tests/yamllint_compat_yaml_files.rs +81 -0
  217. package/typos.toml +2 -0
@@ -0,0 +1,223 @@
1
+ use std::fs;
2
+
3
+ use tempfile::tempdir;
4
+
5
+ #[path = "common/compat.rs"]
6
+ mod compat;
7
+
8
+ use compat::{
9
+ SCENARIOS, build_ryl_command, build_yamllint_command, capture_with_env,
10
+ ensure_yamllint_installed,
11
+ };
12
+
13
+ #[test]
14
+ fn hyphens_rule_matches_yamllint() {
15
+ ensure_yamllint_installed();
16
+
17
+ let dir = tempdir().unwrap();
18
+
19
+ let default_cfg = dir.path().join("hyphens-default.yml");
20
+ fs::write(
21
+ &default_cfg,
22
+ "rules:\n document-start: disable\n hyphens: enable\n",
23
+ )
24
+ .unwrap();
25
+
26
+ let warning_cfg = dir.path().join("hyphens-warning.yml");
27
+ fs::write(
28
+ &warning_cfg,
29
+ "rules:\n document-start: disable\n hyphens:\n level: warning\n",
30
+ )
31
+ .unwrap();
32
+
33
+ let max_cfg = dir.path().join("hyphens-max.yml");
34
+ fs::write(
35
+ &max_cfg,
36
+ "rules:\n document-start: disable\n hyphens:\n max-spaces-after: 3\n",
37
+ )
38
+ .unwrap();
39
+
40
+ let ignore_cfg = dir.path().join("hyphens-ignore.yml");
41
+ fs::write(
42
+ &ignore_cfg,
43
+ "rules:\n document-start: disable\n hyphens:\n ignore:\n - ignored.yaml\n",
44
+ )
45
+ .unwrap();
46
+
47
+ let ignore_list = dir.path().join("hyphens-ignore.txt");
48
+ fs::write(&ignore_list, "ignored-from-file.yaml\n").unwrap();
49
+
50
+ let ignore_from_file_cfg = dir.path().join("hyphens-ignore-from-file.yml");
51
+ let ignore_path = ignore_list.display().to_string().replace('\'', "''");
52
+ fs::write(
53
+ &ignore_from_file_cfg,
54
+ format!(
55
+ "rules:\n document-start: disable\n hyphens:\n ignore-from-file: '{}'\n",
56
+ ignore_path
57
+ ),
58
+ )
59
+ .unwrap();
60
+
61
+ let default_file = dir.path().join("bad.yaml");
62
+ fs::write(&default_file, "---\n- item\n").unwrap();
63
+
64
+ let max_violation_file = dir.path().join("bad-max.yaml");
65
+ fs::write(&max_violation_file, "---\n- item\n").unwrap();
66
+
67
+ let max_ok_file = dir.path().join("ok-max.yaml");
68
+ fs::write(&max_ok_file, "---\n- item\n").unwrap();
69
+
70
+ let ignored_file = dir.path().join("ignored.yaml");
71
+ fs::write(&ignored_file, "---\n- item\n").unwrap();
72
+
73
+ let ignored_from_file = dir.path().join("ignored-from-file.yaml");
74
+ fs::write(&ignored_from_file, "---\n- item\n").unwrap();
75
+
76
+ let exe = env!("CARGO_BIN_EXE_ryl");
77
+
78
+ for scenario in SCENARIOS {
79
+ let mut ryl_default = build_ryl_command(exe, scenario.ryl_format);
80
+ ryl_default.arg("-c").arg(&default_cfg).arg(&default_file);
81
+ let (ryl_default_code, ryl_default_output) =
82
+ capture_with_env(ryl_default, scenario.envs);
83
+
84
+ let mut yam_default = build_yamllint_command(scenario.yam_format);
85
+ yam_default.arg("-c").arg(&default_cfg).arg(&default_file);
86
+ let (yam_default_code, yam_default_output) =
87
+ capture_with_env(yam_default, scenario.envs);
88
+
89
+ assert_eq!(ryl_default_code, 1, "ryl default exit ({})", scenario.label);
90
+ assert_eq!(
91
+ yam_default_code, 1,
92
+ "yamllint default exit ({})",
93
+ scenario.label
94
+ );
95
+ assert_eq!(
96
+ ryl_default_output, yam_default_output,
97
+ "default diagnostics mismatch ({})",
98
+ scenario.label
99
+ );
100
+
101
+ let mut ryl_warning = build_ryl_command(exe, scenario.ryl_format);
102
+ ryl_warning.arg("-c").arg(&warning_cfg).arg(&default_file);
103
+ let (ryl_warning_code, ryl_warning_output) =
104
+ capture_with_env(ryl_warning, scenario.envs);
105
+
106
+ let mut yam_warning = build_yamllint_command(scenario.yam_format);
107
+ yam_warning.arg("-c").arg(&warning_cfg).arg(&default_file);
108
+ let (yam_warning_code, yam_warning_output) =
109
+ capture_with_env(yam_warning, scenario.envs);
110
+
111
+ assert_eq!(ryl_warning_code, 0, "ryl warning exit ({})", scenario.label);
112
+ assert_eq!(
113
+ yam_warning_code, 0,
114
+ "yamllint warning exit ({})",
115
+ scenario.label
116
+ );
117
+ assert_eq!(
118
+ ryl_warning_output, yam_warning_output,
119
+ "warning diagnostics mismatch ({})",
120
+ scenario.label
121
+ );
122
+
123
+ let mut ryl_max_violation = build_ryl_command(exe, scenario.ryl_format);
124
+ ryl_max_violation
125
+ .arg("-c")
126
+ .arg(&max_cfg)
127
+ .arg(&max_violation_file);
128
+ let (ryl_max_code, ryl_max_output) =
129
+ capture_with_env(ryl_max_violation, scenario.envs);
130
+
131
+ let mut yam_max_violation = build_yamllint_command(scenario.yam_format);
132
+ yam_max_violation
133
+ .arg("-c")
134
+ .arg(&max_cfg)
135
+ .arg(&max_violation_file);
136
+ let (yam_max_code, yam_max_output) =
137
+ capture_with_env(yam_max_violation, scenario.envs);
138
+
139
+ assert_eq!(ryl_max_code, 1, "ryl max exit ({})", scenario.label);
140
+ assert_eq!(yam_max_code, 1, "yamllint max exit ({})", scenario.label);
141
+ assert_eq!(
142
+ ryl_max_output, yam_max_output,
143
+ "max diagnostics mismatch ({})",
144
+ scenario.label
145
+ );
146
+
147
+ let mut ryl_max_ok = build_ryl_command(exe, scenario.ryl_format);
148
+ ryl_max_ok.arg("-c").arg(&max_cfg).arg(&max_ok_file);
149
+ let (ryl_max_ok_code, ryl_max_ok_output) =
150
+ capture_with_env(ryl_max_ok, scenario.envs);
151
+
152
+ let mut yam_max_ok = build_yamllint_command(scenario.yam_format);
153
+ yam_max_ok.arg("-c").arg(&max_cfg).arg(&max_ok_file);
154
+ let (yam_max_ok_code, yam_max_ok_output) =
155
+ capture_with_env(yam_max_ok, scenario.envs);
156
+
157
+ assert_eq!(ryl_max_ok_code, 0, "ryl max-ok exit ({})", scenario.label);
158
+ assert_eq!(
159
+ yam_max_ok_code, 0,
160
+ "yamllint max-ok exit ({})",
161
+ scenario.label
162
+ );
163
+ assert_eq!(
164
+ ryl_max_ok_output, yam_max_ok_output,
165
+ "max-ok diagnostics mismatch ({})",
166
+ scenario.label
167
+ );
168
+
169
+ let mut ryl_ignore = build_ryl_command(exe, scenario.ryl_format);
170
+ ryl_ignore.arg("-c").arg(&ignore_cfg).arg(&ignored_file);
171
+ let (ryl_ignore_code, ryl_ignore_output) =
172
+ capture_with_env(ryl_ignore, scenario.envs);
173
+
174
+ let mut yam_ignore = build_yamllint_command(scenario.yam_format);
175
+ yam_ignore.arg("-c").arg(&ignore_cfg).arg(&ignored_file);
176
+ let (yam_ignore_code, yam_ignore_output) =
177
+ capture_with_env(yam_ignore, scenario.envs);
178
+
179
+ assert_eq!(ryl_ignore_code, 0, "ryl ignore exit ({})", scenario.label);
180
+ assert_eq!(
181
+ yam_ignore_code, 0,
182
+ "yamllint ignore exit ({})",
183
+ scenario.label
184
+ );
185
+ assert_eq!(
186
+ ryl_ignore_output, yam_ignore_output,
187
+ "ignore diagnostics mismatch ({})",
188
+ scenario.label
189
+ );
190
+
191
+ let mut ryl_ignore_file = build_ryl_command(exe, scenario.ryl_format);
192
+ ryl_ignore_file
193
+ .arg("-c")
194
+ .arg(&ignore_from_file_cfg)
195
+ .arg(&ignored_from_file);
196
+ let (ryl_ignore_file_code, ryl_ignore_file_output) =
197
+ capture_with_env(ryl_ignore_file, scenario.envs);
198
+
199
+ let mut yam_ignore_file = build_yamllint_command(scenario.yam_format);
200
+ yam_ignore_file
201
+ .arg("-c")
202
+ .arg(&ignore_from_file_cfg)
203
+ .arg(&ignored_from_file);
204
+ let (yam_ignore_file_code, yam_ignore_file_output) =
205
+ capture_with_env(yam_ignore_file, scenario.envs);
206
+
207
+ assert_eq!(
208
+ ryl_ignore_file_code, 0,
209
+ "ryl ignore-from-file exit ({})",
210
+ scenario.label
211
+ );
212
+ assert_eq!(
213
+ yam_ignore_file_code, 0,
214
+ "yamllint ignore-from-file exit ({})",
215
+ scenario.label
216
+ );
217
+ assert_eq!(
218
+ ryl_ignore_file_output, yam_ignore_file_output,
219
+ "ignore-from-file diagnostics mismatch ({})",
220
+ scenario.label
221
+ );
222
+ }
223
+ }
@@ -0,0 +1,398 @@
1
+ use std::fs;
2
+
3
+ use tempfile::tempdir;
4
+
5
+ #[path = "common/compat.rs"]
6
+ mod compat;
7
+
8
+ use compat::{
9
+ SCENARIOS, build_ryl_command, build_yamllint_command, capture_with_env,
10
+ ensure_yamllint_installed,
11
+ };
12
+
13
+ struct Case<'a> {
14
+ label: &'a str,
15
+ config: &'a std::path::Path,
16
+ file: &'a std::path::Path,
17
+ exit: i32,
18
+ }
19
+
20
+ #[test]
21
+ fn indentation_matches_yamllint() {
22
+ ensure_yamllint_installed();
23
+
24
+ let dir = tempdir().unwrap();
25
+
26
+ let base_cfg = dir.path().join("base.yaml");
27
+ fs::write(
28
+ &base_cfg,
29
+ "rules:\n document-start: disable\n indentation:\n spaces: 2\n",
30
+ )
31
+ .unwrap();
32
+
33
+ let seq_cfg = dir.path().join("seq.yaml");
34
+ fs::write(
35
+ &seq_cfg,
36
+ "rules:\n document-start: disable\n indentation:\n spaces: 2\n indent-sequences: true\n",
37
+ )
38
+ .unwrap();
39
+
40
+ let seq_off_cfg = dir.path().join("seq-off.yaml");
41
+ fs::write(
42
+ &seq_off_cfg,
43
+ "rules:\n document-start: disable\n indentation:\n indent-sequences: false\n",
44
+ )
45
+ .unwrap();
46
+
47
+ let multi_cfg = dir.path().join("multi.yaml");
48
+ fs::write(
49
+ &multi_cfg,
50
+ "rules:\n document-start: disable\n indentation:\n spaces: 4\n check-multi-line-strings: true\n",
51
+ )
52
+ .unwrap();
53
+
54
+ let map_file = dir.path().join("map.yaml");
55
+ fs::write(&map_file, "root:\n child: value\n").unwrap();
56
+
57
+ let seq_bad_file = dir.path().join("seq-bad.yaml");
58
+ fs::write(&seq_bad_file, "root:\n- item\n").unwrap();
59
+
60
+ let seq_ok_file = dir.path().join("seq-ok.yaml");
61
+ fs::write(&seq_ok_file, "root:\n - item\n").unwrap();
62
+
63
+ let seq_over_file = dir.path().join("seq-over.yaml");
64
+ fs::write(&seq_over_file, "root:\n - item\n").unwrap();
65
+
66
+ let multi_bad_file = dir.path().join("multi-bad.yaml");
67
+ fs::write(&multi_bad_file, "quote: |\n good\n bad\n").unwrap();
68
+
69
+ let exe = env!("CARGO_BIN_EXE_ryl");
70
+
71
+ let cases = [
72
+ Case {
73
+ label: "mapping-indent",
74
+ config: &base_cfg,
75
+ file: &map_file,
76
+ exit: 1,
77
+ },
78
+ Case {
79
+ label: "sequence-indent-required",
80
+ config: &seq_cfg,
81
+ file: &seq_bad_file,
82
+ exit: 1,
83
+ },
84
+ Case {
85
+ label: "sequence-indent-disabled",
86
+ config: &seq_off_cfg,
87
+ file: &seq_bad_file,
88
+ exit: 0,
89
+ },
90
+ Case {
91
+ label: "sequence-ok",
92
+ config: &seq_cfg,
93
+ file: &seq_ok_file,
94
+ exit: 0,
95
+ },
96
+ Case {
97
+ label: "sequence-over-indented",
98
+ config: &seq_cfg,
99
+ file: &seq_over_file,
100
+ exit: 1,
101
+ },
102
+ Case {
103
+ label: "multi-line",
104
+ config: &multi_cfg,
105
+ file: &multi_bad_file,
106
+ exit: 1,
107
+ },
108
+ ];
109
+
110
+ for scenario in SCENARIOS {
111
+ for case in &cases {
112
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
113
+ ryl_cmd.arg("-c").arg(case.config).arg(case.file);
114
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
115
+
116
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
117
+ yam_cmd.arg("-c").arg(case.config).arg(case.file);
118
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
119
+
120
+ assert_eq!(
121
+ ryl_code, case.exit,
122
+ "ryl exit mismatch {} ({})",
123
+ case.label, scenario.label
124
+ );
125
+ assert_eq!(
126
+ yam_code, case.exit,
127
+ "yamllint exit mismatch {} ({})",
128
+ case.label, scenario.label
129
+ );
130
+ assert_eq!(
131
+ ryl_msg, yam_msg,
132
+ "diagnostics mismatch {} ({})",
133
+ case.label, scenario.label
134
+ );
135
+ }
136
+ }
137
+ }
138
+
139
+ #[test]
140
+ fn nested_sequence_indentation_matches_yamllint() {
141
+ ensure_yamllint_installed();
142
+
143
+ let dir = tempdir().unwrap();
144
+
145
+ let cfg_path = dir.path().join("cfg.yaml");
146
+ fs::write(
147
+ &cfg_path,
148
+ "rules:\n document-start: disable\n indentation:\n spaces: 2\n indent-sequences: consistent\n",
149
+ )
150
+ .unwrap();
151
+
152
+ let yaml_path = dir.path().join("input.yaml");
153
+ fs::write(
154
+ &yaml_path,
155
+ "root:\n - any:\n - changed-files:\n - any-glob-to-any-file:\n - foo\n",
156
+ )
157
+ .unwrap();
158
+
159
+ let exe = env!("CARGO_BIN_EXE_ryl");
160
+
161
+ for scenario in SCENARIOS {
162
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
163
+ ryl_cmd.arg("-c").arg(&cfg_path).arg(&yaml_path);
164
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
165
+
166
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
167
+ yam_cmd.arg("-c").arg(&cfg_path).arg(&yaml_path);
168
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
169
+
170
+ assert_eq!(
171
+ ryl_code, 0,
172
+ "ryl exited with diagnostics ({})",
173
+ scenario.label
174
+ );
175
+ assert_eq!(
176
+ yam_code, 0,
177
+ "yamllint reported unexpected diagnostics ({})",
178
+ scenario.label
179
+ );
180
+ assert_eq!(ryl_msg, yam_msg, "output mismatch ({})", scenario.label);
181
+ }
182
+ }
183
+
184
+ #[test]
185
+ fn sequence_after_comments_matches_yamllint() {
186
+ ensure_yamllint_installed();
187
+
188
+ let dir = tempdir().unwrap();
189
+
190
+ let cfg_path = dir.path().join("cfg.yaml");
191
+ fs::write(
192
+ &cfg_path,
193
+ "rules:\n document-start: disable\n line-length: disable\n indentation:\n spaces: 2\n",
194
+ )
195
+ .unwrap();
196
+
197
+ let yaml_path = dir.path().join("input.yaml");
198
+ fs::write(
199
+ &yaml_path,
200
+ "bug:\n # Bug Issue Template:\n # [Bug]:\n # General:\n # panic:\n # Terraform Plugin SDK:\n # doesn't support update\n # Invalid address to set\n - \"(\\\\[Bug\\\\]:|doesn't support update|Invalid address to set|panic:)\"\n",
201
+ )
202
+ .unwrap();
203
+
204
+ let exe = env!("CARGO_BIN_EXE_ryl");
205
+
206
+ for scenario in SCENARIOS {
207
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
208
+ ryl_cmd.arg("-c").arg(&cfg_path).arg(&yaml_path);
209
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
210
+
211
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
212
+ yam_cmd.arg("-c").arg(&cfg_path).arg(&yaml_path);
213
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
214
+
215
+ assert_eq!(
216
+ yam_code, 0,
217
+ "yamllint should accept input ({})",
218
+ scenario.label
219
+ );
220
+ assert_eq!(
221
+ ryl_code, 0,
222
+ "ryl should accept input ({})\n{}",
223
+ scenario.label, ryl_msg
224
+ );
225
+ assert_eq!(ryl_msg, yam_msg, "output mismatch ({})", scenario.label);
226
+ }
227
+ }
228
+
229
+ #[test]
230
+ fn compact_nested_sequence_indentation_matches_yamllint() {
231
+ ensure_yamllint_installed();
232
+
233
+ let dir = tempdir().unwrap();
234
+
235
+ let cfg_path = dir.path().join("cfg.yaml");
236
+ fs::write(
237
+ &cfg_path,
238
+ "rules:\n document-start: disable\n line-length: disable\n indentation:\n spaces: 2\n indent-sequences: consistent\n",
239
+ )
240
+ .unwrap();
241
+
242
+ let yaml_path = dir.path().join("input.yaml");
243
+ fs::write(
244
+ &yaml_path,
245
+ "- name: Test nerdctl\n tasks:\n - name: Test nerdctl commands\n loop:\n - - pull\n - \"{{ image }}\"\n - - save\n - -o\n - /tmp/hello-world.tar\n",
246
+ )
247
+ .unwrap();
248
+
249
+ let exe = env!("CARGO_BIN_EXE_ryl");
250
+
251
+ for scenario in SCENARIOS {
252
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
253
+ ryl_cmd.arg("-c").arg(&cfg_path).arg(&yaml_path);
254
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
255
+
256
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
257
+ yam_cmd.arg("-c").arg(&cfg_path).arg(&yaml_path);
258
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
259
+
260
+ assert_eq!(
261
+ yam_code, 0,
262
+ "yamllint should accept compact nested sequence input ({})",
263
+ scenario.label
264
+ );
265
+ assert_eq!(
266
+ ryl_code, 0,
267
+ "ryl should accept compact nested sequence input ({})\n{}",
268
+ scenario.label, ryl_msg
269
+ );
270
+ assert_eq!(ryl_msg, yam_msg, "output mismatch ({})", scenario.label);
271
+ }
272
+ }
273
+
274
+ #[test]
275
+ fn readthedocs_style_indentation_matches_yamllint() {
276
+ ensure_yamllint_installed();
277
+
278
+ let dir = tempdir().unwrap();
279
+ let cfg = dir.path().join("cfg.yaml");
280
+ fs::write(
281
+ &cfg,
282
+ "extends: default\nrules:\n line-length:\n max: 110\n",
283
+ )
284
+ .unwrap();
285
+
286
+ let input = dir.path().join("readthedocs.yaml");
287
+ fs::write(
288
+ &input,
289
+ "---\nversion: 2\nformats: []\nsphinx:\n configuration: devel-common/src/docs/rtd-deprecation/conf.py\npython:\n version: \"3.10\"\n install:\n - method: pip\n path: .\n extra_requirements:\n - doc\n system_packages: true\n",
290
+ )
291
+ .unwrap();
292
+
293
+ let exe = env!("CARGO_BIN_EXE_ryl");
294
+ for scenario in SCENARIOS {
295
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
296
+ ryl_cmd.arg("-c").arg(&cfg).arg(&input);
297
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
298
+
299
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
300
+ yam_cmd.arg("-c").arg(&cfg).arg(&input);
301
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
302
+
303
+ assert_eq!(
304
+ ryl_code, yam_code,
305
+ "exit mismatch for readthedocs-style indentation ({})",
306
+ scenario.label
307
+ );
308
+ assert_eq!(
309
+ ryl_msg, yam_msg,
310
+ "diagnostics mismatch for readthedocs-style indentation ({})",
311
+ scenario.label
312
+ );
313
+ }
314
+ }
315
+
316
+ #[test]
317
+ fn flow_mapping_continuation_indentation_matches_yamllint() {
318
+ ensure_yamllint_installed();
319
+
320
+ let dir = tempdir().unwrap();
321
+ let cfg = dir.path().join("cfg.yml");
322
+ fs::write(
323
+ &cfg,
324
+ "extends: default\nrules:\n line-length:\n max: 110\n",
325
+ )
326
+ .unwrap();
327
+
328
+ let input = dir.path().join("input.yml");
329
+ fs::write(
330
+ &input,
331
+ "---\nserializers:\n - {className: org.example.Serializer,\n config: {includeTypes: true}}\n",
332
+ )
333
+ .unwrap();
334
+
335
+ let exe = env!("CARGO_BIN_EXE_ryl");
336
+ for scenario in SCENARIOS {
337
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
338
+ ryl_cmd.arg("-c").arg(&cfg).arg("--strict").arg(&input);
339
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
340
+
341
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
342
+ yam_cmd.arg("-c").arg(&cfg).arg("--strict").arg(&input);
343
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
344
+
345
+ assert_eq!(
346
+ ryl_code, yam_code,
347
+ "exit mismatch for flow mapping continuation indentation ({})",
348
+ scenario.label
349
+ );
350
+ assert_eq!(
351
+ ryl_msg, yam_msg,
352
+ "diagnostics mismatch for flow mapping continuation indentation ({})",
353
+ scenario.label
354
+ );
355
+ }
356
+ }
357
+
358
+ #[test]
359
+ fn multiline_double_quoted_template_indentation_matches_yamllint() {
360
+ ensure_yamllint_installed();
361
+
362
+ let dir = tempdir().unwrap();
363
+ let cfg = dir.path().join("cfg.yml");
364
+ fs::write(
365
+ &cfg,
366
+ "extends: default\nrules:\n line-length:\n max: 110\n",
367
+ )
368
+ .unwrap();
369
+
370
+ let input = dir.path().join("input.yml");
371
+ fs::write(
372
+ &input,
373
+ "---\nlogging:\n log_filename_template:\n default: \"dag_id={{ ti.dag_id }}/run_id={{ ti.run_id }}/task_id={{ ti.task_id }}/\\\n {%% if ti.map_index >= 0 %%}map_index={{ ti.map_index }}/{%% endif %%}\\\n attempt={{ try_number|default(ti.try_number) }}.log\"\n",
374
+ )
375
+ .unwrap();
376
+
377
+ let exe = env!("CARGO_BIN_EXE_ryl");
378
+ for scenario in SCENARIOS {
379
+ let mut ryl_cmd = build_ryl_command(exe, scenario.ryl_format);
380
+ ryl_cmd.arg("-c").arg(&cfg).arg("--strict").arg(&input);
381
+ let (ryl_code, ryl_msg) = capture_with_env(ryl_cmd, scenario.envs);
382
+
383
+ let mut yam_cmd = build_yamllint_command(scenario.yam_format);
384
+ yam_cmd.arg("-c").arg(&cfg).arg("--strict").arg(&input);
385
+ let (yam_code, yam_msg) = capture_with_env(yam_cmd, scenario.envs);
386
+
387
+ assert_eq!(
388
+ ryl_code, yam_code,
389
+ "exit mismatch for multiline quoted template indentation ({})",
390
+ scenario.label
391
+ );
392
+ assert_eq!(
393
+ ryl_msg, yam_msg,
394
+ "diagnostics mismatch for multiline quoted template indentation ({})",
395
+ scenario.label
396
+ );
397
+ }
398
+ }