@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.
- package/.github/CODEOWNERS +1 -0
- package/.github/dependabot.yml +13 -0
- package/.github/workflows/ci.yml +107 -0
- package/.github/workflows/release.yml +613 -0
- package/.github/workflows/update_dependencies.yml +61 -0
- package/.github/workflows/update_linters.yml +56 -0
- package/.pre-commit-config.yaml +87 -0
- package/.yamllint +4 -0
- package/AGENTS.md +200 -0
- package/Cargo.lock +908 -0
- package/Cargo.toml +32 -0
- package/LICENSE +21 -0
- package/README.md +230 -0
- package/bin/ryl.js +1 -0
- package/clippy.toml +1 -0
- package/docs/config-presets.md +100 -0
- package/img/benchmark-5x5-5runs.svg +2176 -0
- package/package.json +28 -0
- package/pyproject.toml +42 -0
- package/ruff.toml +107 -0
- package/rumdl.toml +20 -0
- package/rust-toolchain.toml +3 -0
- package/rustfmt.toml +3 -0
- package/scripts/benchmark_perf_vs_yamllint.py +400 -0
- package/scripts/coverage-missing.ps1 +80 -0
- package/scripts/coverage-missing.sh +60 -0
- package/src/bin/discover_config_bin.rs +24 -0
- package/src/cli_support.rs +33 -0
- package/src/conf/mod.rs +85 -0
- package/src/config.rs +2099 -0
- package/src/decoder.rs +326 -0
- package/src/discover.rs +31 -0
- package/src/lib.rs +19 -0
- package/src/lint.rs +558 -0
- package/src/main.rs +535 -0
- package/src/migrate.rs +233 -0
- package/src/rules/anchors.rs +517 -0
- package/src/rules/braces.rs +77 -0
- package/src/rules/brackets.rs +77 -0
- package/src/rules/colons.rs +475 -0
- package/src/rules/commas.rs +372 -0
- package/src/rules/comments.rs +299 -0
- package/src/rules/comments_indentation.rs +243 -0
- package/src/rules/document_end.rs +175 -0
- package/src/rules/document_start.rs +84 -0
- package/src/rules/empty_lines.rs +152 -0
- package/src/rules/empty_values.rs +255 -0
- package/src/rules/float_values.rs +259 -0
- package/src/rules/flow_collection.rs +562 -0
- package/src/rules/hyphens.rs +104 -0
- package/src/rules/indentation.rs +803 -0
- package/src/rules/key_duplicates.rs +218 -0
- package/src/rules/key_ordering.rs +303 -0
- package/src/rules/line_length.rs +326 -0
- package/src/rules/mod.rs +25 -0
- package/src/rules/new_line_at_end_of_file.rs +23 -0
- package/src/rules/new_lines.rs +95 -0
- package/src/rules/octal_values.rs +121 -0
- package/src/rules/quoted_strings.rs +577 -0
- package/src/rules/span_utils.rs +37 -0
- package/src/rules/trailing_spaces.rs +65 -0
- package/src/rules/truthy.rs +420 -0
- package/tests/brackets_carriage_return.rs +114 -0
- package/tests/build_global_cfg_error.rs +23 -0
- package/tests/cli_anchors_rule.rs +143 -0
- package/tests/cli_braces_rule.rs +104 -0
- package/tests/cli_brackets_rule.rs +104 -0
- package/tests/cli_colons_rule.rs +65 -0
- package/tests/cli_commas_rule.rs +104 -0
- package/tests/cli_comments_indentation_rule.rs +61 -0
- package/tests/cli_comments_rule.rs +67 -0
- package/tests/cli_config_data_error.rs +30 -0
- package/tests/cli_config_flags.rs +66 -0
- package/tests/cli_config_migrate.rs +229 -0
- package/tests/cli_document_end_rule.rs +92 -0
- package/tests/cli_document_start_rule.rs +92 -0
- package/tests/cli_empty_lines_rule.rs +87 -0
- package/tests/cli_empty_values_rule.rs +68 -0
- package/tests/cli_env_config.rs +34 -0
- package/tests/cli_exit_and_errors.rs +41 -0
- package/tests/cli_file_encoding.rs +203 -0
- package/tests/cli_float_values_rule.rs +64 -0
- package/tests/cli_format_options.rs +316 -0
- package/tests/cli_global_cfg_relaxed.rs +20 -0
- package/tests/cli_hyphens_rule.rs +104 -0
- package/tests/cli_indentation_rule.rs +65 -0
- package/tests/cli_invalid_project_config.rs +39 -0
- package/tests/cli_key_duplicates_rule.rs +104 -0
- package/tests/cli_key_ordering_rule.rs +59 -0
- package/tests/cli_line_length_rule.rs +85 -0
- package/tests/cli_list_files.rs +29 -0
- package/tests/cli_new_line_rule.rs +141 -0
- package/tests/cli_new_lines_rule.rs +119 -0
- package/tests/cli_octal_values_rule.rs +60 -0
- package/tests/cli_quoted_strings_rule.rs +47 -0
- package/tests/cli_toml_config.rs +119 -0
- package/tests/cli_trailing_spaces_rule.rs +77 -0
- package/tests/cli_truthy_rule.rs +83 -0
- package/tests/cli_yaml_files_negation.rs +45 -0
- package/tests/colons_rule.rs +303 -0
- package/tests/common/compat.rs +114 -0
- package/tests/common/fake_env.rs +93 -0
- package/tests/common/mod.rs +1 -0
- package/tests/conf_builtin.rs +9 -0
- package/tests/config_anchors.rs +84 -0
- package/tests/config_braces.rs +121 -0
- package/tests/config_brackets.rs +127 -0
- package/tests/config_commas.rs +79 -0
- package/tests/config_comments.rs +65 -0
- package/tests/config_comments_indentation.rs +20 -0
- package/tests/config_deep_merge_nonstring_key.rs +24 -0
- package/tests/config_document_end.rs +54 -0
- package/tests/config_document_start.rs +55 -0
- package/tests/config_empty_lines.rs +48 -0
- package/tests/config_empty_values.rs +35 -0
- package/tests/config_env_errors.rs +23 -0
- package/tests/config_env_invalid_inline.rs +15 -0
- package/tests/config_env_missing.rs +63 -0
- package/tests/config_env_shim.rs +301 -0
- package/tests/config_explicit_file_parse_error.rs +55 -0
- package/tests/config_extended_features.rs +225 -0
- package/tests/config_extends_inline.rs +185 -0
- package/tests/config_extends_sequence.rs +18 -0
- package/tests/config_find_project_home_boundary.rs +54 -0
- package/tests/config_find_project_two_files_in_cwd.rs +47 -0
- package/tests/config_float_values.rs +34 -0
- package/tests/config_from_yaml_paths.rs +32 -0
- package/tests/config_hyphens.rs +51 -0
- package/tests/config_ignore_errors.rs +243 -0
- package/tests/config_ignore_overrides.rs +83 -0
- package/tests/config_indentation.rs +65 -0
- package/tests/config_invalid_globs.rs +16 -0
- package/tests/config_invalid_types.rs +19 -0
- package/tests/config_key_duplicates.rs +34 -0
- package/tests/config_key_ordering.rs +70 -0
- package/tests/config_line_length.rs +65 -0
- package/tests/config_locale.rs +111 -0
- package/tests/config_merge.rs +26 -0
- package/tests/config_new_lines.rs +89 -0
- package/tests/config_octal_values.rs +33 -0
- package/tests/config_quoted_strings.rs +195 -0
- package/tests/config_rule_level.rs +147 -0
- package/tests/config_rules_non_string_keys.rs +23 -0
- package/tests/config_scalar_overrides.rs +27 -0
- package/tests/config_to_toml.rs +110 -0
- package/tests/config_toml_coverage.rs +80 -0
- package/tests/config_toml_discovery.rs +304 -0
- package/tests/config_trailing_spaces.rs +152 -0
- package/tests/config_truthy.rs +77 -0
- package/tests/config_yaml_files.rs +62 -0
- package/tests/config_yaml_files_all_non_string.rs +15 -0
- package/tests/config_yaml_files_empty.rs +30 -0
- package/tests/coverage_commas.rs +46 -0
- package/tests/decoder_decode.rs +338 -0
- package/tests/discover_config_bin_all.rs +66 -0
- package/tests/discover_config_bin_env_invalid_yaml.rs +26 -0
- package/tests/discover_config_bin_project_config_parse_error.rs +24 -0
- package/tests/discover_config_bin_user_global_error.rs +26 -0
- package/tests/discover_module.rs +30 -0
- package/tests/discover_per_file_dir.rs +10 -0
- package/tests/discover_per_file_project_config_error.rs +21 -0
- package/tests/float_values.rs +43 -0
- package/tests/lint_multi_errors.rs +32 -0
- package/tests/main_yaml_ok_filtering.rs +30 -0
- package/tests/migrate_module.rs +259 -0
- package/tests/resolve_ctx_empty_parent.rs +16 -0
- package/tests/rule_anchors.rs +442 -0
- package/tests/rule_braces.rs +258 -0
- package/tests/rule_brackets.rs +217 -0
- package/tests/rule_commas.rs +205 -0
- package/tests/rule_comments.rs +197 -0
- package/tests/rule_comments_indentation.rs +127 -0
- package/tests/rule_document_end.rs +118 -0
- package/tests/rule_document_start.rs +60 -0
- package/tests/rule_empty_lines.rs +96 -0
- package/tests/rule_empty_values.rs +102 -0
- package/tests/rule_float_values.rs +109 -0
- package/tests/rule_hyphens.rs +65 -0
- package/tests/rule_indentation.rs +455 -0
- package/tests/rule_key_duplicates.rs +76 -0
- package/tests/rule_key_ordering.rs +207 -0
- package/tests/rule_line_length.rs +200 -0
- package/tests/rule_new_lines.rs +51 -0
- package/tests/rule_octal_values.rs +53 -0
- package/tests/rule_quoted_strings.rs +290 -0
- package/tests/rule_trailing_spaces.rs +41 -0
- package/tests/rule_truthy.rs +236 -0
- package/tests/user_global_invalid_yaml.rs +32 -0
- package/tests/yamllint_compat_anchors.rs +280 -0
- package/tests/yamllint_compat_braces.rs +411 -0
- package/tests/yamllint_compat_brackets.rs +364 -0
- package/tests/yamllint_compat_colons.rs +298 -0
- package/tests/yamllint_compat_colors.rs +80 -0
- package/tests/yamllint_compat_commas.rs +375 -0
- package/tests/yamllint_compat_comments.rs +167 -0
- package/tests/yamllint_compat_comments_indentation.rs +281 -0
- package/tests/yamllint_compat_config.rs +170 -0
- package/tests/yamllint_compat_document_end.rs +243 -0
- package/tests/yamllint_compat_document_start.rs +136 -0
- package/tests/yamllint_compat_empty_lines.rs +117 -0
- package/tests/yamllint_compat_empty_values.rs +179 -0
- package/tests/yamllint_compat_float_values.rs +216 -0
- package/tests/yamllint_compat_hyphens.rs +223 -0
- package/tests/yamllint_compat_indentation.rs +398 -0
- package/tests/yamllint_compat_key_duplicates.rs +139 -0
- package/tests/yamllint_compat_key_ordering.rs +170 -0
- package/tests/yamllint_compat_line_length.rs +375 -0
- package/tests/yamllint_compat_list.rs +127 -0
- package/tests/yamllint_compat_new_line.rs +133 -0
- package/tests/yamllint_compat_newline_types.rs +185 -0
- package/tests/yamllint_compat_octal_values.rs +172 -0
- package/tests/yamllint_compat_quoted_strings.rs +154 -0
- package/tests/yamllint_compat_syntax.rs +200 -0
- package/tests/yamllint_compat_trailing_spaces.rs +162 -0
- package/tests/yamllint_compat_truthy.rs +130 -0
- package/tests/yamllint_compat_yaml_files.rs +81 -0
- package/typos.toml +2 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
use ryl::rules::brackets::{self, Config, Forbid, Violation};
|
|
2
|
+
|
|
3
|
+
fn defaults() -> Config {
|
|
4
|
+
Config::new_for_tests(Forbid::None, 0, 0, -1, -1)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
#[test]
|
|
8
|
+
fn empty_input_returns_no_diagnostics() {
|
|
9
|
+
let cfg = defaults();
|
|
10
|
+
let diagnostics = brackets::check("", &cfg);
|
|
11
|
+
assert!(
|
|
12
|
+
diagnostics.is_empty(),
|
|
13
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#[test]
|
|
18
|
+
fn accepts_compact_flow_sequence() {
|
|
19
|
+
let cfg = defaults();
|
|
20
|
+
let diagnostics = brackets::check("object: [1, 2]\n", &cfg);
|
|
21
|
+
assert!(
|
|
22
|
+
diagnostics.is_empty(),
|
|
23
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#[test]
|
|
28
|
+
fn reports_space_after_open_bracket() {
|
|
29
|
+
let cfg = defaults();
|
|
30
|
+
let diagnostics = brackets::check("object: [ 1, 2]\n", &cfg);
|
|
31
|
+
assert_eq!(
|
|
32
|
+
diagnostics,
|
|
33
|
+
vec![Violation {
|
|
34
|
+
line: 1,
|
|
35
|
+
column: 10,
|
|
36
|
+
message: "too many spaces inside brackets".to_string(),
|
|
37
|
+
}]
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#[test]
|
|
42
|
+
fn reports_space_before_closing_bracket() {
|
|
43
|
+
let cfg = defaults();
|
|
44
|
+
let diagnostics = brackets::check("object: [1, 2 ]\n", &cfg);
|
|
45
|
+
assert_eq!(
|
|
46
|
+
diagnostics,
|
|
47
|
+
vec![Violation {
|
|
48
|
+
line: 1,
|
|
49
|
+
column: 14,
|
|
50
|
+
message: "too many spaces inside brackets".to_string(),
|
|
51
|
+
}]
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#[test]
|
|
56
|
+
fn forbid_true_rejects_flow_sequence() {
|
|
57
|
+
let cfg = Config::new_for_tests(Forbid::All, 0, 0, -1, -1);
|
|
58
|
+
let diagnostics = brackets::check("object: [1, 2]\n", &cfg);
|
|
59
|
+
assert_eq!(
|
|
60
|
+
diagnostics,
|
|
61
|
+
vec![Violation {
|
|
62
|
+
line: 1,
|
|
63
|
+
column: 10,
|
|
64
|
+
message: "forbidden flow sequence".to_string(),
|
|
65
|
+
}]
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[test]
|
|
70
|
+
fn forbid_non_empty_allows_empty_sequence() {
|
|
71
|
+
let cfg = Config::new_for_tests(Forbid::NonEmpty, 0, 0, -1, -1);
|
|
72
|
+
let diagnostics = brackets::check("object: []\n", &cfg);
|
|
73
|
+
assert!(
|
|
74
|
+
diagnostics.is_empty(),
|
|
75
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[test]
|
|
80
|
+
fn forbid_non_empty_rejects_non_empty_sequence() {
|
|
81
|
+
let cfg = Config::new_for_tests(Forbid::NonEmpty, 0, 0, -1, -1);
|
|
82
|
+
let diagnostics = brackets::check("object: [1]\n", &cfg);
|
|
83
|
+
assert_eq!(
|
|
84
|
+
diagnostics,
|
|
85
|
+
vec![Violation {
|
|
86
|
+
line: 1,
|
|
87
|
+
column: 10,
|
|
88
|
+
message: "forbidden flow sequence".to_string(),
|
|
89
|
+
}]
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#[test]
|
|
94
|
+
fn min_spaces_inside_enforced_on_both_sides() {
|
|
95
|
+
let cfg = Config::new_for_tests(Forbid::None, 1, -1, -1, -1);
|
|
96
|
+
let diagnostics = brackets::check("object: [1, 2]\n", &cfg);
|
|
97
|
+
assert_eq!(
|
|
98
|
+
diagnostics,
|
|
99
|
+
vec![
|
|
100
|
+
Violation {
|
|
101
|
+
line: 1,
|
|
102
|
+
column: 10,
|
|
103
|
+
message: "too few spaces inside brackets".to_string(),
|
|
104
|
+
},
|
|
105
|
+
Violation {
|
|
106
|
+
line: 1,
|
|
107
|
+
column: 14,
|
|
108
|
+
message: "too few spaces inside brackets".to_string(),
|
|
109
|
+
},
|
|
110
|
+
]
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[test]
|
|
115
|
+
fn max_spaces_inside_limits_padding() {
|
|
116
|
+
let cfg = Config::new_for_tests(Forbid::None, 0, 1, -1, -1);
|
|
117
|
+
let diagnostics = brackets::check("object: [ 1, 2 ]\n", &cfg);
|
|
118
|
+
assert_eq!(
|
|
119
|
+
diagnostics,
|
|
120
|
+
vec![
|
|
121
|
+
Violation {
|
|
122
|
+
line: 1,
|
|
123
|
+
column: 11,
|
|
124
|
+
message: "too many spaces inside brackets".to_string(),
|
|
125
|
+
},
|
|
126
|
+
Violation {
|
|
127
|
+
line: 1,
|
|
128
|
+
column: 18,
|
|
129
|
+
message: "too many spaces inside brackets".to_string(),
|
|
130
|
+
},
|
|
131
|
+
]
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#[test]
|
|
136
|
+
fn empty_sequence_spacing_overrides_defaults() {
|
|
137
|
+
let cfg = Config::new_for_tests(Forbid::None, 0, 0, 1, 2);
|
|
138
|
+
let diagnostics = brackets::check("object: []\n", &cfg);
|
|
139
|
+
assert_eq!(
|
|
140
|
+
diagnostics,
|
|
141
|
+
vec![Violation {
|
|
142
|
+
line: 1,
|
|
143
|
+
column: 10,
|
|
144
|
+
message: "too few spaces inside empty brackets".to_string(),
|
|
145
|
+
}]
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
let diagnostics = brackets::check("object: [ ]\n", &cfg);
|
|
149
|
+
assert_eq!(
|
|
150
|
+
diagnostics,
|
|
151
|
+
vec![Violation {
|
|
152
|
+
line: 1,
|
|
153
|
+
column: 13,
|
|
154
|
+
message: "too many spaces inside empty brackets".to_string(),
|
|
155
|
+
}]
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
#[test]
|
|
160
|
+
fn multiline_sequences_skip_spacing_checks() {
|
|
161
|
+
let cfg = defaults();
|
|
162
|
+
let diagnostics = brackets::check("seq: [\n 1,\n 2\n]\n", &cfg);
|
|
163
|
+
assert!(
|
|
164
|
+
diagnostics.is_empty(),
|
|
165
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
#[test]
|
|
170
|
+
fn brackets_inside_scalars_are_ignored() {
|
|
171
|
+
let cfg = defaults();
|
|
172
|
+
let diagnostics = brackets::check("value: \"[ not a sequence ]\"\n", &cfg);
|
|
173
|
+
assert!(
|
|
174
|
+
diagnostics.is_empty(),
|
|
175
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
#[test]
|
|
180
|
+
fn comments_inside_flow_sequences_are_ignored() {
|
|
181
|
+
let cfg = defaults();
|
|
182
|
+
let diagnostics = brackets::check("object: [1, # comment\n 2]\n", &cfg);
|
|
183
|
+
assert!(
|
|
184
|
+
diagnostics.is_empty(),
|
|
185
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
#[test]
|
|
190
|
+
fn carriage_returns_inside_flow_are_ignored() {
|
|
191
|
+
let cfg = defaults();
|
|
192
|
+
let diagnostics = brackets::check("object: [1,\r\n 2]\r\n", &cfg);
|
|
193
|
+
assert!(
|
|
194
|
+
diagnostics.is_empty(),
|
|
195
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
#[test]
|
|
200
|
+
fn nested_sequences_mark_outer_non_empty() {
|
|
201
|
+
let cfg = defaults();
|
|
202
|
+
let diagnostics = brackets::check("outer: [[1]]\n", &cfg);
|
|
203
|
+
assert!(
|
|
204
|
+
diagnostics.is_empty(),
|
|
205
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#[test]
|
|
210
|
+
fn unmatched_closing_bracket_is_ignored() {
|
|
211
|
+
let cfg = defaults();
|
|
212
|
+
let diagnostics = brackets::check("]\n", &cfg);
|
|
213
|
+
assert!(
|
|
214
|
+
diagnostics.is_empty(),
|
|
215
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
216
|
+
);
|
|
217
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
use ryl::rules::commas::{self, Config, Violation};
|
|
2
|
+
|
|
3
|
+
fn defaults() -> Config {
|
|
4
|
+
Config::new_for_tests(0, 1, 1)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
#[test]
|
|
8
|
+
fn empty_input_returns_no_diagnostics() {
|
|
9
|
+
let cfg = defaults();
|
|
10
|
+
let diagnostics = commas::check("", &cfg);
|
|
11
|
+
assert!(
|
|
12
|
+
diagnostics.is_empty(),
|
|
13
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#[test]
|
|
18
|
+
fn accepts_well_spaced_flow_sequence() {
|
|
19
|
+
let cfg = defaults();
|
|
20
|
+
let diagnostics = commas::check("[1, 2]\n", &cfg);
|
|
21
|
+
assert!(
|
|
22
|
+
diagnostics.is_empty(),
|
|
23
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#[test]
|
|
28
|
+
fn reports_space_before_comma() {
|
|
29
|
+
let cfg = defaults();
|
|
30
|
+
let diagnostics = commas::check("[1 ,2]\n", &cfg);
|
|
31
|
+
assert_eq!(
|
|
32
|
+
diagnostics,
|
|
33
|
+
vec![
|
|
34
|
+
Violation {
|
|
35
|
+
line: 1,
|
|
36
|
+
column: 3,
|
|
37
|
+
message: "too many spaces before comma".to_string(),
|
|
38
|
+
},
|
|
39
|
+
Violation {
|
|
40
|
+
line: 1,
|
|
41
|
+
column: 5,
|
|
42
|
+
message: "too few spaces after comma".to_string(),
|
|
43
|
+
},
|
|
44
|
+
]
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#[test]
|
|
49
|
+
fn reports_missing_space_after_comma() {
|
|
50
|
+
let cfg = defaults();
|
|
51
|
+
let diagnostics = commas::check("[1,2]\n", &cfg);
|
|
52
|
+
assert_eq!(
|
|
53
|
+
diagnostics,
|
|
54
|
+
vec![Violation {
|
|
55
|
+
line: 1,
|
|
56
|
+
column: 4,
|
|
57
|
+
message: "too few spaces after comma".to_string(),
|
|
58
|
+
}]
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#[test]
|
|
63
|
+
fn reports_excess_space_after_comma() {
|
|
64
|
+
let cfg = defaults();
|
|
65
|
+
let diagnostics = commas::check("[1, 2]\n", &cfg);
|
|
66
|
+
assert_eq!(
|
|
67
|
+
diagnostics,
|
|
68
|
+
vec![Violation {
|
|
69
|
+
line: 1,
|
|
70
|
+
column: 5,
|
|
71
|
+
message: "too many spaces after comma".to_string(),
|
|
72
|
+
}]
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#[test]
|
|
77
|
+
fn ignores_newline_after_comma() {
|
|
78
|
+
let cfg = defaults();
|
|
79
|
+
let diagnostics = commas::check("[1,\n 2]\n", &cfg);
|
|
80
|
+
assert!(
|
|
81
|
+
diagnostics.is_empty(),
|
|
82
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[test]
|
|
87
|
+
fn ignores_comma_at_line_start() {
|
|
88
|
+
let cfg = defaults();
|
|
89
|
+
let diagnostics = commas::check("[\n 1\n, 2]\n", &cfg);
|
|
90
|
+
assert!(
|
|
91
|
+
diagnostics.is_empty(),
|
|
92
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#[test]
|
|
97
|
+
fn newline_before_comma_is_ignored() {
|
|
98
|
+
let cfg = defaults();
|
|
99
|
+
let diagnostics = commas::check("[1\n, 2]\n", &cfg);
|
|
100
|
+
assert!(
|
|
101
|
+
diagnostics.is_empty(),
|
|
102
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
#[test]
|
|
107
|
+
fn ignores_commas_inside_scalars() {
|
|
108
|
+
let cfg = defaults();
|
|
109
|
+
let diagnostics = commas::check("[\"café, menu\", 3]\n", &cfg);
|
|
110
|
+
assert!(
|
|
111
|
+
diagnostics.is_empty(),
|
|
112
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#[test]
|
|
117
|
+
fn respects_relaxed_spacing_config() {
|
|
118
|
+
let cfg = Config::new_for_tests(-1, 0, -1);
|
|
119
|
+
let diagnostics = commas::check("[1 ,2]\n", &cfg);
|
|
120
|
+
assert!(
|
|
121
|
+
diagnostics.is_empty(),
|
|
122
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[test]
|
|
127
|
+
fn handles_flow_mapping_entries() {
|
|
128
|
+
let cfg = defaults();
|
|
129
|
+
let diagnostics = commas::check("{foo: 1 ,bar: 2}\n", &cfg);
|
|
130
|
+
assert_eq!(
|
|
131
|
+
diagnostics,
|
|
132
|
+
vec![
|
|
133
|
+
Violation {
|
|
134
|
+
line: 1,
|
|
135
|
+
column: 8,
|
|
136
|
+
message: "too many spaces before comma".to_string(),
|
|
137
|
+
},
|
|
138
|
+
Violation {
|
|
139
|
+
line: 1,
|
|
140
|
+
column: 10,
|
|
141
|
+
message: "too few spaces after comma".to_string(),
|
|
142
|
+
},
|
|
143
|
+
]
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
#[test]
|
|
148
|
+
fn allows_comment_after_comma_on_same_line() {
|
|
149
|
+
let cfg = defaults();
|
|
150
|
+
let diagnostics = commas::check("[1, # comment\n 2]\n", &cfg);
|
|
151
|
+
assert!(
|
|
152
|
+
diagnostics.is_empty(),
|
|
153
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
#[test]
|
|
158
|
+
fn allows_comment_after_comma_with_crlf() {
|
|
159
|
+
let cfg = defaults();
|
|
160
|
+
let diagnostics = commas::check("[1, # comment\r\n 2]\r\n", &cfg);
|
|
161
|
+
assert!(
|
|
162
|
+
diagnostics.is_empty(),
|
|
163
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
#[test]
|
|
168
|
+
fn carriage_return_after_comma_is_ignored() {
|
|
169
|
+
let cfg = defaults();
|
|
170
|
+
let diagnostics = commas::check("[1,\r\n 2]\r\n", &cfg);
|
|
171
|
+
assert!(
|
|
172
|
+
diagnostics.is_empty(),
|
|
173
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#[test]
|
|
178
|
+
fn trailing_spaces_without_next_token_do_not_panic() {
|
|
179
|
+
let cfg = defaults();
|
|
180
|
+
let diagnostics = commas::check("[1, ", &cfg);
|
|
181
|
+
assert!(
|
|
182
|
+
diagnostics.is_empty(),
|
|
183
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
#[test]
|
|
188
|
+
fn bare_carriage_return_is_treated_as_line_break() {
|
|
189
|
+
let cfg = defaults();
|
|
190
|
+
let diagnostics = commas::check("[1, 2]\r", &cfg);
|
|
191
|
+
assert!(
|
|
192
|
+
diagnostics.is_empty(),
|
|
193
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
#[test]
|
|
198
|
+
fn bare_carriage_return_before_comma_is_ignored() {
|
|
199
|
+
let cfg = defaults();
|
|
200
|
+
let diagnostics = commas::check("[1\r, 2]\r", &cfg);
|
|
201
|
+
assert!(
|
|
202
|
+
diagnostics.is_empty(),
|
|
203
|
+
"unexpected diagnostics: {diagnostics:?}"
|
|
204
|
+
);
|
|
205
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
use ryl::config::YamlLintConfig;
|
|
2
|
+
use ryl::rules::comments::{self, Config, Violation};
|
|
3
|
+
|
|
4
|
+
fn build_config(yaml: &str) -> Config {
|
|
5
|
+
let cfg = YamlLintConfig::from_yaml_str(yaml).expect("config parses");
|
|
6
|
+
Config::resolve(&cfg)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
#[test]
|
|
10
|
+
fn missing_space_reports_violation() {
|
|
11
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
12
|
+
let hits = comments::check("#comment\n", &resolved);
|
|
13
|
+
assert_eq!(
|
|
14
|
+
hits,
|
|
15
|
+
vec![Violation {
|
|
16
|
+
line: 1,
|
|
17
|
+
column: 2,
|
|
18
|
+
message: "missing starting space in comment".to_string(),
|
|
19
|
+
}]
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[test]
|
|
24
|
+
fn allows_hash_art_lines() {
|
|
25
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
26
|
+
let hits = comments::check("########################\n", &resolved);
|
|
27
|
+
assert!(hits.is_empty(), "hash art should be allowed: {hits:?}");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#[test]
|
|
31
|
+
fn enforces_min_spacing_for_inline_comments() {
|
|
32
|
+
let resolved = build_config(
|
|
33
|
+
"rules:\n comments:\n require-starting-space: true\n min-spaces-from-content: 2\n",
|
|
34
|
+
);
|
|
35
|
+
let hits = comments::check("key: value # comment\n", &resolved);
|
|
36
|
+
assert_eq!(
|
|
37
|
+
hits,
|
|
38
|
+
vec![Violation {
|
|
39
|
+
line: 1,
|
|
40
|
+
column: 12,
|
|
41
|
+
message: "too few spaces before comment: expected 2".to_string(),
|
|
42
|
+
}]
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#[test]
|
|
47
|
+
fn disables_min_spacing_with_negative_one() {
|
|
48
|
+
let resolved = build_config(
|
|
49
|
+
"rules:\n comments:\n require-starting-space: true\n min-spaces-from-content: -1\n",
|
|
50
|
+
);
|
|
51
|
+
let hits = comments::check("key: value # comment\n", &resolved);
|
|
52
|
+
assert!(
|
|
53
|
+
hits.is_empty(),
|
|
54
|
+
"min spacing of -1 should disable the check: {hits:?}"
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#[test]
|
|
59
|
+
fn shebang_respected_when_ignored() {
|
|
60
|
+
let resolved = build_config(
|
|
61
|
+
"rules:\n comments:\n require-starting-space: true\n ignore-shebangs: true\n",
|
|
62
|
+
);
|
|
63
|
+
let hits = comments::check("#!/usr/bin/env foo\n", &resolved);
|
|
64
|
+
assert!(hits.is_empty(), "shebang should be ignored: {hits:?}");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
#[test]
|
|
68
|
+
fn shebang_flagged_when_not_ignored() {
|
|
69
|
+
let resolved = build_config(
|
|
70
|
+
"rules:\n comments:\n require-starting-space: true\n ignore-shebangs: false\n",
|
|
71
|
+
);
|
|
72
|
+
let hits = comments::check("#!/usr/bin/env foo\n", &resolved);
|
|
73
|
+
assert_eq!(
|
|
74
|
+
hits,
|
|
75
|
+
vec![Violation {
|
|
76
|
+
line: 1,
|
|
77
|
+
column: 2,
|
|
78
|
+
message: "missing starting space in comment".to_string(),
|
|
79
|
+
}]
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#[test]
|
|
84
|
+
fn inline_comment_reports_both_issues() {
|
|
85
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
86
|
+
let hits = comments::check("value: foo #bar\n", &resolved);
|
|
87
|
+
assert_eq!(
|
|
88
|
+
hits,
|
|
89
|
+
vec![
|
|
90
|
+
Violation {
|
|
91
|
+
line: 1,
|
|
92
|
+
column: 12,
|
|
93
|
+
message: "too few spaces before comment: expected 2".to_string(),
|
|
94
|
+
},
|
|
95
|
+
Violation {
|
|
96
|
+
line: 1,
|
|
97
|
+
column: 13,
|
|
98
|
+
message: "missing starting space in comment".to_string(),
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
#[test]
|
|
105
|
+
fn url_fragment_does_not_count_as_comment() {
|
|
106
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
107
|
+
let hits = comments::check("link: https://example.com/#anchor\n", &resolved);
|
|
108
|
+
assert!(
|
|
109
|
+
hits.is_empty(),
|
|
110
|
+
"URL fragments should not be treated as comments: {hits:?}"
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[test]
|
|
115
|
+
fn ignores_hash_characters_inside_quotes() {
|
|
116
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
117
|
+
let hits = comments::check("string: \"value #not comment\" # comment\n", &resolved);
|
|
118
|
+
assert_eq!(
|
|
119
|
+
hits,
|
|
120
|
+
vec![Violation {
|
|
121
|
+
line: 1,
|
|
122
|
+
column: 30,
|
|
123
|
+
message: "too few spaces before comment: expected 2".to_string(),
|
|
124
|
+
}]
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#[test]
|
|
129
|
+
fn ignores_hash_inside_single_quotes() {
|
|
130
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
131
|
+
let hits = comments::check("string: 'value #not comment' # comment\n", &resolved);
|
|
132
|
+
assert_eq!(
|
|
133
|
+
hits,
|
|
134
|
+
vec![Violation {
|
|
135
|
+
line: 1,
|
|
136
|
+
column: 30,
|
|
137
|
+
message: "too few spaces before comment: expected 2".to_string(),
|
|
138
|
+
}]
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#[test]
|
|
143
|
+
fn handles_escaped_hash_inside_double_quotes() {
|
|
144
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
145
|
+
let hits = comments::check("string: \"path\\#not comment\" # comment\n", &resolved);
|
|
146
|
+
assert_eq!(
|
|
147
|
+
hits,
|
|
148
|
+
vec![Violation {
|
|
149
|
+
line: 1,
|
|
150
|
+
column: 29,
|
|
151
|
+
message: "too few spaces before comment: expected 2".to_string(),
|
|
152
|
+
}]
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#[test]
|
|
157
|
+
fn handles_crlf_newlines() {
|
|
158
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
159
|
+
let hits = comments::check("key: value # comment\r\n#comment\r\n", &resolved);
|
|
160
|
+
assert_eq!(hits.len(), 2, "expected two violations: {hits:?}");
|
|
161
|
+
assert_eq!(hits[0].line, 1);
|
|
162
|
+
assert_eq!(hits[1].line, 2);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#[test]
|
|
166
|
+
fn multiline_quoted_scalars_ignore_hashes() {
|
|
167
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
168
|
+
let input = "value: \"first line\\n second # still scalar\\n third\"\n";
|
|
169
|
+
let hits = comments::check(input, &resolved);
|
|
170
|
+
assert!(
|
|
171
|
+
hits.is_empty(),
|
|
172
|
+
"quoted scalar hash should not be comment: {hits:?}"
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
#[test]
|
|
177
|
+
fn block_scalar_lines_do_not_trigger_comment_checks() {
|
|
178
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
179
|
+
let input =
|
|
180
|
+
"job:\n run: |\n line one\n line two\n line three\n next: value\n";
|
|
181
|
+
let hits = comments::check(input, &resolved);
|
|
182
|
+
assert!(
|
|
183
|
+
hits.is_empty(),
|
|
184
|
+
"block scalar content must be ignored: {hits:?}"
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
#[test]
|
|
189
|
+
fn empty_block_scalar_is_ignored() {
|
|
190
|
+
let resolved = build_config("rules:\n comments: {}\n");
|
|
191
|
+
let input = "job:\n run: |\n next: value\n";
|
|
192
|
+
let hits = comments::check(input, &resolved);
|
|
193
|
+
assert!(
|
|
194
|
+
hits.is_empty(),
|
|
195
|
+
"empty block scalar should reset tracker: {hits:?}"
|
|
196
|
+
);
|
|
197
|
+
}
|