1use anyhow::Result;
4use regex::Regex;
5use std::collections::HashMap;
6
7#[derive(Debug, Clone)]
9pub struct ReactComponentInfo {
10 pub name: String,
11 pub component_type: ComponentType,
12 pub hooks_used: Vec<HookInfo>,
13 pub props_analysis: PropsInfo,
14 pub lifecycle_methods: Vec<String>,
15 pub jsx_elements: Vec<String>,
16 pub context_usage: Vec<ContextInfo>,
17 pub state_management: Vec<StateManagementInfo>,
18}
19
20#[derive(Debug, Clone)]
22pub enum ComponentType {
23 Functional,
24 Class,
25 HigherOrderComponent,
26 ForwardRef,
27 Memo,
28 CustomHook,
29}
30
31#[derive(Debug, Clone)]
33pub struct HookInfo {
34 pub name: String,
35 pub hook_type: String,
36 pub dependencies: Vec<String>,
37 pub custom_hook: bool,
38}
39
40#[derive(Debug, Clone)]
42pub struct ContextInfo {
43 pub context_name: String,
44 pub usage_type: String, pub values_consumed: Vec<String>,
46}
47
48#[derive(Debug, Clone)]
50pub struct StateManagementInfo {
51 pub pattern_type: String, pub state_variables: Vec<String>,
53 pub actions: Vec<String>,
54}
55
56#[derive(Debug, Clone)]
58pub struct PropsInfo {
59 pub prop_names: Vec<String>,
60 pub has_prop_types: bool,
61 pub has_default_props: bool,
62 pub destructured: bool,
63 pub typescript_props: bool,
64}
65
66#[derive(Debug, Clone)]
68pub struct NodeJsPatternInfo {
69 pub pattern_type: NodePatternType,
70 pub framework: String,
71 pub route_info: Option<RouteInfo>,
72 pub middleware_chain: Vec<String>,
73 pub http_methods: Vec<String>,
74 pub database_patterns: Vec<DatabasePatternInfo>,
75}
76
77#[derive(Debug, Clone)]
79pub struct DatabasePatternInfo {
80 pub db_type: String, pub operations: Vec<String>, pub orm_framework: Option<String>, }
84
85#[derive(Debug, Clone)]
87pub enum NodePatternType {
88 ExpressRoute,
89 ExpressMiddleware,
90 FastifyRoute,
91 KoaRoute,
92 DatabaseQuery,
93 ErrorHandler,
94 AuthMiddleware,
95 ApiEndpoint,
96 WebSocketHandler,
97}
98
99#[derive(Debug, Clone)]
101pub struct RouteInfo {
102 pub path: String,
103 pub method: String,
104 pub parameters: Vec<String>,
105 pub query_params: Vec<String>,
106 pub middleware_used: Vec<String>,
107}
108
109#[derive(Debug, Clone)]
111pub struct ModernJsFeatureInfo {
112 pub feature_type: ModernFeatureType,
113 pub usage_pattern: String,
114 pub complexity_score: i32,
115 pub best_practices: Vec<String>,
116 pub typescript_specific: bool,
117}
118
119#[derive(Debug, Clone)]
121pub enum ModernFeatureType {
122 AsyncAwait,
123 Destructuring,
124 SpreadOperator,
125 ArrowFunction,
126 TemplateString,
127 DynamicImport,
128 OptionalChaining,
129 NullishCoalescing,
130 ClassFields,
131 Decorator,
132 TypeScriptInterface,
133 TypeScriptEnum,
134 TypeScriptGenerics,
135 UnionTypes,
137 IntersectionTypes,
138 ConditionalTypes,
139 MappedTypes,
140 TemplateLiteralTypes,
141 TupleTypes,
142}
143
144#[derive(Debug, Clone)]
146pub struct FrameworkInfo {
147 pub name: String,
148 pub confidence: f32,
149 pub version_detected: Option<String>,
150 pub features_used: Vec<String>,
151 pub best_practices: Vec<String>,
152}
153
154#[derive(Debug, Clone)]
156pub struct SecurityAssessment {
157 pub level: SecurityLevel,
158 pub vulnerabilities_detected: Vec<SecurityVulnerability>,
159 pub security_features: Vec<SecurityFeature>,
160 pub recommendations: Vec<String>,
161}
162
163#[derive(Debug, Clone)]
165pub enum SecurityLevel {
166 High, Medium, Low, Vulnerable, }
171
172#[derive(Debug, Clone)]
174pub struct SecurityVulnerability {
175 pub vulnerability_type: VulnerabilityType,
176 pub severity: VulnerabilitySeverity,
177 pub description: String,
178 pub location: String,
179 pub recommendation: String,
180}
181
182#[derive(Debug, Clone)]
184pub enum VulnerabilityType {
185 SqlInjection,
186 XssRisk,
187 CsrfMissing,
188 WeakAuthentication,
189 InsecureDataTransmission,
190 DangerousEval,
191 UnvalidatedInput,
192}
193
194#[derive(Debug, Clone)]
196pub enum VulnerabilitySeverity {
197 Critical,
198 High,
199 Medium,
200 Low,
201 Info,
202}
203
204#[derive(Debug, Clone)]
206pub struct SecurityFeature {
207 pub feature_type: SecurityFeatureType,
208 pub implementation_quality: ImplementationQuality,
209 pub description: String,
210}
211
212#[derive(Debug, Clone)]
214pub enum SecurityFeatureType {
215 Authentication,
216 Authorization,
217 InputValidation,
218 CsrfProtection,
219 DataEncryption,
220 SecureHeaders,
221 RateLimiting,
222}
223
224#[derive(Debug, Clone)]
226pub enum ImplementationQuality {
227 Excellent,
228 Good,
229 Adequate,
230 Poor,
231 Missing,
232}
233
234#[derive(Debug, Clone)]
236pub struct PerformanceAnalysis {
237 pub overall_score: i32,
238 pub optimizations_detected: Vec<PerformanceOptimization>,
239 pub performance_issues: Vec<PerformanceIssue>,
240 pub recommendations: Vec<String>,
241}
242
243#[derive(Debug, Clone)]
245pub struct PerformanceOptimization {
246 pub optimization_type: OptimizationType,
247 pub impact_level: ImpactLevel,
248 pub description: String,
249 pub best_practices_followed: bool,
250}
251
252#[derive(Debug, Clone)]
254pub enum OptimizationType {
255 LazyLoading,
256 CodeSplitting,
257 Memoization,
258 Caching,
259 DatabaseOptimization,
260 BundleOptimization,
261 ImageOptimization,
262 AssetMinification,
263}
264
265#[derive(Debug, Clone)]
267pub struct PerformanceIssue {
268 pub issue_type: PerformanceIssueType,
269 pub severity: IssueSeverity,
270 pub description: String,
271 pub recommendation: String,
272}
273
274#[derive(Debug, Clone)]
276pub enum PerformanceIssueType {
277 LargeBundle,
278 UnoptimizedImages,
279 MissingCaching,
280 InefficientQueries,
281 MemoryLeaks,
282 BlockingOperations,
283 ExcessiveRerendering,
284}
285
286#[derive(Debug, Clone)]
288pub enum IssueSeverity {
289 Critical,
290 High,
291 Medium,
292 Low,
293}
294
295#[derive(Debug, Clone)]
297pub enum ImpactLevel {
298 High, Medium, Low, Positive, }
303
304#[derive(Debug, Clone)]
306pub struct VueComponentInfo {
307 pub name: String,
308 pub component_type: VueComponentType,
309 pub composition_api: bool,
310 pub props: Vec<VuePropsInfo>,
311 pub emits: Vec<String>,
312 pub directives: Vec<VueDirective>,
313 pub lifecycle_hooks: Vec<String>,
314 pub composables: Vec<String>,
315}
316
317#[derive(Debug, Clone)]
319pub enum VueComponentType {
320 SingleFileComponent,
321 OptionsAPI,
322 CompositionAPI,
323 FunctionalComponent,
324 AsyncComponent,
325}
326
327#[derive(Debug, Clone)]
329pub struct VuePropsInfo {
330 pub name: String,
331 pub prop_type: String,
332 pub required: bool,
333 pub default_value: Option<String>,
334 pub validator: bool,
335}
336
337#[derive(Debug, Clone)]
339pub struct VueDirective {
340 pub name: String,
341 pub directive_type: VueDirectiveType,
342 pub has_modifiers: bool,
343 pub dynamic_argument: bool,
344}
345
346#[derive(Debug, Clone)]
348pub enum VueDirectiveType {
349 BuiltIn, Custom, Component, }
353
354#[derive(Debug, Clone)]
356pub struct AngularComponentInfo {
357 pub name: String,
358 pub component_type: AngularComponentType,
359 pub selector: String,
360 pub inputs: Vec<AngularInputInfo>,
361 pub outputs: Vec<AngularOutputInfo>,
362 pub lifecycle_hooks: Vec<String>,
363 pub services: Vec<String>,
364 pub change_detection: ChangeDetectionStrategy,
365}
366
367#[derive(Debug, Clone)]
369pub enum AngularComponentType {
370 Component,
371 Directive,
372 Pipe,
373 Service,
374 Guard,
375 Resolver,
376}
377
378#[derive(Debug, Clone)]
380pub struct AngularInputInfo {
381 pub name: String,
382 pub alias: Option<String>,
383 pub input_type: String,
384 pub required: bool,
385}
386
387#[derive(Debug, Clone)]
389pub struct AngularOutputInfo {
390 pub name: String,
391 pub alias: Option<String>,
392 pub event_type: String,
393}
394
395#[derive(Debug, Clone)]
397pub enum ChangeDetectionStrategy {
398 Default,
399 OnPush,
400 Detached,
401}
402
403#[derive(Debug, Clone)]
405pub struct TypeScriptAnalysisInfo {
406 pub generics_usage: Vec<GenericInfo>,
407 pub type_constraints: Vec<TypeConstraint>,
408 pub utility_types: Vec<UtilityTypeUsage>,
409 pub type_guards: Vec<TypeGuard>,
410 pub conditional_types: Vec<ConditionalType>,
411 pub mapped_types: Vec<MappedType>,
412 pub complexity_score: i32,
413}
414
415#[derive(Debug, Clone)]
417pub struct GenericInfo {
418 pub name: String,
419 pub constraints: Vec<String>,
420 pub default_type: Option<String>,
421 pub variance: TypeVariance,
422 pub usage_context: GenericContext,
423}
424
425#[derive(Debug, Clone)]
427pub enum TypeVariance {
428 Covariant,
429 Contravariant,
430 Invariant,
431 Bivariant,
432}
433
434#[derive(Debug, Clone)]
436pub enum GenericContext {
437 Function,
438 Interface,
439 Class,
440 TypeAlias,
441 Utility,
442}
443
444#[derive(Debug, Clone)]
446pub struct TypeConstraint {
447 pub constraint_type: ConstraintType,
448 pub target_type: String,
449 pub constraint_expression: String,
450 pub complexity: i32,
451}
452
453#[derive(Debug, Clone)]
455pub enum ConstraintType {
456 Extends,
457 Keyof,
458 Typeof,
459 Conditional,
460 Mapped,
461 Template,
462}
463
464#[derive(Debug, Clone)]
466pub struct UtilityTypeUsage {
467 pub utility_name: String,
468 pub usage_pattern: String,
469 pub complexity_impact: i32,
470 pub best_practice_score: f32,
471}
472
473#[derive(Debug, Clone)]
475pub struct TypeGuard {
476 pub guard_type: TypeGuardType,
477 pub target_types: Vec<String>,
478 pub predicate_function: String,
479 pub runtime_safety: bool,
480}
481
482#[derive(Debug, Clone)]
484pub enum TypeGuardType {
485 UserDefined,
486 BuiltIn,
487 AssertionFunction,
488 DiscriminatedUnion,
489}
490
491#[derive(Debug, Clone)]
493pub struct ConditionalType {
494 pub condition: String,
495 pub true_type: String,
496 pub false_type: String,
497 pub complexity_score: i32,
498}
499
500#[derive(Debug, Clone)]
502pub struct MappedType {
503 pub source_type: String,
504 pub transformation: String,
505 pub modifiers: Vec<TypeModifier>,
506 pub complexity_score: i32,
507}
508
509#[derive(Debug, Clone, PartialEq)]
511pub enum TypeModifier {
512 Optional,
513 Required,
514 Readonly,
515 Mutable,
516}
517
518#[derive(Debug, Clone)]
520pub struct WebSocketAnalysis {
521 pub implementation_type: WebSocketImplementationType,
522 pub patterns: Vec<WebSocketPattern>,
523 pub real_time_features: Vec<RealTimeFeature>,
524 pub security_assessment: WebSocketSecurityAssessment,
525 pub performance_metrics: WebSocketPerformanceMetrics,
526}
527
528#[derive(Debug, Clone)]
530pub enum WebSocketImplementationType {
531 SocketIO,
532 NativeWebSocket,
533 SignalR,
534 SockJS,
535 Custom,
536}
537
538#[derive(Debug, Clone)]
540pub struct WebSocketPattern {
541 pub pattern_type: WebSocketPatternType,
542 pub event_handlers: Vec<String>,
543 pub room_management: bool,
544 pub authentication: bool,
545 pub error_handling: bool,
546 pub reconnection_logic: bool,
547}
548
549#[derive(Debug, Clone)]
551pub enum WebSocketPatternType {
552 RealTimeChat,
553 LiveUpdates,
554 GameMultiplayer,
555 CollaborativeEditing,
556 NotificationSystem,
557 StreamingData,
558 FileTransfer,
559}
560
561#[derive(Debug, Clone)]
563pub struct RealTimeFeature {
564 pub feature_name: String,
565 pub implementation_quality: ImplementationQuality,
566 pub scalability_considerations: Vec<String>,
567 pub latency_optimization: bool,
568}
569
570#[derive(Debug, Clone)]
572pub struct WebSocketSecurityAssessment {
573 pub authentication_method: Option<WebSocketAuthMethod>,
574 pub authorization_checks: bool,
575 pub rate_limiting: bool,
576 pub input_validation: bool,
577 pub origin_checks: bool,
578 pub ssl_tls_enforced: bool,
579}
580
581#[derive(Debug, Clone)]
583pub enum WebSocketAuthMethod {
584 Jwt,
585 SessionBased,
586 ApiKey,
587 OAuth,
588 Custom,
589 None,
590}
591
592#[derive(Debug, Clone)]
594pub struct WebSocketPerformanceMetrics {
595 pub connection_pooling: bool,
596 pub message_batching: bool,
597 pub compression_enabled: bool,
598 pub heartbeat_implementation: bool,
599 pub scaling_strategy: ScalingStrategy,
600}
601
602#[derive(Debug, Clone)]
604pub enum ScalingStrategy {
605 SingleInstance,
606 LoadBalanced,
607 Clustered,
608 Microservices,
609 Redis,
610 RabbitMQ,
611}
612
613#[allow(dead_code)] #[derive(Debug, Clone)]
616pub struct AdvancedNodePatternInfo {
617 pub pattern_type: AdvancedNodePatternType,
618 pub middleware_chain: Vec<MiddlewareInfo>,
619 pub error_handling: Vec<ErrorHandlingPattern>,
620 pub performance_indicators: Vec<PerformanceIndicator>,
621 pub microservice_patterns: Vec<MicroservicePattern>,
622 pub database_patterns: Vec<DatabasePattern>,
623}
624
625#[allow(dead_code)] #[derive(Debug, Clone)]
628pub enum AdvancedNodePatternType {
629 SecurityMiddleware,
630 PerformanceMiddleware,
631 WebSocketHandler,
632 MicroserviceGateway,
633 EventDrivenArchitecture,
634 StreamProcessing,
635 BackgroundJobProcessor,
636}
637
638#[allow(dead_code)] #[derive(Debug, Clone)]
641pub struct MiddlewareInfo {
642 pub name: String,
643 pub middleware_type: MiddlewareType,
644 pub order: i32,
645 pub dependencies: Vec<String>,
646 pub security_impact: Option<String>,
647 pub performance_impact: Option<String>,
648}
649
650#[allow(dead_code)] #[derive(Debug, Clone)]
653pub enum MiddlewareType {
654 Authentication,
655 Authorization,
656 RateLimiting,
657 Cors,
658 Logging,
659 Validation,
660 Caching,
661 Compression,
662 ErrorHandling,
663 Custom,
664}
665
666#[allow(dead_code)] #[derive(Debug, Clone)]
669pub struct ErrorHandlingPattern {
670 pub pattern_type: ErrorHandlingType,
671 pub implementation_quality: ImplementationQuality,
672 pub error_classification: Vec<ErrorClassification>,
673 pub recovery_strategies: Vec<String>,
674 pub monitoring_integration: bool,
675}
676
677#[allow(dead_code)] #[derive(Debug, Clone)]
680pub enum ErrorHandlingType {
681 TryCatch,
682 PromiseChain,
683 AsyncAwait,
684 EventEmitter,
685 Circuit,
686 Retry,
687 Fallback,
688}
689
690#[allow(dead_code)] #[derive(Debug, Clone)]
693pub struct ErrorClassification {
694 pub error_type: ErrorType,
695 pub severity: ErrorSeverity,
696 pub handling_strategy: String,
697 pub user_impact: UserImpact,
698}
699
700#[allow(dead_code)] #[allow(clippy::enum_variant_names)] #[derive(Debug, Clone)]
704pub enum ErrorType {
705 ValidationError,
706 AuthenticationError,
707 AuthorizationError,
708 DatabaseError,
709 NetworkError,
710 BusinessLogicError,
711 SystemError,
712 UnknownError,
713}
714
715#[allow(dead_code)] #[derive(Debug, Clone)]
718pub enum ErrorSeverity {
719 Critical,
720 High,
721 Medium,
722 Low,
723 Info,
724}
725
726#[allow(dead_code)] #[derive(Debug, Clone)]
729pub enum UserImpact {
730 ServiceUnavailable,
731 FeatureImpaired,
732 PerformanceDegraded,
733 NoImpact,
734}
735
736#[allow(dead_code)] #[derive(Debug, Clone)]
739pub struct PerformanceIndicator {
740 pub indicator_type: PerformanceType,
741 pub impact_level: ImpactLevel,
742 pub description: String,
743 pub recommendation: String,
744 pub metrics: Option<PerformanceMetrics>,
745}
746
747#[allow(dead_code)] #[derive(Debug, Clone)]
750pub enum PerformanceType {
751 Memory,
752 Cpu,
753 Network,
754 Disk,
755 Database,
756 Caching,
757 Bundling,
758 Rendering,
759}
760
761#[allow(dead_code)] #[derive(Debug, Clone)]
764pub struct PerformanceMetrics {
765 pub response_time: Option<f64>,
766 pub throughput: Option<f64>,
767 pub memory_usage: Option<f64>,
768 pub cpu_usage: Option<f64>,
769 pub error_rate: Option<f64>,
770}
771
772#[allow(dead_code)] #[derive(Debug, Clone)]
775pub struct MicroservicePattern {
776 pub pattern_name: String,
777 pub service_communication: ServiceCommunication,
778 pub data_consistency: DataConsistency,
779 pub fault_tolerance: FaultTolerance,
780 pub monitoring_observability: MonitoringLevel,
781}
782
783#[allow(dead_code)] #[derive(Debug, Clone)]
786pub enum ServiceCommunication {
787 Http,
788 GraphQL,
789 GRpc,
790 MessageQueue,
791 EventStream,
792 WebSocket,
793}
794
795#[allow(dead_code)] #[derive(Debug, Clone)]
798pub enum DataConsistency {
799 Strong,
800 Eventual,
801 Weak,
802 Session,
803 Causal,
804}
805
806#[allow(dead_code)] #[derive(Debug, Clone)]
809pub enum FaultTolerance {
810 CircuitBreaker,
811 Retry,
812 Timeout,
813 Bulkhead,
814 Fallback,
815 None,
816}
817
818#[allow(dead_code)] #[derive(Debug, Clone)]
821pub enum MonitoringLevel {
822 Comprehensive,
823 Basic,
824 Minimal,
825 None,
826}
827
828#[allow(dead_code)] #[derive(Debug, Clone)]
831pub struct DatabasePattern {
832 pub database_type: DatabaseType,
833 pub access_pattern: DatabaseAccessPattern,
834 pub optimization_level: OptimizationLevel,
835 pub connection_management: ConnectionManagement,
836 pub transaction_handling: TransactionHandling,
837}
838
839#[allow(dead_code)] #[derive(Debug, Clone)]
842pub enum DatabaseType {
843 PostgreSQL,
844 MySQL,
845 MongoDB,
846 Redis,
847 Elasticsearch,
848 SQLite,
849 Cassandra,
850 DynamoDB,
851}
852
853#[allow(dead_code)] #[derive(Debug, Clone)]
856pub enum DatabaseAccessPattern {
857 DirectAccess,
858 Orm,
859 QueryBuilder,
860 Repository,
861 ActiveRecord,
862 DataMapper,
863}
864
865#[allow(dead_code)] #[derive(Debug, Clone)]
868pub enum OptimizationLevel {
869 High,
870 Medium,
871 Low,
872 None,
873}
874
875#[allow(dead_code)] #[derive(Debug, Clone)]
878pub enum ConnectionManagement {
879 Pool,
880 SingleConnection,
881 PerRequest,
882 Lazy,
883 Cached,
884}
885
886#[allow(dead_code)] #[derive(Debug, Clone)]
889pub enum TransactionHandling {
890 Acid,
891 Eventually,
892 TwoPhase,
893 Saga,
894 Compensating,
895 None,
896}
897
898pub struct JavaScriptAnalyzer {
900 framework_patterns: HashMap<String, Regex>,
901 react_patterns: HashMap<String, Regex>,
902 nodejs_patterns: HashMap<String, Regex>,
903 typescript_patterns: HashMap<String, Regex>,
904 vue_patterns: HashMap<String, Regex>,
905 angular_patterns: HashMap<String, Regex>,
906 security_patterns: HashMap<String, Regex>,
908 performance_patterns: HashMap<String, Regex>,
909 websocket_patterns: HashMap<String, Regex>,
910 advanced_typescript_patterns: HashMap<String, Regex>,
911}
912
913impl JavaScriptAnalyzer {
914 pub fn new() -> Self {
915 let mut analyzer = Self {
916 framework_patterns: HashMap::new(),
917 react_patterns: HashMap::new(),
918 nodejs_patterns: HashMap::new(),
919 typescript_patterns: HashMap::new(),
920 vue_patterns: HashMap::new(),
921 angular_patterns: HashMap::new(),
922 security_patterns: HashMap::new(),
923 performance_patterns: HashMap::new(),
924 websocket_patterns: HashMap::new(),
925 advanced_typescript_patterns: HashMap::new(),
926 };
927 analyzer.initialize_patterns();
928 analyzer
929 }
930
931 fn initialize_patterns(&mut self) {
932 self.framework_patterns.insert(
934 "React".to_string(),
935 Regex::new(r"import React|from.*react|jsx|\.jsx").unwrap(),
936 );
937 self.framework_patterns.insert(
938 "Express".to_string(),
939 Regex::new(r"express\(\)|app\.\w+\(").unwrap(),
940 );
941 self.framework_patterns.insert(
942 "Vue".to_string(),
943 Regex::new(r"Vue\.|new Vue|@Component|\.vue|v-if|v-for").unwrap(),
944 );
945 self.framework_patterns.insert(
946 "Angular".to_string(),
947 Regex::new(r"@Component|@Injectable|@NgModule|angular|\.component\.ts").unwrap(),
948 );
949 self.framework_patterns.insert(
950 "Next.js".to_string(),
951 Regex::new(r"next/|getStaticProps|getServerSideProps|pages/").unwrap(),
952 );
953
954 self.react_patterns.insert(
956 "useState".to_string(),
957 Regex::new(r"useState\s*\(").unwrap(),
958 );
959 self.react_patterns.insert(
960 "useEffect".to_string(),
961 Regex::new(r"useEffect\s*\(").unwrap(),
962 );
963 self.react_patterns.insert(
964 "useContext".to_string(),
965 Regex::new(r"useContext\s*\(").unwrap(),
966 );
967 self.react_patterns.insert(
968 "useReducer".to_string(),
969 Regex::new(r"useReducer\s*\(").unwrap(),
970 );
971 self.react_patterns
972 .insert("useMemo".to_string(), Regex::new(r"useMemo\s*\(").unwrap());
973 self.react_patterns.insert(
974 "useCallback".to_string(),
975 Regex::new(r"useCallback\s*\(").unwrap(),
976 );
977 self.react_patterns
978 .insert("useRef".to_string(), Regex::new(r"useRef\s*\(").unwrap());
979 self.react_patterns.insert(
980 "custom_hook".to_string(),
981 Regex::new(r"function\s+use[A-Z]\w*|const\s+use[A-Z]\w*\s*=").unwrap(),
982 );
983 self.react_patterns.insert(
984 "context_provider".to_string(),
985 Regex::new(r"\.Provider|createContext|React\.createContext").unwrap(),
986 );
987 self.react_patterns.insert(
988 "hoc".to_string(),
989 Regex::new(r"function\s+with[A-Z]\w*|const\s+with[A-Z]\w*").unwrap(),
990 );
991
992 self.nodejs_patterns.insert(
994 "route".to_string(),
995 Regex::new(r"app\.(get|post|put|delete|patch)\s*\(").unwrap(),
996 );
997 self.nodejs_patterns.insert(
998 "middleware".to_string(),
999 Regex::new(r"app\.use\s*\(|function\s*\(\s*req\s*,\s*res\s*,\s*next\s*\)").unwrap(),
1000 );
1001 self.nodejs_patterns.insert(
1002 "mongodb".to_string(),
1003 Regex::new(r"mongoose\.|\.find\(|\.findOne\(|\.save\(|\.updateOne\(").unwrap(),
1004 );
1005 self.nodejs_patterns.insert(
1006 "postgresql".to_string(),
1007 Regex::new(r"pg\.|pool\.query|client\.query|SELECT\s+\*\s+FROM").unwrap(),
1008 );
1009 self.nodejs_patterns.insert(
1010 "redis".to_string(),
1011 Regex::new(r"redis\.|\.get\(|\.set\(|\.hget\(|\.hset\(").unwrap(),
1012 );
1013
1014 self.typescript_patterns.insert(
1016 "interface".to_string(),
1017 Regex::new(r"interface\s+[A-Z]\w*").unwrap(),
1018 );
1019 self.typescript_patterns.insert(
1020 "type_alias".to_string(),
1021 Regex::new(r"type\s+[A-Z]\w*\s*=").unwrap(),
1022 );
1023 self.typescript_patterns
1024 .insert("enum".to_string(), Regex::new(r"enum\s+[A-Z]\w*").unwrap());
1025 self.typescript_patterns.insert(
1026 "generics".to_string(),
1027 Regex::new(r"<[A-Z]\w*(?:\s*,\s*[A-Z]\w*)*>").unwrap(),
1028 );
1029 self.typescript_patterns
1030 .insert("decorators".to_string(), Regex::new(r"@\w+\s*\(").unwrap());
1031
1032 self.vue_patterns.insert(
1034 "single_file_component".to_string(),
1035 Regex::new(r"<template>|<script>|<style>").unwrap(),
1036 );
1037 self.vue_patterns.insert(
1038 "composition_api".to_string(),
1039 Regex::new(r"setup\s*\(|ref\s*\(|reactive\s*\(|computed\s*\(").unwrap(),
1040 );
1041 self.vue_patterns.insert(
1042 "options_api".to_string(),
1043 Regex::new(r"data\s*\(\s*\)|methods\s*:|computed\s*:|watch\s*:").unwrap(),
1044 );
1045 self.vue_patterns.insert(
1046 "directives".to_string(),
1047 Regex::new(r"v-if|v-for|v-model|v-show|v-bind|v-on").unwrap(),
1048 );
1049 self.vue_patterns.insert(
1050 "composables".to_string(),
1051 Regex::new(r"use[A-Z]\w*\s*\(").unwrap(),
1052 );
1053
1054 self.angular_patterns.insert(
1056 "component_decorator".to_string(),
1057 Regex::new(r"@Component\s*\(\s*\{").unwrap(),
1058 );
1059 self.angular_patterns.insert(
1060 "service_decorator".to_string(),
1061 Regex::new(r"@Injectable\s*\(\s*\{").unwrap(),
1062 );
1063 self.angular_patterns.insert(
1064 "input_output".to_string(),
1065 Regex::new(r"@Input\s*\(\s*\)|@Output\s*\(\s*\)").unwrap(),
1066 );
1067 self.angular_patterns.insert(
1068 "lifecycle_hooks".to_string(),
1069 Regex::new(r"ngOnInit|ngOnDestroy|ngOnChanges|ngAfterViewInit").unwrap(),
1070 );
1071 self.angular_patterns.insert(
1072 "dependency_injection".to_string(),
1073 Regex::new(r"constructor\s*\(\s*private|inject\s*\(").unwrap(),
1074 );
1075
1076 self.security_patterns.insert(
1078 "authentication_middleware".to_string(),
1079 Regex::new(r"passport\.|jwt\.|authenticate\s*\(|verify\s*\(").unwrap(),
1080 );
1081 self.security_patterns.insert(
1082 "input_validation".to_string(),
1083 Regex::new(r"validate\s*\(|sanitize\s*\(|escape\s*\(|joi\.|yup\.").unwrap(),
1084 );
1085 self.security_patterns.insert(
1086 "csrf_protection".to_string(),
1087 Regex::new(r"csrf\.|csrfToken|__RequestVerificationToken").unwrap(),
1088 );
1089 self.security_patterns.insert(
1090 "sql_injection_risk".to_string(),
1091 Regex::new(r"query\s*\(\s*.*\$\{|execute\s*\(\s*.*\+").unwrap(),
1092 );
1093 self.security_patterns.insert(
1094 "xss_vulnerability".to_string(),
1095 Regex::new(r"innerHTML\s*=|dangerouslySetInnerHTML|eval\s*\(").unwrap(),
1096 );
1097
1098 self.performance_patterns.insert(
1100 "lazy_loading".to_string(),
1101 Regex::new(r"lazy\s*\(|import\s*\(|React\.lazy|defineAsyncComponent").unwrap(),
1102 );
1103 self.performance_patterns.insert(
1104 "memoization".to_string(),
1105 Regex::new(r"useMemo\s*\(|useCallback\s*\(|memo\s*\(|React\.memo").unwrap(),
1106 );
1107 self.performance_patterns.insert(
1108 "caching".to_string(),
1109 Regex::new(r"cache\.|redis\.|localStorage|sessionStorage").unwrap(),
1110 );
1111 self.performance_patterns.insert(
1112 "database_optimization".to_string(),
1113 Regex::new(r"\.populate\s*\(|\.select\s*\(|\.limit\s*\(|\.sort\s*\(").unwrap(),
1114 );
1115
1116 self.websocket_patterns.insert(
1118 "socket_io".to_string(),
1119 Regex::new(r"socket\.io|io\s*\(|socket\.emit|socket\.on").unwrap(),
1120 );
1121 self.websocket_patterns.insert(
1122 "native_websocket".to_string(),
1123 Regex::new(r"new WebSocket\s*\(|ws\.|WebSocketServer").unwrap(),
1124 );
1125 self.websocket_patterns.insert(
1126 "room_management".to_string(),
1127 Regex::new(r"\.join\s*\(|\.leave\s*\(|\.to\s*\(|\.in\s*\(").unwrap(),
1128 );
1129
1130 self.advanced_typescript_patterns.insert(
1132 "union_intersection".to_string(),
1133 Regex::new(r"\w+\s*\|\s*\w+|\w+\s*&\s*\w+").unwrap(),
1134 );
1135 self.advanced_typescript_patterns.insert(
1136 "conditional_types".to_string(),
1137 Regex::new(r"extends\s+[^?]+\?\s*[^:]+\s*:\s*\w+").unwrap(),
1138 );
1139 self.advanced_typescript_patterns.insert(
1140 "mapped_types".to_string(),
1141 Regex::new(r"Partial<|Required<|Readonly<|Pick<|Omit<|\[\s*\w+\s+in\s+keyof").unwrap(),
1142 );
1143 self.advanced_typescript_patterns.insert(
1144 "utility_types".to_string(),
1145 Regex::new(r"Record<|Exclude<|Extract<|ReturnType<|Parameters<|keyof\s+\w+").unwrap(),
1146 );
1147 }
1148
1149 pub fn detect_frameworks(&self, content: &str) -> Result<Vec<FrameworkInfo>> {
1151 let mut frameworks = Vec::new();
1152
1153 for (framework_name, pattern) in &self.framework_patterns {
1154 if pattern.is_match(content) {
1155 let (confidence, features) = self.analyze_framework_usage(framework_name, content);
1156
1157 frameworks.push(FrameworkInfo {
1158 name: framework_name.clone(),
1159 confidence,
1160 version_detected: self.detect_framework_version(framework_name, content),
1161 features_used: features,
1162 best_practices: self.get_framework_recommendations(framework_name),
1163 });
1164 }
1165 }
1166
1167 Ok(frameworks)
1168 }
1169
1170 fn analyze_framework_usage(&self, framework: &str, content: &str) -> (f32, Vec<String>) {
1171 let mut confidence: f32 = match framework {
1172 "React" => 0.7,
1173 "Express" => 0.7,
1174 "Vue" => 0.7,
1175 "Angular" => 0.7,
1176 "Next.js" => 0.7,
1177 _ => 0.5,
1178 };
1179
1180 let mut features = Vec::new();
1181
1182 match framework {
1183 "React" => {
1184 if content.contains("useState") {
1185 confidence += 0.1;
1186 features.push("Hooks".to_string());
1187 }
1188 if content.contains("JSX") || content.contains("<") {
1189 confidence += 0.1;
1190 features.push("JSX".to_string());
1191 }
1192 if content.contains("Component") {
1193 confidence += 0.05;
1194 features.push("Components".to_string());
1195 }
1196 }
1197 "Express" => {
1198 if content.contains("app.get") || content.contains("app.post") {
1199 confidence += 0.1;
1200 features.push("Routing".to_string());
1201 }
1202 if content.contains("middleware") {
1203 confidence += 0.05;
1204 features.push("Middleware".to_string());
1205 }
1206 }
1207 "Vue" => {
1208 if content.contains("v-if") || content.contains("v-for") {
1209 confidence += 0.1;
1210 features.push("Directives".to_string());
1211 }
1212 if content.contains("@Component") {
1213 confidence += 0.1;
1214 features.push("Components".to_string());
1215 }
1216 }
1217 "Angular" => {
1218 if content.contains("@Component") {
1219 confidence += 0.15;
1220 features.push("Components".to_string());
1221 }
1222 if content.contains("@Injectable") {
1223 confidence += 0.1;
1224 features.push("Services".to_string());
1225 }
1226 }
1227 _ => {}
1228 }
1229
1230 (confidence.min(1.0), features)
1231 }
1232
1233 fn detect_framework_version(&self, _framework: &str, _content: &str) -> Option<String> {
1234 None
1236 }
1237
1238 fn get_framework_recommendations(&self, framework: &str) -> Vec<String> {
1239 match framework {
1240 "React" => vec![
1241 "Use functional components with hooks".to_string(),
1242 "Implement proper error boundaries".to_string(),
1243 "Use React.memo for performance optimization".to_string(),
1244 ],
1245 "Express" => vec![
1246 "Add proper error handling middleware".to_string(),
1247 "Implement request validation".to_string(),
1248 "Use helmet for security headers".to_string(),
1249 ],
1250 "Vue" => vec![
1251 "Use composition API for better type safety".to_string(),
1252 "Implement proper component naming conventions".to_string(),
1253 ],
1254 "Angular" => vec![
1255 "Use OnPush change detection strategy".to_string(),
1256 "Implement proper dependency injection".to_string(),
1257 "Use reactive forms for complex forms".to_string(),
1258 ],
1259 _ => vec!["Follow framework best practices".to_string()],
1260 }
1261 }
1262
1263 pub fn analyze_react_patterns(&self, content: &str) -> Result<Vec<ReactComponentInfo>> {
1265 let mut components = Vec::new();
1266 let functional_component_pattern =
1267 Regex::new(r"function\s+([A-Z]\w*)\s*\(|const\s+([A-Z]\w*)\s*=\s*\([^)]*\)\s*=>")?;
1268 let class_component_pattern =
1269 Regex::new(r"class\s+([A-Z]\w*)\s+extends\s+(?:React\.)?Component")?;
1270
1271 for captures in functional_component_pattern.captures_iter(content) {
1273 let component_name = captures
1274 .get(1)
1275 .or_else(|| captures.get(2))
1276 .unwrap()
1277 .as_str()
1278 .to_string();
1279
1280 let hooks_used = self.analyze_hooks_usage(content)?;
1281 let context_usage = self.analyze_context_usage(content)?;
1282 let state_management = self.analyze_state_management(content)?;
1283 let jsx_elements = self.extract_jsx_elements(content)?;
1284
1285 components.push(ReactComponentInfo {
1286 name: component_name,
1287 component_type: if content.contains(&format!("use{}", "")) {
1288 ComponentType::CustomHook
1289 } else {
1290 ComponentType::Functional
1291 },
1292 hooks_used,
1293 props_analysis: self.analyze_props(content)?,
1294 lifecycle_methods: Vec::new(), jsx_elements,
1296 context_usage,
1297 state_management,
1298 });
1299 }
1300
1301 for captures in class_component_pattern.captures_iter(content) {
1303 let component_name = captures.get(1).unwrap().as_str().to_string();
1304 let lifecycle_methods = self.detect_lifecycle_methods(content)?;
1305 let jsx_elements = self.extract_jsx_elements(content)?;
1306
1307 components.push(ReactComponentInfo {
1308 name: component_name,
1309 component_type: ComponentType::Class,
1310 hooks_used: Vec::new(), props_analysis: self.analyze_props(content)?,
1312 lifecycle_methods,
1313 jsx_elements,
1314 context_usage: Vec::new(), state_management: Vec::new(), });
1317 }
1318
1319 Ok(components)
1320 }
1321
1322 fn analyze_hooks_usage(&self, content: &str) -> Result<Vec<HookInfo>> {
1323 let mut hooks = Vec::new();
1324
1325 let hook_types = vec![
1326 ("useState", "state"),
1327 ("useEffect", "effect"),
1328 ("useContext", "context"),
1329 ("useReducer", "reducer"),
1330 ("useMemo", "memoization"),
1331 ("useCallback", "callback"),
1332 ("useRef", "reference"),
1333 ];
1334
1335 for (hook_name, hook_type) in hook_types {
1336 if let Some(pattern) = self.react_patterns.get(hook_name) {
1337 if pattern.is_match(content) {
1338 let dependencies = self.extract_hook_dependencies(content, hook_name);
1339 hooks.push(HookInfo {
1340 name: hook_name.to_string(),
1341 hook_type: hook_type.to_string(),
1342 dependencies,
1343 custom_hook: false,
1344 });
1345 }
1346 }
1347 }
1348
1349 if let Some(custom_hook_pattern) = self.react_patterns.get("custom_hook") {
1351 for _captures in custom_hook_pattern.captures_iter(content) {
1352 hooks.push(HookInfo {
1353 name: "custom_hook".to_string(),
1354 hook_type: "custom".to_string(),
1355 dependencies: Vec::new(),
1356 custom_hook: true,
1357 });
1358 }
1359 }
1360
1361 Ok(hooks)
1362 }
1363
1364 fn analyze_context_usage(&self, content: &str) -> Result<Vec<ContextInfo>> {
1365 let mut context_usage = Vec::new();
1366
1367 let context_provider_pattern = Regex::new(r"(\w+)\.Provider")?;
1368 let use_context_pattern = Regex::new(r"useContext\s*\(\s*(\w+)\s*\)")?;
1369 let _create_context_pattern = Regex::new(r"createContext\s*\(\s*([^)]*)\s*\)")?;
1370
1371 for captures in context_provider_pattern.captures_iter(content) {
1373 let context_name = captures.get(1).unwrap().as_str().to_string();
1374 context_usage.push(ContextInfo {
1375 context_name,
1376 usage_type: "provider".to_string(),
1377 values_consumed: Vec::new(),
1378 });
1379 }
1380
1381 for captures in use_context_pattern.captures_iter(content) {
1383 let context_name = captures.get(1).unwrap().as_str().to_string();
1384 context_usage.push(ContextInfo {
1385 context_name,
1386 usage_type: "useContext".to_string(),
1387 values_consumed: Vec::new(),
1388 });
1389 }
1390
1391 Ok(context_usage)
1392 }
1393
1394 fn analyze_state_management(&self, content: &str) -> Result<Vec<StateManagementInfo>> {
1395 let mut state_management = Vec::new();
1396
1397 if content.contains("useSelector")
1399 || content.contains("useDispatch")
1400 || content.contains("connect")
1401 {
1402 state_management.push(StateManagementInfo {
1403 pattern_type: "redux".to_string(),
1404 state_variables: self.extract_redux_state_variables(content),
1405 actions: self.extract_redux_actions(content),
1406 });
1407 }
1408
1409 if content.contains("create(") && content.contains("useStore") {
1411 state_management.push(StateManagementInfo {
1412 pattern_type: "zustand".to_string(),
1413 state_variables: Vec::new(),
1414 actions: Vec::new(),
1415 });
1416 }
1417
1418 Ok(state_management)
1419 }
1420
1421 fn extract_hook_dependencies(&self, content: &str, hook_name: &str) -> Vec<String> {
1422 let pattern = format!(r"{hook_name}[^;]*?\[([^\]]*)\]");
1423 if let Ok(regex) = Regex::new(&pattern) {
1424 if let Some(captures) = regex.captures(content) {
1425 let deps = captures.get(1).unwrap().as_str();
1426 return deps
1427 .split(',')
1428 .map(|s| s.trim().to_string())
1429 .filter(|s| !s.is_empty())
1430 .collect();
1431 }
1432 }
1433 Vec::new()
1434 }
1435
1436 fn extract_redux_state_variables(&self, _content: &str) -> Vec<String> {
1437 Vec::new()
1439 }
1440
1441 fn extract_redux_actions(&self, _content: &str) -> Vec<String> {
1442 Vec::new()
1444 }
1445
1446 fn detect_lifecycle_methods(&self, content: &str) -> Result<Vec<String>> {
1447 let lifecycle_methods = vec![
1448 "componentDidMount",
1449 "componentDidUpdate",
1450 "componentWillUnmount",
1451 "componentDidCatch",
1452 "getSnapshotBeforeUpdate",
1453 "getDerivedStateFromProps",
1454 "shouldComponentUpdate",
1455 "render",
1456 "constructor",
1457 ];
1458
1459 let mut found_methods = Vec::new();
1460 for method in lifecycle_methods {
1461 let pattern = format!(r"{method}s*\(");
1462 if Regex::new(&pattern)?.is_match(content) {
1463 found_methods.push(method.to_string());
1464 }
1465 }
1466
1467 Ok(found_methods)
1468 }
1469
1470 fn analyze_props(&self, content: &str) -> Result<PropsInfo> {
1471 let destructuring_pattern = Regex::new(r"\{\s*([^}]+)\s*\}\s*=\s*props")?;
1472 let prop_types_pattern = Regex::new(r"\.propTypes\s*=")?;
1473 let typescript_props_pattern = Regex::new(r":\s*\w+Props")?;
1474
1475 let mut prop_names = Vec::new();
1476 let destructured = destructuring_pattern.is_match(content);
1477
1478 if let Some(captures) = destructuring_pattern.captures(content) {
1479 let props_str = captures.get(1).unwrap().as_str();
1480 prop_names = props_str
1481 .split(',')
1482 .map(|p| p.trim().to_string())
1483 .filter(|p| !p.is_empty())
1484 .collect();
1485 }
1486
1487 Ok(PropsInfo {
1488 prop_names,
1489 has_prop_types: prop_types_pattern.is_match(content),
1490 has_default_props: false,
1491 destructured,
1492 typescript_props: typescript_props_pattern.is_match(content),
1493 })
1494 }
1495
1496 fn extract_jsx_elements(&self, content: &str) -> Result<Vec<String>> {
1497 let jsx_pattern = Regex::new(r"<([A-Z]\w*)")?;
1498 let mut elements = Vec::new();
1499
1500 for captures in jsx_pattern.captures_iter(content) {
1501 let element = captures.get(1).unwrap().as_str().to_string();
1502 if !elements.contains(&element) {
1503 elements.push(element);
1504 }
1505 }
1506
1507 Ok(elements)
1508 }
1509
1510 pub fn analyze_nodejs_patterns(&self, content: &str) -> Result<Vec<NodeJsPatternInfo>> {
1512 let mut patterns = Vec::new();
1513
1514 if self.nodejs_patterns.get("route").unwrap().is_match(content) {
1515 let database_patterns = self.analyze_database_patterns(content)?;
1516
1517 patterns.push(NodeJsPatternInfo {
1518 pattern_type: NodePatternType::ExpressRoute,
1519 framework: "Express".to_string(),
1520 route_info: self.extract_route_info(content),
1521 middleware_chain: self.extract_middleware_chain(content),
1522 http_methods: vec!["GET".to_string(), "POST".to_string()],
1523 database_patterns,
1524 });
1525 }
1526
1527 if self
1528 .nodejs_patterns
1529 .get("middleware")
1530 .unwrap()
1531 .is_match(content)
1532 {
1533 patterns.push(NodeJsPatternInfo {
1534 pattern_type: NodePatternType::ExpressMiddleware,
1535 framework: "Express".to_string(),
1536 route_info: None,
1537 middleware_chain: Vec::new(),
1538 http_methods: Vec::new(),
1539 database_patterns: Vec::new(),
1540 });
1541 }
1542
1543 Ok(patterns)
1544 }
1545
1546 fn analyze_database_patterns(&self, content: &str) -> Result<Vec<DatabasePatternInfo>> {
1547 let mut db_patterns = Vec::new();
1548
1549 if self
1551 .nodejs_patterns
1552 .get("mongodb")
1553 .unwrap()
1554 .is_match(content)
1555 {
1556 db_patterns.push(DatabasePatternInfo {
1557 db_type: "mongodb".to_string(),
1558 operations: self.extract_db_operations(content, "mongodb"),
1559 orm_framework: if content.contains("mongoose") {
1560 Some("mongoose".to_string())
1561 } else {
1562 None
1563 },
1564 });
1565 }
1566
1567 if self
1569 .nodejs_patterns
1570 .get("postgresql")
1571 .unwrap()
1572 .is_match(content)
1573 {
1574 db_patterns.push(DatabasePatternInfo {
1575 db_type: "postgresql".to_string(),
1576 operations: self.extract_db_operations(content, "postgresql"),
1577 orm_framework: self.detect_orm_framework(content),
1578 });
1579 }
1580
1581 if self.nodejs_patterns.get("redis").unwrap().is_match(content) {
1583 db_patterns.push(DatabasePatternInfo {
1584 db_type: "redis".to_string(),
1585 operations: self.extract_db_operations(content, "redis"),
1586 orm_framework: None,
1587 });
1588 }
1589
1590 Ok(db_patterns)
1591 }
1592
1593 fn extract_db_operations(&self, content: &str, db_type: &str) -> Vec<String> {
1594 let mut operations = Vec::new();
1595
1596 let patterns = match db_type {
1597 "mongodb" => vec![
1598 "find",
1599 "findOne",
1600 "save",
1601 "updateOne",
1602 "deleteOne",
1603 "insertOne",
1604 ],
1605 "postgresql" => vec!["SELECT", "INSERT", "UPDATE", "DELETE"],
1606 "redis" => vec!["get", "set", "hget", "hset", "lpush", "rpop"],
1607 _ => vec![],
1608 };
1609
1610 for operation in patterns {
1611 if content.contains(operation) {
1612 operations.push(operation.to_string());
1613 }
1614 }
1615
1616 operations
1617 }
1618
1619 fn detect_orm_framework(&self, content: &str) -> Option<String> {
1620 if content.contains("prisma") {
1621 Some("prisma".to_string())
1622 } else if content.contains("typeorm") {
1623 Some("typeorm".to_string())
1624 } else if content.contains("sequelize") {
1625 Some("sequelize".to_string())
1626 } else {
1627 None
1628 }
1629 }
1630
1631 fn extract_route_info(&self, content: &str) -> Option<RouteInfo> {
1632 let route_pattern = Regex::new(r"app\.(\w+)\s*\(").unwrap();
1634
1635 if let Some(captures) = route_pattern.captures(content) {
1636 let method = captures.get(1).unwrap().as_str().to_uppercase();
1637
1638 Some(RouteInfo {
1639 path: "/unknown".to_string(), method,
1641 parameters: Vec::new(),
1642 query_params: Vec::new(),
1643 middleware_used: Vec::new(),
1644 })
1645 } else {
1646 None
1647 }
1648 }
1649
1650 #[allow(dead_code)] fn extract_route_parameters(&self, path: &str) -> Vec<String> {
1652 let param_pattern = Regex::new(r":(\w+)").unwrap();
1653 param_pattern
1654 .captures_iter(path)
1655 .map(|cap| cap.get(1).unwrap().as_str().to_string())
1656 .collect()
1657 }
1658
1659 fn extract_middleware_chain(&self, _content: &str) -> Vec<String> {
1660 Vec::new()
1662 }
1663
1664 pub fn analyze_modern_js_features(&self, content: &str) -> Result<Vec<ModernJsFeatureInfo>> {
1666 let mut features = Vec::new();
1667
1668 let async_pattern = Regex::new(r"async\s+function|await\s+")?;
1670 if async_pattern.is_match(content) {
1671 features.push(ModernJsFeatureInfo {
1672 feature_type: ModernFeatureType::AsyncAwait,
1673 usage_pattern: "async/await".to_string(),
1674 complexity_score: 3,
1675 best_practices: vec!["Handle errors with try/catch".to_string()],
1676 typescript_specific: false,
1677 });
1678 }
1679
1680 let destructuring_pattern = Regex::new(r"(?:const|let|var)\s*\{[^}]+\}\s*=")?;
1682 if destructuring_pattern.is_match(content) {
1683 features.push(ModernJsFeatureInfo {
1684 feature_type: ModernFeatureType::Destructuring,
1685 usage_pattern: "object/array destructuring".to_string(),
1686 complexity_score: 2,
1687 best_practices: vec!["Use default values for optional properties".to_string()],
1688 typescript_specific: false,
1689 });
1690 }
1691
1692 let optional_chaining_pattern = Regex::new(r"\?\.")?;
1694 if optional_chaining_pattern.is_match(content) {
1695 features.push(ModernJsFeatureInfo {
1696 feature_type: ModernFeatureType::OptionalChaining,
1697 usage_pattern: "optional chaining operator".to_string(),
1698 complexity_score: 2,
1699 best_practices: vec!["Prefer over manual null checks".to_string()],
1700 typescript_specific: false,
1701 });
1702 }
1703
1704 if let Some(interface_pattern) = self.typescript_patterns.get("interface") {
1706 if interface_pattern.is_match(content) {
1707 features.push(ModernJsFeatureInfo {
1708 feature_type: ModernFeatureType::TypeScriptInterface,
1709 usage_pattern: "TypeScript interfaces".to_string(),
1710 complexity_score: 3,
1711 best_practices: vec!["Use interfaces for object shape definitions".to_string()],
1712 typescript_specific: true,
1713 });
1714 }
1715 }
1716
1717 if let Some(enum_pattern) = self.typescript_patterns.get("enum") {
1718 if enum_pattern.is_match(content) {
1719 features.push(ModernJsFeatureInfo {
1720 feature_type: ModernFeatureType::TypeScriptEnum,
1721 usage_pattern: "TypeScript enums".to_string(),
1722 complexity_score: 2,
1723 best_practices: vec![
1724 "Consider const assertions for better performance".to_string()
1725 ],
1726 typescript_specific: true,
1727 });
1728 }
1729 }
1730
1731 Ok(features)
1732 }
1733
1734 pub fn get_comprehensive_recommendations(
1736 &self,
1737 frameworks: &[FrameworkInfo],
1738 components: &[ReactComponentInfo],
1739 nodejs_patterns: &[NodeJsPatternInfo],
1740 modern_features: &[ModernJsFeatureInfo],
1741 ) -> Vec<String> {
1742 let mut recommendations = Vec::new();
1743
1744 for framework in frameworks {
1746 recommendations.extend(framework.best_practices.clone());
1747 }
1748
1749 if !components.is_empty() {
1751 let functional_count = components
1752 .iter()
1753 .filter(|c| matches!(c.component_type, ComponentType::Functional))
1754 .count();
1755 let class_count = components
1756 .iter()
1757 .filter(|c| matches!(c.component_type, ComponentType::Class))
1758 .count();
1759
1760 if class_count > functional_count {
1761 recommendations.push("Consider migrating class components to functional components with hooks for better performance and maintainability".to_string());
1762 }
1763
1764 let components_without_props = components
1765 .iter()
1766 .filter(|c| !c.props_analysis.typescript_props && !c.props_analysis.has_prop_types)
1767 .count();
1768 if components_without_props > 0 {
1769 recommendations.push("Add TypeScript interfaces or PropTypes for better type safety and development experience".to_string());
1770 }
1771
1772 for component in components {
1774 if component
1775 .hooks_used
1776 .iter()
1777 .any(|h| h.name == "useEffect" && h.dependencies.is_empty())
1778 {
1779 recommendations.push(
1780 "Specify dependencies array for useEffect to prevent infinite re-renders"
1781 .to_string(),
1782 );
1783 break;
1784 }
1785 }
1786 }
1787
1788 for pattern in nodejs_patterns {
1790 if pattern.database_patterns.is_empty()
1791 && matches!(pattern.pattern_type, NodePatternType::ExpressRoute)
1792 {
1793 recommendations.push(
1794 "Consider adding database integration for persistent data storage".to_string(),
1795 );
1796 }
1797
1798 if pattern.middleware_chain.is_empty() {
1799 recommendations.push(
1800 "Add authentication and validation middleware to secure API endpoints"
1801 .to_string(),
1802 );
1803 }
1804 }
1805
1806 let async_usage = modern_features
1808 .iter()
1809 .any(|f| matches!(f.feature_type, ModernFeatureType::AsyncAwait));
1810 if async_usage {
1811 recommendations.push(
1812 "Ensure proper error handling with try/catch blocks for async operations"
1813 .to_string(),
1814 );
1815 }
1816
1817 let typescript_usage = modern_features.iter().any(|f| f.typescript_specific);
1818 if !typescript_usage {
1819 recommendations.push(
1820 "Consider adopting TypeScript for better type safety and developer experience"
1821 .to_string(),
1822 );
1823 }
1824
1825 recommendations
1827 .push("Use ESLint and Prettier for consistent code formatting and quality".to_string());
1828 recommendations
1829 .push("Implement comprehensive testing with unit and integration tests".to_string());
1830 recommendations.push(
1831 "Consider using a state management solution for complex applications".to_string(),
1832 );
1833
1834 recommendations
1835 }
1836
1837 pub fn analyze_vue_patterns(&self, content: &str) -> Result<Vec<VueComponentInfo>> {
1841 let mut components = Vec::new();
1842
1843 if self
1845 .vue_patterns
1846 .get("single_file_component")
1847 .unwrap()
1848 .is_match(content)
1849 {
1850 let component_name = "VueComponent".to_string(); let composition_api = self
1853 .vue_patterns
1854 .get("composition_api")
1855 .unwrap()
1856 .is_match(content);
1857 let options_api = self
1858 .vue_patterns
1859 .get("options_api")
1860 .unwrap()
1861 .is_match(content);
1862
1863 let component_type = if composition_api {
1864 VueComponentType::CompositionAPI
1865 } else if options_api {
1866 VueComponentType::OptionsAPI
1867 } else {
1868 VueComponentType::SingleFileComponent
1869 };
1870
1871 components.push(VueComponentInfo {
1872 name: component_name,
1873 component_type,
1874 composition_api,
1875 props: Vec::new(), emits: Vec::new(),
1877 directives: if self
1878 .vue_patterns
1879 .get("directives")
1880 .unwrap()
1881 .is_match(content)
1882 {
1883 vec![VueDirective {
1884 name: "v-if".to_string(),
1885 directive_type: VueDirectiveType::BuiltIn,
1886 has_modifiers: false,
1887 dynamic_argument: false,
1888 }]
1889 } else {
1890 Vec::new()
1891 },
1892 lifecycle_hooks: Vec::new(),
1893 composables: if self
1894 .vue_patterns
1895 .get("composables")
1896 .unwrap()
1897 .is_match(content)
1898 {
1899 vec!["useComposable".to_string()]
1900 } else {
1901 Vec::new()
1902 },
1903 });
1904 }
1905
1906 Ok(components)
1907 }
1908
1909 pub fn analyze_angular_patterns(&self, content: &str) -> Result<Vec<AngularComponentInfo>> {
1911 let mut components = Vec::new();
1912
1913 if self
1915 .angular_patterns
1916 .get("component_decorator")
1917 .unwrap()
1918 .is_match(content)
1919 {
1920 let selector = "app-component".to_string(); let component_name = "AngularComponent".to_string(); let component_type = if self
1924 .angular_patterns
1925 .get("service_decorator")
1926 .unwrap()
1927 .is_match(content)
1928 {
1929 AngularComponentType::Service
1930 } else {
1931 AngularComponentType::Component
1932 };
1933
1934 components.push(AngularComponentInfo {
1935 name: component_name,
1936 component_type,
1937 selector,
1938 inputs: Vec::new(), outputs: Vec::new(),
1940 lifecycle_hooks: if self
1941 .angular_patterns
1942 .get("lifecycle_hooks")
1943 .unwrap()
1944 .is_match(content)
1945 {
1946 vec!["ngOnInit".to_string()]
1947 } else {
1948 Vec::new()
1949 },
1950 services: Vec::new(),
1951 change_detection: ChangeDetectionStrategy::Default,
1952 });
1953 }
1954
1955 Ok(components)
1956 }
1957
1958 pub fn analyze_security_assessment(&self, content: &str) -> Result<SecurityAssessment> {
1960 let mut vulnerabilities = Vec::new();
1961 let mut security_features = Vec::new();
1962 let mut security_score = 0;
1963
1964 if self
1966 .security_patterns
1967 .get("authentication_middleware")
1968 .unwrap()
1969 .is_match(content)
1970 {
1971 security_score += 2;
1972 security_features.push(SecurityFeature {
1973 feature_type: SecurityFeatureType::Authentication,
1974 implementation_quality: ImplementationQuality::Good,
1975 description: "Authentication middleware detected".to_string(),
1976 });
1977 }
1978
1979 if self
1981 .security_patterns
1982 .get("input_validation")
1983 .unwrap()
1984 .is_match(content)
1985 {
1986 security_score += 2;
1987 security_features.push(SecurityFeature {
1988 feature_type: SecurityFeatureType::InputValidation,
1989 implementation_quality: ImplementationQuality::Good,
1990 description: "Input validation patterns detected".to_string(),
1991 });
1992 }
1993
1994 if self
1996 .security_patterns
1997 .get("sql_injection_risk")
1998 .unwrap()
1999 .is_match(content)
2000 {
2001 security_score -= 3;
2002 vulnerabilities.push(SecurityVulnerability {
2003 vulnerability_type: VulnerabilityType::SqlInjection,
2004 severity: VulnerabilitySeverity::High,
2005 description: "Potential SQL injection vulnerability".to_string(),
2006 location: "Query construction".to_string(),
2007 recommendation: "Use parameterized queries".to_string(),
2008 });
2009 }
2010
2011 if self
2012 .security_patterns
2013 .get("xss_vulnerability")
2014 .unwrap()
2015 .is_match(content)
2016 {
2017 security_score -= 3;
2018 vulnerabilities.push(SecurityVulnerability {
2019 vulnerability_type: VulnerabilityType::XssRisk,
2020 severity: VulnerabilitySeverity::High,
2021 description: "Potential XSS vulnerability".to_string(),
2022 location: "DOM manipulation".to_string(),
2023 recommendation: "Sanitize user input".to_string(),
2024 });
2025 }
2026
2027 let level = match security_score {
2028 score if score >= 3 => SecurityLevel::High,
2029 score if score >= 1 => SecurityLevel::Medium,
2030 score if score >= 0 => SecurityLevel::Low,
2031 _ => SecurityLevel::Vulnerable,
2032 };
2033
2034 Ok(SecurityAssessment {
2035 level,
2036 vulnerabilities_detected: vulnerabilities,
2037 security_features,
2038 recommendations: vec![
2039 "Implement comprehensive input validation".to_string(),
2040 "Add authentication and authorization middleware".to_string(),
2041 "Use HTTPS for all communications".to_string(),
2042 ],
2043 })
2044 }
2045
2046 pub fn analyze_performance_patterns(&self, content: &str) -> Result<PerformanceAnalysis> {
2048 let mut optimizations = Vec::new();
2049 let issues = Vec::new();
2050 let mut score = 50; if self
2054 .performance_patterns
2055 .get("lazy_loading")
2056 .unwrap()
2057 .is_match(content)
2058 {
2059 score += 15;
2060 optimizations.push(PerformanceOptimization {
2061 optimization_type: OptimizationType::LazyLoading,
2062 impact_level: ImpactLevel::Positive,
2063 description: "Lazy loading implementation detected".to_string(),
2064 best_practices_followed: true,
2065 });
2066 }
2067
2068 if self
2070 .performance_patterns
2071 .get("memoization")
2072 .unwrap()
2073 .is_match(content)
2074 {
2075 score += 10;
2076 optimizations.push(PerformanceOptimization {
2077 optimization_type: OptimizationType::Memoization,
2078 impact_level: ImpactLevel::Positive,
2079 description: "Memoization patterns detected".to_string(),
2080 best_practices_followed: true,
2081 });
2082 }
2083
2084 if self
2086 .performance_patterns
2087 .get("caching")
2088 .unwrap()
2089 .is_match(content)
2090 {
2091 score += 10;
2092 optimizations.push(PerformanceOptimization {
2093 optimization_type: OptimizationType::Caching,
2094 impact_level: ImpactLevel::Positive,
2095 description: "Caching mechanisms detected".to_string(),
2096 best_practices_followed: true,
2097 });
2098 }
2099
2100 if self
2102 .performance_patterns
2103 .get("database_optimization")
2104 .unwrap()
2105 .is_match(content)
2106 {
2107 score += 5;
2108 optimizations.push(PerformanceOptimization {
2109 optimization_type: OptimizationType::DatabaseOptimization,
2110 impact_level: ImpactLevel::Medium,
2111 description: "Database optimization patterns detected".to_string(),
2112 best_practices_followed: true,
2113 });
2114 }
2115
2116 Ok(PerformanceAnalysis {
2117 overall_score: score.min(100),
2118 optimizations_detected: optimizations,
2119 performance_issues: issues,
2120 recommendations: vec![
2121 "Implement lazy loading for non-critical resources".to_string(),
2122 "Use memoization for expensive calculations".to_string(),
2123 "Add appropriate caching strategies".to_string(),
2124 "Optimize database queries with indexing".to_string(),
2125 ],
2126 })
2127 }
2128
2129 pub fn analyze_websocket_patterns(&self, content: &str) -> Result<Option<WebSocketAnalysis>> {
2131 let socket_io_detected = self
2132 .websocket_patterns
2133 .get("socket_io")
2134 .unwrap()
2135 .is_match(content);
2136 let native_ws_detected = self
2137 .websocket_patterns
2138 .get("native_websocket")
2139 .unwrap()
2140 .is_match(content);
2141
2142 if !socket_io_detected && !native_ws_detected {
2143 return Ok(None);
2144 }
2145
2146 let implementation_type = if socket_io_detected {
2147 WebSocketImplementationType::SocketIO
2148 } else {
2149 WebSocketImplementationType::NativeWebSocket
2150 };
2151
2152 let mut patterns = Vec::new();
2153 let room_management = self
2154 .websocket_patterns
2155 .get("room_management")
2156 .unwrap()
2157 .is_match(content);
2158
2159 patterns.push(WebSocketPattern {
2160 pattern_type: WebSocketPatternType::RealTimeChat,
2161 event_handlers: vec!["message".to_string(), "connect".to_string()],
2162 room_management,
2163 authentication: false, error_handling: false,
2165 reconnection_logic: false,
2166 });
2167
2168 Ok(Some(WebSocketAnalysis {
2169 implementation_type,
2170 patterns,
2171 real_time_features: vec![RealTimeFeature {
2172 feature_name: "Real-time messaging".to_string(),
2173 implementation_quality: ImplementationQuality::Good,
2174 scalability_considerations: vec!["Consider using Redis for scaling".to_string()],
2175 latency_optimization: false,
2176 }],
2177 security_assessment: WebSocketSecurityAssessment {
2178 authentication_method: None,
2179 authorization_checks: false,
2180 rate_limiting: false,
2181 input_validation: false,
2182 origin_checks: false,
2183 ssl_tls_enforced: false,
2184 },
2185 performance_metrics: WebSocketPerformanceMetrics {
2186 connection_pooling: false,
2187 message_batching: false,
2188 compression_enabled: false,
2189 heartbeat_implementation: false,
2190 scaling_strategy: ScalingStrategy::SingleInstance,
2191 },
2192 }))
2193 }
2194
2195 pub fn analyze_enhanced_typescript(&self, content: &str) -> Result<TypeScriptAnalysisInfo> {
2197 let mut analysis = TypeScriptAnalysisInfo {
2198 generics_usage: Vec::new(),
2199 type_constraints: Vec::new(),
2200 utility_types: Vec::new(),
2201 type_guards: Vec::new(),
2202 conditional_types: Vec::new(),
2203 mapped_types: Vec::new(),
2204 complexity_score: 0,
2205 };
2206
2207 let mut complexity = 0;
2208
2209 if self
2211 .advanced_typescript_patterns
2212 .get("union_intersection")
2213 .unwrap()
2214 .is_match(content)
2215 {
2216 complexity += 2;
2217 }
2218
2219 if self
2221 .advanced_typescript_patterns
2222 .get("conditional_types")
2223 .unwrap()
2224 .is_match(content)
2225 {
2226 complexity += 4;
2227 analysis.conditional_types.push(ConditionalType {
2228 condition: "T extends U".to_string(),
2229 true_type: "T".to_string(),
2230 false_type: "never".to_string(),
2231 complexity_score: 4,
2232 });
2233 }
2234
2235 if self
2237 .advanced_typescript_patterns
2238 .get("mapped_types")
2239 .unwrap()
2240 .is_match(content)
2241 {
2242 complexity += 3;
2243 analysis.mapped_types.push(MappedType {
2244 source_type: "T".to_string(),
2245 transformation: "Partial<T>".to_string(),
2246 modifiers: vec![TypeModifier::Optional],
2247 complexity_score: 3,
2248 });
2249 }
2250
2251 if self
2253 .advanced_typescript_patterns
2254 .get("utility_types")
2255 .unwrap()
2256 .is_match(content)
2257 {
2258 complexity += 2;
2259 analysis.utility_types.push(UtilityTypeUsage {
2260 utility_name: "Partial".to_string(),
2261 usage_pattern: "Partial<T>".to_string(),
2262 complexity_impact: 2,
2263 best_practice_score: 0.8,
2264 });
2265 }
2266
2267 analysis.complexity_score = complexity;
2268 Ok(analysis)
2269 }
2270}
2271
2272impl Default for JavaScriptAnalyzer {
2273 fn default() -> Self {
2274 Self::new()
2275 }
2276}
2277
2278#[cfg(test)]
2279mod tests {
2280 use super::*;
2281
2282 #[test]
2283 fn test_framework_detection() {
2284 let analyzer = JavaScriptAnalyzer::new();
2285
2286 let react_code = "import React from 'react'; function App() { return <div>Hello</div>; }";
2287 let frameworks = analyzer.detect_frameworks(react_code).unwrap();
2288 assert!(frameworks.iter().any(|f| f.name == "React"));
2289 assert!(frameworks[0].confidence > 0.7);
2290
2291 let express_code =
2292 "const express = require('express'); app.get('/api/users', (req, res) => {});";
2293 let frameworks = analyzer.detect_frameworks(express_code).unwrap();
2294 assert!(frameworks.iter().any(|f| f.name == "Express"));
2295 }
2296
2297 #[test]
2298 fn test_react_component_detection() {
2299 let analyzer = JavaScriptAnalyzer::new();
2300
2301 let code = "function MyComponent(props) { const [state, setState] = useState(0); const data = useContext(MyContext); return <div>Hello</div>; }";
2302 let components = analyzer.analyze_react_patterns(code).unwrap();
2303
2304 assert!(!components.is_empty(), "Should not be empty");
2305 assert_eq!(components[0].name, "MyComponent");
2306 assert!(matches!(
2307 components[0].component_type,
2308 ComponentType::Functional | ComponentType::CustomHook
2309 ));
2310 assert!(!components[0].hooks_used.is_empty(), "Should not be empty");
2311 assert!(
2312 !components[0].context_usage.is_empty(),
2313 "Should not be empty"
2314 );
2315 }
2316
2317 #[test]
2318 fn test_advanced_hooks_detection() {
2319 let analyzer = JavaScriptAnalyzer::new();
2320
2321 let code = r#"
2322 function MyComponent() {
2323 const [count, setCount] = useState(0);
2324 const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);
2325 const callback = useCallback(() => doSomething(count), [count]);
2326 const ref = useRef(null);
2327
2328 useEffect(() => {
2329 console.log('Effect runs');
2330 }, [count]);
2331
2332 return <div ref={ref}>{memoizedValue}</div>;
2333 }
2334 "#;
2335
2336 let components = analyzer.analyze_react_patterns(code).unwrap();
2337 assert!(!components.is_empty(), "Should not be empty");
2338
2339 let hooks = &components[0].hooks_used;
2340 assert!(hooks.iter().any(|h| h.name == "useState"));
2341 assert!(hooks.iter().any(|h| h.name == "useMemo"));
2342 assert!(hooks.iter().any(|h| h.name == "useCallback"));
2343 assert!(hooks.iter().any(|h| h.name == "useEffect"));
2344 assert!(hooks.iter().any(|h| h.name == "useRef"));
2345 }
2346
2347 #[test]
2348 fn test_database_pattern_detection() {
2349 let analyzer = JavaScriptAnalyzer::new();
2350
2351 let mongodb_code = r#"
2352 app.get('/users', async (req, res) => {
2353 const users = await User.find({});
2354 res.json(users);
2355 });
2356 "#;
2357
2358 let patterns = analyzer.analyze_nodejs_patterns(mongodb_code).unwrap();
2359 assert!(!patterns.is_empty(), "Should not be empty");
2360 assert!(
2361 !patterns[0].database_patterns.is_empty(),
2362 "Should not be empty"
2363 );
2364 assert_eq!(patterns[0].database_patterns[0].db_type, "mongodb");
2365 }
2366
2367 #[test]
2368 fn test_typescript_feature_detection() {
2369 let analyzer = JavaScriptAnalyzer::new();
2370
2371 let typescript_code = r#"
2372 interface User {
2373 id: number;
2374 name: string;
2375 }
2376
2377 enum Status {
2378 Active,
2379 Inactive
2380 }
2381
2382 function getUser<T>(id: T): Promise<User> {
2383 return fetch(`/api/users/${id}`).then(res => res.json());
2384 }
2385 "#;
2386
2387 let features = analyzer
2388 .analyze_modern_js_features(typescript_code)
2389 .unwrap();
2390 assert!(features
2391 .iter()
2392 .any(|f| matches!(f.feature_type, ModernFeatureType::TypeScriptInterface)));
2393 assert!(features
2394 .iter()
2395 .any(|f| matches!(f.feature_type, ModernFeatureType::TypeScriptEnum)));
2396 assert!(features.iter().any(|f| f.typescript_specific));
2397 }
2398
2399 #[test]
2400 fn test_comprehensive_recommendations() {
2401 let analyzer = JavaScriptAnalyzer::new();
2402
2403 let frameworks = vec![FrameworkInfo {
2404 name: "React".to_string(),
2405 confidence: 0.9,
2406 version_detected: None,
2407 features_used: vec!["Hooks".to_string()],
2408 best_practices: vec!["Use functional components".to_string()],
2409 }];
2410
2411 let components = vec![ReactComponentInfo {
2412 name: "TestComponent".to_string(),
2413 component_type: ComponentType::Class,
2414 hooks_used: Vec::new(),
2415 props_analysis: PropsInfo {
2416 prop_names: Vec::new(),
2417 has_prop_types: false,
2418 has_default_props: false,
2419 destructured: false,
2420 typescript_props: false,
2421 },
2422 lifecycle_methods: vec!["componentDidMount".to_string()],
2423 jsx_elements: Vec::new(),
2424 context_usage: Vec::new(),
2425 state_management: Vec::new(),
2426 }];
2427
2428 let recommendations =
2429 analyzer.get_comprehensive_recommendations(&frameworks, &components, &[], &[]);
2430
2431 assert!(!recommendations.is_empty(), "Should not be empty");
2432 assert!(recommendations
2433 .iter()
2434 .any(|r| r.contains("functional components")));
2435 assert!(recommendations.iter().any(|r| r.contains("TypeScript")));
2436 }
2437
2438 #[test]
2441 fn test_vue_component_analysis() {
2442 let analyzer = JavaScriptAnalyzer::new();
2443
2444 let vue_code = r#"
2445 <template>
2446 <div v-if="show">
2447 <p v-for="item in items" :key="item.id">{{ item.name }}</p>
2448 </div>
2449 </template>
2450
2451 <script>
2452 import { ref, computed, onMounted } from 'vue'
2453
2454 export default {
2455 setup() {
2456 const count = ref(0)
2457 const doubled = computed(() => count.value * 2)
2458
2459 onMounted(() => {
2460 console.log('Component mounted')
2461 })
2462
2463 return { count, doubled }
2464 }
2465 }
2466 </script>
2467 "#;
2468
2469 let components = analyzer.analyze_vue_patterns(vue_code).unwrap();
2470 assert!(!components.is_empty(), "Should not be empty");
2471 assert_eq!(components[0].name, "VueComponent");
2472 assert!(matches!(
2473 components[0].component_type,
2474 VueComponentType::CompositionAPI
2475 ));
2476 assert!(components[0].composition_api);
2477 assert!(!components[0].directives.is_empty(), "Should not be empty");
2478 assert_eq!(components[0].directives[0].name, "v-if");
2479 }
2480
2481 #[test]
2482 fn test_angular_component_analysis() {
2483 let analyzer = JavaScriptAnalyzer::new();
2484
2485 let angular_code = r#"
2486 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2487
2488 @Component({
2489 selector: 'app-user',
2490 templateUrl: './user.component.html'
2491 })
2492 export class UserComponent implements OnInit {
2493 @Input() user: User;
2494 @Output() userSelected = new EventEmitter<User>();
2495
2496 constructor(private userService: UserService) {}
2497
2498 ngOnInit() {
2499 this.loadUser();
2500 }
2501
2502 ngOnDestroy() {
2503 // cleanup
2504 }
2505 }
2506 "#;
2507
2508 let components = analyzer.analyze_angular_patterns(angular_code).unwrap();
2509 assert!(!components.is_empty(), "Should not be empty");
2510 assert_eq!(components[0].name, "AngularComponent");
2511 assert!(matches!(
2512 components[0].component_type,
2513 AngularComponentType::Component
2514 ));
2515 assert_eq!(components[0].selector, "app-component");
2516 assert!(
2517 !components[0].lifecycle_hooks.is_empty(),
2518 "Should not be empty"
2519 );
2520 assert_eq!(components[0].lifecycle_hooks[0], "ngOnInit");
2521 }
2522
2523 #[test]
2524 fn test_security_assessment() {
2525 let analyzer = JavaScriptAnalyzer::new();
2526
2527 let secure_code = r#"
2528 const jwt = require('jsonwebtoken');
2529 const joi = require('joi');
2530
2531 app.use(passport.authenticate('jwt', { session: false }));
2532
2533 const schema = joi.object({
2534 email: joi.string().email().required(),
2535 password: joi.string().min(6).required()
2536 });
2537
2538 app.post('/login', async (req, res) => {
2539 const { error } = schema.validate(req.body);
2540 if (error) return res.status(400).send(error.details);
2541
2542 // Safe query using parameterized query
2543 const user = await User.findOne({ email: req.body.email });
2544 res.json({ token: jwt.sign({ id: user.id }, process.env.JWT_SECRET) });
2545 });
2546 "#;
2547
2548 let assessment = analyzer.analyze_security_assessment(secure_code).unwrap();
2549 assert!(matches!(
2550 assessment.level,
2551 SecurityLevel::High | SecurityLevel::Medium
2552 ));
2553 assert!(
2554 !assessment.security_features.is_empty(),
2555 "Should not be empty"
2556 );
2557
2558 let vulnerable_code = r#"
2559 app.get('/user/:id', (req, res) => {
2560 // SQL injection vulnerability
2561 const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
2562 db.query(query, (err, results) => {
2563 res.innerHTML = results[0].bio; // XSS vulnerability
2564 });
2565 });
2566 "#;
2567
2568 let vulnerable_assessment = analyzer
2569 .analyze_security_assessment(vulnerable_code)
2570 .unwrap();
2571 assert!(matches!(
2572 vulnerable_assessment.level,
2573 SecurityLevel::Vulnerable
2574 ));
2575 assert!(
2576 !vulnerable_assessment.vulnerabilities_detected.is_empty(),
2577 "Should not be empty"
2578 );
2579 }
2580
2581 #[test]
2582 fn test_performance_analysis() {
2583 let analyzer = JavaScriptAnalyzer::new();
2584
2585 let optimized_code = r#"
2586 import { lazy, memo, useMemo, useCallback } from 'react';
2587
2588 const LazyComponent = lazy(() => import('./HeavyComponent'));
2589
2590 const OptimizedComponent = memo(({ data, onUpdate }) => {
2591 const expensiveValue = useMemo(() => {
2592 return data.reduce((acc, item) => acc + item.value, 0);
2593 }, [data]);
2594
2595 const handleClick = useCallback(() => {
2596 onUpdate(expensiveValue);
2597 }, [expensiveValue, onUpdate]);
2598
2599 return <LazyComponent value={expensiveValue} onClick={handleClick} />;
2600 });
2601
2602 // Database optimization
2603 const users = await User.find({})
2604 .select('name email')
2605 .limit(10)
2606 .sort({ createdAt: -1 });
2607
2608 // Caching
2609 const cachedData = cache.get('user-data') || await fetchUserData();
2610 "#;
2611
2612 let analysis = analyzer
2613 .analyze_performance_patterns(optimized_code)
2614 .unwrap();
2615 assert!(analysis.overall_score > 50);
2616 assert!(
2617 !analysis.optimizations_detected.is_empty(),
2618 "Should not be empty"
2619 );
2620
2621 let optimizations = &analysis.optimizations_detected;
2622 assert!(optimizations
2623 .iter()
2624 .any(|o| matches!(o.optimization_type, OptimizationType::LazyLoading)));
2625 assert!(optimizations
2626 .iter()
2627 .any(|o| matches!(o.optimization_type, OptimizationType::Memoization)));
2628 assert!(optimizations
2629 .iter()
2630 .any(|o| matches!(o.optimization_type, OptimizationType::Caching)));
2631 assert!(optimizations
2632 .iter()
2633 .any(|o| matches!(o.optimization_type, OptimizationType::DatabaseOptimization)));
2634 }
2635
2636 #[test]
2637 fn test_websocket_analysis() {
2638 let analyzer = JavaScriptAnalyzer::new();
2639
2640 let socket_io_code = r#"
2641 const io = require('socket.io')(server);
2642
2643 io.on('connection', (socket) => {
2644 console.log('User connected');
2645
2646 socket.join('room1');
2647 socket.to('room1').emit('user-joined', { id: socket.id });
2648
2649 socket.on('message', (data) => {
2650 io.to('room1').emit('message', data);
2651 });
2652
2653 socket.on('disconnect', () => {
2654 console.log('User disconnected');
2655 });
2656 });
2657 "#;
2658
2659 let analysis = analyzer.analyze_websocket_patterns(socket_io_code).unwrap();
2660 assert!(analysis.is_some(), "Should have value");
2661
2662 let ws_analysis = analysis.unwrap();
2663 assert!(matches!(
2664 ws_analysis.implementation_type,
2665 WebSocketImplementationType::SocketIO
2666 ));
2667 assert!(!ws_analysis.patterns.is_empty(), "Should not be empty");
2668 assert!(ws_analysis.patterns[0].room_management);
2669 assert!(
2670 !ws_analysis.patterns[0].event_handlers.is_empty(),
2671 "Should not be empty"
2672 );
2673
2674 let native_ws_code = r#"
2675 const WebSocket = require('ws');
2676 const wss = new WebSocketServer({ port: 8080 });
2677
2678 wss.on('connection', (ws) => {
2679 ws.on('message', (data) => {
2680 ws.send('Echo: ' + data);
2681 });
2682 });
2683 "#;
2684
2685 let native_analysis = analyzer.analyze_websocket_patterns(native_ws_code).unwrap();
2686 assert!(native_analysis.is_some(), "Should have value");
2687 assert!(matches!(
2688 native_analysis.unwrap().implementation_type,
2689 WebSocketImplementationType::NativeWebSocket
2690 ));
2691 }
2692
2693 #[test]
2694 fn test_enhanced_typescript_analysis() {
2695 let analyzer = JavaScriptAnalyzer::new();
2696
2697 let complex_ts_code = r#"
2698 type User = {
2699 id: number;
2700 name: string;
2701 };
2702
2703 type Admin = {
2704 permissions: string[];
2705 };
2706
2707 // Union and intersection types
2708 type UserOrAdmin = User | Admin;
2709 type SuperUser = User & Admin;
2710
2711 // Conditional types
2712 type NonNullable<T> = T extends null | undefined ? never : T;
2713
2714 // Mapped types
2715 type Partial<T> = {
2716 [P in keyof T]?: T[P];
2717 };
2718
2719 // Utility types
2720 type UserKeys = keyof User;
2721 type UserName = Pick<User, 'name'>;
2722 type PartialUser = Partial<User>;
2723 type UserRecord = Record<string, User>;
2724 "#;
2725
2726 let analysis = analyzer
2727 .analyze_enhanced_typescript(complex_ts_code)
2728 .unwrap();
2729 assert!(analysis.complexity_score > 0);
2730 assert!(
2731 !analysis.conditional_types.is_empty(),
2732 "Should not be empty"
2733 );
2734 assert!(!analysis.mapped_types.is_empty(), "Should not be empty");
2735 assert!(!analysis.utility_types.is_empty(), "Should not be empty");
2736
2737 let conditional_type = &analysis.conditional_types[0];
2738 assert_eq!(conditional_type.complexity_score, 4);
2739
2740 let mapped_type = &analysis.mapped_types[0];
2741 assert!(mapped_type.modifiers.contains(&TypeModifier::Optional));
2742
2743 let utility_type = &analysis.utility_types[0];
2744 assert_eq!(utility_type.utility_name, "Partial");
2745 assert!(utility_type.best_practice_score > 0.0);
2746 }
2747
2748 #[test]
2749 fn test_no_websocket_patterns() {
2750 let analyzer = JavaScriptAnalyzer::new();
2751
2752 let regular_code = r#"
2753 function regularFunction() {
2754 console.log('No WebSocket here');
2755 return fetch('/api/data').then(res => res.json());
2756 }
2757 "#;
2758
2759 let analysis = analyzer.analyze_websocket_patterns(regular_code).unwrap();
2760 assert!(analysis.is_none(), "Should be none");
2761 }
2762}