<!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] が、 本研究が新しいのは: