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.
- package/README.md +134 -3
- package/dist/config-parser.d.ts.map +1 -1
- package/dist/config-parser.js +7 -1
- package/dist/config-parser.js.map +1 -1
- package/dist/diagnostics.d.ts +34 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +53 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/exit-codes.d.ts +10 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +10 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/feature-finder.d.ts +38 -0
- package/dist/feature-finder.d.ts.map +1 -1
- package/dist/feature-finder.js +86 -8
- package/dist/feature-finder.js.map +1 -1
- package/dist/formatters/index.d.ts +44 -4
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +52 -15
- package/dist/formatters/index.js.map +1 -1
- package/dist/formatters/stylish.d.ts +3 -0
- package/dist/formatters/stylish.d.ts.map +1 -1
- package/dist/formatters/stylish.js +32 -1
- package/dist/formatters/stylish.js.map +1 -1
- package/dist/formatters/tap.d.ts +14 -0
- package/dist/formatters/tap.d.ts.map +1 -1
- package/dist/formatters/tap.js +22 -7
- package/dist/formatters/tap.js.map +1 -1
- package/dist/gherkin/parse.d.ts +42 -1
- package/dist/gherkin/parse.d.ts.map +1 -1
- package/dist/gherkin/parse.js +68 -3
- package/dist/gherkin/parse.js.map +1 -1
- package/dist/index.d.ts +27 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/linter.d.ts +31 -3
- package/dist/linter.d.ts.map +1 -1
- package/dist/linter.js +82 -15
- package/dist/linter.js.map +1 -1
- package/dist/logger.d.ts +2 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +4 -0
- package/dist/logger.js.map +1 -1
- package/dist/main.d.ts +9 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +158 -31
- package/dist/main.js.map +1 -1
- package/dist/rules/no-dupe-feature-names.d.ts.map +1 -1
- package/dist/rules/no-dupe-feature-names.js +26 -13
- package/dist/rules/no-dupe-feature-names.js.map +1 -1
- package/dist/rules/no-dupe-file-names.d.ts.map +1 -1
- package/dist/rules/no-dupe-file-names.js +32 -17
- package/dist/rules/no-dupe-file-names.js.map +1 -1
- package/dist/rules/no-dupe-scenario-names.d.ts.map +1 -1
- package/dist/rules/no-dupe-scenario-names.js +34 -22
- package/dist/rules/no-dupe-scenario-names.js.map +1 -1
- package/dist/rules.d.ts +41 -3
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +112 -4
- package/dist/rules.js.map +1 -1
- package/dist/stats/collect.d.ts +31 -0
- package/dist/stats/collect.d.ts.map +1 -0
- package/dist/stats/collect.js +249 -0
- package/dist/stats/collect.js.map +1 -0
- package/dist/stats/command.d.ts +4 -0
- package/dist/stats/command.d.ts.map +1 -0
- package/dist/stats/command.js +113 -0
- package/dist/stats/command.js.map +1 -0
- package/dist/stats/format/index.d.ts +25 -0
- package/dist/stats/format/index.d.ts.map +1 -0
- package/dist/stats/format/index.js +25 -0
- package/dist/stats/format/index.js.map +1 -0
- package/dist/stats/format/json.d.ts +10 -0
- package/dist/stats/format/json.d.ts.map +1 -0
- package/dist/stats/format/json.js +5 -0
- package/dist/stats/format/json.js.map +1 -0
- package/dist/stats/format/markdown.d.ts +8 -0
- package/dist/stats/format/markdown.d.ts.map +1 -0
- package/dist/stats/format/markdown.js +123 -0
- package/dist/stats/format/markdown.js.map +1 -0
- package/dist/stats/format/shared.d.ts +34 -0
- package/dist/stats/format/shared.d.ts.map +1 -0
- package/dist/stats/format/shared.js +37 -0
- package/dist/stats/format/shared.js.map +1 -0
- package/dist/stats/format/text.d.ts +5 -0
- package/dist/stats/format/text.d.ts.map +1 -0
- package/dist/stats/format/text.js +175 -0
- package/dist/stats/format/text.js.map +1 -0
- package/dist/stats/index.d.ts +21 -0
- package/dist/stats/index.d.ts.map +1 -0
- package/dist/stats/index.js +17 -0
- package/dist/stats/index.js.map +1 -0
- package/dist/stats/normalise.d.ts +38 -0
- package/dist/stats/normalise.d.ts.map +1 -0
- package/dist/stats/normalise.js +65 -0
- package/dist/stats/normalise.js.map +1 -0
- package/dist/stats/similar.d.ts +61 -0
- package/dist/stats/similar.d.ts.map +1 -0
- package/dist/stats/similar.js +173 -0
- package/dist/stats/similar.js.map +1 -0
- package/dist/stats/types.d.ts +159 -0
- package/dist/stats/types.d.ts.map +1 -0
- package/dist/stats/types.js +10 -0
- package/dist/stats/types.js.map +1 -0
- package/dist/types.d.ts +47 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/util/glob.d.ts +18 -0
- package/dist/util/glob.d.ts.map +1 -1
- package/dist/util/glob.js +126 -22
- package/dist/util/glob.js.map +1 -1
- package/dist/util/stream.d.ts +31 -0
- package/dist/util/stream.d.ts.map +1 -0
- package/dist/util/stream.js +67 -0
- package/dist/util/stream.js.map +1 -0
- package/dist/watch.d.ts +36 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +203 -0
- package/dist/watch.js.map +1 -0
- 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
|
-
|
|
13
|
-
seen.
|
|
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
|
|
18
|
-
if (
|
|
8
|
+
const paths = seen.get(fileName);
|
|
9
|
+
if (paths === undefined) {
|
|
19
10
|
seen.set(fileName, [file.relativePath]);
|
|
20
|
-
return [];
|
|
21
11
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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;
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
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;
|
|
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
|
-
/**
|
|
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
|
package/dist/rules.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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":";;;;;;;;AAAA;;GAEG;AACH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AACvC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;
|
|
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"}
|