|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Swift-Spyable is a Swift macro library that generates spy/mock classes for protocols. It replaces manual test double creation with automated, type-safe spy generation using Swift macros. |
| 8 | + |
| 9 | +## Common Commands |
| 10 | + |
| 11 | +### Building and Testing |
| 12 | +- `swift build` - Build the package |
| 13 | +- `swift test` - Run all tests |
| 14 | +- `swift test -Xswiftc -Xfrontend -Xswiftc -dump-macro-expansions --enable-code-coverage` - Run tests with coverage and macro expansion dumps |
| 15 | +- `swift test --filter TestName` - Run specific test |
| 16 | + |
| 17 | +### Code Formatting |
| 18 | +- `swift format --recursive --in-place ./Package.swift ./Sources ./Tests ./Examples` - Format all code (automatically done by CI) |
| 19 | + |
| 20 | +### Platform-Specific Testing |
| 21 | +- macOS: Use Xcode 15.4+ or 16.2+ |
| 22 | +- Linux: Requires Swift 5.9+ |
| 23 | +- Run Examples: `cd Examples && swift test` |
| 24 | + |
| 25 | +## Architecture |
| 26 | + |
| 27 | +The codebase follows a clear separation between public API and implementation: |
| 28 | + |
| 29 | +### Core Structure |
| 30 | +- `Sources/Spyable/` - Public API (`@Spyable` macro) |
| 31 | +- `Sources/SpyableMacro/` - Macro implementation |
| 32 | + - `Macro/SpyableMacro.swift` - Main macro entry point |
| 33 | + - `Factories/` - Code generation logic split by concern |
| 34 | + - `Extractors/` - Protocol syntax extraction |
| 35 | + - `Extensions/` - SwiftSyntax utilities |
| 36 | + - `Diagnostics/` - Error handling |
| 37 | + |
| 38 | +### Key Design Patterns |
| 39 | +1. **Factory Pattern**: Each aspect of spy generation (methods, properties, call tracking) has its own factory |
| 40 | +2. **Visitor Pattern**: Uses SwiftSyntax visitors to traverse and analyze protocol declarations |
| 41 | +3. **Builder Pattern**: Constructs spy classes incrementally through multiple factories |
| 42 | + |
| 43 | +### Generated Spy Structure |
| 44 | +For a protocol `MyProtocol`, the macro generates `MyProtocolSpy` with: |
| 45 | +- `{method}Called` - Bool tracking if method was called |
| 46 | +- `{method}CallsCount` - Int counting method calls |
| 47 | +- `{method}ReceivedArguments` - Tuple of last received arguments |
| 48 | +- `{method}ReceivedInvocations` - Array of all invocations |
| 49 | +- `{method}Closure` - Optional closure for stubbing behavior |
| 50 | +- `{method}ReturnValue` - Stubbed return value (non-void methods) |
| 51 | +- `{method}ThrowableError` - Error to throw (throwing methods) |
| 52 | + |
| 53 | +## Development Workflow |
| 54 | + |
| 55 | +### Adding New Features |
| 56 | +1. Identify which factory needs modification or if a new factory is needed |
| 57 | +2. Update the factory implementation in `Sources/SpyableMacro/Factories/` |
| 58 | +3. Add corresponding tests in `Tests/SpyableMacroTests/` |
| 59 | +4. Update `SpyFactory.createSpy()` if adding a new factory |
| 60 | +5. Test with Examples project to ensure real-world usage works |
| 61 | + |
| 62 | +### Testing Strategy |
| 63 | +- Unit tests use `assertBuildResult` for macro expansion testing |
| 64 | +- Each factory has dedicated test files (e.g., `UT_CalledFactory.swift`) |
| 65 | +- Integration tests live in the Examples project |
| 66 | +- Always test edge cases: generics, async/throws, access levels |
| 67 | + |
| 68 | +### Debugging Macros |
| 69 | +1. Use `swift test -Xswiftc -Xfrontend -Xswiftc -dump-macro-expansions` to see generated code |
| 70 | +2. Add diagnostic messages in macro implementation using `context.diagnose()` |
| 71 | +3. Check `SpyableDiagnostic` for existing error types |
| 72 | + |
| 73 | +## Important Considerations |
| 74 | + |
| 75 | +### Swift Syntax |
| 76 | +- The project heavily uses SwiftSyntax for AST manipulation |
| 77 | +- When modifying syntax generation, ensure proper formatting and indentation |
| 78 | +- Use `DeclSyntax`, `TokenSyntax`, and related types from SwiftSyntax |
| 79 | + |
| 80 | +### Compatibility |
| 81 | +- Maintains compatibility with Swift 5.9+ |
| 82 | +- Must work across macOS, Linux, and iOS platforms |
| 83 | +- Windows support is experimental (CI disabled) |
| 84 | + |
| 85 | +### Code Generation Rules |
| 86 | +1. Generated code respects the original protocol's access level |
| 87 | +2. Property spies include both getter and setter tracking |
| 88 | +3. Methods with multiple parameters generate tuple types for arguments |
| 89 | +4. Generic constraints are preserved in generated spies |
| 90 | +5. Associated types are handled but may require manual implementation |
| 91 | + |
| 92 | +### CI/CD |
| 93 | +- GitHub Actions automatically formats code on main branch pushes |
| 94 | +- PRs are created for formatting changes |
| 95 | +- Matrix testing ensures compatibility across platforms and Swift versions |
| 96 | +- Code coverage is tracked via Codecov |
0 commit comments