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

/**
 * ファイルの行数をカウントするスクリプト。
 * 物理行数と、空行・コメントを除いた実効行数を計測。
 * Rust (.rs), JavaScript (.js, .mjs), TypeScript (.ts) に対応。
 */

const WARN_FILE_LINES = 200;
const TARGET_EXTENSIONS = ['.js', '.mjs', '.ts', '.rs'];

function countLines(filePath) {
    const content = fs.readFileSync(filePath, 'utf-8');
    const lines = content.split('\n');
    let physicalLines = lines.length;
    let logicalLines = 0;
    let inComment = false;

    for (let line of lines) {
        const trimmed = line.trim();
        if (!trimmed) continue;

        // ブロックコメント対応
        if (inComment) {
            if (trimmed.includes('*/')) {
                inComment = false;
                // */ 以降にコードがあるか(簡易)
                if (trimmed.split('*/')[1].trim()) logicalLines++;
            }
            continue;
        }

        if (trimmed.startsWith('//')) continue;
        if (trimmed.startsWith('/*')) {
            if (!trimmed.includes('*/')) {
                inComment = true;
            } else {
                // /* */ が一行で完結し、かつ前後にコードがあるか(実運用上は稀だが考慮)
                const contentWithoutComment = trimmed.replace(/\/\*.*?\*\//g, '').trim();
                if (contentWithoutComment) logicalLines++;
            }
            continue;
        }

        logicalLines++;
    }

    console.log(`\nLines Info: ${filePath}`);
    console.log(`  Physical: ${physicalLines}`);
    console.log(`  Logical : ${logicalLines} ${logicalLines > WARN_FILE_LINES ? '[WARN!]' : '[OK]'}`);

    return { physicalLines, logicalLines };
}

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))) {
            countLines(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 {
                countLines(arg);
            }
        } else {
            console.error(`File or directory not found: ${arg}`);
        }
    });
} else {
    walkDir('.');
}