pi-lens 2.2.9 → 3.0.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 +198 -0
- package/README.md +709 -519
- package/clients/__tests__/file-time.test.js +216 -0
- package/clients/__tests__/file-time.test.ts +276 -0
- package/clients/__tests__/format-service.test.js +245 -0
- package/clients/__tests__/format-service.test.ts +339 -0
- package/clients/__tests__/formatters.test.js +271 -0
- package/clients/__tests__/formatters.test.ts +401 -0
- package/clients/amain-types.js +164 -0
- package/clients/amain-types.ts +165 -0
- package/clients/architect-client.js +56 -12
- package/clients/architect-client.ts +81 -16
- package/clients/ast-grep-client.js +2 -2
- package/clients/ast-grep-client.ts +14 -39
- package/clients/ast-grep-parser.ts +1 -1
- package/clients/ast-grep-rule-manager.js +8 -0
- package/clients/ast-grep-rule-manager.ts +10 -1
- package/clients/ast-grep-types.js +9 -0
- package/clients/ast-grep-types.ts +106 -0
- package/clients/auto-loop.js +10 -0
- package/clients/auto-loop.ts +14 -1
- package/clients/biome-client.js +81 -19
- package/clients/biome-client.ts +103 -22
- package/clients/bus/bus.js +191 -0
- package/clients/bus/bus.ts +251 -0
- package/clients/bus/events.js +214 -0
- package/clients/bus/events.ts +279 -0
- package/clients/bus/index.js +8 -0
- package/clients/bus/index.ts +9 -0
- package/clients/bus/integration.js +158 -0
- package/clients/bus/integration.ts +214 -0
- package/clients/complexity-client.js +13 -7
- package/clients/complexity-client.ts +13 -7
- package/clients/config-validator.js +465 -0
- package/clients/config-validator.ts +558 -0
- package/clients/dependency-checker.js +4 -10
- package/clients/dependency-checker.ts +4 -10
- package/clients/dispatch/__tests__/autofix-integration.test.js +245 -0
- package/clients/dispatch/__tests__/autofix-integration.test.ts +300 -0
- package/clients/dispatch/__tests__/runner-registration.test.js +236 -0
- package/clients/dispatch/__tests__/runner-registration.test.ts +282 -0
- package/clients/dispatch/bus-dispatcher.js +177 -0
- package/clients/dispatch/bus-dispatcher.ts +251 -0
- package/clients/dispatch/dispatcher.edge.test.js +82 -0
- package/clients/dispatch/dispatcher.edge.test.ts +100 -0
- package/clients/dispatch/dispatcher.format.test.js +46 -0
- package/clients/dispatch/dispatcher.format.test.ts +58 -0
- package/clients/dispatch/dispatcher.inline.test.js +74 -0
- package/clients/dispatch/dispatcher.inline.test.ts +93 -0
- package/clients/dispatch/dispatcher.js +19 -53
- package/clients/dispatch/dispatcher.ts +20 -67
- package/clients/dispatch/plan.js +9 -4
- package/clients/dispatch/plan.ts +9 -4
- package/clients/dispatch/runners/architect.js +21 -7
- package/clients/dispatch/runners/architect.test.js +138 -0
- package/clients/dispatch/runners/architect.test.ts +162 -0
- package/clients/dispatch/runners/architect.ts +22 -7
- package/clients/dispatch/runners/ast-grep-napi.js +462 -0
- package/clients/dispatch/runners/ast-grep-napi.test.js +111 -0
- package/clients/dispatch/runners/ast-grep-napi.test.ts +133 -0
- package/clients/dispatch/runners/ast-grep-napi.ts +506 -0
- package/clients/dispatch/runners/ast-grep.js +62 -19
- package/clients/dispatch/runners/ast-grep.ts +70 -18
- package/clients/dispatch/runners/biome.js +29 -53
- package/clients/dispatch/runners/biome.ts +29 -63
- package/clients/dispatch/runners/config-validation.js +67 -0
- package/clients/dispatch/runners/config-validation.ts +82 -0
- package/clients/dispatch/runners/go-vet.js +4 -28
- package/clients/dispatch/runners/go-vet.ts +4 -32
- package/clients/dispatch/runners/index.js +30 -10
- package/clients/dispatch/runners/index.ts +30 -10
- package/clients/dispatch/runners/oxlint.js +141 -0
- package/clients/dispatch/runners/oxlint.test.js +230 -0
- package/clients/dispatch/runners/oxlint.test.ts +303 -0
- package/clients/dispatch/runners/oxlint.ts +175 -0
- package/clients/dispatch/runners/pyright.js +40 -70
- package/clients/dispatch/runners/pyright.test.js +16 -2
- package/clients/dispatch/runners/pyright.test.ts +14 -2
- package/clients/dispatch/runners/pyright.ts +48 -91
- package/clients/dispatch/runners/python-slop.js +97 -0
- package/clients/dispatch/runners/python-slop.test.js +203 -0
- package/clients/dispatch/runners/python-slop.test.ts +298 -0
- package/clients/dispatch/runners/python-slop.ts +124 -0
- package/clients/dispatch/runners/ruff.js +18 -71
- package/clients/dispatch/runners/ruff.ts +19 -79
- package/clients/dispatch/runners/rust-clippy.js +28 -32
- package/clients/dispatch/runners/rust-clippy.ts +29 -31
- package/clients/dispatch/runners/scan_codebase.test.js +89 -0
- package/clients/dispatch/runners/scan_codebase.test.ts +105 -0
- package/clients/dispatch/runners/shellcheck.js +147 -0
- package/clients/dispatch/runners/shellcheck.test.js +98 -0
- package/clients/dispatch/runners/shellcheck.test.ts +129 -0
- package/clients/dispatch/runners/shellcheck.ts +188 -0
- package/clients/dispatch/runners/similarity.js +230 -0
- package/clients/dispatch/runners/similarity.ts +339 -0
- package/clients/dispatch/runners/spellcheck.js +106 -0
- package/clients/dispatch/runners/spellcheck.test.js +158 -0
- package/clients/dispatch/runners/spellcheck.test.ts +214 -0
- package/clients/dispatch/runners/spellcheck.ts +136 -0
- package/clients/dispatch/runners/tree-sitter.js +107 -0
- package/clients/dispatch/runners/tree-sitter.ts +135 -0
- package/clients/dispatch/runners/ts-lsp.js +104 -33
- package/clients/dispatch/runners/ts-lsp.ts +120 -38
- package/clients/dispatch/runners/ts-slop.js +113 -0
- package/clients/dispatch/runners/ts-slop.test.js +180 -0
- package/clients/dispatch/runners/ts-slop.test.ts +230 -0
- package/clients/dispatch/runners/ts-slop.ts +142 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.js +134 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.ts +186 -0
- package/clients/dispatch/runners/utils/runner-helpers.js +115 -0
- package/clients/dispatch/runners/utils/runner-helpers.ts +167 -0
- package/clients/dispatch/runners/utils.js +2 -4
- package/clients/dispatch/runners/utils.ts +2 -4
- package/clients/dispatch/types.ts +1 -1
- package/clients/dispatch/utils/format-utils.js +49 -0
- package/clients/dispatch/utils/format-utils.ts +60 -0
- package/clients/dogfood.test.js +201 -0
- package/clients/dogfood.test.ts +269 -0
- package/clients/file-time.js +152 -0
- package/clients/file-time.ts +208 -0
- package/clients/file-utils.js +40 -0
- package/clients/file-utils.ts +44 -0
- package/clients/fix-scanners.js +10 -20
- package/clients/fix-scanners.ts +10 -22
- package/clients/format-service.js +172 -0
- package/clients/format-service.ts +254 -0
- package/clients/formatters.js +435 -0
- package/clients/formatters.ts +508 -0
- package/clients/go-client.js +5 -14
- package/clients/go-client.ts +5 -13
- package/clients/installer/index.js +356 -0
- package/clients/installer/index.ts +426 -0
- package/clients/jscpd-client.js +11 -9
- package/clients/jscpd-client.ts +12 -8
- package/clients/knip-client.js +3 -7
- package/clients/knip-client.ts +3 -6
- package/clients/lsp/__tests__/client.test.js +325 -0
- package/clients/lsp/__tests__/client.test.ts +434 -0
- package/clients/lsp/__tests__/config.test.js +166 -0
- package/clients/lsp/__tests__/config.test.ts +209 -0
- package/clients/lsp/__tests__/error-recovery.test.js +213 -0
- package/clients/lsp/__tests__/error-recovery.test.ts +279 -0
- package/clients/lsp/__tests__/integration.test.js +127 -0
- package/clients/lsp/__tests__/integration.test.ts +160 -0
- package/clients/lsp/__tests__/launch.test.js +260 -0
- package/clients/lsp/__tests__/launch.test.ts +329 -0
- package/clients/lsp/__tests__/server.test.js +259 -0
- package/clients/lsp/__tests__/server.test.ts +332 -0
- package/clients/lsp/__tests__/service.test.js +417 -0
- package/clients/lsp/__tests__/service.test.ts +499 -0
- package/clients/lsp/client.js +235 -0
- package/clients/lsp/client.ts +328 -0
- package/clients/lsp/config.js +115 -0
- package/clients/lsp/config.ts +149 -0
- package/clients/lsp/index.js +222 -0
- package/clients/lsp/index.ts +280 -0
- package/clients/lsp/installer/index.js +391 -0
- package/clients/lsp/interactive-install.js +210 -0
- package/clients/lsp/interactive-install.ts +251 -0
- package/clients/lsp/language.js +170 -0
- package/clients/lsp/language.ts +216 -0
- package/clients/lsp/launch.js +174 -0
- package/clients/lsp/launch.ts +240 -0
- package/clients/lsp/lsp/launch.js +116 -0
- package/clients/lsp/lsp/server.js +532 -0
- package/clients/lsp/lsp-index.js +10 -0
- package/clients/lsp/lsp-index.ts +11 -0
- package/clients/lsp/path-utils.js +48 -0
- package/clients/lsp/path-utils.ts +52 -0
- package/clients/lsp/server.js +615 -0
- package/clients/lsp/server.ts +800 -0
- package/clients/lsp/test-py-spawn/requirements.txt +1 -0
- package/clients/lsp/test-py-spawn/test.py +3 -0
- package/clients/lsp/test-py-svc/requirements.txt +1 -0
- package/clients/lsp/test-py-svc/test.py +3 -0
- package/clients/lsp/test-python-project/requirements.txt +1 -0
- package/clients/lsp/test-python-project/test.py +5 -0
- package/clients/metrics-history.js +2 -2
- package/clients/metrics-history.ts +2 -2
- package/clients/production-readiness.js +522 -0
- package/clients/production-readiness.ts +556 -0
- package/clients/project-index.js +255 -0
- package/clients/project-index.ts +383 -0
- package/clients/project-metadata.js +531 -0
- package/clients/project-metadata.ts +624 -0
- package/clients/ruff-client.js +56 -16
- package/clients/ruff-client.ts +72 -15
- package/clients/runner-tracker.js +152 -0
- package/clients/runner-tracker.ts +213 -0
- package/clients/rust-client.js +4 -11
- package/clients/rust-client.ts +5 -11
- package/clients/safe-spawn.js +96 -0
- package/clients/safe-spawn.ts +128 -0
- package/clients/scan-architectural-debt.js +3 -6
- package/clients/scan-architectural-debt.ts +3 -6
- package/clients/scan-utils.js +5 -20
- package/clients/scan-utils.ts +5 -29
- package/clients/secrets-scanner.js +3 -17
- package/clients/secrets-scanner.ts +4 -20
- package/clients/services/__tests__/effect-integration.test.js +86 -0
- package/clients/services/__tests__/effect-integration.test.ts +111 -0
- package/clients/services/effect-integration.js +194 -0
- package/clients/services/effect-integration.ts +268 -0
- package/clients/services/index.js +7 -0
- package/clients/services/index.ts +8 -0
- package/clients/services/runner-service.js +105 -0
- package/clients/services/runner-service.ts +179 -0
- package/clients/sg-runner.js +87 -13
- package/clients/sg-runner.ts +97 -13
- package/clients/state-matrix.js +160 -0
- package/clients/state-matrix.ts +202 -0
- package/clients/subprocess-client.js +10 -9
- package/clients/subprocess-client.ts +10 -8
- package/clients/test-runner-client.js +3 -7
- package/clients/test-runner-client.ts +3 -6
- package/clients/tool-availability.js +4 -10
- package/clients/tool-availability.ts +4 -9
- package/clients/tree-sitter-client.js +564 -0
- package/clients/tree-sitter-client.ts +797 -0
- package/clients/tree-sitter-query-loader.js +355 -0
- package/clients/tree-sitter-query-loader.ts +425 -0
- package/clients/type-coverage-client.js +3 -7
- package/clients/type-coverage-client.ts +3 -6
- package/clients/typescript-client.codefix.test.js +157 -0
- package/clients/typescript-client.codefix.test.ts +186 -0
- package/clients/typescript-client.js +43 -0
- package/clients/typescript-client.ts +98 -0
- package/commands/booboo.js +799 -219
- package/commands/booboo.ts +1004 -225
- package/commands/clients/ast-grep-client.js +250 -0
- package/commands/clients/ast-grep-parser.js +86 -0
- package/commands/clients/ast-grep-rule-manager.js +91 -0
- package/commands/clients/ast-grep-types.js +9 -0
- package/commands/clients/biome-client.js +380 -0
- package/commands/clients/complexity-client.js +667 -0
- package/commands/clients/file-kinds.js +177 -0
- package/commands/clients/file-utils.js +40 -0
- package/commands/clients/jscpd-client.js +169 -0
- package/commands/clients/knip-client.js +211 -0
- package/commands/clients/ruff-client.js +297 -0
- package/commands/clients/safe-spawn.js +88 -0
- package/commands/clients/scan-utils.js +83 -0
- package/commands/clients/sg-runner.js +190 -0
- package/commands/clients/types.js +11 -0
- package/commands/clients/typescript-client.js +505 -0
- package/commands/fix-from-booboo.js +398 -0
- package/commands/fix-from-booboo.ts +485 -0
- package/commands/fix-simplified.js +618 -0
- package/commands/fix-simplified.ts +768 -0
- package/commands/rate.js +10 -14
- package/commands/rate.ts +9 -16
- package/default-architect.yaml +59 -15
- package/index.ts +342 -429
- package/package.json +16 -3
- package/rules/ast-grep-rules/rules/empty-catch.yml +38 -13
- package/rules/ast-grep-rules/rules/no-array-constructor.yml +1 -0
- package/rules/ast-grep-rules/rules/no-debugger.yml +2 -0
- package/rules/python-slop-rules/.sgconfig.yml +4 -0
- package/rules/python-slop-rules/rules/slop-rules.yml +647 -0
- package/rules/tree-sitter-queries/python/bare-except.yml +54 -0
- package/rules/tree-sitter-queries/python/eval-exec.yml +50 -0
- package/rules/tree-sitter-queries/python/is-vs-equals.yml +60 -0
- package/rules/tree-sitter-queries/python/mutable-default-arg.yml +57 -0
- package/rules/tree-sitter-queries/python/unreachable-except.yml +60 -0
- package/rules/tree-sitter-queries/python/wildcard-import.yml +46 -0
- package/rules/tree-sitter-queries/tsx/dangerously-set-inner-html.yml +63 -0
- package/rules/tree-sitter-queries/typescript/await-in-loop.yml +56 -0
- package/rules/tree-sitter-queries/typescript/console-statement.yml +47 -0
- package/rules/tree-sitter-queries/typescript/debugger.yml +47 -0
- package/rules/tree-sitter-queries/typescript/deep-nesting.yml +117 -0
- package/rules/tree-sitter-queries/typescript/deep-promise-chain.yml +73 -0
- package/rules/tree-sitter-queries/typescript/empty-catch.yml +64 -0
- package/rules/tree-sitter-queries/typescript/eval.yml +48 -0
- package/rules/tree-sitter-queries/typescript/hardcoded-secrets.yml +78 -0
- package/rules/tree-sitter-queries/typescript/long-parameter-list.yml +62 -0
- package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +49 -0
- package/rules/tree-sitter-queries/typescript/nested-ternary.yml +45 -0
- package/rules/ts-slop-rules/.sgconfig.yml +4 -0
- package/rules/ts-slop-rules/rules/in-correct-optional-input-type.yml +10 -0
- package/rules/ts-slop-rules/rules/jwt-no-verify.yml +13 -0
- package/rules/ts-slop-rules/rules/no-architecture-violation.yml +10 -0
- package/rules/ts-slop-rules/rules/no-case-declarations.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dangerously-set-inner-html.yml +10 -0
- package/rules/ts-slop-rules/rules/no-debugger.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-args.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-class-members.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-keys.yml +10 -0
- package/rules/ts-slop-rules/rules/no-eval.yml +13 -0
- package/rules/ts-slop-rules/rules/no-hardcoded-secrets.yml +12 -0
- package/rules/ts-slop-rules/rules/no-implied-eval.yml +12 -0
- package/rules/ts-slop-rules/rules/no-inner-html.yml +13 -0
- package/rules/ts-slop-rules/rules/no-javascript-url.yml +10 -0
- package/rules/ts-slop-rules/rules/no-mutable-default.yml +10 -0
- package/rules/ts-slop-rules/rules/no-nested-links.yml +12 -0
- package/rules/ts-slop-rules/rules/no-new-symbol.yml +10 -0
- package/rules/ts-slop-rules/rules/no-new-wrappers.yml +13 -0
- package/rules/ts-slop-rules/rules/no-open-redirect.yml +16 -0
- package/rules/ts-slop-rules/rules/slop-rules.yml +455 -0
- package/rules/ts-slop-rules/rules/weak-rsa-key.yml +12 -0
- package/skills/ast-grep/SKILL.md +182 -0
- package/clients/dispatch/runners/secrets.js +0 -109
- package/commands/fix.js +0 -244
- package/commands/fix.ts +0 -373
- package/rules/ast-grep-rules/rules/no-lonely-if.yml +0 -13
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amain State Types: 57 syntax types + 15 token types
|
|
3
|
+
*
|
|
4
|
+
* Adapted from Amain paper's Java AST structure for TypeScript.
|
|
5
|
+
* 57 syntax types (non-leaf AST nodes) + 15 token types (leaf categories) = 72 states
|
|
6
|
+
*
|
|
7
|
+
* Reference: https://github.com/CGCL-codes/Amain (ASE 2022)
|
|
8
|
+
*/
|
|
9
|
+
import * as ts from "typescript";
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// 57 Syntax Types (non-leaf AST nodes, indices 0-56)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export const SYNTAX_TYPES = [
|
|
14
|
+
// Declarations (0-9)
|
|
15
|
+
"FunctionDeclaration", // 0
|
|
16
|
+
"ArrowFunction", // 1
|
|
17
|
+
"FunctionExpression", // 2
|
|
18
|
+
"ClassDeclaration", // 3
|
|
19
|
+
"InterfaceDeclaration", // 4
|
|
20
|
+
"TypeAliasDeclaration", // 5
|
|
21
|
+
"EnumDeclaration", // 6
|
|
22
|
+
"MethodDeclaration", // 7
|
|
23
|
+
"Constructor", // 8
|
|
24
|
+
"GetAccessor", // 9
|
|
25
|
+
// More declarations (10-19)
|
|
26
|
+
"SetAccessor", // 10
|
|
27
|
+
"PropertyDeclaration", // 11
|
|
28
|
+
"Parameter", // 12
|
|
29
|
+
"VariableDeclaration", // 13
|
|
30
|
+
"ModuleDeclaration", // 14
|
|
31
|
+
"ImportDeclaration", // 15
|
|
32
|
+
"ExportDeclaration", // 16
|
|
33
|
+
"NamespaceExportDeclaration", // 17
|
|
34
|
+
"ImportClause", // 18
|
|
35
|
+
"NamespaceImport", // 19
|
|
36
|
+
// Statements (20-39)
|
|
37
|
+
"IfStatement", // 20
|
|
38
|
+
"ForStatement", // 21
|
|
39
|
+
"ForOfStatement", // 22
|
|
40
|
+
"ForInStatement", // 23
|
|
41
|
+
"WhileStatement", // 24
|
|
42
|
+
"DoWhileStatement", // 25
|
|
43
|
+
"SwitchStatement", // 26
|
|
44
|
+
"CaseClause", // 27
|
|
45
|
+
"DefaultClause", // 28
|
|
46
|
+
"TryStatement", // 29
|
|
47
|
+
"CatchClause", // 30
|
|
48
|
+
"ThrowStatement", // 31
|
|
49
|
+
"ReturnStatement", // 32
|
|
50
|
+
"BreakStatement", // 33
|
|
51
|
+
"ContinueStatement", // 34
|
|
52
|
+
"Block", // 35
|
|
53
|
+
"EmptyStatement", // 36
|
|
54
|
+
// More statements (37-39)
|
|
55
|
+
"DebuggerStatement", // 37
|
|
56
|
+
"LabeledStatement", // 38
|
|
57
|
+
"WithStatement", // 39
|
|
58
|
+
// Expressions (40-56)
|
|
59
|
+
"BinaryExpression", // 40
|
|
60
|
+
"UnaryExpression", // 41
|
|
61
|
+
"PrefixUnaryExpression", // 42
|
|
62
|
+
"PostfixUnaryExpression", // 43
|
|
63
|
+
"ConditionalExpression", // 44
|
|
64
|
+
"CallExpression", // 45
|
|
65
|
+
"PropertyAccessExpression", // 46
|
|
66
|
+
"ElementAccessExpression", // 47
|
|
67
|
+
"NewExpression", // 48
|
|
68
|
+
"ParenthesizedExpression", // 49
|
|
69
|
+
"TypeAssertionExpression", // 50
|
|
70
|
+
"AsExpression", // 51
|
|
71
|
+
"NonNullExpression", // 52
|
|
72
|
+
"TemplateExpression", // 53
|
|
73
|
+
"ArrayLiteralExpression", // 54
|
|
74
|
+
"ObjectLiteralExpression", // 55
|
|
75
|
+
"ExpressionStatement", // 56
|
|
76
|
+
];
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// 15 Token Types (leaf node categories, indices 57-71)
|
|
79
|
+
// ============================================================================
|
|
80
|
+
export const TOKEN_TYPES = [
|
|
81
|
+
"Identifier", // 57
|
|
82
|
+
"StringLiteral", // 58
|
|
83
|
+
"NumericLiteral", // 59
|
|
84
|
+
"TrueKeyword", // 60
|
|
85
|
+
"FalseKeyword", // 61
|
|
86
|
+
"NullKeyword", // 62
|
|
87
|
+
"UndefinedKeyword", // 63
|
|
88
|
+
"ThisKeyword", // 64
|
|
89
|
+
"SuperKeyword", // 65
|
|
90
|
+
"RegularExpressionLiteral", // 66
|
|
91
|
+
"NoSubstitutionTemplateLiteral", // 67
|
|
92
|
+
"TemplateHead", // 68
|
|
93
|
+
"TemplateMiddle", // 69
|
|
94
|
+
"TemplateTail", // 70
|
|
95
|
+
"ComputedPropertyName", // 71
|
|
96
|
+
];
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// Constants
|
|
99
|
+
// ============================================================================
|
|
100
|
+
export const NUM_SYNTAX = SYNTAX_TYPES.length; // 57
|
|
101
|
+
export const NUM_TOKEN = TOKEN_TYPES.length; // 15
|
|
102
|
+
export const NUM_STATES = NUM_SYNTAX + NUM_TOKEN; // 72
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// State Index Mapping
|
|
105
|
+
// ============================================================================
|
|
106
|
+
/**
|
|
107
|
+
* Map a TypeScript AST node to its Amain state index (0-71)
|
|
108
|
+
*/
|
|
109
|
+
export function getStateIndex(node) {
|
|
110
|
+
// Try syntax types first (0-56)
|
|
111
|
+
const kindName = ts.SyntaxKind[node.kind];
|
|
112
|
+
const syntaxIdx = SYNTAX_TYPES.indexOf(kindName);
|
|
113
|
+
if (syntaxIdx !== -1)
|
|
114
|
+
return syntaxIdx;
|
|
115
|
+
// Map to token types (57-71) based on node kind
|
|
116
|
+
if (ts.isIdentifier(node))
|
|
117
|
+
return 57;
|
|
118
|
+
if (ts.isStringLiteral(node))
|
|
119
|
+
return 58;
|
|
120
|
+
if (ts.isNumericLiteral(node))
|
|
121
|
+
return 59;
|
|
122
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword)
|
|
123
|
+
return 60;
|
|
124
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword)
|
|
125
|
+
return 61;
|
|
126
|
+
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
127
|
+
return 62;
|
|
128
|
+
if (node.kind === ts.SyntaxKind.UndefinedKeyword)
|
|
129
|
+
return 63;
|
|
130
|
+
if (node.kind === ts.SyntaxKind.ThisKeyword)
|
|
131
|
+
return 64;
|
|
132
|
+
if (node.kind === ts.SyntaxKind.SuperKeyword)
|
|
133
|
+
return 65;
|
|
134
|
+
if (node.kind === ts.SyntaxKind.RegularExpressionLiteral)
|
|
135
|
+
return 66;
|
|
136
|
+
if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)
|
|
137
|
+
return 67;
|
|
138
|
+
if (node.kind === ts.SyntaxKind.TemplateHead)
|
|
139
|
+
return 68;
|
|
140
|
+
if (node.kind === ts.SyntaxKind.TemplateMiddle)
|
|
141
|
+
return 69;
|
|
142
|
+
if (node.kind === ts.SyntaxKind.TemplateTail)
|
|
143
|
+
return 70;
|
|
144
|
+
if (node.kind === ts.SyntaxKind.ComputedPropertyName)
|
|
145
|
+
return 71;
|
|
146
|
+
// Default: treat as identifier for any other leaf node
|
|
147
|
+
return 57;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if a node is a syntax type (non-leaf) vs token type (leaf)
|
|
151
|
+
*/
|
|
152
|
+
export function isSyntaxNode(node) {
|
|
153
|
+
return getStateIndex(node) < NUM_SYNTAX;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get state name for debugging
|
|
157
|
+
*/
|
|
158
|
+
export function getStateName(index) {
|
|
159
|
+
if (index < NUM_SYNTAX)
|
|
160
|
+
return SYNTAX_TYPES[index];
|
|
161
|
+
if (index < NUM_STATES)
|
|
162
|
+
return TOKEN_TYPES[index - NUM_SYNTAX];
|
|
163
|
+
return "Unknown";
|
|
164
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amain State Types: 57 syntax types + 15 token types
|
|
3
|
+
*
|
|
4
|
+
* Adapted from Amain paper's Java AST structure for TypeScript.
|
|
5
|
+
* 57 syntax types (non-leaf AST nodes) + 15 token types (leaf categories) = 72 states
|
|
6
|
+
*
|
|
7
|
+
* Reference: https://github.com/CGCL-codes/Amain (ASE 2022)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as ts from "typescript";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// 57 Syntax Types (non-leaf AST nodes, indices 0-56)
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
export const SYNTAX_TYPES = [
|
|
17
|
+
// Declarations (0-9)
|
|
18
|
+
"FunctionDeclaration", // 0
|
|
19
|
+
"ArrowFunction", // 1
|
|
20
|
+
"FunctionExpression", // 2
|
|
21
|
+
"ClassDeclaration", // 3
|
|
22
|
+
"InterfaceDeclaration", // 4
|
|
23
|
+
"TypeAliasDeclaration", // 5
|
|
24
|
+
"EnumDeclaration", // 6
|
|
25
|
+
"MethodDeclaration", // 7
|
|
26
|
+
"Constructor", // 8
|
|
27
|
+
"GetAccessor", // 9
|
|
28
|
+
|
|
29
|
+
// More declarations (10-19)
|
|
30
|
+
"SetAccessor", // 10
|
|
31
|
+
"PropertyDeclaration", // 11
|
|
32
|
+
"Parameter", // 12
|
|
33
|
+
"VariableDeclaration", // 13
|
|
34
|
+
"ModuleDeclaration", // 14
|
|
35
|
+
"ImportDeclaration", // 15
|
|
36
|
+
"ExportDeclaration", // 16
|
|
37
|
+
"NamespaceExportDeclaration", // 17
|
|
38
|
+
"ImportClause", // 18
|
|
39
|
+
"NamespaceImport", // 19
|
|
40
|
+
|
|
41
|
+
// Statements (20-39)
|
|
42
|
+
"IfStatement", // 20
|
|
43
|
+
"ForStatement", // 21
|
|
44
|
+
"ForOfStatement", // 22
|
|
45
|
+
"ForInStatement", // 23
|
|
46
|
+
"WhileStatement", // 24
|
|
47
|
+
"DoWhileStatement", // 25
|
|
48
|
+
"SwitchStatement", // 26
|
|
49
|
+
"CaseClause", // 27
|
|
50
|
+
"DefaultClause", // 28
|
|
51
|
+
"TryStatement", // 29
|
|
52
|
+
"CatchClause", // 30
|
|
53
|
+
"ThrowStatement", // 31
|
|
54
|
+
"ReturnStatement", // 32
|
|
55
|
+
"BreakStatement", // 33
|
|
56
|
+
"ContinueStatement", // 34
|
|
57
|
+
"Block", // 35
|
|
58
|
+
"EmptyStatement", // 36
|
|
59
|
+
|
|
60
|
+
// More statements (37-39)
|
|
61
|
+
"DebuggerStatement", // 37
|
|
62
|
+
"LabeledStatement", // 38
|
|
63
|
+
"WithStatement", // 39
|
|
64
|
+
|
|
65
|
+
// Expressions (40-56)
|
|
66
|
+
"BinaryExpression", // 40
|
|
67
|
+
"UnaryExpression", // 41
|
|
68
|
+
"PrefixUnaryExpression", // 42
|
|
69
|
+
"PostfixUnaryExpression", // 43
|
|
70
|
+
"ConditionalExpression", // 44
|
|
71
|
+
"CallExpression", // 45
|
|
72
|
+
"PropertyAccessExpression", // 46
|
|
73
|
+
"ElementAccessExpression", // 47
|
|
74
|
+
"NewExpression", // 48
|
|
75
|
+
"ParenthesizedExpression", // 49
|
|
76
|
+
"TypeAssertionExpression", // 50
|
|
77
|
+
"AsExpression", // 51
|
|
78
|
+
"NonNullExpression", // 52
|
|
79
|
+
"TemplateExpression", // 53
|
|
80
|
+
"ArrayLiteralExpression", // 54
|
|
81
|
+
"ObjectLiteralExpression", // 55
|
|
82
|
+
"ExpressionStatement", // 56
|
|
83
|
+
] as const;
|
|
84
|
+
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// 15 Token Types (leaf node categories, indices 57-71)
|
|
87
|
+
// ============================================================================
|
|
88
|
+
|
|
89
|
+
export const TOKEN_TYPES = [
|
|
90
|
+
"Identifier", // 57
|
|
91
|
+
"StringLiteral", // 58
|
|
92
|
+
"NumericLiteral", // 59
|
|
93
|
+
"TrueKeyword", // 60
|
|
94
|
+
"FalseKeyword", // 61
|
|
95
|
+
"NullKeyword", // 62
|
|
96
|
+
"UndefinedKeyword", // 63
|
|
97
|
+
"ThisKeyword", // 64
|
|
98
|
+
"SuperKeyword", // 65
|
|
99
|
+
"RegularExpressionLiteral", // 66
|
|
100
|
+
"NoSubstitutionTemplateLiteral", // 67
|
|
101
|
+
"TemplateHead", // 68
|
|
102
|
+
"TemplateMiddle", // 69
|
|
103
|
+
"TemplateTail", // 70
|
|
104
|
+
"ComputedPropertyName", // 71
|
|
105
|
+
] as const;
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// Constants
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
export const NUM_SYNTAX = SYNTAX_TYPES.length; // 57
|
|
112
|
+
export const NUM_TOKEN = TOKEN_TYPES.length; // 15
|
|
113
|
+
export const NUM_STATES = NUM_SYNTAX + NUM_TOKEN; // 72
|
|
114
|
+
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// State Index Mapping
|
|
117
|
+
// ============================================================================
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Map a TypeScript AST node to its Amain state index (0-71)
|
|
121
|
+
*/
|
|
122
|
+
export function getStateIndex(node: ts.Node): number {
|
|
123
|
+
// Try syntax types first (0-56)
|
|
124
|
+
const kindName = ts.SyntaxKind[node.kind];
|
|
125
|
+
const syntaxIdx = SYNTAX_TYPES.indexOf(
|
|
126
|
+
kindName as (typeof SYNTAX_TYPES)[number],
|
|
127
|
+
);
|
|
128
|
+
if (syntaxIdx !== -1) return syntaxIdx;
|
|
129
|
+
|
|
130
|
+
// Map to token types (57-71) based on node kind
|
|
131
|
+
if (ts.isIdentifier(node)) return 57;
|
|
132
|
+
if (ts.isStringLiteral(node)) return 58;
|
|
133
|
+
if (ts.isNumericLiteral(node)) return 59;
|
|
134
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) return 60;
|
|
135
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) return 61;
|
|
136
|
+
if (node.kind === ts.SyntaxKind.NullKeyword) return 62;
|
|
137
|
+
if (node.kind === ts.SyntaxKind.UndefinedKeyword) return 63;
|
|
138
|
+
if (node.kind === ts.SyntaxKind.ThisKeyword) return 64;
|
|
139
|
+
if (node.kind === ts.SyntaxKind.SuperKeyword) return 65;
|
|
140
|
+
if (node.kind === ts.SyntaxKind.RegularExpressionLiteral) return 66;
|
|
141
|
+
if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral) return 67;
|
|
142
|
+
if (node.kind === ts.SyntaxKind.TemplateHead) return 68;
|
|
143
|
+
if (node.kind === ts.SyntaxKind.TemplateMiddle) return 69;
|
|
144
|
+
if (node.kind === ts.SyntaxKind.TemplateTail) return 70;
|
|
145
|
+
if (node.kind === ts.SyntaxKind.ComputedPropertyName) return 71;
|
|
146
|
+
|
|
147
|
+
// Default: treat as identifier for any other leaf node
|
|
148
|
+
return 57;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if a node is a syntax type (non-leaf) vs token type (leaf)
|
|
153
|
+
*/
|
|
154
|
+
export function isSyntaxNode(node: ts.Node): boolean {
|
|
155
|
+
return getStateIndex(node) < NUM_SYNTAX;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get state name for debugging
|
|
160
|
+
*/
|
|
161
|
+
export function getStateName(index: number): string {
|
|
162
|
+
if (index < NUM_SYNTAX) return SYNTAX_TYPES[index];
|
|
163
|
+
if (index < NUM_STATES) return TOKEN_TYPES[index - NUM_SYNTAX];
|
|
164
|
+
return "Unknown";
|
|
165
|
+
}
|
|
@@ -15,7 +15,6 @@ import { minimatch } from "minimatch";
|
|
|
15
15
|
export class ArchitectClient {
|
|
16
16
|
constructor(verbose = false) {
|
|
17
17
|
this.config = null;
|
|
18
|
-
this.configPath = null;
|
|
19
18
|
this.isUserConfig = false;
|
|
20
19
|
this.log = verbose
|
|
21
20
|
? (msg) => console.error(`[architect] ${msg}`)
|
|
@@ -47,18 +46,32 @@ export class ArchitectClient {
|
|
|
47
46
|
}
|
|
48
47
|
// Fall back to built-in default
|
|
49
48
|
try {
|
|
49
|
+
// Try multiple possible locations for the default config
|
|
50
|
+
const possibleDefaultPaths = [
|
|
51
|
+
path.join(projectRoot, "default-architect.yaml"),
|
|
52
|
+
path.join(projectRoot, "..", "default-architect.yaml"),
|
|
53
|
+
path.join(process.cwd(), "default-architect.yaml"),
|
|
54
|
+
];
|
|
50
55
|
// Handle both CommonJS and ESM environments
|
|
51
|
-
let currentDir = ".";
|
|
52
56
|
if (typeof __dirname !== "undefined") {
|
|
53
|
-
|
|
57
|
+
possibleDefaultPaths.push(path.join(__dirname, "..", "default-architect.yaml"));
|
|
58
|
+
possibleDefaultPaths.push(path.join(__dirname, "..", "..", "default-architect.yaml"));
|
|
54
59
|
}
|
|
55
|
-
const defaultPath
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
for (const defaultPath of possibleDefaultPaths) {
|
|
61
|
+
try {
|
|
62
|
+
const content = fs.readFileSync(defaultPath, "utf-8");
|
|
63
|
+
this.config = this.parseYaml(content);
|
|
64
|
+
this.configPath = defaultPath;
|
|
65
|
+
this.isUserConfig = false;
|
|
66
|
+
this.log("Using default architect rules (create .pi-lens/architect.yaml to customize)");
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Try next path
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
this.log("No architect config available");
|
|
74
|
+
return false;
|
|
62
75
|
}
|
|
63
76
|
catch {
|
|
64
77
|
this.log("No architect config available");
|
|
@@ -113,6 +126,8 @@ export class ArchitectClient {
|
|
|
113
126
|
pattern: rule.pattern,
|
|
114
127
|
message: check.message,
|
|
115
128
|
line: lineNum,
|
|
129
|
+
fix: check.fix,
|
|
130
|
+
note: check.note,
|
|
116
131
|
});
|
|
117
132
|
// Prevent infinite loop on empty matches
|
|
118
133
|
if (match.index === regex.lastIndex) {
|
|
@@ -209,9 +224,14 @@ export class ArchitectClient {
|
|
|
209
224
|
section = "must";
|
|
210
225
|
continue;
|
|
211
226
|
}
|
|
212
|
-
// Message for current violation
|
|
227
|
+
// Message for current violation (handle nested quotes)
|
|
213
228
|
if (trimmed.startsWith("message:") && violation) {
|
|
214
|
-
|
|
229
|
+
// Match "..." or '...' allowing the other quote type inside
|
|
230
|
+
const dquoteMatch = trimmed.match(/message:\s*"([^"]*)"/);
|
|
231
|
+
const squoteMatch = !dquoteMatch
|
|
232
|
+
? trimmed.match(/message:\s*'([^']*)'/)
|
|
233
|
+
: null;
|
|
234
|
+
const match = dquoteMatch || squoteMatch;
|
|
215
235
|
if (match) {
|
|
216
236
|
violation.message = match[1];
|
|
217
237
|
if (rule) {
|
|
@@ -222,6 +242,30 @@ export class ArchitectClient {
|
|
|
222
242
|
}
|
|
223
243
|
continue;
|
|
224
244
|
}
|
|
245
|
+
// Fix guidance for current violation
|
|
246
|
+
if (trimmed.startsWith("fix:") && violation) {
|
|
247
|
+
const dquoteMatch = trimmed.match(/fix:\s*"([^"]*)"/);
|
|
248
|
+
const squoteMatch = !dquoteMatch
|
|
249
|
+
? trimmed.match(/fix:\s*'([^']*)'/)
|
|
250
|
+
: null;
|
|
251
|
+
const match = dquoteMatch || squoteMatch;
|
|
252
|
+
if (match) {
|
|
253
|
+
violation.fix = match[1];
|
|
254
|
+
}
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
// Note guidance for current violation
|
|
258
|
+
if (trimmed.startsWith("note:") && violation) {
|
|
259
|
+
const dquoteMatch = trimmed.match(/note:\s*"([^"]*)"/);
|
|
260
|
+
const squoteMatch = !dquoteMatch
|
|
261
|
+
? trimmed.match(/note:\s*'([^']*)'/)
|
|
262
|
+
: null;
|
|
263
|
+
const match = dquoteMatch || squoteMatch;
|
|
264
|
+
if (match) {
|
|
265
|
+
violation.note = match[1];
|
|
266
|
+
}
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
225
269
|
// Must items (simple strings)
|
|
226
270
|
if (section === "must" && trimmed.startsWith("- ") && rule) {
|
|
227
271
|
const item = trimmed.slice(2).replace(/^["']|["']$/g, "");
|
|
@@ -19,11 +19,18 @@ export interface ArchitectViolation {
|
|
|
19
19
|
pattern: string;
|
|
20
20
|
message: string;
|
|
21
21
|
line?: number;
|
|
22
|
+
fix?: string;
|
|
23
|
+
note?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export interface ArchitectRule {
|
|
25
27
|
pattern: string;
|
|
26
|
-
must_not?: Array<{
|
|
28
|
+
must_not?: Array<{
|
|
29
|
+
pattern: string;
|
|
30
|
+
message: string;
|
|
31
|
+
fix?: string;
|
|
32
|
+
note?: string;
|
|
33
|
+
}>;
|
|
27
34
|
must?: string[];
|
|
28
35
|
max_lines?: number;
|
|
29
36
|
}
|
|
@@ -44,8 +51,8 @@ export interface FileArchitectResult {
|
|
|
44
51
|
|
|
45
52
|
export class ArchitectClient {
|
|
46
53
|
private config: ArchitectConfig | null = null;
|
|
47
|
-
private configPath: string | null = null;
|
|
48
54
|
private isUserConfig: boolean = false;
|
|
55
|
+
private configPath: string | undefined;
|
|
49
56
|
private log: (msg: string) => void;
|
|
50
57
|
|
|
51
58
|
constructor(verbose = false) {
|
|
@@ -81,20 +88,40 @@ export class ArchitectClient {
|
|
|
81
88
|
|
|
82
89
|
// Fall back to built-in default
|
|
83
90
|
try {
|
|
91
|
+
// Try multiple possible locations for the default config
|
|
92
|
+
const possibleDefaultPaths = [
|
|
93
|
+
path.join(projectRoot, "default-architect.yaml"),
|
|
94
|
+
path.join(projectRoot, "..", "default-architect.yaml"),
|
|
95
|
+
path.join(process.cwd(), "default-architect.yaml"),
|
|
96
|
+
];
|
|
97
|
+
|
|
84
98
|
// Handle both CommonJS and ESM environments
|
|
85
|
-
let currentDir = ".";
|
|
86
99
|
if (typeof __dirname !== "undefined") {
|
|
87
|
-
|
|
100
|
+
possibleDefaultPaths.push(
|
|
101
|
+
path.join(__dirname, "..", "default-architect.yaml"),
|
|
102
|
+
);
|
|
103
|
+
possibleDefaultPaths.push(
|
|
104
|
+
path.join(__dirname, "..", "..", "default-architect.yaml"),
|
|
105
|
+
);
|
|
88
106
|
}
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
|
|
108
|
+
for (const defaultPath of possibleDefaultPaths) {
|
|
109
|
+
try {
|
|
110
|
+
const content = fs.readFileSync(defaultPath, "utf-8");
|
|
111
|
+
this.config = this.parseYaml(content);
|
|
112
|
+
this.configPath = defaultPath;
|
|
113
|
+
this.isUserConfig = false;
|
|
114
|
+
this.log(
|
|
115
|
+
"Using default architect rules (create .pi-lens/architect.yaml to customize)",
|
|
116
|
+
);
|
|
117
|
+
return true;
|
|
118
|
+
} catch {
|
|
119
|
+
// Try next path
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.log("No architect config available");
|
|
124
|
+
return false;
|
|
98
125
|
} catch {
|
|
99
126
|
this.log("No architect config available");
|
|
100
127
|
return false;
|
|
@@ -154,6 +181,8 @@ export class ArchitectClient {
|
|
|
154
181
|
pattern: rule.pattern,
|
|
155
182
|
message: check.message,
|
|
156
183
|
line: lineNum,
|
|
184
|
+
fix: check.fix,
|
|
185
|
+
note: check.note,
|
|
157
186
|
});
|
|
158
187
|
|
|
159
188
|
// Prevent infinite loop on empty matches
|
|
@@ -226,7 +255,12 @@ export class ArchitectClient {
|
|
|
226
255
|
const lines = block.split("\n");
|
|
227
256
|
let rule: ArchitectRule | null = null;
|
|
228
257
|
let section: "must_not" | "must" | null = null;
|
|
229
|
-
let violation: {
|
|
258
|
+
let violation: {
|
|
259
|
+
pattern: string;
|
|
260
|
+
message: string;
|
|
261
|
+
fix?: string;
|
|
262
|
+
note?: string;
|
|
263
|
+
} | null = null;
|
|
230
264
|
|
|
231
265
|
for (const line of lines) {
|
|
232
266
|
const trimmed = line.trim();
|
|
@@ -269,9 +303,14 @@ export class ArchitectClient {
|
|
|
269
303
|
continue;
|
|
270
304
|
}
|
|
271
305
|
|
|
272
|
-
// Message for current violation
|
|
306
|
+
// Message for current violation (handle nested quotes)
|
|
273
307
|
if (trimmed.startsWith("message:") && violation) {
|
|
274
|
-
|
|
308
|
+
// Match "..." or '...' allowing the other quote type inside
|
|
309
|
+
const dquoteMatch = trimmed.match(/message:\s*"([^"]*)"/);
|
|
310
|
+
const squoteMatch = !dquoteMatch
|
|
311
|
+
? trimmed.match(/message:\s*'([^']*)'/)
|
|
312
|
+
: null;
|
|
313
|
+
const match = dquoteMatch || squoteMatch;
|
|
275
314
|
if (match) {
|
|
276
315
|
violation.message = match[1];
|
|
277
316
|
if (rule) {
|
|
@@ -283,6 +322,32 @@ export class ArchitectClient {
|
|
|
283
322
|
continue;
|
|
284
323
|
}
|
|
285
324
|
|
|
325
|
+
// Fix guidance for current violation
|
|
326
|
+
if (trimmed.startsWith("fix:") && violation) {
|
|
327
|
+
const dquoteMatch = trimmed.match(/fix:\s*"([^"]*)"/);
|
|
328
|
+
const squoteMatch = !dquoteMatch
|
|
329
|
+
? trimmed.match(/fix:\s*'([^']*)'/)
|
|
330
|
+
: null;
|
|
331
|
+
const match = dquoteMatch || squoteMatch;
|
|
332
|
+
if (match) {
|
|
333
|
+
violation.fix = match[1];
|
|
334
|
+
}
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Note guidance for current violation
|
|
339
|
+
if (trimmed.startsWith("note:") && violation) {
|
|
340
|
+
const dquoteMatch = trimmed.match(/note:\s*"([^"]*)"/);
|
|
341
|
+
const squoteMatch = !dquoteMatch
|
|
342
|
+
? trimmed.match(/note:\s*'([^']*)'/)
|
|
343
|
+
: null;
|
|
344
|
+
const match = dquoteMatch || squoteMatch;
|
|
345
|
+
if (match) {
|
|
346
|
+
violation.note = match[1];
|
|
347
|
+
}
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
|
|
286
351
|
// Must items (simple strings)
|
|
287
352
|
if (section === "must" && trimmed.startsWith("- ") && rule) {
|
|
288
353
|
const item = trimmed.slice(2).replace(/^["']|["']$/g, "");
|
|
@@ -182,7 +182,7 @@ message: found
|
|
|
182
182
|
const result = spawnSync("npx", ["sg", "scan", "--config", configPath, "--json", absolutePath], {
|
|
183
183
|
encoding: "utf-8",
|
|
184
184
|
timeout: 15000,
|
|
185
|
-
shell:
|
|
185
|
+
shell: process.platform === "win32",
|
|
186
186
|
});
|
|
187
187
|
// ast-grep exits 1 when it finds issues
|
|
188
188
|
const output = result.stdout || result.stderr || "";
|
|
@@ -192,7 +192,7 @@ message: found
|
|
|
192
192
|
return parser.parseOutput(output, absolutePath);
|
|
193
193
|
}
|
|
194
194
|
catch (err) {
|
|
195
|
-
this.log(`Scan error: ${err.message}`);
|
|
195
|
+
this.log(`Scan error: ${err instanceof Error ? err.message : String(err)}`);
|
|
196
196
|
return [];
|
|
197
197
|
}
|
|
198
198
|
}
|