Skip to content

bukinator-dev/legacy-analyzer

Repository files navigation

Java Legacy Analyzer

A powerful CLI tool that analyzes Java legacy code, generates Mockito test mocks, and maps API invocation sequences across your entire codebase.

🎯 Features

  • πŸ“Š Code Analysis: Deep analysis of Java classes including complexity, dependencies, and testability
  • πŸ§ͺ Mock Generation: Automatically generates Mockito test classes with proper annotations
  • πŸ”— API Sequence Mapping: Traces method call sequences up to 4 levels deep across files
  • 🌲 Visual Tree Display: Shows method invocation hierarchy in ASCII tree format
  • πŸ“ Organized Output: Auto-creates separate directories for generated tests and API reports
  • πŸ” Risk Detection: Identifies high-risk areas that need thorough testing
  • πŸ’‘ Smart Suggestions: Provides specific test coverage recommendations
  • 🎨 Cross-Platform: Works on Windows, Linux, and macOS with ASCII-safe output

πŸ“‹ Table of Contents

  1. Installation
  2. Quick Start
  3. Commands Reference
  4. Understanding API Analysis
  5. Interpreting Results
  6. Output Directory Structure
  7. Use Cases & Examples
  8. Best Practices

πŸš€ Installation

Requirements:

  • Python 3.7 or higher
  • No external dependencies required (pure Python!)

Setup:

# Clone or download the repository
cd legacy-analyzer

# Make the CLI executable (Unix/Linux/macOS)
chmod +x legacy-cli

# Ready to use!
./legacy-cli --help

# On Windows, use:
legacy-cli.bat --help

# Or use Python directly on any platform:
python main.py --help

Adding to PATH (Optional):

# Unix/Linux/macOS - Add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:/path/to/legacy-analyzer"

# Windows - Add the directory to your System PATH environment variable
# Then you can use: legacy-cli analyze MyFile.java

⚑ Quick Start

1. Analyze a Single Java Class

# Using legacy-cli (recommended)
./legacy-cli analyze examples/UserService.java

# Or with Python directly
python main.py analyze examples/UserService.java

What you'll see:

  • Complexity breakdown (Simple/Moderate/Complex methods)
  • Mockable dependencies
  • Testability score (0-100)
  • Test coverage suggestions
  • Risk areas

2. Generate Test Class with Mocks

# Using legacy-cli (recommended)
./legacy-cli generate examples/UserService.java --output UserServiceTest.java

# Or with Python directly
python main.py generate examples/UserService.java --output UserServiceTest.java

Output: generated-tests/UserServiceTest.java (auto-created directory)

Contains:

  • @Mock annotations for dependencies
  • @InjectMocks for class under test
  • Test method stubs for all public methods
  • Exception test cases

3. Analyze Project APIs (Entire Codebase)

# Using legacy-cli (recommended)
./legacy-cli api-analyze examples

# Or with Python directly
python main.py api-analyze examples

What you'll see:

  • All public APIs (methods) discovered
  • Tree view of method invocation sequences
  • Cross-file method call tracking
  • External API dependencies highlighted
  • Exception handling paths

πŸ“– Commands Reference

analyze - Single File Analysis

Analyzes a Java class for testability and complexity.

# Using legacy-cli
./legacy-cli analyze <java-file> [--verbose]

# Or with Python
python main.py analyze <java-file> [--verbose]

Options:

  • --verbose, -v - Show detailed analysis

Example:

./legacy-cli analyze examples/UserService.java --verbose

Output Sections:

  1. Complexity Analysis: Method count breakdown
  2. Dependencies: Mockable fields
  3. Testability Score: 0-100 rating
  4. Test Coverage Suggestions: What to test
  5. Risk Areas: High-priority test targets
  6. Public Methods: List of testable methods

generate - Generate Test Class

Creates a complete JUnit + Mockito test class.

# Using legacy-cli
./legacy-cli generate <java-file> [options]

# Or with Python
python main.py generate <java-file> [options]

Options:

  • --output, -o FILE - Output file name (saved to generated-tests/)
  • --quick-mocks - Generate only mock field declarations
  • --no-setup - Skip @Before setup method

Examples:

