第 3 章 プログラム変更の特定手法 17
3.5 プログラム要素の移動の特定
また,編集操作によるプログラム要素の追加の特定は,時刻t2のスナップショッ トSt2に存在したプログラム要素を構成するすべての文字が編集操作によって挿入 された文字かどうかで判断する.時刻t2のスナップショットSt2に存在しているプ ログラム要素pが時刻t1から時刻t2の間に行われた編集操作ops(t1,t2)によっ て追加されたかどうかを判別するアルゴリズムをアルゴリズム 5に示す.
入力は追加されたかどうかを判別する対象であるSt2に存在するプログラム要 素(entity)と,アルゴリズム 4と同様にoperationsとsourcef ileを持つ.また 同様にentityはstart, endをもつ.出力は判定結果(result)として,entityが 編集操作によって追加されたプログラム要素であればtrueの値を,そうでなけれ ばfalseの値を返す.
判定の手順としてはまず,sourcef ileに存在するすべての文字に対してその文 字が挿入された文字ではないことを表す値を判定用変数(isInserted)に記録し ておく.また,operationsに存在するすべての編集操作の挿入文字に対して,そ の文字が挿入された文字であることを表す値をisInsertedに記録しておく(1行 目〜11行目).こうすることで,編集操作をすべて適用した後の時刻t2における
sourcef ileから,そのsourcef ileを構成するそれぞれの文字が時刻t1〜時刻t2の
間に行われた編集操作によって挿入された文字かどうかを判別できるようになる.
次に,sourcef ileに対してoperationsに存在するすべての編集操作を適用する.
ソースファイルに対する編集操作の適用は3.2 節に示したとおりである.このと き,編集操作の適用によって挿入された文字は再び削除されない限りsourcef ile に残る(12行目〜14行目).
最後に,sourcef ileのentityの範囲に存在するすべての文字について挿入され た文字かどうかを調べ,その範囲にあるすべての文字が編集操作によって挿入さ れた文字であった場合はentityは追加されたと判断してresultにtrueを入れて 返し,挿入されていない文字(St1のsourcef ileに元から存在していた文字)が一 つでも存在する場合は追加されていないと判断してresultにfalseを入れて返す
(15行目〜21行目).
3.5. プログラム要素の移動の特定 35
Algorithm 5: 編集操作によるプログラム要素の追加の特定 Input: operations
Input: entity Input: sourcefile Output: result
1 fori = 0 to |sourcefile|-1 do
2 c← sourcefile[i];
3 c.isInserted← false;
4 end
5 fori = 0 to |operations|-1 do
6 op← operations[i];
7 forj = 0 to |op.insertedText|-1 do
8 c← op.insertedText[i];
9 c.isInserted← true;
10 end
11 end
12 fori = 0 to |operations|-1 do
13 adopt(sourcefile, operations[i]);
14 end
15 result← true;
16 fori = entity.start to entity.end do
17 c← sourcefile[i];
18 if c.isInserted = false then
19 result← false
20 end
21 end
Algorithm 6: MoveChange(Ds, As)
1 DCs← Dsに含まれるすべてのDC;
2 ACs← Asに含まれるすべてのAC;
3 foreach d∈DCs,a∈ACsdo
4 if d.endingTime < a.startingTime ∧d.text = a.text ∧
5 d < k < aとなる AC であるkが存在しない then
6 Cd← dの削除対象であるクラス;
7 Ca ←aの追加対象であるクラス;
8 if Cd.fileName 6= Ca.fileName ∨ Cd.name 6= Ca.name then
9 dをMCに置き換え;
10 aをなかったものとする;
11 end
12 end
13 end
14 DF s ← Dsに含まれるすべてのDF;
15 AF s← Asに含まれるすべてのAF;
16 foreach d∈DF s,a∈AF sdo
17 if d.endingTime < a.startingTime ∧d.text = a.text ∧
18 d < k < aとなる AF であるkが存在しない then
19 Fd← dの削除対象であるフィールド;
20 Fa← aの追加対象であるフィールド;
21 if Fd.fileName 6=Fa.fileName ∨ Fd.className 6= Fa.className then
22 dをMFに置き換え;
23 aをなかったものとする;
24 end
25 end
26 end
27 DM s ← Dsに含まれるすべてのDM;
28 AM s← Asに含まれるすべてのAM;
29 foreach d∈DM s, a∈AM sdo
30 if d.endingTime < a.startingTime ∧d.text = a.text ∧
31 d < k < aとなる AM であるkが存在しない then
32 Fd← dの削除対象であるメソッド;
33 Fa← aの追加対象であるメソッド;
34 if Md.fileName 6=Ma.fileName ∨ Md.className 6=Ma.className then
35 dをMMに置き換え;
36 aをなかったものとする;
37 end
38 end
39 end
3.5. プログラム要素の移動の特定 37 含んだプログラム変更の集合Asから,プログラム要素の移動に関する変更(MC, MF,MM)を特定する.
アルゴリズム 6において,クラスの移動の特定が1〜13行目,フィールドの移 動の特定が14〜26行目,メソッドの移動の特定が27〜39行目となっている.ク ラス,フィールド,メソッドの各プログラム要素の移動の特定手順は特定対象が異 なる点を除いてすべて同様の手順となるため,本節ではクラスの移動に関するプ ログラム変更(MC)に焦点を当てて説明する.
本手法ではプログラム要素の移動を同じ内容のプログラム要素が削除,追加の 順番で行われたものと捉えている.そのためクラスの移動の特定では,以下の条 件を満たすクラスの削除(DC)とクラスの追加(AC)のペアをクラスの移動と みなすことで実現している.
1. DCが行われた後にACが行われている
2. ペアとなるDCとACの間に他のACが行われていない
3. DCの対象となったクラスとACの対象となったクラスのテキスト表現が 同じ
4. DCの対象となったクラスとACの対象となったクラスの存在していたクラ スかファイルが異なる
条件4ではDCとACにおいて,お互いのファイルかクラスのどちらかが異な る場合に移動と判断している.この判断について詳しく説明すると,DCとAC でファイルとクラスが両方異なる場合は,別のファイルに存在する別のクラスへ DCとACで対象としているクラスの移動が行われたと判断できる.またファイ ルが同じでクラスが異なる場合は,同じファイル上にそれぞれ存在する,トップク ラスや内部クラスの間で移動が行われたものと判断できる.しかし仮に,ファイ ルとクラスの両方が同じ場合は,同じクラス内でのプログラム要素のソースファ イル上の順序の入れ替えのために行われたものと判断できるため,それらはクラ スの移動と判断しない.最後にファイルが異なりクラスが同じである場合につい てだが,Javaにおいて異なるファイルに完全限定名が同じであるクラスが複数存 在する場合はコンパイルエラーとなるが,本手法では各ソースファイルの構文解 析のみを行いコンパイルエラーを考慮しないため,このような場合においてもク ラスの移動が行われたものと判断する.