# Участие в разработке Rust Diff Analyzer
Спасибо за интерес к участию в проекте!
## Стиль кода и стандарты
Этот проект следует стандартам кодирования [RustManifest](https://github.com/RAprogramm/RustManifest). Пожалуйста, ознакомьтесь с ними перед началом работы.
Ключевые моменты:
- Используйте `cargo +nightly fmt` для форматирования
- Никаких `unwrap()` или `expect()` в продакшен коде
- Документация только через Rustdoc (без инлайн комментариев)
- Описательные имена переменных и функций
## Настройка окружения
### Требования
- Rust nightly toolchain
- cargo-make (опционально, для автоматизации задач)
- cargo-nextest (для запуска тестов)
### Установка
```bash
git clone https://github.com/RAprogramm/rust-prod-diff-checker
cd rust-prod-diff-checker
# Установка nightly toolchain
rustup toolchain install nightly
rustup component add rustfmt --toolchain nightly
rustup component add clippy
# Установка test runner (опционально, но рекомендуется)
cargo install cargo-nextest
```
### Pre-commit проверки
Перед коммитом убедитесь, что все проверки проходят:
```bash
# Проверка форматирования
cargo +nightly fmt --all -- --check
# Линтинг
cargo clippy --all-targets --all-features -- -D warnings
# Тесты
cargo test --all-features
# Или с nextest
cargo nextest run --all-features
```
## Git Workflow
### Именование веток
Используйте номер issue как имя ветки:
```
123
```
### Сообщения коммитов
Формат: `#<номер_issue> <тип>: <описание>`
```
#123 feat: add new output format
#123 fix: correct line counting in parser
#45 docs: update API examples
#78 test: add property tests for extractor
#90 refactor: simplify config loading
```
Типы:
- `feat` - новая функциональность
- `fix` - исправление бага
- `docs` - документация
- `test` - тесты
- `refactor` - рефакторинг кода
- `chore` - служебные задачи
### Pull Requests
1. Создайте ветку от `main`
2. Внесите изменения
3. Убедитесь, что все CI проверки проходят
4. Создайте PR с описательным заголовком
5. Включите `Closes #<issue>` в описание
### Держите изменения продакшен кода маленькими
**Качество код-ревью падает с размером.** Важен именно *продакшен код*, а не общее количество строк.
| < 100 строк | Тщательное | Низкий |
| 100-300 строк | Умеренное | Средний |
| 300+ строк | Поверхностное | Высокий |
**Тесты и бенчмарки не считаются так же:**
- PR с 50 строками в `src/` и 1000 строками тестов — **легко ревьюить**
- PR с 300 строками в `src/` и 0 тестов — **сложно ревьюить и рискованно**
Используйте [rust-prod-diff-checker](https://github.com/RAprogramm/rust-prod-diff-checker) GitHub Action для автоматического анализа размера PR и разделения продакшен изменений от тестов/бенчмарков.
**Правило:** Если ревьюер не может понять ваши изменения продакшен кода за 15 минут — PR слишком большой.
## Тестирование
### Организация тестов
```
tests/
├── integration.rs # Интеграционные тесты
├── property.rs # Property-based тесты
└── fixtures/ # Тестовые данные
```
### Написание тестов
- Покрывайте все публичные API функции
- Тестируйте пути ошибок, не только happy path
- Используйте property-based тестирование для парсеров
- Никаких `unwrap()` в тестах — используйте `?` с правильными типами ошибок
```rust
#[test]
fn test_parse_diff() -> Result<(), Box<dyn std::error::Error>> {
let diff = include_str!("fixtures/sample.diff");
let result = parse_diff(diff)?;
assert_eq!(result.len(), 3);
Ok(())
}
```
### Запуск тестов
```bash
# Все тесты
cargo test --all-features
# С покрытием
cargo llvm-cov nextest --all-features
# Конкретный тест
cargo test test_parse_diff
# Только property тесты
cargo test --test property
```
## CI/CD Pipeline
### Автоматические проверки
Каждый PR запускает:
| Format | `cargo +nightly fmt --check` |
| Clippy | `cargo clippy -D warnings` |
| Test | `cargo test --all-features` |
| Doc | `cargo doc --no-deps` |
| Coverage | Загрузка в Codecov |
| Benchmark | Компиляция бенчмарков |
| Audit | Сканирование уязвимостей |
| REUSE | Проверка лицензий |
### Требования к покрытию
- Цель проекта: auto (поддерживать текущий уровень)
- Цель патча: 80% (новый код должен быть хорошо протестирован)
## Архитектура
### Структура модулей
```
src/
├── lib.rs # Экспорт публичного API
├── error.rs # Типы ошибок (AppError)
├── config.rs # Работа с конфигурацией
├── analysis/
│ ├── mod.rs # Модуль анализа
│ ├── ast_visitor.rs # AST visitor для семантического извлечения
│ ├── extractor.rs # Извлечение AST
│ └── mapper.rs # Маппинг изменений (возвращает MapResult)
├── classifier/
│ └── ... # Логика классификации кода
├── git/
│ └── diff_parser.rs # Парсинг git diff
├── types/
│ ├── change.rs # Change, Summary, AnalysisResult
│ ├── classification.rs # Enum CodeType
│ ├── scope.rs # AnalysisScope, ExclusionReason
│ └── semantic_unit.rs # SemanticUnit с qualified_name()
└── output/
├── formatter.rs # Форматирование вывода
├── comment.rs # Формат PR комментария с таблицами
├── github.rs # Формат GitHub Actions
└── json.rs # JSON формат
```
### Ключевые типы
- `SemanticUnit` - Элемент кода с `qualified_name()` для контекста impl
- `Change` - Изменение semantic unit с классификацией и счётчиком строк
- `MapResult` - Результат `map_changes()` содержит изменения и `AnalysisScope`
- `AnalysisScope` - Отслеживает проанализированные и пропущенные файлы
- `ExclusionReason` - Причина пропуска файла (NonRust, IgnorePattern)
- `CodeType` - Классификация: Production, Test, Benchmark, Example
- `Config` - Конфигурация времени выполнения
## Добавление функциональности
### Новый формат вывода
1. Создайте `src/output/newformat.rs`
2. Реализуйте трейт `OutputFormatter`
3. Добавьте в enum `OutputFormat` в `config.rs`
4. Зарегистрируйте в `src/output/formatter.rs`
5. Добавьте тесты и документацию
### Новый тип Code Unit
1. Добавьте вариант в `UnitKind` в `src/analysis/extractor.rs`
2. Реализуйте извлечение в `extract_units()`
3. Добавьте вес в `config.rs`
4. Обновите тесты
## Процесс релиза
Релизы автоматизированы через CI при пуше тега:
1. Обновите версию в `Cargo.toml`
2. Коммит: `chore(release): prepare v1.x.x`
3. Создайте и запушьте тег:
```bash
git tag v1.x.x
git push origin v1.x.x
```
4. CI собирает бинарники для всех платформ
5. GitHub Release создается автоматически
6. Changelog обновляется
### Версионирование
Следуйте [Semantic Versioning](https://semver.org/):
- MAJOR: Ломающие изменения API
- MINOR: Новая функциональность, обратно совместимая
- PATCH: Исправления багов
## Документация
### Документация кода
Все публичные элементы должны иметь Rustdoc:
```rust
/// Parses a unified diff string into structured file diffs.
///
/// # Errors
///
/// Returns `AppError::DiffParse` if the diff format is invalid.
///
/// # Examples
///
/// ```
/// use rust_diff_analyzer::git::parse_diff;
///
/// let diff = "diff --git a/foo.rs b/foo.rs\n...";
/// let files = parse_diff(diff)?;
/// # Ok::<(), rust_diff_analyzer::AppError>(())
/// ```
pub fn parse_diff(input: &str) -> Result<Vec<FileDiff>, AppError> {
// ...
}
```
### Обновление README
Обновляйте README.md при:
- Добавлении новых CLI опций
- Изменении формата конфигурации
- Добавлении новых форматов вывода
- Изменении inputs/outputs GitHub Action
## Получение помощи
- Открывайте issue для багов или запросов функциональности
- Проверяйте существующие issues перед созданием новых
- Предоставляйте минимальное воспроизведение для багов
## Лицензия
Участвуя в проекте, вы соглашаетесь, что ваши contributions будут лицензированы под MIT License.