# Full test class
./legacy-cli generate examples/UserService.java --output UserServiceTest.java
# Output: generated-tests/UserServiceTest.java

# Quick mocks only (for copy-paste)
./legacy-cli generate examples/UserService.java --quick-mocks

# Save to custom location (absolute path)
./legacy-cli generate examples/UserService.java --output /tmp/MyTest.java

Generated Test Structure:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
    @Mock
    private UserDAO userDAO;

    @InjectMocks
    private UserService userService;

    @Before
    public void setUp() { }

    @Test
    public void testGetUserById_Success() { }

    @Test(expected = Exception.class)
    public void testGetUserById_ThrowsException() { }
}

api-analyze - Project-Wide API Analysis

Scans entire project to map all public APIs and their invocation sequences.

# Using legacy-cli
./legacy-cli api-analyze <project-directory> [options]

# Or with Python
python main.py api-analyze <project-directory> [options]

Options:

  • --export, -e FILE - Export to markdown (saved to api-reports/)
  • --summary - Show only summary table

Examples:

# Full analysis with tree view
./legacy-cli api-analyze examples

# Export to markdown report
./legacy-cli api-analyze examples --export api-report.md
# Output: api-reports/api-report.md

# Show summary table only
./legacy-cli api-analyze examples --summary

πŸ” Understanding API Analysis

What is Analyzed?

The api-analyze command discovers:

  1. Public APIs: All public methods (excluding constructors)
  2. Call Sequences: Method invocation chains up to 4 levels deep
  3. Cross-File Calls: Methods calling other methods in different files
  4. External Dependencies: Calls to libraries, frameworks, databases
  5. Exception Paths: Thrown and caught exceptions

How Sequences are Traced

API Method (depth 0)
β”œβ”€β”€ Internal Method Call (depth 1)
β”‚   β”œβ”€β”€ External DB Call (depth 2)
β”‚   └── External Logger Call (depth 2)
└── External API Call (depth 1)

Depth Limits:

  • Maximum depth: 4 levels
  • Prevents infinite recursion
  • Stops at external dependencies

πŸ“Š Interpreting Results

Tree View Symbols

|--  Non-last item in list (has siblings below)
+--  Last item in list (no more siblings)
|    Continuation line (parent has more children)
     Spacing (parent is complete)

Example Output:

Call Sequence (Tree View):
  |-- newEmail.contains("@")
  |-- user.setEmail(newEmail)
  |-- UserDAO.update(user)
  +-- [UserService.java] UserService.getUserById(userId)
      |-- [EXTERNAL] Logger.info("Getting user...") (depth: 1)
      |-- [EXTERNAL] UserDAO.findById(userId) (depth: 1)
      +-- [EXTERNAL] Logger.warn("User not found") (depth: 1)

Interpretation:

  1. updateUserEmail calls 4 methods sequentially
  2. The last call (getUserById) is an internal method
  3. getUserById makes 3 external calls (to Logger and UserDAO)
  4. External calls are highlighted with [EXTERNAL]
  5. Depth indicators show nesting level

File Location Indicators

  • [EXTERNAL] - Third-party library, framework, or JDK call
  • [FileName.java] - Internal project method with source file name
  • ClassName.methodName(params) - Full method signature

Ordered List View

The same sequence in numbered format:

Call Sequence (Ordered List):
  1. newEmail.contains("@")
  2. user.setEmail(newEmail)
  3. UserDAO.update(user)
  4. [UserService.java] UserService.getUserById(userId)
    5. [EXTERNAL] Logger.info("Getting user...") (depth: 1)
    6. [EXTERNAL] UserDAO.findById(userId) (depth: 1)
    7. [EXTERNAL] Logger.warn("User not found") (depth: 1)

Use the ordered list to:

  • Understand execution order
  • Count total method calls
  • Identify performance bottlenecks

External API Calls Section

External API Calls:
  [EXT] Logger.info("Getting user...")
  [EXT] UserDAO.findById(userId)
  [EXT] NotificationService.send(...)

These are potential integration points that need:

  • Mocking in tests
  • Error handling
  • Performance monitoring
  • Circuit breakers (if remote services)

Exception Paths

