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
package/dist/linter.d.ts
CHANGED
|
@@ -1,18 +1,46 @@
|
|
|
1
1
|
import type { Configuration, FileResult, RuleRegistry } from './types.ts';
|
|
2
|
+
import type { Sequence } from './util/stream.ts';
|
|
2
3
|
export interface LintOptions {
|
|
3
4
|
/**
|
|
4
5
|
* The dialect to read a file in when it carries no `# language:` header,
|
|
5
6
|
* for projects written entirely in one language.
|
|
6
7
|
*/
|
|
7
8
|
language?: string;
|
|
9
|
+
/**
|
|
10
|
+
* How many files to read ahead of the one being checked. Left out, a
|
|
11
|
+
* sensible default is used; there is rarely a reason to set it.
|
|
12
|
+
*/
|
|
13
|
+
readAhead?: number;
|
|
8
14
|
}
|
|
9
15
|
/**
|
|
10
|
-
* Lints every file
|
|
16
|
+
* Lints every file, handing back each result as soon as it is final.
|
|
11
17
|
*
|
|
12
18
|
* Files are read concurrently but checked one after another, because rules
|
|
13
|
-
* that look for duplicates across files need a predictable order.
|
|
19
|
+
* that look for duplicates across files need a predictable order. Results
|
|
20
|
+
* come in the order the files were given.
|
|
21
|
+
*
|
|
22
|
+
* A rule that reports across files - two files sharing a name - cannot know
|
|
23
|
+
* what it has found until every file has been seen, so switching one on holds
|
|
24
|
+
* every result back until the end. That is the honest cost of the question it
|
|
25
|
+
* answers, not something to work around: a result handed over early would
|
|
26
|
+
* have to be taken back. With no such rule on, each result arrives as its
|
|
27
|
+
* file is checked.
|
|
28
|
+
*
|
|
29
|
+
* Files are read ahead of being checked, a bounded number at a time, so the
|
|
30
|
+
* next one is on its way while this one is being checked without the whole
|
|
31
|
+
* suite being held in memory at once.
|
|
32
|
+
*
|
|
33
|
+
* Stopping early - `break` in a `for await` - stops the reading as well as
|
|
34
|
+
* the checking, rather than running on to the last file.
|
|
35
|
+
*/
|
|
36
|
+
export declare function lintStream(files: Sequence<string>, configuration: Configuration, rules: RuleRegistry, options?: LintOptions): AsyncGenerator<FileResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Lints every file and returns one result per file, in the order given.
|
|
39
|
+
*
|
|
40
|
+
* The whole run at once. For results as they are ready - a progress line, an
|
|
41
|
+
* editor, stopping at the first error - use `lintStream`.
|
|
14
42
|
*/
|
|
15
|
-
export declare function lint(files:
|
|
43
|
+
export declare function lint(files: Sequence<string>, configuration: Configuration, rules: RuleRegistry, options?: LintOptions): Promise<FileResult[]>;
|
|
16
44
|
/** True when any file has a finding serious enough to fail the run. */
|
|
17
45
|
export declare function hasErrors(results: readonly FileResult[]): boolean;
|
|
18
46
|
/** How many findings there are of each severity. */
|
package/dist/linter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,aAAa,EAAE,UAAU,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAExE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAK/C,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAuB,UAAU,CAC/B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,WAAgB,GACxB,cAAc,CAAC,UAAU,CAAC,CAuD5B;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CACxB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,EAAE,CAAC,CAMvB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,OAAO,CAIjE;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAaA"}
|
package/dist/linter.js
CHANGED
|
@@ -2,35 +2,102 @@
|
|
|
2
2
|
* Running the rules over a set of feature files.
|
|
3
3
|
*/
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { readAndParseFiles } from './gherkin/parse.js';
|
|
6
|
+
import { beginRun, finishRun, isRuleEnabled, runEnabledRules } from './rules.js';
|
|
7
7
|
import { readSuppressions } from './suppressions.js';
|
|
8
8
|
import { sortBy } from './util/collections.js';
|
|
9
|
+
/** Stands in for a file whose directives were never read, and hides nothing. */
|
|
10
|
+
const EMPTY_SUPPRESSIONS = { isEmpty: true, isSuppressed: () => false };
|
|
11
|
+
/** True when a rule that only reports once every file has been seen is on. */
|
|
12
|
+
function reportsAcrossFiles(rules, configuration) {
|
|
13
|
+
for (const rule of rules.values()) {
|
|
14
|
+
if (rule.onRunEnd !== undefined && isRuleEnabled(configuration[rule.name])) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
9
20
|
/**
|
|
10
|
-
* Lints every file
|
|
21
|
+
* Lints every file, handing back each result as soon as it is final.
|
|
11
22
|
*
|
|
12
23
|
* Files are read concurrently but checked one after another, because rules
|
|
13
|
-
* that look for duplicates across files need a predictable order.
|
|
24
|
+
* that look for duplicates across files need a predictable order. Results
|
|
25
|
+
* come in the order the files were given.
|
|
26
|
+
*
|
|
27
|
+
* A rule that reports across files - two files sharing a name - cannot know
|
|
28
|
+
* what it has found until every file has been seen, so switching one on holds
|
|
29
|
+
* every result back until the end. That is the honest cost of the question it
|
|
30
|
+
* answers, not something to work around: a result handed over early would
|
|
31
|
+
* have to be taken back. With no such rule on, each result arrives as its
|
|
32
|
+
* file is checked.
|
|
33
|
+
*
|
|
34
|
+
* Files are read ahead of being checked, a bounded number at a time, so the
|
|
35
|
+
* next one is on its way while this one is being checked without the whole
|
|
36
|
+
* suite being held in memory at once.
|
|
37
|
+
*
|
|
38
|
+
* Stopping early - `break` in a `for await` - stops the reading as well as
|
|
39
|
+
* the checking, rather than running on to the last file.
|
|
14
40
|
*/
|
|
15
|
-
export async function
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
41
|
+
export async function* lintStream(files, configuration, rules, options = {}) {
|
|
42
|
+
const run = beginRun(rules, configuration);
|
|
43
|
+
const held = reportsAcrossFiles(rules, configuration);
|
|
44
|
+
const waiting = [];
|
|
45
|
+
/** Where to put a finding that names a file, and what may hide it there. */
|
|
46
|
+
const byPath = new Map();
|
|
47
|
+
for await (const result of readAndParseFiles(files, {
|
|
48
|
+
language: options.language,
|
|
49
|
+
readAhead: options.readAhead,
|
|
50
|
+
})) {
|
|
20
51
|
// Parse errors are not suppressible: the file could not be read, so
|
|
21
52
|
// hiding the message would leave nothing in its place.
|
|
22
53
|
let errors = result.errors;
|
|
54
|
+
let suppressions = EMPTY_SUPPRESSIONS;
|
|
23
55
|
if (errors.length === 0) {
|
|
24
|
-
errors = await runEnabledRules(result.feature, result.file, configuration, rules);
|
|
25
|
-
|
|
56
|
+
errors = await runEnabledRules(result.feature, result.file, configuration, rules, run);
|
|
57
|
+
suppressions = readSuppressions(result.file.lines);
|
|
26
58
|
if (!suppressions.isEmpty) {
|
|
27
59
|
errors = errors.filter((error) => !suppressions.isSuppressed(error));
|
|
28
60
|
}
|
|
29
61
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
62
|
+
const fileResult = { filePath: path.resolve(result.file.relativePath), errors };
|
|
63
|
+
byPath.set(result.file.relativePath, { result: fileResult, suppressions });
|
|
64
|
+
if (held) {
|
|
65
|
+
waiting.push(fileResult);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
fileResult.errors = sortBy(fileResult.errors, (error) => error.line);
|
|
69
|
+
yield fileResult;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// What only the whole run could show: two files sharing a name, and the
|
|
73
|
+
// like. A finding naming no file is about the run itself - a rule that
|
|
74
|
+
// failed looking back over it - and goes against the first file so that it
|
|
75
|
+
// is seen at all.
|
|
76
|
+
for (const { filePath, ...error } of await finishRun(rules, configuration, run)) {
|
|
77
|
+
const target = filePath === undefined ? undefined : byPath.get(filePath);
|
|
78
|
+
if (target === undefined) {
|
|
79
|
+
waiting[0]?.errors.push(error);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (!target.suppressions.isSuppressed(error)) {
|
|
83
|
+
target.result.errors.push(error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const result of waiting) {
|
|
87
|
+
result.errors = sortBy(result.errors, (error) => error.line);
|
|
88
|
+
yield result;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Lints every file and returns one result per file, in the order given.
|
|
93
|
+
*
|
|
94
|
+
* The whole run at once. For results as they are ready - a progress line, an
|
|
95
|
+
* editor, stopping at the first error - use `lintStream`.
|
|
96
|
+
*/
|
|
97
|
+
export async function lint(files, configuration, rules, options = {}) {
|
|
98
|
+
const results = [];
|
|
99
|
+
for await (const result of lintStream(files, configuration, rules, options)) {
|
|
100
|
+
results.push(result);
|
|
34
101
|
}
|
|
35
102
|
return results;
|
|
36
103
|
}
|
package/dist/linter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
export declare function error(message: string): void;
|
|
7
7
|
/** Writes a bold red message to stderr. */
|
|
8
8
|
export declare function boldError(message: string): void;
|
|
9
|
+
/** Writes a message to stderr without colouring it. */
|
|
10
|
+
export declare function note(message: string): void;
|
|
9
11
|
/** Text decorations used by the stylish formatter. */
|
|
10
12
|
export declare const style: {
|
|
11
13
|
gray: (text: string) => string;
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,sCAAsC;AACtC,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,2CAA2C;AAC3C,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,sDAAsD;AACtD,eAAO,MAAM,KAAK;IAChB,IAAI,SAAS,MAAM,KAAG,MAAM;IAC5B,SAAS,SAAS,MAAM,KAAG,MAAM;IACjC,gFAAgF;IAChF,QAAQ,aAAa,MAAM,QAAQ,MAAM,KAAG,MAAM;CAEnD,CAAC"}
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,sCAAsC;AACtC,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,2CAA2C;AAC3C,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,uDAAuD;AACvD,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,sDAAsD;AACtD,eAAO,MAAM,KAAK;IAChB,IAAI,SAAS,MAAM,KAAG,MAAM;IAC5B,SAAS,SAAS,MAAM,KAAG,MAAM;IACjC,gFAAgF;IAChF,QAAQ,aAAa,MAAM,QAAQ,MAAM,KAAG,MAAM;CAEnD,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -18,6 +18,10 @@ export function error(message) {
|
|
|
18
18
|
export function boldError(message) {
|
|
19
19
|
console.error(paint(`${ESC}31m${ESC}1m`, message));
|
|
20
20
|
}
|
|
21
|
+
/** Writes a message to stderr without colouring it. */
|
|
22
|
+
export function note(message) {
|
|
23
|
+
console.error(message);
|
|
24
|
+
}
|
|
21
25
|
/** Text decorations used by the stylish formatter. */
|
|
22
26
|
export const style = {
|
|
23
27
|
gray: (text) => paint(`${ESC}38;5;243m`, text),
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC;AAEzB,SAAS,QAAQ;IACf,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,OAAe;IAC3C,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC7D,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI,EAAE,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,GAAG,GAAG,WAAW,EAAE,IAAI,CAAC;IAC9D,SAAS,EAAE,CAAC,IAAY,EAAU,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACvF,gFAAgF;IAChF,QAAQ,EAAE,CAAC,QAAgB,EAAE,IAAY,EAAU,EAAE,CACnD,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,EAAE,IAAI,CAAC;CAClE,CAAC"}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC;AAEzB,SAAS,QAAQ;IACf,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,OAAe;IAC3C,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC7D,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI,EAAE,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,GAAG,GAAG,WAAW,EAAE,IAAI,CAAC;IAC9D,SAAS,EAAE,CAAC,IAAY,EAAU,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACvF,gFAAgF;IAChF,QAAQ,EAAE,CAAC,QAAgB,EAAE,IAAY,EAAU,EAAE,CACnD,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,EAAE,IAAI,CAAC;CAClE,CAAC"}
|
package/dist/main.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
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
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";
|
|
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
|
@@ -6,19 +6,18 @@ import fs from 'node:fs';
|
|
|
6
6
|
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
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { EXIT_LINT_ERRORS, EXIT_OK, EXIT_USAGE } from './exit-codes.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';
|
|
11
13
|
import { isKnownLanguage } from './gherkin/dialects.js';
|
|
12
|
-
import { hasErrors, lint } from './linter.js';
|
|
13
|
-
import
|
|
14
|
+
import { hasErrors, lint, lintStream } from './linter.js';
|
|
15
|
+
import { SILENT, TO_STDERR } from './diagnostics.js';
|
|
14
16
|
import { loadRules } from './rules.js';
|
|
17
|
+
import { runStats } from './stats/command.js';
|
|
15
18
|
import { version } from './version.js';
|
|
16
|
-
/**
|
|
17
|
-
const
|
|
18
|
-
/** At least one finding serious enough to fail the run. Warnings alone do not. */
|
|
19
|
-
const EXIT_LINT_ERRORS = 1;
|
|
20
|
-
/** The linter could not run: bad arguments, missing or invalid config. */
|
|
21
|
-
const EXIT_USAGE = 2;
|
|
19
|
+
/** Directory names a watch takes no notice of, however deep they turn up. */
|
|
20
|
+
const DEFAULT_IGNORED_NAMES = ['node_modules', '.git'];
|
|
22
21
|
function usage() {
|
|
23
22
|
return [
|
|
24
23
|
'Usage: gurkencheck [options] <feature-files>',
|
|
@@ -33,14 +32,32 @@ function usage() {
|
|
|
33
32
|
` -i, --ignore <globs> comma separated globs to skip, overriding ${DEFAULT_IGNORE_FILE_NAME}`,
|
|
34
33
|
' -r, --rulesdir <dir> directory of custom rules; may be given more than once',
|
|
35
34
|
' -l, --language <code> dialect for files with no "# language:" header',
|
|
35
|
+
' -w, --watch keep running, checking again whenever a file changes',
|
|
36
36
|
' -h, --help show this message',
|
|
37
37
|
' -v, --version show the version number',
|
|
38
38
|
'',
|
|
39
|
+
'Commands:',
|
|
40
|
+
' stats [paths] report on the shape of your feature files,',
|
|
41
|
+
' rather than on what is wrong with them',
|
|
42
|
+
'',
|
|
39
43
|
'With no files given, the working directory is searched recursively.',
|
|
40
44
|
'Documentation: https://sebs.github.io/gurkencheck/',
|
|
41
45
|
].join('\n');
|
|
42
46
|
}
|
|
43
|
-
|
|
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) {
|
|
55
|
+
// Subcommands are matched before the options are read, so that `stats` can
|
|
56
|
+
// accept a --format of its own without the two sets of names colliding.
|
|
57
|
+
// A directory really called `stats` is still lintable, as `./stats`.
|
|
58
|
+
if (argv[0] === 'stats') {
|
|
59
|
+
return runStats(argv.slice(1), diagnostics);
|
|
60
|
+
}
|
|
44
61
|
let parsed;
|
|
45
62
|
try {
|
|
46
63
|
parsed = parseArgs({
|
|
@@ -51,6 +68,7 @@ export async function run(argv) {
|
|
|
51
68
|
ignore: { type: 'string', short: 'i' },
|
|
52
69
|
rulesdir: { type: 'string', short: 'r', multiple: true },
|
|
53
70
|
language: { type: 'string', short: 'l' },
|
|
71
|
+
watch: { type: 'boolean', short: 'w' },
|
|
54
72
|
help: { type: 'boolean', short: 'h' },
|
|
55
73
|
version: { type: 'boolean', short: 'v' },
|
|
56
74
|
},
|
|
@@ -58,8 +76,11 @@ export async function run(argv) {
|
|
|
58
76
|
});
|
|
59
77
|
}
|
|
60
78
|
catch (thrown) {
|
|
61
|
-
|
|
62
|
-
|
|
79
|
+
diagnostics.report({
|
|
80
|
+
level: 'error',
|
|
81
|
+
message: thrown instanceof Error ? thrown.message : String(thrown),
|
|
82
|
+
});
|
|
83
|
+
diagnostics.report({ level: 'notice', message: usage() });
|
|
63
84
|
return EXIT_USAGE;
|
|
64
85
|
}
|
|
65
86
|
const { values, positionals } = parsed;
|
|
@@ -77,46 +98,128 @@ export async function run(argv) {
|
|
|
77
98
|
rules = await loadRules(additionalRulesDirs);
|
|
78
99
|
}
|
|
79
100
|
catch (thrown) {
|
|
80
|
-
|
|
101
|
+
diagnostics.report({
|
|
102
|
+
level: 'error',
|
|
103
|
+
message: thrown instanceof Error ? thrown.message : String(thrown),
|
|
104
|
+
});
|
|
81
105
|
return EXIT_USAGE;
|
|
82
106
|
}
|
|
83
107
|
const configuration = await readConfiguration(values.config, rules);
|
|
84
108
|
if (!configuration.ok) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
diagnostics.report({
|
|
110
|
+
level: 'error',
|
|
111
|
+
message: configuration.message,
|
|
112
|
+
details: configuration.details,
|
|
113
|
+
});
|
|
89
114
|
return EXIT_USAGE;
|
|
90
115
|
}
|
|
91
116
|
const ignore = values.ignore?.split(',').map((pattern) => pattern.trim());
|
|
92
|
-
|
|
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);
|
|
93
121
|
if (invalidPatterns.length > 0) {
|
|
94
122
|
for (const pattern of invalidPatterns) {
|
|
95
|
-
|
|
123
|
+
diagnostics.report({
|
|
124
|
+
level: 'error',
|
|
125
|
+
message: `Invalid format of the feature file path/pattern: "${pattern}".`,
|
|
126
|
+
});
|
|
96
127
|
}
|
|
97
|
-
|
|
128
|
+
diagnostics.report({
|
|
129
|
+
level: 'detail',
|
|
130
|
+
message: 'To run the linter please specify an existing feature file, directory or glob.',
|
|
131
|
+
});
|
|
98
132
|
return EXIT_USAGE;
|
|
99
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.
|
|
100
137
|
let formatter;
|
|
138
|
+
let streaming;
|
|
101
139
|
try {
|
|
102
|
-
|
|
140
|
+
streaming = await loadStreamingFormatter(values.format);
|
|
141
|
+
if (streaming === undefined) {
|
|
142
|
+
formatter = await loadFormatter(values.format);
|
|
143
|
+
}
|
|
103
144
|
}
|
|
104
145
|
catch (thrown) {
|
|
105
|
-
|
|
146
|
+
diagnostics.report({
|
|
147
|
+
level: 'error',
|
|
148
|
+
message: thrown instanceof Error ? thrown.message : String(thrown),
|
|
149
|
+
});
|
|
106
150
|
return EXIT_USAGE;
|
|
107
151
|
}
|
|
108
152
|
const language = values.language ?? configuration.language;
|
|
109
153
|
if (language !== undefined && !isKnownLanguage(language)) {
|
|
110
|
-
|
|
154
|
+
diagnostics.report({
|
|
155
|
+
level: 'error',
|
|
156
|
+
message: `Unknown language "${language}". Use a Gherkin language code, such as "fr".`,
|
|
157
|
+
});
|
|
111
158
|
return EXIT_USAGE;
|
|
112
159
|
}
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
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;
|
|
118
221
|
}
|
|
119
|
-
return
|
|
222
|
+
return failed ? EXIT_LINT_ERRORS : EXIT_OK;
|
|
120
223
|
}
|
|
121
224
|
/**
|
|
122
225
|
* True when this file is the script node was asked to run.
|
|
@@ -137,8 +240,32 @@ function isMainModule() {
|
|
|
137
240
|
return false;
|
|
138
241
|
}
|
|
139
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
|
+
}
|
|
140
267
|
// Only take over the process when run as a command, not when imported.
|
|
141
268
|
if (isMainModule()) {
|
|
142
|
-
process.exitCode = await
|
|
269
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
143
270
|
}
|
|
144
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":";AACA;;GAEG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AACvC,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAAC,wBAAwB,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAC,
|
|
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,
|
|
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
|
-
|
|
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
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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;
|
|
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,
|
|
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"}
|