プログラム変更支援を目的とした コードクローン情報付加ツール

43
2004/3/9 情情情情情情情情情情 1 情情情情情情情情情情情情情情情 情情情情情情情情情情情情情情 佐佐佐佐⁽ ¹⁾ 佐佐佐佐⁽ ²⁾ 佐佐佐佐⁽ ³⁾ 佐佐佐佐⁽ ²⁾ 佐佐佐佐⁽ ²⁾ ⁽ ¹⁾ 情情情情情情 情情情情情情情情 ⁽ ²⁾ 情情情情情情 情情情情情情情情 ⁽ ³⁾ 情情情情情情 情情 情情情情

Upload: caleb-fleming

Post on 30-Dec-2015

35 views

Category:

Documents


0 download

DESCRIPTION

プログラム変更支援を目的とした コードクローン情報付加ツール. 佐々木亨 ⁽¹⁾ 肥後芳樹 ⁽²⁾ 神谷年洋 ⁽³⁾ 楠本真二 ⁽²⁾ 井上克郎 ⁽²⁾ ⁽¹⁾ 大阪大学基礎工学部情報科学科 ⁽²⁾ 大阪大学大学院情報科学研究科 ⁽³⁾ 科学技術振興機構 さきがけ. 研究の背景 . コードクローンとは ソースコード中に存在するコード片で、同形のコード片が他に存在するもの コピー&ペーストによるプログラム再利用などで生じる ソフトウェア保守を困難にする あるコード片にバグがあると、そのコードクローン全てについて修正の検討をしなければならない - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 1

プログラム変更支援を目的としたコードクローン情報付加ツール

佐々木亨⁽ ¹⁾ 肥後芳樹⁽ ²⁾ 神谷年洋⁽ ³⁾ 楠本真二⁽ ²⁾ 井上克郎⁽ ²⁾

                             ⁽ ¹⁾ 大阪大学基礎工学部情報科学科                             ⁽ ²⁾ 大阪大学大学院情報科学研究科                             ⁽ ³⁾ 科学技術振興機構 さきがけ

Page 2: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 2

研究の背景  コードクローンとは

ソースコード中に存在するコード片で、同形のコード片が他に存在するもの

コピー&ペーストによるプログラム再利用などで生じる

ソフトウェア保守を困難にする あるコード片にバグがあると、そのコードクローン

全てについて修正の検討をしなければならない 機能を追加する場合も同様のことが言える

Page 3: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 3

クローンクラス クローンクラス 同形のコードクローンの

集合 例 C1

C5

C4

C3

C2

クローンクラス1{C1,C4,C5}

クローンクラス 2{C2,C3}

Page 4: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 4

コードクローン検出ツール CCFinder

ソースコードを字句解析してトークンの列に分解してから、トークン単位で直接比較することによりクローンを検出

数百万行規模のシステムにも実用時間で解析可能

実用的に意味のないクローンを検出しない

さまざまな企業のソフトウェアにも適用している

Page 5: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 5

CCFinder の出力#begin{file description}0 1475 3429 /home/test/test1.c1 3213 9669 /home/test/test2.c2 3584 11420 /home/test/test3.c

        :#end{file description}

#begin{clone}#begin{set}0 1250,3,2811 1258,17,28530 1260,3,2861 1268,13,29031 2962,3,8913 2970,10,8955#end{set}#begin{set}1 49,1,66 55,41,1202 62,1,93 68,39,1472 75,1,159   81,37,213#end{set}

::

#end{clone}

解析対象のファイル群の情報

クローンクラス情報

ファイルの ID ・ファイル行数・ファイルパスなどからなる

クローンクラスID1 のファイルの 49 行目から 55 行目ID2 のファイルの 62 行目から 68 行目ID2 のファイルの 75 行目から 81 行目

Page 6: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 6

クローン情報を用いてソースコードを修正する際の問題点 コードクローンに対する機能追加・修正中

にクローン情報とソースコードで行番号のずれが生じる

対処法 行番号のずれを意識しながら作業する

効率が悪い 修正箇所を間違える可能性

Page 7: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 7

研究の目的 コードクローンに対する機能追加・修正中

に行番号のずれを意識せずに作業する             コードクローンの位置情報を、コメントと

してソースコードに埋め込む手法の提案とツールの実装を行う

Page 8: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 8

コードクローン情報の追加(コメントの利用)

基本方針 クローンクラスごとに割り付けた ID を利用する クローンクラスに含まれる全行にコメントを追

加する コメントの形式