Exception Paths:
  ! Throws: IllegalArgumentException
  ! Throws: Exception
  ! Catches: SQLException

Interpretation:

  • Throws: - Declared in method signature (throws Exception)
  • Throws: (in body) - Explicit throw new Exception() statements
  • Catches: - Try-catch blocks handling exceptions

Testing implications:

  • Test happy path AND exception paths
  • Verify exception messages
  • Test error recovery logic

πŸ“ Output Directory Structure

legacy-analyzer/
β”œβ”€β”€ legacy-cli                 # Unix/Linux/macOS executable
β”œβ”€β”€ legacy-cli.bat             # Windows batch file
β”œβ”€β”€ main.py                    # CLI entry point
β”œβ”€β”€ java_parser.py             # Java parser
β”œβ”€β”€ analyzer.py                # Code analyzer
β”œβ”€β”€ mock_generator.py          # Test generator
β”œβ”€β”€ api_analyzer.py            # API sequence analyzer
β”œβ”€β”€ output_formatter.py        # Console formatter
β”œβ”€β”€ api_output_formatter.py    # API formatter
β”œβ”€β”€ .gitignore                 # Git ignore
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ UserService.java
β”‚   └── PaymentProcessor.java
β”œβ”€β”€ generated-tests/           # ← AUTO-CREATED
β”‚   └── UserServiceTest.java
└── api-reports/               # ← AUTO-CREATED
    └── api-analysis.md

Generated Directories:

  • generated-tests/ - All test files (git-ignored)
  • api-reports/ - All markdown reports (git-ignored)

Path Behavior:

  • Relative paths: Saved to auto-created subdirectories
  • Absolute paths: Saved to exact location specified
# Relative β†’ generated-tests/MyTest.java
./legacy-cli generate File.java --output MyTest.java

# Absolute β†’ /home/user/custom/MyTest.java
./legacy-cli generate File.java --output /home/user/custom/MyTest.java

πŸ’‘ Use Cases & Examples

Use Case 1: Adding Tests to Legacy Code

Scenario: You have a 500-line OrderService.java with no tests.

# Step 1: Analyze complexity
./legacy-cli analyze OrderService.java --verbose

# Step 2: Generate test scaffolding
./legacy-cli generate OrderService.java --output OrderServiceTest.java

# Step 3: Customize generated tests
# Edit generated-tests/OrderServiceTest.java
# Add specific assertions and mock behaviors

What you get:

  • Understanding of code complexity
  • Complete test class structure
  • Mock setup for all dependencies
  • Test stubs for all public methods

Use Case 2: Understanding API Flow

Scenario: You need to understand how processPayment works across multiple classes.

# Analyze the entire payment module
./legacy-cli api-analyze src/payment/ --export payment-api-flow.md

What you learn:

  • Which methods processPayment calls
  • Cross-class dependencies
  • External service integrations (PaymentGateway, Database)
  • Exception handling strategy

Example result:

processPayment()
β”œβ”€β”€ validateCard() [CardValidator.java]
β”‚   β”œβ”€β”€ [EXTERNAL] CardDatabase.lookup()
β”‚   └── [EXTERNAL] FraudService.check()
β”œβ”€β”€ [EXTERNAL] PaymentGateway.charge()
└── sendConfirmation() [NotificationService.java]
    β”œβ”€β”€ [EXTERNAL] EmailService.send()
    └── [EXTERNAL] SMSService.send()

Use Case 3: Refactoring with Confidence

Scenario: You want to refactor a complex method but need to understand its impact.

# Before refactoring
./legacy-cli api-analyze src/ --export before-refactor.md

# After refactoring
./legacy-cli api-analyze src/ --export after-refactor.md

# Compare the two markdown files to see changes

Benefits:

  • Document original behavior
  • Verify refactoring didn't change call sequences
  • Identify unintended side effects

Use Case 4: Code Review & Documentation

Scenario: Reviewing a PR that adds new APIs.

# Generate API documentation
./legacy-cli api-analyze src/ --export pr-123-api-changes.md

Use the report to:

  • Review method invocation patterns
  • Identify missing error handling
  • Spot potential performance issues
  • Document API contracts

πŸŽ“ Best Practices

