【文献】
丸山 勝久,プログラム依存グラフの等価性に基づくアスペクトの干渉検出,情報処理学会論文誌,2009年12月15日,Vol.50,No.12,pp.3108−3126
【文献】
George C. NECULA,Translation validation for an optimizing compiler,Proceedings of the ACM SIGPLAN 2000 conference on Programming language design and implementation,2000年 5月,Vol.35,Issue.5,pp.83-94
(58)【調査した分野】(Int.Cl.,DB名)
前記構造比較手段は、前記リファクタリング前正規化ソースコード情報と、前記リファクタリング後正規化ソースコード情報の構造グラフを比較して、構造が一致すると判定された場合には、前記リファクタリング前ソースコードと前記リファクタリング後ソースコードを等価と判定して、等価性の検証処理を終了し、
前記構造が不一致と判定された場合には、前記記号実行手段の処理へ移行することを特徴とする請求項1記載のソースコード等価性検証装置。
前記正規化手段は、前記リファクタリングパターン情報に対して定義された変更箇所特定情報を参照して、前記リファクタリング前ソースコード情報と、前記リファクタリング後ソースコード情報とを比較して、ソースコードの構造上の変更箇所を特定する変更箇所情報を生成する変更箇所特定手段を更に備え、
前記記号実行手段は、前記変更箇所特定手段が抽出した前記リファクタリング前ソースコード情報と、前記リファクタリング後ソースコード情報との変更箇所情報と、前記リファクタリングパターン情報に対して定義された抽象化情報を参照して、前記リファクタリング前正規化ソースコード情報と、前記リファクタリング後正規化ソースコード情報を抽象化する抽象化手段を更に備え、
前記抽象化手段が生成したリファクタリング前抽象化ソースコード情報と、リファクタリング後抽象化ソースコード情報に対して、記号実行をすることを特徴とする請求項1記載のソースコード等価性検証装置。
前記記号実行手段が、前記リファクタリング前正規化ソースコード情報と、前記リファクタリング後正規化ソースコード情報に対して、前記リファクタリングパターン情報毎に定義された抽象化処理を実施した後、実行木を生成し、全ての葉ノードに対して、各葉ノードのパス制約と変数状態との論理積を取り、全ての葉ノードの論理積に亘って論理和を取って記号実行サマリを表わす論理式を算出し、
前記等価性判定手段は、前記記号実行手段が算出した前記リファクタリング前正規化ソースコード情報の記号実行サマリを表わす論理式と、前記リファクタリング後正規化ソースコード情報の記号実行サマリを表わす論理式が、論理的に等価であるか否かを判定する
ことを特徴とする請求項1記載のソースコード等価性検証装置。
表示画面上に、ソースコード等価性検証結果と共に、前記リファクタリング前正規化ソースコード情報の構造グラフと、前記リファクタリング後正規化ソースコード情報の構造グラフとを対比して表示し、更に、リファクタリング前のソースコードに対する記号実行サマリ情報と、リファクタリング後のソースコードに対する記号実行サマリ情報とを対比して表示する、または前記表示情報を全て出力装置へ出力する検証結果出力手段を更に有することを特徴とする請求項1記載のソースコード等価性検証装置。
前記検証結果出力手段は、前記等価性判定手段が前記リファクタリング前正規化ソースコード情報の論理式と、前記リファクタリング後正規化ソースコード情報の論理式が論理的に等価ではないと判定した場合に、反例情報を更に表示、若しくは出力することを特徴とする請求項4、または請求項5に記載のソースコード等価性検証装置。
前記構造比較ステップは、前記リファクタリング前正規化ソースコード情報と、前記リファクタリング後正規化ソースコード情報の構造グラフを比較して、構造が一致すると判定された場合には、前記リファクタリング前ソースコードと前記リファクタリング後ソースコードを等価と判定して、等価性の検証処理を終了し、
前記構造が不一致と判定された場合には、前記記号実行ステップの処理へ移行することを特徴とする請求項7記載のソースコード等価性検証方法。
前記正規化ステップは、前記リファクタリングパターン情報に対して定義された変更箇所特定情報を参照して、前記リファクタリング前ソースコード情報と、前記リファクタリング後ソースコード情報とを比較して、ソースコードの構造上の変更箇所を特定する変更箇所情報を生成する変更箇所特定ステップを更に含み、
前記記号実行ステップは、前記変更箇所特定ステップで抽出した前記リファクタリング前ソースコード情報と、前記リファクタリング後ソースコード情報との変更箇所情報と、前記リファクタリングパターン情報に対して定義された抽象化情報を参照して、前記リファクタリング前正規化ソースコード情報と、前記リファクタリング後正規化ソースコード情報を抽象化する抽象化ステップを更に含み、
前記抽象化ステップで生成したリファクタリング前抽象化ソースコード情報と、リファクタリング後抽象化ソースコード情報に対して、記号実行をすることを特徴とする請求項7記載のソースコード等価性検証方法。
前記記号実行ステップにおいて、前記リファクタリング前正規化ソースコード情報と、前記リファクタリング後正規化ソースコード情報に対して、前記リファクタリングパターン情報毎に定義された抽象化処理を実施した後、実行木を生成し、全ての葉ノードに対して、各葉ノードのパス制約と変数状態との論理積を取り、全ての葉ノードの論理積に亘って論理和を取って記号実行サマリを表わす論理式を算出し、
前記等価性判定ステップにおいて、前記記号実行ステップで算出した前記リファクタリング前正規化ソースコード情報の記号実行サマリを表わす論理式と、前記リファクタリング後正規化ソースコード情報の記号実行サマリを表わす論理式が、論理的に等価であるか否かを判定することを特徴とする請求項7記載のソースコード等価性検証方法。
表示画面上に、ソースコード等価性検証結果と共に、前記リファクタリング前正規化ソースコード情報の構造グラフと、前記リファクタリング後正規化ソースコード情報の構造グラフとを対比して表示し、更に、リファクタリング前のソースコードに対する記号実行サマリ情報と、リファクタリング後のソースコードに対する記号実行サマリ情報とを対比して表示する、または前記表示情報を全て出力装置へ出力する検証結果出力ステップを更に有することを特徴とする請求項7記載のソースコード等価性検証方法。
前記検証結果出力ステップにおいて、前記等価性判定ステップで前記リファクタリング前正規化ソースコード情報の論理式と、前記リファクタリング後正規化ソースコード情報の論理式が論理的に等価ではないと判定した場合に、反例情報を更に表示、若しくは出力することを特徴とする請求項10、または請求項11に記載のソースコード等価性検証方法。
【発明を実施するための形態】
【0033】
以下、本発明における実施形態を、図面を用いて説明する。
【実施例1】
【0034】
以下、
図1乃至
図10を用いて本発明の一実施形態に係るソースコード等価性検証装置1000の構成と処理について説明する。
【0035】
先ず、
図1を用いて本発明の一実施形態に係るソースコード等価性検証装置のハードウェア構成について説明する。
本発明の一実施形態に係るソースコード等価性検証装置のハードウェア構成としては、例えば、
図1に示されるような一般的なパーソナルコンピュータで実現される。
ソースコード等価性検証装置1000は、CPU(Central Processing Unit)101、主記憶装置102、ネットワークI/F103、グラフィックI/F104、入出力I/F105、補助記憶装置I/F106が、バスにより結合された形態になっている。
【0036】
CPU101は、ソースコード等価性検証装置100の各部を制御し、主記憶装置102にソースコード等価性検証プログラム200をロードして実行する。
主記憶装置102は、通常、RAMなどの揮発メモリで構成され、CPU101が実行するプログラム、参照するデータが補助記憶装置などからロードされて、記憶される。
【0037】
ネットワークI/F103は、外部ネットワーク150と接続するためのインタフェースである。
グラフィックI/F104は、LCD(Liquid Crystal Display)などの表示装置120を接続するためのインタフェースである。
入出力I/F105は、入出力装置を接続するためのインタフェースである。
図1の例では、キーボード131とポインティングデバイスのマウス132が接続されている。
補助記憶装置I/F106は、HDD(Hard Disk Drive)141やDVD(Digital Versatile Disk)ドライブ装置142などの補助記憶装置を接続するためのインタフェースである。
【0038】
HDD141は、大容量の記憶容量を有しており、本実施形態を実行するためのソースコード等価性検証プログラム200が格納されている。
DVDドライブ装置142は、DVDやCDなどの光学ディスクにデータを書き込んだり、光学ディスクからデータを読み込んだりする装置であり、ソースコード等価性検証プログラム200は、例えば、CD−ROMにより提供されたものをインストールすることができる。
【0039】
本実施形態のソースコード等価性検証装置1000は、上記のようなパーソナルコンピュータに、ソースコード等価性検証プログラム200をインストールして、各機能を実行するものである。
【0040】
次に、
図2を用いて本発明の一実施形態に係るソースコード等価性検証装置のソフトウェア構成について説明する。
ソースコード等価性検証装置1000で実行するプログラム等価性検証プログラム200のモジュール構成は、サブルーチンであるソースコード解析モジュール201、構造グラフ生成・更新モジュール202、構造グラフ解析モジュール203、実行木生成モジュール204、記号実行実行モジュール205、入出力モジュール206、データベースモジュール207からなる。
なお、プログラム等価性検証プログラム200は、OS(Operating System)上で動作するアプリケーションソフトウェアであり、ソースコード等価性検証装置のソフトウェア構成として、OSやライブラリプログラムも含むが図では、省略している。
【0041】
ソースコード解析モジュール201は、ソースコードの字句解析・構文解析を行い、構造グラフ生成のために必要な情報を取り出すモジュールである。
構造グラフ生成・更新モジュール202は、ソースコード解析モジュール201の解析結果に基づいて、構造グラフを生成したり、更新したりするモジュールである。
構造グラフ解析モジュール203は、構造グラフのグラフ構造を解析するモジュールである。
実行木生成モジュール204は、構造グラフ解析モジュール203の解析結果に基づき、実行木を生成するモジュールである。
記号実行実行モジュール205は、実行木生成モジュール204が生成した実行木に対する記号実行を行うモジュールである。
入出力モジュール206は、外部から必要なデータの入出力を行うモジュールである。
データベースモジュール207は、各種データベースにアクセスするためのモジュールである。
【0042】
図3は、ソースコード等価性検証装置1000の機能構成図を示す。制御部110は、
図1のCPU101、主記憶装置102から成り、記憶部1600は主に
図1のHDD141から成るが、主記憶装置102を含めることもある。入力装置130は、
図1の入出力I/F105、キーボード131、マウス132などを含み、更に補助記憶装置I/F106を介してDVDドライブ装置142から読込む構成を含めてもよい。出力装置120は、グラフィックI/F104、表示装置120などを含み、更に補助記憶装置I/F106を介してDVDドライブ装置142へ書き込む構成を含めてもよい。通信部103は、
図1のネットワークI/F103を表わすが、ネットワーク150を介して例えば外部計算機160と接続されている。
【0043】
記憶部1600は、ソースコード等価性検証プログラム200、本装置で対応するリファクタリングの種類を予め登録しているリファクタリングパターン登録情報1120、リファクタリング前/後ソースコード情報に施す正規化処理を前記リファクタリングパターン毎に予め登録している正規化データベース1601、およびリファクタリング前/後ソースコード情報に施す抽象化処理を前記リファクタリングパターン毎に予め登録している抽象化データベース1602を予め備えておく。
【0044】
記憶部1600は更に、ソースコード等価性検証処理が実施される際に確保されるリファクタリング前/後ソースコード記憶領域1603、リファクタリング前/後ソースコード情報記憶領域1604、リファクタリング前/後記号実行結果記憶領域1605、及び検証結果記憶領域1606を有する。
【0045】
制御部110は、記憶部1600からソースコード等価性検証プログラム200をロードして、CPU101で実行することにより、入力部1100、正規化部1200、構造比較検証処理部1300、記号実行実施判定部1700、記号実行検証処理部1400、出力部1500の各機能を実現する。
【0046】
次に、
図4乃至
図10を用いて本発明の一実施形態に係るソースコード等価性検証装置の各機能と、それらの処理について説明する。
図4は、本発明の一実施形態に係るソースコード等価性検証装置全体の機能と、データフローを示した図である。
図5は、本発明の一実施形態に係るソースコード等価性検証装置の処理を示すフローチャートである。
図6は、入力部1100の機能の詳細とデータフローを示した図である。
図7は、正規化部1200の機能の詳細とデータフローを示した図である。
図8は、構造比較検証処理部1300の機能の詳細とデータフローを示した図である。
図9は、記号実行実施判定部1700の機能の詳細とデータフローを示した図である。
図10は、記号実行検証処理部1400の機能の詳細とデータフローを示した図である。
【0047】
ソフトウェア開発者は、外部計算機160に実装されたソフトウェア開発装置で作成したソフトウェアにリファクタリングを実施して、リファクタリング実施後のソースコードがリファクタリング実施前のソースコードと等価であるかどうかを検証するために、リファクタリング前/後ソースコードを、ネットワーク150を介してソースコード等価性検証装置1000へ送って、検証を依頼する。依頼されたリファクタリング前/後ソースコードは、記憶部1600のリファクタリング前/後ソースコード記憶領域1603に記憶され、等価性検証処理がなされる。
【0048】
または、ソフトウェア開発装置が本実施形態のソースコード等価性検証装置1000と同じパーソナルコンピュータに実装されている場合には、ソフトウェア開発者は、
図3の入力装置130などにより、リファクタリング前/後ソースコードを入力して、それらのデータをリファクタリング前/後ソースコード記憶領域1603に記憶させて等価性検証処理を実行する。
【0049】
ソフトウェア開発者が、リファクタリング前/後ソースコードを入力して、等価性検証処理を依頼する際に、如何なる種類のリファクタリングを実施したのかを表わすリファクタリングパターン入力情報0003を添付して入力する。
【0050】
本実施形態のソースコード等価性検証装置1000は、
図4に示されるように、リファクタリング前ソースコード0001とリファクタリング後ソースコード0002の二つのソースコードと、リファクタリング前ソースコード0001に対して適用されたリファクタリングパターンに関する入力情報であるリファクタリングパターン入力情報0003の入力によって、リファクタリング前ソースコード0001とリファクタリング後ソースコード0002のソースコードの等価性を検証するものである。
【0051】
先ず、入力部1100において、入力された、または既に記憶部1603に記憶されたリファクタリング前ソースコード0001を受け付ける(
図5のS101)。リファクタリング後ソースコード入力ステップS102では、入力部1100において、リファクタリング後ソースコード0002を受け付ける(S102)。また、入力部1100において、リファクタリングパターン入力情報0003の入力を受け付ける(S103)。
【0052】
以下、
図6を用いて上記の入力部1100の機能の詳細とその処理について説明する。
リファクタリング前ソースコード0001は、
図6に示されるように、入力部1100におけるソースコード入力部1101によって受付けられ、ソースコードの字句解析と構文解析を行い、リファクタリング前ソースコード情報1001に変換される。リファクタリング後ソースコード0002も、入力部1100におけるソースコード入力部1101によって受付けられ、ソースコードの字句解析と構文解析を行い、リファクタリング後ソースコード情報1002に変換され、記憶部1600に格納される。また、リファクタリングパターン入力情報0003は、入力部1100におけるリファクタリングパターン入力部1102によって受け付けられ、リファクタリングパターン種別を表すリファクタリングパターン情報1003に変換され、記憶部1600に格納される。
【0053】
次に、リファクタリング前ソースコード情報1001と、リファクタリング後ソースコード情報1002を比較し、ソースコードの構造上の変更箇所を特定する(S1041)。
そして、正規化部1200は、記憶部1600に格納された情報を用いて、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002の正規化を行う(S1042)。
【0054】
ここで、正規化とは、リファクタリングが行われたソースコードのソースコード情報を、そのソースコードと等価なソースコードに対応するソースコード情報に変換することを意味する。この正規化は、この後に続く構造比較ステップS1043と記号実行ステップS1045に適した形にするために行われる。
【0055】
以下、
図7を用いて上記の正規化部1200の機能の詳細とその処理について説明する。
リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002は、正規化部1200の変更箇所特定部1201に入力される。一方、正規化DB1601に格納されているリファクタリングパターン情報1003に対応した変更箇所特定情報1007bが読み出される。そして、変更箇所特定部1201はソースコード情報を比較し、リファクタリングパターン情報1003に対応した変更箇所特定情報1007bを参照し、ソースコードの構造上の変更箇所を特定し、変更箇所情報1004を生成する(S1041)。
【0056】
次に、リファクタリングパターン入力情報1003に対応する正規化の方法を表した正規化情報1007aを記憶部1600の正規化DB1601から取得する(S1042)。正規化DB1601には、リファクタリングパターンごとに対応した正規化情報1007aを格納してある。正規化部1200のソースコード正規化部1202において、リファクタリング前ソースコード情報1001に対して、取得した正規化情報1007aに基づき正規化を行い、リファクタリング前正規化ソースコード情報1005を生成する。また、正規化部1200のソースコード正規化部1202において、リファクタリング後ソースコード情報1002に対して、正規化情報1007aに基づき、正規化を行い、リファクタリング後正規化ソースコード情報1006を生成する。
【0057】
次に、構造比較検証処理部1300は、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006の構造を比較し、同じ構造であるか否かを検証する(ステップS1043)。
【0058】
以下、
図8を用いて構造比較検証処理部1300の機能の詳細とその処理について説明する。
構造比較検証処理部1300は、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006を受け取り、二つの正規化後のソースコード情報の構造が一致しているか否かの比較を行い、一致した場合は、構造比較結果1008として、一致しているという情報を生成し、不一致の場合は、構造比較結果1008として、不一致であるという情報を生成する(S1043)。
【0059】
次に、記号実行実施判定部1700では、記号実行を行うべきか否かを判定する(S1047)。ここで、上記の構造比較ステップS1043の結果で、構造が一致していると判定されたときには、等価非等価出力ステップS105に行き、構造が不一致であると判定されたときには、ソースコード情報抽象化ステップS1044に行く。
【0060】
以下、
図9を用いて記号実行実施判定部1700の機能の詳細とその処理について説明する。
記号実行実施判定部1700は、構造比較結果1008を受け取り、構造比較結果1008で、構造が「一致」であれば、等価非等価出力ステップS105へ移行し、出力部1500より、ソースコードが等価であるとして検証結果0004を出力する。
ソースコードが等価であるという結果が出力されたときには、ユーザは、行われたリファクタリングが正当であると判断することができる。
【0061】
記号実行実施判定部1700は、構造比較結果1008を受け取り、構造比較結果1008で、構造が「不一致」であれば、記号実行開始指示1009を生成する。
【0062】
次に、ソースコード情報の抽象化を行う(S1044)。
ここで、ソースコード情報の抽象化とは、各々のソースコード情報に対して、記号実行したときに、同じ入力を与えて、同じ結果がでるようにした状態を保ったまま、ソースコード情報を縮約することを意味する。
【0063】
次に、抽象化したリファクタリング前のソースコード情報と、抽象化したリファクタリング後のソースコード情報に対して、記号実行を行う(S1045)。
そして、記号実行の結果(記号実行サマリ)を論理的に比較し、同じ入力に対して、同じ出力が得られるときには、元のソースコードが等価であると、判断し、出力(記号実行サマリ)が異なるときには、元のソースコードが非等価であると、判断して(S1046)、等価非等価の結果出力を行う。
【0064】
リファクタリング前とリファクタリング後の記号実行の結果である記号実行サマリを比較し、論理的に等価であるかどうかの判定は、SATソルバやSMTソルバや決定手続きなどと呼ばれる手法を用いることで行う。記号実行サマリを構成する各葉ノードに対して、そのパス制約と変数状態との論理積を求め、それらの論理和を計算することにより記号実行サマリを表現する論理式を生成することができる。リファクタリング前の記号実行サマリから生成した論理式とリファクタリング後の記号実行サマリから生成した論理式とが等価であることをSATソルバで判定することにより、記号実行サマリの等価性が判定できる。
【0065】
ここで、ソースコードが等価であるという結果が出力されたときには、ユーザは、行われたリファクタリングが正当であると判断することができ、ソースコードが非等価であるいう結果が出力されたときには、ユーザは、行われたリファクタリングが不当であると判断することができる。そして、ユーザは、行われたリファクタリングが不当であると判断したときには、行ったリファクタリングを見直して、正当なものに修正する作業を開始することができる。
【0066】
記号実行検証処理部1400は、記号実行開始指示1009を受けて、ソースコード抽象化ステップS1044を開始する。ソースコード抽象化ステップS1044では、記憶部1600の抽象化DB1602に格納されている抽象化情報1010を用いて、リファクタリング前正規化ソースコード情報と変更箇所情報1004を受け取り、抽象化を行い、リファクタリング前抽象化ソースコード情報1403を生成する。また、ソースコード抽象化ステップS1044では、記憶部1600の抽象化DB1602に格納されている抽象化情報1010を用いて、リファクタリング後正規化ソースコード情報と変更箇所情報1004を受け取り、抽象化を行い、リファクタリング後抽象化ソースコード情報1404を生成する。ここで、抽象化DBに格納されている抽象化情報1010は、正規化後のソースコード情報に対して、変更箇所情報1004に関わらない箇所とループや再帰呼び出しの箇所を置き換えて、この後の記号実行ステップS1045の時に、変更箇所情報1004に関わらない箇所とループや再帰呼び出しの箇所を記号実行しないように変換する処理の方法に関する情報である。
【0067】
記号実行ステップS1045では、記号実行部1402において、リファクタリング前抽象化ソースコード情報1403とリファクタリング後抽象化ソースコード情報1404に対して、記号実行を行い、それぞれリファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406を得る。記号実行結果比較ステップS1046では、記号実行結果比較部1407において、リファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406が同じものであるか否かを比較し判定する。記号実行結果比較部1407において、リファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406が同じものであった場合、等価非等価出力ステップS105へ移行し、等価として出力部1500に検証結果0004を出力させる。記号実行結果比較部1407において、リファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406が異なるものであった場合、等価非等価出力ステップS105へ移行し、非等価として出力部1500に検証結果0004を出力させる。
【0068】
本実施形態のソースコード等価性検証装置によれば、計算量が爆発しやすい記号実行を行う前に、それぞれのリファクタリング前後のそれぞれのソースコード情報に対して、正規化後に、構造比較を行い、その元になるソースコードが等価であると判定された場合には、記号実行を行わない。
【0069】
また、構造比較で元になるソースコードが非等価と判定された場合には、ソースコード情報の抽象化を行って、ソースコード情報を縮減してから、記号実行を行うので、記号実行の計算量を削減することができる。
【実施例2】
【0070】
以下、上記の
図5を参照しながら、
図11乃至
図14を用いて本発明の一実施形態に係るソースコード等価性検証装置の処理の具体例について説明する。この例は、
図5の記号実行実施判定S1047の処理で、ソースコード情報である構造グラフの構造が一致すると判定される例である。
図11は、リファクタリング前後のソースコードの例を示す図である(その一)。
図12は、リファクタリング前後のソースコードに対応するソースコード情報の例を示す図である(その一)。
図13は、ソースコード情報に対して行われる正規化の例を示す図である。
図14は、正規化した構造グラフを構造比較により等価性検証した結果を表示する出力部の表示例を示す図である。
【0071】
この例では、ソースコードに対するリファクタリングとして、リファクタリングパターンExtractMethodに基づいたリファクタリングが行われる場合について説明する。リファクタリングパターンExtractMethodは、複数個所で同じ処理をしているソースコードにおいて、その同じ処理を関数として抜き出し、複数個所で同じ処理をしていた箇所を抜き出した関数への呼び出しに置き換えて、複数箇所に存在したソースコードを共通化するリファクタリングのパターンである。このリファクタリングパターンExtractMethodは、一つの関数においてソースコードの記述量が多い場合に、関数の可読性を向上させるために、その関数内のソースコードの一部を別の関数として抜き出すリファクタリングとしても用いられる。
【0072】
以下、
図11によりリファクタリングパターンExtractMethodによって、ソースコードのリファクタリングを行う例を説明する。
ソースコードC001は、リファクタリングパターンExtractMethodの適用前のソースコードであり、グローバル変数global_varに対してmain関数において10を代入するプログラムである。このソースコードC001に対して、リファクタリングパターンExtractMethodを適用したソースコードがC002となる。ソースコードC002は、ソースコードC001におけるglobal_var=10;というグローバル変数への代入文を関数fooとして抜き出し、global_var=10;の記述部分であった箇所を関数fooの呼び出しに変換している。
【0073】
先ず、
図11に示したリファクタリングの例における、
図5のリファクタリング前ソースコード入力S101とリファクタリング後ソースコード入力S102とリファクタリングパターンS103のステップについて説明する。
入力部1100では、ソースコード入力部1101によって、リファクタリング前ソースコード0001とリファクタリング後ソースコード0002を受け付けて、対応するリファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報を生成する。ここで、リファクタリング前ソースコード0001はソースコードC001、リファクタリング後ソースコード0002はソースコードC002に対応する。
【0074】
ソースコード等価性検証装置1000は、入力されたリファクタリング前ソースコード0001とリファクタリング後ソースコード0002をソースコード入力部1101によって字句解析と構文解析し、
図12の例で示されるような内部で扱う構造グラフに変換する。リファクタリングパターンExtractMethodの例では、ソースコードC001は、構造グラフM001、ソースコードC002は、構造グラフM002に変換される。ここで、リファクタリング前ソースコード情報1001は構造グラフM001、リファクタリング後ソースコード情報1002は構造グラフM002に対応する。
【0075】
入力部1100では、リファクタリングパターン入力部1102において、リファクタリングパターン入力情報0003を受け付けて、リファクタリングパターン情報1003を生成する。この例では、例えば、リファクタリングパターン入力情報0003が、リファクタリングパターンExtractMethodを表す文字列“ExtractMethod”や、画面のメニューでの選択番号のときに、リファクタリングパターン情報1003として、内部で、リファクタリングパターンExtractMethodを指し示すコードを生成する。
【0076】
次に、
図5の変更箇所特定S1041のステップについて説明する。
正規化部1200の変更箇所特定部1201において、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002とリファクタリングパターン情報1003から、正規化DB1601に記憶されている対応する変更箇所特定情報1007bを参照し、ソースコード上のどこを変更したのかを構造グラフ上から特定し、変更箇所情報1004を出力する。このリファクタリングパターンExtractMethodの例では、リファクタリングパターンExtractMethodは、リファクタリング後ソースコード情報1002において関数(entry foo)が増加するという特徴から、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002の関数の宣言を比較し、リファクタリング後ソースコード情報1002のみに現れる関数を変更箇所として特定する。
図12上では、リファクタリング前ソースコード情報1001の構造グラフM001とリファクタリング後ソースコード情報1002の構造グラフM002の中で、関数を示すentryを比較し、ノードM003が指し示すentryのfoo関数が増えていることから、ノードM003およびfoo関数を呼び出すノードM004が、変更箇所情報1004に該当する。
【0077】
次に、
図5のソースコード情報正規化S1042のステップについて説明する。正規化部1200のソースコード正規化部1202において、変更箇所情報1004とリファクタリング前ソースコード情報1001から、正規化DB1601に記憶している対応する正規化情報1007aを用いて正規化を行い、リファクタリング前正規化ソースコード情報1005を生成する。リファクタリング後ソースコード情報1002も同様に正規化を行い、リファクタリング後正規化ソースコード情報1006を生成する。このリファクタリングパターンExtractMethodにおけるソースコード正規化部1202の例を示すと、
図13のようになる。先ず、正規化DB1601からリファクタリングパターン情報1003であるリファクタリングパターンExtractMethodに対応する正規化情報1007aを取得する。リファクタリングパターン情報1003のExtractMethodに対応する正規化情報1007aによれば、正規化方法は、Extractしたリファクタリング後ソースコード情報0002における変更箇所1004の関数を、インライン展開して元に戻したときのソースコードを表す構造にすることである。
【0078】
図13における変更箇所情報1004は、リファクタリング後ソースコード情報1002の構造グラフM002におけるノードM003とノードM004であり、これらのノードは、リファクタリングにより作られたExtractされた関数fooであるので、その関数fooを正規化して元に戻すと、構造グラフM006のようになる。これがリファクタリング後正規化ソースコード情報1006となる。リファクタリング前正規化ソースコード情報1005は、リファクタリングパターンExtractMethodに関して正規化処理が無いため、
図13上のリファクタリング前ソースコード情報0001の構造グラフM001は正規化では何も変更されずに、そのまま、構造グラフM005となる。
【0079】
次に、
図5の構造比較S1043のステップについて説明する。
構造比較検証処理部1300では、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006を受け取り、ソースコード情報の構造の比較を行い、その結果を構造比較結果1008として生成する。リファクタリングパターンExtractMethodによるリファクタリングを行った
図13による例において、構造比較検証処理部1300は、リファクタリング前正規化ソースコード情報1005のグラフM005とリファクタリング後正規化ソースコード情報1006のグラフM006の二つのグラフが同じ構造でありそれぞれのノードが同じであるため、構造比較結果1008として、ソースコードC001とソースコードC002を等価であると判定する。
【0080】
次に、
図5の記号実行実施判定S1047のステップについて説明する。
記号実行実施判定部1700は、リファクタリングパターンExtractMethodによるリファクタリングを行った
図11による例において、構造比較結果1008として、リファクタリング前後のソースが等価として判定されるため、等価非等価出力ステップS105に移行し、出力部1500は、構造比較検証処理部1300が等価と判定した結果を受けて、検証結果0004として等価であることを出力する。
【0081】
記号実行実施判定部1700は、リファクタリングパターンExtractMethodによるリファクタリングを行ったこの
図11による例では、正規化部1200による変換と構造比較検証処理部1300の判定処理によって、リファクタリング前後のソースコードが、各々等価と判定できるため、記号実行検証処理部1400により、記号実行の計算を必要とせず、計算量を不必要に増加させずに、迅速な等価判定が可能となる。
【0082】
図14には、構造比較検証処理部1300の判定処理によって、等価と判定された場合の出力部1500による検証結果0004の表示例を示す。
図14に示す表示例には、判定結果P100として構造比較により判定したこと、および、その結果等価と判定されたことを示している。また、構造比較に用いた構造グラフデータとして、正規化を実施した後のリファクタリング前正規化ソースコード情報の構造グラフP111とリファクタリング後正規化ソースコード情報の構造グラフP112を表示している。さらに、リファクタリング適用情報P120として、適用されているリファクタリングパターン名であるExtractMethod、ExtractMethodで抽出された関数名であるfooと、当該リファクタリングパターンが適用されている位置の情報としてリファクタリング適用前ソースコードに対してはファイル名sample.cと行番号3が、リファクタリング適用後ソースコードに対してはファイル名sample.cと行番号6が表示されている。
【0083】
図14に示す、リファクタリング適用情報P120を見ることにより、等価性検証装置が認識したリファクタリングのパターンと箇所が、開発者が意図したリファクタリングと一致していることを確認することができる。
【実施例3】
【0084】
以下、上記の
図5を参照しながら、
図15乃至
図20を用いて本発明の一実施形態に係るソースコード等価性検証装置の処理の具体例について説明する。この例は、
図5の記号実行実施判定の処理で、リファクタリングパターンによらないリファクタリングが実施されたソースコードにおいて、ソースコード情報である構造グラフの構造が不一致であると判定される例である。
【0085】
図15は、リファクタリング前後のソースコードの例を示す図である(その二)。
図16は、リファクタリング前後のソースコードに対応するソースコード情報の例を示す図である(その二)。
図17は、抽象化されたソースコード情報の例を示す図である。
図18は、リファクタリング前ソースコードとリファクタリング後ソースコードに対して記号実行したときの実行木を示した例である。
図19は、記号実行の一例を説明するために、ソースコードとそれより派生するデータ構造について示した図である。
図20は、記号実行検証処理部により等価性検証した結果を表示する表示部の表示例を示す図である。
【0086】
この例では、ソースコードに対するリファクタリングとして、ソースコードにおける条件式を変更せずに変数への代入を整理するリファクタリングが行われる場合について説明する。
【0087】
図15では、リファクタリング前のソースコードC003とリファクタリング後のソースコードC004が示されており、ソースコードC003とソースコードC004の間で、ソースコードにおける条件式を変更せずに変数への代入を整理するリファクタリングが適用されている。具体的には、リファクタリング前のソースコードC003では、ソースコード部分C005が示す所において、変数aに対して値を代入し、ソースコード部分C006が示す所において、変数a(右辺)の値を用いて演算し変数a(左辺)に代入している。リファクタリング後のソースコードC004では、ソースコード部分C007が示す所において、変数bに対して値を代入し、ソースコード部分C008が示す所において、変数bの値を用いて演算し変数aに代入している。リファクタリング前と後で、ソースコード部分C005が示す所とソースコード部分C007が示す所に存在する条件式、ソースコード部分C006が示す所とソースコード部分C008が示す所に存在する条件式は一致しているが、用いている変数を変更し、ソースコードC004の方が、ソースコード行数が少なく可読性が高いものになっている。
図15の例で示すリファクタリングは、非特許文献4に記載されているリファクタリングパターン72種に該当せず、本実施形態のソースコード等価性検証装置1000においてもパターンとしてデータベースに登録されていないものとする。
【0088】
先ず、
図15に示したリファクタリングの例における、
図5のリファクタリング前ソースコード入力S101とリファクタリング後ソースコード入力S102について説明する。このリファクタリングの例では、リファクタリング前ソースコード0001がソースコードC003、リファクタリング後ソースコード0002がソースコードC004に対応する。入力部1100では、ソースコード入力部1101によって、リファクタリング前ソースコード0001とリファクタリング後ソースコード0002を受け付けて、対応するリファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002を生成する。
図15のリファクタリングの例において、ソースコード入力部1101がリファクタリング前ソースコード0001としてソースコードC003を受け付け、字句解析と構文解析を行い、リファクタリング前ソースコード情報1001として
図16の構造グラフM008に変換する。また、ソースコード入力部1101は、リファクタリング後ソースコード0002としてソースコードC004を受けつけ、字句解析と構文解析を行い、リファクタリング後ソースコード情報1002として
図16の構造グラフM009に変換する。ここで、リファクタリング前ソースコード情報1001は構造グラフM008、リファクタリング後ソースコード情報1002は構造グラフM009に対応する。
【0089】
次に、リファクタリングパターンに関する情報を入力するS103のステップについて説明する。
入力部1100では、リファクタリングパターン入力部1102において、リファクタリングパターン入力情報0003を受け付けて、リファクタリングパターン情報1003を生成する。このリファクタリングの例では、リファクタリングパターンは、登録されていないものと仮定しているため、「該当無し」を示す文字列やメニューの選択番号がリファクタリングパターン入力部1102に入力され、リファクタリングパターン入力部は、リファクタリングパターン情報1003として、「該当無し」を示すコードを生成する。
【0090】
次に、
図5の変更箇所特定S1041のステップについて説明する。
正規化部1200の変更箇所特定部1201において、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002から、ソースコード上のどこを変更したのかを特定し、変更箇所情報1004を出力する。このリファクタリングの例では、リファクタリング前ソースコード情報1001である構造グラフM008とリファクタリング後ソースコード情報0002である構造グラフM009を比較し、両方に関数fooと関数varが存在しているため関数レベルの増減が無く、foo関数の内部に差異がみられるため、変更箇所特定部1201は、foo関数の内部を変更箇所情報1004として出力する。なお、この例では、リファクタリングパターンとして「該当無し」なので、正規化DB1601の変更箇所特定情報1007bは、参照せず、構造グラフの構造を解析することだけで、変更箇所を特定する。
【0091】
次に、
図5のソースコード情報正規化S1042のステップについて説明する。
正規化部1200のソースコード正規化部1202において、変更箇所情報1004とリファクタリング前ソースコード情報1001から、正規化DB1601の中にある対応する正規化情報1007aの正規化手法を用いて正規化を行い、リファクタリング前正規化ソースコード情報1005を生成する。リファクタリング後ソースコード情報1002も同様に正規化を行い、リファクタリング後正規化ソースコード情報1006を生成する。このリファクタリングの例では、正規化DB1601からリファクタリングパターン情報1003が「該当無し」に対応する正規化情報を取得する。ここで、リファクタリングパターン情報1003が「該当無し」に対応する正規化情報は、変換無しとなるため、ソースコード正規化部1202は、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002に関して、何も変更せずにリファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006を出力する。正規化部1200で変換されていないので、リファクタリング前正規化ソースコード情報1005は、
図16における構造グラフM008であり、リファクタリング後正規化ソースコード情報1006は、
図16における構造グラフM009である。
【0092】
次に、
図5の構造比較S1043のステップについて説明する。
構造比較検証処理部1300では、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006を受け取り、ソースコード情報の構造の比較を行い、構造比較結果1008を生成する。
【0093】
複数のグラフ構造の間の一致・不一致を探索する方法は種々考えられるが、例えば階層の最上位のノードから比較を開始して、その子供のノード間の比較、さらにその子供のノード間の比較というように、順次階層を下げて、全ての階層のノード間の比較を行ない、その途中で不一致が判定されたら、両グラフ構造は異なると判定する方法が挙げられる。
【0094】
このリファクタリングの例では、リファクタリング前正規化ソースコード情報1005のグラフM008とリファクタリング後正規化ソースコード情報1006の構造グラフM009を比較し、グラフM009には、ノード「entry foo」の子供のノード「a=0」が無いことから、明らかにグラフ構造が異なると判定して、構造比較結果1008を、リファクタリング前後のソースコードが非等価と判定する。
【0095】
次に、
図5の記号実行実施判定ステップS1047について説明する。
記号実行実施判定部1700は、このリファクタリングの例において、構造比較結果1008として、ソースコードが非等価と判定されたため、記号実行開始指示1009のコマンドを生成する。
【0096】
次に、
図5のソースコード情報抽象化ステップS1044について説明する。
記号実行検証処理部1400は、記号実行開始指示1009を受け取ると、抽象化部1401において、変更箇所情報1004と抽象化DB1602の抽象化方法を記録した抽象化情報1010を用いて、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006の抽象化を行う。抽象化DB1602の抽象化情報1010には、変更箇所情報1004に対応して適切な抽象化手法が記録されている。このリファクタリングの例では、変更箇所情報1004は関数fooの内部と判明しているため、抽象化DB1602から、関数fooを除いたソースコードの中で、リファクタリング前後で差異が生じていない関数を変数に変換して抽象化する方法を記載した抽象化情報1010を取得する。抽象化部1401において、リファクタリング前後で差異が生じていない関数を変数に変換して抽象化する方法を、リファクタリング前正規化ソースコード情報1005のグラフM008とリファクタリング後正規化ソースコード情報1006のグラフM009に適用した結果を示すと、
図17のようになる。
図16のリファクタリング前正規化ソースコード情報1005の構造グラフM008において、ノードM010の関数varはリファクタリングによって差異が生じていないため、関数varを呼び出す箇所のノードM011と合わせて変数vとして抽象化を行い、
図17の構造グラフM014のように変換する。ただし、この抽象化は、ノードM010と他のノードとのDataDependency(データの依存性)がないことが必要である)。
図16におけるリファクタリング後正規化ソースコード情報1006のグラフM009に関しても、同様に抽象化を行い構造グラフM015に変換される。抽象化部1401は、前記構造グラフM014をリファクタリング前抽象化ソースコード情報1403、前記構造グラフM015をリファクタリング後抽象化ソースコード情報1404として出力する。ここで、この抽象化は、構造グラフM008、M009の各々において、ノードがカットされて、各々が記号実行されたときには、計算量が減ることに留意する。
【0097】
次に、
図5の記号実行S1045のステップについて説明する。
記号実行検証処理部1400では、抽象化部1401において抽象化を行った後、リファクタリング前抽象化ソースコード情報1403とリファクタリング後抽象化ソースコード情報1404のそれぞれに対して、記号実行部1402において、記号実行を実行し、その結果としてリファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406を生成する。このリファクタリングの例において、記号実行部1402にて、前記リファクタリング前抽象化ソースコード情報1403とリファクタリング後抽象化ソースコード情報1404を記号実行した結果は、
図18に示されるようになる。このリファクタリングの例では、リファクタリング前抽象化ソースコード情報1403は、
図17の構造グラフM014に該当し、構造グラフM014に対して記号実行を行うと、
図18における実行木E100ができる。また、
図18の実行木E100における記号実行サマリであるE101,E102,E103,E104が、リファクタリング前抽象化ソースコード情報1403に対するリファクタリング前記号実行結果1405となる。リファクタリング後抽象化ソースコード情報1404は、
図17の構造グラフM015に該当し、構造グラフM015に対して記号実行を行うと、
図18における実行木E200ができる。また、
図18の実行木E200における記号実行サマリであるE201,E202,E203,E204が、リファクタリング後抽象化ソースコード情報1404に対するリファクタリング後記号実行結果1406となる。
【0098】
次に、
図5の記号実行結果比較S1046のステップについて説明する。
記号実行検証処理部1400の記号実行結果比較部1407では、リファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406とが論理的に等価かどうかを比較し、リファクタリング前後のソースコードが等価か非等価かの判定を行う。
図15のリファクタリングの例では、リファクタリング前記号実行結果1405は、E101,E102,E103,E104であり、リファクタリング後記号実行結果1406は、E201,E202,E203,E204である。これら二つの記号実行結果が論理的に等価であることを以下のようにして判定する。
【0099】
リファクタリング前の記号実行サマリを表現する論理式として、E101のパス制約と変数状態との論理積、E102のパス制約と変数状態との論理積、E103のパス制約と変数状態との論理積、E104のパス制約と変数状態との論理積、との4個の論理式の論理和を取る。すなわち、((β<0)AND(γ<0)AND(a=−γ)AND(b=0)AND(v=γ))OR((β<0)AND(NOT(γ<0))AND(a=γ)AND(b=0)AND(v=γ))OR((NOT(β<0))AND(γ<0)AND(a=β−γ)AND(b=β)AND(v=γ))OR((NOT(β<0))AND(NOT(γ<0))AND(a=β+γ)AND(b=β)AND(v=γ))がリファクタリング前の記号実行サマリを表現する論理式である。リファクタリング後の記号実行サマリを表現する論理式として、E201のパス制約と変数状態との論理積、E202のパス制約と変数状態との論理積、E203のパス制約と変数状態との論理積、E204のパス制約と変数状態との論理積、との4個の論理式の論理和を取る。便宜上、リファクタリング後の出力変数a,b,vの値をそれぞれa’,b’,v’とすると、リファクタリング後の記号実行サマリを表現する論理式は、((β<0)AND(γ<0)AND(a’=−γ)AND(b’=0)AND(v’=γ))OR((β<0)AND(NOT(γ<0))AND(a’=γ)AND(b’=0)AND(v’=γ))OR((NOT(β<0))AND(γ<0)AND(a’=β−γ)AND(b’=β)AND(v’=γ))OR((NOT(β<0))AND(NOT(γ<0))AND(a’=β+γ)AND(b’=β)AND(v’=γ))となる。
【0100】
リファクタリング前の記号実行サマリを表現する論理式と、リファクタリング後の記号実行サマリを表現する論理式が、論理的に等価であるかどうかを判定する。
その判定方法は、前記リファクタリング前の記号実行サマリを表現する論理式と、リファクタリング後の記号実行サマリを表現する論理式のそれぞれに含まれる記号変数の値が同じである場合には出力変数の値が等しくなることを検証すれば良い。これを、リファクタリング前記号実行サマリを表現する論理式と、リファクタリング後記号実行サマリを表現する論理式と、論理式NOT((a=a’)AND(b=b’)AND(v=v’))との論理積の式に対する充足可能性問題とおいて、SATソルバによって解くことで実現する。SATソルバによって解いた結果が充足不可能であれば、同じ入力の値を与えた場合に、リファクタリング前とリファクタリング後で異なる出力の値が得られることは無いことが分かるため、論理的に等価であると判定する。充足可能な場合は、同じ入力の値に対してリファクタリング前とリファクタリング後で異なる値が得られる場合が存在することを示している。この時、SATソルバが出力する充足可能な値の例を用いて、非等価である入力の値の例(反例)を得ることができる。ここで使用するSATソルバは一般に提供されているプログラムを使用する。
【0101】
この例においては両者の論理式が等価であるとの結果を得ることができる。この結果は、E101とE201のペアと、E102とE202のペアと、E103とE203のペアと、E104とE204のペアがそれぞれパス制約と変数状態が一致していることからも分かる。
【0102】
記号実行結果比較部1407は、SATソルバによって得られた等価という判定を、出力部1500に送る。このとき、リファクタリング前の記号実行木E100とリファクタリング後の記号実行木E200の間には構造上の差異が生じているが、記号実行の最終的な記号実行サマリが論理的に一致しているため。ソースコードが等価と判定する。
【0103】
次に、
図5の等価非等価出力S105のステップについて説明する。
出力部1500は、記号実行結果比較部1407が、ソースコードが等価と判定した結果を受けて、検証結果0004として、ソースコードが等価であることを出力する。出力部1500が出力する検証結果0004の例を
図20に示す。
【0104】
図20に示す表示例には、判定結果P200として記号実行により判定したこと、および、その結果等価と判定されたことを示している。また、構造比較に用いた構造グラフデータとして、正規化を実施した後のリファクタリング前正規化ソースコード情報の構造グラフP211とリファクタリング後正規化ソースコード情報の構造グラフP212を表示している。さらに、リファクタリング適用情報P220として、適用された正規化リファクタリングパターンが「該当無し」を表示している。構造グラフP211とP212においては、構造比較の結果、相違と判断されたノードに対して色を変化させることにより、ソースコード中のどの部分が構造比較の結果、等価でないと判断されたのかが分かるようになっている。また、構造グラフを比較表示することにより、どのように抽象化が実施されたのかが分かるようになっている。
【0105】
図20に示す表示例では、記号実行による判定に特有な情報として、リファクタリング前のソースコードに対する記号実行サマリ情報P230、および、リファクタリング後のソースコードに対する記号実行サマリ情報P231を表示している。記号実行サマリ情報P230およびP231では、それぞれE101、E102、E103、E104、および、E201、E202、E203、E204におけるパス制約および変数状態を一行ずつ表示している。これにより、開発者は記号実行の結果を知ることができ、かつ、どのような論理式を用いて等価性を判定したかを知ることができる。そして、これにより、ユーザは、リファクタリングが妥当なものであることを判断できる。
【0106】
図20に示す表示例は、記号実行により等価と判定された場合の表示例である。記号実行により非等価と判定された場合には、
図20に示す情報に加えて、反例情報も表示する。反例情報とは、SATソルバによって得られる、リファクタリング前の記号実行サマリとリファクタリング後の記号実行サマリとが等価でないような入力の例である。この反例情報を示すことにより、開発者はどのような入力に対してリファクタリング前のソースコードとリファクタリング後のソースコードとが異なる出力をするのかを知ることができる。これにより、不適切なリファクタリングとなっている原因を分析することが可能となる。
【0107】
本例では、記号実行実施判定S1047の判定で、ソースコード情報である構造グラフ上の構造の差異が認められることから、ソースコードが等価であることを検証するために、記号実行を実施している。ソースコード情報の抽象化を行い、ソースコード情報の縮減を行うことにより、記号実行処理では記号実行における計算量を削減することができる。
【実施例4】
【0108】
以下、上記の
図5を参照しながら、
図21乃至
図27を用いて本発明の一実施形態に係るソースコード等価性検証装置の処理の具体例について説明する。この例は、
図5の記号実行実施判定S1047の処理で、登録されたリファクタリングパターンに該当するリファクタリングが実施されたソースコードにおいて、ソースコード情報である構造グラフの構造が不一致であると判定される例である。
【0109】
図21は、リファクタリング前後のソースコードの例を示す図である(その三)。
図22は、リファクタリング前のソースコードに対応するソースコード情報の例を示す図である(その三)。
図23は、リファクタリング後のソースコードに対応するソースコード情報の例を示す図である(その三)。
図24は、正規化されたリファクタリング後のソースコード情報の例を示す図である。
図25は、抽象化されたソースコード情報の例を示す図である。
図26は、抽象化された場合における、リファクタリング前ソースコードとリファクタリング後ソースコードに対して記号実行したときの実行木を示した例である。
図27は、抽象化された場合における、表示部による等価性検証結果の表示例を示した図である。
【0110】
この例では、ソースコードに対するリファクタリングとして、リファクタリングパターンParameterizedMethodに基づいてリファクタリングが行われる場合について説明する。リファクタリングパターンParameterizedMethodは、複数箇所で似た処理をしているソースコードにおいて、その似た処理を関数として抜き出し、複数箇所で似た処理をしていた箇所を抜き出した関数への呼び出しに置き換えて、複数箇所に存在した似たソースコードを共通化するリファクタリングのパターンである。
【0111】
前記したExtractMethodでは同一の処理を抜き出すことを想定していたが、ParameterizedMethodは類似するが同一ではない処理を抜き出すことを想定している点で両者は異なる。ParameterizedMethodでは、類似はするが同一でない処理の抜き出しを実現するにあたり、抜き出した関数において、処理の差異の種別を示す引数を受取り、その引数に対する条件分岐で差異を実現する。抜き出された箇所では、抜き出した関数を、差異を示す引数を付けて呼び出すことにより、処理の差異を吸収する。
【0112】
図21では、リファクタリング前のソースコードC009とリファクタリング後のソースコードC010が示されている。ソースコードC009は、リファクタリングパターンParameterizedMethodの適用前のソースコードで、関数foo1は、グローバル変数aとグローバル変数bを加算してグローバル変数cに代入し、グローバル変数cを引数に関数barを呼び出すC011の部分と、グローバル変数cを引数に関数qux1を呼び出すC012の部分で構成され、関数foo2は、グローバル変数aとグローバル変数bを減算してグローバル変数cに代入し、グローバル変数cを引数に関数barを呼び出すC013の部分と、グローバル変数cを引数に関数qux2を呼び出すC014の部分で構成される。ソースコードC010は、リファクタリングパターンParametrizedMethod適用後のソースコードであり、ソースコードC009における関数foo1内の処理の一部であるC011と、類似した関数foo2内の処理の一部であるC013の箇所を関数bazとして抜き出し、抜き出した箇所に対応する位置であるC015とC017において関数bazへの呼び出しに置き換えている。抜き出した関数bazではC019に示す処理部分において、関数foo1のC011と関数foo2のC013の差異である、グローバル変数aとグローバル変数bへの加算処理と減算処理とを、真偽値を取る引数に対する条件分岐で振り分けることによって対応している。
【0113】
図21に示したリファクタリングの例における、
図5のリファクタリング前ソースコード入力S101とリファクタリング後ソースコード入力S102について説明する。このリファクタリングの例では、リファクタリング前ソースコード0001がソースコードC009、リファクタリング後ソースコード0002がソースコードC010に対応する。入力部1100では、ソースコード入力部1101によって、リファクタリング前ソースコード0001とリファクタリング後ソースコード0002を受け付けて、対応するリファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002を生成する。
【0114】
図21のリファクタリングの例において、ソースコード入力部1101がリファクタリング前ソースコード0001としてソースコードC009を受け付け、字句解析と構文解析を行い、リファクタリング前ソースコード情報1001として
図22の構造グラフM017に変換する。また、ソースコード入力部1101は、リファクタリング後ソースコード0002としてソースコードC010を受け付け、字句解析と構文解析を行い、リファクタリング後ソースコード情報1002として
図23の構造グラフM018に変換する。ここで、リファクタリング前ソースコード情報1001は構造グラフM017、リファクタリング後ソースコード情報1002は構造グラフM018に対応する。
【0115】
次に、リファクタリングパターンに関する情報を入力するS103のステップについて説明する。
入力部1100では、リファクタリングパターン入力部1102において、リファクタリングパターン入力情報0003を受け付けて、リファクタリングパターン情報1003を生成する。この例では、例えば、リファクタリングパターン入力情報0003が、リファクタリングパターンParameterizedMethodを表す文字列“ParameterizedMethod”や、画面のメニューでの選択番号の場合に、リファクタリングパターン登録情報1120を参照して、内部で、リファクタリングパターンParameterizedMethodを指し示すコードであるリファクタリングパターン情報1003を生成する。
【0116】
次に、
図5の変更箇所特定S1041のステップについて説明する。
正規化部1200の変更箇所特定部1201において、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002とリファクタリングパターン情報1003から、正規化DB1601に登録してある対応する変更箇所特定情報1007bを参照し、ソースコード上のどこを変更したのかを特定し、変更箇所情報1004を出力する。このリファクタリングパターンParameterizedMethodの例では、リファクタリングパターンParameterizedMethodは、リファクタリング後ソースコード情報1002において関数が増加するという特徴から、リファクタリング前ソースコード情報1001とリファクタリング後ソースコード情報1002の関数の宣言を比較し、リファクタリング後ソースコード情報1002にのみ現れる関数宣言ノードを変更箇所情報として特定する。また、リファクタリング後ソースコード情報1002にのみ現れる関数を呼び出すノードも変更箇所情報1004とする。
図22と
図23では、リファクタリング前ソースコード情報1001の構造グラフM017とリファクタリング後ソースコード情報1002の構造グラフM018の中で、関数を示すentryノードを比較し、ノードM019が指し示すentryノードの関数bazが増えていることから、ノードM019が変更箇所情報1004に該当する。さらに、関数bazを呼び出すノードM020とM021も、変更箇所情報1004に該当する。
【0117】
次に、
図5のソースコード情報正規化S1042のステップについて説明する。正規化部1200のソースコード正規化部1202において、変更箇所情報1004とリファクタリング前ソースコード情報1001から、正規化DB1601の中にある対応する正規化情報1007aを用いて正規化を行い、リファクタリング前正規化ソースコード情報1005を生成する。リファクタリング後ソースコード情報1002も同様に正規化を行い、リファクタリング後正規化ソースコード情報1006を生成する。リファクタリングパターン情報1003であるリファクタリングパターンParameterizedMethodに対応する正規化情報1007aによれば、正規化方法は、リファクタリング後ソースコード情報0002に対して、変更箇所1004で識別している抜き出した関数を、インライン展開したときのソースコードを表す構造にすることである。リファクタリング後ソースコード情報1002に対してソースコード正規化部1202で正規化を行った例を示すと、
図24のようになる。
【0118】
図24における変更箇所は、リファクタリング後ソースコード情報1002の構造グラフM018におけるノードM019とノードM020とノードM021であり、これらのノードは、リファクタリングによって抜き出された関数bazの宣言および呼び出し箇所であるので、その関数bazを正規化してインライン展開すると、構造グラフM022のようになる。これがリファクタリング後正規化ソースコード情報1006となる。リファクタリング前正規化ソースコード情報1005は、リファクタリングパターンParameterizedMethodに関して正規化処理が無いため、リファクタリング前ソースコード情報1001の構造グラフM017は正規化では何も変更されずに、リファクタリング前正規化ソースコード情報1005となる。
【0119】
次に、
図5の構造比較S1043のステップについて説明する。
構造比較検証処理部1300では、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006を受け取り、ソースコード情報の構造の比較を行い、その結果を構造比較結果1008として生成する。リファクタリングパターンParameterizedMethodによるリファクタリングを行った
図21の例において、構造比較検証処理部1300は、リファクタリング前正規化ソースコード情報1005のグラフM017とリファクタリング後正規化ソースコード情報1006のグラフM022の二つのグラフを比較し、明らかにグラフ構造が異なるため、構造比較結果1008を、リファクタリング前後のソースコードが構造不一致による非等価と判定する。
【0120】
次に、
図5の記号実行実施判定ステップS1047について説明する。
記号実行実施判定部1700は、このリファクタリングの例において、構造比較結果1008として、ソースコードが非等価と判定されため、記号実行開始指示1009のコマンドを生成する。
【0121】
次に、
図5のソースコード情報抽象化ステップS1044について説明する。
記号実行検証処理部1400は、記号実行開始指示1009を受け取ると、抽象化部1401において、変更箇所情報1004と抽象化DB1602の抽象化方法を記録した抽象化情報1010を用いて、リファクタリング前正規化ソースコード情報1005とリファクタリング後正規化ソースコード情報1006の抽象化を行う。抽象化DB1602の抽象化情報1010には、リファクタリングパターン情報1003と変更箇所情報1004に対応して適切な抽象化手法が記録されている。リファクタリングパターン情報1003がリファクタリングパターンParameterizedMethodeである例では、抽象化DB1602から、リファクタリング前正規化ソースコード情報1005であるグラフM017とリファクタリング後正規化ソースコード情報1006であるグラフM022を比較して、同じグラフ構造を持つ箇所をすべて削除することを記載した抽象化情報1010を取得する。抽象化部1401において、リファクタリング前正規化ソースコード情報1005であるグラフM017とリファクタリング後正規化ソースコード情報1006であるグラフM022に対して、抽象化情報1010を適用した結果を示すと、
図25のようになる。リファクタリング前正規化ソースコード情報1005であるグラフM017の関数foo1を示すグラフとリファクタリング後正規化ソースコード情報1006であるグラフM022の関数foo1を示すグラフを比較すると、関数barを呼び出すグラフM017のノードM023とグラフM022のノードM025が一致し、関数quxを呼び出すグラフM017のノードM024とグラフM022のノードM026が一致するため、これらのノードを削除し、関数foo2に関しても同様に同じグラフ構造を持つ箇所をすべて削除すると、リファクタリング前正規化ソースコード情報1005であるグラフM017はグラフM027のように抽象化され、リファクタリング後正規化ソースコード情報1006であるグラフM022はグラフM028のように抽象化される。グラフM027はリファクタリング前抽象化ソースコード情報1403に、グラフM028はリファクタリング後抽象化ソースコード情報1404に該当する。ここで、この抽象化は、グラフM017、M022の各々において、ノード数が減少しており、各々のグラフが記号実行されたときには、その計算量が減ることに留意する。
【0122】
次に、
図5の記号実行S1045のステップについて説明する。
記号実行検証処理部1400では、抽象化部1401において抽象化を行った後、リファクタリング前抽象化ソースコード情報1403とリファクタリング後抽象化ソースコード情報1404のそれぞれに対して、記号実行部1402において、記号実行を実施し、その結果としてリファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406を生成する。このリファクタリングの例において、記号実行部1402にて、前記リファクタリング前抽象化ソースコード情報1403とリファクタリング後抽象化ソースコード情報1404のそれぞれの関数foo1を記号実行した結果は、
図26に示されるようになる。このリファクタリングの例では、リファクタリング前抽象化ソースコード情報1403は、
図25の構造グラフM027に該当する。構造グラフM027に対して記号実行を行うと、
図26における実行木E300ができる。また、
図26の実行木E300における記号実行サマリであるE301が、リファクタリング前抽象化ソースコード情報1403に対するリファクタリング前記号実行結果1405となる。リファクタリング後抽象化ソースコード情報1404は、
図21のリファクタリングの例では、
図25の構造グラフM028に該当し、構造グラフM028に対して記号実行を行うと、
図26における実行木E400ができる。また、
図26の実行木E400における記号実行サマリであるE401,E402が、リファクタリング後抽象化ソースコード情報1404に対するリファクタリング後記号実行結果1406となる。関数foo2に関しても、記号実行部1402ではリファクタリング前抽象化ソースコード情報1403と、リファクタリング後抽象化ソースコード情報1404に対して、それぞれ同様に記号実行を行う。リファクタリング前抽象化ソースコード情報1403に対して実行木E350を生成し、実行木E350における記号実行サマリであるE351が、リファクタリング前記号実行結果1405となる。リファクタリング後抽象化ソースコード情報1404に対しては実行木E450を生成し、その記号実行サマリであるE451およびE452がリファクタリング後記号実行結果1406となる。
【0123】
次に、
図5の記号実行結果比較S1046のステップについて説明する。
記号実行検証処理部1400の記号実行結果比較部1407では、リファクタリング前記号実行結果1405とリファクタリング後記号実行結果1406の比較を行い、リファクタリング前後のソースコードが等価か非等価かの判定を行う。
図21のリファクタリングの例では、関数foo1に対するリファクタリング前記号実行結果1405は、E301であり、リファクタリング後記号実行結果1406は、E401,E402である。これらの二つの記号実行結果をSATソルバを用いて比較することにより、記号実行結果比較部1407は、関数foo1についてソースコードが等価と判定する。この例においては、E402のパス制約が矛盾式であるためE402が存在しないと考えても良いこと、および、E301とE401の変数状態が一致し、パス制約がどちらも恒真式であることからも、記号実行サマリが等価であることが分かる。このとき、リファクタリング前の記号実行木E300とリファクタリング後の記号実行木E400の間には構造上の差異が生じているが、記号実行の最終的な記号実行サマリが論理的に等価であるため。ソースコードを等価と判定する。記号実行結果比較部1407では、関数foo2についても同様にして比較を行い、等価と判定する。関数foo2に対する記号実行サマリが等価であることは、E451のパス制約が矛盾式であるためE451が存在しないと考えても良いこと、および、E351とE452の変数状態が一致し、パス制約がどちらも恒等式であることからも分かる。記号実行比較部は判定した結果を出力部1500に送る。
【0124】
次に、
図5の等価非等価出力S105のステップについて説明する。
出力部1500は、記号実行結果比較部1407が、ソースコードが等価と判定した結果を受けて、検証結果0004として、ソースコードが等価であることを出力する。出力部1500が出力する検証結果0004の例を
図27に示す。
【0125】
図27に示す表示例には、判定結果P300として記号実行により判定したこと、および、その結果等価と判定されたことを示している。また、構造比較に用いた構造グラフデータとして、正規化を実施した後のリファクタリング前正規化ソースコード情報1005の構造グラフP311とリファクタリング後正規化ソースコード情報1006の構造グラフP312を表示している。構造グラフP311とP312においては、構造比較の結果、相違と判断されたノードに対して色を変化させることにより、ソースコード中のどの部分が構造比較の結果、等価でないと判断されたのかが分かるようになっている。また、構造グラフを見ることにより、どのように正規化が実施されたのかが分かるようになっている。
【0126】
図27では、さらに、リファクタリング適用情報P320として、適用された正規化リファクタリングパターンである「Parameterized Method」と、対象関数名の情報としてbazを、適用箇所情報としてリファクタリング適用前後それぞれについてリファクタリングが適用されているファイル名と行番号を表示している。これにより、開発者は等価性検証装置が処理したリファクタリングパターンおよび適用箇所が意図した結果と一致しているかどうかを確認することができる。
【0127】
図27に示す表示例では、記号実行による判定に特有な情報として、リファクタリング前のソースコードに対する記号実行サマリ情報P330、および、リファクタリング後のソースコードに対する記号実行サマリ情報P331を表示している。記号実行サマリ情報P330およびP331では、それぞれE301、E351、および、E401、E402、E451、E452におけるパス制約および変数状態を一行ずつ表示している。これにより、開発者は記号実行の結果を知ることができ、かつ、どのような論理式を用いて等価性を判定したかを知ることができる。そして、これにより、ユーザは、リファクタリングが妥当なものであることを判断できる。
【0128】
図27に示す表示例は、記号実行により等価と判定された場合の表示例である。記号実行により非等価と判定された場合には、
図27に示す情報に加えて、反例情報も表示する。反例情報とは、SATソルバによって得られる、リファクタリング前の記号実行サマリとリファクタリング後の記号実行サマリとが等価でないような入力の例である。この反例情報を示すことにより、開発者はどのような入力に対してリファクタリング前のソースコードとリファクタリング後のソースコードとが異なる出力をするのかを知ることができる。これにより、不適切なリファクタリングとなっている原因を分析することが可能となる。
【0129】
本例では、S1047の判定で、ソースコード情報である構造グラフ上の構造の差異を生じるため、ソースコードが等価であることを検証するために、記号実行する必要があるが、ソースコード情報の抽象化を行い、ソースコード情報の縮減を行うために、記号実行における計算量を削減することができる。
【符号の説明】
【0130】
0001…リファクタリング前ソースコード
0002…リファクタリング後ソースコード
0003…リファクタリングパターン
0004…検証結果
101…CPU
102…主記憶装置
103…ネットワークI/F
104…グラフィックI/F
105…入出力I/F
106…補助記憶装置I/F
110…制御部
120…表示・出力装置
130…入力装置
131…キーボード
132…マウス
141…HDD(Hard Disk Drive)
142…DVDドライブ装置
150…外部ネットワーク
160…外部計算機
200…ソースコード等価性検証プログラム
1000…ソースコード等価性検証装置
1100…入力部
1120…リファクタリングパターン登録情報
1200…正規化部
1300…構造比較検証処理部
1400…記号実行検証処理部
1500…出力部
1600…記憶部
1601…正規化データベース
1602…抽象化データベース
1603…リファクタリング前/後ソースコード記憶領域
1604…リファクタリング前/後ソースコード情報記憶領域
1605…リファクタリング前/後記号実行結果記憶領域
1606…検証結果記憶領域
1700…記号実行実施判定部
1001…リファクタリング前ソースコード情報
1002…リファクタリング後ソースコード情報
1003…リファクタリングパターン情報
1004…変更箇所情報
1005…リファクタリング前正規化ソースコード情報
1006…リファクタリング後正規化ソースコード情報
1007a…正規化情報
1007b…変更箇所特定情報
1008…構造比較結果
1009…記号実行開始指示
1010…抽象化情報
1101…ソースコード入力部
1102…リファクタリングパターン入力部
1201…変更箇所特定部
1202…ソースコード正規化部
1401…抽象化部
1402…記号実行部
1403…リファクタリング前抽象化ソースコード情報
1404…リファクタリング後抽象化ソースコード情報
1405…リファクタリング前記号実行結果
1406…リファクタリング後記号実行結果
1407…記号実行結果比較部
1601…正規化データベース
1602…抽象化データベース
S101…リファクタリング前ソースコード入力ステップ
S102…リファクタリング後ソースコード入力ステップ
S103…リファクタリングパターン入力情報入力ステップ
S1041…変更箇所特定ステップ
S1042…ソースコード正規化ステップ
S1043…構造比較ステップ
S1044…ソースコード抽象化ステップ
S1045…記号実行ステップ
S1046…記号実行結果比較ステップ
S1047…記号実行実施判定ステップ
S105…等価非等価出力ステップ
C001…リファクタリング適用前のソースコード
C002…リファクタリング適用後のソースコード
C003…リファクタリング適用前のソースコード
C004…リファクタリング適用後のソースコード
C005…C003における関数foo内のソースコードの前半部
C006…C003における関数foo内のソースコードの後半部
C007…C004における関数foo内のソースコードの前半部
C008…C004における関数foo内のソースコードの後半部
C009…リファクタリング適用前のソースコード
C010…リファクタリング適用後のソースコード
C011…C009における関数foo1内のソースコードの前半部
C012…C009における関数foo1内のソースコードの後半部
C013…C009における関数foo2内のソースコードの前半部
C014…C009における関数foo2内のソースコードの後半部
C015…C010における関数foo1内のソースコードの前半部
C016…C010における関数foo1内のソースコードの後半部
C017…C010における関数foo2内のソースコードの前半部
C018…C010における関数foo2内のソースコードの後半部
C019…C010における関数baz内のソースコードの前半部
C020…C010における関数baz内のソースコードの後半部
E001…記号実行を説明するためのソースコード
E002…ソースコードの構造グラフ
E003…構造グラフにおける関数fooのエントリーを示すノード
E004…構造グラフにおけるE003の遷移先のノード
E005…構造グラフにおけるE004の遷移先のノード
E006…構造グラフにおけるE005の分岐先のノード
E007…構造グラフにおけるE005の分岐先のノード
E008…構造グラフにおけるE006と7の遷移先のノード
E009a…構造グラフにおけるE008の分岐先のノード
E009b…構造グラフにおけるE008の分岐先のノード
E010…E003に対応する実行木ノード
E010a…E010のパス制約
E010b…E010の変数状態
E011…E004に対応する実行木ノード
E011a…E011のパス制約
E011b…E011の変数状態
E012…E006に対応する実行木ノード
E012a…E012のパス制約
E012b…E012の変数状態
E013…E007に対応する実行木ノード
E013a…E013のパス制約
E013b…E013の変数状態
E014…E006を経由した場合のE009に対応する実行木ノード
E015…E006を経由した場合のE009aに対応する実行木ノード
E016…E007を経由した場合のE009に対応する実行木ノード
E017…E007を経由した場合のE009aに対応する実行木ノード
E020…記号実行の実行木
E100…リファクタリング適用前のソースコード情報の記号実行の実行木
E101…E100における記号実行サマリに含まれるノード
E102…E100における記号実行サマリに含まれるノード
E103…E100における記号実行サマリに含まれるノード
E104…E100における記号実行サマリに含まれるノード
E200…リファクタリング適用後のソースコード情報の記号実行の実行木
E201…E200における記号実行サマリに含まれるノード
E202…E200における記号実行サマリに含まれるノード
E203…E200における記号実行サマリに含まれるノード
E204…E200における記号実行サマリに含まれるノード
E300…リファクタリング適用前の関数foo1の抽象化ソースコード情報に対する記号実行の実行木
E301…E300における記号実行サマリに含まれるノード
E350…リファクタリング適用前の関数foo2の抽象化ソースコード情報に対する記号実行の実行木
E351…E350における記号実行サマリに含まれるノード
E400…リファクタリング適用後の関数foo1の抽象化ソースコード情報に対する記号実行の実行木
E401…E400における記号実行サマリに含まれるノード
E402…E400における記号実行サマリに含まれるノード
E450…リファクタリング適用後の関数foo2の抽象化ソースコード情報に対する記号実行の実行木
E451…E450における記号実行サマリに含まれるノード
E452…E450における記号実行サマリに含まれるノード
M001…リファクタリング適用前のソースコードの構造グラフ
M002…リファクタリング適用後のソースコードの構造グラフ
M003…リファクタリングによって追加された関数を示すノード
M004…リファクタリングによって追加された関数を呼び出すノード
M005…リファクタリング適用前のソースコード情報の正規化済みの構造グラフ
M006…リファクタリング適用後のソースコード情報の正規化済みの構造グラフ
M007…正規化によって関数が展開された結果のリンク
M008…リファクタリング適用前のソースコードの構造グラフ
M009…リファクタリング適用後のソースコードの構造グラフ
M010…M008における関数varを示すノード
M011…M008における関数varを呼び出すノード
M012…M009における関数varを示すノード
M013…M009における関数varを呼び出すノード
M014…リファクタリング適用前のソースコード情報の抽象化済みの構造グラフ
M015…リファクタリング適用後のソースコード情報の抽象化済みの構造グラフ
M016…M014における抽象化された箇所を示すノード
M017…リファクタリング適用前のソースコードの構造グラフ
M018…リファクタリング適用後のソースコードの構造グラフ
M019…リファクタリングによって追加された関数を示すノード
M020…リファクタリングによって追加された関数を呼び出すノード
M021…リファクタリングによって追加された関数を呼び出すノード
M022…リファクタリング適用後のソースコード情報の正規化済みの構造グラフ
M023…M017における関数barを呼び出すノード
M024…M017における関数qux1を呼び出すノード
M025…M022における関数barを呼び出すノード
M026…M022における関数qux1を呼び出すノード
P100…C001とC002に対する等価性検証の検証結果表示における判定結果
P111…C001とC002に対する等価性検証の検証結果表示におけるC001の正規化済みの構造グラフ
P112…C001とC002に対する等価性検証の検証結果表示におけるC002の正規化済みの構造グラフ
P120…C001とC002に対する等価性検証の検証結果表示におけるリファクタリング適用情報
P200…C003とC004に対する等価性検証の検証結果表示における判定結果
P211…C003とC004に対する等価性検証の検証結果表示におけるC003の正規化済みの構造グラフ
P212…C003とC004に対する等価性検証の検証結果表示におけるC004の正規化済みの構造グラフ
P220…C003とC004に対する等価性検証の検証結果表示におけるリファクタリング適用情報
P230…C003とC004に対する等価性検証の検証結果表示におけるC003の記号実行サマリ表示
P231…C003とC004に対する等価性検証の検証結果表示におけるC004の記号実行サマリ表示
P300…C009とC010に対する等価性検証の検証結果表示における判定結果
P311…C009とC010に対する等価性検証の検証結果表示におけるC009の正規化済みの構造グラフ
P312…C009とC010に対する等価性検証の検証結果表示におけるC010の正規化済みの構造グラフ
P320…C009とC010に対する等価性検証の検証結果表示におけるリファクタリング適用情報
P330…C009とC010に対する等価性検証の検証結果表示におけるC009の記号実行サマリ表示
P331…C009とC010に対する等価性検証の検証結果表示におけるC010の記号実行サマリ表示