gurkencheck 0.0.6 → 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 (120) hide show
  1. package/README.md +134 -3
  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/exit-codes.d.ts +10 -0
  10. package/dist/exit-codes.d.ts.map +1 -0
  11. package/dist/exit-codes.js +10 -0
  12. package/dist/exit-codes.js.map +1 -0
  13. package/dist/feature-finder.d.ts +38 -0
  14. package/dist/feature-finder.d.ts.map +1 -1
  15. package/dist/feature-finder.js +86 -8
  16. package/dist/feature-finder.js.map +1 -1
  17. package/dist/formatters/index.d.ts +44 -4
  18. package/dist/formatters/index.d.ts.map +1 -1
  19. package/dist/formatters/index.js +52 -15
  20. package/dist/formatters/index.js.map +1 -1
  21. package/dist/formatters/stylish.d.ts +3 -0
  22. package/dist/formatters/stylish.d.ts.map +1 -1
  23. package/dist/formatters/stylish.js +32 -1
  24. package/dist/formatters/stylish.js.map +1 -1
  25. package/dist/formatters/tap.d.ts +14 -0
  26. package/dist/formatters/tap.d.ts.map +1 -1
  27. package/dist/formatters/tap.js +22 -7
  28. package/dist/formatters/tap.js.map +1 -1
  29. package/dist/gherkin/parse.d.ts +42 -1
  30. package/dist/gherkin/parse.d.ts.map +1 -1
  31. package/dist/gherkin/parse.js +68 -3
  32. package/dist/gherkin/parse.js.map +1 -1
  33. package/dist/index.d.ts +27 -9
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +15 -5
  36. package/dist/index.js.map +1 -1
  37. package/dist/linter.d.ts +31 -3
  38. package/dist/linter.d.ts.map +1 -1
  39. package/dist/linter.js +82 -15
  40. package/dist/linter.js.map +1 -1
  41. package/dist/logger.d.ts +2 -0
  42. package/dist/logger.d.ts.map +1 -1
  43. package/dist/logger.js +4 -0
  44. package/dist/logger.js.map +1 -1
  45. package/dist/main.d.ts +9 -1
  46. package/dist/main.d.ts.map +1 -1
  47. package/dist/main.js +158 -31
  48. package/dist/main.js.map +1 -1
  49. package/dist/rules/no-dupe-feature-names.d.ts.map +1 -1
  50. package/dist/rules/no-dupe-feature-names.js +26 -13
  51. package/dist/rules/no-dupe-feature-names.js.map +1 -1
  52. package/dist/rules/no-dupe-file-names.d.ts.map +1 -1
  53. package/dist/rules/no-dupe-file-names.js +32 -17
  54. package/dist/rules/no-dupe-file-names.js.map +1 -1
  55. package/dist/rules/no-dupe-scenario-names.d.ts.map +1 -1
  56. package/dist/rules/no-dupe-scenario-names.js +34 -22
  57. package/dist/rules/no-dupe-scenario-names.js.map +1 -1
  58. package/dist/rules.d.ts +41 -3
  59. package/dist/rules.d.ts.map +1 -1
  60. package/dist/rules.js +112 -4
  61. package/dist/rules.js.map +1 -1
  62. package/dist/stats/collect.d.ts +31 -0
  63. package/dist/stats/collect.d.ts.map +1 -0
  64. package/dist/stats/collect.js +249 -0
  65. package/dist/stats/collect.js.map +1 -0
  66. package/dist/stats/command.d.ts +4 -0
  67. package/dist/stats/command.d.ts.map +1 -0
  68. package/dist/stats/command.js +113 -0
  69. package/dist/stats/command.js.map +1 -0
  70. package/dist/stats/format/index.d.ts +25 -0
  71. package/dist/stats/format/index.d.ts.map +1 -0
  72. package/dist/stats/format/index.js +25 -0
  73. package/dist/stats/format/index.js.map +1 -0
  74. package/dist/stats/format/json.d.ts +10 -0
  75. package/dist/stats/format/json.d.ts.map +1 -0
  76. package/dist/stats/format/json.js +5 -0
  77. package/dist/stats/format/json.js.map +1 -0
  78. package/dist/stats/format/markdown.d.ts +8 -0
  79. package/dist/stats/format/markdown.d.ts.map +1 -0
  80. package/dist/stats/format/markdown.js +123 -0
  81. package/dist/stats/format/markdown.js.map +1 -0
  82. package/dist/stats/format/shared.d.ts +34 -0
  83. package/dist/stats/format/shared.d.ts.map +1 -0
  84. package/dist/stats/format/shared.js +37 -0
  85. package/dist/stats/format/shared.js.map +1 -0
  86. package/dist/stats/format/text.d.ts +5 -0
  87. package/dist/stats/format/text.d.ts.map +1 -0
  88. package/dist/stats/format/text.js +175 -0
  89. package/dist/stats/format/text.js.map +1 -0
  90. package/dist/stats/index.d.ts +21 -0
  91. package/dist/stats/index.d.ts.map +1 -0
  92. package/dist/stats/index.js +17 -0
  93. package/dist/stats/index.js.map +1 -0
  94. package/dist/stats/normalise.d.ts +38 -0
  95. package/dist/stats/normalise.d.ts.map +1 -0
  96. package/dist/stats/normalise.js +65 -0
  97. package/dist/stats/normalise.js.map +1 -0
  98. package/dist/stats/similar.d.ts +61 -0
  99. package/dist/stats/similar.d.ts.map +1 -0
  100. package/dist/stats/similar.js +173 -0
  101. package/dist/stats/similar.js.map +1 -0
  102. package/dist/stats/types.d.ts +159 -0
  103. package/dist/stats/types.d.ts.map +1 -0
  104. package/dist/stats/types.js +10 -0
  105. package/dist/stats/types.js.map +1 -0
  106. package/dist/types.d.ts +47 -3
  107. package/dist/types.d.ts.map +1 -1
  108. package/dist/util/glob.d.ts +18 -0
  109. package/dist/util/glob.d.ts.map +1 -1
  110. package/dist/util/glob.js +126 -22
  111. package/dist/util/glob.js.map +1 -1
  112. package/dist/util/stream.d.ts +31 -0
  113. package/dist/util/stream.d.ts.map +1 -0
  114. package/dist/util/stream.js +67 -0
  115. package/dist/util/stream.js.map +1 -0
  116. package/dist/watch.d.ts +36 -0
  117. package/dist/watch.d.ts.map +1 -0
  118. package/dist/watch.js +203 -0
  119. package/dist/watch.js.map +1 -0
  120. package/package.json +1 -1
@@ -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"}
package/dist/rules.js CHANGED
@@ -39,7 +39,13 @@ async function loadRulesFrom(directory) {
39
39
  const loaded = [];
40
40
  for (const file of files) {
41
41
  const absolute = path.join(resolved, file);
42
- const module = (await import(__rewriteRelativeImportExtension(pathToFileURL(absolute).href)));
42
+ let module;
43
+ try {
44
+ module = (await import(__rewriteRelativeImportExtension(pathToFileURL(absolute).href)));
45
+ }
46
+ catch (thrown) {
47
+ throw new Error(`Could not load the rule "${absolute}": ${thrown instanceof Error ? thrown.message : String(thrown)}`);
48
+ }
43
49
  loaded.push(extractRule(module, absolute));
44
50
  }
45
51
  return loaded;
@@ -77,20 +83,106 @@ export function getRuleSeverity(config) {
77
83
  export function getRuleSettings(config) {
78
84
  return Array.isArray(config) ? config[1] : undefined;
79
85
  }
80
- /** Clears the state kept by rules that look for duplicates across files. */
86
+ /**
87
+ * Clears the state kept by rules that look for duplicates across files.
88
+ *
89
+ * @deprecated Use `beginRun`, which does this and hands each rule a context
90
+ * of its own besides.
91
+ */
81
92
  export function resetRules(rules) {
82
93
  for (const rule of rules.values()) {
83
94
  rule.reset?.();
84
95
  }
85
96
  }
97
+ /**
98
+ * One rule's state for one run, made the first time the rule asks for it.
99
+ *
100
+ * Exported because testing a rule on its own means handing it one of these.
101
+ */
102
+ export function newRunContext() {
103
+ let state;
104
+ let made = false;
105
+ return {
106
+ state(create) {
107
+ if (!made) {
108
+ state = create();
109
+ made = true;
110
+ }
111
+ return state;
112
+ },
113
+ };
114
+ }
115
+ /** Starts a run, telling every enabled rule that one is beginning. */
116
+ export function beginRun(rules, configuration) {
117
+ // Rules written before contexts existed keep their state in the module and
118
+ // clear it here. Deprecated, but still honoured.
119
+ resetRules(rules);
120
+ const contexts = new Map();
121
+ const run = {
122
+ contextFor(ruleName) {
123
+ let context = contexts.get(ruleName);
124
+ if (context === undefined) {
125
+ context = newRunContext();
126
+ contexts.set(ruleName, context);
127
+ }
128
+ return context;
129
+ },
130
+ };
131
+ for (const rule of rules.values()) {
132
+ const config = configuration[rule.name];
133
+ if (isRuleEnabled(config)) {
134
+ rule.onRunStart?.(getRuleSettings(config), run.contextFor(rule.name));
135
+ }
136
+ }
137
+ return run;
138
+ }
139
+ /**
140
+ * Ends a run, collecting what could only be worked out once every file had
141
+ * been seen.
142
+ *
143
+ * As while checking a file, a rule that throws costs you its own findings
144
+ * rather than everyone else's.
145
+ */
146
+ export async function finishRun(rules, configuration, run) {
147
+ const findings = [];
148
+ for (const rule of rules.values()) {
149
+ const config = configuration[rule.name];
150
+ if (!isRuleEnabled(config) || rule.onRunEnd === undefined) {
151
+ continue;
152
+ }
153
+ const severity = getRuleSeverity(config);
154
+ try {
155
+ const found = await rule.onRunEnd(getRuleSettings(config), run.contextFor(rule.name));
156
+ for (const finding of found) {
157
+ findings.push({ severity, ...finding });
158
+ }
159
+ }
160
+ catch (thrown) {
161
+ // No file to blame: what failed was the look back over all of them.
162
+ findings.push({
163
+ message: `Rule "${rule.name}" failed at the end of the run: ${thrown instanceof Error ? thrown.message : String(thrown)}`,
164
+ rule: 'unexpected-error',
165
+ line: 0,
166
+ });
167
+ }
168
+ }
169
+ return findings;
170
+ }
86
171
  /**
87
172
  * Runs every enabled rule against one feature file.
88
173
  *
89
174
  * Rules are awaited one at a time. Most return an array outright, in which
90
175
  * case awaiting costs nothing; a rule that needs to wait for something can
91
176
  * return a promise instead.
177
+ *
178
+ * A rule that throws is reported as an `unexpected-error` finding naming it,
179
+ * and the remaining rules still run.
180
+ *
181
+ * `run` carries the state the rules keep between the files of one run. Left
182
+ * out, a run of this one file alone is started, which is what a caller
183
+ * checking a single file wants.
92
184
  */
93
- export async function runEnabledRules(feature, file, configuration, rules) {
185
+ export async function runEnabledRules(feature, file, configuration, rules, run = beginRun(rules, configuration)) {
94
186
  const errors = [];
95
187
  for (const rule of rules.values()) {
96
188
  const config = configuration[rule.name];
@@ -98,7 +190,23 @@ export async function runEnabledRules(feature, file, configuration, rules) {
98
190
  continue;
99
191
  }
100
192
  const severity = getRuleSeverity(config);
101
- for (const error of await rule.run(feature, file, getRuleSettings(config))) {
193
+ let found;
194
+ try {
195
+ found = await rule.run(feature, file, getRuleSettings(config), run.contextFor(rule.name));
196
+ }
197
+ catch (thrown) {
198
+ // A rule that throws - one of your own from --rulesdir, or a built-in
199
+ // one meeting a file it did not expect - costs you that rule's findings
200
+ // for this file, not every other rule's. The failure is reported in
201
+ // their place so that it cannot pass unnoticed.
202
+ errors.push({
203
+ message: `Rule "${rule.name}" failed: ${thrown instanceof Error ? thrown.message : String(thrown)}`,
204
+ rule: 'unexpected-error',
205
+ line: 0,
206
+ });
207
+ continue;
208
+ }
209
+ for (const error of found) {
102
210
  // The configuration decides how loudly a rule reports, so a custom rule
103
211
  // needs no say in it - but one that sets a severity itself is respected.
104
212
  errors.push({ severity, ...error });
package/dist/rules.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { ParseResult } from '../gherkin/parse.ts';
2
+ import type { SimilarityOptions } from './similar.ts';
3
+ import type { Sequence } from '../util/stream.ts';
4
+ import type { Distribution, Statistics } from './types.ts';
5
+ export interface CollectOptions {
6
+ /** How alike two steps have to be to be reported as nearly the same. */
7
+ similarity?: SimilarityOptions;
8
+ }
9
+ /**
10
+ * A summary of a set of counts.
11
+ *
12
+ * The quantiles are nearest-rank: the median of an even set is the lower of
13
+ * the two middle values rather than the average of them, so every number in
14
+ * the summary is a number some scenario actually has.
15
+ */
16
+ export declare function distribution(values: readonly number[]): Distribution;
17
+ /**
18
+ * Counts a set of parsed feature files.
19
+ *
20
+ * Files the parser refused are listed rather than counted: half a broken file
21
+ * is worse than none of it, because the numbers would quietly be wrong.
22
+ */
23
+ export declare function collectStatistics(parsed: readonly ParseResult[], options?: CollectOptions): Statistics;
24
+ /**
25
+ * The same count, over files arriving one at a time.
26
+ *
27
+ * Nothing here holds on to a parsed document once it has been counted, so a
28
+ * suite of any size costs the same as the report it produces.
29
+ */
30
+ export declare function collectStatisticsFrom(parsed: Sequence<ParseResult>, options?: CollectOptions): Promise<Statistics>;
31
+ //# sourceMappingURL=collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/stats/collect.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAWrD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EAMZ,UAAU,EAGX,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CAkBpE;AAgRD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,GAAE,cAAmB,GAC3B,UAAU,CAMZ;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC7B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC,CAMrB"}