gurkencheck 0.0.7 → 0.0.9

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 (80) hide show
  1. package/README.md +19 -0
  2. package/dist/config-parser.d.ts.map +1 -1
  3. package/dist/config-parser.js +7 -1
  4. package/dist/config-parser.js.map +1 -1
  5. package/dist/diagnostics.d.ts +34 -0
  6. package/dist/diagnostics.d.ts.map +1 -0
  7. package/dist/diagnostics.js +53 -0
  8. package/dist/diagnostics.js.map +1 -0
  9. package/dist/feature-finder.d.ts +38 -0
  10. package/dist/feature-finder.d.ts.map +1 -1
  11. package/dist/feature-finder.js +86 -8
  12. package/dist/feature-finder.js.map +1 -1
  13. package/dist/formatters/index.d.ts +44 -4
  14. package/dist/formatters/index.d.ts.map +1 -1
  15. package/dist/formatters/index.js +52 -15
  16. package/dist/formatters/index.js.map +1 -1
  17. package/dist/formatters/stylish.d.ts +3 -0
  18. package/dist/formatters/stylish.d.ts.map +1 -1
  19. package/dist/formatters/stylish.js +32 -1
  20. package/dist/formatters/stylish.js.map +1 -1
  21. package/dist/formatters/tap.d.ts +14 -0
  22. package/dist/formatters/tap.d.ts.map +1 -1
  23. package/dist/formatters/tap.js +22 -7
  24. package/dist/formatters/tap.js.map +1 -1
  25. package/dist/gherkin/parse.d.ts +42 -1
  26. package/dist/gherkin/parse.d.ts.map +1 -1
  27. package/dist/gherkin/parse.js +68 -3
  28. package/dist/gherkin/parse.js.map +1 -1
  29. package/dist/index.d.ts +18 -10
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +10 -6
  32. package/dist/index.js.map +1 -1
  33. package/dist/linter.d.ts +31 -3
  34. package/dist/linter.d.ts.map +1 -1
  35. package/dist/linter.js +82 -15
  36. package/dist/linter.js.map +1 -1
  37. package/dist/logger.d.ts +2 -0
  38. package/dist/logger.d.ts.map +1 -1
  39. package/dist/logger.js +4 -0
  40. package/dist/logger.js.map +1 -1
  41. package/dist/main.d.ts +9 -1
  42. package/dist/main.d.ts.map +1 -1
  43. package/dist/main.js +147 -26
  44. package/dist/main.js.map +1 -1
  45. package/dist/rules/no-dupe-feature-names.d.ts.map +1 -1
  46. package/dist/rules/no-dupe-feature-names.js +26 -13
  47. package/dist/rules/no-dupe-feature-names.js.map +1 -1
  48. package/dist/rules/no-dupe-file-names.d.ts.map +1 -1
  49. package/dist/rules/no-dupe-file-names.js +32 -17
  50. package/dist/rules/no-dupe-file-names.js.map +1 -1
  51. package/dist/rules/no-dupe-scenario-names.d.ts.map +1 -1
  52. package/dist/rules/no-dupe-scenario-names.js +34 -22
  53. package/dist/rules/no-dupe-scenario-names.js.map +1 -1
  54. package/dist/rules.d.ts +41 -3
  55. package/dist/rules.d.ts.map +1 -1
  56. package/dist/rules.js +112 -4
  57. package/dist/rules.js.map +1 -1
  58. package/dist/stats/collect.d.ts +8 -0
  59. package/dist/stats/collect.d.ts.map +1 -1
  60. package/dist/stats/collect.js +67 -37
  61. package/dist/stats/collect.js.map +1 -1
  62. package/dist/stats/command.d.ts +2 -1
  63. package/dist/stats/command.d.ts.map +1 -1
  64. package/dist/stats/command.js +34 -34
  65. package/dist/stats/command.js.map +1 -1
  66. package/dist/types.d.ts +47 -3
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/util/glob.d.ts +18 -0
  69. package/dist/util/glob.d.ts.map +1 -1
  70. package/dist/util/glob.js +126 -22
  71. package/dist/util/glob.js.map +1 -1
  72. package/dist/util/stream.d.ts +31 -0
  73. package/dist/util/stream.d.ts.map +1 -0
  74. package/dist/util/stream.js +67 -0
  75. package/dist/util/stream.js.map +1 -0
  76. package/dist/watch.d.ts +36 -0
  77. package/dist/watch.d.ts.map +1 -0
  78. package/dist/watch.js +203 -0
  79. package/dist/watch.js.map +1 -0
  80. package/package.json +1 -1
package/dist/main.d.ts CHANGED
@@ -1,3 +1,11 @@
1
1
  #!/usr/bin/env node
2
- export declare function run(argv: readonly string[]): Promise<number>;
2
+ import type { Diagnostics } from './diagnostics.ts';
3
+ /**
4
+ * Runs the command line.
5
+ *
6
+ * Anything said about the run goes through `diagnostics`, which says nothing
7
+ * unless it is given somewhere to say it - so calling this from a test or a
8
+ * library leaves the console alone until you ask for it.
9
+ */
10
+ export declare function run(argv: readonly string[], diagnostics?: Diagnostics): Promise<number>;
3
11
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AA4CA,wBAAsB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FlE"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAsClD;;;;;;GAMG;AACH,wBAAsB,GAAG,CACvB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,WAAW,GAAE,WAAoB,GAChC,OAAO,CAAC,MAAM,CAAC,CAmKjB"}
package/dist/main.js CHANGED
@@ -7,14 +7,17 @@ import { pathToFileURL } from 'node:url';
7
7
  import { parseArgs } from 'node:util';
8
8
  import { DEFAULT_CONFIG_FILE_NAME, readConfiguration } from './config-parser.js';
9
9
  import { EXIT_LINT_ERRORS, EXIT_OK, EXIT_USAGE } from './exit-codes.js';
10
- import { DEFAULT_IGNORE_FILE_NAME, findFeatureFiles } from './feature-finder.js';
11
- import { DEFAULT_FORMAT, FORMATTERS, loadFormatter } from './formatters/index.js';
10
+ import { DEFAULT_IGNORE_FILE_NAME, featureRoots, findFeatureFileStream, } from './feature-finder.js';
11
+ import { watch } from './watch.js';
12
+ import { DEFAULT_FORMAT, FORMATTERS, loadFormatter, loadStreamingFormatter, } from './formatters/index.js';
12
13
  import { isKnownLanguage } from './gherkin/dialects.js';
13
- import { hasErrors, lint } from './linter.js';
14
- import * as logger from './logger.js';
14
+ import { hasErrors, lint, lintStream } from './linter.js';
15
+ import { SILENT, TO_STDERR } from './diagnostics.js';
15
16
  import { loadRules } from './rules.js';
16
17
  import { runStats } from './stats/command.js';
17
18
  import { version } from './version.js';
