/// <summary>
/// 単一クラス内で、イベントメソッド rootName を起点としたメソッド呼び出し階層を DFS で展開。
/// 1イベント(rootName)ごとに、同じメソッド名は1回だけ子展開する。
/// 2回目以降の呼び出しは「(再利用)」として行だけ出力し、子メソッドには潜らない。
/// 階層表示 = 全角スペース×深さ + (深さ>0なら '∟')+ メソッド名(+(再利用)/(再帰))。
/// </summary>
private static void TraverseMethodTreeRows(
string className,
string rootName,
string methodName,
int depth,
Dictionary<string, HashSet<string>> adj,
Dictionary<string, int> lineMap,
HashSet<string> path,
HashSet<string> visitedRoot,
List<object[]> outRows)
{
string key = methodName;
// ① 再帰ループ検出(現在のパス上に既に存在する)
if (path.Contains(key))
{
string baseName = methodName + " (再帰)";
string lnLoopStr = "";
int lnLoop;
if (lineMap.TryGetValue(methodName, out lnLoop))
{
lnLoopStr = lnLoop.ToString();
}
string indentR = new string(' ', depth); // 全角スペース
string displayR = (depth > 0)
? indentR + "∟" + baseName
: baseName;
outRows.Add(new object[]
{
className, // 0
rootName, // 1
depth.ToString(), // 2
displayR, // 3 階層表示
baseName, // 4 メソッド名
lnLoopStr // 5 行番号
});
return;
}
// ② このイベント(rootName)配下で既に子展開済みかどうか
if (visitedRoot.Contains(methodName))
{
// → 行は出すが、子メソッドには潜らない(再利用マークのみ)
string lnStr2 = "";
int ln2;
if (lineMap.TryGetValue(methodName, out ln2))
{
lnStr2 = ln2.ToString();
}
string dispName = methodName + " (再利用)";
string indent2 = new string(' ', depth); // 全角スペース
string display2 = (depth > 0)
? indent2 + "∟" + dispName
: dispName;
outRows.Add(new object[]
{
className, // 0
rootName, // 1
depth.ToString(), // 2
display2, // 3 階層表示
dispName, // 4 メソッド名(再利用)
lnStr2 // 5 行番号
});
return;
}
// ③ 初回出現:今回出力+子展開対象にする
visitedRoot.Add(methodName);
path.Add(key);
string lnStr = "";
int ln;
if (lineMap.TryGetValue(methodName, out ln))
{
lnStr = ln.ToString();
}
string indent = new string(' ', depth); // 全角スペース
string display = (depth > 0)
? indent + "∟" + methodName
: methodName;
outRows.Add(new object[]
{
className, // 0
rootName, // 1
depth.ToString(), // 2
display, // 3 階層表示
methodName, // 4 メソッド名
lnStr // 5 行番号
});
// ④ 子メソッドへ(初回のみ)
HashSet<string> children;
if (adj.TryGetValue(methodName, out children))
{
List<string> list = new List<string>(children);
list.Sort((a, b) =>
{
int la = lineMap.ContainsKey(a) ? lineMap[a] : int.MaxValue;
int lb = lineMap.ContainsKey(b) ? lineMap[b] : int.MaxValue;
if (la != lb) return la.CompareTo(lb);
return string.Compare(a, b, StringComparison.Ordinal);
});
foreach (string child in list)
{
TraverseMethodTreeRows(
className,
rootName,
child,
depth + 1,
adj,
lineMap,
path,
visitedRoot,
outRows);
}
}
path.Remove(key);
}
最近のコメント