クローンクラスの先頭行は“ //@$ クローンクラスの ID@”

先頭行以外は“ //@ クローンクラスの ID@” ある行が 2 つ以上のクローンクラスに属している場

合はコンマで区切る

Page 9: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 9

コメント追加例クローンクラス 1#begin{set} 1     30,1,45     33,1,521     40,1,58     43,1,651     83,1,102    86,1,109#end{set}

クローンクラス 2#begin{set} 1     30,1,45     34,1,551     83,1,102    87,1,112#end{set}

30: while(a>10){31: b=b+a; 32: a=a+1;33: }34: sum = a;

40: while(c>10){41: d=d+c;42: c=c+1;43: }

83: while(e>10){84: f=f+e;85: e=e+1;86: }87: sum = e;

//@$1@//@1@ //@1@//@1@

//@$1@//@1@//@1@//@1@

//@$1@//@1@//@1@//@1@

//@$1@,@$2@//@1@,@2@//@1@,@2@//@1@,@2@//@2@

//@$1@//@1@//@1@//@1@

//@$1@,@$2@//@1@,@2@//@1@,@2@//@1@,@2@//@2@

Page 10: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 10

デバッグへの利用手順1.あるバグを発見する

2.ソースコードにクローン情報の コメントを付加する

3.バグを修正する4.修正部分のコメントを調べる

5.コメント中のクローンクラスの ID を利用してクローンクラスの 先頭行を見つける

6.他の修正箇所を見つける7.同様の修正を行う8.不要になったコメントを除去する

while(a > 10){ b=b+a; a=a+1; }Sum = a; : while(c > 10){ d=d+c; c=c+1; } :

while(e > 10){ f=f+e; e=e+1; }Sum = e;

//@$1@,@$2@

//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@

//@$1@ //@1@ //@1@ //@1@

//@$1@,@$2@

//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@

while(a < 10){ b=b+a; a=a+1; }Sum = a; : while(c > 10){ d=d+c; c=c+1; } :

while(e > 10){ f=f+e; e=e+1; }Sum = e;

//@$1@,@$2@

//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@

//@$1@ //@1@ //@1@ //@1@

//@$1@,@$2@

//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@

while(a < 10){ b=b+a; a=a+1; }Sum = a; : while(c < 10){ d=d+c; c=c+1; } :

while(e < 10){ f=f+e; e=e+1; }Sum = e;

//@$1@,@$2@

//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@

//@$1@ //@1@ //@1@ //@1@

//@$1@,@$2@

//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@

while(a < 10){ b=b+a; a=a+1; }Sum = a; : while(c < 10){ d=d+c; c=c+1; } :

while(e < 10){ f=f+e; e=e+1; }Sum = e;

while 文の条件が間違っている

Page 11: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 11

ツールの機能 コメント追加機能

コメントにはクローンクラスの ID を利用 コメントはクローンクラスに含まれる全行に追加 追加はオリジナルファイルに行わず、編集用の一時的なファイルに行

う クローンクラス検索機能

クローンクラスを指定し、そのコメントがあるファイル情報等を検索・表示

一時ファイル編集機能 コメント追加後、ファイル編集のためにファイルを選択して開く

コメント除去機能 不要となったコメントを、クローンクラスの ID を指定して除去する すべてのコメントを一括して除去する

一時ファイル書き戻し機能 編集用の一時的なファイルの変更をオリジナルファイルに反映させる

Page 12: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 12

適用実験 日本語入力システム「かんな」 (http://canna.so

urceforge.jp) のバージョン 3.6 と 3.6p1 の間でのセキュリティ問題の修正に対して擬似的なデバッグを行うことで適用した ソースコードは C 言語で記述、 92 ファイル、約 9 万

行 この修正は、バッファのオーバーフローを調べる処理

の追加で、全20箇所にほぼ同じ修正を行っている 具体的な追加コードは if(Request.type7.datalen!=SIZEOFSHORT*3) return (-1);     等

実行環境  FreeBSD   Pentium4 1.5GHz 512MB

Page 13: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 13

具体例(修正前の「かんな」ソースコード)

下図の 2405 行目の直前にオーバーフローの検査処理を追加する