19
+ /** Directory names a watch takes no notice of, however deep they turn up. */
20
+ const DEFAULT_IGNORED_NAMES = ['node_modules', '.git'];
18
21
  function usage() {
19
22
  return [
20
23
  'Usage: gurkencheck [options] <feature-files>',
@@ -29,6 +32,7 @@ function usage() {
29
32
  ` -i, --ignore <globs> comma separated globs to skip, overriding ${DEFAULT_IGNORE_FILE_NAME}`,
30
33
  ' -r, --rulesdir <dir> directory of custom rules; may be given more than once',
31
34
  ' -l, --language <code> dialect for files with no "# language:" header',
35
+ ' -w, --watch keep running, checking again whenever a file changes',
32
36
  ' -h, --help show this message',
33
37
  ' -v, --version show the version number',
34
38
  '',
@@ -40,12 +44,19 @@ function usage() {
40
44
  'Documentation: https://sebs.github.io/gurkencheck/',
41
45
  ].join('\n');
42
46
  }
43
- export async function run(argv) {
47
+ /**
48
+ * Runs the command line.
49
+ *
50
+ * Anything said about the run goes through `diagnostics`, which says nothing
51
+ * unless it is given somewhere to say it - so calling this from a test or a
52
+ * library leaves the console alone until you ask for it.
53
+ */
54
+ export async function run(argv, diagnostics = SILENT) {
44
55
  // Subcommands are matched before the options are read, so that `stats` can
45
56
  // accept a --format of its own without the two sets of names colliding.
46
57
  // A directory really called `stats` is still lintable, as `./stats`.
47
58
  if (argv[0] === 'stats') {
48
- return runStats(argv.slice(1));
59
+ return runStats(argv.slice(1), diagnostics);
49
60
  }
50
61
  let parsed;
51
62
  try {
@@ -57,6 +68,7 @@ export async function run(argv) {
57
68
  ignore: { type: 'string', short: 'i' },
58
69
  rulesdir: { type: 'string', short: 'r', multiple: true },
59
70
  language: { type: 'string', short: 'l' },
71
+ watch: { type: 'boolean', short: 'w' },
60
72
  help: { type: 'boolean', short: 'h' },
61
73
  version: { type: 'boolean', short: 'v' },
62
74
  },
@@ -64,8 +76,11 @@ export async function run(argv) {
64
76
  });
65
77
  }
66
78
  catch (thrown) {
67
- logger.boldError(thrown instanceof Error ? thrown.message : String(thrown));
68
- console.error(usage());
79
+ diagnostics.report({
80
+ level: 'error',
81
+ message: thrown instanceof Error ? thrown.message : String(thrown),
82
+ });
83
+ diagnostics.report({ level: 'notice', message: usage() });
69
84
  return EXIT_USAGE;
70
85
  }
71
86
  const { values, positionals } = parsed;
@@ -83,46 +98,128 @@ export async function run(argv) {
83
98
  rules = await loadRules(additionalRulesDirs);
84
99
  }
85
100
  catch (thrown) {
86
- logger.boldError(thrown instanceof Error ? thrown.message : String(thrown));
101
+ diagnostics.report({
102
+ level: 'error',
103
+ message: thrown instanceof Error ? thrown.message : String(thrown),
104
+ });
87
105
  return EXIT_USAGE;
88
106
  }
89
107
  const configuration = await readConfiguration(values.config, rules);
90
108
  if (!configuration.ok) {
91
- logger.boldError(configuration.message);
92
- for (const detail of configuration.details) {
93
- logger.error(`- ${detail}`);
94
- }
109
+ diagnostics.report({
110
+ level: 'error',
111
+ message: configuration.message,
112
+ details: configuration.details,
113
+ });
95
114
  return EXIT_USAGE;
96
115
  }
97
116
  const ignore = values.ignore?.split(',').map((pattern) => pattern.trim());
98
- const { files, invalidPatterns } = findFeatureFiles(positionals, ignore);
117
+ // Files are handed over as the walk finds them, so reading and checking
118
+ // start on the first one rather than after the last. Only the patterns are
119
+ // checked here; the walk itself happens once per pass.
120
+ const { invalidPatterns } = findFeatureFileStream(positionals, ignore);
99
121
  if (invalidPatterns.length > 0) {
100
122
  for (const pattern of invalidPatterns) {
101
- logger.boldError(`Invalid format of the feature file path/pattern: "${pattern}".`);
123
+ diagnostics.report({
124
+ level: 'error',
125
+ message: `Invalid format of the feature file path/pattern: "${pattern}".`,
126
+ });
102
127
  }
103
- logger.error('To run the linter please specify an existing feature file, directory or glob.');
128
+ diagnostics.report({
129
+ level: 'detail',
130
+ message: 'To run the linter please specify an existing feature file, directory or glob.',
131
+ });
104
132
  return EXIT_USAGE;
105
133
  }
134
+ // A format that can write as the run goes on is driven from the stream, so
135
+ // the first findings appear while the rest of the files are still being
136
+ // checked. The others are handed the whole run at the end, as before.
106
137
  let formatter;
138
+ let streaming;
107
139
  try {
108
- formatter = await loadFormatter(values.format);
140
+ streaming = await loadStreamingFormatter(values.format);
141
+ if (streaming === undefined) {
142
+ formatter = await loadFormatter(values.format);
143
+ }
109
144
  }
110
145
  catch (thrown) {
111
- logger.boldError(thrown instanceof Error ? thrown.message : String(thrown));
146
+ diagnostics.report({
147
+ level: 'error',
148
+ message: thrown instanceof Error ? thrown.message : String(thrown),
149
+ });
112
150
  return EXIT_USAGE;
113
151
  }
114
152
  const language = values.language ?? configuration.language;
115
153
  if (language !== undefined && !isKnownLanguage(language)) {
116
- logger.boldError(`Unknown language "${language}". Use a Gherkin language code, such as "fr".`);
154
+ diagnostics.report({
155
+ level: 'error',
156
+ message: `Unknown language "${language}". Use a Gherkin language code, such as "fr".`,
157
+ });
117
158
  return EXIT_USAGE;
118
159
  }
119
- const results = await lint(files, configuration.configuration, rules, { language });
120
- // A formatter may print the output itself or hand it back as a string.
121
- const output = await formatter(results);
122
- if (typeof output === 'string' && output !== '') {
123
- console.log(output);
160
+ // Discovery is a stream, and a stream can only be read once - so a run that
161
+ // may happen more than once is given a fresh one each time.
162
+ const discover = () => findFeatureFileStream(positionals, ignore).files;
163
+ const checkOnce = async () => {
164
+ if (streaming !== undefined) {
165
+ return await runStreaming(streaming, discover(), configuration.configuration, rules, language, diagnostics);
166
+ }
167
+ const results = await lint(discover(), configuration.configuration, rules, { language });
168
+ // A formatter may print the output itself or hand it back as a string.
169
+ let output;
170
+ try {
171
+ output = await formatter(results);
172
+ }
173
+ catch (thrown) {
174
+ diagnostics.report({
175
+ level: 'error',
176
+ message: `The formatter failed: ${thrown instanceof Error ? thrown.message : String(thrown)}`,
177
+ });
178
+ return EXIT_USAGE;
179
+ }
180
+ if (typeof output === 'string' && output !== '') {
181
+ console.log(output);
182
+ }
183
+ return hasErrors(results) ? EXIT_LINT_ERRORS : EXIT_OK;
184
+ };
185
+ if (values.watch === true) {
186
+ // Watching never fails: a run that found something is the normal state of
187
+ // affairs while you are fixing it, and the exit code is only read once,
188
+ // when you stop.
189
+ return await watch(featureRoots(positionals), values.config ?? DEFAULT_CONFIG_FILE_NAME, { diagnostics, ignore: DEFAULT_IGNORED_NAMES }, checkOnce);
190
+ }
191
+ return await checkOnce();
192
+ }
193
+ /**
194
+ * Lints while writing, so a long run says something before it is over.
195
+ *
196
+ * Nothing is kept but whether anything has failed: holding every result to
197
+ * count them at the end would give back the memory the stream just saved.
198
+ */
199
+ async function runStreaming(streaming, files, configuration, rules, language, diagnostics) {
200
+ const write = (text) => {
201
+ if (text !== undefined && text !== '') {
202
+ process.stdout.write(text);
203
+ }
204
+ };
205
+ let failed = false;
206
+ try {
207
+ const run = streaming();
208
+ write(run.start?.());
209
+ for await (const result of lintStream(files, configuration, rules, { language })) {
210
+ failed ||= result.errors.some((error) => (error.severity ?? 'error') === 'error');
211
+ write(run.file(result));
212
+ }
213
+ write(run.end?.());
214
+ }
215
+ catch (thrown) {
216
+ diagnostics.report({
217
+ level: 'error',
218
+ message: `The formatter failed: ${thrown instanceof Error ? thrown.message : String(thrown)}`,
219
+ });
220
+ return EXIT_USAGE;
124
221
  }
125
- return hasErrors(results) ? EXIT_LINT_ERRORS : EXIT_OK;
222
+ return failed ? EXIT_LINT_ERRORS : EXIT_OK;
126
223
  }
127
224
  /**
128
225
  * True when this file is the script node was asked to run.
@@ -143,8 +240,32 @@ function isMainModule() {
143
240
  return false;
144
241
  }
145
242
  }
243
+ /**
244
+ * Runs the command line, turning anything unexpected into a usage failure.
245
+ *
246
+ * Without this, a crash leaves node to exit 1 - which is the code for "the
247
+ * linter found something" - so a broken run and a dirty feature file would
248
+ * look identical to CI. Anything reaching this handler is a bug rather than a
249
+ * finding, so the whole error is printed and the run fails as unusable.
250
+ */
251
+ async function main(argv) {
252
+ try {
253
+ return await run(argv, TO_STDERR);
254
+ }
255
+ catch (thrown) {
256
+ TO_STDERR.report({
257
+ level: 'error',
258
+ message: 'gurkencheck stopped unexpectedly. This is a bug, please report it:',
259
+ });
260
+ TO_STDERR.report({
261
+ level: 'detail',
262
+ message: thrown instanceof Error ? (thrown.stack ?? thrown.message) : String(thrown),
263
+ });
264
+ return EXIT_USAGE;
265
+ }
266
+ }
146
267
  // Only take over the process when run as a command, not when imported.
147
268
  if (isMainModule()) {
148
- process.exitCode = await run(process.argv.slice(2));
269
+ process.exitCode = await main(process.argv.slice(2));
149
270
  }
150
271
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-dupe-feature-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-dupe-feature-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAQ1C,QAAA,MAAM,IAAI,EAAE,QAoBX,CAAC;eAEa,IAAI"}
1
+ {"version":3,"file":"no-dupe-feature-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-dupe-feature-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAa,MAAM,aAAa,CAAC;AActD,QAAA,MAAM,IAAI,EAAE,QAqCX,CAAC;eAEa,IAAI"}
@@ -1,24 +1,37 @@
1
1
  import { at } from '../util/location.js';
2
2
  const name = 'no-dupe-feature-names';
3
- /** Feature name -> the files it has already been seen in. */
4
- const seen = new Map();
5
3
  const rule = {
6
4
  name,
7
- reset() {
8
- seen.clear();
9
- },
10
- run(feature, file) {
5
+ run(feature, file, _configuration, context) {
11
6
  if (feature === undefined) {
12
7
  return [];
13
8
  }
14
- const previous = seen.get(feature.name);
15
- if (previous === undefined) {
16
- seen.set(feature.name, [file.relativePath]);
17
- return [];
9
+ const seen = context.state(() => new Map());
10
+ const sightings = seen.get(feature.name) ?? [];
11
+ sightings.push({ filePath: file.relativePath, at: at(feature.location) });
12
+ seen.set(feature.name, sightings);
13
+ return [];
14
+ },
15
+ onRunEnd(_configuration, context) {
16
+ const seen = context.state(() => new Map());
17
+ const findings = [];
18
+ for (const sightings of seen.values()) {
19
+ if (sightings.length < 2) {
20
+ continue;
21
+ }
22
+ // Each file hears about the others. Reporting only the later one made
23
+ // the finding move when the files were given in a different order.
24
+ for (const sighting of sightings) {
25
+ const others = sightings.filter((other) => other !== sighting);
26
+ findings.push({
27
+ message: `Feature name is also used in: ${others.map((other) => other.filePath).join(', ')}`,
28
+ rule: name,
29
+ ...sighting.at,
30
+ filePath: sighting.filePath,
31
+ });
32
+ }
18
33
  }
19
- const message = `Feature name is already used in: ${previous.join(', ')}`;
20
- previous.push(file.relativePath);
21
- return [{ message, rule: name, ...at(feature.location) }];
34
+ return findings;
22
35
  },
23
36
  };
24
37
  export default rule;
@@ -1 +1 @@
1
- {"version":3,"file":"no-dupe-feature-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-feature-names.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,uBAAuB,CAAC;AAErC,6DAA6D;AAC7D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC;AAEzC,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,KAAK;QACH,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,GAAG,CAAC,OAAO,EAAE,IAAI;QACf,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YAC5C,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,oCAAoC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjC,OAAO,CAAC,EAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,CAAC,CAAC;IAC1D,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"no-dupe-feature-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-feature-names.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,uBAAuB,CAAC;AAWrC,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO;QACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAO,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/C,SAAS,CAAC,IAAI,CAAC,EAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,CAAC,CAAC;QACxE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAElC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,QAAQ,CAAC,cAAc,EAAE,OAAO;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAO,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAElC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,sEAAsE;YACtE,mEAAmE;YACnE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;gBAC/D,QAAQ,CAAC,IAAI,CAAC;oBACZ,OAAO,EAAE,iCAAiC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBAC5F,IAAI,EAAE,IAAI;oBACV,GAAG,QAAQ,CAAC,EAAE;oBACd,QAAQ,EAAE,QAAQ,CAAC,QAAQ;iBAC5B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-dupe-file-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-dupe-file-names.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAa1C,QAAA,MAAM,IAAI,EAAE,QAkBX,CAAC;eAEa,IAAI"}
1
+ {"version":3,"file":"no-dupe-file-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-dupe-file-names.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAa,MAAM,aAAa,CAAC;AAatD,QAAA,MAAM,IAAI,EAAE,QAyCX,CAAC;eAEa,IAAI"}
@@ -1,27 +1,42 @@
1
1
  import path from 'node:path';
2
2
  const name = 'no-dupe-file-names';
3
- /**
4
- * Two feature files with the same name in different folders are easy to
5
- * confuse, and tools that write one report per feature - naming it after the
6
- * file - quietly overwrite one with the other.
7
- */
8
- /** File name without its extension -> the paths it has already been seen at. */
9
- const seen = new Map();
10
3
  const rule = {
11
4
  name,
12
- reset() {
13
- seen.clear();
14
- },
15
- run(_feature, file) {
5
+ run(_feature, file, _configuration, context) {
6
+ const seen = context.state(() => new Map());
16
7
  const fileName = path.basename(file.relativePath, path.extname(file.relativePath));
17
- const previous = seen.get(fileName);
18
- if (previous === undefined) {
8
+ const paths = seen.get(fileName);
9
+ if (paths === undefined) {
19
10
  seen.set(fileName, [file.relativePath]);
20
- return [];
21
11
  }
22
- const message = `File name is already used in: ${previous.join(', ')}`;
23
- previous.push(file.relativePath);
24
- return [{ message, rule: name, line: 0 }];
12
+ else if (!paths.includes(file.relativePath)) {
13
+ // A file handed to the linter twice is the caller repeating itself, not
14
+ // two files sharing a name.
15
+ paths.push(file.relativePath);
16
+ }
17
+ return [];
18
+ },
19
+ onRunEnd(_configuration, context) {
20
+ const seen = context.state(() => new Map());
21
+ const findings = [];
22
+ for (const paths of seen.values()) {
23
+ if (paths.length < 2) {
24
+ continue;
25
+ }
26
+ // Every file involved hears about every other. Which of them was read
27
+ // first is an accident of the order the files came in, so blaming that
28
+ // one alone says more about the run than about the files.
29
+ for (const filePath of paths) {
30
+ const others = paths.filter((other) => other !== filePath);
31
+ findings.push({
32
+ message: `File name is also used in: ${others.join(', ')}`,
33
+ rule: name,
34
+ line: 0,
35
+ filePath,
36
+ });
37
+ }
38
+ }
39
+ return findings;
25
40
  },
26
41
  };
27
42
  export default rule;
@@ -1 +1 @@
1
- {"version":3,"file":"no-dupe-file-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-file-names.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,IAAI,GAAG,oBAAoB,CAAC;AAElC;;;;GAIG;AAEH,gFAAgF;AAChF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC;AAEzC,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,KAAK;QACH,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,GAAG,CAAC,QAAQ,EAAE,IAAI;QAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEpC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YACxC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,iCAAiC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjC,OAAO,CAAC,EAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAC,CAAC,CAAC;IAC1C,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"no-dupe-file-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-file-names.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,IAAI,GAAG,oBAAoB,CAAC;AAWlC,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAO,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9C,wEAAwE;YACxE,4BAA4B;YAC5B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,QAAQ,CAAC,cAAc,EAAE,OAAO;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAO,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAElC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,SAAS;YACX,CAAC;YACD,sEAAsE;YACtE,uEAAuE;YACvE,0DAA0D;YAC1D,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;gBAC3D,QAAQ,CAAC,IAAI,CAAC;oBACZ,OAAO,EAAE,8BAA8B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBAC1D,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,CAAC;oBACP,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-dupe-scenario-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-dupe-scenario-names.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAgBrD,QAAA,MAAM,IAAI,EAAE,QAoCX,CAAC;eAEa,IAAI"}
1
+ {"version":3,"file":"no-dupe-scenario-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-dupe-scenario-names.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAa,MAAM,aAAa,CAAC;AAiBtD,QAAA,MAAM,IAAI,EAAE,QAkDX,CAAC;eAEa,IAAI"}
@@ -3,38 +3,50 @@ import { at } from '../util/location.js';
3
3
  const name = 'no-dupe-scenario-names';
4
4
  /** Whether duplicates are looked for across all files or within each file. */
5
5
  const availableConfigs = ['anywhere', 'in-feature'];
6
- /** Scenario name -> everywhere it has already been seen. */
7
- const seen = new Map();
8
6
  const rule = {
9
7
  name,
10
8
  availableConfigs,
11
- reset() {
12
- seen.clear();
13
- },
14
- run(feature, file, configuration) {
9
+ run(feature, file, configuration, context) {
15
10
  if (feature === undefined) {
16
11
  return [];
17
12
  }
18
- if (configuration === 'in-feature') {
19
- seen.clear();
20
- }
21
- const errors = [];
13
+ const seen = context.state(() => new Map());
14
+ const withinOneFile = configuration === 'in-feature';
22
15
  for (const { scenario } of scenariosOf(feature)) {
23
- const sighting = { file: file.relativePath, line: scenario.location.line };
24
- const previous = seen.get(scenario.name);
25
- if (previous === undefined) {
26
- seen.set(scenario.name, [sighting]);
16
+ // Told to look within each file, a name only clashes with the same name
17
+ // in the same file - so which file it is in is part of what makes a
18
+ // name that name. A newline cannot appear in either half, so the two
19
+ // cannot run together into a key that means something else.
20
+ const key = withinOneFile ? `${file.relativePath}\n${scenario.name}` : scenario.name;
21
+ const sightings = seen.get(key) ?? [];
22
+ sightings.push({ filePath: file.relativePath, at: at(scenario.location) });
23
+ seen.set(key, sightings);
24
+ }
25
+ return [];
26
+ },
27
+ onRunEnd(_configuration, context) {
28
+ const seen = context.state(() => new Map());
29
+ const findings = [];
30
+ for (const sightings of seen.values()) {
31
+ if (sightings.length < 2) {
27
32
  continue;
28
33
  }
29
- const where = previous.map((seenAt) => `${seenAt.file}:${seenAt.line}`).join(', ');
30
- previous.push(sighting);
31
- errors.push({
32
- message: `Scenario name is already used in: ${where}`,
33
- rule: name,
34
- ...at(scenario.location),
35
- });
34
+ // Every scenario in the group hears about the others, so renaming can
35
+ // start from whichever one is easiest to change.
36
+ for (const sighting of sightings) {
37
+ const others = sightings.filter((other) => other !== sighting);
38
+ const where = others
39
+ .map((other) => `${other.filePath}:${other.at.line}`)
40
+ .join(', ');
41
+ findings.push({
42
+ message: `Scenario name is also used in: ${where}`,
43
+ rule: name,
44
+ ...sighting.at,
45
+ filePath: sighting.filePath,
46
+ });
47
+ }
36
48
  }
37
- return errors;
49
+ return findings;
38
50
  },
39
51
  };
40
52
  export default rule;
@@ -1 +1 @@
1
- {"version":3,"file":"no-dupe-scenario-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-scenario-names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,YAAY,CAAU,CAAC;AAO7D,4DAA4D;AAC5D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE3C,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,gBAAgB;IAChB,KAAK;QACH,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa;QAC9B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAgB,EAAE,CAAC;QAE/B,KAAK,MAAM,EAAC,QAAQ,EAAC,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAa,EAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAC,CAAC;YACnF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAEzC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACpC,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnF,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,qCAAqC,KAAK,EAAE;gBACrD,IAAI,EAAE,IAAI;gBACV,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;aACzB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"no-dupe-scenario-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-scenario-names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,YAAY,CAAU,CAAC;AAW7D,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,gBAAgB;IAChB,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO;QACvC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAO,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,aAAa,GAAG,aAAa,KAAK,YAAY,CAAC;QAErD,KAAK,MAAM,EAAC,QAAQ,EAAC,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,wEAAwE;YACxE,oEAAoE;YACpE,qEAAqE;YACrE,4DAA4D;YAC5D,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACtC,SAAS,CAAC,IAAI,CAAC,EAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAC,CAAC,CAAC;YACzE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC3B,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,QAAQ,CAAC,cAAc,EAAE,OAAO;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAO,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAElC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,sEAAsE;YACtE,iDAAiD;YACjD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;gBAC/D,MAAM,KAAK,GAAG,MAAM;qBACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;qBACpD,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,QAAQ,CAAC,IAAI,CAAC;oBACZ,OAAO,EAAE,kCAAkC,KAAK,EAAE;oBAClD,IAAI,EAAE,IAAI;oBACV,GAAG,QAAQ,CAAC,EAAE;oBACd,QAAQ,EAAE,QAAQ,CAAC,QAAQ;iBAC5B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
package/dist/rules.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Configuration, FeatureFile, RuleConfig, RuleError, RuleRegistry, Severity } from './types.ts';
1
+ import type { Configuration, FeatureFile, RuleConfig, RuleError, RuleRegistry, RunContext, RunFinding, Severity } from './types.ts';
2
2
  import type { Feature } from '@cucumber/messages';
3
3
  /**
4
4
  * The built-in rules, plus any found in the given directories. A custom rule
@@ -11,14 +11,52 @@ export declare function isRuleEnabled(config: RuleConfig | undefined): boolean;
11
11
  export declare function getRuleSeverity(config: RuleConfig | undefined): Severity;
12
12
  /** The rule's own settings, or `undefined` when only a state was given. */
13
13
  export declare function getRuleSettings(config: RuleConfig | undefined): unknown;
14
- /** Clears the state kept by rules that look for duplicates across files. */
14
+ /**
15
+ * Clears the state kept by rules that look for duplicates across files.
16
+ *
17
+ * @deprecated Use `beginRun`, which does this and hands each rule a context
18
+ * of its own besides.
19
+ */
15
20
  export declare function resetRules(rules: RuleRegistry): void;
21
+ /**
22
+ * One rule's state for one run, made the first time the rule asks for it.
23
+ *
24
+ * Exported because testing a rule on its own means handing it one of these.
25
+ */
26
+ export declare function newRunContext(): RunContext;
27
+ /**
28
+ * What one run of the rules keeps for itself.
29
+ *
30
+ * Two runs in the same process have two of these, so a rule remembering what
31
+ * it has seen cannot see what another run has seen.
32
+ */
33
+ export interface Run {
34
+ /** The context for one rule, made the first time it is asked for. */
35
+ contextFor(ruleName: string): RunContext;
36
+ }
37
+ /** Starts a run, telling every enabled rule that one is beginning. */
38
+ export declare function beginRun(rules: RuleRegistry, configuration: Configuration): Run;
39
+ /**
40
+ * Ends a run, collecting what could only be worked out once every file had
41
+ * been seen.
42
+ *
43
+ * As while checking a file, a rule that throws costs you its own findings
44
+ * rather than everyone else's.
45
+ */
46
+ export declare function finishRun(rules: RuleRegistry, configuration: Configuration, run: Run): Promise<RunFinding[]>;
16
47
  /**
17
48
  * Runs every enabled rule against one feature file.
18
49
  *
19
50
  * Rules are awaited one at a time. Most return an array outright, in which
20
51
  * case awaiting costs nothing; a rule that needs to wait for something can
21
52
  * return a promise instead.
53
+ *
54
+ * A rule that throws is reported as an `unexpected-error` finding naming it,
55
+ * and the remaining rules still run.
56
+ *
57
+ * `run` carries the state the rules keep between the files of one run. Left
58
+ * out, a run of this one file alone is started, which is what a caller
59
+ * checking a single file wants.
22
60
  */
23
- export declare function runEnabledRules(feature: Feature | undefined, file: FeatureFile, configuration: Configuration, rules: RuleRegistry): Promise<RuleError[]>;
61
+ export declare function runEnabledRules(feature: Feature | undefined, file: FeatureFile, configuration: Configuration, rules: RuleRegistry, run?: Run): Promise<RuleError[]>;
24
62
  //# sourceMappingURL=rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EAEX,UAAU,EACV,SAAS,EACT,YAAY,EACZ,QAAQ,EACT,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AA4ChD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,mBAAmB,GAAE,SAAS,MAAM,EAAO,GAC1C,OAAO,CAAC,YAAY,CAAC,CAavB;AAOD,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAGrE;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAExE;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAEvE;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAIpD;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,SAAS,EAAE,CAAC,CAiBtB"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EAEX,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,QAAQ,EACT,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAmDhD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,mBAAmB,GAAE,SAAS,MAAM,EAAO,GAC1C,OAAO,CAAC,YAAY,CAAC,CAavB;AAOD,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAGrE;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAExE;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAIpD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAY1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,GAAG;IAClB,qEAAqE;IACrE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC;CAC1C;AAED,sEAAsE;AACtE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,GAAG,GAAG,CAyB/E;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,aAAa,EAC5B,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,UAAU,EAAE,CAAC,CA0BvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,YAAY,EACnB,GAAG,GAAE,GAAoC,GACxC,OAAO,CAAC,SAAS,EAAE,CAAC,CAuCtB"}