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('.');
}