#!/bin/bash # Documentation coverage checker # Ensures all code is properly documented set -e PROJECT_ROOT="/docker/mev-beta" cd "$PROJECT_ROOT" || exit 1 # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' info() { echo -e "${BLUE}ℹ${NC} $1"; } success() { echo -e "${GREEN}✓${NC} $1"; } warn() { echo -e "${YELLOW}⚠${NC} $1"; } error() { echo -e "${RED}✗${NC} $1"; } section() { echo -e "\n${CYAN}━━━ $1 ━━━${NC}\n"; } echo "📚 Documentation Coverage Check" echo "================================" echo "" ISSUES=0 # 1. Package Documentation section "1. Package Documentation" info "Checking package doc.go files..." PACKAGE_DIRS=$(find pkg/ -type d -mindepth 1 -maxdepth 2) TOTAL_PACKAGES=0 DOCUMENTED_PACKAGES=0 for pkg_dir in $PACKAGE_DIRS; do TOTAL_PACKAGES=$((TOTAL_PACKAGES + 1)) if [ -f "$pkg_dir/doc.go" ]; then DOCUMENTED_PACKAGES=$((DOCUMENTED_PACKAGES + 1)) success "$(basename $pkg_dir) has doc.go" else warn "$(basename $pkg_dir) missing doc.go" ISSUES=$((ISSUES + 1)) fi done PKG_COVERAGE=$((DOCUMENTED_PACKAGES * 100 / (TOTAL_PACKAGES + 1))) info "Package documentation: $PKG_COVERAGE% ($DOCUMENTED_PACKAGES/$TOTAL_PACKAGES)" # 2. Exported Function Documentation section "2. Exported Function Documentation" info "Checking exported function comments..." UNDOCUMENTED=() for file in $(find pkg/ -name "*.go" -not -name "*_test.go"); do # Find exported functions without comments while IFS= read -r line_num; do func_name=$(sed -n "${line_num}p" "$file" | awk '{print $2}' | cut -d'(' -f1) prev_line=$((line_num - 1)) prev_content=$(sed -n "${prev_line}p" "$file") if ! echo "$prev_content" | grep -q "^//"; then UNDOCUMENTED+=("$file:$line_num: $func_name") ISSUES=$((ISSUES + 1)) fi done < <(grep -n "^func [A-Z]" "$file" | cut -d: -f1 || true) done if [ ${#UNDOCUMENTED[@]} -gt 0 ]; then warn "Found ${#UNDOCUMENTED[@]} undocumented exported functions:" for item in "${UNDOCUMENTED[@]}"; do echo " - $item" done | head -10 if [ ${#UNDOCUMENTED[@]} -gt 10 ]; then echo " ... and $((${#UNDOCUMENTED[@]} - 10)) more" fi else success "All exported functions documented" fi # 3. Exported Type Documentation section "3. Exported Type Documentation" info "Checking exported type comments..." UNDOC_TYPES=0 for file in $(find pkg/ -name "*.go" -not -name "*_test.go"); do # Find exported types without comments while IFS= read -r line_num; do type_name=$(sed -n "${line_num}p" "$file" | awk '{print $2}') prev_line=$((line_num - 1)) prev_content=$(sed -n "${prev_line}p" "$file") if ! echo "$prev_content" | grep -q "^//.*$type_name"; then echo " - $file:$line_num: type $type_name" UNDOC_TYPES=$((UNDOC_TYPES + 1)) ISSUES=$((ISSUES + 1)) fi done < <(grep -n "^type [A-Z]" "$file" | cut -d: -f1 || true) done if [ "$UNDOC_TYPES" -gt 0 ]; then warn "Found $UNDOC_TYPES undocumented exported types" else success "All exported types documented" fi # 4. README Files section "4. README Files" CRITICAL_DIRS=("pkg" "cmd" "bindings" "contracts" "scripts" "docs") for dir in "${CRITICAL_DIRS[@]}"; do if [ -d "$dir" ] && [ ! -f "$dir/README.md" ]; then warn "$dir/ missing README.md" ISSUES=$((ISSUES + 1)) elif [ -f "$dir/README.md" ]; then success "$dir/ has README.md" fi done # 5. Project Documentation section "5. Project Documentation" REQUIRED_DOCS=("SPEC.md" "CLAUDE.md" "README.md" "docs/DEVELOPMENT_SETUP.md") for doc in "${REQUIRED_DOCS[@]}"; do if [ -f "$doc" ]; then # Check if file is non-empty if [ -s "$doc" ]; then SIZE=$(wc -l < "$doc") success "$doc exists ($SIZE lines)" else warn "$doc is empty" ISSUES=$((ISSUES + 1)) fi else error "$doc missing" ISSUES=$((ISSUES + 1)) fi done # 6. Inline Comments section "6. Inline Comments" info "Checking inline comment density..." TOTAL_LINES=$(find pkg/ -name "*.go" -not -name "*_test.go" -exec wc -l {} + | tail -1 | awk '{print $1}') COMMENT_LINES=$(find pkg/ -name "*.go" -not -name "*_test.go" -exec grep -c "^//" {} + | awk '{s+=$1} END {print s}') COMMENT_RATIO=$((COMMENT_LINES * 100 / (TOTAL_LINES + 1))) info "Inline comment ratio: $COMMENT_RATIO% ($COMMENT_LINES/$TOTAL_LINES)" if [ "$COMMENT_RATIO" -lt 10 ]; then warn "Low inline comment density (< 10%)" elif [ "$COMMENT_RATIO" -lt 20 ]; then info "Moderate inline comment density (10-20%)" else success "Good inline comment density (> 20%)" fi # 7. API Documentation section "7. API Documentation" if [ -d "api" ] || grep -r "http.Handle\|http.HandleFunc" pkg/ --include="*.go" | grep -q "."; then if [ ! -f "docs/API.md" ]; then warn "API endpoints detected but docs/API.md missing" ISSUES=$((ISSUES + 1)) else success "API documentation exists" fi fi # 8. Examples section "8. Examples" info "Checking for example code..." EXAMPLE_COUNT=$(find . -name "example*" -o -name "*_example.go" | wc -l) info "Found $EXAMPLE_COUNT example files" if [ "$EXAMPLE_COUNT" -lt 1 ]; then warn "No examples found (consider adding example_test.go files)" fi # Summary section "Documentation Summary" TOTAL_EXPORTED=$(find pkg/ -name "*.go" -not -name "*_test.go" -exec grep -c "^func [A-Z]\|^type [A-Z]" {} + | awk '{s+=$1} END {print s}') OVERALL_COVERAGE=$(((TOTAL_EXPORTED - ISSUES) * 100 / (TOTAL_EXPORTED + 1))) echo "Total exported symbols: $TOTAL_EXPORTED" echo "Documentation issues: $ISSUES" echo "Overall coverage: $OVERALL_COVERAGE%" echo "" if [ "$ISSUES" -eq 0 ]; then success "✅ All documentation requirements met!" exit 0 elif [ "$OVERALL_COVERAGE" -ge 80 ]; then warn "⚠️ Documentation coverage: $OVERALL_COVERAGE% (good, but $ISSUES issues found)" exit 0 else error "❌ Documentation coverage: $OVERALL_COVERAGE% (below 80% threshold)" exit 1 fi