15 KiB
15 KiB
コード差分レビューコマンド
現在のコード差分を分析し、コーディング規約とベストプラクティスに従ったレビューを実施します。
使用方法
/review-diff [対象ファイル・ディレクトリ]
対象が指定されない場合は、すべての変更されたファイルをレビューします。
処理手順
- 現在の変更差分を取得・分析
- プロジェクトのコーディング規約を特定
- 使用技術のベストプラクティスを適用
- 問題点と改善提案を整理
- 詳細なレビューレポートを生成
実装
ステップ1: 変更差分の取得
# git statusで変更ファイルを確認
echo "📋 変更されたファイルを確認中..."
CHANGED_FILES=$(git status --porcelain)
if [ -z "$CHANGED_FILES" ]; then
echo "ℹ️ レビュー対象の変更がありません"
exit 0
fi
echo "📝 変更されたファイル:"
echo "$CHANGED_FILES"
echo ""
# 詳細差分を取得
echo "🔍 差分を分析中..."
DIFF_CONTENT=$(git diff --no-color)
STAGED_DIFF=$(git diff --cached --no-color)
if [ -n "$STAGED_DIFF" ]; then
echo "📦 ステージング済みの変更も含めて分析します"
DIFF_CONTENT="$DIFF_CONTENT\n\n=== STAGED CHANGES ===\n$STAGED_DIFF"
fi
ステップ2: プロジェクト環境の分析
# プロジェクトの技術スタックを特定
echo "🔍 プロジェクト環境を分析中..."
PROJECT_TYPE=""
LANGUAGES=()
FRAMEWORKS=()
CONFIG_FILES=()
# 言語・フレームワークの検出
if [ -f "package.json" ]; then
PROJECT_TYPE="Node.js"
LANGUAGES+=("JavaScript" "TypeScript")
echo "📦 Node.js プロジェクトを検出"
# フレームワーク検出
if grep -q "react" package.json; then
FRAMEWORKS+=("React")
fi
if grep -q "vue" package.json; then
FRAMEWORKS+=("Vue.js")
fi
if grep -q "next" package.json; then
FRAMEWORKS+=("Next.js")
fi
if grep -q "express" package.json; then
FRAMEWORKS+=("Express")
fi
CONFIG_FILES+=("package.json" ".eslintrc*" ".prettierrc*" "tsconfig.json")
fi
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
PROJECT_TYPE="Python"
LANGUAGES+=("Python")
echo "🐍 Python プロジェクトを検出"
if grep -q "django" requirements.txt 2>/dev/null; then
FRAMEWORKS+=("Django")
fi
if grep -q "flask" requirements.txt 2>/dev/null; then
FRAMEWORKS+=("Flask")
fi
if grep -q "fastapi" requirements.txt 2>/dev/null; then
FRAMEWORKS+=("FastAPI")
fi
CONFIG_FILES+=("requirements.txt" "pyproject.toml" ".flake8" "mypy.ini")
fi
if [ -f "go.mod" ]; then
PROJECT_TYPE="Go"
LANGUAGES+=("Go")
echo "🔷 Go プロジェクトを検出"
CONFIG_FILES+=("go.mod" "go.sum")
fi
if [ -f "Cargo.toml" ]; then
PROJECT_TYPE="Rust"
LANGUAGES+=("Rust")
echo "🦀 Rust プロジェクトを検出"
CONFIG_FILES+=("Cargo.toml" "Cargo.lock")
fi
# その他の設定ファイル
CONFIG_FILES+=(".gitignore" "README.md" ".editorconfig")
echo "🏗️ 検出された技術スタック:"
echo " 言語: ${LANGUAGES[*]}"
echo " フレームワーク: ${FRAMEWORKS[*]}"
ステップ3: レビュー基準の設定
# レビュー基準を設定
echo "📐 レビュー基準を設定中..."
REVIEW_CRITERIA=()
# 共通基準
REVIEW_CRITERIA+=(
"コードの可読性と保守性"
"命名規則の一貫性"
"セキュリティベストプラクティス"
"パフォーマンス最適化"
"エラーハンドリング"
"テスタビリティ"
"ドキュメント整備"
)
# 言語固有の基準
for lang in "${LANGUAGES[@]}"; do
case $lang in
"JavaScript"|"TypeScript")
REVIEW_CRITERIA+=(
"ESLint/Prettier準拠"
"型安全性(TypeScript)"
"非同期処理のベストプラクティス"
"メモリリーク対策"
"バンドルサイズ最適化"
)
;;
"Python")
REVIEW_CRITERIA+=(
"PEP 8準拠"
"型ヒント使用"
"例外処理の適切性"
"パッケージ構造"
"docstring記述"
)
;;
"Go")
REVIEW_CRITERIA+=(
"Go Convention準拠"
"エラーハンドリング"
"Goroutineとチャネルの使用"
"メモリ効率"
"テストカバレッジ"
)
;;
"Rust")
REVIEW_CRITERIA+=(
"Rust Convention準拠"
"所有権とライフタイム"
"Result型でのエラーハンドリング"
"メモリ安全性"
"パフォーマンス"
)
;;
esac
done
echo "📋 適用されるレビュー基準:"
for criteria in "${REVIEW_CRITERIA[@]}"; do
echo " - $criteria"
done
ステップ4: 自動チェックの実行
# 利用可能なリンター・チェッカーを実行
echo "🔧 自動チェックを実行中..."
LINT_RESULTS=()
# JavaScript/TypeScript
if command -v npm >/dev/null 2>&1 && [ -f "package.json" ]; then
echo "📝 ESLint チェック実行中..."
if npm run lint --silent 2>/dev/null; then
LINT_RESULTS+=("✅ ESLint: 問題なし")
else
LINT_RESULTS+=("❌ ESLint: 問題が検出されました")
fi
if command -v tsc >/dev/null 2>&1 && [ -f "tsconfig.json" ]; then
echo "🏷️ TypeScript型チェック実行中..."
if npx tsc --noEmit --skipLibCheck 2>/dev/null; then
LINT_RESULTS+=("✅ TypeScript: 型エラーなし")
else
LINT_RESULTS+=("❌ TypeScript: 型エラーが検出されました")
fi
fi
fi
# Python
if command -v ruff >/dev/null 2>&1; then
echo "🐍 Ruff チェック実行中..."
if ruff check . --quiet 2>/dev/null; then
LINT_RESULTS+=("✅ Ruff: 問題なし")
else
LINT_RESULTS+=("❌ Ruff: 問題が検出されました")
fi
fi
if command -v mypy >/dev/null 2>&1; then
echo "🏷️ MyPy型チェック実行中..."
if mypy . --ignore-missing-imports --quiet 2>/dev/null; then
LINT_RESULTS+=("✅ MyPy: 型エラーなし")
else
LINT_RESULTS+=("❌ MyPy: 型エラーが検出されました")
fi
fi
# Go
if command -v golangci-lint >/dev/null 2>&1 && [ -f "go.mod" ]; then
echo "🔷 golangci-lint チェック実行中..."
if golangci-lint run --quiet 2>/dev/null; then
LINT_RESULTS+=("✅ golangci-lint: 問題なし")
else
LINT_RESULTS+=("❌ golangci-lint: 問題が検出されました")
fi
fi
# Rust
if command -v cargo >/dev/null 2>&1 && [ -f "Cargo.toml" ]; then
echo "🦀 Cargo clippy チェック実行中..."
if cargo clippy --quiet -- -D warnings 2>/dev/null; then
LINT_RESULTS+=("✅ Clippy: 問題なし")
else
LINT_RESULTS+=("❌ Clippy: 問題が検出されました")
fi
fi
echo "🔍 自動チェック結果:"
for result in "${LINT_RESULTS[@]}"; do
echo " $result"
done
ステップ5: レビューレポート生成
# レビューレポートを生成
echo ""
echo "📊 コード差分レビューレポート"
echo "=================================="
echo ""
echo "📅 レビュー実施日時: $(date '+%Y年%m月%d日 %H:%M:%S')"
echo "🏗️ プロジェクトタイプ: $PROJECT_TYPE"
echo "💻 検出言語: ${LANGUAGES[*]}"
echo "🚀 使用フレームワーク: ${FRAMEWORKS[*]}"
echo ""
echo "## 📋 変更ファイル一覧"
git status --porcelain | while read -r line; do
status=${line:0:2}
file=${line:3}
case $status in
"M ") echo " 📝 変更: $file" ;;
"A ") echo " ➕ 追加: $file" ;;
"D ") echo " ❌ 削除: $file" ;;
"R ") echo " 🔄 リネーム: $file" ;;
"??") echo " ❓ 未追跡: $file" ;;
*) echo " 📄 $status: $file" ;;
esac
done
echo ""
echo "## 🔧 自動チェック結果"
for result in "${LINT_RESULTS[@]}"; do
echo " $result"
done
echo ""
echo "## 📐 レビューポイント"
echo ""
echo "### ✅ 良い点"
echo "- Conventional Commits形式でのコミットメッセージ作成"
echo "- 適切なファイル構造とディレクトリ組織"
echo "- 設定ファイルの適切な管理"
echo ""
echo "### 🔍 改善提案"
echo ""
# ファイル別の具体的な改善提案
git diff --name-only | while read -r file; do
echo "#### 📄 $file"
case $file in
*.js|*.ts|*.jsx|*.tsx)
echo "- **JavaScript/TypeScript ベストプラクティス**"
echo " - console.log の削除を確認"
echo " - 未使用インポートの削除"
echo " - 適切な型定義の使用"
echo " - エラーハンドリングの実装"
;;
*.py)
echo "- **Python ベストプラクティス**"
echo " - PEP 8準拠の確認"
echo " - 型ヒントの追加"
echo " - docstringの記述"
echo " - 例外処理の適切な実装"
;;
*.go)
echo "- **Go ベストプラクティス**"
echo " - エラーハンドリングの確認"
echo " - 未使用変数の削除"
echo " - 適切なパッケージ構造"
echo " - テストの追加"
;;
*.rs)
echo "- **Rust ベストプラクティス**"
echo " - 所有権とライフタイムの確認"
echo " - Result型の適切な使用"
echo " - パフォーマンス最適化"
echo " - 安全性の確認"
;;
*.md)
echo "- **Markdown ドキュメント**"
echo " - リンクの有効性確認"
echo " - 見出し構造の整理"
echo " - コードブロックの言語指定"
echo " - 誤字脱字の確認"
;;
*.json)
echo "- **JSON設定ファイル**"
echo " - フォーマットの統一"
echo " - 不要なプロパティの削除"
echo " - セキュリティ設定の確認"
;;
*)
echo "- **一般的な改善点**"
echo " - ファイル形式の適切性"
echo " - 文字エンコーディングの確認"
echo " - 改行コードの統一"
;;
esac
echo ""
done
echo "### 🚀 次のステップ"
echo "1. 自動チェックで検出された問題の修正"
echo "2. 改善提案の検討・実装"
echo "3. テストの実行・追加"
echo "4. ドキュメントの更新"
echo "5. コードレビューの依頼"
echo ""
echo "## 📈 品質メトリクス"
echo ""
TOTAL_FILES=$(git diff --name-only | wc -l)
ADDED_LINES=$(git diff --numstat | awk '{add+=$1} END {print add+0}')
DELETED_LINES=$(git diff --numstat | awk '{del+=$2} END {print del+0}')
echo "📊 変更統計:"
echo " - 変更ファイル数: $TOTAL_FILES"
echo " - 追加行数: +$ADDED_LINES"
echo " - 削除行数: -$DELETED_LINES"
echo " - 正味変更: $((ADDED_LINES - DELETED_LINES))"
echo ""
echo "🎯 レビュー完了!改善提案を参考にコードの品質向上を図ってください。"
レビュー対象
セキュリティ(最重要・厚めにチェック)
- 認証・認可
- ハードコードされた認証情報(API key, password, token等)
- 認証トークンの安全な保管方法
- 認可チェックの実装(権限検証の欠落)
- セッション管理の安全性
- インジェクション攻撃
- SQLインジェクション脆弱性
- NoSQLインジェクション
- コマンドインジェクション
- XSS(Stored/Reflected/DOM-based)
- LDAP/XMLインジェクション
- 入力検証とサニタイゼーション
- ユーザー入力の検証不足
- ファイルアップロードの検証
- Content-Type検証
- サイズ制限の実装
- ホワイトリスト方式の採用
- データ保護
- 機密情報のログ出力
- 暗号化の適切な実装
- 安全でない乱数生成
- パスワードのハッシュ化(bcrypt、Argon2等)
- API/ネットワークセキュリティ
- CORS設定の安全性
- CSRF対策の実装
- Rate limiting の実装
- HTTPSの強制
- 依存関係のセキュリティ
- 既知の脆弱性を持つライブラリ
- 最新版への更新の必要性
- その他のセキュリティ
- パストラバーサル脆弱性
- XXE(XML External Entity)攻撃
- サーバーサイドリクエストフォージェリ(SSRF)
- 安全でないデシリアライゼーション
テストケース(重要・厚めにチェック)
- テストカバレッジ
- 新規機能に対するテストの有無
- 既存機能への影響範囲のテスト
- エッジケースのカバー状況
- エラーケースのテスト
- テストの種類と品質
- 単体テスト(Unit Test)の適切性
- 統合テスト(Integration Test)の必要性
- E2Eテストの必要性
- テストの可読性と保守性
- テストケースの十分性
- 正常系のテスト
- 異常系のテスト(バリデーションエラー、ネットワークエラー等)
- 境界値テスト
- 並行処理のテスト(該当する場合)
- セキュリティテスト
- 認証・認可のテスト
- 入力検証のテスト
- エラーハンドリングのテスト
- モックとテストデータ
- 外部依存のモック化
- テストデータの適切性
- テスト環境の分離
- パフォーマンステスト
- 負荷テストの必要性評価
- レスポンスタイムの検証
- 過剰なテストの検出
- 実装の詳細に依存しすぎたテスト(脆弱なテスト)
- 重複したテストケース
- 価値の低いテスト(自明な処理のテスト)
- メンテナンスコストが高すぎるテスト
- 不要にモックが多すぎるテスト
コード品質
- 可読性、保守性、パフォーマンス
- 命名規則の一貫性
- 重複コードの検出
- 複雑度の評価
- デッドコードの検出
ベストプラクティス
- 言語・フレームワーク固有の推奨事項
- 既存のアーキテクチャとの整合性
- 適切なエラーハンドリング
ドキュメント
- README、コメント、型定義
- API仕様の更新
- 変更履歴の記録
技術スタック別対応
- Node.js: ESLint、Prettier、TypeScript
- Python: Ruff、MyPy、PEP 8
- Go: golangci-lint、Go Convention
- Rust: Clippy、Rust Convention
注意事項
- 自動チェックツールが利用可能な場合のみ実行
- プロジェクト固有のルールがある場合は設定ファイルを参照
- レビュー結果は参考として活用し、最終判断は開発者が行う
- セキュリティに関わる問題は特に注意深く確認