2399 static 2400 ProcWideReq7(buf) 2401 BYTE *buf ; 2402 { 2403 ir_debug( Dmsg(10, "ProcWideReq7 start!!\n")); 2404  2405 buf += HEADER_SIZE; Request.type7.context = S2TOS(buf); 2406 buf += SIZEOFSHORT; Request.type7.number = S2TOS(buf); 2407 buf += SIZEOFSHORT; Request.type7.yomilen = (short)S2TOS(buf); 2408 ir_debug( Dmsg(10, "req->context =%d\n", Request.type7.context)); 2409 ir_debug( Dmsg(10, "req->number =%d\n", Request.type7.number)); 2410 ir_debug( Dmsg(10, "req->yomilen =%d\n", Request.type7.yomilen)); 2411  2412 return( 0 ) ; 2413   }

Page 14: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 14

#begin{set} 0.91     2367,1,7452     2375,24,74830.91     2383,1,7519     2391,24,75500.91     2399,1,7586     2407,24,76170.91     2415,1,7657     2423,24,76880.91     2433,1,7739     2441,24,7770         :#end{set}#begin{set} 0.91     2376,5,7488     2381,2,75180.91     2392,5,7555     2397,2,75850.91     2408,5,7626     2413,2,76560.91     2426,5,7708     2431,2,77380.91     2444,5,7790     2449,2,7820       :#end{set}#begin{set} 0.91     2399,1,7586     2407,50,76190.91     2587,1,8410     2595,51,8443      :#end{set}

#begin{set} 0.91     2367,1,7452     2375,24,74830.91     2383,1,7519     2391,24,75500.91     2399,1,7586     2407,24,76170.91     2415,1,7657     2423,24,76880.91     2433,1,7739     2441,24,7770         :#end{set}#begin{set} 0.91     2376,5,7488     2381,2,75180.91     2392,5,7555     2397,2,75850.91     2408,5,7626     2413,2,76560.91     2426,5,7708     2431,2,77380.91     2444,5,7790     2449,2,7820       :#end{set}#begin{set} 0.91     2399,1,7586     2407,50,76190.91     2587,1,8410     2595,51,8443      :#end{set}

2405 行目に追加したためソースコードとコードクローン情報の間で行番号が 2行ずつずれている

ツールを利用しない場合  - コードクローン位置情報のずれ

2420行目に同様の 2行分の修正を行ったとする

2420行目に同様の 2行分の修正を行ったとする

赤い部分のずれは 2 行青い部分のずれは 4 行

この修正例において全部で20箇所 101行もの処理を追

この修正例において全部で20箇所 101行もの処理を追

行番号の増減を意識しながら作業するのは困難

#begin{set} 0.91     2367,1,7452     2375,24,74830.91     2383,1,7519     2391,24,75500.91     2399,1,7586     2407,24,76170.91     2415,1,7657     2423,24,76880.91     2433,1,7739     2441,24,7770         :#end{set}#begin{set} 0.91     2376,5,7488     2381,2,75180.91     2392,5,7555     2397,2,75850.91     2408,5,7626     2413,2,76560.91     2426,5,7708     2431,2,77380.91     2444,5,7790     2449,2,7820       :#end{set}#begin{set} 0.91     2399,1,7586     2407,50,76190.91     2587,1,8410     2595,51,8443      :#end{set}

「かんな」バージョン 3.6 のコードクローン情報

Page 15: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 15

2399 static //@$1311@,@$1318@2400 ProcWideReq7(buf) //@1311@,@1318@2401 BYTE *buf ; //@1311@,@1318@2402 { //@1311@,@1318@2403   ir_debug( Dmsg(10, "ProcWideReq7 start!!\n")); //@1311@,@1318@2404 //@1311@,@1318@2405 if(Request.type7.datalen!=SIZEOFSHORT*3)2406 return (-1);2407 buf += HEADER_SIZE; Request.type7.context = S2TOS(buf); //@1311@,@1318@2408 buf += SIZEOFSHORT; Request.type7.number = S2TOS(buf); //@1311@,@1318@2409 buf += SIZEOFSHORT; Request.type7.yomilen = (short)S2TOS(buf); //@1311@,@13

18@2410   ir_debug( Dmsg(10, "req->context =%d\n", Request.type7.context)); //@$1317

