@silvestv/migration-planificator 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.
Files changed (122) hide show
  1. package/LICENSE +96 -0
  2. package/README.fr.md +359 -0
  3. package/README.md +360 -0
  4. package/SECURITY.md +187 -0
  5. package/dist/client.bundle.js +357 -0
  6. package/dist/src/core/app-analyzer.js +134 -0
  7. package/dist/src/core/ast/matchers/html/html-attribute-matcher.js +86 -0
  8. package/dist/src/core/ast/matchers/html/html-component-matcher.js +40 -0
  9. package/dist/src/core/ast/matchers/html/html-element-matcher.js +54 -0
  10. package/dist/src/core/ast/matchers/html/html-parser.js +58 -0
  11. package/dist/src/core/ast/matchers/html/html-pipe-matcher.js +95 -0
  12. package/dist/src/core/ast/matchers/html/html-text-matcher.js +53 -0
  13. package/dist/src/core/ast/matchers/html/index.js +118 -0
  14. package/dist/src/core/ast/matchers/index.js +377 -0
  15. package/dist/src/core/ast/matchers/ts/collection-matcher.js +51 -0
  16. package/dist/src/core/ast/matchers/ts/context-matcher.js +275 -0
  17. package/dist/src/core/ast/matchers/ts/decorator-matcher.js +465 -0
  18. package/dist/src/core/ast/matchers/ts/expression-matcher.js +237 -0
  19. package/dist/src/core/ast/matchers/ts/file-matcher.js +97 -0
  20. package/dist/src/core/ast/matchers/ts/hierarchy-matcher.js +172 -0
  21. package/dist/src/core/ast/matchers/ts/import-matcher.js +39 -0
  22. package/dist/src/core/ast/matchers/ts/index.js +53 -0
  23. package/dist/src/core/ast/matchers/ts/node-matcher.js +156 -0
  24. package/dist/src/core/ast/matchers/ts/symbol-matcher.js +281 -0
  25. package/dist/src/core/ast/matchers/ts/type-matcher.js +207 -0
  26. package/dist/src/core/ast/matchers/utils/matcher-helpers.js +37 -0
  27. package/dist/src/core/ast/scanner-ast.js +444 -0
  28. package/dist/src/core/project-detector.js +196 -0
  29. package/dist/src/core/project-strategy/index.js +9 -0
  30. package/dist/src/core/project-strategy/nx-strategy.js +130 -0
  31. package/dist/src/core/project-strategy/project-strategy.interface.js +2 -0
  32. package/dist/src/core/project-strategy/standalone-strategy.js +74 -0
  33. package/dist/src/core/project-strategy/strategy-factory.js +15 -0
  34. package/dist/src/core/rules-loader.js +89 -0
  35. package/dist/src/core/scan-reporter.js +316 -0
  36. package/dist/src/core/scanner-delta.js +339 -0
  37. package/dist/src/core/scanner-orchestrator.js +266 -0
  38. package/dist/src/core/scanner-regex.js +298 -0
  39. package/dist/src/core/workload/calculator.js +82 -0
  40. package/dist/src/core/workload/constants.js +15 -0
  41. package/dist/src/core/workload/grouping.js +18 -0
  42. package/dist/src/core/workload/hierarchy-calculator.js +127 -0
  43. package/dist/src/core/workload/index.js +11 -0
  44. package/dist/src/core/workload/metadata.js +20 -0
  45. package/dist/src/core/workload/special-workload.js +101 -0
  46. package/dist/src/core/workload/target-resolver.js +34 -0
  47. package/dist/src/data/angular-migration-rules.json +2337 -0
  48. package/dist/src/data/markdown/angular-migration-17-18.md +408 -0
  49. package/dist/src/data/markdown/angular-migration-18-19.md +600 -0
  50. package/dist/src/data/markdown/angular-migration-19-20.md +521 -0
  51. package/dist/src/data/rules/rearchitecture/rearchitecture-rules.json +66 -0
  52. package/dist/src/data/rules/to18/rules-18-obligatoire.json +374 -0
  53. package/dist/src/data/rules/to18/rules-18-optionnelle.json +188 -0
  54. package/dist/src/data/rules/to18/rules-18-recommande.json +218 -0
  55. package/dist/src/data/rules/to19/rules-19-obligatoire.json +348 -0
  56. package/dist/src/data/rules/to19/rules-19-optionnelle.json +223 -0
  57. package/dist/src/data/rules/to19/rules-19-recommande.json +200 -0
  58. package/dist/src/data/rules/to20/rules-20-obligatoire.json +556 -0
  59. package/dist/src/data/rules/to20/rules-20-optionnelle.json +190 -0
  60. package/dist/src/data/rules/to20/rules-20-recommande.json +151 -0
  61. package/dist/src/index.js +161 -0
  62. package/dist/src/models/chip-config.js +45 -0
  63. package/dist/src/models/interfaces/app-details.interface.js +2 -0
  64. package/dist/src/models/interfaces/ast-interfaces.js +5 -0
  65. package/dist/src/models/interfaces/ast-pattern.interface.js +2 -0
  66. package/dist/src/models/interfaces/client-interfaces.js +6 -0
  67. package/dist/src/models/interfaces/detection-stats.interface.js +2 -0
  68. package/dist/src/models/interfaces/html-match.interface.js +2 -0
  69. package/dist/src/models/interfaces/html-report-data.interface.js +2 -0
  70. package/dist/src/models/interfaces/lib-details.interface.js +2 -0
  71. package/dist/src/models/interfaces/migration-rules.interface.js +2 -0
  72. package/dist/src/models/interfaces/parsed-args.interface.js +2 -0
  73. package/dist/src/models/interfaces/project-info.interface.js +2 -0
  74. package/dist/src/models/interfaces/project-overview-data.interface.js +2 -0
  75. package/dist/src/models/interfaces/rule-match.interface.js +2 -0
  76. package/dist/src/models/interfaces/rule.interface.js +2 -0
  77. package/dist/src/models/interfaces/rules-by-priority.interface.js +2 -0
  78. package/dist/src/models/interfaces/scanner-comparison.interface.js +2 -0
  79. package/dist/src/models/interfaces/special-workload.interface.js +2 -0
  80. package/dist/src/models/interfaces/workload-report.interface.js +2 -0
  81. package/dist/src/models/types/build-block-blob.type.js +2 -0
  82. package/dist/src/models/types/migration-version.type.js +2 -0
  83. package/dist/src/models/types/project-type.type.js +2 -0
  84. package/dist/src/models/types/risk-level.type.js +2 -0
  85. package/dist/src/models/types/rule-category.type.js +2 -0
  86. package/dist/src/models/types/rule-priority.type.js +2 -0
  87. package/dist/src/models/types/rule-workload-type.type.js +2 -0
  88. package/dist/src/templates/landing/applications-analyzed.template.js +18 -0
  89. package/dist/src/templates/landing/card-app-info.template.js +63 -0
  90. package/dist/src/templates/landing/card-lib-info.template.js +67 -0
  91. package/dist/src/templates/landing/libs-analyzed.template.js +22 -0
  92. package/dist/src/templates/landing/nx-summary.template.js +115 -0
  93. package/dist/src/templates/landing/project-overview.template.js +27 -0
  94. package/dist/src/templates/page/index-page.template.js +95 -0
  95. package/dist/src/templates/page/main.template.js +83 -0
  96. package/dist/src/templates/page/migration-guide.template.js +175 -0
  97. package/dist/src/templates/page/workload-report.template.js +53 -0
  98. package/dist/src/templates/workload/dashboard.template.js +184 -0
  99. package/dist/src/templates/workload/filters-panel.template.js +215 -0
  100. package/dist/src/templates/workload/guide-rule-card.template.js +107 -0
  101. package/dist/src/templates/workload/hierarchy-nx.template.js +104 -0
  102. package/dist/src/templates/workload/hierarchy-shared.js +163 -0
  103. package/dist/src/templates/workload/hierarchy-standalone.template.js +36 -0
  104. package/dist/src/templates/workload/hierarchy.template.js +35 -0
  105. package/dist/src/templates/workload/rule-modal.template.js +280 -0
  106. package/dist/src/utils/core/args-parser.js +123 -0
  107. package/dist/src/utils/core/array-helpers.js +18 -0
  108. package/dist/src/utils/core/ast-helpers.js +99 -0
  109. package/dist/src/utils/core/file-helpers.js +109 -0
  110. package/dist/src/utils/core/html-helpers.js +36 -0
  111. package/dist/src/utils/core/index.js +28 -0
  112. package/dist/src/utils/core/logger.js +38 -0
  113. package/dist/src/utils/core/rule-helpers.js +15 -0
  114. package/dist/src/utils/core/workload-formatter.js +6 -0
  115. package/dist/src/utils/shared/array-helpers.js +25 -0
  116. package/dist/src/utils/shared/date-helpers.js +109 -0
  117. package/dist/src/utils/shared/html-helpers.js +37 -0
  118. package/dist/src/utils/shared/index.js +25 -0
  119. package/dist/src/utils/shared/rule-helpers.js +20 -0
  120. package/dist/src/utils/shared/time-formatters.js +76 -0
  121. package/dist/styles.css +2 -0
  122. package/package.json +107 -0
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HtmlMatcher = exports.SymbolMatcher = exports.FileMatcher = exports.CollectionMatcher = exports.TypeMatcher = exports.ExpressionMatcher = exports.HierarchyMatcher = exports.DecoratorMatcher = exports.ImportMatcher = exports.ContextMatcher = exports.NodeMatcher = exports.clearTemplateCache = void 0;
37
+ exports.matchesAstPattern = matchesAstPattern;
38
+ const ts_morph_1 = require("ts-morph");
39
+ // Import matchers TypeScript (depuis ts/)
40
+ const NodeMatcher = __importStar(require("./ts/node-matcher"));
41
+ exports.NodeMatcher = NodeMatcher;
42
+ const ContextMatcher = __importStar(require("./ts/context-matcher"));
43
+ exports.ContextMatcher = ContextMatcher;
44
+ const ImportMatcher = __importStar(require("./ts/import-matcher"));
45
+ exports.ImportMatcher = ImportMatcher;
46
+ const DecoratorMatcher = __importStar(require("./ts/decorator-matcher"));
47
+ exports.DecoratorMatcher = DecoratorMatcher;
48
+ const HierarchyMatcher = __importStar(require("./ts/hierarchy-matcher"));
49
+ exports.HierarchyMatcher = HierarchyMatcher;
50
+ const ExpressionMatcher = __importStar(require("./ts/expression-matcher"));
51
+ exports.ExpressionMatcher = ExpressionMatcher;
52
+ const TypeMatcher = __importStar(require("./ts/type-matcher"));
53
+ exports.TypeMatcher = TypeMatcher;
54
+ const CollectionMatcher = __importStar(require("./ts/collection-matcher"));
55
+ exports.CollectionMatcher = CollectionMatcher;
56
+ const FileMatcher = __importStar(require("./ts/file-matcher"));
57
+ exports.FileMatcher = FileMatcher;
58
+ const SymbolMatcher = __importStar(require("./ts/symbol-matcher"));
59
+ exports.SymbolMatcher = SymbolMatcher;
60
+ // Import matchers HTML (depuis html/)
61
+ const HtmlMatcher = __importStar(require("./html"));
62
+ exports.HtmlMatcher = HtmlMatcher;
63
+ /**
64
+ * Fonction principale : vérifie si un nœud correspond à un pattern AST
65
+ * OPTIMISÉ : excludeContext en premier (88% des règles l'utilisent)
66
+ */
67
+ function matchesAstPattern(node, pattern) {
68
+ // Gestion spéciale des patterns HTML purs (Attribute, PipeExpression)
69
+ if (HtmlMatcher.isHtmlPattern(pattern)) {
70
+ return HtmlMatcher.matchesHtmlPatternInComponent(node, pattern);
71
+ }
72
+ // 1. excludeContext EN PREMIER (88% des règles)
73
+ if (pattern.excludeContext) {
74
+ if (ContextMatcher.isInExcludedContext(node, pattern.excludeContext)) {
75
+ return false;
76
+ }
77
+ }
78
+ // 2. nodeType (rapide, mais souvent déjà filtré par getDescendantsOfKind)
79
+ if (pattern.nodeType) {
80
+ if (!NodeMatcher.matchesNodeType(node, pattern.nodeType)) {
81
+ return false;
82
+ }
83
+ }
84
+ // 3. Critères légers et fréquents
85
+ if (pattern.name !== undefined) {
86
+ if (!NodeMatcher.matchesName(node, pattern.name)) {
87
+ return false;
88
+ }
89
+ }
90
+ if (pattern.propertyName !== undefined) {
91
+ if (!NodeMatcher.matchesPropertyName(node, pattern.propertyName)) {
92
+ return false;
93
+ }
94
+ }
95
+ if (pattern.functionName !== undefined) {
96
+ if (!NodeMatcher.matchesFunctionName(node, pattern.functionName)) {
97
+ return false;
98
+ }
99
+ }
100
+ // 4. context requis (après excludeContext)
101
+ if (pattern.context) {
102
+ if (!ContextMatcher.matchesContext(node, pattern.context)) {
103
+ return false;
104
+ }
105
+ }
106
+ // Vérifier moduleSpecifier (pour ImportDeclaration)
107
+ if (pattern.moduleSpecifier !== undefined) {
108
+ if (!ImportMatcher.matchesModuleSpecifier(node, pattern.moduleSpecifier)) {
109
+ return false;
110
+ }
111
+ }
112
+ // Vérifier namedImports
113
+ if (pattern.namedImports !== undefined) {
114
+ if (!ImportMatcher.matchesNamedImports(node, pattern.namedImports)) {
115
+ return false;
116
+ }
117
+ }
118
+ // Vérifier les propriétés (pour Decorator, ObjectLiteral)
119
+ if (pattern.properties !== undefined) {
120
+ if (!DecoratorMatcher.matchesProperties(node, pattern.properties, matchesAstPattern)) {
121
+ return false;
122
+ }
123
+ }
124
+ // Vérifier template (pour @Component)
125
+ if (pattern.template !== undefined) {
126
+ if (!DecoratorMatcher.matchesTemplate(node, pattern.template)) {
127
+ return false;
128
+ }
129
+ }
130
+ // Vérifier arguments (pour CallExpression)
131
+ if (pattern.arguments !== undefined) {
132
+ if (!ExpressionMatcher.matchesArguments(node, pattern.arguments, matchesAstPattern)) {
133
+ return false;
134
+ }
135
+ }
136
+ // Vérifier initializer (valeur initiale)
137
+ if (pattern.initializer !== undefined) {
138
+ if (!TypeMatcher.matchesInitializer(node, pattern.initializer, matchesAstPattern)) {
139
+ return false;
140
+ }
141
+ }
142
+ // Vérifier parent
143
+ if (pattern.parent !== undefined) {
144
+ if (!HierarchyMatcher.matchesParent(node, pattern.parent, matchesAstPattern)) {
145
+ return false;
146
+ }
147
+ }
148
+ // Vérifier inClass
149
+ if (pattern.inClass !== undefined) {
150
+ if (!HierarchyMatcher.matchesInClass(node, pattern.inClass, matchesAstPattern)) {
151
+ return false;
152
+ }
153
+ }
154
+ // Vérifier notInClass
155
+ if (pattern.notInClass !== undefined) {
156
+ if (HierarchyMatcher.matchesInClass(node, pattern.notInClass, matchesAstPattern)) {
157
+ return false;
158
+ }
159
+ }
160
+ // Vérifier expression
161
+ if (pattern.expression !== undefined) {
162
+ if (!ExpressionMatcher.matchesExpression(node, pattern.expression, matchesAstPattern)) {
163
+ return false;
164
+ }
165
+ }
166
+ // Vérifier left (BinaryExpression)
167
+ if (pattern.left !== undefined) {
168
+ if (!ExpressionMatcher.matchesLeft(node, pattern.left, matchesAstPattern)) {
169
+ return false;
170
+ }
171
+ }
172
+ // Vérifier right (BinaryExpression)
173
+ if (pattern.right !== undefined) {
174
+ if (!ExpressionMatcher.matchesRight(node, pattern.right)) {
175
+ return false;
176
+ }
177
+ }
178
+ // Vérifier operatorKind
179
+ if (pattern.operatorKind !== undefined) {
180
+ if (!NodeMatcher.matchesOperatorKind(node, pattern.operatorKind)) {
181
+ return false;
182
+ }
183
+ }
184
+ // Vérifier type
185
+ if (pattern.type !== undefined) {
186
+ if (!TypeMatcher.matchesType(node, pattern.type)) {
187
+ return false;
188
+ }
189
+ }
190
+ // Vérifier returnType
191
+ if (pattern.returnType !== undefined) {
192
+ if (!TypeMatcher.matchesReturnType(node, pattern.returnType)) {
193
+ return false;
194
+ }
195
+ }
196
+ // Vérifier body
197
+ if (pattern.body !== undefined) {
198
+ if (!ExpressionMatcher.matchesBody(node, pattern.body, matchesAstPattern)) {
199
+ return false;
200
+ }
201
+ }
202
+ // Vérifier modifiers
203
+ if (pattern.modifiers !== undefined) {
204
+ if (!NodeMatcher.matchesModifiers(node, pattern.modifiers)) {
205
+ return false;
206
+ }
207
+ }
208
+ // Vérifier exported
209
+ if (pattern.exported !== undefined) {
210
+ if (!NodeMatcher.matchesExported(node, pattern.exported)) {
211
+ return false;
212
+ }
213
+ }
214
+ // Vérifier parameters
215
+ if (pattern.parameters !== undefined) {
216
+ if (!DecoratorMatcher.matchesParameters(node, pattern.parameters)) {
217
+ return false;
218
+ }
219
+ }
220
+ // Vérifier elements (ArrayLiteralExpression)
221
+ if (pattern.elements !== undefined) {
222
+ // Cas spécial: referTo dans elements (résolution de symboles cross-file)
223
+ if (typeof pattern.elements === 'object' && 'referTo' in pattern.elements) {
224
+ if (!ts_morph_1.Node.isArrayLiteralExpression(node)) {
225
+ return false;
226
+ }
227
+ const elements = node.getElements();
228
+ const elementsPattern = pattern.elements;
229
+ const hasMatch = elements.some(element => {
230
+ // Vérifier nodeType si présent dans le pattern elements
231
+ if (elementsPattern.nodeType) {
232
+ if (!NodeMatcher.matchesNodeType(element, elementsPattern.nodeType)) {
233
+ return false;
234
+ }
235
+ }
236
+ // Vérifier referTo
237
+ return SymbolMatcher.matchesReferTo(element, elementsPattern.referTo);
238
+ });
239
+ if (!hasMatch) {
240
+ return false;
241
+ }
242
+ }
243
+ else {
244
+ // Logique normale (notEmpty, contains, etc.)
245
+ if (!CollectionMatcher.matchesElements(node, pattern.elements, matchesAstPattern)) {
246
+ return false;
247
+ }
248
+ }
249
+ }
250
+ // Vérifier ancestor
251
+ if (pattern.ancestor !== undefined) {
252
+ if (!HierarchyMatcher.matchesAncestor(node, pattern.ancestor, matchesAstPattern)) {
253
+ return false;
254
+ }
255
+ }
256
+ // Vérifier chainContains
257
+ if (pattern.chainContains !== undefined) {
258
+ if (!ExpressionMatcher.matchesChainContains(node, pattern.chainContains, matchesAstPattern)) {
259
+ return false;
260
+ }
261
+ }
262
+ // Vérifier containsAny
263
+ if (pattern.containsAny !== undefined) {
264
+ if (!CollectionMatcher.matchesContainsAny(node, pattern.containsAny, matchesAstPattern)) {
265
+ return false;
266
+ }
267
+ }
268
+ // Vérifier containsAll
269
+ if (pattern.containsAll !== undefined) {
270
+ if (!CollectionMatcher.matchesContainsAll(node, pattern.containsAll, matchesAstPattern)) {
271
+ return false;
272
+ }
273
+ }
274
+ // Vérifier value
275
+ if (pattern.value !== undefined) {
276
+ if (!NodeMatcher.matchesValue(node, pattern.value)) {
277
+ return false;
278
+ }
279
+ }
280
+ // Vérifier valueMatches
281
+ if (pattern.valueMatches !== undefined) {
282
+ if (!NodeMatcher.matchesValuePattern(node, pattern.valueMatches)) {
283
+ return false;
284
+ }
285
+ }
286
+ // Vérifier text
287
+ if (pattern.text !== undefined) {
288
+ if (!NodeMatcher.matchesText(node, pattern.text)) {
289
+ return false;
290
+ }
291
+ }
292
+ // Vérifier nextStatement
293
+ if (pattern.nextStatement !== undefined) {
294
+ if (!ContextMatcher.matchesNextStatement(node, pattern.nextStatement)) {
295
+ return false;
296
+ }
297
+ }
298
+ // Vérifier nextProvider
299
+ if (pattern.nextProvider !== undefined) {
300
+ if (!ContextMatcher.matchesNextProvider(node, pattern.nextProvider)) {
301
+ return false;
302
+ }
303
+ }
304
+ // Vérifier implements
305
+ if (pattern.implements !== undefined) {
306
+ if (!HierarchyMatcher.matchesImplements(node, pattern.implements)) {
307
+ return false;
308
+ }
309
+ }
310
+ // Vérifier implementsGeneric
311
+ if (pattern.implementsGeneric !== undefined) {
312
+ if (!HierarchyMatcher.matchesImplementsGeneric(node, pattern.implementsGeneric)) {
313
+ return false;
314
+ }
315
+ }
316
+ // Vérifier object
317
+ if (pattern.object !== undefined) {
318
+ if (!TypeMatcher.matchesObject(node, pattern.object)) {
319
+ return false;
320
+ }
321
+ }
322
+ // Vérifier property
323
+ if (pattern.property !== undefined) {
324
+ if (!TypeMatcher.matchesProperty(node, pattern.property)) {
325
+ return false;
326
+ }
327
+ }
328
+ // Vérifier declarations
329
+ if (pattern.declarations !== undefined) {
330
+ if (!DecoratorMatcher.matchesDeclarations(node, pattern.declarations, matchesAstPattern)) {
331
+ return false;
332
+ }
333
+ }
334
+ // Vérifier pipeName
335
+ if (pattern.pipeName !== undefined) {
336
+ if (!DecoratorMatcher.matchesPipeName(node, pattern.pipeName)) {
337
+ return false;
338
+ }
339
+ }
340
+ // Vérifier optionalChaining
341
+ if (pattern.optionalChaining !== undefined) {
342
+ if (!DecoratorMatcher.matchesOptionalChaining(node, pattern.optionalChaining)) {
343
+ return false;
344
+ }
345
+ }
346
+ // Vérifier nonNullAssertion
347
+ if (pattern.nonNullAssertion !== undefined) {
348
+ if (!DecoratorMatcher.matchesNonNullAssertion(node, pattern.nonNullAssertion)) {
349
+ return false;
350
+ }
351
+ }
352
+ // Vérifier inFile (nom de fichier)
353
+ if (pattern.inFile !== undefined) {
354
+ const sourceFile = node.getSourceFile();
355
+ const filePath = sourceFile.getFilePath();
356
+ if (!FileMatcher.matchesInFilePattern(filePath, pattern.inFile)) {
357
+ return false;
358
+ }
359
+ }
360
+ // Vérifier testSetup
361
+ if (pattern.testSetup !== undefined) {
362
+ const sourceFile = node.getSourceFile();
363
+ if (!FileMatcher.matchesTestSetup(sourceFile, pattern.testSetup)) {
364
+ return false;
365
+ }
366
+ }
367
+ // Vérifier referTo (résolution de symboles cross-file au niveau racine)
368
+ if (pattern.referTo !== undefined) {
369
+ if (!SymbolMatcher.matchesReferTo(node, pattern.referTo)) {
370
+ return false;
371
+ }
372
+ }
373
+ return true;
374
+ }
375
+ // Export des fonctions utilitaires de cache
376
+ var decorator_matcher_1 = require("./ts/decorator-matcher");
377
+ Object.defineProperty(exports, "clearTemplateCache", { enumerable: true, get: function () { return decorator_matcher_1.clearTemplateCache; } });
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.matchesElements = matchesElements;
4
+ exports.matchesContainsAny = matchesContainsAny;
5
+ exports.matchesContainsAll = matchesContainsAll;
6
+ const ts_morph_1 = require("ts-morph");
7
+ /**
8
+ * Vérifie les éléments d'un tableau (ArrayLiteralExpression)
9
+ */
10
+ function matchesElements(node, elementsPattern, matchesAstPatternFn) {
11
+ if (!ts_morph_1.Node.isArrayLiteralExpression(node)) {
12
+ return false;
13
+ }
14
+ const elements = node.getElements();
15
+ // Vérifier notEmpty (tableau doit avoir au moins un élément)
16
+ if (typeof elementsPattern === 'object' && elementsPattern.notEmpty === true) {
17
+ return elements.length > 0;
18
+ }
19
+ // Vérifier contains (au moins un élément matche le pattern)
20
+ if (elementsPattern.contains) {
21
+ return elements.some(element => matchesAstPatternFn(element, elementsPattern.contains));
22
+ }
23
+ // Cas où elementsPattern est directement un pattern AST
24
+ return elements.some(element => matchesAstPatternFn(element, elementsPattern));
25
+ }
26
+ /**
27
+ * Vérifie qu'au moins un sous-pattern matche (containsAny)
28
+ */
29
+ function matchesContainsAny(node, patterns, matchesAstPatternFn) {
30
+ let hasMatch = false;
31
+ node.forEachDescendant((child) => {
32
+ if (patterns.some(pattern => matchesAstPatternFn(child, pattern))) {
33
+ hasMatch = true;
34
+ }
35
+ });
36
+ return hasMatch;
37
+ }
38
+ /**
39
+ * Vérifie que tous les sous-patterns matchent (containsAll)
40
+ */
41
+ function matchesContainsAll(node, patterns, matchesAstPatternFn) {
42
+ const matches = new Set();
43
+ node.forEachDescendant((child) => {
44
+ patterns.forEach((pattern, index) => {
45
+ if (matchesAstPatternFn(child, pattern)) {
46
+ matches.add(index);
47
+ }
48
+ });
49
+ });
50
+ return matches.size === patterns.length;
51
+ }
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clearContextCaches = clearContextCaches;
4
+ exports.isInExcludedContext = isInExcludedContext;
5
+ exports.matchesNextStatement = matchesNextStatement;
6
+ exports.matchesNextProvider = matchesNextProvider;
7
+ exports.matchesContext = matchesContext;
8
+ const ts_morph_1 = require("ts-morph");
9
+ /**
10
+ * Cache pour les résultats de vérification excludeContext
11
+ * Évite de refaire les mêmes traversals coûteux
12
+ */
13
+ let excludeContextCache = new WeakMap();
14
+ /**
15
+ * Cache des comment ranges par fichier (calculé une seule fois)
16
+ */
17
+ let commentRangesCache = new WeakMap();
18
+ /**
19
+ * Vide les caches pour libérer la mémoire entre les batches
20
+ * CRITIQUE : Appeler après removeSourceFile() pour forcer GC immédiat
21
+ */
22
+ function clearContextCaches() {
23
+ excludeContextCache = new WeakMap();
24
+ commentRangesCache = new WeakMap();
25
+ }
26
+ /**
27
+ * Récupère les comment ranges d'un fichier (avec cache)
28
+ */
29
+ function getCommentRanges(sourceFile) {
30
+ let cached = commentRangesCache.get(sourceFile);
31
+ if (cached) {
32
+ return cached;
33
+ }
34
+ const leadingComments = sourceFile.getLeadingCommentRanges() || [];
35
+ const trailingComments = sourceFile.getTrailingCommentRanges() || [];
36
+ cached = [...leadingComments, ...trailingComments].map(range => ({
37
+ pos: range.getPos(),
38
+ end: range.getEnd()
39
+ }));
40
+ commentRangesCache.set(sourceFile, cached);
41
+ return cached;
42
+ }
43
+ /**
44
+ * Vérifie si le nœud est dans un commentaire (optimisé avec cache)
45
+ */
46
+ function isNodeInComment(node) {
47
+ const sourceFile = node.getSourceFile();
48
+ const start = node.getStart();
49
+ const commentRanges = getCommentRanges(sourceFile);
50
+ return commentRanges.some(range => start >= range.pos && start <= range.end);
51
+ }
52
+ /**
53
+ * Vérifie si le nœud est dans un StringLiteral (optimisé, limite profondeur)
54
+ */
55
+ function isNodeInStringLiteral(node) {
56
+ let parent = node.getParent();
57
+ let depth = 0;
58
+ // Augmenté à 20 pour gérer les objets profondément imbriqués (Nx, configs complexes)
59
+ // Exemple: const config = { a: { b: { c: { d: "string" } } } } → profondeur 12+
60
+ const MAX_DEPTH = 20;
61
+ while (parent && depth < MAX_DEPTH) {
62
+ if (ts_morph_1.Node.isStringLiteral(parent)) {
63
+ return true;
64
+ }
65
+ // Optimisation: arrêter si on atteint un SourceFile
66
+ if (ts_morph_1.Node.isSourceFile(parent)) {
67
+ return false;
68
+ }
69
+ parent = parent.getParent();
70
+ depth++;
71
+ }
72
+ return false;
73
+ }
74
+ /**
75
+ * Vérifie si le nœud est dans un ImportSpecifier (optimisé, limite profondeur)
76
+ */
77
+ function isNodeInImportSpecifier(node) {
78
+ let parent = node.getParent();
79
+ let depth = 0;
80
+ // Augmenté à 10 pour cohérence (ImportSpecifier est généralement à profondeur 3-4)
81
+ const MAX_DEPTH = 10;
82
+ while (parent && depth < MAX_DEPTH) {
83
+ if (ts_morph_1.Node.isImportSpecifier(parent)) {
84
+ return true;
85
+ }
86
+ if (ts_morph_1.Node.isSourceFile(parent)) {
87
+ return false;
88
+ }
89
+ parent = parent.getParent();
90
+ depth++;
91
+ }
92
+ return false;
93
+ }
94
+ /**
95
+ * Vérifie si le nœud est dans un contexte exclu (StringLiteral, Comment)
96
+ * OPTIMISÉ avec cache et early exit
97
+ */
98
+ function isInExcludedContext(node, excludeContext) {
99
+ // Vérifier le cache
100
+ const cached = excludeContextCache.get(node);
101
+ if (cached) {
102
+ return excludeContext.some(ctx => cached.has(ctx));
103
+ }
104
+ // Calculer les contextes (seulement ceux demandés)
105
+ const contexts = new Set();
106
+ // Vérifier seulement les contextes demandés (optimisation)
107
+ if (excludeContext.includes('StringLiteral')) {
108
+ if (isNodeInStringLiteral(node)) {
109
+ contexts.add('StringLiteral');
110
+ }
111
+ }
112
+ if (excludeContext.includes('Comment')) {
113
+ if (isNodeInComment(node)) {
114
+ contexts.add('Comment');
115
+ }
116
+ }
117
+ if (excludeContext.includes('ImportSpecifier')) {
118
+ if (isNodeInImportSpecifier(node)) {
119
+ contexts.add('ImportSpecifier');
120
+ }
121
+ }
122
+ // Mettre en cache
123
+ excludeContextCache.set(node, contexts);
124
+ // Vérifier si au moins un contexte exclu est présent
125
+ return excludeContext.some(ctx => contexts.has(ctx));
126
+ }
127
+ /**
128
+ * Vérifie la prochaine instruction (nextStatement)
129
+ */
130
+ function matchesNextStatement(node, nextStatementPattern) {
131
+ // Trouver le statement parent
132
+ let currentStatement = node;
133
+ while (currentStatement && !ts_morph_1.Node.isStatement(currentStatement)) {
134
+ currentStatement = currentStatement.getParent();
135
+ }
136
+ if (!currentStatement) {
137
+ return false;
138
+ }
139
+ const parent = currentStatement.getParent();
140
+ if (!parent) {
141
+ return false;
142
+ }
143
+ let statements = [];
144
+ // Récupérer les statements selon le type de parent
145
+ if (ts_morph_1.Node.isBlock(parent)) {
146
+ statements = parent.getStatements();
147
+ }
148
+ else if (ts_morph_1.Node.isSourceFile(parent)) {
149
+ statements = parent.getStatements();
150
+ }
151
+ else if (ts_morph_1.Node.isCaseClause(parent) || ts_morph_1.Node.isDefaultClause(parent)) {
152
+ statements = parent.getStatements();
153
+ }
154
+ else {
155
+ return false;
156
+ }
157
+ const currentIndex = statements.indexOf(currentStatement);
158
+ if (currentIndex === -1) {
159
+ return false;
160
+ }
161
+ // Vérifier notContains : matcher si le pattern est absent du statement suivant
162
+ if (nextStatementPattern.notContains) {
163
+ // Si pas de statement suivant, le pattern est bien absent → match
164
+ if (currentIndex === statements.length - 1) {
165
+ return true;
166
+ }
167
+ const nextStatement = statements[currentIndex + 1];
168
+ const nextText = nextStatement.getText();
169
+ // Vérifier si au moins un des patterns est présent dans le statement suivant
170
+ const hasAny = nextStatementPattern.notContains.some((pattern) => nextText.includes(pattern));
171
+ // Matcher si AUCUN pattern n'est présent
172
+ return !hasAny;
173
+ }
174
+ return true;
175
+ }
176
+ /**
177
+ * Vérifie le provider suivant (nextProvider)
178
+ */
179
+ function matchesNextProvider(node, nextProviderPattern) {
180
+ // Trouver le tableau de providers parent
181
+ let parent = node.getParent();
182
+ while (parent && !ts_morph_1.Node.isArrayLiteralExpression(parent)) {
183
+ parent = parent.getParent();
184
+ }
185
+ if (!parent || !ts_morph_1.Node.isArrayLiteralExpression(parent)) {
186
+ return false;
187
+ }
188
+ const elements = parent.getElements();
189
+ const currentIndex = elements.indexOf(node);
190
+ if (currentIndex === -1) {
191
+ return false;
192
+ }
193
+ // Vérifier missing : le provider ne doit PAS être présent dans les éléments restants
194
+ if (nextProviderPattern.missing) {
195
+ const missingProviderName = nextProviderPattern.missing;
196
+ // Vérifier tous les providers après le nœud courant
197
+ for (let i = currentIndex + 1; i < elements.length; i++) {
198
+ const providerElement = elements[i];
199
+ const providerText = providerElement.getText();
200
+ // Vérifier si le provider manquant est présent
201
+ if (providerText.includes(missingProviderName)) {
202
+ // Le provider est présent, donc le pattern ne matche PAS
203
+ return false;
204
+ }
205
+ }
206
+ // Le provider est bien absent de tous les providers restants
207
+ return true;
208
+ }
209
+ return true;
210
+ }
211
+ /**
212
+ * Vérifie le contexte requis (context)
213
+ */
214
+ function matchesContext(node, context) {
215
+ // Convertir en tableau si c'est une chaîne unique
216
+ const contexts = Array.isArray(context) ? context : [context];
217
+ // Contextes spéciaux personnalisés
218
+ if (contexts.includes('ProvidersArray')) {
219
+ if (isInProvidersArray(node)) {
220
+ return true;
221
+ }
222
+ }
223
+ // Contextes AST standards
224
+ let parent = node.getParent();
225
+ while (parent) {
226
+ const parentKind = parent.getKindName();
227
+ if (contexts.includes(parentKind)) {
228
+ return true;
229
+ }
230
+ parent = parent.getParent();
231
+ }
232
+ return false;
233
+ }
234
+ /**
235
+ * Vérifie si le nœud est dans un tableau providers d'un @NgModule ou @Component
236
+ */
237
+ function isInProvidersArray(node) {
238
+ // Vérifier si le nœud est dans un ArrayLiteralExpression
239
+ let parent = node.getParent();
240
+ while (parent) {
241
+ // Si on trouve un ArrayLiteralExpression, vérifier si c'est un tableau providers
242
+ if (ts_morph_1.Node.isArrayLiteralExpression(parent)) {
243
+ const propAssignment = parent.getParent();
244
+ // Vérifier si c'est une PropertyAssignment avec le nom "providers"
245
+ if (propAssignment && ts_morph_1.Node.isPropertyAssignment(propAssignment)) {
246
+ const propName = propAssignment.getName();
247
+ if (propName === 'providers') {
248
+ // Vérifier si la PropertyAssignment est dans un ObjectLiteralExpression
249
+ const objLiteral = propAssignment.getParent();
250
+ if (objLiteral && ts_morph_1.Node.isObjectLiteralExpression(objLiteral)) {
251
+ // Vérifier si l'ObjectLiteralExpression est dans un CallExpression (argument du décorateur)
252
+ const callExpr = objLiteral.getParent();
253
+ if (callExpr && ts_morph_1.Node.isCallExpression(callExpr)) {
254
+ // Vérifier si le CallExpression est dans un Decorator
255
+ const decorator = callExpr.getParent();
256
+ if (decorator && ts_morph_1.Node.isDecorator(decorator)) {
257
+ // Vérifier si le décorateur est @NgModule ou @Component
258
+ const expr = decorator.getExpression();
259
+ if (ts_morph_1.Node.isCallExpression(expr)) {
260
+ const decoratorName = expr.getExpression().getText();
261
+ return decoratorName === 'NgModule' || decoratorName === 'Component';
262
+ }
263
+ }
264
+ }
265
+ }
266
+ }
267
+ }
268
+ // On a trouvé un ArrayLiteralExpression mais ce n'est pas providers
269
+ // Ne pas continuer la recherche plus haut
270
+ return false;
271
+ }
272
+ parent = parent.getParent();
273
+ }
274
+ return false;
275
+ }