@angular-modernizer/api 0.1.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/LICENSE +21 -0
- package/README.md +507 -0
- package/dist/analysis/complexity-metrics-calculator.d.ts +99 -0
- package/dist/analysis/complexity-metrics-calculator.d.ts.map +1 -0
- package/dist/analysis/complexity-metrics-calculator.js +195 -0
- package/dist/analysis/complexity-metrics-calculator.js.map +1 -0
- package/dist/analysis/dependency-analyzer.d.ts +227 -0
- package/dist/analysis/dependency-analyzer.d.ts.map +1 -0
- package/dist/analysis/dependency-analyzer.js +451 -0
- package/dist/analysis/dependency-analyzer.js.map +1 -0
- package/dist/analysis/external-template-loader.d.ts +44 -0
- package/dist/analysis/external-template-loader.d.ts.map +1 -0
- package/dist/analysis/external-template-loader.js +69 -0
- package/dist/analysis/external-template-loader.js.map +1 -0
- package/dist/analysis/selector-mapper.d.ts +77 -0
- package/dist/analysis/selector-mapper.d.ts.map +1 -0
- package/dist/analysis/selector-mapper.js +146 -0
- package/dist/analysis/selector-mapper.js.map +1 -0
- package/dist/analysis/service-detector.d.ts +164 -0
- package/dist/analysis/service-detector.d.ts.map +1 -0
- package/dist/analysis/service-detector.js +231 -0
- package/dist/analysis/service-detector.js.map +1 -0
- package/dist/analysis/service-pattern-recognizer.d.ts +247 -0
- package/dist/analysis/service-pattern-recognizer.d.ts.map +1 -0
- package/dist/analysis/service-pattern-recognizer.js +444 -0
- package/dist/analysis/service-pattern-recognizer.js.map +1 -0
- package/dist/analysis/symbol-locator.d.ts +81 -0
- package/dist/analysis/symbol-locator.d.ts.map +1 -0
- package/dist/analysis/symbol-locator.js +128 -0
- package/dist/analysis/symbol-locator.js.map +1 -0
- package/dist/analysis/template-analyzer-usage.d.ts +144 -0
- package/dist/analysis/template-analyzer-usage.d.ts.map +1 -0
- package/dist/analysis/template-analyzer-usage.js +474 -0
- package/dist/analysis/template-analyzer-usage.js.map +1 -0
- package/dist/analysis/template-analyzer.d.ts +80 -0
- package/dist/analysis/template-analyzer.d.ts.map +1 -0
- package/dist/analysis/template-analyzer.js +146 -0
- package/dist/analysis/template-analyzer.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/investigation/angular-symbol-finder.d.ts +76 -0
- package/dist/investigation/angular-symbol-finder.d.ts.map +1 -0
- package/dist/investigation/angular-symbol-finder.js +199 -0
- package/dist/investigation/angular-symbol-finder.js.map +1 -0
- package/dist/investigation/call-graph-builder.d.ts +85 -0
- package/dist/investigation/call-graph-builder.d.ts.map +1 -0
- package/dist/investigation/call-graph-builder.js +196 -0
- package/dist/investigation/call-graph-builder.js.map +1 -0
- package/dist/investigation/codebase-searcher.d.ts +99 -0
- package/dist/investigation/codebase-searcher.d.ts.map +1 -0
- package/dist/investigation/codebase-searcher.js +201 -0
- package/dist/investigation/codebase-searcher.js.map +1 -0
- package/dist/investigation/stack-trace-parser.d.ts +70 -0
- package/dist/investigation/stack-trace-parser.d.ts.map +1 -0
- package/dist/investigation/stack-trace-parser.js +117 -0
- package/dist/investigation/stack-trace-parser.js.map +1 -0
- package/dist/investigation/type-resolver.d.ts +59 -0
- package/dist/investigation/type-resolver.d.ts.map +1 -0
- package/dist/investigation/type-resolver.js +111 -0
- package/dist/investigation/type-resolver.js.map +1 -0
- package/dist/investigation/usage-finder.d.ts +69 -0
- package/dist/investigation/usage-finder.d.ts.map +1 -0
- package/dist/investigation/usage-finder.js +132 -0
- package/dist/investigation/usage-finder.js.map +1 -0
- package/dist/metrics/complexity-metrics.d.ts +196 -0
- package/dist/metrics/complexity-metrics.d.ts.map +1 -0
- package/dist/metrics/complexity-metrics.js +445 -0
- package/dist/metrics/complexity-metrics.js.map +1 -0
- package/dist/public-api.d.ts +77 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +50 -0
- package/dist/public-api.js.map +1 -0
- package/dist/transformation/import-manager.d.ts +276 -0
- package/dist/transformation/import-manager.d.ts.map +1 -0
- package/dist/transformation/import-manager.js +488 -0
- package/dist/transformation/import-manager.js.map +1 -0
- package/dist/transformation/ng-morph-adapter.d.ts +111 -0
- package/dist/transformation/ng-morph-adapter.d.ts.map +1 -0
- package/dist/transformation/ng-morph-adapter.js +179 -0
- package/dist/transformation/ng-morph-adapter.js.map +1 -0
- package/dist/transformation/ngmodule-manager.d.ts +145 -0
- package/dist/transformation/ngmodule-manager.d.ts.map +1 -0
- package/dist/transformation/ngmodule-manager.js +356 -0
- package/dist/transformation/ngmodule-manager.js.map +1 -0
- package/package.json +62 -0
- package/src/analysis/complexity-metrics-calculator.ts +253 -0
- package/src/analysis/dependency-analyzer.ts +720 -0
- package/src/analysis/external-template-loader.ts +79 -0
- package/src/analysis/selector-mapper.ts +186 -0
- package/src/analysis/service-detector.ts +280 -0
- package/src/analysis/service-pattern-recognizer.ts +545 -0
- package/src/analysis/symbol-locator.ts +170 -0
- package/src/analysis/template-analyzer-usage.ts +614 -0
- package/src/analysis/template-analyzer.ts +208 -0
- package/src/index.ts +51 -0
- package/src/investigation/angular-symbol-finder.ts +263 -0
- package/src/investigation/call-graph-builder.ts +298 -0
- package/src/investigation/codebase-searcher.ts +286 -0
- package/src/investigation/stack-trace-parser.ts +166 -0
- package/src/investigation/type-resolver.ts +144 -0
- package/src/investigation/usage-finder.ts +198 -0
- package/src/metrics/complexity-metrics.ts +617 -0
- package/src/public-api.ts +119 -0
- package/src/transformation/import-manager.ts +626 -0
- package/src/transformation/ng-morph-adapter.ts +252 -0
- package/src/transformation/ngmodule-manager.ts +450 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector-mapper.d.ts","sourceRoot":"","sources":["../../src/analysis/selector-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAGV,OAAO,EAER,MAAM,UAAU,CAAC;AAGlB;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAkC;IAErD;;;;;;;;OAQG;IACH,uBAAuB,CACrB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,SAAS;IAQrB;;;;;;;OAOG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAKrD;;;;OAIG;IACH,UAAU,IAAI,IAAI;IAIlB;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IA2CxB;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;IA6BpC;;;;;;;;;OASG;IACH,OAAO,CAAC,aAAa;CAetB"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @angular-modernizer/api - Selector Mapper
|
|
3
|
+
*
|
|
4
|
+
* Reusable selector-to-className mapping utility.
|
|
5
|
+
* Extracted from Phase 3's selector map caching for reuse across components.
|
|
6
|
+
*
|
|
7
|
+
* Philosophy: "Build Once, Use Everywhere"
|
|
8
|
+
* - O(n) initial build, O(1) lookups
|
|
9
|
+
* - Lazy initialization (only builds when first needed)
|
|
10
|
+
* - Universal coverage (standard `` + custom decorators)
|
|
11
|
+
*/
|
|
12
|
+
import { SyntaxKind } from 'ts-morph';
|
|
13
|
+
/**
|
|
14
|
+
* Selector Mapper - Maps component selectors to class names.
|
|
15
|
+
*
|
|
16
|
+
* Provides O(1) selector lookups using a cached map built from project files.
|
|
17
|
+
* Supports both standard `` decorators and custom decorators (e.g., ``).
|
|
18
|
+
*/
|
|
19
|
+
export class SelectorMapper {
|
|
20
|
+
selectorMap;
|
|
21
|
+
/**
|
|
22
|
+
* Find a component class name by its selector.
|
|
23
|
+
*
|
|
24
|
+
* Builds the selector map lazily on first call, then reuses for O(1) lookups.
|
|
25
|
+
*
|
|
26
|
+
* @param project - ts-morph Project
|
|
27
|
+
* @param selector - Component selector (e.g., 'app-user-profile')
|
|
28
|
+
* @returns Class name (e.g., 'UserProfileComponent') or undefined if not found
|
|
29
|
+
*/
|
|
30
|
+
findComponentBySelector(project, selector) {
|
|
31
|
+
// Build selector map lazily on first use
|
|
32
|
+
this.selectorMap ??= this.buildSelectorMap(project);
|
|
33
|
+
// O(1) lookup in cached map
|
|
34
|
+
return this.selectorMap.get(selector);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get the complete selector map.
|
|
38
|
+
*
|
|
39
|
+
* Builds the map lazily if not yet built.
|
|
40
|
+
*
|
|
41
|
+
* @param project - ts-morph Project
|
|
42
|
+
* @returns Map of selector → className
|
|
43
|
+
*/
|
|
44
|
+
getSelectorMap(project) {
|
|
45
|
+
this.selectorMap ??= this.buildSelectorMap(project);
|
|
46
|
+
return this.selectorMap;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Clear the cached selector map.
|
|
50
|
+
*
|
|
51
|
+
* Useful for testing or when project files have changed significantly.
|
|
52
|
+
*/
|
|
53
|
+
clearCache() {
|
|
54
|
+
this.selectorMap = undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build a comprehensive selector map for the entire project.
|
|
58
|
+
*
|
|
59
|
+
* Scans all source files once to build selector → className mapping.
|
|
60
|
+
* Performance: O(n) initial build, O(1) lookup per selector.
|
|
61
|
+
*
|
|
62
|
+
* @param project - ts-morph Project
|
|
63
|
+
* @returns Map of selector → className
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
buildSelectorMap(project) {
|
|
67
|
+
const selectorMap = new Map();
|
|
68
|
+
const sourceFiles = project.getSourceFiles();
|
|
69
|
+
for (const sourceFile of sourceFiles) {
|
|
70
|
+
// Skip node_modules and test files for performance
|
|
71
|
+
const filePath = sourceFile.getFilePath();
|
|
72
|
+
if (filePath.includes('node_modules') ||
|
|
73
|
+
filePath.includes('.spec.ts') ||
|
|
74
|
+
filePath.includes('.d.ts')) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const classes = sourceFile.getClasses();
|
|
78
|
+
for (const classDecl of classes) {
|
|
79
|
+
const className = classDecl.getName();
|
|
80
|
+
if (!className) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Check if this class has a @Component decorator
|
|
84
|
+
// (regardless of other decorators like @ExportComponent)
|
|
85
|
+
const componentDecorator = this.findDecorator(classDecl, 'Component');
|
|
86
|
+
if (componentDecorator) {
|
|
87
|
+
// Extract selector from @Component metadata
|
|
88
|
+
const selector = this.extractSelectorFromDecorator(componentDecorator);
|
|
89
|
+
if (selector) {
|
|
90
|
+
// Add to map: selector → className
|
|
91
|
+
selectorMap.set(selector, className);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return selectorMap;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Extract the selector from a `` decorator.
|
|
100
|
+
*
|
|
101
|
+
* @param decorator - The `` decorator
|
|
102
|
+
* @returns The selector string or undefined
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
extractSelectorFromDecorator(decorator) {
|
|
106
|
+
const args = decorator.getArguments();
|
|
107
|
+
if (args.length === 0) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const metadataObj = args[0];
|
|
111
|
+
if (!metadataObj ||
|
|
112
|
+
metadataObj.getKind() !== SyntaxKind.ObjectLiteralExpression) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
const objLiteral = metadataObj;
|
|
116
|
+
const selectorProperty = objLiteral.getProperty('selector');
|
|
117
|
+
if (selectorProperty) {
|
|
118
|
+
const initializer = selectorProperty.getChildAtIndex(2); // Skip name and colon
|
|
119
|
+
const text = initializer.getText();
|
|
120
|
+
// Remove quotes if present
|
|
121
|
+
return text.replaceAll(/^['"`]|['"`]$/g, '');
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Find a decorator by name on a class declaration.
|
|
127
|
+
*
|
|
128
|
+
* Supports both standard decorators (``) and custom decorators (``).
|
|
129
|
+
*
|
|
130
|
+
* @param classDecl - Class declaration
|
|
131
|
+
* @param decoratorName - Decorator name (without @)
|
|
132
|
+
* @returns Decorator or undefined
|
|
133
|
+
* @private
|
|
134
|
+
*/
|
|
135
|
+
findDecorator(classDecl, decoratorName) {
|
|
136
|
+
const decorators = classDecl.getDecorators();
|
|
137
|
+
for (const decorator of decorators) {
|
|
138
|
+
const name = decorator.getName();
|
|
139
|
+
if (name === decoratorName) {
|
|
140
|
+
return decorator;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=selector-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector-mapper.js","sourceRoot":"","sources":["../../src/analysis/selector-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @angular-modernizer/api - Service Detector
|
|
3
|
+
*
|
|
4
|
+
* Centralized service detection API with caching and bulk operations.
|
|
5
|
+
* Single source of truth for service detection across all analysis rules.
|
|
6
|
+
*
|
|
7
|
+
* ARCHITECTURE:
|
|
8
|
+
* - Wraps ServicePatternRecognizer for consistent detection
|
|
9
|
+
* - Provides caching to avoid redundant AST traversal
|
|
10
|
+
* - Supports bulk detection for performance
|
|
11
|
+
* - Used by all analysis rules that need service detection
|
|
12
|
+
*/
|
|
13
|
+
import type { SourceFile, ClassDeclaration } from 'ts-morph';
|
|
14
|
+
import type { ServicePatternRecognizer, ServiceDetectionResult } from './service-pattern-recognizer.js';
|
|
15
|
+
/**
|
|
16
|
+
* Bulk detection result for multiple classes.
|
|
17
|
+
*/
|
|
18
|
+
export interface BulkDetectionResult {
|
|
19
|
+
/** Map of class name to detection result */
|
|
20
|
+
results: Map<string, ServiceDetectionResult>;
|
|
21
|
+
/** Total number of services detected */
|
|
22
|
+
serviceCount: number;
|
|
23
|
+
/** Total number of classes analyzed */
|
|
24
|
+
totalCount: number;
|
|
25
|
+
/** Detection time in milliseconds */
|
|
26
|
+
detectionTimeMs: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* ServiceDetector - Centralized service detection with caching.
|
|
30
|
+
*
|
|
31
|
+
* SINGLE SOURCE OF TRUTH:
|
|
32
|
+
* - All analysis rules should use this detector
|
|
33
|
+
* - Ensures consistent service detection across rules
|
|
34
|
+
* - Provides performance optimization through caching
|
|
35
|
+
*
|
|
36
|
+
* USAGE:
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const detector = new ServiceDetector(recognizer);
|
|
39
|
+
*
|
|
40
|
+
* // Single detection
|
|
41
|
+
* const result = detector.detectService(classDecl);
|
|
42
|
+
*
|
|
43
|
+
* // Bulk detection
|
|
44
|
+
* const bulk = detector.detectServicesInFile(sourceFile);
|
|
45
|
+
*
|
|
46
|
+
* // Cache management
|
|
47
|
+
* detector.clearCache();
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare class ServiceDetector {
|
|
51
|
+
private readonly recognizer;
|
|
52
|
+
private readonly cache;
|
|
53
|
+
/**
|
|
54
|
+
* Create a new ServiceDetector.
|
|
55
|
+
*
|
|
56
|
+
* @param recognizer - ServicePatternRecognizer instance
|
|
57
|
+
*/
|
|
58
|
+
constructor(recognizer: ServicePatternRecognizer);
|
|
59
|
+
/**
|
|
60
|
+
* Detect if a class is a service with caching.
|
|
61
|
+
*
|
|
62
|
+
* Results are cached by file path + class name for performance.
|
|
63
|
+
*
|
|
64
|
+
* @param classDecl - The class declaration to analyze
|
|
65
|
+
* @returns Service detection result with confidence
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const result = detector.detectService(classDecl);
|
|
70
|
+
* if (result.isService && result.confidence >= 0.7) {
|
|
71
|
+
* console.info(`High confidence service detected via ${result.detectionMethod}`);
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
detectService(classDecl: ClassDeclaration): ServiceDetectionResult;
|
|
76
|
+
/**
|
|
77
|
+
* Simple check if a class is a service (cached).
|
|
78
|
+
*
|
|
79
|
+
* @param classDecl - The class declaration to check
|
|
80
|
+
* @returns True if detected as service
|
|
81
|
+
*/
|
|
82
|
+
isService(classDecl: ClassDeclaration): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Detect all services in a source file (bulk operation).
|
|
85
|
+
*
|
|
86
|
+
* More efficient than detecting each class individually.
|
|
87
|
+
*
|
|
88
|
+
* @param sourceFile - The source file to analyze
|
|
89
|
+
* @returns Bulk detection result with statistics
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const bulk = detector.detectServicesInFile(sourceFile);
|
|
94
|
+
* console.info(`Found ${bulk.serviceCount} services in ${bulk.detectionTimeMs}ms`);
|
|
95
|
+
*
|
|
96
|
+
* for (const [className, result] of bulk.results) {
|
|
97
|
+
* if (result.isService) {
|
|
98
|
+
* console.info(`${className}: ${result.detectionMethod} (${result.confidence})`);
|
|
99
|
+
* }
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
detectServicesInFile(sourceFile: SourceFile): BulkDetectionResult;
|
|
104
|
+
/**
|
|
105
|
+
* Detect services in multiple source files (bulk operation).
|
|
106
|
+
*
|
|
107
|
+
* @param sourceFiles - Array of source files to analyze
|
|
108
|
+
* @returns Bulk detection result with combined statistics
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const files = project.getSourceFiles();
|
|
113
|
+
* const bulk = detector.detectServicesInFiles(files);
|
|
114
|
+
* console.info(`Found ${bulk.serviceCount} services across ${files.length} files`);
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
detectServicesInFiles(sourceFiles: SourceFile[]): BulkDetectionResult;
|
|
118
|
+
/**
|
|
119
|
+
* Filter classes to only services.
|
|
120
|
+
*
|
|
121
|
+
* @param classes - Array of class declarations
|
|
122
|
+
* @returns Array of service class declarations
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const allClasses = sourceFile.getClasses();
|
|
127
|
+
* const services = detector.filterServices(allClasses);
|
|
128
|
+
* console.info(`Found ${services.length} services out of ${allClasses.length} classes`);
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
filterServices(classes: ClassDeclaration[]): ClassDeclaration[];
|
|
132
|
+
/**
|
|
133
|
+
* Get detection statistics from cache.
|
|
134
|
+
*
|
|
135
|
+
* @returns Statistics about cached detections
|
|
136
|
+
*/
|
|
137
|
+
getCacheStatistics(): {
|
|
138
|
+
totalEntries: number;
|
|
139
|
+
serviceEntries: number;
|
|
140
|
+
nonServiceEntries: number;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Clear the detection cache.
|
|
144
|
+
*
|
|
145
|
+
* Call this when the AST has been modified and cached results
|
|
146
|
+
* may be stale.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* // After modifying files
|
|
151
|
+
* await project.save();
|
|
152
|
+
* detector.clearCache();
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
clearCache(): void;
|
|
156
|
+
/**
|
|
157
|
+
* Get cache key for a class declaration.
|
|
158
|
+
*
|
|
159
|
+
* @param classDecl - The class declaration
|
|
160
|
+
* @returns Cache key string
|
|
161
|
+
*/
|
|
162
|
+
private getCacheKey;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=service-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-detector.d.ts","sourceRoot":"","sources":["../../src/analysis/service-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAExG;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAE7C,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IAErB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IAEnB,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2B;IACtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsC;IAE5D;;;;OAIG;gBACS,UAAU,EAAE,wBAAwB;IAKhD;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,SAAS,EAAE,gBAAgB,GAAG,sBAAsB;IAgBlE;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO;IAI/C;;;;;;;;;;;;;;;;;;;OAmBG;IACH,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,mBAAmB;IA+BjE;;;;;;;;;;;;OAYG;IACH,qBAAqB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,mBAAmB;IA+BrE;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE;IAI/D;;;;OAIG;IACH,kBAAkB,IAAI;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,CAAC;KAC3B;IAmBD;;;;;;;;;;;;OAYG;IACH,UAAU,IAAI,IAAI;IAIlB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;CAKpB"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @angular-modernizer/api - Service Detector
|
|
3
|
+
*
|
|
4
|
+
* Centralized service detection API with caching and bulk operations.
|
|
5
|
+
* Single source of truth for service detection across all analysis rules.
|
|
6
|
+
*
|
|
7
|
+
* ARCHITECTURE:
|
|
8
|
+
* - Wraps ServicePatternRecognizer for consistent detection
|
|
9
|
+
* - Provides caching to avoid redundant AST traversal
|
|
10
|
+
* - Supports bulk detection for performance
|
|
11
|
+
* - Used by all analysis rules that need service detection
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* ServiceDetector - Centralized service detection with caching.
|
|
15
|
+
*
|
|
16
|
+
* SINGLE SOURCE OF TRUTH:
|
|
17
|
+
* - All analysis rules should use this detector
|
|
18
|
+
* - Ensures consistent service detection across rules
|
|
19
|
+
* - Provides performance optimization through caching
|
|
20
|
+
*
|
|
21
|
+
* USAGE:
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const detector = new ServiceDetector(recognizer);
|
|
24
|
+
*
|
|
25
|
+
* // Single detection
|
|
26
|
+
* const result = detector.detectService(classDecl);
|
|
27
|
+
*
|
|
28
|
+
* // Bulk detection
|
|
29
|
+
* const bulk = detector.detectServicesInFile(sourceFile);
|
|
30
|
+
*
|
|
31
|
+
* // Cache management
|
|
32
|
+
* detector.clearCache();
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class ServiceDetector {
|
|
36
|
+
recognizer;
|
|
37
|
+
cache;
|
|
38
|
+
/**
|
|
39
|
+
* Create a new ServiceDetector.
|
|
40
|
+
*
|
|
41
|
+
* @param recognizer - ServicePatternRecognizer instance
|
|
42
|
+
*/
|
|
43
|
+
constructor(recognizer) {
|
|
44
|
+
this.recognizer = recognizer;
|
|
45
|
+
this.cache = new Map();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Detect if a class is a service with caching.
|
|
49
|
+
*
|
|
50
|
+
* Results are cached by file path + class name for performance.
|
|
51
|
+
*
|
|
52
|
+
* @param classDecl - The class declaration to analyze
|
|
53
|
+
* @returns Service detection result with confidence
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const result = detector.detectService(classDecl);
|
|
58
|
+
* if (result.isService && result.confidence >= 0.7) {
|
|
59
|
+
* console.info(`High confidence service detected via ${result.detectionMethod}`);
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
detectService(classDecl) {
|
|
64
|
+
const cacheKey = this.getCacheKey(classDecl);
|
|
65
|
+
// Check cache first
|
|
66
|
+
const cached = this.cache.get(cacheKey);
|
|
67
|
+
if (cached) {
|
|
68
|
+
return cached;
|
|
69
|
+
}
|
|
70
|
+
// Detect and cache result
|
|
71
|
+
const result = this.recognizer.detectService(classDecl);
|
|
72
|
+
this.cache.set(cacheKey, result);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Simple check if a class is a service (cached).
|
|
77
|
+
*
|
|
78
|
+
* @param classDecl - The class declaration to check
|
|
79
|
+
* @returns True if detected as service
|
|
80
|
+
*/
|
|
81
|
+
isService(classDecl) {
|
|
82
|
+
return this.detectService(classDecl).isService;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Detect all services in a source file (bulk operation).
|
|
86
|
+
*
|
|
87
|
+
* More efficient than detecting each class individually.
|
|
88
|
+
*
|
|
89
|
+
* @param sourceFile - The source file to analyze
|
|
90
|
+
* @returns Bulk detection result with statistics
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const bulk = detector.detectServicesInFile(sourceFile);
|
|
95
|
+
* console.info(`Found ${bulk.serviceCount} services in ${bulk.detectionTimeMs}ms`);
|
|
96
|
+
*
|
|
97
|
+
* for (const [className, result] of bulk.results) {
|
|
98
|
+
* if (result.isService) {
|
|
99
|
+
* console.info(`${className}: ${result.detectionMethod} (${result.confidence})`);
|
|
100
|
+
* }
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
detectServicesInFile(sourceFile) {
|
|
105
|
+
const startTime = Date.now();
|
|
106
|
+
const results = new Map();
|
|
107
|
+
const classes = sourceFile.getClasses();
|
|
108
|
+
let serviceCount = 0;
|
|
109
|
+
for (const classDecl of classes) {
|
|
110
|
+
const className = classDecl.getName();
|
|
111
|
+
if (!className) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const result = this.detectService(classDecl);
|
|
115
|
+
results.set(className, result);
|
|
116
|
+
if (result.isService) {
|
|
117
|
+
serviceCount++;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const endTime = Date.now();
|
|
121
|
+
return {
|
|
122
|
+
results,
|
|
123
|
+
serviceCount,
|
|
124
|
+
totalCount: classes.length,
|
|
125
|
+
detectionTimeMs: endTime - startTime,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Detect services in multiple source files (bulk operation).
|
|
130
|
+
*
|
|
131
|
+
* @param sourceFiles - Array of source files to analyze
|
|
132
|
+
* @returns Bulk detection result with combined statistics
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const files = project.getSourceFiles();
|
|
137
|
+
* const bulk = detector.detectServicesInFiles(files);
|
|
138
|
+
* console.info(`Found ${bulk.serviceCount} services across ${files.length} files`);
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
detectServicesInFiles(sourceFiles) {
|
|
142
|
+
const startTime = Date.now();
|
|
143
|
+
const results = new Map();
|
|
144
|
+
let serviceCount = 0;
|
|
145
|
+
let totalCount = 0;
|
|
146
|
+
for (const sourceFile of sourceFiles) {
|
|
147
|
+
const fileResult = this.detectServicesInFile(sourceFile);
|
|
148
|
+
// Merge results with class name prefixed by file path for uniqueness
|
|
149
|
+
const filePath = sourceFile.getFilePath();
|
|
150
|
+
for (const [className, result] of fileResult.results) {
|
|
151
|
+
const key = `${filePath}:${className}`;
|
|
152
|
+
results.set(key, result);
|
|
153
|
+
}
|
|
154
|
+
serviceCount += fileResult.serviceCount;
|
|
155
|
+
totalCount += fileResult.totalCount;
|
|
156
|
+
}
|
|
157
|
+
const endTime = Date.now();
|
|
158
|
+
return {
|
|
159
|
+
results,
|
|
160
|
+
serviceCount,
|
|
161
|
+
totalCount,
|
|
162
|
+
detectionTimeMs: endTime - startTime,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Filter classes to only services.
|
|
167
|
+
*
|
|
168
|
+
* @param classes - Array of class declarations
|
|
169
|
+
* @returns Array of service class declarations
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* const allClasses = sourceFile.getClasses();
|
|
174
|
+
* const services = detector.filterServices(allClasses);
|
|
175
|
+
* console.info(`Found ${services.length} services out of ${allClasses.length} classes`);
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
filterServices(classes) {
|
|
179
|
+
return classes.filter((cls) => this.isService(cls));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get detection statistics from cache.
|
|
183
|
+
*
|
|
184
|
+
* @returns Statistics about cached detections
|
|
185
|
+
*/
|
|
186
|
+
getCacheStatistics() {
|
|
187
|
+
let serviceEntries = 0;
|
|
188
|
+
let nonServiceEntries = 0;
|
|
189
|
+
for (const result of this.cache.values()) {
|
|
190
|
+
if (result.isService) {
|
|
191
|
+
serviceEntries++;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
nonServiceEntries++;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
totalEntries: this.cache.size,
|
|
199
|
+
serviceEntries,
|
|
200
|
+
nonServiceEntries,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Clear the detection cache.
|
|
205
|
+
*
|
|
206
|
+
* Call this when the AST has been modified and cached results
|
|
207
|
+
* may be stale.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* // After modifying files
|
|
212
|
+
* await project.save();
|
|
213
|
+
* detector.clearCache();
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
clearCache() {
|
|
217
|
+
this.cache.clear();
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Get cache key for a class declaration.
|
|
221
|
+
*
|
|
222
|
+
* @param classDecl - The class declaration
|
|
223
|
+
* @returns Cache key string
|
|
224
|
+
*/
|
|
225
|
+
getCacheKey(classDecl) {
|
|
226
|
+
const filePath = classDecl.getSourceFile().getFilePath();
|
|
227
|
+
const className = classDecl.getName() ?? 'anonymous';
|
|
228
|
+
return `${filePath}:${className}`;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=service-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-detector.js","sourceRoot":"","sources":["../../src/analysis/service-detector.ts"],"names":[],"mappings":"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"}
|