pipework 0.269.0 → 0.271.0
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/CHANGELOG.md +9 -0
- package/REFERENCE.md +44 -0
- package/dist/cli/commands/check-steps.d.ts +34 -0
- package/dist/cli/commands/check-steps.d.ts.map +1 -0
- package/dist/cli/commands/check-steps.js +60 -0
- package/dist/cli/commands/check-steps.js.map +1 -0
- package/dist/cli/commands/check.d.ts +43 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +232 -133
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +36 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +55 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/lint/config.d.ts +4 -0
- package/dist/lint/config.d.ts.map +1 -1
- package/dist/lint/config.js +6 -0
- package/dist/lint/config.js.map +1 -1
- package/dist/lint/doctrine.d.ts +4 -0
- package/dist/lint/doctrine.d.ts.map +1 -1
- package/dist/lint/doctrine.js +14 -7
- package/dist/lint/doctrine.js.map +1 -1
- package/dist/lint/rules/doctrine.d.ts +3 -0
- package/dist/lint/rules/doctrine.d.ts.map +1 -0
- package/dist/lint/rules/doctrine.js +28 -0
- package/dist/lint/rules/doctrine.js.map +1 -0
- package/dist/trace/cardinality/check.d.ts +5 -1
- package/dist/trace/cardinality/check.d.ts.map +1 -1
- package/dist/trace/cardinality/check.js +3 -1
- package/dist/trace/cardinality/check.js.map +1 -1
- package/dist/trace/check/coverage-check.d.ts +2 -0
- package/dist/trace/check/coverage-check.d.ts.map +1 -1
- package/dist/trace/check/coverage-check.js +3 -1
- package/dist/trace/check/coverage-check.js.map +1 -1
- package/dist/trace/check/flow-check.d.ts +2 -0
- package/dist/trace/check/flow-check.d.ts.map +1 -1
- package/dist/trace/check/flow-check.js +3 -1
- package/dist/trace/check/flow-check.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/check-steps.ts +98 -0
- package/src/cli/commands/check.ts +283 -147
- package/src/cli/commands/lint.ts +34 -1
- package/src/cli/index.ts +56 -2
- package/src/lint/config.ts +6 -0
- package/src/lint/doctrine.ts +17 -8
- package/src/lint/rules/doctrine.ts +31 -0
- package/src/trace/cardinality/check.ts +9 -2
- package/src/trace/check/coverage-check.ts +5 -1
- package/src/trace/check/flow-check.ts +5 -1
package/src/cli/commands/lint.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { spawnSync } from 'node:child_process'
|
|
|
2
2
|
import { dirname, relative } from 'node:path'
|
|
3
3
|
import { findConfig } from '../../core/config/discover.js'
|
|
4
4
|
import { error } from '../output.js'
|
|
5
|
-
import { builtinConfigArgs, lintTargets, loadLintIncludes, resolveEslintBin } from './check.js'
|
|
5
|
+
import { builtinConfigArgs, lintPopulation, lintTargets, loadLintIncludes, resolveEslintBin, resolveModulePaths } from './check.js'
|
|
6
|
+
import { parseShard } from './shard.js'
|
|
6
7
|
|
|
7
8
|
// eslint options that take their value as the next argument. Anything else starting
|
|
8
9
|
// with `-` is a switch, so the argument after it is a file.
|
|
@@ -36,6 +37,7 @@ export function namesFiles(args: readonly string[]): boolean {
|
|
|
36
37
|
* those. Every argument is forwarded verbatim. Returns eslint's exit code.
|
|
37
38
|
*/
|
|
38
39
|
export async function lintCommand(cwd: string, args: readonly string[]): Promise<number> {
|
|
40
|
+
if (args.includes('--list-files')) return listFiles(cwd, args)
|
|
39
41
|
const eslintBin = resolveEslintBin(cwd)
|
|
40
42
|
const configPath = findConfig(cwd)
|
|
41
43
|
const root = configPath === null ? cwd : dirname(configPath)
|
|
@@ -60,3 +62,34 @@ export async function lintCommand(cwd: string, args: readonly string[]): Promise
|
|
|
60
62
|
}
|
|
61
63
|
return result.status ?? 1
|
|
62
64
|
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `pipework lint --list-files [--shard i/n]`: the repo-relative files `check`'s lint
|
|
68
|
+
* pass covers, one per line, read from pipework.config.ts. Nothing is linted.
|
|
69
|
+
*/
|
|
70
|
+
async function listFiles(cwd: string, args: readonly string[]): Promise<number> {
|
|
71
|
+
const rest = args.filter(a => a !== '--list-files')
|
|
72
|
+
let shard
|
|
73
|
+
if (rest.length === 2 && rest[0] === '--shard') {
|
|
74
|
+
try {
|
|
75
|
+
shard = parseShard(rest[1]!)
|
|
76
|
+
} catch (err) {
|
|
77
|
+
error(err instanceof Error ? err.message : String(err))
|
|
78
|
+
return 1
|
|
79
|
+
}
|
|
80
|
+
} else if (rest.length > 0) {
|
|
81
|
+
error(`--list-files takes only --shard <i>/<n>; got ${rest.join(' ')}. It lists files and does not run eslint.`)
|
|
82
|
+
return 1
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const configPath = findConfig(cwd)
|
|
86
|
+
const root = configPath === null ? cwd : dirname(configPath)
|
|
87
|
+
const scope = await resolveModulePaths(root)
|
|
88
|
+
if (scope.configError !== undefined) {
|
|
89
|
+
error(`Cannot list lint files: pipework.config.ts failed to load: ${scope.configError.message}`)
|
|
90
|
+
return 1
|
|
91
|
+
}
|
|
92
|
+
const population = lintPopulation(root, scope.paths, await loadLintIncludes(root), shard)
|
|
93
|
+
if (population.files.length > 0) process.stdout.write(population.files.join('\n') + '\n')
|
|
94
|
+
return 0
|
|
95
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -18,8 +18,13 @@ ${bold('Commands:')}
|
|
|
18
18
|
openapi Write an http surface's OpenAPI document (no database needed; --surface <name>, --out <file>)
|
|
19
19
|
run <script> Execute a script as a traced, audited flow (with --tenant: one transaction, rolled back if it throws)
|
|
20
20
|
test Run tests with automatic database setup
|
|
21
|
-
check Type-check, lint, and boundary enforcement
|
|
21
|
+
check Type-check, lint, and boundary enforcement (--format json, --only/--skip steps)
|
|
22
|
+
doctrine [files] Doctrine rules alone; JSON per violation and per scanned file with --format json
|
|
23
|
+
flow [files] Flow annotation rules alone (same options)
|
|
24
|
+
cardinality [files] @downstream cardinality rules alone (same options)
|
|
25
|
+
startup Startup validation alone: pipework.config.ts loaded, no database
|
|
22
26
|
lint [eslint args] Lint the current module (the workspace at its root) with check's config; every argument goes to eslint
|
|
27
|
+
lint --list-files [--shard i/n]: print the files check's lint covers, lint nothing
|
|
23
28
|
codemod Fill missing @downstream cardinality across the corpus
|
|
24
29
|
db Database lifecycle: setup, teardown, reset
|
|
25
30
|
alerts unit-fault Record an abnormal systemd stop (ExecStopPost=pipework alerts unit-fault --unit %n)
|
|
@@ -49,6 +54,15 @@ ${bold('Scoping (check, test):')}
|
|
|
49
54
|
--reap Drop orphan test databases and exit (test only)
|
|
50
55
|
--shard <i>/<n> Run part i of n disjoint parts of the selected run (test, check); the n parts together equal the unsharded run
|
|
51
56
|
|
|
57
|
+
${bold('Steps (check, doctrine, flow, cardinality, startup):')}
|
|
58
|
+
--format json Structured result: {step, status, pipeworkVersion, reads, files, violations}; check emits an array, one record per step
|
|
59
|
+
--output-file <path> Write the JSON there instead of stdout (human lines stay on stderr)
|
|
60
|
+
--only <a,b> check: run only these steps
|
|
61
|
+
--skip <a,b> check: run all but these steps (not with --only)
|
|
62
|
+
Steps: checksums, vitest-config, eslint-config, config-load, doctrine, flow, cardinality,
|
|
63
|
+
coverage, lint, typecheck, startup, boundaries, dependencies, install
|
|
64
|
+
doctrine, flow and cardinality take file paths: only those files are judged
|
|
65
|
+
|
|
52
66
|
${bold('Examples:')}
|
|
53
67
|
pipework init
|
|
54
68
|
pipework upgrade
|
|
@@ -74,14 +88,27 @@ ${bold('Examples:')}
|
|
|
74
88
|
pipework test --reap # drop orphan test databases
|
|
75
89
|
pipework check --staged
|
|
76
90
|
pipework check --all
|
|
91
|
+
pipework check --format json --skip lint,typecheck --output-file r.json
|
|
92
|
+
pipework doctrine --format json --output-file d.json src/a.ts src/b.ts
|
|
77
93
|
pipework lint # the module you are in, exactly as check lints it
|
|
78
94
|
pipework lint --format json --output-file r.json src/a.ts # only src/a.ts
|
|
95
|
+
pipework lint --list-files --shard 1/4 # the files check's lint pass covers for part 1 of 4, from pipework.config.ts
|
|
79
96
|
pipework codemod
|
|
80
97
|
pipework codemod --dry-run
|
|
81
98
|
pipework alerts unit-fault --unit subseam-core.service # reads $SERVICE_RESULT, $EXIT_CODE, $EXIT_STATUS
|
|
82
99
|
pipework alerts stale --max-age jobs.claim=5m # exit 1 with a line per stale loop; 0 and silent when none
|
|
83
100
|
`
|
|
84
101
|
|
|
102
|
+
function parseFormat(format: string | undefined, outputFile: string | undefined): 'human' | 'json' {
|
|
103
|
+
if (format !== undefined && format !== 'human' && format !== 'json') {
|
|
104
|
+
throw new Error(`--format takes "json" or "human"; got "${format}".`)
|
|
105
|
+
}
|
|
106
|
+
if (outputFile !== undefined && format !== 'json') {
|
|
107
|
+
throw new Error('--output-file needs --format json.')
|
|
108
|
+
}
|
|
109
|
+
return format === 'json' ? 'json' : 'human'
|
|
110
|
+
}
|
|
111
|
+
|
|
85
112
|
export async function run(argv: string[]): Promise<void> {
|
|
86
113
|
// `lint` hands everything after it to eslint, flags included, so it is dispatched
|
|
87
114
|
// before parseArgs, which would refuse eslint's options.
|
|
@@ -129,6 +156,10 @@ export async function run(argv: string[]): Promise<void> {
|
|
|
129
156
|
test: { type: 'boolean' },
|
|
130
157
|
'admin-url': { type: 'string' },
|
|
131
158
|
'dry-run': { type: 'boolean' },
|
|
159
|
+
format: { type: 'string' },
|
|
160
|
+
'output-file': { type: 'string' },
|
|
161
|
+
only: { type: 'string' },
|
|
162
|
+
skip: { type: 'string' },
|
|
132
163
|
},
|
|
133
164
|
})
|
|
134
165
|
|
|
@@ -256,7 +287,30 @@ export async function run(argv: string[]): Promise<void> {
|
|
|
256
287
|
const { parseShard: parseShardCheck } = await import('./commands/shard.js')
|
|
257
288
|
const shardCheck = values.shard === undefined ? undefined : parseShardCheck(values.shard)
|
|
258
289
|
const { check } = await import('./commands/check.js')
|
|
259
|
-
await check
|
|
290
|
+
const { parseStepSelection } = await import('./commands/check-steps.js')
|
|
291
|
+
await check(cwd, parsedCheck.scope, shardCheck, {
|
|
292
|
+
format: parseFormat(values.format, values['output-file']),
|
|
293
|
+
outputFile: values['output-file'],
|
|
294
|
+
select: parseStepSelection(values.only, values.skip),
|
|
295
|
+
})
|
|
296
|
+
break
|
|
297
|
+
}
|
|
298
|
+
case 'doctrine':
|
|
299
|
+
case 'flow':
|
|
300
|
+
case 'cardinality':
|
|
301
|
+
case 'startup': {
|
|
302
|
+
if (values.only !== undefined || values.skip !== undefined) {
|
|
303
|
+
throw new Error(`--only and --skip select steps of check; ${command} is one step.`)
|
|
304
|
+
}
|
|
305
|
+
const { parseScope: parseScopeStep } = await import('./commands/scope.js')
|
|
306
|
+
const parsedStep = parseScopeStep({ all: values.all, module: values.module, staged: values.staged, fast: values.fast, full: values.full })
|
|
307
|
+
const { stepCommand } = await import('./commands/check.js')
|
|
308
|
+
process.exitCode = await stepCommand(cwd, command, {
|
|
309
|
+
format: parseFormat(values.format, values['output-file']),
|
|
310
|
+
outputFile: values['output-file'],
|
|
311
|
+
scope: parsedStep.scope,
|
|
312
|
+
files: positionals.slice(1),
|
|
313
|
+
})
|
|
260
314
|
break
|
|
261
315
|
}
|
|
262
316
|
case 'codemod': {
|
package/src/lint/config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import tseslint from '@typescript-eslint/eslint-plugin'
|
|
2
2
|
import tsparser from '@typescript-eslint/parser'
|
|
3
3
|
import { noReexports } from './rules/no-reexports.js'
|
|
4
|
+
import { doctrineRules } from './rules/doctrine.js'
|
|
4
5
|
|
|
5
6
|
export const rules = {
|
|
6
7
|
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
@@ -11,6 +12,10 @@ export const rules = {
|
|
|
11
12
|
'@typescript-eslint/no-unnecessary-condition': 'error',
|
|
12
13
|
'@typescript-eslint/strict-boolean-expressions': 'error',
|
|
13
14
|
'pipework/no-reexports': 'error',
|
|
15
|
+
'define/prefer-pipe-define': 'error',
|
|
16
|
+
'define/no-raw-pgTable': 'error',
|
|
17
|
+
'define/brand-primary-key': 'error',
|
|
18
|
+
'define/use-traits': 'error',
|
|
14
19
|
} as const
|
|
15
20
|
|
|
16
21
|
export interface LintOptions {
|
|
@@ -33,6 +38,7 @@ export function createLintConfig(config?: LintOptions): unknown[] {
|
|
|
33
38
|
const appliedPlugins: Record<string, unknown> = {
|
|
34
39
|
'@typescript-eslint': tseslint,
|
|
35
40
|
'pipework': { rules: { 'no-reexports': noReexports } },
|
|
41
|
+
'define': { rules: doctrineRules },
|
|
36
42
|
...config?.extraPlugins,
|
|
37
43
|
}
|
|
38
44
|
|
package/src/lint/doctrine.ts
CHANGED
|
@@ -11,27 +11,36 @@ export interface DoctrineViolation {
|
|
|
11
11
|
export interface DoctrineResult {
|
|
12
12
|
readonly violations: readonly DoctrineViolation[]
|
|
13
13
|
readonly scanned: number
|
|
14
|
+
/** Every file read, in input order; a clean one has no violation. */
|
|
15
|
+
readonly scannedFiles: readonly string[]
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export function validateDoctrine(cwd: string, sourceFiles: readonly string[]): DoctrineResult {
|
|
17
19
|
const violations: DoctrineViolation[] = []
|
|
18
20
|
let scanned = 0
|
|
21
|
+
const scannedFiles: string[] = []
|
|
19
22
|
|
|
20
23
|
for (const file of sourceFiles) {
|
|
21
24
|
const abs = join(cwd, file)
|
|
22
25
|
if (!existsSync(abs)) continue
|
|
23
26
|
|
|
24
|
-
const content = readFileSync(abs, 'utf-8')
|
|
25
|
-
const lines = content.split('\n')
|
|
26
27
|
scanned++
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
checkRawPgTableImport(file, lines, violations)
|
|
30
|
-
checkUnbrandedPrimaryKeys(file, lines, violations)
|
|
31
|
-
checkHandWrittenTraitFields(file, lines, violations)
|
|
28
|
+
scannedFiles.push(file)
|
|
29
|
+
violations.push(...doctrineViolations(file, readFileSync(abs, 'utf-8')))
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
return { violations, scanned }
|
|
32
|
+
return { violations, scanned, scannedFiles }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The four doctrine scans over one file's text; shared by `check` and the eslint rules. */
|
|
36
|
+
export function doctrineViolations(file: string, content: string): DoctrineViolation[] {
|
|
37
|
+
const lines = content.split('\n')
|
|
38
|
+
const violations: DoctrineViolation[] = []
|
|
39
|
+
checkSchemaTableUsage(file, lines, violations)
|
|
40
|
+
checkRawPgTableImport(file, lines, violations)
|
|
41
|
+
checkUnbrandedPrimaryKeys(file, lines, violations)
|
|
42
|
+
checkHandWrittenTraitFields(file, lines, violations)
|
|
43
|
+
return violations
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
const SCHEMA_TABLE_PATTERN = /\bschema\.table\s*\(/
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { basename } from 'node:path'
|
|
2
|
+
import type { Rule } from 'eslint'
|
|
3
|
+
import { doctrineViolations, isSourceFileName } from '../doctrine.js'
|
|
4
|
+
|
|
5
|
+
const RULES = ['prefer-pipe-define', 'no-raw-pgTable', 'brand-primary-key', 'use-traits'] as const
|
|
6
|
+
|
|
7
|
+
function doctrineRule(name: string): Rule.RuleModule {
|
|
8
|
+
const id = `define/${name}`
|
|
9
|
+
return {
|
|
10
|
+
meta: {
|
|
11
|
+
type: 'problem',
|
|
12
|
+
docs: { description: `Doctrine rule ${id}; same scan as the doctrine step of pipework check.` },
|
|
13
|
+
schema: [],
|
|
14
|
+
},
|
|
15
|
+
create(context) {
|
|
16
|
+
return {
|
|
17
|
+
'Program:exit'() {
|
|
18
|
+
if (!isSourceFileName(basename(context.filename))) return
|
|
19
|
+
for (const v of doctrineViolations(context.filename, context.sourceCode.text)) {
|
|
20
|
+
if (v.rule !== id) continue
|
|
21
|
+
context.report({ loc: { line: v.line, column: 0 }, message: v.message })
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const doctrineRules: Record<string, Rule.RuleModule> = Object.fromEntries(
|
|
30
|
+
RULES.map(name => [name, doctrineRule(name)]),
|
|
31
|
+
)
|
|
@@ -8,9 +8,15 @@ import { join } from 'node:path'
|
|
|
8
8
|
import { collectFlowStepSites } from '../check/flow-step-site.js'
|
|
9
9
|
import { analyzeCardinality, type AnalyzerEntry, type CardinalityResult } from './analyze.js'
|
|
10
10
|
|
|
11
|
+
export interface CardinalityCheckResult extends CardinalityResult {
|
|
12
|
+
/** Every file parsed, in input order; a clean one has no violation. */
|
|
13
|
+
readonly scannedFiles: readonly string[]
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
/** Analyzes `@downstream` cardinality across `sourceFiles` (paths relative to `cwd`). */
|
|
12
|
-
export function checkCardinality(cwd: string, sourceFiles: readonly string[]):
|
|
17
|
+
export function checkCardinality(cwd: string, sourceFiles: readonly string[]): CardinalityCheckResult {
|
|
13
18
|
const entries: AnalyzerEntry[] = []
|
|
19
|
+
const scannedFiles: string[] = []
|
|
14
20
|
|
|
15
21
|
for (const file of sourceFiles) {
|
|
16
22
|
const abs = join(cwd, file)
|
|
@@ -23,11 +29,12 @@ export function checkCardinality(cwd: string, sourceFiles: readonly string[]): C
|
|
|
23
29
|
// the type checker's diagnostic, not this check's.
|
|
24
30
|
continue
|
|
25
31
|
}
|
|
32
|
+
scannedFiles.push(file)
|
|
26
33
|
|
|
27
34
|
for (const site of sites) {
|
|
28
35
|
entries.push({ file, site })
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
return analyzeCardinality(entries)
|
|
39
|
+
return { ...analyzeCardinality(entries), scannedFiles }
|
|
33
40
|
}
|
|
@@ -37,6 +37,8 @@ export interface CoverageViolation {
|
|
|
37
37
|
export interface CoverageCheckResult {
|
|
38
38
|
readonly violations: readonly CoverageViolation[]
|
|
39
39
|
readonly scanned: number
|
|
40
|
+
/** Every file parsed, in input order; a clean one has no violation. */
|
|
41
|
+
readonly scannedFiles: readonly string[]
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
interface IoSite {
|
|
@@ -61,6 +63,7 @@ export function checkCoverage(
|
|
|
61
63
|
): CoverageCheckResult {
|
|
62
64
|
const violations: CoverageViolation[] = []
|
|
63
65
|
let scanned = 0
|
|
66
|
+
const scannedFiles: string[] = []
|
|
64
67
|
|
|
65
68
|
for (const file of sourceFiles) {
|
|
66
69
|
const abs = join(cwd, file)
|
|
@@ -78,6 +81,7 @@ export function checkCoverage(
|
|
|
78
81
|
continue
|
|
79
82
|
}
|
|
80
83
|
scanned++
|
|
84
|
+
scannedFiles.push(file)
|
|
81
85
|
|
|
82
86
|
const ioSites = collectIoSites(program, extras)
|
|
83
87
|
const flowStepRanges = collectFlowStepRanges(sites)
|
|
@@ -124,7 +128,7 @@ export function checkCoverage(
|
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
|
|
127
|
-
return { violations, scanned }
|
|
131
|
+
return { violations, scanned, scannedFiles }
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
interface FlowStepRange {
|
|
@@ -23,12 +23,15 @@ export interface FlowViolation {
|
|
|
23
23
|
export interface FlowCheckResult {
|
|
24
24
|
readonly violations: readonly FlowViolation[]
|
|
25
25
|
readonly scanned: number
|
|
26
|
+
/** Every file parsed, in input order; a clean one has no violation. */
|
|
27
|
+
readonly scannedFiles: readonly string[]
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
/** Validates every `@flow_step` annotation in `sourceFiles` (paths relative to `cwd`). */
|
|
29
31
|
export function checkFlowAnnotations(cwd: string, sourceFiles: readonly string[]): FlowCheckResult {
|
|
30
32
|
const violations: FlowViolation[] = []
|
|
31
33
|
let scanned = 0
|
|
34
|
+
const scannedFiles: string[] = []
|
|
32
35
|
|
|
33
36
|
for (const file of sourceFiles) {
|
|
34
37
|
const abs = join(cwd, file)
|
|
@@ -42,13 +45,14 @@ export function checkFlowAnnotations(cwd: string, sourceFiles: readonly string[]
|
|
|
42
45
|
continue
|
|
43
46
|
}
|
|
44
47
|
scanned++
|
|
48
|
+
scannedFiles.push(file)
|
|
45
49
|
|
|
46
50
|
for (const site of sites) {
|
|
47
51
|
collectSiteViolations(file, site, violations)
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
return { violations, scanned }
|
|
55
|
+
return { violations, scanned, scannedFiles }
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
function collectSiteViolations(file: string, site: FlowStepSite, out: FlowViolation[]): void {
|