@2411 ir_debug( Dmsg(10, “req->number =%d\n", Request.type7.number)); //@1317@2412 ir_debug( Dmsg(10, "req->yomilen =%d\n", Request.type7.yomilen)); //@1317@2413   //@1317@2414   return( 0 ) ; //@1317@2415 } //@1317@

追加処理

この部分のコメントを見ればクローンクラス 1311 と 1318 に関して同様の修正の検討をすればいいとわかる(実際に 1311 に対して修正を行っていた)

行番号のずれを意識することなく作業することができる

ツールを利用する場合 - コメント付加後に追加

コメント追加 約 5 秒コメント全消去 約 3 秒一時ファイル書き戻し

約 3 秒

クローンクラス検索 1 秒未満

Page 16: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 16

まとめと今後の課題 まとめ

プログラム変更作業を支援するための、コードクローン情報付加手法の提案、ツールの試作をし、「かんな」のバグ修正作業に適用した

今後の課題 実際のソフトウェア開発・保守現場での評価

Page 17: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 17

終わり

Page 18: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 18

これ以降は発表に入れないスライド

Page 19: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 19

定義 完全性

修正が必要な箇所のうち実際に検出された割合 効率性

検出されたうち実際に修正箇所である割合 検出された

ある修正箇所を特定したときに、その箇所にあるコメント内のクローンクラス ID をたどってたどり着ける箇所

Page 20: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 20

評価内容//CL1

//CL1,2

//CL2

//CL3

//CL2,3

総修正箇所は 4 箇所検出された箇所は 5 箇所

検出された修正箇所は 3 箇所完全性  (4 箇所中 3 箇所 )   75%効率性  (5 箇所中 3 箇所 )   60%

Page 21: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 21

評価結果grep 本ツール

総修正箇所 20 箇所 20 箇所

検出された箇所 61 箇所 15 箇所

検出された箇所中の修正箇所

19 箇所 15 箇所

完全性 95% 75%

効率性 34% 100%

f値 0.5 0.86

f 値を見ると、本ツールは grep より有効である

効率性完全性効率性完全性2

値=f

Page 22: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 22

補足実験 CCFinder の最小一致トークン数を変化させた

トークン数 完全性 効率性 コメント数50 13% 100% 0.5個40 17% 100% 1.0個30 75% 100% 4.2個20 90% 100% 11個10 100% 5%未満 30個

• コメント数 : 1修正箇所中のコメント数

Page 23: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 23

grep で検出されなかった唯一のクローン

staticProcWideReq1(buf)BYTE *buf ;/* ARGSUSED */{ ir_debug( Dmsg(10, "ProcWideReq1 start!!\n") ); return( 0 ) ;}

・この部分を検索キーとすれば grep でも検出されるが、これだと他にも数多く検出される ( 135 行一致する  f 値は 0.26 )

このように grep などのコード片を指定して検索する場合は利用者の能力に

よって検索結果に差が出るしかし、

本ツールではその必要がないためその心配がない

Page 24: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 24

1311 は修正箇所で 1318 は修正しなくてよかったのはなぜ?

クローンクラス 1311

クローンクラス 1312 クローンクラス 1318

実際には 1312 に対して修正が行われていたつまり、 1311 に修正を行ったというより、1312 に対して修正を行っていた

Page 25: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 25

編集用の一時ファイルの作成方法 ディレクトリ Append_Comment_Files 中にディレクトリファイル

階層を実現する  1 /Canna36/cmd/wtoc/wtoc.c  2 /Canna36/dic/ideo/pubdic/pod.c  3 /Canna36/doc/man/guide/tex/cannaindex.c  4 /Canna36/misc/is.c  5 /Canna36/sample/sample.c

  1’ /Append_Comment_Files/Canna36/cmd/wtoc/wtoc.c  2’ /Append_Comment_Files/Canna36/dic/ideo/pubdic/pod.c  3’ /Append_Comment_Files/Canna36/man/guide/tex/cannaindex.c  4’ /Append_Comment_Files/Canna36/misc/is.c  5’ /Append_Comment_Files/Canna36/sample/sample.c

Page 26: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 26

既存のコードクローン検出手法(1/2)

Baker の手法 行単位でソースコードを比較してコードクローンを検

出Baxter らの手法

C 言語のソースファイルを入力,構文解析して,解析木 ( の部分木 ) を比較する

[Baker1995] B. S. Baker: “On finding Duplication and Near-Duplication in Large Software System,” Proc. Second IEEE Working Conf. Reverse Eng., pp. 86-95, Tronto, Canada (Jul., 1995).[Baxter1998] I. D. Baxter, A. Yahin, L. Moura, M. Sant’Anna, and L. Bier: “Clone Detection Using Abstract Syntax Trees,” Proc. of ICSM ’98, pp. 368-377, Bethesda, Maryland (Nov., 1998).

Page 27: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 27

既存のコードクローン検出手法(2/2)

Merlo らの手法 手続き(メソッドや関数)の特徴メトリクスを

比較して,計測値が似ていればコードクローンであると判定する

[Balazinska1999] M. Balazinska, E. Merlo, M. Dagenais, B. Lague, and K.A. Kontogiannis, "Measuring Clone Based Reengineering Opportunities", Proc. 6th IEEE Int'l Symposium on Software Metrics (METRICS '99), pp. 292-303, Boca Raton, Florida, Nov. 1999.

Page 28: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 28

CCFinder: コードクローン検出ツール

ソースコードを字句解析してトークンの列に直してからコードクローン検出を行う (浅い)文法知識に基づいたソースコード変形

クラススコープや名前空間による複雑な名前の正規化を行う

初期化テーブルを取り除く モジュールの区切りを認識する

言語依存部分を取り替えることで,さまざまなプログラミング言語に対応

Page 29: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 29

コードクローン検出手順(1) ソースコードを入力し,トークンの列にす

る(2) 変形ルールにより,トークン列を変形する(3) パラメータ置換を行う(4) マッチングアルゴリズムによりコードクロ

ーンを検出する(5) コードクローンの位置 ( ファイル,行 , カ

ラム ) を出力する

Page 30: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 30

1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. }10. static void goo(String [] a) throws RESyntaxException {11. RE exp = new RE("[0-9,]+");12. int sum = 0;13. for (int i = 0; i < a.length; ++i)14. if (exp.match(a[i]))15. sum += parseNumber(exp.getParen(0));16. System.out.println("sum = " + sum);17. }

