diff --git a/.github/workflows/pr-automation.yml b/.github/workflows/pr-automation.yml index 89d555ac..d0aef62a 100644 --- a/.github/workflows/pr-automation.yml +++ b/.github/workflows/pr-automation.yml @@ -20,109 +20,109 @@ jobs: tests-passed: ${{ steps.tests.outputs.passed }} steps: - - name: ๐Ÿ“ฅ Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - name: ๐Ÿ” Get changed files - id: changed-files - uses: tj-actions/changed-files@v40 - with: - files: | - **/*.c - **/*.cpp - **/*.java - **/*.py - **/*.js - **/*.ts - **/*.go - **/*.rs - - - name: โœ… Run PR Validation - id: validation - if: steps.changed-files.outputs.any_changed == 'true' - run: | - echo "Running validation checks..." - - # Call existing validation workflow logic - ./.github/scripts/validate-pr.sh || validation_failed=true - - if [ "$validation_failed" = true ]; then - echo "passed=false" >> $GITHUB_OUTPUT - exit 1 - else - echo "passed=true" >> $GITHUB_OUTPUT - fi - - - name: ๐Ÿ Setup Python for testing - if: contains(steps.changed-files.outputs.all_changed_files, '.py') - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: โ˜• Setup Java for testing - if: contains(steps.changed-files.outputs.all_changed_files, '.java') - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '11' - - - name: ๐Ÿ”ง Setup Node.js for testing - if: contains(steps.changed-files.outputs.all_changed_files, '.js') || contains(steps.changed-files.outputs.all_changed_files, '.ts') - uses: actions/setup-node@v4 - with: - node-version: '18' - - - name: ๐Ÿฆ€ Setup Rust for testing - if: contains(steps.changed-files.outputs.all_changed_files, '.rs') - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - - - name: ๐Ÿงช Run code compilation tests - id: tests - if: steps.changed-files.outputs.any_changed == 'true' - run: | - echo "Running compilation tests..." - test_failed=false - - for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - case "$file" in - *.cpp) - echo "Testing C++ file: $file" - g++ -std=c++17 -Wall -Wextra -o test_cpp "$file" || test_failed=true - ;; - *.c) - echo "Testing C file: $file" - gcc -Wall -Wextra -o test_c "$file" || test_failed=true - ;; - *.java) - echo "Testing Java file: $file" - javac "$file" || test_failed=true - ;; - *.py) - echo "Testing Python file: $file" - python -m py_compile "$file" || test_failed=true - ;; - *.js) - echo "Testing JavaScript file: $file" - node -c "$file" || test_failed=true - ;; - *.rs) - echo "Testing Rust file: $file" - rustc --check "$file" || test_failed=true - ;; - esac - done - - if [ "$test_failed" = true ]; then - echo "passed=false" >> $GITHUB_OUTPUT - exit 1 - else - echo "passed=true" >> $GITHUB_OUTPUT - fi + - name: ๐Ÿ“ฅ Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: ๐Ÿ” Get changed files + id: changed-files + uses: tj-actions/changed-files@v40 + with: + files: | + **/*.c + **/*.cpp + **/*.java + **/*.py + **/*.js + **/*.ts + **/*.go + **/*.rs + + - name: โœ… Run PR Validation + id: validation + if: steps.changed-files.outputs.any_changed == 'true' + run: | + echo "Running validation checks..." + + # Call existing validation workflow logic + ./.github/scripts/validate-pr.sh || validation_failed=true + + if [ "$validation_failed" = true ]; then + echo "passed=false" >> $GITHUB_OUTPUT + exit 1 + else + echo "passed=true" >> $GITHUB_OUTPUT + fi + + - name: ๐Ÿ Setup Python for testing + if: contains(steps.changed-files.outputs.all_changed_files, '.py') + uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: โ˜• Setup Java for testing + if: contains(steps.changed-files.outputs.all_changed_files, '.java') + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "11" + + - name: ๐Ÿ”ง Setup Node.js for testing + if: contains(steps.changed-files.outputs.all_changed_files, '.js') || contains(steps.changed-files.outputs.all_changed_files, '.ts') + uses: actions/setup-node@v4 + with: + node-version: "18" + + - name: ๐Ÿฆ€ Setup Rust for testing + if: contains(steps.changed-files.outputs.all_changed_files, '.rs') + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: ๐Ÿงช Run code compilation tests + id: tests + if: steps.changed-files.outputs.any_changed == 'true' + run: | + echo "Running compilation tests..." + test_failed=false + + for file in ${{ steps.changed-files.outputs.all_changed_files }}; do + case "$file" in + *.cpp) + echo "Testing C++ file: $file" + g++ -std=c++17 -Wall -Wextra -o test_cpp "$file" || test_failed=true + ;; + *.c) + echo "Testing C file: $file" + gcc -Wall -Wextra -o test_c "$file" || test_failed=true + ;; + *.java) + echo "Testing Java file: $file" + javac "$file" || test_failed=true + ;; + *.py) + echo "Testing Python file: $file" + python -m py_compile "$file" || test_failed=true + ;; + *.js) + echo "Testing JavaScript file: $file" + node -c "$file" || test_failed=true + ;; + *.rs) + echo "Testing Rust file: $file" + rustc --check "$file" || test_failed=true + ;; + esac + done + + if [ "$test_failed" = true ]; then + echo "passed=false" >> $GITHUB_OUTPUT + exit 1 + else + echo "passed=true" >> $GITHUB_OUTPUT + fi # Wait for all checks to complete wait-for-checks: @@ -132,11 +132,11 @@ jobs: if: always() steps: - - name: Wait for other workflows - run: | - echo "โณ Waiting for all validation and test workflows to complete..." - sleep 30 - echo "โœ… Proceeding with labeling and notifications" + - name: Wait for other workflows + run: | + echo "โณ Waiting for all validation and test workflows to complete..." + sleep 30 + echo "โœ… Proceeding with labeling and notifications" # Auto-labeling and first-time contributor welcome auto-label: @@ -146,112 +146,112 @@ jobs: if: always() steps: - - name: ๐ŸŽƒ Add Hacktoberfest labels and welcome contributors - uses: actions/github-script@v7 - env: - VALIDATION_PASSED: ${{ needs.run-tests.outputs.validation-passed }} - TESTS_PASSED: ${{ needs.run-tests.outputs.tests-passed }} - with: - script: | - const { owner, repo, number } = context.issue; - const validationPassed = process.env.VALIDATION_PASSED === 'true'; - const testsPassed = process.env.TESTS_PASSED === 'true'; - - // Get PR and contributor info - const pr = await github.rest.pulls.get({ owner, repo, pull_number: number }); - const contributor = pr.data.user.login; - - // Check if first-time contributor - const contributions = await github.rest.repos.listPullRequestsAssociatedWithCommit({ - owner, - repo, - commit_sha: pr.data.head.sha - }); - - const isFirstTime = contributions.data.length <= 1; - - // Add labels based on PR content and status - const labels = ['hacktoberfest-accepted']; - - // Add language labels based on changed files - const files = await github.rest.pulls.listFiles({ owner, repo, pull_number: number }); - const languages = new Set(); - - files.data.forEach(file => { - const ext = file.filename.split('.').pop(); - switch(ext) { - case 'cpp': languages.add('C++'); break; - case 'c': languages.add('C'); break; - case 'java': languages.add('Java'); break; - case 'py': languages.add('Python'); break; - case 'js': languages.add('JavaScript'); break; - case 'rs': languages.add('Rust'); break; - case 'go': languages.add('Go'); break; + - name: ๐ŸŽƒ Add Hacktoberfest labels and welcome contributors + uses: actions/github-script@v7 + env: + VALIDATION_PASSED: ${{ needs.run-tests.outputs.validation-passed }} + TESTS_PASSED: ${{ needs.run-tests.outputs.tests-passed }} + with: + script: | + const { owner, repo, number } = context.issue; + const validationPassed = process.env.VALIDATION_PASSED === 'true'; + const testsPassed = process.env.TESTS_PASSED === 'true'; + + // Get PR and contributor info + const pr = await github.rest.pulls.get({ owner, repo, pull_number: number }); + const contributor = pr.data.user.login; + + // Check if first-time contributor + const contributions = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + owner, + repo, + commit_sha: pr.data.head.sha + }); + + const isFirstTime = contributions.data.length <= 1; + + // Add labels based on PR content and status + const labels = ['hacktoberfest-accepted']; + + // Add language labels based on changed files + const files = await github.rest.pulls.listFiles({ owner, repo, pull_number: number }); + const languages = new Set(); + + files.data.forEach(file => { + const ext = file.filename.split('.').pop(); + switch(ext) { + case 'cpp': languages.add('C++'); break; + case 'c': languages.add('C'); break; + case 'java': languages.add('Java'); break; + case 'py': languages.add('Python'); break; + case 'js': languages.add('JavaScript'); break; + case 'rs': languages.add('Rust'); break; + case 'go': languages.add('Go'); break; + } + }); + + languages.forEach(lang => labels.push(lang.toLowerCase())); + + // Add difficulty labels + if (files.data.length <= 2) labels.push('good first issue'); + if (files.data.length > 5) labels.push('advanced'); + + // Add status labels + if (testsPassed) { + labels.push('tests-passing'); + } else { + labels.push('needs-work'); } - }); - - languages.forEach(lang => labels.push(lang.toLowerCase())); - - // Add difficulty labels - if (files.data.length <= 2) labels.push('good first issue'); - if (files.data.length > 5) labels.push('advanced'); - - // Add status labels - if (testsPassed) { - labels.push('tests-passing'); - } else { - labels.push('needs-work'); - } - - if (isFirstTime) { - labels.push('first-time-contributor'); - } - - // Apply labels - await github.rest.issues.addLabels({ - owner, - repo, - issue_number: number, - labels - }); - - // Welcome first-time contributors - if (isFirstTime) { - const welcomeMessage = ` - ๐ŸŽ‰ **Welcome to Hacktoberfest 2025, @${contributor}!** ๐ŸŽƒ - - Thank you for your first contribution to our DSA repository! Here's what happens next: - - ## ๐Ÿ” Automatic Checks - - โœ… **Code Validation**: ${validationPassed ? 'Passed' : 'Failed'} - - ๐Ÿงช **Compilation Tests**: ${testsPassed ? 'Passed' : 'Failed'} - - ## ๐Ÿ“‹ Next Steps - ${testsPassed ? - '๐ŸŽฏ **Great job!** Your code compiled successfully. Maintainers [@Karanjot786](https://github.com/Karanjot786) and [@Pradeepsingh61](https://github.com/Pradeepsingh61) will review your PR soon.' : - 'โš ๏ธ **Action needed**: Please fix the compilation errors and push your changes.'} - - ## ๐ŸŽ What You Get - - ๐Ÿ† **Hacktoberfest Credit**: This PR counts toward your 6 PR goal for exclusive T-shirt + Tree! - - ๐ŸŒŸ **Hall of Fame**: You'll be featured in our contributors list - - ๐Ÿ“š **Learning**: Code review feedback from experienced developers - - ## ๐Ÿ’ก Tips for Success - - Follow our [Contributing Guidelines](./CONTRIBUTING.md) - - Add comments explaining your algorithm - - Include time/space complexity analysis - - Test your code before submitting - - Welcome to the community! ๐Ÿš€ - `; - await github.rest.issues.createComment({ + if (isFirstTime) { + labels.push('first-time-contributor'); + } + + // Apply labels + await github.rest.issues.addLabels({ owner, repo, issue_number: number, - body: welcomeMessage + labels }); - } + + // Welcome first-time contributors + if (isFirstTime) { + const welcomeMessage = ` + ๐ŸŽ‰ **Welcome to Hacktoberfest 2025, @${contributor}!** ๐ŸŽƒ + + Thank you for your first contribution to our DSA repository! Here's what happens next: + + ## ๐Ÿ” Automatic Checks + - โœ… **Code Validation**: ${validationPassed ? 'Passed' : 'Failed'} + - ๐Ÿงช **Compilation Tests**: ${testsPassed ? 'Passed' : 'Failed'} + + ## ๐Ÿ“‹ Next Steps + ${testsPassed ? + '๐ŸŽฏ **Great job!** Your code compiled successfully. Maintainers [@Karanjot786](https://github.com/Karanjot786) and [@Pradeepsingh61](https://github.com/Pradeepsingh61) will review your PR soon.' : + 'โš ๏ธ **Action needed**: Please fix the compilation errors and push your changes.'} + + ## ๐ŸŽ What You Get + - ๐Ÿ† **Hacktoberfest Credit**: This PR counts toward your 6 PR goal for exclusive T-shirt + Tree! + - ๐ŸŒŸ **Hall of Fame**: You'll be featured in our contributors list + - ๐Ÿ“š **Learning**: Code review feedback from experienced developers + + ## ๐Ÿ’ก Tips for Success + - Follow our [Contributing Guidelines](./CONTRIBUTING.md) + - Add comments explaining your algorithm + - Include time/space complexity analysis + - Test your code before submitting + + Welcome to the community! ๐Ÿš€ + `; + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: number, + body: welcomeMessage + }); + } # Request review from maintainers request-review: @@ -261,33 +261,33 @@ jobs: if: needs.run-tests.outputs.tests-passed == 'true' steps: - - name: ๐Ÿ“‹ Request review from maintainers - uses: actions/github-script@v7 - with: - script: | - const { owner, repo, number } = context.issue; - - // List of maintainers who can review - const reviewers = ['Karanjot786']; - - // Get PR details - const pr = await github.rest.pulls.get({ owner, repo, pull_number: number }); - - // Don't request review from the PR author - const availableReviewers = reviewers.filter(reviewer => - reviewer !== pr.data.user.login - ); - - if (availableReviewers.length > 0) { - await github.rest.pulls.requestReviewers({ - owner, - repo, - pull_number: number, - reviewers: availableReviewers.slice(0, 2) // Request max 2 reviewers - }); - - console.log(`Requested review from: ${availableReviewers.slice(0, 2).join(', ')}`); - } + - name: ๐Ÿ“‹ Request review from maintainers + uses: actions/github-script@v7 + with: + script: | + const { owner, repo, number } = context.issue; + + // List of maintainers who can review + const reviewers = ['Karanjot786']; + + // Get PR details + const pr = await github.rest.pulls.get({ owner, repo, pull_number: number }); + + // Don't request review from the PR author + const availableReviewers = reviewers.filter(reviewer => + reviewer !== pr.data.user.login + ); + + if (availableReviewers.length > 0) { + await github.rest.pulls.requestReviewers({ + owner, + repo, + pull_number: number, + reviewers: availableReviewers.slice(0, 2) // Request max 2 reviewers + }); + + console.log(`Requested review from: ${availableReviewers.slice(0, 2).join(', ')}`); + } # Notify about PR status notify-status: @@ -297,45 +297,45 @@ jobs: if: always() steps: - - name: ๐Ÿ“Š Comment PR status - uses: actions/github-script@v7 - with: - script: | - const { owner, repo, number } = context.issue; - - const validationPassed = '${{ needs.run-tests.outputs.validation-passed }}' === 'true'; - const testsPassed = '${{ needs.run-tests.outputs.tests-passed }}' === 'true'; - - let statusMessage = '## ๐Ÿค– Automated PR Status\n\n'; - - // Validation status - statusMessage += `### ๐Ÿ” Code Validation\n`; - statusMessage += validationPassed ? - 'โœ… **Passed** - File naming and structure look good!\n\n' : - 'โŒ **Failed** - Please check file naming conventions and directory structure.\n\n'; - - // Test status - statusMessage += `### ๐Ÿงช Compilation Tests\n`; - statusMessage += testsPassed ? - 'โœ… **Passed** - All code compiles successfully!\n\n' : - 'โŒ **Failed** - Please fix compilation errors and try again.\n\n'; - - // Overall status - statusMessage += `### ๐Ÿ“‹ Overall Status\n`; - if (validationPassed && testsPassed) { - statusMessage += '๐ŸŽ‰ **Ready for Review** - Your PR has passed all automated checks!\n'; - statusMessage += '๐Ÿ‘ฅ Maintainers have been notified for review.\n\n'; - } else { - statusMessage += 'โš ๏ธ **Needs Work** - Please address the issues above.\n'; - statusMessage += '๐Ÿ’ก Push new commits to automatically re-run these checks.\n\n'; - } - - statusMessage += '---\n'; - statusMessage += '*This comment was generated automatically. Checks will re-run when you push new commits.*'; - - await github.rest.issues.createComment({ - owner, - repo, - issue_number: number, - body: statusMessage - }); \ No newline at end of file + - name: ๐Ÿ“Š Comment PR status + uses: actions/github-script@v7 + with: + script: | + const { owner, repo, number } = context.issue; + + const validationPassed = '${{ needs.run-tests.outputs.validation-passed }}' === 'true'; + const testsPassed = '${{ needs.run-tests.outputs.tests-passed }}' === 'true'; + + let statusMessage = '## ๐Ÿค– Automated PR Status\n\n'; + + // Validation status + statusMessage += `### ๐Ÿ” Code Validation\n`; + statusMessage += validationPassed ? + 'โœ… **Passed** - File naming and structure look good!\n\n' : + 'โŒ **Failed** - Please check file naming conventions and directory structure.\n\n'; + + // Test status + statusMessage += `### ๐Ÿงช Compilation Tests\n`; + statusMessage += testsPassed ? + 'โœ… **Passed** - All code compiles successfully!\n\n' : + 'โŒ **Failed** - Please fix compilation errors and try again.\n\n'; + + // Overall status + statusMessage += `### ๐Ÿ“‹ Overall Status\n`; + if (validationPassed && testsPassed) { + statusMessage += '๐ŸŽ‰ **Ready for Review** - Your PR has passed all automated checks!\n'; + statusMessage += '๐Ÿ‘ฅ Maintainers have been notified for review.\n\n'; + } else { + statusMessage += 'โš ๏ธ **Needs Work** - Please address the issues above.\n'; + statusMessage += '๐Ÿ’ก Push new commits to automatically re-run these checks.\n\n'; + } + + statusMessage += '---\n'; + statusMessage += '*This comment was generated automatically. Checks will re-run when you push new commits.*'; + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: number, + body: statusMessage + }); diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 91370912..04ec255e 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -2,7 +2,7 @@ name: ๐Ÿ” PR Validation on: pull_request: - branches: [ main ] + branches: [main] types: [opened, synchronize, reopened] jobs: @@ -10,164 +10,164 @@ jobs: runs-on: ubuntu-latest steps: - - name: ๐Ÿ“ฅ Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: ๐Ÿ” Get changed files - id: changed-files - uses: tj-actions/changed-files@v40 - with: - files: | - C/** - CPP/** - Java/** - Python/** - JavaScript/** - Go/** - Rust/** - Kotlin/** - Swift/** - PHP/** - Ruby/** - CSharp/** - Dart/** - Scala/** - - - name: ๐Ÿ“‹ Validate file naming conventions - if: steps.changed-files.outputs.any_changed == 'true' - run: | - echo "๐Ÿ” Checking file naming conventions..." - - invalid_files=() - - for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - echo "Checking: $file" - - # Extract filename and extension - filename=$(basename "$file") - dir=$(dirname "$file") - - # Check for proper naming conventions (Allow snake_case, camelCase, or PascalCase) - case "$file" in - *.c|*.cpp|*.py) - # Allow snake_case, camelCase, or PascalCase for C/C++/Python - if [[ ! "$filename" =~ ^[a-zA-Z0-9_]+\.[a-z]+$ ]]; then - invalid_files+=("$file: Use alphanumeric characters and underscores only (e.g., binary_search.cpp, maxRectangle.cpp)") + - name: ๐Ÿ“ฅ Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: ๐Ÿ” Get changed files + id: changed-files + uses: tj-actions/changed-files@v40 + with: + files: | + C/** + CPP/** + Java/** + Python/** + JavaScript/** + Go/** + Rust/** + Kotlin/** + Swift/** + PHP/** + Ruby/** + CSharp/** + Dart/** + Scala/** + + - name: ๐Ÿ“‹ Validate file naming conventions + if: steps.changed-files.outputs.any_changed == 'true' + run: | + echo "๐Ÿ” Checking file naming conventions..." + + invalid_files=() + + for file in ${{ steps.changed-files.outputs.all_changed_files }}; do + echo "Checking: $file" + + # Extract filename and extension + filename=$(basename "$file") + dir=$(dirname "$file") + + # Check for proper naming conventions (Allow snake_case, camelCase, or PascalCase) + case "$file" in + *.c|*.cpp|*.py) + # Allow snake_case, camelCase, or PascalCase for C/C++/Python + if [[ ! "$filename" =~ ^[a-zA-Z0-9_]+\.[a-z]+$ ]]; then + invalid_files+=("$file: Use alphanumeric characters and underscores only (e.g., binary_search.cpp, maxRectangle.cpp)") + fi + ;; + *.java) + # Should use PascalCase for Java classes + if [[ ! "$filename" =~ ^[A-Z][a-zA-Z0-9]*\.java$ ]]; then + invalid_files+=("$file: Java files should use PascalCase (e.g., BinarySearch.java, MaxRectangle.java)") + fi + ;; + *.js|*.ts|*.go|*.rs|*.kt|*.swift|*.php|*.rb|*.cs|*.dart|*.scala) + # Allow flexible naming for other languages + if [[ ! "$filename" =~ ^[a-zA-Z0-9_]+\.[a-z]+$ ]]; then + invalid_files+=("$file: Use alphanumeric characters and underscores only") + fi + ;; + esac + + # Check directory structure + if [[ "$file" =~ \.(c|cpp|java|py|js|ts|go|rs|kt|swift|php|rb|cs|dart|scala)$ ]]; then + if [[ ! "$dir" =~ (algorithms|data_structures|dynamic_programming|projects)/ ]]; then + invalid_files+=("$file: Should be in algorithms/, data_structures/, dynamic_programming/, or projects/ subdirectory") fi - ;; - *.java) - # Should use PascalCase for Java classes - if [[ ! "$filename" =~ ^[A-Z][a-zA-Z0-9]*\.java$ ]]; then - invalid_files+=("$file: Java files should use PascalCase (e.g., BinarySearch.java, MaxRectangle.java)") - fi - ;; - *.js|*.ts|*.go|*.rs|*.kt|*.swift|*.php|*.rb|*.cs|*.dart|*.scala) - # Allow flexible naming for other languages - if [[ ! "$filename" =~ ^[a-zA-Z0-9_]+\.[a-z]+$ ]]; then - invalid_files+=("$file: Use alphanumeric characters and underscores only") - fi - ;; - esac - - # Check directory structure - must contain a valid category - if [[ "$file" =~ \.(c|cpp|java|py|js|ts|go|rs|kt|swift|php|rb|cs|dart|scala)$ ]]; then - if [[ ! "$dir" =~ (algorithms|data_structures|dynamic_programming|projects) ]]; then - invalid_files+=("$file: Should be in algorithms/, data_structures/, dynamic_programming/, or projects/ subdirectory") - fi - fi - done - - if [ ${#invalid_files[@]} -gt 0 ]; then - echo "โŒ Found naming/structure violations:" - printf '%s\n' "${invalid_files[@]}" - exit 1 - else - echo "โœ… All files follow naming conventions!" - fi - - - name: ๐Ÿ“ Check for required documentation - if: steps.changed-files.outputs.any_changed == 'true' - run: | - echo "๐Ÿ“ Checking for documentation in code files..." - - missing_docs=() - - for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - if [[ "$file" =~ \.(c|cpp|java|py|js|ts|go|rs|kt|swift|php|rb|cs|dart|scala)$ ]]; then - echo "Checking documentation in: $file" - - # Check for basic documentation elements - if ! grep -q -i "algorithm\|description\|complexity" "$file" 2>/dev/null; then - missing_docs+=("$file: Missing algorithm description or complexity analysis") fi + done - # Check for comments - if ! grep -q -E "//|#|\*|--|