For Mock Generation

  1. Always review generated tests - They're starting points, not complete tests
  2. Add specific assertions - Replace generic assertNotNull with business logic checks
  3. Mock external dependencies - Database, HTTP clients, file I/O
  4. Test edge cases - Null inputs, empty lists, boundary values
  5. Verify interactions - Use verify() to check method calls

Example customization:

// Generated (generic)
@Test
public void testGetUserById_Success() {
    when(userDAO.findById(1)).thenReturn(mock(User.class));
    User result = userService.getUserById(1);
    assertNotNull(result);
}

// Customized (specific)
@Test
public void testGetUserById_Success() {
    User mockUser = new User(1, "John", "john@example.com");
    when(userDAO.findById(1)).thenReturn(mockUser);

    User result = userService.getUserById(1);

    assertEquals(1, result.getId());
    assertEquals("John", result.getName());
    verify(userDAO, times(1)).findById(1);
}

For API Analysis

  1. Start with small modules - Analyze one package at a time
  2. Focus on complex methods - Methods with 20+ lines and deep nesting
  3. Document external dependencies - Note which need mocking/stubbing
  4. Track exception flows - Ensure all paths are tested
  5. Export to markdown - Keep reports in version control for historical reference

For Large Codebases

# Analyze by package
./legacy-cli api-analyze src/payment --export payment-apis.md
./legacy-cli api-analyze src/orders --export order-apis.md
./legacy-cli api-analyze src/users --export user-apis.md

# Use --summary for quick overview
./legacy-cli api-analyze src/ --summary

πŸ”§ Complexity Indicators

Method Complexity

  • [S] Simple (≀5 lines) - Easy to test
  • [M] Moderate (6-15 lines) - Needs good coverage
  • [C] Complex (>15 lines) - High priority for testing

Testability Score

  • 80-100 (Good) - Easy to test, well-structured
  • 60-79 (Fair) - Some improvements needed
  • 0-59 (Needs Improvement) - Difficult to test, refactoring recommended

Factors affecting score:

  • Constructor injection (+20 points)
  • Few dependencies (+10 points)
  • No static methods (+5 points)
  • Clear method signatures (+5 points)

πŸ› Troubleshooting

"No public APIs found"

  • Check that Java files have public methods
  • Ensure you're pointing to the correct directory
  • Verify files have .java extension

"Cannot parse Java file"

  • Ensure Java syntax is valid
  • Check for unusual annotations or syntax
  • File must contain a valid class declaration

Unicode/Encoding Errors

  • Tool uses ASCII-safe characters
  • Should work on all platforms
  • If issues persist, redirect output: ./legacy-cli api-analyze examples > output.txt

πŸ“š Additional Resources

Project Structure

legacy-analyzer/
β”œβ”€β”€ πŸ“„ README.md              ← You are here
β”œβ”€β”€ πŸ“„ CHANGELOG.md           ← Version history
β”œβ”€β”€ πŸ“„ QUICKSTART.md          ← 2-minute guide
β”œβ”€β”€ legacy-cli                ← Unix/Linux/macOS executable
β”œβ”€β”€ legacy-cli.bat            ← Windows executable
└── examples/                 ← Sample Java files

Example Files Provided

  • UserService.java - CRUD service with DAO pattern
  • PaymentProcessor.java - Complex business logic with external calls

Try them:

./legacy-cli analyze examples/UserService.java
./legacy-cli api-analyze examples

🀝 Contributing

Found a bug? Have a feature request?

  1. Check existing issues
  2. Create a new issue with details
  3. Include example Java files if applicable

πŸ“ License

This tool is provided as-is for analyzing and testing Java code.


⭐ Key Takeaways

  1. analyze - Understand single file complexity
  2. generate - Create test scaffolding quickly
  3. api-analyze - Map entire project API flows
  4. Tree View - Visualize method call hierarchy
  5. External Calls - Identify integration points
  6. Auto-organized - Files saved to clean directories

Start simple, analyze often, test thoroughly.


Built with ❀️ for testing legacy Java code

About

A powerful CLI tool that analyzes Java legacy code, generates Mockito test mocks, and maps API invocation sequences across your entire codebase.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors