@aicqtools/guardrail 1.0.0-alpha.10
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/LICENSE +21 -0
- package/dist/docs/build.d.ts +12 -0
- package/dist/docs/build.d.ts.map +1 -0
- package/dist/docs/build.js +23 -0
- package/dist/docs/build.js.map +1 -0
- package/dist/docs/index.d.ts +4 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +3 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/docs/render-rule-md.d.ts +4 -0
- package/dist/docs/render-rule-md.d.ts.map +1 -0
- package/dist/docs/render-rule-md.js +117 -0
- package/dist/docs/render-rule-md.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/matcher/index.d.ts +4 -0
- package/dist/matcher/index.d.ts.map +1 -0
- package/dist/matcher/index.js +3 -0
- package/dist/matcher/index.js.map +1 -0
- package/dist/matcher/traverse.d.ts +3 -0
- package/dist/matcher/traverse.d.ts.map +1 -0
- package/dist/matcher/traverse.js +9 -0
- package/dist/matcher/traverse.js.map +1 -0
- package/dist/matcher/yaml-rule.d.ts +34 -0
- package/dist/matcher/yaml-rule.d.ts.map +1 -0
- package/dist/matcher/yaml-rule.js +32 -0
- package/dist/matcher/yaml-rule.js.map +1 -0
- package/dist/mcp/handlers.d.ts +36 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +32 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +4 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +53 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +3 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +8 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/rules-default/ai-explainability-metadata.d.ts +3 -0
- package/dist/rules-default/ai-explainability-metadata.d.ts.map +1 -0
- package/dist/rules-default/ai-explainability-metadata.js +41 -0
- package/dist/rules-default/ai-explainability-metadata.js.map +1 -0
- package/dist/rules-default/api-response-shape.d.ts +3 -0
- package/dist/rules-default/api-response-shape.d.ts.map +1 -0
- package/dist/rules-default/api-response-shape.js +52 -0
- package/dist/rules-default/api-response-shape.js.map +1 -0
- package/dist/rules-default/async-await-consistency.d.ts +3 -0
- package/dist/rules-default/async-await-consistency.d.ts.map +1 -0
- package/dist/rules-default/async-await-consistency.js +38 -0
- package/dist/rules-default/async-await-consistency.js.map +1 -0
- package/dist/rules-default/audit-log-ai-decision.d.ts +3 -0
- package/dist/rules-default/audit-log-ai-decision.d.ts.map +1 -0
- package/dist/rules-default/audit-log-ai-decision.js +33 -0
- package/dist/rules-default/audit-log-ai-decision.js.map +1 -0
- package/dist/rules-default/camelcase-migration-column.d.ts +3 -0
- package/dist/rules-default/camelcase-migration-column.d.ts.map +1 -0
- package/dist/rules-default/camelcase-migration-column.js +56 -0
- package/dist/rules-default/camelcase-migration-column.js.map +1 -0
- package/dist/rules-default/controller-needs-async-wrapper.d.ts +3 -0
- package/dist/rules-default/controller-needs-async-wrapper.d.ts.map +1 -0
- package/dist/rules-default/controller-needs-async-wrapper.js +56 -0
- package/dist/rules-default/controller-needs-async-wrapper.js.map +1 -0
- package/dist/rules-default/enforce-utf8-encoding.d.ts +10 -0
- package/dist/rules-default/enforce-utf8-encoding.d.ts.map +1 -0
- package/dist/rules-default/enforce-utf8-encoding.js +28 -0
- package/dist/rules-default/enforce-utf8-encoding.js.map +1 -0
- package/dist/rules-default/explicit-kst-timezone.d.ts +3 -0
- package/dist/rules-default/explicit-kst-timezone.d.ts.map +1 -0
- package/dist/rules-default/explicit-kst-timezone.js +49 -0
- package/dist/rules-default/explicit-kst-timezone.js.map +1 -0
- package/dist/rules-default/fk-needs-on-delete.d.ts +3 -0
- package/dist/rules-default/fk-needs-on-delete.d.ts.map +1 -0
- package/dist/rules-default/fk-needs-on-delete.js +54 -0
- package/dist/rules-default/fk-needs-on-delete.js.map +1 -0
- package/dist/rules-default/human-oversight-checkpoint.d.ts +3 -0
- package/dist/rules-default/human-oversight-checkpoint.d.ts.map +1 -0
- package/dist/rules-default/human-oversight-checkpoint.js +37 -0
- package/dist/rules-default/human-oversight-checkpoint.js.map +1 -0
- package/dist/rules-default/index.d.ts +6 -0
- package/dist/rules-default/index.d.ts.map +1 -0
- package/dist/rules-default/index.js +138 -0
- package/dist/rules-default/index.js.map +1 -0
- package/dist/rules-default/korean-comment-encoding.d.ts +3 -0
- package/dist/rules-default/korean-comment-encoding.d.ts.map +1 -0
- package/dist/rules-default/korean-comment-encoding.js +28 -0
- package/dist/rules-default/korean-comment-encoding.js.map +1 -0
- package/dist/rules-default/mask-card-number.d.ts +3 -0
- package/dist/rules-default/mask-card-number.d.ts.map +1 -0
- package/dist/rules-default/mask-card-number.js +45 -0
- package/dist/rules-default/mask-card-number.js.map +1 -0
- package/dist/rules-default/mask-pii-in-ai-prompt.d.ts +3 -0
- package/dist/rules-default/mask-pii-in-ai-prompt.d.ts.map +1 -0
- package/dist/rules-default/mask-pii-in-ai-prompt.js +41 -0
- package/dist/rules-default/mask-pii-in-ai-prompt.js.map +1 -0
- package/dist/rules-default/naver-kakao-oauth-webview.d.ts +3 -0
- package/dist/rules-default/naver-kakao-oauth-webview.d.ts.map +1 -0
- package/dist/rules-default/naver-kakao-oauth-webview.js +40 -0
- package/dist/rules-default/naver-kakao-oauth-webview.js.map +1 -0
- package/dist/rules-default/no-bare-except.d.ts +7 -0
- package/dist/rules-default/no-bare-except.d.ts.map +1 -0
- package/dist/rules-default/no-bare-except.js +23 -0
- package/dist/rules-default/no-bare-except.js.map +1 -0
- package/dist/rules-default/no-bare-throw.d.ts +7 -0
- package/dist/rules-default/no-bare-throw.d.ts.map +1 -0
- package/dist/rules-default/no-bare-throw.js +32 -0
- package/dist/rules-default/no-bare-throw.js.map +1 -0
- package/dist/rules-default/no-boolean-trap.d.ts +8 -0
- package/dist/rules-default/no-boolean-trap.d.ts.map +1 -0
- package/dist/rules-default/no-boolean-trap.js +33 -0
- package/dist/rules-default/no-boolean-trap.js.map +1 -0
- package/dist/rules-default/no-console-log.d.ts +3 -0
- package/dist/rules-default/no-console-log.d.ts.map +1 -0
- package/dist/rules-default/no-console-log.js +27 -0
- package/dist/rules-default/no-console-log.js.map +1 -0
- package/dist/rules-default/no-cvv-logging.d.ts +3 -0
- package/dist/rules-default/no-cvv-logging.d.ts.map +1 -0
- package/dist/rules-default/no-cvv-logging.js +36 -0
- package/dist/rules-default/no-cvv-logging.js.map +1 -0
- package/dist/rules-default/no-default-export-from-libs.d.ts +7 -0
- package/dist/rules-default/no-default-export-from-libs.d.ts.map +1 -0
- package/dist/rules-default/no-default-export-from-libs.js +24 -0
- package/dist/rules-default/no-default-export-from-libs.js.map +1 -0
- package/dist/rules-default/no-direct-anthropic.yaml +15 -0
- package/dist/rules-default/no-direct-openai.yaml +17 -0
- package/dist/rules-default/no-empty-catch.d.ts +3 -0
- package/dist/rules-default/no-empty-catch.d.ts.map +1 -0
- package/dist/rules-default/no-empty-catch.js +37 -0
- package/dist/rules-default/no-empty-catch.js.map +1 -0
- package/dist/rules-default/no-fstring-sql.d.ts +3 -0
- package/dist/rules-default/no-fstring-sql.d.ts.map +1 -0
- package/dist/rules-default/no-fstring-sql.js +24 -0
- package/dist/rules-default/no-fstring-sql.js.map +1 -0
- package/dist/rules-default/no-id-overwrite.d.ts +8 -0
- package/dist/rules-default/no-id-overwrite.d.ts.map +1 -0
- package/dist/rules-default/no-id-overwrite.js +27 -0
- package/dist/rules-default/no-id-overwrite.js.map +1 -0
- package/dist/rules-default/no-inline-date.yaml +9 -0
- package/dist/rules-default/no-inline-math-round.yaml +12 -0
- package/dist/rules-default/no-jsonb-circular.d.ts +3 -0
- package/dist/rules-default/no-jsonb-circular.d.ts.map +1 -0
- package/dist/rules-default/no-jsonb-circular.js +33 -0
- package/dist/rules-default/no-jsonb-circular.js.map +1 -0
- package/dist/rules-default/no-magic-number.d.ts +3 -0
- package/dist/rules-default/no-magic-number.d.ts.map +1 -0
- package/dist/rules-default/no-magic-number.js +145 -0
- package/dist/rules-default/no-magic-number.js.map +1 -0
- package/dist/rules-default/no-mutable-default-arg.d.ts +3 -0
- package/dist/rules-default/no-mutable-default-arg.d.ts.map +1 -0
- package/dist/rules-default/no-mutable-default-arg.js +30 -0
- package/dist/rules-default/no-mutable-default-arg.js.map +1 -0
- package/dist/rules-default/no-pickle.yaml +12 -0
- package/dist/rules-default/no-plain-card-number.d.ts +3 -0
- package/dist/rules-default/no-plain-card-number.d.ts.map +1 -0
- package/dist/rules-default/no-plain-card-number.js +51 -0
- package/dist/rules-default/no-plain-card-number.js.map +1 -0
- package/dist/rules-default/no-print-in-prod.yaml +9 -0
- package/dist/rules-default/no-process-env-leak.d.ts +7 -0
- package/dist/rules-default/no-process-env-leak.d.ts.map +1 -0
- package/dist/rules-default/no-process-env-leak.js +37 -0
- package/dist/rules-default/no-process-env-leak.js.map +1 -0
- package/dist/rules-default/no-shell-true.d.ts +3 -0
- package/dist/rules-default/no-shell-true.d.ts.map +1 -0
- package/dist/rules-default/no-shell-true.js +42 -0
- package/dist/rules-default/no-shell-true.js.map +1 -0
- package/dist/rules-default/prefer-const-array.d.ts +9 -0
- package/dist/rules-default/prefer-const-array.d.ts.map +1 -0
- package/dist/rules-default/prefer-const-array.js +34 -0
- package/dist/rules-default/prefer-const-array.js.map +1 -0
- package/dist/rules-default/prefer-named-imports.d.ts +8 -0
- package/dist/rules-default/prefer-named-imports.d.ts.map +1 -0
- package/dist/rules-default/prefer-named-imports.js +25 -0
- package/dist/rules-default/prefer-named-imports.js.map +1 -0
- package/dist/rules-default/preserve-transaction-log.d.ts +3 -0
- package/dist/rules-default/preserve-transaction-log.d.ts.map +1 -0
- package/dist/rules-default/preserve-transaction-log.js +33 -0
- package/dist/rules-default/preserve-transaction-log.js.map +1 -0
- package/dist/rules-default/pytest-fixture-naming.d.ts +3 -0
- package/dist/rules-default/pytest-fixture-naming.d.ts.map +1 -0
- package/dist/rules-default/pytest-fixture-naming.js +36 -0
- package/dist/rules-default/pytest-fixture-naming.js.map +1 -0
- package/dist/rules-default/requests-needs-timeout.d.ts +3 -0
- package/dist/rules-default/requests-needs-timeout.d.ts.map +1 -0
- package/dist/rules-default/requests-needs-timeout.js +43 -0
- package/dist/rules-default/requests-needs-timeout.js.map +1 -0
- package/dist/rules-default/require-idempotency-key.d.ts +3 -0
- package/dist/rules-default/require-idempotency-key.d.ts.map +1 -0
- package/dist/rules-default/require-idempotency-key.js +47 -0
- package/dist/rules-default/require-idempotency-key.js.map +1 -0
- package/dist/rules-default/require-tls-1-2-plus.d.ts +3 -0
- package/dist/rules-default/require-tls-1-2-plus.d.ts.map +1 -0
- package/dist/rules-default/require-tls-1-2-plus.js +30 -0
- package/dist/rules-default/require-tls-1-2-plus.js.map +1 -0
- package/dist/rules-default/rfc5987-korean-filename.d.ts +3 -0
- package/dist/rules-default/rfc5987-korean-filename.d.ts.map +1 -0
- package/dist/rules-default/rfc5987-korean-filename.js +32 -0
- package/dist/rules-default/rfc5987-korean-filename.js.map +1 -0
- package/dist/rules-default/route-needs-auth.d.ts +3 -0
- package/dist/rules-default/route-needs-auth.d.ts.map +1 -0
- package/dist/rules-default/route-needs-auth.js +48 -0
- package/dist/rules-default/route-needs-auth.js.map +1 -0
- package/dist/rules-default/route-needs-rate-limit.d.ts +3 -0
- package/dist/rules-default/route-needs-rate-limit.d.ts.map +1 -0
- package/dist/rules-default/route-needs-rate-limit.js +47 -0
- package/dist/rules-default/route-needs-rate-limit.js.map +1 -0
- package/dist/rules-default/separate-refund-permission.d.ts +3 -0
- package/dist/rules-default/separate-refund-permission.d.ts.map +1 -0
- package/dist/rules-default/separate-refund-permission.js +33 -0
- package/dist/rules-default/separate-refund-permission.js.map +1 -0
- package/dist/rules-default/track-ai-model-version.d.ts +3 -0
- package/dist/rules-default/track-ai-model-version.d.ts.map +1 -0
- package/dist/rules-default/track-ai-model-version.js +37 -0
- package/dist/rules-default/track-ai-model-version.js.map +1 -0
- package/dist/rules-default/type-hint-required-public.d.ts +10 -0
- package/dist/rules-default/type-hint-required-public.d.ts.map +1 -0
- package/dist/rules-default/type-hint-required-public.js +29 -0
- package/dist/rules-default/type-hint-required-public.js.map +1 -0
- package/dist/rules-default/verify-pg-response.d.ts +3 -0
- package/dist/rules-default/verify-pg-response.d.ts.map +1 -0
- package/dist/rules-default/verify-pg-response.js +37 -0
- package/dist/rules-default/verify-pg-response.js.map +1 -0
- package/dist/rules-default/won-format-thousands.d.ts +3 -0
- package/dist/rules-default/won-format-thousands.d.ts.map +1 -0
- package/dist/rules-default/won-format-thousands.js +24 -0
- package/dist/rules-default/won-format-thousands.js.map +1 -0
- package/dist/runner/apply-rule-config.d.ts +69 -0
- package/dist/runner/apply-rule-config.d.ts.map +1 -0
- package/dist/runner/apply-rule-config.js +164 -0
- package/dist/runner/apply-rule-config.js.map +1 -0
- package/dist/runner/context.d.ts +12 -0
- package/dist/runner/context.d.ts.map +1 -0
- package/dist/runner/context.js +34 -0
- package/dist/runner/context.js.map +1 -0
- package/dist/runner/index.d.ts +9 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +6 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/ruleset-signature.d.ts +4 -0
- package/dist/runner/ruleset-signature.d.ts.map +1 -0
- package/dist/runner/ruleset-signature.js +11 -0
- package/dist/runner/ruleset-signature.js.map +1 -0
- package/dist/runner/run-file.d.ts +10 -0
- package/dist/runner/run-file.d.ts.map +1 -0
- package/dist/runner/run-file.js +48 -0
- package/dist/runner/run-file.js.map +1 -0
- package/dist/runner/run-project.d.ts +30 -0
- package/dist/runner/run-project.d.ts.map +1 -0
- package/dist/runner/run-project.js +118 -0
- package/dist/runner/run-project.js.map +1 -0
- package/dist/runner/run-rule.d.ts +5 -0
- package/dist/runner/run-rule.d.ts.map +1 -0
- package/dist/runner/run-rule.js +53 -0
- package/dist/runner/run-rule.js.map +1 -0
- package/dist/runner/suppressions.d.ts +37 -0
- package/dist/runner/suppressions.d.ts.map +1 -0
- package/dist/runner/suppressions.js +127 -0
- package/dist/runner/suppressions.js.map +1 -0
- package/dist/suggest/analyze.d.ts +10 -0
- package/dist/suggest/analyze.d.ts.map +1 -0
- package/dist/suggest/analyze.js +193 -0
- package/dist/suggest/analyze.js.map +1 -0
- package/dist/suggest/format.d.ts +13 -0
- package/dist/suggest/format.d.ts.map +1 -0
- package/dist/suggest/format.js +120 -0
- package/dist/suggest/format.js.map +1 -0
- package/dist/suggest/index.d.ts +5 -0
- package/dist/suggest/index.d.ts.map +1 -0
- package/dist/suggest/index.js +4 -0
- package/dist/suggest/index.js.map +1 -0
- package/dist/suggest/mine.d.ts +11 -0
- package/dist/suggest/mine.d.ts.map +1 -0
- package/dist/suggest/mine.js +207 -0
- package/dist/suggest/mine.js.map +1 -0
- package/dist/suggest/types.d.ts +74 -0
- package/dist/suggest/types.d.ts.map +1 -0
- package/dist/suggest/types.js +2 -0
- package/dist/suggest/types.js.map +1 -0
- package/dist/sync/index.d.ts +5 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +3 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/render.d.ts +9 -0
- package/dist/sync/render.d.ts.map +1 -0
- package/dist/sync/render.js +70 -0
- package/dist/sync/render.js.map +1 -0
- package/dist/sync/sync-files.d.ts +12 -0
- package/dist/sync/sync-files.d.ts.map +1 -0
- package/dist/sync/sync-files.js +29 -0
- package/dist/sync/sync-files.js.map +1 -0
- package/package.json +71 -0
- package/scripts/copy-yaml-rules.mjs +19 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { detectLanguage, parseSource } from '@aicqtools/core';
|
|
3
|
+
import { runRule } from './run-rule.js';
|
|
4
|
+
import { applySuppressions, parseSuppressions } from './suppressions.js';
|
|
5
|
+
export async function runFile(filePath, rules) {
|
|
6
|
+
const language = detectLanguage(filePath);
|
|
7
|
+
if (!language)
|
|
8
|
+
return { filePath, language: null, diagnostics: [] };
|
|
9
|
+
const source = await readFile(filePath, 'utf-8');
|
|
10
|
+
return runFileWithSource(filePath, source, language, rules);
|
|
11
|
+
}
|
|
12
|
+
export function runFileWithSource(filePath, source, language, rules) {
|
|
13
|
+
const tree = parseSource(language, source);
|
|
14
|
+
const diagnostics = [];
|
|
15
|
+
const run = { filePath, source, language, diagnostics };
|
|
16
|
+
for (const rule of rules) {
|
|
17
|
+
try {
|
|
18
|
+
runRule(rule, run, tree);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
diagnostics.push(ruleFailedDiagnostic(filePath, rule.id, err));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Apply inline-suppression directives last so they catch diagnostics from every rule
|
|
25
|
+
// (function rules, YAML pattern rules, and synthetic `@aicq/parse-failed`/rule-failed).
|
|
26
|
+
let suppressed = diagnostics;
|
|
27
|
+
try {
|
|
28
|
+
const suppressions = parseSuppressions(tree, source, language);
|
|
29
|
+
suppressed = applySuppressions(diagnostics, suppressions);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Suppression parsing must never abort a run. If the tree shape surprises us,
|
|
33
|
+
// fall through with the unfiltered diagnostics.
|
|
34
|
+
}
|
|
35
|
+
return { filePath, language, diagnostics: suppressed };
|
|
36
|
+
}
|
|
37
|
+
function ruleFailedDiagnostic(filePath, ruleId, err) {
|
|
38
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39
|
+
return {
|
|
40
|
+
ruleId: '@aicq/parse-failed',
|
|
41
|
+
severity: 'warning',
|
|
42
|
+
message: `parser failed in rule ${ruleId}: ${message}`,
|
|
43
|
+
messageKo: `파서 실패 (룰 ${ruleId}): ${message}`,
|
|
44
|
+
file: filePath,
|
|
45
|
+
range: { start: { line: 1, column: 1 }, end: { line: 1, column: 1 } },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=run-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-file.js","sourceRoot":"","sources":["../../src/runner/run-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAQzE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,KAAsB;IACpE,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAEpE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,MAAc,EACd,QAAkB,EAClB,KAAsB;IAEtB,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,qFAAqF;IACrF,wFAAwF;IACxF,IAAI,UAAU,GAA0B,WAAW,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/D,UAAU,GAAG,iBAAiB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;QAC9E,gDAAgD;IAClD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,MAAc,EAAE,GAAY;IAC1E,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO;QACL,MAAM,EAAE,oBAAoB;QAC5B,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,yBAAyB,MAAM,KAAK,OAAO,EAAE;QACtD,SAAS,EAAE,YAAY,MAAM,MAAM,OAAO,EAAE;QAC5C,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;KACtE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CheckResult, RuleOverride } from '@aicqtools/core';
|
|
2
|
+
import { FileCache } from '@aicqtools/core';
|
|
3
|
+
import type { Rule } from '@aicqtools/rule-sdk';
|
|
4
|
+
export interface RunProjectOptions {
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
readonly include: readonly string[];
|
|
7
|
+
readonly exclude: readonly string[];
|
|
8
|
+
readonly rules: readonly Rule[];
|
|
9
|
+
readonly cache?: FileCache;
|
|
10
|
+
/**
|
|
11
|
+
* When true, the file walker appends entries from the repo-root `.gitignore` to the effective
|
|
12
|
+
* exclude list. Unreadable / missing / malformed `.gitignore` is silently ignored (never throws).
|
|
13
|
+
* Defaults to false to keep behavior deterministic across projects.
|
|
14
|
+
*/
|
|
15
|
+
readonly respectGitignore?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Per-path rule overrides (alpha.8). When set, each file's rule set is re-resolved against
|
|
18
|
+
* matching `overrides` entries on top of the globally-resolved `rules` baseline. Empty array
|
|
19
|
+
* (or omitted) is the fast path — runner falls back to the baseline list unchanged.
|
|
20
|
+
*/
|
|
21
|
+
readonly overrides?: readonly RuleOverride[];
|
|
22
|
+
}
|
|
23
|
+
export declare function runProject(opts: RunProjectOptions): Promise<CheckResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Build the final ignore list for `fast-glob`. Always starts from the configured `exclude`;
|
|
26
|
+
* when `respectGitignore` is true, parses the root `.gitignore` (best-effort) and appends its
|
|
27
|
+
* entries. Negation (`!pattern`) and trailing-slash directory entries are honored.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveIgnores(cwd: string, exclude: readonly string[], respectGitignore: boolean): Promise<string[]>;
|
|
30
|
+
//# sourceMappingURL=run-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-project.d.ts","sourceRoot":"","sources":["../../src/runner/run-project.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAc,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAwB,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAKhD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC9C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAmE9E;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,gBAAgB,EAAE,OAAO,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBnB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import fastGlob from 'fast-glob';
|
|
2
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { FileCache, hashRulesetSignature } from '@aicqtools/core';
|
|
5
|
+
import { applyOverridesForFile } from './apply-rule-config.js';
|
|
6
|
+
import { runFile } from './run-file.js';
|
|
7
|
+
import { rulesetSignature } from './ruleset-signature.js';
|
|
8
|
+
export async function runProject(opts) {
|
|
9
|
+
const start = Date.now();
|
|
10
|
+
const ignore = await resolveIgnores(opts.cwd, opts.exclude, opts.respectGitignore ?? false);
|
|
11
|
+
const files = await fastGlob([...opts.include], {
|
|
12
|
+
cwd: opts.cwd,
|
|
13
|
+
ignore,
|
|
14
|
+
absolute: true,
|
|
15
|
+
onlyFiles: true,
|
|
16
|
+
dot: false,
|
|
17
|
+
});
|
|
18
|
+
const cache = opts.cache;
|
|
19
|
+
const overrides = opts.overrides ?? [];
|
|
20
|
+
// Per-entry match counters (alpha.10). Allocated only when overrides is non-empty so the
|
|
21
|
+
// unused-feature fast path stays allocation-free. Slots that remain 0 after the scan are
|
|
22
|
+
// reported by the CLI as "matched no files — ignored." warnings.
|
|
23
|
+
const matchCounts = overrides.length > 0 ? new Array(overrides.length).fill(0) : undefined;
|
|
24
|
+
// The ruleset hash mixes in the overrides shape so cache entries invalidate when a user adds,
|
|
25
|
+
// removes, or edits override paths/rules. Without this, a stale entry could survive a config
|
|
26
|
+
// change that should have flipped a diagnostic on or off.
|
|
27
|
+
const rulesHash = cache
|
|
28
|
+
? hashRulesetSignature([
|
|
29
|
+
...rulesetSignature(opts.rules),
|
|
30
|
+
'overrides=' + JSON.stringify(overrides),
|
|
31
|
+
])
|
|
32
|
+
: '';
|
|
33
|
+
const diagnostics = [];
|
|
34
|
+
for (const file of files) {
|
|
35
|
+
try {
|
|
36
|
+
const fileRules = applyOverridesForFile(opts.rules, overrides, file, matchCounts);
|
|
37
|
+
if (cache) {
|
|
38
|
+
const st = await stat(file);
|
|
39
|
+
const cached = cache.get({
|
|
40
|
+
filePath: file,
|
|
41
|
+
mtime: Math.floor(st.mtimeMs),
|
|
42
|
+
size: st.size,
|
|
43
|
+
rulesHash,
|
|
44
|
+
});
|
|
45
|
+
if (cached) {
|
|
46
|
+
diagnostics.push(...cached);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const result = await runFile(file, fileRules);
|
|
50
|
+
cache.set({ filePath: file, mtime: Math.floor(st.mtimeMs), size: st.size, rulesHash }, result.diagnostics);
|
|
51
|
+
diagnostics.push(...result.diagnostics);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const result = await runFile(file, fileRules);
|
|
55
|
+
diagnostics.push(...result.diagnostics);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
// Per-file isolation: a parser crash or rule throw on one file must not abort the whole run.
|
|
60
|
+
// Skip cache.set on failure so the next run retries instead of caching the error.
|
|
61
|
+
diagnostics.push(parseFailedDiagnostic(file, err));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
diagnostics,
|
|
66
|
+
filesScanned: files.length,
|
|
67
|
+
durationMs: Date.now() - start,
|
|
68
|
+
...(matchCounts ? { overrideMatchCounts: matchCounts } : {}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Build the final ignore list for `fast-glob`. Always starts from the configured `exclude`;
|
|
73
|
+
* when `respectGitignore` is true, parses the root `.gitignore` (best-effort) and appends its
|
|
74
|
+
* entries. Negation (`!pattern`) and trailing-slash directory entries are honored.
|
|
75
|
+
*/
|
|
76
|
+
export async function resolveIgnores(cwd, exclude, respectGitignore) {
|
|
77
|
+
const ignores = [...exclude];
|
|
78
|
+
if (!respectGitignore)
|
|
79
|
+
return ignores;
|
|
80
|
+
try {
|
|
81
|
+
const gitignorePath = resolve(cwd, '.gitignore');
|
|
82
|
+
const st = await stat(gitignorePath);
|
|
83
|
+
if (!st.isFile())
|
|
84
|
+
return ignores;
|
|
85
|
+
const text = await readFile(gitignorePath, 'utf-8');
|
|
86
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
87
|
+
const line = raw.trim();
|
|
88
|
+
if (line.length === 0 || line.startsWith('#'))
|
|
89
|
+
continue;
|
|
90
|
+
// We intentionally don't try to fully emulate gitignore semantics — just translate the
|
|
91
|
+
// common shapes into fast-glob globs. Anything we can't reason about we leave as-is.
|
|
92
|
+
const negated = line.startsWith('!');
|
|
93
|
+
const body = (negated ? line.slice(1) : line).trim();
|
|
94
|
+
if (body.length === 0)
|
|
95
|
+
continue;
|
|
96
|
+
// Directory entry like `out/` → `**/out/**`
|
|
97
|
+
const cleaned = body.replace(/\/$/, '');
|
|
98
|
+
const glob = cleaned.includes('/') ? cleaned : `**/${cleaned}/**`;
|
|
99
|
+
ignores.push(negated ? `!${glob}` : glob);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// `.gitignore` missing / unreadable / not a regular file — fall through with static excludes.
|
|
104
|
+
}
|
|
105
|
+
return ignores;
|
|
106
|
+
}
|
|
107
|
+
function parseFailedDiagnostic(file, err) {
|
|
108
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
109
|
+
return {
|
|
110
|
+
ruleId: '@aicq/parse-failed',
|
|
111
|
+
severity: 'warning',
|
|
112
|
+
message: `parser failed during file parse: ${message}`,
|
|
113
|
+
messageKo: `파서 실패 (파일 파싱 단계): ${message}`,
|
|
114
|
+
file,
|
|
115
|
+
range: { start: { line: 1, column: 1 }, end: { line: 1, column: 1 } },
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=run-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-project.js","sourceRoot":"","sources":["../../src/runner/run-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-rule.d.ts","sourceRoot":"","sources":["../../src/runner/run-rule.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC,OAAO,KAAK,EAAE,IAAI,EAA6B,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAyChE,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAK5E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import Parser from 'tree-sitter';
|
|
2
|
+
import micromatch from 'micromatch';
|
|
3
|
+
import { traverse } from '../matcher/traverse.js';
|
|
4
|
+
import { makeRuleContext } from './context.js';
|
|
5
|
+
import { loadLanguage } from '@aicqtools/core';
|
|
6
|
+
function ruleAppliesTo(rule, language) {
|
|
7
|
+
const langs = Array.isArray(rule.language) ? rule.language : [rule.language];
|
|
8
|
+
return langs.includes(language);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Honor `rule.pathExclude` — a list of micromatch globs. Matching is performed against the
|
|
12
|
+
* file path as supplied (absolute by default in normal runs, fixture-relative in unit tests),
|
|
13
|
+
* and also against the path with backslashes normalized to forward slashes so authors can write
|
|
14
|
+
* `**\/llm/client.*` without worrying about Windows separators. The match is "any glob" — one
|
|
15
|
+
* match is enough to skip the rule for the file.
|
|
16
|
+
*/
|
|
17
|
+
function isPathExcluded(rule, filePath) {
|
|
18
|
+
if (!rule.pathExclude || rule.pathExclude.length === 0)
|
|
19
|
+
return false;
|
|
20
|
+
const globs = [...rule.pathExclude];
|
|
21
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
22
|
+
return micromatch.isMatch(normalized, globs, { dot: true }) || micromatch.isMatch(filePath, globs, { dot: true });
|
|
23
|
+
}
|
|
24
|
+
function runFunctionRule(rule, run, tree) {
|
|
25
|
+
const ctx = makeRuleContext(run, rule);
|
|
26
|
+
traverse(tree.rootNode, (node) => {
|
|
27
|
+
const visitor = rule.visitors[node.type];
|
|
28
|
+
if (visitor)
|
|
29
|
+
visitor(node, ctx);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function runPatternRule(rule, run, tree) {
|
|
33
|
+
const lang = loadLanguage(run.language);
|
|
34
|
+
const query = new Parser.Query(lang, rule.query);
|
|
35
|
+
const matches = query.matches(tree.rootNode);
|
|
36
|
+
const ctx = makeRuleContext(run, rule);
|
|
37
|
+
for (const match of matches) {
|
|
38
|
+
const target = match.captures[0]?.node;
|
|
39
|
+
if (target)
|
|
40
|
+
ctx.report({ node: target });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function runRule(rule, run, tree) {
|
|
44
|
+
if (!ruleAppliesTo(rule, run.language))
|
|
45
|
+
return;
|
|
46
|
+
if (isPathExcluded(rule, run.filePath))
|
|
47
|
+
return;
|
|
48
|
+
if (rule.kind === 'function')
|
|
49
|
+
runFunctionRule(rule, run, tree);
|
|
50
|
+
else
|
|
51
|
+
runPatternRule(rule, run, tree);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=run-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-rule.js","sourceRoot":"","sources":["../../src/runner/run-rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type Parser from 'tree-sitter';
|
|
2
|
+
import type { Diagnostic, Language } from '@aicqtools/core';
|
|
3
|
+
/**
|
|
4
|
+
* Inline suppression directives — ESLint-style comment markers that suppress diagnostics
|
|
5
|
+
* for a specific line, the next line, or the entire file. Supported syntaxes:
|
|
6
|
+
*
|
|
7
|
+
* // aicq-disable-next-line <rule-id>[, <rule-id>...]
|
|
8
|
+
* // aicq-disable-line <rule-id>[, ...]
|
|
9
|
+
* // aicq-disable-file <rule-id>[, ...]
|
|
10
|
+
*
|
|
11
|
+
* Python uses `#` instead of `//`. Block comments (`/* ...\*\/`) are also recognized.
|
|
12
|
+
* The trailing rule-id list may be omitted — a bare directive suppresses *all* rules for that
|
|
13
|
+
* scope. Multiple ids may be separated by commas, whitespace, or both. Unknown ids are silently
|
|
14
|
+
* accepted (a project may rename rules; we don't want a stale directive to crash the run).
|
|
15
|
+
*/
|
|
16
|
+
export type Scope = number | 'file';
|
|
17
|
+
export interface Suppressions {
|
|
18
|
+
/** Per-line maps: line number → set of rule ids ('*' = all). */
|
|
19
|
+
readonly byLine: Map<number, Set<string> | '*'>;
|
|
20
|
+
/** File-wide suppressions. */
|
|
21
|
+
readonly fileLevel: Set<string> | '*' | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Walk the tree's comment nodes and produce a Suppressions map. Never throws — if the grammar
|
|
25
|
+
* yields no comment nodes for a given language, the result is empty (and applySuppressions is
|
|
26
|
+
* a no-op). The `language` parameter is reserved for future per-language tweaks; today it's
|
|
27
|
+
* only used to recognize that block comments may span multiple lines.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseSuppressions(tree: Parser.Tree, source: string, language: Language): Suppressions;
|
|
30
|
+
/**
|
|
31
|
+
* Filter diagnostics through the parsed suppressions. Diagnostics whose `ruleId` is suppressed
|
|
32
|
+
* either file-wide or on its specific line are removed. `@aicq/parse-failed` (and any other
|
|
33
|
+
* synthetic diagnostic emitted by the runner) is treated like any other rule and can be
|
|
34
|
+
* suppressed by id or with a bare directive.
|
|
35
|
+
*/
|
|
36
|
+
export declare function applySuppressions(diagnostics: readonly Diagnostic[], suppressions: Suppressions): Diagnostic[];
|
|
37
|
+
//# sourceMappingURL=suppressions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../../src/runner/suppressions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG5D;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;IAChD,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC;CAC9C;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,YAAY,CA0Dd;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,YAAY,EAAE,YAAY,GACzB,UAAU,EAAE,CAed"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { traverse } from '../matcher/traverse.js';
|
|
2
|
+
const COMMENT_NODE_TYPES = new Set(['comment', 'block_comment', 'line_comment']);
|
|
3
|
+
// Capture group 1: directive verb. Group 2: optional rule-id list.
|
|
4
|
+
const DIRECTIVE_RE = /aicq-disable-(next-line|line|file)\b\s*(.*)/i;
|
|
5
|
+
/**
|
|
6
|
+
* Walk the tree's comment nodes and produce a Suppressions map. Never throws — if the grammar
|
|
7
|
+
* yields no comment nodes for a given language, the result is empty (and applySuppressions is
|
|
8
|
+
* a no-op). The `language` parameter is reserved for future per-language tweaks; today it's
|
|
9
|
+
* only used to recognize that block comments may span multiple lines.
|
|
10
|
+
*/
|
|
11
|
+
export function parseSuppressions(tree, source, language) {
|
|
12
|
+
void language; // currently uniform across supported languages
|
|
13
|
+
const byLine = new Map();
|
|
14
|
+
let fileLevel = null;
|
|
15
|
+
const mergeAtLine = (line, ids) => {
|
|
16
|
+
const existing = byLine.get(line);
|
|
17
|
+
if (existing === undefined) {
|
|
18
|
+
byLine.set(line, ids === '*' ? '*' : new Set(ids));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (existing === '*' || ids === '*') {
|
|
22
|
+
byLine.set(line, '*');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
for (const id of ids)
|
|
26
|
+
existing.add(id);
|
|
27
|
+
};
|
|
28
|
+
const mergeFile = (ids) => {
|
|
29
|
+
if (fileLevel === '*' || ids === '*') {
|
|
30
|
+
fileLevel = '*';
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (fileLevel === null) {
|
|
34
|
+
fileLevel = new Set(ids);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
for (const id of ids)
|
|
38
|
+
fileLevel.add(id);
|
|
39
|
+
};
|
|
40
|
+
traverse(tree.rootNode, (node) => {
|
|
41
|
+
if (!COMMENT_NODE_TYPES.has(node.type))
|
|
42
|
+
return;
|
|
43
|
+
const raw = source.slice(node.startIndex, node.endIndex);
|
|
44
|
+
// Strip comment delimiters before regex match so the body is what we scan.
|
|
45
|
+
const body = stripCommentDelimiters(raw);
|
|
46
|
+
const m = DIRECTIVE_RE.exec(body);
|
|
47
|
+
if (!m)
|
|
48
|
+
return;
|
|
49
|
+
const verb = m[1]?.toLowerCase();
|
|
50
|
+
if (!verb)
|
|
51
|
+
return;
|
|
52
|
+
const ids = parseRuleIds(m[2] ?? '');
|
|
53
|
+
if (verb === 'file') {
|
|
54
|
+
mergeFile(ids);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Lines are 1-based to match Diagnostic.range.start.line
|
|
58
|
+
const startLine = node.startPosition.row + 1;
|
|
59
|
+
const endLine = node.endPosition.row + 1;
|
|
60
|
+
if (verb === 'next-line') {
|
|
61
|
+
mergeAtLine(endLine + 1, ids);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// 'line' — for a leading standalone comment, apply to the comment's own line(s).
|
|
65
|
+
// For a trailing comment (e.g. `code; // aicq-disable-line`), the comment is on the
|
|
66
|
+
// same line as the code, so this also applies correctly.
|
|
67
|
+
for (let l = startLine; l <= endLine; l++)
|
|
68
|
+
mergeAtLine(l, ids);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return { byLine, fileLevel };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Filter diagnostics through the parsed suppressions. Diagnostics whose `ruleId` is suppressed
|
|
75
|
+
* either file-wide or on its specific line are removed. `@aicq/parse-failed` (and any other
|
|
76
|
+
* synthetic diagnostic emitted by the runner) is treated like any other rule and can be
|
|
77
|
+
* suppressed by id or with a bare directive.
|
|
78
|
+
*/
|
|
79
|
+
export function applySuppressions(diagnostics, suppressions) {
|
|
80
|
+
if (suppressions.fileLevel === '*')
|
|
81
|
+
return [];
|
|
82
|
+
const fileSet = suppressions.fileLevel instanceof Set ? suppressions.fileLevel : null;
|
|
83
|
+
const hasAnyLine = suppressions.byLine.size > 0;
|
|
84
|
+
if (!fileSet && !hasAnyLine)
|
|
85
|
+
return [...diagnostics];
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const d of diagnostics) {
|
|
88
|
+
if (fileSet && fileSet.has(d.ruleId))
|
|
89
|
+
continue;
|
|
90
|
+
const lineMap = suppressions.byLine.get(d.range.start.line);
|
|
91
|
+
if (lineMap === '*')
|
|
92
|
+
continue;
|
|
93
|
+
if (lineMap && lineMap.has(d.ruleId))
|
|
94
|
+
continue;
|
|
95
|
+
out.push(d);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
function stripCommentDelimiters(raw) {
|
|
100
|
+
// `//foo` → `foo`, `# foo` → `foo`, `/* foo */` → `foo`, `<!-- foo -->` (just in case) → `foo`
|
|
101
|
+
return raw
|
|
102
|
+
.replace(/^\s*\/\*/, '')
|
|
103
|
+
.replace(/\*\/\s*$/, '')
|
|
104
|
+
.replace(/^\s*\/\//, '')
|
|
105
|
+
.replace(/^\s*#/, '')
|
|
106
|
+
.replace(/^\s*<!--/, '')
|
|
107
|
+
.replace(/-->\s*$/, '')
|
|
108
|
+
.trim();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Split the directive tail into a set of rule ids. Empty tail → '*' (bare directive).
|
|
112
|
+
* Accepts commas, whitespace, or both as separators; ignores empty tokens; lowercases nothing
|
|
113
|
+
* (rule ids are case-sensitive). Returns `'*'` when the tail is empty.
|
|
114
|
+
*/
|
|
115
|
+
function parseRuleIds(tail) {
|
|
116
|
+
const trimmed = tail.trim();
|
|
117
|
+
if (trimmed.length === 0)
|
|
118
|
+
return '*';
|
|
119
|
+
const tokens = trimmed
|
|
120
|
+
.split(/[,\s]+/)
|
|
121
|
+
.map((s) => s.trim())
|
|
122
|
+
.filter((s) => s.length > 0);
|
|
123
|
+
if (tokens.length === 0)
|
|
124
|
+
return '*';
|
|
125
|
+
return new Set(tokens);
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=suppressions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suppressions.js","sourceRoot":"","sources":["../../src/runner/suppressions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnalyzeRepoOptions, RuleSuggestionReport } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Approach A — built-in rule recommender. Scans the repo with all supplied rules,
|
|
4
|
+
* ranks them by how many violations they would flag, and emits a paste-ready
|
|
5
|
+
* `aicq.config.yaml` enable-snippet. Also reads `package.json` / `requirements.txt`
|
|
6
|
+
* (no AST) and flags built-in rules whose id/docs/message mentions a declared
|
|
7
|
+
* dependency ("stack match").
|
|
8
|
+
*/
|
|
9
|
+
export declare function analyzeRepo(opts: AnalyzeRepoOptions): Promise<RuleSuggestionReport>;
|
|
10
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/suggest/analyze.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,kBAAkB,EAGlB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAiBpB;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAmFzF"}
|