<!-- Generated by codeindex at 2026-02-08T11:28:19+08:00 -->

# README_AI.md - parsers

## Overview

The `parsers` module provides language-specific parsing functionality for extracting symbols, imports, inheritance relationships, and call graphs from source code files. Each language has its own parser module that implements the `BaseLanguageParser` interface using tree-sitter for syntax analysis.

## Architecture

The module follows a plugin-based architecture where:
- **Base Interface**: `BaseLanguageParser` defines the contract for all language parsers
- **Language Implementations**: Concrete parser classes (e.g., `PythonParser`, `PhpParser`, `JavaParser`) implement language-specific parsing logic
- **Utilities**: Shared helper functions for common tree-sitter operations
- **Backward Compatibility**: Legacy functions provide smooth migration paths

## Core Components

### Base Parser (`base.py`)

Defines the abstract base class that all language parsers must implement:

```python
class BaseLanguageParser:
    def extract_symbols(tree, source_bytes) -> list[Symbol]
    def extract_imports(tree, source_bytes) -> list[Import]
    def extract_calls(tree, source_bytes, symbols, imports) -> list[Call]
    def extract_inheritances(tree, source_bytes) -> list[Inheritance]
    def parse(path) -> ParseResult
```

**Syntax Error Detection**:
- All parsers check `tree.root_node.has_error` after parsing
- Returns `ParseResult` with error message if syntax errors detected
- Includes `file_lines` count for context
- Prevents extraction attempts on malformed code

### Language Parsers

#### Python Parser (`python_parser.py`)
- Extracts classes, functions, methods, decorators
- Handles Python-specific constructs (decorators, comprehensions, type hints)
- Supports nested definitions and closures
- **Syntax Validation**: Detects Python syntax errors before symbol extraction

#### PHP Parser (`php_parser.py`)
- Extracts classes (with inheritance/interfaces), methods (with visibility, static, return types), properties, functions
- Parses PHPDoc comments for documentation
- Supports namespaces, traits, and modern PHP 8.x syntax
- **Namespace Extraction**: Overrides `parse()` method to extract PHP namespace declarations from source files
- Returns namespace information in `ParseResult` for fully qualified name resolution
- **Syntax Validation**: Detects PHP syntax errors before symbol extraction

#### Java Parser (`java_parser.py`) **[NEW - v0.13.0]**
- **Comprehensive Java Support**: Classes, interfaces, enums, records (Java 14+)
- **Symbol Extraction**: Methods, constructors, fields with full signature information
- **Syntax Validation**: Detects Java syntax errors before symbol extraction
- **Advanced Features**:
  - JavaDoc comment parsing
  - Annotation extraction (marker annotations and parameterized annotations)
  - Generics support (type parameters)
  - Modifiers (public, private, static, final, etc.)
  - Inheritance resolution (extends/implements)
  - Package/namespace handling
- **Call Graph Analysis**:
  - Method invocations (instance and static)
  - Constructor calls (object creation)
  - Static import resolution
  - Super method calls with parent class resolution
  - Call type detection (FUNCTION, METHOD, STATIC_METHOD, CONSTRUCTOR)
- **Type Resolution**:
  - Qualified name resolution using import statements
  - Generic type stripping for inheritance analysis
  - Java standard library classes (java.lang.*) implicit import handling

### Utilities (`utils.py`)

Shared helper functions:
- `get_node_text()`: Extract text from tree-sitter nodes
- `count_arguments()`: Count function/method parameters

## Key Data Structures

### Symbol
Represents a code entity:
- `name`: Fully qualified symbol name
- `kind`: Type (class, function, method, field, interface, enum, record, constructor)
- `signature`: Full declaration signature with modifiers
- `docstring`: Extracted documentation
- `line_start`, `line_end`: Source location
- `annotations`: List of decorators/annotations (Java)

