@futdevpro/dynamo-eslint 1.20.3 → 1.20.5

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.
Files changed (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +304 -304
  3. package/build/plugin/rules/ts/no-as-cast.d.ts.map +1 -1
  4. package/build/plugin/rules/ts/no-as-cast.js +43 -0
  5. package/build/plugin/rules/ts/no-as-cast.js.map +1 -1
  6. package/package.json +14 -7
  7. package/.c8rc.json +0 -26
  8. package/.cursor/rules/__assistant_guide.mdc +0 -30
  9. package/.cursor/rules/__main.mdc +0 -64
  10. package/.cursor/rules/_ag_backend-structure.mdc +0 -86
  11. package/.cursor/rules/_ag_backend.mdc +0 -16
  12. package/.cursor/rules/_ag_debug.mdc +0 -8
  13. package/.cursor/rules/_ag_documentation_writing_rules.mdc +0 -372
  14. package/.cursor/rules/_ag_file-refactoring.mdc +0 -113
  15. package/.cursor/rules/_ag_fixes_rules.mdc +0 -6
  16. package/.cursor/rules/_ag_frontend-structure.mdc +0 -87
  17. package/.cursor/rules/_ag_frontend.mdc +0 -40
  18. package/.cursor/rules/_ag_import-rules.mdc +0 -45
  19. package/.cursor/rules/_ag_naming.mdc +0 -116
  20. package/.cursor/rules/_ag_running_commands.mdc +0 -5
  21. package/.cursor/rules/_ag_server-controller.mdc +0 -6
  22. package/.cursor/rules/_ag_should-be.mdc +0 -7
  23. package/.cursor/rules/_ag_swearing.mdc +0 -47
  24. package/.cursor/rules/ai_development_guide.md +0 -61
  25. package/.cursor/rules/ai_directives.md +0 -114
  26. package/.cursor/rules/cursor-rules.md +0 -160
  27. package/.cursor/rules/default-command.mdc +0 -465
  28. package/.cursor/rules/error_code_pattern.md +0 -40
  29. package/.cursor/rules/saved rule mcp server use.md +0 -16
  30. package/.dynamo/pipeline.cicd.config.json +0 -184
  31. package/.dynamo/version-bump.config.json +0 -5
  32. package/.eslintrc.json +0 -4
  33. package/.github/workflows/main.yml +0 -436
  34. package/.husky/pre-commit +0 -2
  35. package/.vscode/settings.json +0 -11
  36. package/__documentations/2026-04-18-ccap-review-integration.md +0 -173
  37. package/__documentations/2026-08-18-bfr-ctm-005-eslint9-validator-report.md +0 -45
  38. package/__documentations/2026-08-22-angular-20-phase2-release.md +0 -83
  39. package/eslint.config.js +0 -15
  40. package/pnpm-workspace.yaml +0 -2
  41. package/samples/.vscode/settings.json +0 -13
  42. package/samples/base/.eslintrc.json +0 -6
  43. package/samples/base/eslint.config.js +0 -3
  44. package/samples/fsm/.eslintrc.json +0 -4
  45. package/samples/fsm/eslint.config.js +0 -3
  46. package/samples/ngx/.eslintrc.json +0 -6
  47. package/samples/ngx/eslint.config.js +0 -3
  48. package/samples/ngx-package/.eslintrc.json +0 -4
  49. package/samples/ngx-package/eslint.config.js +0 -3
  50. package/samples/nts/.eslintrc.json +0 -6
  51. package/samples/nts/eslint.config.js +0 -3
  52. package/samples/nts-package/.eslintrc.json +0 -4
  53. package/samples/nts-package/eslint.config.js +0 -3
  54. package/samples/package.json.example +0 -22
  55. package/samples/poc-sample.ts +0 -38
  56. package/samples/poc-violations.ts +0 -54
  57. package/scripts/run-coverage-tests.js +0 -24
  58. package/spec/support/helpers/ts-node-helper.js +0 -9
  59. package/spec/support/jasmine.coverage.json +0 -23
  60. package/spec/support/jasmine.json +0 -24
  61. package/src/configs/angular20-compatibility.spec.ts +0 -73
  62. package/src/configs/base.ts +0 -156
  63. package/src/configs/fsm.ts +0 -10
  64. package/src/configs/ngx-package.ts +0 -10
  65. package/src/configs/ngx.ts +0 -93
  66. package/src/configs/nts-package.ts +0 -20
  67. package/src/configs/nts.ts +0 -34
  68. package/src/index.ts +0 -4
  69. package/src/plugin/index.ts +0 -86
  70. package/src/plugin/rules/angular/angular-for-track-logic.spec.ts +0 -44
  71. package/src/plugin/rules/angular/angular-for-track-logic.ts +0 -88
  72. package/src/plugin/rules/angular/effect-signal-loop.spec.ts +0 -89
  73. package/src/plugin/rules/angular/effect-signal-loop.ts +0 -125
  74. package/src/plugin/rules/angular/no-async-ngoninit.spec.ts +0 -50
  75. package/src/plugin/rules/angular/no-async-ngoninit.ts +0 -43
  76. package/src/plugin/rules/angular/no-component-direct-api.spec.ts +0 -78
  77. package/src/plugin/rules/angular/no-component-direct-api.ts +0 -82
  78. package/src/plugin/rules/angular/no-method-call-in-template.spec.ts +0 -63
  79. package/src/plugin/rules/angular/no-method-call-in-template.ts +0 -89
  80. package/src/plugin/rules/angular/no-ngfor-directive.spec.ts +0 -44
  81. package/src/plugin/rules/angular/no-ngfor-directive.ts +0 -62
  82. package/src/plugin/rules/angular/no-ngif-directive.spec.ts +0 -44
  83. package/src/plugin/rules/angular/no-ngif-directive.ts +0 -62
  84. package/src/plugin/rules/explicit-types.spec.ts +0 -190
  85. package/src/plugin/rules/explicit-types.ts +0 -186
  86. package/src/plugin/rules/import/import-order.spec.ts +0 -219
  87. package/src/plugin/rules/import/import-order.ts +0 -197
  88. package/src/plugin/rules/import/no-import-type.spec.ts +0 -69
  89. package/src/plugin/rules/import/no-import-type.ts +0 -46
  90. package/src/plugin/rules/import/no-js-import.spec.ts +0 -82
  91. package/src/plugin/rules/import/no-js-import.ts +0 -45
  92. package/src/plugin/rules/naming-patterns.spec.ts +0 -189
  93. package/src/plugin/rules/naming-patterns.ts +0 -426
  94. package/src/plugin/rules/no-getter-logic.spec.ts +0 -591
  95. package/src/plugin/rules/no-getter-logic.ts +0 -220
  96. package/src/plugin/rules/prefer-enum-over-string-union.spec.ts +0 -583
  97. package/src/plugin/rules/prefer-enum-over-string-union.ts +0 -333
  98. package/src/plugin/rules/prefer-interface-over-duplicate-types.spec.ts +0 -404
  99. package/src/plugin/rules/prefer-interface-over-duplicate-types.ts +0 -314
  100. package/src/plugin/rules/require-jsdoc-description.spec.ts +0 -779
  101. package/src/plugin/rules/require-jsdoc-description.ts +0 -572
  102. package/src/plugin/rules/require-test-description-prefix.spec.ts +0 -459
  103. package/src/plugin/rules/require-test-description-prefix.ts +0 -154
  104. package/src/plugin/rules/ts/data-model-extends.spec.ts +0 -84
  105. package/src/plugin/rules/ts/data-model-extends.ts +0 -100
  106. package/src/plugin/rules/ts/no-any-type.spec.ts +0 -28
  107. package/src/plugin/rules/ts/no-any-type.ts +0 -36
  108. package/src/plugin/rules/ts/no-as-cast.spec.ts +0 -51
  109. package/src/plugin/rules/ts/no-as-cast.ts +0 -51
  110. package/src/plugin/rules/ts/no-dynamic-imports.spec.ts +0 -54
  111. package/src/plugin/rules/ts/no-dynamic-imports.ts +0 -49
  112. package/src/plugin/rules/ts/no-native-browser-dialogs.spec.ts +0 -54
  113. package/src/plugin/rules/ts/no-native-browser-dialogs.ts +0 -84
  114. package/src/plugin/rules/ts/no-plain-function-export.spec.ts +0 -72
  115. package/src/plugin/rules/ts/no-plain-function-export.ts +0 -73
  116. package/src/plugin/rules/ts/one-export-per-file.spec.ts +0 -64
  117. package/src/plugin/rules/ts/one-export-per-file.ts +0 -77
  118. package/src/scripts/dynamo-fix.ts +0 -172
  119. package/src/scripts/eslintrc-audit.ts +0 -116
  120. package/src/scripts/fix-return-types.spec.ts +0 -65
  121. package/src/scripts/fix-return-types.ts +0 -289
  122. package/src/scripts/validate-imports.ts +0 -292
  123. package/src/scripts/validate-naming.ts +0 -213
  124. package/src/scripts/validator-cli.integration.spec.ts +0 -99
  125. package/tsconfig.json +0 -32
@@ -1,62 +0,0 @@
1
- import { Rule } from 'eslint';
2
-
3
- /** `*ngFor` használat detektálása HTML template-ekben. */
4
- const NGFOR_REGEX: RegExp = /\*ngFor/g;
5
-
6
- /**
7
- * Adott offset alapján a sor és oszlop kiszámítása az alap szövegből.
8
- */
9
- function computeLoc(text: string, index: number): { line: number; column: number } {
10
- const before: string = text.substring(0, index);
11
- const newlineMatches: RegExpMatchArray | null = before.match(/\n/g);
12
- const line: number = (newlineMatches ? newlineMatches.length : 0) + 1;
13
- const lastNewline: number = before.lastIndexOf('\n');
14
- const column: number = lastNewline === -1 ? index : index - lastNewline - 1;
15
- return { line: line, column: column };
16
- }
17
-
18
- /**
19
- * No-ngFor-directive szabály: Angular template-ekben `*ngFor` helyett `@for` szintaxist használj.
20
- * CCAP "no-ngfor-directive" review ESLint template-text-scan portja.
21
- */
22
- const rule: Rule.RuleModule = {
23
- meta: {
24
- type: 'suggestion',
25
- docs: {
26
- description: 'Forbid `*ngFor` directive in Angular templates; use `@for` block syntax instead.',
27
- recommended: true,
28
- },
29
- schema: [],
30
- messages: {
31
- noNgFor: '`*ngFor` direktíva tilos. Használj `@for` block szintaxist.',
32
- },
33
- },
34
- create(context: Rule.RuleContext): Rule.RuleListener {
35
- const filename: string = context.filename ?? '';
36
- if (!filename.endsWith('.html')) {
37
- return {};
38
- }
39
- const text: string = context.sourceCode.text ?? '';
40
-
41
- return {
42
- Program(): void {
43
- try {
44
- const localRegex: RegExp = new RegExp(NGFOR_REGEX.source, 'g');
45
- let match: RegExpExecArray | null = localRegex.exec(text);
46
- while (match !== null) {
47
- const loc: { line: number; column: number } = computeLoc(text, match.index);
48
- context.report({
49
- loc: { start: loc, end: { line: loc.line, column: loc.column + match[0].length } },
50
- messageId: 'noNgFor',
51
- });
52
- match = localRegex.exec(text);
53
- }
54
- } catch (error) {
55
- console.error('[no-ngfor-directive] Error in Program visitor:', error);
56
- }
57
- },
58
- };
59
- },
60
- };
61
-
62
- export default rule;
@@ -1,44 +0,0 @@
1
- import noNgIfDirectiveRule from './no-ngif-directive';
2
-
3
- describe('| no-ngif-directive', () => {
4
- it('| should be a valid ESLint rule', () => {
5
- expect(noNgIfDirectiveRule.meta?.type).toBe('suggestion');
6
- expect(noNgIfDirectiveRule.meta?.messages?.noNgIf).toBeDefined();
7
- });
8
-
9
- it('| should skip non-html files', () => {
10
- const mockContext: any = { filename: '/x/foo.ts', report: () => {}, options: [], sourceCode: { text: '' } };
11
- const result: any = noNgIfDirectiveRule.create(mockContext);
12
- expect(result.Program).toBeUndefined();
13
- });
14
-
15
- it('| should report `*ngIf`', () => {
16
- let reportCount: number = 0;
17
- const mockContext: any = {
18
- filename: '/x/user.component.html',
19
- report: (options: any): void => {
20
- if (options.messageId === 'noNgIf') {
21
- reportCount += 1;
22
- }
23
- },
24
- options: [],
25
- sourceCode: { text: '<div *ngIf="condition">X</div>' },
26
- };
27
- const rule: any = noNgIfDirectiveRule.create(mockContext);
28
- rule.Program();
29
- expect(reportCount).toBeGreaterThan(0);
30
- });
31
-
32
- it('| should NOT report `@if` block', () => {
33
- let reportCount: number = 0;
34
- const mockContext: any = {
35
- filename: '/x/user.component.html',
36
- report: (): void => { reportCount += 1; },
37
- options: [],
38
- sourceCode: { text: '@if (condition) { <div>X</div> }' },
39
- };
40
- const rule: any = noNgIfDirectiveRule.create(mockContext);
41
- rule.Program();
42
- expect(reportCount).toBe(0);
43
- });
44
- });
@@ -1,62 +0,0 @@
1
- import { Rule } from 'eslint';
2
-
3
- /** `*ngIf` használat detektálása HTML template-ekben. */
4
- const NGIF_REGEX: RegExp = /\*ngIf/g;
5
-
6
- /**
7
- * Adott offset alapján a sor és oszlop kiszámítása az alap szövegből.
8
- */
9
- function computeLoc(text: string, index: number): { line: number; column: number } {
10
- const before: string = text.substring(0, index);
11
- const newlineMatches: RegExpMatchArray | null = before.match(/\n/g);
12
- const line: number = (newlineMatches ? newlineMatches.length : 0) + 1;
13
- const lastNewline: number = before.lastIndexOf('\n');
14
- const column: number = lastNewline === -1 ? index : index - lastNewline - 1;
15
- return { line: line, column: column };
16
- }
17
-
18
- /**
19
- * No-ngIf-directive szabály: Angular template-ekben `*ngIf` helyett `@if` szintaxist használj.
20
- * CCAP "no-ngif-directive" review ESLint template-text-scan portja.
21
- */
22
- const rule: Rule.RuleModule = {
23
- meta: {
24
- type: 'suggestion',
25
- docs: {
26
- description: 'Forbid `*ngIf` directive in Angular templates; use `@if` block syntax instead.',
27
- recommended: true,
28
- },
29
- schema: [],
30
- messages: {
31
- noNgIf: '`*ngIf` direktíva tilos. Használj `@if` block szintaxist.',
32
- },
33
- },
34
- create(context: Rule.RuleContext): Rule.RuleListener {
35
- const filename: string = context.filename ?? '';
36
- if (!filename.endsWith('.html')) {
37
- return {};
38
- }
39
- const text: string = context.sourceCode.text ?? '';
40
-
41
- return {
42
- Program(): void {
43
- try {
44
- const localRegex: RegExp = new RegExp(NGIF_REGEX.source, 'g');
45
- let match: RegExpExecArray | null = localRegex.exec(text);
46
- while (match !== null) {
47
- const loc: { line: number; column: number } = computeLoc(text, match.index);
48
- context.report({
49
- loc: { start: loc, end: { line: loc.line, column: loc.column + match[0].length } },
50
- messageId: 'noNgIf',
51
- });
52
- match = localRegex.exec(text);
53
- }
54
- } catch (error) {
55
- console.error('[no-ngif-directive] Error in Program visitor:', error);
56
- }
57
- },
58
- };
59
- },
60
- };
61
-
62
- export default rule;
@@ -1,190 +0,0 @@
1
- import explicitTypesRule from './explicit-types';
2
-
3
- describe('| explicit-types', () => {
4
- it('| should be a valid ESLint rule', () => {
5
- expect(explicitTypesRule.meta?.type).toBe('suggestion');
6
- expect(explicitTypesRule.meta?.docs?.description).toContain('explicit type annotations');
7
- });
8
-
9
- it('| should have create function that returns visitor object', () => {
10
- const mockContext = {
11
- report: () => {},
12
- } as any;
13
-
14
- const result = explicitTypesRule.create(mockContext);
15
-
16
- expect(typeof result).toBe('object');
17
- expect(typeof result.FunctionDeclaration).toBe('function');
18
- expect(typeof result.ArrowFunctionExpression).toBe('function');
19
- expect(typeof result.VariableDeclarator).toBe('function');
20
- expect(typeof result.PropertyDefinition).toBe('function');
21
- });
22
-
23
- it('| should report missing return types on function declarations', () => {
24
- const mockContext = {
25
- report: (options: any) => {
26
- expect(options.messageId).toBe('missingReturnType');
27
- expect(options.data.name).toBe('testFunction');
28
- },
29
- } as any;
30
-
31
- const mockNode = {
32
- type: 'FunctionDeclaration' as const,
33
- id: { name: 'testFunction' },
34
- returnType: null,
35
- params: [],
36
- } as any;
37
-
38
- const rule = explicitTypesRule.create(mockContext);
39
- rule.FunctionDeclaration(mockNode);
40
- });
41
-
42
- it('| should not report when function has return type', () => {
43
- const mockContext = {
44
- report: (options: any) => {
45
- fail('Should not report when function has return type');
46
- },
47
- } as any;
48
-
49
- const mockNode = {
50
- type: 'FunctionDeclaration' as const,
51
- id: { name: 'testFunction' },
52
- returnType: { type: 'TSTypeAnnotation' },
53
- params: [],
54
- } as any;
55
-
56
- const rule = explicitTypesRule.create(mockContext);
57
- rule.FunctionDeclaration(mockNode);
58
- });
59
-
60
- it('| should report missing return types on arrow functions', () => {
61
- const mockContext = {
62
- report: (options: any) => {
63
- expect(options.messageId).toBe('missingArrowReturnType');
64
- },
65
- } as any;
66
-
67
- const mockNode = {
68
- type: 'ArrowFunctionExpression' as const,
69
- returnType: null,
70
- params: [],
71
- } as any;
72
-
73
- const rule = explicitTypesRule.create(mockContext);
74
- rule.ArrowFunctionExpression(mockNode);
75
- });
76
-
77
- it('| should report missing types on variable declarations', () => {
78
- const mockContext = {
79
- report: (options: any) => {
80
- expect(options.messageId).toBe('missingVariableType');
81
- expect(options.data.name).toBe('testVar');
82
- },
83
- } as any;
84
-
85
- const mockNode = {
86
- type: 'VariableDeclarator' as const,
87
- id: { name: 'testVar', typeAnnotation: null },
88
- init: null,
89
- } as any;
90
-
91
- const rule = explicitTypesRule.create(mockContext);
92
- rule.VariableDeclarator(mockNode);
93
- });
94
-
95
- it('| should not report when variable has type annotation', () => {
96
- const mockContext = {
97
- report: (options: any) => {
98
- fail('Should not report when variable has type annotation');
99
- },
100
- } as any;
101
-
102
- const mockNode = {
103
- type: 'VariableDeclarator' as const,
104
- id: { name: 'testVar', typeAnnotation: { type: 'TSTypeAnnotation' } },
105
- init: null,
106
- } as any;
107
-
108
- const rule = explicitTypesRule.create(mockContext);
109
- rule.VariableDeclarator(mockNode);
110
- });
111
-
112
- it('| should not report when variable has typed initializer', () => {
113
- const mockContext = {
114
- report: (options: any) => {
115
- fail('Should not report when variable has typed initializer');
116
- },
117
- } as any;
118
-
119
- const mockNode = {
120
- type: 'VariableDeclarator' as const,
121
- id: { name: 'testVar', typeAnnotation: null },
122
- init: { type: 'CallExpression' },
123
- } as any;
124
-
125
- const rule = explicitTypesRule.create(mockContext);
126
- rule.VariableDeclarator(mockNode);
127
- });
128
-
129
- it('| should report missing parameter types', () => {
130
- const mockContext = {
131
- report: (options: any) => {
132
- expect(options.messageId).toBe('missingParameterType');
133
- expect(options.data.name).toBe('param');
134
- },
135
- } as any;
136
-
137
- const mockNode = {
138
- type: 'FunctionDeclaration' as const,
139
- id: { name: 'testFunction' },
140
- returnType: { type: 'TSTypeAnnotation' },
141
- params: [
142
- { type: 'Identifier', name: 'param', typeAnnotation: null }
143
- ],
144
- } as any;
145
-
146
- const rule = explicitTypesRule.create(mockContext);
147
- rule.FunctionDeclaration(mockNode);
148
- });
149
-
150
- it('| should report missing class property types', () => {
151
- const mockContext = {
152
- report: (options: any) => {
153
- expect(options.messageId).toBe('missingPropertyType');
154
- expect(options.data.name).toBe('property');
155
- },
156
- } as any;
157
-
158
- const mockNode = {
159
- type: 'PropertyDefinition' as const,
160
- key: { name: 'property' },
161
- typeAnnotation: null,
162
- value: null,
163
- } as any;
164
-
165
- const rule = explicitTypesRule.create(mockContext);
166
- rule.PropertyDefinition(mockNode);
167
- });
168
-
169
- it('| should report missing destructuring types', () => {
170
- const mockContext = {
171
- report: (options: any) => {
172
- expect(options.messageId).toBe('missingDestructuringType');
173
- },
174
- } as any;
175
-
176
- const objectPatternNode = {
177
- type: 'ObjectPattern' as const,
178
- typeAnnotation: null,
179
- } as any;
180
-
181
- const arrayPatternNode = {
182
- type: 'ArrayPattern' as const,
183
- typeAnnotation: null,
184
- } as any;
185
-
186
- const rule = explicitTypesRule.create(mockContext);
187
- rule.ObjectPattern(objectPatternNode);
188
- rule.ArrayPattern(arrayPatternNode);
189
- });
190
- });
@@ -1,186 +0,0 @@
1
- import { Rule } from 'eslint';
2
-
3
- const rule: Rule.RuleModule = {
4
- meta: {
5
- type: 'suggestion',
6
- docs: {
7
- description: 'Enforce explicit type annotations on all TypeScript declarations',
8
- recommended: true,
9
- },
10
- schema: [],
11
- messages: {
12
- missingReturnType: 'Function "{{name}}" must have an explicit return type annotation.',
13
- missingArrowReturnType: 'Arrow function must have an explicit return type annotation.',
14
- missingVariableType: 'Variable "{{name}}" must have an explicit type annotation.',
15
- missingParameterType: 'Parameter "{{name}}" must have an explicit type annotation.',
16
- missingPropertyType: 'Class property "{{name}}" must have an explicit type annotation.',
17
- missingDestructuringType: 'Destructuring assignment must have explicit type annotations.',
18
- },
19
- },
20
- create(context) {
21
- return {
22
- // Function declarations
23
- FunctionDeclaration(node: any) {
24
- try {
25
- // Check return type
26
- if (!node.returnType) {
27
- context.report({
28
- node: node.id || node, // Report on function name if available
29
- messageId: 'missingReturnType',
30
- data: { name: node.id?.name || 'anonymous' },
31
- });
32
- }
33
-
34
- // Check function parameters with defensive checks
35
- if (node.params && Array.isArray(node.params)) {
36
- node.params.forEach((param: any) => {
37
- try {
38
- if (param && param.type === 'Identifier' && !param.typeAnnotation) {
39
- context.report({
40
- node: param,
41
- messageId: 'missingParameterType',
42
- data: { name: param.name || 'unknown' },
43
- });
44
- }
45
- } catch (paramError) {
46
- console.error('[explicit-types] Error processing function parameter:', paramError);
47
- }
48
- });
49
- }
50
- } catch (error) {
51
- console.error('[explicit-types] Error in FunctionDeclaration visitor:', error);
52
- }
53
- },
54
-
55
- // Arrow functions
56
- ArrowFunctionExpression(node: any) {
57
- try {
58
- // Check return type
59
- if (!node.returnType) {
60
- context.report({
61
- node: node.params.length > 0 ? node.params[0] : node, // Report on first param or node
62
- messageId: 'missingArrowReturnType',
63
- });
64
- }
65
-
66
- // Check arrow function parameters with defensive checks
67
- if (node.params && Array.isArray(node.params)) {
68
- node.params.forEach((param: any) => {
69
- try {
70
- if (param && param.type === 'Identifier' && !param.typeAnnotation) {
71
- context.report({
72
- node: param,
73
- messageId: 'missingParameterType',
74
- data: { name: param.name || 'unknown' },
75
- });
76
- }
77
- } catch (paramError) {
78
- console.error('[explicit-types] Error processing arrow function parameter:', paramError);
79
- }
80
- });
81
- }
82
- } catch (error) {
83
- console.error('[explicit-types] Error in ArrowFunctionExpression visitor:', error);
84
- }
85
- },
86
-
87
- // Variable declarations
88
- VariableDeclarator(node: any) {
89
- try {
90
- // Defensive check for node.id
91
- if (!node.id) {
92
- return;
93
- }
94
-
95
- if (!node.id.typeAnnotation) {
96
- // Check if this variable is declared in a for loop
97
- let isInForLoop = false;
98
- let parent = node.parent;
99
-
100
- while (parent) {
101
- if (parent.type === 'ForStatement' || parent.type === 'ForInStatement' || parent.type === 'ForOfStatement') {
102
- isInForLoop = true;
103
- break;
104
- }
105
- parent = parent.parent;
106
- }
107
-
108
- // Skip if variable is in a for loop
109
- if (isInForLoop) {
110
- return;
111
- }
112
-
113
- // Skip if variable is initialized with a typed value that can be inferred
114
- const hasTypedInitializer = node.init && (
115
- node.init.type === 'CallExpression' ||
116
- node.init.type === 'NewExpression' ||
117
- node.init.type === 'ArrayExpression' ||
118
- node.init.type === 'ObjectExpression' ||
119
- node.init.type === 'Literal'
120
- );
121
-
122
- if (!hasTypedInitializer) {
123
- context.report({
124
- node: node.id,
125
- messageId: 'missingVariableType',
126
- data: { name: (node.id as any)?.name || 'destructured' },
127
- });
128
- }
129
- }
130
- } catch (error) {
131
- console.error('[explicit-types] Error in VariableDeclarator visitor:', error);
132
- }
133
- },
134
-
135
- // Class properties
136
- PropertyDefinition(node: any) {
137
- try {
138
- // Defensive check for node.key
139
- if (!node.key) {
140
- return;
141
- }
142
-
143
- if (!node.typeAnnotation && !node.value) {
144
- context.report({
145
- node: node.key,
146
- messageId: 'missingPropertyType',
147
- data: { name: (node.key as any)?.name || 'computed' },
148
- });
149
- }
150
- } catch (error) {
151
- console.error('[explicit-types] Error in PropertyDefinition visitor:', error);
152
- }
153
- },
154
-
155
- // Object destructuring
156
- ObjectPattern(node: any) {
157
- try {
158
- if (!node.typeAnnotation) {
159
- context.report({
160
- node,
161
- messageId: 'missingDestructuringType',
162
- });
163
- }
164
- } catch (error) {
165
- console.error('[explicit-types] Error in ObjectPattern visitor:', error);
166
- }
167
- },
168
-
169
- // Array destructuring
170
- ArrayPattern(node: any) {
171
- try {
172
- if (!node.typeAnnotation) {
173
- context.report({
174
- node,
175
- messageId: 'missingDestructuringType',
176
- });
177
- }
178
- } catch (error) {
179
- console.error('[explicit-types] Error in ArrayPattern visitor:', error);
180
- }
181
- },
182
- };
183
- },
184
- };
185
-
186
- export default rule;