> */ #[Route(path: '/users/{limit}', method: 'GET')] public function getUsers(int $limit = 10): JsonResult { $users = $this->repository->findAll($limit); return new JsonResult(['users' => $users]); } } interface UserServiceInterface { public function findById(int $id): ?User; } trait TimestampTrait { public function getCreatedAt(): \DateTime { return $this->createdAt; } } enum UserStatus: string { case ACTIVE = 'active'; case INACTIVE = 'inactive'; case SUSPENDED = 'suspended'; } function helper_function(string $name): string { return "Hello, {$name}!"; } PHP; echo "=== Testing Discovery Tokenizer ===\n\n"; // Create a temporary file for testing $tempFile = tempnam(sys_get_temp_dir(), 'discovery_test'); file_put_contents($tempFile, $testCode); try { $file = File::fromSplFileInfo(new \SplFileInfo($tempFile)); $fileSystemService = new FileSystemService(); $classExtractor = new ClassExtractor($fileSystemService); $tokenizer = new DiscoveryTokenizer(); // Test class extraction echo "1. Class Extraction:\n"; $classes = $classExtractor->extractDetailedFromFile($file); foreach ($classes as $class) { echo sprintf( " %s: %s (line %d) in namespace %s\n", $class['type'], $class['name'], $class['line'], $class['namespace'] ?? 'global' ); } // Test function extraction echo "\n2. Function Extraction:\n"; $functions = $classExtractor->extractFunctionsFromFile($file); foreach ($functions as $function) { echo sprintf( " %s: %s (line %d) - %s %s\n", $function['type'], $function['name'], $function['line'], $function['visibility'], $function['class'] ? "in {$function['class']}" : 'global' ); } // Test attribute extraction echo "\n3. Attribute Extraction:\n"; $attributes = $classExtractor->extractAttributesFromFile($file); foreach ($attributes as $attribute) { echo sprintf( " %s (line %d) targeting %s in %s context\n", $attribute['name'], $attribute['line'], $attribute['target'], $attribute['context'] ); } // Test use statements echo "\n4. Use Statements:\n"; $uses = $classExtractor->extractUseStatementsFromFile($file); foreach ($uses as $use) { echo sprintf( " %s%s (line %d)\n", $use['class'], $use['alias'] ? " as {$use['alias']}" : '', $use['line'] ); } // Test complete analysis echo "\n5. Complete Analysis:\n"; $analysis = $classExtractor->analyzeFile($file); echo sprintf( " Classes: %d, Functions: %d, Attributes: %d, Uses: %d\n", count($analysis['classes']), count($analysis['functions']), count($analysis['attributes']), count($analysis['uses']) ); // Compare with direct tokenizer usage echo "\n6. Direct Tokenizer Comparison:\n"; $directClasses = $tokenizer->extractClasses($testCode); echo " Direct tokenizer found " . count($directClasses) . " classes\n"; // Check if results match $extractorCount = count($classes); $tokenizerCount = count($directClasses); $match = $extractorCount === $tokenizerCount; echo sprintf( " Results match: %s (Extractor: %d, Tokenizer: %d)\n", $match ? 'YES ✓' : 'NO ✗', $extractorCount, $tokenizerCount ); } finally { // Clean up unlink($tempFile); } echo "\n=== Discovery Tokenizer Test Complete ===\n";