Newer
Older
TelosDB / scripts / analyze_nesting.js
@楽曲作りまくりおじさん 楽曲作りまくりおじさん 6 days ago 3 KB chore: comprehensive project restructuring and cleanup
import fs from 'fs';
import path from 'path';

/**
 * コードのネスト深度を解析するスクリプト。
 * Rust (.rs), JavaScript (.js, .mjs), TypeScript (.ts) に対応。
 */

const MAX_NESTING = 4;
const TARGET_EXTENSIONS = ['.js', '.mjs', '.ts', '.rs'];

function analyzeNesting(filePath) {
    const content = fs.readFileSync(filePath, 'utf-8');
    const lines = content.split('\n');
    let currentLevel = 0;
    let maxLevelInFile = 0;
    let inComment = false;
    let inString = false;
    let stringChar = '';

    console.log(`\nAnalyzing: ${filePath}`);

    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        let lineLevel = currentLevel;

        for (let j = 0; j < line.length; j++) {
            const char = line[j];
            const nextChar = line[j + 1];

            // 文字列中
            if (inString) {
                if (char === stringChar && line[j - 1] !== '\\') {
                    inString = false;
                }
                continue;
            }

            // コメント(ブロック)
            if (inComment) {
                if (char === '*' && nextChar === '/') {
                    inComment = false;
                    j++;
                }
                continue;
            }

            // 新しい文字列の開始
            if (char === '"' || char === "'" || char === '`') {
                inString = true;
                stringChar = char;
                continue;
            }

            // コメントの開始
            if (char === '/' && nextChar === '/') {
                break; // 行末までコメント
            }
            if (char === '/' && nextChar === '*') {
                inComment = true;
                j++;
                continue;
            }

            // ネスト
            if (char === '{') {
                currentLevel++;
                if (currentLevel > maxLevelInFile) maxLevelInFile = currentLevel;
            } else if (char === '}') {
                currentLevel--;
            }
        }

        if (lineLevel >= MAX_NESTING || currentLevel >= MAX_NESTING) {
            console.log(`  [WARN] Line ${i + 1} (Level ${Math.max(lineLevel, currentLevel)}): ${line.trim().substring(0, 50)}...`);
        }
    }

    if (maxLevelInFile >= MAX_NESTING) {
        console.log(`  [RESULT] Max Nesting Level: ${maxLevelInFile} (REFACTOR NEEDED)`);
    } else {
        console.log(`  [RESULT] Max Nesting Level: ${maxLevelInFile} (OK)`);
    }
    return maxLevelInFile;
}

function walkDir(dir) {
    const files = fs.readdirSync(dir);
    files.forEach(file => {
        const fullPath = path.join(dir, file);
        if (fs.statSync(fullPath).isDirectory()) {
            if (file !== 'node_modules' && file !== 'target' && file !== '.git') {
                walkDir(fullPath);
            }
        } else if (TARGET_EXTENSIONS.includes(path.extname(file))) {
            analyzeNesting(fullPath);
        }
    });
}

const args = process.argv.slice(2);
if (args.length > 0) {
    args.forEach(arg => {
        if (fs.existsSync(arg)) {
            if (fs.statSync(arg).isDirectory()) {
                walkDir(arg);
            } else {
                analyzeNesting(arg);
            }
        } else {
            console.error(`File or directory not found: ${arg}`);
        }
    });
} else {
    walkDir('.');
}