例題ソースコード

Page 31: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 31

static void foo ( ) {

String a [ ] = new String [ ] { "123,400" , "abc" , "orange 100" } ;

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

sum += pat . getParen 0 ;

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

Sample . parseNumber ( ) )

if pat . match a [ i ]( ) )

org . apache . regexp . RE pat = new org . apache . regexp . RE ( "[0-9,]+" ) ;

static void goo ( ) {String a [ ]

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

if exp . match a [ i ]( ) )

exp = new RE ( "[0-9,]+" ) ;

(

RE

sum += exp . getParen 0 ;parseNumber ( ) )(

(

(

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

ステップ (1):ソースコードを入力し,トークンの列にする

Page 32: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 32

static void foo ( ) {

String a [ ] = new String [ ] { "123,400" , "abc" , "orange 100" } ;

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

sum += pat . getParen 0 ;

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

Sample . parseNumber ( ) )

if pat . match a [ i ]( ) )

org . apache . regexp . RE pat = new org . apache . regexp . RE ( "[0-9,]+" ) ;

static void goo ( ) {String a [ ]

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

if exp . match a [ i ]( ) )

exp = new RE ( "[0-9,]+" ) ;

(

RE

sum += exp . getParen 0 ;parseNumber ( ) )(

(

(

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

static void foo ( ) {

String a [ ] = new String [ ] { $u } ;

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

sum += pat . getParen 0 ;

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

Sample . parseNumber ( ) )

if pat . match a [ i ]( ) )

RE pat = new RE ( "[0-9,]+" ) ;

static void goo ( ) {String a [ ]

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

if exp . match a [ i ]( ) )

exp = new RE ( "[0-9,]+" ) ;

(

RE

sum += exp . getParen 0 ;parseNumber ( ) )(

(

(

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

$p .

ステップ (2):変形ルールにより,トークン列を変形する

Page 33: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 33

static void foo ( ) {

String a [ ] = new String [ ] { $u } ;

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

sum += pat . getParen 0 ;

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

Sample . parseNumber ( ) )

if pat . match a [ i ]( ) )

RE pat = new RE ( "[0-9,]+" ) ;

static void goo ( ) {String a [ ]

int sum = 0 ;

for ( int i = 0 ; i < a . length ; ++ i )

System . out . println ( "sum = " + sum ) ;

}

throws RESyntaxException

if exp . match a [ i ]( ) )

exp = new RE ( "[0-9,]+" ) ;

(

RE

sum += exp . getParen 0 ;parseNumber ( ) )(

(

(

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

$p .

static $p ( ) {

[ ] = new [ ] { $u } ;

= ;

for ( = ; < . ; ++ )

+= . ;

. . ( + ) ;

}

throws

. ( ) )

if . [ ]( ) )

= new ( ) ;

static ( ) {[ ]

= ;

for ( = ; < . ; ++ )

. . ( + ) ;

}

throws

if . [ ]( ) )

= new ( ) ;

(

+= . ;( ) )(

(

(

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

.

$p $p

$p $p

$p $p $p $p

$p $p $p

$p $p $p $p $p $p $p

$p $p $p $p

$p $p $p $p $p $p

$p $p $p $p $p

$p $p $p $p $p

$p $p $p $p

$p $p $p

$p $p $p $p $p $p $p

$p $p $p $p

$p $p $p $p $p $p

$p $p $p $p $p

$p

ステップ (3):パラメータ置換を行う

Page 34: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 34

ステップ(4):マッチングアルゴリズムにより,コードクローンを検出

stat

ic$p $p ( ) th

rows

$p { $p $p [ ] "="

$p $p [ ] { $u } ; $p $p "="

new

$p ( $p ) ; $p $p "="

$p

static * $p * * * * * * * * * * * * * *$p * * * * * * * * * * * * * *( * * ) * * throws * $p * * * * * * * * * * * * * *{ * * $p * * * * * * * * * * * * * *$p * * * * * * * * * * * * * *[ * * ] * * "=" * * * $p * * * * * * * * * * * * * *$p * * * * * * * * * * * * * *[ * * ] * * { * * $u * } * ; * * $p * * * * * * * * * * * * * *$p * * * * * * * * * * * * * *"=" * * * new * $p * * * * * * * * * * * * * *( * * $p * * * * * * * * * * * * * *) * * ; * * $p * * * * * * * * * * * * * *$p * * * * * * * * * * * * * *"=" * * * $p * * * * * * * * * * * * * *

Page 35: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 35

1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) { 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. } 9. System.out.println("sum = " + sum);10. }11. static void goo(String [] a) throws RESyntaxException {12. RE exp = new RE("[0-9,]+");13. int sum = 0;14. for (int i = 0; i < a.length; ++i) {15. if (exp.match(a[i]))16. sum += parseNumber(exp.getParen(0));17. }18. System.out.println("sum = " + sum);19. }

4-6 行目と

13-15 行目,

8-10 行目と

17-19 行目

Page 36: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 36

クローン

1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. }10. static void goo(String [] a) throws RESyntaxException {11. RE exp = new RE("[0-9,]+");12. int sum = 0;13. for (int i = 0; i < a.length; ++i)14. if (exp.match(a[i]))15. sum += parseNumber(exp.getParen(0));16. System.out.println("sum = " + sum);17. }

Page 37: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 37

Java向けの変形ルールRJ1 :パッケージ名除去

( PackageName ‘.’ )+ ClassName → ClassNameRJ2:Callee 挿入

NDotOrNew NClassName ‘(‘→ NDotOrNew CalleeIdentifier ‘.’ NClassName ‘(‘

RJ3: テーブル初期化除去'=' '{' InitalizationList, '}' → '=' '{' UniqueIdentifier '}‘']' '{' InitalizationList, '}' → ']' '{' UniqueIdentifier '}’

RJ4: モジュールの分離トップレベルの定義や宣言の終わりに UniqueIdentifier を挿入する

RJ5: 可視性キーワードの除去protected, public , synchronized などのキーワードを取り除く

RJ6: コンパウンド・ブロックの処理if (…), else, while (…) の直後が単文なら {} を補う

Page 38: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 38

修正のたびにコードクローンの位置情報を更新すると‥

クローンペア

修正する

クローンでなくなる

検出されなくなる

Page 39: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 39

実装 Java で実装 動作環境  FreeBSD

メニューバー

ステータスバー

Page 40: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 40

先頭行から修正箇所を探し出す支援はないのか? ありません 一般的なプログラムテキストにおいて

コードクローンの大部分は大きさが 20 トークン程度( 10 行程度)であるといわれている

Page 41: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 41

本ツールの対応している言語 CCFinder が対応していることが前提で、

さらに行間のコメントで始まる言語 CCFinder は C/C++,Java,COBOL,Fortran,Em

acsLisp に対応 現在、 C/C++, Java に対応

Page 42: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 42

CCFider が実用時間とは?具体的には?

トークン列の比較にサフィックス木を利用しているため、高速

10MLOC ( 1千万行)ソースコードを 68分( Pentium3 650MHz RAM 1GB )で解析

本適用例においては 40 秒で解析

Page 43: プログラム変更支援を目的とした コードクローン情報付加ツール

2004/3/9 情報処理学会全国大会 43

コードクローンはすべて悪いか? そうとは限らない

時間的制約のあるシステムでは、関数呼び出しのオーバーヘッドを抑えるためにわざと同様の処理を並べて書くことがある