### Import
Represents an import statement:
- `module`: Module/package name
- `names`: Imported names (empty for wildcard imports)
- `is_from`: True for relative imports (Python) or static imports (Java)

### Inheritance
Represents class inheritance:
- `child`: Child class fully qualified name
- `parent`: Parent class/interface fully qualified name

### Call
Represents a function/method call:
- `caller`: Calling function/method name
- `callee`: Called function/method name
- `line_number`: Call location
- `call_type`: Type of call (FUNCTION, METHOD, STATIC_METHOD, CONSTRUCTOR)
- `arguments_count`: Number of arguments passed

### Annotation
Represents Java annotations or Python decorators:
- `name`: Annotation name (e.g., "@Override", "@RequestMapping")
- `arguments`: Dictionary of annotation parameters

## Parser Customization

### Overriding parse() Method

Language parsers can override the base `parse()` method to add language-specific extraction logic. The PHP parser demonstrates this pattern:

```python
def parse(self, path):
    """Override to add namespace extraction."""
    # Standard parsing (symbols, imports, calls, inheritances)
    result = super().parse(path)
    
    # Language-specific extraction (namespace for PHP)
    namespace = self._extract_namespace(tree, source_bytes)
    
    return ParseResult(..., namespace=namespace)
```

This allows language-specific features to be extracted without modifying the base parser interface.

## Error Handling

### Syntax Error Detection

All language parsers implement early syntax error detection:

1. **Parse with tree-sitter**: Generate AST from source bytes
2. **Check for errors**: Inspect `tree.root_node.has_error`
3. **Return error result**: If syntax errors detected:
   ```python
   return ParseResult(
       path=path,
       error="Syntax error in source file",
       file_lines=file_lines,
   )
   ```
4. **Continue extraction**: Only if AST is valid

This prevents extraction attempts on malformed code and provides clear error feedback.

## Java Parser Implementation Details

### Package and Import Resolution

The Java parser builds an import map to resolve short class names to fully qualified names:

```java
import java.util.List;        // Maps "List" → "java.util.List"
import static Math.max;       // Static import: maps "max" → "java.lang.Math.max"
```

### Inheritance Extraction

Supports multiple inheritance patterns:
- **Class extension**: `class Child extends Parent`
- **Interface implementation**: `class Foo implements Bar, Baz`
- **Interface extension**: `interface A extends B, C`

All parent types are resolved to fully qualified names using the import map.

### Call Graph Extraction

The Java parser extracts four types of calls:

1. **Instance Method Calls**: `obj.method()`
2. **Static Method Calls**: `ClassName.staticMethod()`
3. **Constructor Calls**: `new ClassName()`
4. **Super Calls**: `super.method()` (resolves to parent class method)

Call resolution handles:
- Chained method calls (`obj.getX().getY()`)
- Static imports (`max(a, b)` → `java.lang.Math.max`)
- Qualified method calls (`java.util.Collections.sort()`)

### Annotation Parsing

Extracts both marker and parameterized annotations:

```java
@Override                           // Marker annotation
@RequestMapping(value = "/api")    // Parameterized annotation
```

## PHP Parser Implementation Details

### Namespace Handling

The PHP parser extracts namespace declarations to support fully qualified name resolution:

```php
namespace App\Controllers;  // Extracted as "App\Controllers"
```

The namespace is stored in `ParseResult.namespace` and can be used to:
- Resolve short class names to fully qualified names
- Generate accurate import/dependency graphs
- Support PSR-4 autoloading analysis

### Parse Method Override

The PHP parser overrides the base `parse()` method to:
1. Perform standard extraction (symbols, imports, inheritances, calls)
2. Extract namespace from the AST root node
3. Return `ParseResult` with namespace information

This ensures namespace data is available for downstream processing without requiring a separate parse pass.

## Usage

### Direct Usage

```python
from codeindex.parsers import JavaParser, PhpParser, PythonParser

# Parse a Java file
parser = JavaParser()
result = parser.parse("src/Main.java")

# Parse a PHP file (with namespace extraction)
php_parser = PhpParser()
result = php_parser.parse("src/Controller.php")
print(f"Namespace: {result.namespace}")

# Check for syntax errors
if result.error:
    print(f"Parse error: {result.error}")
else:
    # Access extracted data
    for symbol in result.symbols:
        print(f"{symbol.kind}: {symbol.name}")
    
    for call in result.calls:
        print(f"{call.caller} → {call.callee} ({call.call_type})")
```

### Via Main Parser Interface

```python
from codeindex.parser import parse_file

# Automatically selects correct parser based on file extension
result = parse_file("src/Main.java")
result = parse_file("src/Controller.php")  # Includes namespace
```

## Backward Compatibility

Legacy functions are provided for smooth migration:

- `is_java_file(path)`: Check if file is Java
- `get_java_parser()`: Get lazy-loaded parser instance
- `parse_java_file(file_path, content)`: Parse Java from string content

Similar functions exist for PHP and Python parsers.

## Extension Points

To add a new language:

1. Create `{language}_parser.py` implementing `BaseLanguageParser`
2. Install tree-sitter grammar: `pip install tree-sitter-{language}`
3. Register in `__init__.py`:
   ```python
   from .my_language_parser import MyLanguageParser
   __all__ = [..., "MyLanguageParser"]
   ```
4. Update `parser.py` to recognize file extensions
5. (Optional) Override `parse()` method for language-specific extraction (e.g., namespace, package)
6. Implement syntax error detection (check `tree.root_node.has_error`)

## Design Principles

- **Separation of Concerns**: Each language parser is self-contained
- **Tree-sitter Foundation**: All parsers use tree-sitter for reliable parsing
- **Consistent Interface**: `BaseLanguageParser` ensures uniform API
- **Progressive Extraction**: Symbols → Imports → Inheritances → Calls
- **Extensibility**: `parse()` method can be overridden for language-specific features
- **Error Resilience**: Parsers return partial results on errors
- **Early Validation**: Syntax errors detected before extraction attempts

## Performance Considerations

- **Lazy Loading**: Parsers are instantiated only when needed
- **Single-pass Parsing**: Each file is parsed once, extracting all data
- **Efficient AST Traversal**: Recursive descent with early termination
- **Import Map Caching**: Built once per file and reused for all resolutions
- **Early Error Detection**: Syntax validation prevents wasted extraction work

## Testing

Comprehensive test coverage in `tests/parsers/`:
- `test_java_parser.py`: Java parser unit tests
- `test_php_parser.py`: PHP parser tests (includes namespace extraction tests)
- `test_python_parser.py`: Python parser tests

Test fixtures include real-world code patterns and edge cases.

## Dependencies

- **tree-sitter**: Core parsing engine
- **tree-sitter-python**: Python grammar
- **tree-sitter-php**: PHP grammar
- **tree-sitter-java**: Java grammar (v0.13.0+)

## Version History

- **v0.13.1**: Added syntax error detection for all language parsers
- **v0.13.0**: Added comprehensive Java parser with full language support
- **v0.2.3**: Added PHP parser with enhanced PHPDoc support and namespace extraction
- **v0.2.0**: Introduced `BaseLanguageParser` architecture
- **v0.1.0**: Initial Python parser implementation


**Commit ``**: 

Changed files:
- `__init__.py`
- `typescript_parser.py`


**Commit ``**: 

Changed files:
- `__init__.py`
- `swift.py`
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `swift_parser.py`


**Commit ``**: 

Changed files:
- `__init__.py`
- `objc_parser.py`


**Commit ``**: 

Changed files:
- `objc_parser.py`


**Commit ``**: 

Changed files:
- `objc_parser.py`

---

## Recent Changes

**Commit ``**: 

Changed files:
- `__init__.py`
- `java_parser.py`
