<!DOCTYPE html> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <html><head> <title>タイトル</title> <style> body { line-height: 1.5; } h1 { border-bottom: solid 4px; } h2 { border-bottom: solid 2px; } h3 { border-bottom: solid 1px; } table { border-collapse: collapse; margin: 0.5em; } code { font-weight: bold; color: purple; } pre { border: 1px solid black; padding: 0.3em; } </style>
印刷用の場合、改ページはこうする:
<p style="page-break-before: always;"> 2ページ目。
void printResult(Stream out, String result) {
out.writeLine("result:"+result);
}
void printStat(Stream out, int stat) {
out.writeLine("stat:"+stat);
}
void printInfo(Stream strm, String info) {
strm.writeLine("info:"+info); // お前、ここはoutやろ。
}
ここでは、ある変数に代入される値が通る一連の処理 (または関数の引数および返り値が通る処理) を、 その変数の「データパス」と定義する。
問. 以下の例で変数 line
に着目する。
private BufferedReader fp; public String get() { String line = fp.readLine(); int i = line.indexOf(' '); return line.substring(0, i); }
グラフ化するとこうなる:
グラフ中の赤線部分が
変数 line
のデータパスである:
fp.readLine()
→ line
→ #this:indexOf()
→ #arg1:substring()
これは、変数 line
になにが代入され、
それがどのように使われるかを示している。
private BufferedReader fp; public String get() { String line = fp.readLine(); int i = line.indexOf(' '); return line.substring(0, i); } public void show() { String name = get(); System.out.println(name+"!!"); }
get()
中の変数 line
(の処理結果) は、
いまや show()
中では name
となっていることに着目。
これをグラフ化するとこうなる:
最終的に、
変数 line
のデータパスは:
fp.readLine()
→ line
→ #this:indexOf()
→ #arg1:substring()
→ assign:name
→ L:+
→ #arg0:println()
line
の使われ方」を表すことになる。
単純化のため、いまのところパスの分岐は考慮しない。
以上のようなデータパスを、 プログラム中のすべての変数に対して (interprocedural で) 抽出し、 変数名との相関を学習する。 ここでは「データパスを与えると、変数名を予測する」ようなモデルを学習する。
つまり、以下のようなデータパスが出てきたら:
fp.readLine()
→ ???
→ #this:indexOf()
→ #arg1:substring()
→ assign:name
→ L:+
→ #arg0:println()
ここでの ???
= line
ではないか、
と予測するということである。もしここで line
以外の名前が使われていたら、
その変数名は (この使われ方に対しては) 一貫していない、ということになる。
以上の技術を、巨大な Java コードベースに対して行えば (これがチョー大変!!) 完了。
「コード中の変数名を予測・提案する」という研究は以前からある [1] が、 本研究が新しいのは: