(57)【要約】【課題】リファクタリングを行った際の振舞いの誤検知を防止できる解析装置、解析プログラムおよび解析方法を提供する。【解決手段】解析装置は、解析部と、変換部と、縮約部と、比較部とを有する。解析部は、比較対象の２つのソースコードを取得し、取得したソースコード毎に解析して２つのソースコードの抽象構文木を生成する。変換部は、生成した抽象構文木に基づき、２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する。縮約部は、所定のルールに基づき、グラフ化された２つのソースコードにおける各グラフの冗長部分を縮約する。比較部は、縮約された各グラフを比較して２つのソースコードの差異を出力する。【選択図】図１
2019003385.tif 000002
【特許請求の範囲】
【請求項１】
比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成する解析部と、
生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する変換部と、
所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約する縮約部と、
縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する比較部と
を有することを特徴とする解析装置。
【請求項２】
前記変換部は、
前記処理に対応する第１ノードと、前記データの参照に対応する第２ノードと、前記データの設定に対応する第３ノードとの接続関係を示す３部グラフに変換する
ことを特徴とする請求項１に記載の解析装置。
【請求項３】
グラフ化された前記２つのソースコードにおける前記各グラフの部分グラフを結合して、所定のメソッドの定義の部分グラフを生成する結合部をさらに備える、
ことを特徴とする請求項１または２に記載の解析装置。
【請求項４】
縮約された前記各グラフに基づいてハッシュ値を算出する算出部をさらに備え、
前記比較部は、
前記各グラフの前記ハッシュ値を比較して前記差異を出力する
ことを特徴とする請求項１〜３のいずれか一項に記載の解析装置。
【請求項５】
前記算出部は、
前記各グラフを前記処理の流れおよび前記データの流れの方向とは逆向きに辿って前記ハッシュ値を算出する
ことを特徴とする請求項４に記載の解析装置。
【請求項６】
前記比較部は、
算出された前記ハッシュ値同士が一致する場合に、前記２つのソースコードの前記差異が無いことを示す情報を出力する
ことを特徴とする請求項４または５に記載の解析装置。
【請求項７】
コンピュータに、
比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成し、
生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化し、
所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約し、
縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する
処理を実行させることを特徴とする解析プログラム。
【請求項８】
コンピュータが、
比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成し、
生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化し、
所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約し、
縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する
処理を実行することを特徴とする解析方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明の実施形態は、解析装置、解析プログラムおよび解析方法に関する。
【背景技術】
【０００２】
従来、例えばソフトウェア開発等において、プログラムの更新を行った際に、プログラムの振舞いの等価性を比較するために、変更前および変更後のソースコードを解析する解析装置がある。
【０００３】
ソースコードを解析する手法として、変更前および変更後のソースコードの文字列を一定の単位毎に比較し、比較結果に基づいて２つのソースコードの等価性を判定する技術が提案されている。
【先行技術文献】
【特許文献】
【０００４】
【特許文献１】特開２０１４−１０６９９号公報
【発明の概要】
【発明が解決しようとする課題】
【０００５】
しかしながら、上述した従来技術では、例えば、プログラムの振舞いを変えないソースコードの変更、いわゆるリファクタリングを行った際に、プログラムの振舞いが変わったと誤検知する場合がある、という問題がある。
【０００６】
１つの側面では、リファクタリングを行った際の振舞いの誤検知を防止できる解析装置、解析プログラムおよび解析方法を提供することを目的とする。
【０００７】
一つの態様では、解析装置は、解析部と、変換部と、縮約部と、比較部とを有する。前記解析部は、比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成する。前記変換部は、生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する。前記縮約部は、所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約する。前記比較部は、縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する。
【発明の効果】
【０００８】
本発明の１実施形態によれば、リファクタリングを行った際の振舞いの誤検知を防止できる。
【図面の簡単な説明】
【０００９】
【図１】図１は、実施例に係る解析装置の構成を示す機能ブロック図である。
【図２】図２は、解析処理を説明する説明図である。
【図３】図３は、変換処理を説明する説明図である。
【図４】図４は、３部グラフテーブルの一例を示す図である。
【図５】図５は、３部グラフテーブルの一例を示す図である。
【図６】図６は、３部グラフテーブルの一例を示す図である。
【図７】図７は、結合処理を説明する説明図である。
【図８】図８は、縮約処理を説明する説明図である。
【図９】図９は、縮約処理を説明する説明図である。
【図１０】図１０は、縮約処理を説明する説明図である。
【図１１】図１１は、算出処理を説明する説明図である。
【図１２】図１２は、実施形態に係る解析装置が実行する全体処理を例示するフローチャートである。
【図１３】図１３は、変換処理を例示するフローチャートである。
【図１４】図１４は、第１処理（ＭＤ）を例示するフローチャートである。
【図１５】図１５は、第２処理（ＰＳ）を例示するフローチャートである。
【図１６】図１６は、第３処理（Ｂ）を例示するフローチャートである。
【図１７】図１７は、第４処理（ＬＶＤ）を例示するフローチャートである。
【図１８】図１８は、第５処理（ＲＳ）を例示するフローチャートである。
【図１９】図１９は、第６処理（ＭＩＸ）を例示するフローチャートである。
【図２０】図２０は、第７処理（Ｘ）を例示するフローチャートである。
【図２１】図２１は、結合処理を例示するフローチャートである。
【図２２】図２２は、縮約処理を例示するフローチャートである。
【図２３】図２３は、第１処理（ルール適用）を例示するフローチャートである。
【図２４】図２４は、ノードスキップ処理を例示するフローチャートである。
【図２５】図２５は、算出処理を例示するフローチャートである。
【図２６】図２６は、解析プログラムを実行するコンピュータを示す図である。
【発明を実施するための形態】
【００１０】
以下に、本願の開示する解析装置、解析プログラムおよび解析方法の実施例を図面に基づいて詳細に説明する。なお、この実施例によりこの発明が限定されるものではない。
【実施例】
【００１１】
図１は、実施例に係る解析装置１の構成を示す機能ブロック図である。図１に示すように、この解析装置１は、受付部１１と、解析部１２と、変換部１３と、結合部１４と、縮約部１５と、算出部１６と、比較部１７と、ソースコードファイル群格納部１１１と、抽象構文木格納部１１２と、３部グラフ格納部１１３と、結合グラフ格納部１１４と、縮約グラフ格納部１１５と、ハッシュ値格納部１１６とを有する。
【００１２】
受付部１１は、比較対象となる２つのソースコードＳＣａ，ＳＣｂを受け付け、ソースコードファイル群格納部１１１に格納する。ソースコードＳＣａ，ＳＣｂは、Ｊａｖａ（登録商標）やＣ言語といったプログラミング言語の言語仕様に従って書かれたテキストファイルである。なお、以下では、ＪａｖａにおけるソースコードＳＣａ，ＳＣｂを一例に挙げて説明することとする。
【００１３】
また、２つのソースコードＳＣａ，ＳＣｂの関係としては、例えば、リビジョンの異なるソースコードである。より具体的には、２つのソースコードＳＣａ，ＳＣｂは、リファクタリング前後のソースコードである。なお、２つのソースコードＳＣａ，ＳＣｂをまとめてソースコードＳＣと記載する場合がある。
【００１４】
解析部１２は、比較対象の２つのソースコードＳＣａ，ＳＣｂを取得し、取得したソースコードＳＣａ，ＳＣｂ毎に解析して、解析結果を抽象構文木格納部１１２に格納する。なお、解析部１２は、２つのソースコードＳＣａ，ＳＣｂを受付部１１から直接取得してもよく、ソースコードファイル群格納部１１１から取得してもよい。ここで、図２を用いて、解析部１２の解析処理について具体的に説明する。
【００１５】
図２は、解析処理を説明する説明図である。図２には、ＪａｖａにおけるソースコードＳＣａおよびＪａｖａの構文規則ＳＲを示している。図２に示すように、解析部１２は、ソースコードＳＣを構文規則ＳＲに従って解析して抽象構文木ＡＳＴを生成する。なお、図２には、抽象構文木ＡＳＴの主な要素のみを示している。また、図２には、比較対象の２つのソースコードＳＣａ、ＳＣｂのうち一方のソースコードＳＣａを示しており、他方のソースコードＳＣｂについては、図７で説明する。
【００１６】
また、図２に示すソースコードＳＣや構文規則ＳＲは、一例であり、これに限定されるものではなく、より複雑なソースコードＳＣであってもよく、また、他の構文規則ＳＲであってもよい。
【００１７】
図１に戻って、変換部１３について説明する。変換部１３は、生成した抽象構文木ＡＳＴに基づき、２つのソースコードＳＣａ，ＳＣｂにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する。変換部１３は、例えば抽象構文木格納部１１２から抽象構文木ＡＳＴを取得し、生成したグラフのデータを３部グラフ格納部１１３に格納する。
【００１８】
ここで、図３を用いて、変換部１３の変換処理について具体的に説明する。図３は、変換処理を説明する説明図である。図３に示すように、変換部１３は、生成した抽象構文木ＡＳＴを３部グラフ１３０に変換する。
【００１９】
ここで、３部グラフ１３０は、第１ノードｎ１（以下、主ノードｎ１と記載する場合がある）と、第２ノードｎ２（以下、端子ｎ２と記載する場合がある）と、第３ノードｎ３（以下、端子ｎ３と記載する場合がある）と、エッジｅとを有する。
【００２０】
第１ノードｎ１は、ソースコードＳＣのメソッド内およびメソッド間の処理に対応する。なお、図３では、各主ノードｎ１を矩形状で示すとともに、矩形内にクラスを示す。また、図３に示す各主ノードｎ１のクラスについては、図６で後述する。
【００２１】
第２ノードｎ２は、ソースコードＳＣにおけるデータの参照に対応する。第２ノードｎ２は、例えば、メソッド呼び出しの戻り値、ローカル変数の参照値、メソッド処理内容の定義で引き渡されるパラメータの値、処理を行ったあとの環境等が設定される。図３では、第２ノードｎ２を、円形状で示すとともに、円形内に正の値「１」または「２」を示す。正の値「１」は、環境を示し、「２」は、パラメータを示す。
【００２２】
第３ノードｎ３は、ソースコードＳＣにおけるデータの設定、更新に対応する。第３ノードｎ３は、例えば、メソッド呼び出し時に引き渡すパラメータの値、ローカル変数の設定値、定義したメソッドの処理内容の実行の結果返される戻り値、直前の処理を行ったあとの環境等が設定される。図３では、第３ノードｎ３を、円形状で示すとともに、円形内に負の値「―１」または「―２」を示す。負の値「―１」は、環境を示し、「―２」は、パラメータを示す。
【００２３】
エッジｅは、処理の実行順序を示す。図３では、エッジｅを矢印で示す。具体的には、エッジｅは、所定の主ノードｎ１（例えば、図３に示す「Ｄ申請」）の端子ｎ２と、かかる主ノードｎ１の次に実行される主ノードｎ１（例えば、図３に示す「ＢＮ」）の端子ｎ３とを接続する。また、図示していないが、エッジｅは、主ノードｎ１と各端子ｎ２、ｎ３とを接続する。
【００２４】
このように、３部グラフ１３０に変換することで、２つのソースコードＳＣａ、ＳＣｂを統一した条件化で比較できるようになるため、比較結果から差異を検出する際の精度を向上させることができる。
【００２５】
変換部１３は、変換した３部グラフ１３０の情報を３部グラフ格納部１１３に格納する。ここで、図４〜図６を用いて、３部グラフ格納部１１３に格納される３部グラフ１３０のデータ構造を示す３部グラフテーブルについて説明する。
【００２６】
図４〜図６は、３部グラフテーブルの一例を示す図である。図４には、第１〜第３ノードｎ１〜ｎ３の情報であるノードテーブルを示す。図５には、エッジｅの情報であるエッジテーブルを示す。図６には、第１ノードｎ１のクラスに関する情報であるクラステーブルを示す。
【００２７】
図４に示すように、ノードテーブルは、「ＩＤ」、「格納位置」、「ノード種類」、「クラス」、「属性」といった項目を有する。「ＩＤ」は、各ノードを識別する識別情報である。「格納位置」は、対応するソースコードＳＣが格納された位置を示す。「ノード種類」は、第１〜第３ノードｎ１〜ｎ３のいずれであるかを示す。「クラス」は、第１ノードｎ１のクラスを示す。「属性」は、データの属性を示す。
【００２８】
例えば、図４に示すように、ＩＤが「１１」のノードは、第１ノードｎ１であり、クラスが「Ｄ」であり、属性が「申請」である。また、ＩＤが「１」のノードに対応するソースコードＳＣは、「／ｓｒｃ／ｒｅｖ．１／」に格納されている。
【００２９】
また、図５に示すように、エッジテーブルは、「起点ＩＤ」、「終点ＩＤ」といった項目を含む。「起点ＩＤ」は、エッジｅの起点となるノードを識別する識別情報である（図３参照）「終点ＩＤ」は、エッジｅの終点となるノードを識別する識別情報である（図３参照）。
【００３０】
例えば、起点ＩＤが「１１」であり、終点ＩＤが「１２」であるエッジｅは、主ノードｎ１と端子ｎ２とを接続するエッジである。
【００３１】
また、図６に示すように、クラステーブルは、「名称」、「内容」といった項目を含む。「名称」は、各主ノードｎ１の名称を示す。「内容」は、各名称における主ノードｎ１の処理内容を示す。
【００３２】
例えば、名称が「Ｄ」の主ノードｎ１の処理内容は、「メソッドの処理内容の定義（Method  Definition）」であることを示している。例えば、図３に示す「Ｄ申請」は、処理内容が「申請」であることを示している。
【００３３】
次に、図１に戻って結合部１４について説明する。結合部１４は、変換部１３によってグラフ化された２つのソースコードＳＣａ、ＳＣｂにおける各グラフ（３部グラフ１３０）の部分グラフを結合して、所定のメソッドの定義の部分グラフを生成する。結合部１４は、例えば、受付部１１がユーザからメソッドの定義の指定を受け付け、指定されたメソッドの定義の部分グラフを生成する。
【００３４】
ここで、結合部１４による結合処理について説明する。図７は、結合処理を説明する説明図である。図７には、ソースコードＳＣｂおよびソースコードＳＣｂを変換して生成した３部グラフ１３０を示している。
【００３５】
また、図７に示すように、３部グラフ１３０は、部分グラフ１３０ａおよび部分グラフ１３０ｂを含む。部分グラフ１３０ａは、ソースコードＳＣｂにおけるメソッドＡを示すグラフであり、部分グラフ１３０ｂは、ソースコードＳＣｂにおけるメソッドＢを示すグラフである。
【００３６】
結合部１４は、部分グラフ１３０ａおよび部分グラフ１３０ｂをメソッドＡの定義について結合し、結合グラフ１４０を生成する。具体的には、結合部１４は、部分グラフ１３０ａの主ノードｎ１である「Ｃ抽出」を部分グラフ１３０ｂに置き換える。
【００３７】
より具体的には、結合部１４は、まず、部分グラフ１３０ａの主ノードｎａ１１である「Ｃ抽出」および対応する端子ｎａ２１、ｎａ３１と、部分グラフ１３０ｂの主ノードｎｂ１１である「Ｄ抽出」および対応する端子ｎｂ２１、ｎｂ３１とを削除する。
【００３８】
つづいて、結合部１４は、部分グラフ１３０ａの主ノードｎａ１２である「ＤＬｒ」の端子ｎａ２２と、部分グラフ１３０ｂの主ノードｎｂ１２である「ＢＮ」の端子ｎｂ３２とを接続する。
【００３９】
つづいて、結合部１４は、部分グラフ１３０ａの主ノードｎａ１３である「ＩＶ１」の端子ｎａ２３の「２」と、部分グラフ１３０ｂの主ノードｎｂ１３である「ＩＤ」の端子ｎｂ３３の「―２」とを接続する。
【００４０】
つづいて、結合部１４は、部分グラフ１３０ａの主ノードｎａ１４である「ＷＬｒ」の端子ｎａ３４の「―２」と、部分グラフ１３０ｂの主ノードｎｂ１４である「Ｃ処理」の端子ｎｂ２４の「２」とを接続する。
【００４１】
つづいて、結合部１４は、部分グラフ１３０ａの主ノードｎａ１４である「ＷＬｒ」の端子ｎａ３４の「―１」と、部分グラフ１３０ｂの主ノードｎｂ１５である「ＢＸ」の端子ｎｂ２５とを接続して、部分グラフ１３０ａ、１３０ｂが結合した結合グラフ１４０が完成する。
【００４２】
このように、注目しているメソッドＡについて部分グラフ１３０ａ、１３０ｂを結合することで、２つのソースコードＳＣａ、ＳＣｂの比較を容易に行うことができる。
【００４３】
図１に戻って、縮約部１５について説明する。縮約部１５は、所定のルールに基づき、グラフ化された２つのソースコードＳＣａ、ＳＣｂにおける各グラフ（３部グラフ１３０または結合グラフ１４０）の冗長部分を縮約する。
【００４４】
ここで、図８〜１０を用いて縮約部１５による縮約処理について具体的に説明する。図８〜１０は、縮約処理を説明する説明図である。図８〜１０では、結合部１４によって生成された結合グラフ１４０に対する縮約部１５の縮約処理について説明する。なお、縮約処理は、結合グラフ１４０に限らず、３部グラフ１３０や、部分グラフ１３０ａ、１３０ｂに対して行ってもよい。
【００４５】
図８〜１０に示すように、縮約部１５は、所定のルール０〜５に従って、縮約処理を行う。まず、縮約部１５は、結合グラフ１４０に対してルール０を適用して、主ノードｎ１ｆである「ＩＤ」および対応する端子ｎ２ｆ、ｎ３ｆを除去する。ルール０は、適用のための条件はなく、常に処理が行われる。
【００４６】
このとき、縮約部１５は、主ノードｎ１ｃである「ＩＶ１」の端子ｎ２ｃの「２」と、主ノードｎ１ｇである「Ｃ処理」の端子ｎ３ｇの「―２」とを接続する。これにより、縮約部１５は、ルール０を適用した縮約グラフ１５０ａを生成する。
【００４７】
つづいて、縮約部１５は、縮約グラフ１５０ａに対してルール１を適用して、主ノードｎ１ｊである「ＲＬｒ」の端子ｎ２ｊと、主ノードｎ１ｋである「Ｃ送信」の端子ｎ３ｋとを接続しているエッジを除去する。
【００４８】
ルール１の適用条件は、主ノードｎ１ｉである「ＷＬｒ」から「ＲＬｒ」に至るパス（ＲＬ（−１）←（１）ｆｎ，・・・，ｆ１（−１）←（１）ＷＬ）の中に、「ＲＬｒ」の属性をｒとし、ｆ１，・・・，ｆｎのうち対となる最も外側の「ＢＮ」，「ＢＸ」をｆ＿｛ｋＮ｝，ｆ＿｛ｋＸ｝として、∀ｉ＝１，・・・，ｋＮ，ｋＸ，・・・，ｎ：ｆｉが「ＷＬｒ」でも「ＤＬｒ」でも「Ｄ」でもないパス「ＷＬｒ（属性がｒ）」から対象主ノードｎ１ｊである「ＲＬｒ」へのパスが存在することである。なお、パスとは、複数の主ノードｆ１，・・・，ｆｎとした場合、ｆ１からｆｎの方向に接続された経路（パスｆｎ，・・・，ｆ１）を指す。
【００４９】
このとき、縮約部１５は、主ノードｎ１ｇである「Ｃ処理」の端子ｎ２ｇと、主ノードｎ１ｋである「Ｃ送信」の端子ｎ３ｋとを接続する。これにより、縮約部１５は、ルール１を適用した縮約グラフ１５０ｂを生成する。
【００５０】
つづいて、縮約部１５は、縮約グラフ１５０ｂに対してルール２を適用して、主ノードｎ１ｊである「ＲＬｒ」および対応する端子ｎ２ｆ、ｎ３ｆを除去する。ルール２の適用条件は、主ノードｎ１ｊである「ＲＬｒ」の端子ｎ２ｊ（円形内の数字が「２」の端子）から出るエッジがないことである。
【００５１】
このとき、縮約部１５は、主ノードｎ１ｉである「ＷＬｒ」の端子ｎ２ｉと、主ノードｎ１ｋである「Ｃ送信」の端子ｎ３ｋとを接続する。これにより、縮約部１５は、ルール２を適用した縮約グラフ１５０ｃを生成する。
【００５２】
つづいて、縮約部１５は、縮約グラフ１５０ｃに対してルール３を適用して、主ノードｎ１ｉである「ＷＬｒ」および対応する端子ｎ２ｉ、ｎ３ｉを除去する。
【００５３】
ルール３の適用条件は、主ノードｎ１ｉである「ＷＬｒ」から「Ｄ」に至るパス（Ｄ（−１）←（１）ｆｎ，・・・，ｆ１（−１）←（１）ＷＬ）の中に、「ＷＬｒ」の属性をｒとし、ｆ１，・・・，ｆｎのうち対となる最も外側の「ＢＮ」，「ＢＸ」をｆ＿｛ｋＮ｝，ｆ＿｛ｋＸ｝として、∃ｋＴ：ｆｋＴ＝ＢＮなら、∀ｉ＝ｋＴ，・・，ｋＮ，ｋＸ，・・・，ｎ：ｆｉが「ＲＬｒ」ではなく、そうでないなら∀ｉ＝１，・・・，ｋＮ，ｋＸ，・・・，ｎ：ｆｉが「ＲＬｒ」でも「Ｄ」でもないパスが存在することである。
【００５４】
このとき、縮約部１５は、主ノードｎ１ｈである「ＢＸ」の端子ｎ２ｈと、主ノードｎ１ｋである「Ｃ送信」の端子ｎ３ｋとを接続する。これにより、縮約部１５は、ルール３を適用した縮約グラフ１５０ｄを生成する。
【００５５】
つづいて、縮約部１５は、縮約グラフ１５０ｄに対してルール４を適用して、主ノードｎ１ｄである「ＤＬｒ」および対応する端子ｎ２ｄ、ｎ３ｄを除去する。
【００５６】
ルール４の適用条件は、主ノードｎ１ｄである「ＤＬｒ」から「Ｄ」に至るパス（Ｄ（−１）←（１）ｆｎ，・・・，ｆ１（−１）←（１）ＤＬ）の中に、「ＤＬｒ」の属性をｒとし、ｆ１，・・・，ｆｎのうち対となる最も外側の「ＢＮ」，「ＢＸ」をｆ＿｛ｋＮ｝，ｆ＿｛ｋＸ｝として、∃ｋＴ：ｆｋＴ＝ＢＮなら、∀ｉ＝ｋＴ，・・，ｋＮ，ｋＸ，・・・，ｎ：ｆｉが「ＷＬｒ」ではなく、そうでないなら∀ｉ＝１，・・・，ｋＮ，ｋＸ，・・・，ｎ：ｆｉが「ＷＬｒ」でも「Ｄ」でもないパスが存在することである。
【００５７】
このとき、縮約部１５は、主ノードｎ１ｃである「ＩＶ１」の端子ｎ２ｃと、主ノードｎ１ｅである「ＢＮ」の端子ｎ３ｅとを接続する。これにより、縮約部１５は、ルール４を適用した縮約グラフ１５０ｅを生成する。
【００５８】
つづいて、縮約部１５は、縮約グラフ１５０ｅに対してルール５を適用して、主ノードｎ１ｅである「ＢＮ」および対応する端子ｎ２ｅ、ｎ３ｅと、主ノードｎ１ｈである「ＢＸ」および対応する端子ｎ２ｈ、ｎ３ｈとを除去する。
【００５９】
ルール５の適用条件は、主ノードｎ１ｅである「ＢＮ」から「ＢＸ」に至るパス（ＢＸ（−１）←（１）ｆｎ，・・・，ｆ１（−１）←（１）ＢＮ）の中に、ｆ１，・・・，ｆｎのうち対となる「ＢＮ」，「ＢＸ」をｆ＿｛ｋＮ｝，ｆ＿｛ｋＸ｝として、∀ｉ＝１，・・・，ｋＮ，ｋＸ，・・・，ｎ：ｆｉが「Ｄ」、「ＲＬ」、「ＷＬ」、「ＤＬ」、「ＢＮ」、「ＢＸ」のいずれでもないパスが存在することである。
【００６０】
このとき、縮約部１５は、主ノードｎ１ｃである「ＩＶ１」の端子ｎ２ｃと、主ノードｎ１ｇである「Ｃ処理」の端子ｎ３ｇとを接続し、主ノードｎ１ｇである「Ｃ処理」の端子ｎ２ｇと、主ノードｎ１ｋである「Ｃ送信」の端子ｎ３ｋとを接続する。これにより、縮約部１５は、ルール５を適用した縮約グラフ１５０ｆを生成する。
【００６１】
さらに、縮約部１５は、縮約グラフ１５０ｆに対してルール５を適用して、主ノードｎ１ｂである「ＢＮ」および対応する端子ｎ２ｂ、ｎ３ｂと、主ノードｎ１ｌである「ＢＸ」および対応する端子ｎ２ｌ、ｎ３ｌとを除去する。
【００６２】
このとき、縮約部１５は、主ノードｎ１ａである「Ｄ申請」の端子ｎ２ａと、主ノードｎ１ｃである「ＩＶ１」の端子ｎ３ｃとを接続し、主ノードｎ１ｋである「Ｃ送信」の端子ｎ２ｋと、主ノードｎ１ａである「Ｄ申請」の端子ｎ３ａとを接続する。これにより、縮約部１５は、ルール５を適用した縮約グラフ１５０ｇを生成する。
【００６３】
図１に戻って算出部１６について説明する。算出部１６は、縮約部１５によって縮約された各グラフ（縮約グラフ１５０ｇ）に基づいてハッシュ値を算出する。ここで、図１１を用いて、算出部１６が算出する算出処理について具体的に説明する。
【００６４】
図１１は、算出処理を説明する説明図である。図１１には、縮約部１５によって縮約された縮約グラフ１５０ｇを示している。図１１に示すように、算出部１６は、縮約グラフ１５０ｇに基づいて所定長さのハッシュ値を算出する。図１１では、１６バイトの長さのバイト列からなるハッシュ値を算出する。
【００６５】
より具体的には、算出部１６は、各グラフを処理の流れおよびデータの流れの方向とは逆向きに辿ってハッシュ値を算出する。例えば、図１１に示す例では、算出部１６は、端子ｎ３ａ←端子ｎ２ｋ←端子ｎ３ｋ（「−１」の端子）←端子ｎ２ｇ（「１」の端子）←端子ｎ３ｇ（「―１」の端子）←端子ｎ２ｃ（「１」の端子）←端子ｎ３ｃ←端子ｎ２ａ←端子ｎ３ｋ（「−２」の端子）←端子ｎ２ｇ（「２」の端子）←端子ｎ３ｇ（「―２」の端子）←端子ｎ２ｃ（「２」の端子）の順に辿ることでハッシュ値を算出する。
【００６６】
なお、算出部１６は、各グラフを処理の流れおよびデータの流れの方向とは逆向きに辿ってハッシュ値を算出したが、各グラフを処理の流れおよびデータの流れの方向と同じ方向に辿ってハッシュ値を算出してもよい。
【００６７】
このように、２つのソースコードＳＣａ、ＳＣｂを比較する際に、ハッシュ値を用いることで、正確な比較処理を行うことができるため、リファクタリングにより誤検知を高精度に防止できる。
【００６８】
さらに、処理およびデータの流れとは逆向きに辿ってハッシュ値を算出することで、処理およびデータの流れの影響を除外できるため、比較処理をさらに正確に行うことができる。
【００６９】
図１に戻って、比較部１７について説明する。比較部１７は、縮約された各グラフ（縮約グラフ１５０ｆ）を比較して、２つのソースコードＳＣａ、ＳＣｂの差異を出力する。
【００７０】
例えば、比較部１７は、算出部１６によって算出されたハッシュ値を比較して、２つのソースコードＳＣａ、ＳＣｂにおけるハッシュ値が一致する場合に、２つのソースコードＳＣａ、ＳＣｂの差異が無いことを示す情報を比較結果として出力する。つまり、比較部１７は、ハッシュ値が一致する場合には、２つのソースコードＳＣａ、ＳＣｂにおける振舞いが同じであるとする比較結果を出力する。これにより、２つのソースコードＳＣａ、ＳＣｂの振舞いに差異があるか否かを正確に検出することができる。
【００７１】
一方、比較部１７は、ハッシュ値が一致しない場合には、２つのソースコードＳＣａ、ＳＣｂの間に差異があることを示す比較結果を出力する。つまり、比較部１７は、ハッシュ値が異なる場合には、２つのソースコードＳＣａ、ＳＣｂにおける振舞いが異なるとする比較結果を出力する。
【００７２】
なお、比較部１７は、ハッシュ値を比較することで、２つのソースコードＳＣａ、ＳＣｂの間に差異があるか否かを判定したが、これに限らず、例えば、縮約グラフ１５０ｇの形状等を比較して差異の有無を判定してもよい。
【００７３】
次に、図１２〜２５を用いて、実施形態に係る解析装置１の動作について説明する。図１２は、実施形態に係る解析装置１が実行する全体処理を例示するフローチャートである。
【００７４】
図１２に示すように、受付部１１は、比較対象の２つのソースコードＳＣａ、ＳＣｂの格納位置が指定された格納指示があったか否かを判定する（ステップＳ１１）。つづいて、解析部１２は、受付部１１が格納指示を受け付けた場合（ステップＳ１１；Ｙｅｓ）、２つのソースコードＳＣａ、ＳＣｂ毎に解析して、抽象構文木を生成する（ステップＳ１２）。
【００７５】
つづいて、変換部１３は、格納位置にあるファイル全てを順に３部グラフ１３０に変換する（ステップＳ１３）。具体的には、変換部１３は、生成した抽象構文木に基づき、２つのソースコードＳＣａ、ＳＣｂにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する。
【００７６】
つづいて、受付部１１は、比較指示があったか否かを判定する（ステップＳ１４）。受付部１１は、比較指示があった場合（ステップＳ１４；Ｙｅｓ）、ソースコードファイル群の２つの格納位置ｄ１，ｄ２と、対象メソッドの名称ｎが指定された比較指示を受け付ける（ステップＳ１５）。
【００７７】
つづいて、結合部１４、縮約部１５および算出部１６は、格納位置ｄ１および名称ｎを指定して、部分グラフ１３０ａ、１３０ｂの結合、冗長部分の縮約、ハッシュ値算出を行うことで、ハッシュ値ｈ１を得る（ステップＳ１６）。
【００７８】
つづいて、結合部１４、縮約部１５および算出部１６は、格納位置ｄ２および名称ｎを指定して、部分グラフ１３０ａ、１３０ｂの結合、冗長部分の縮約、ハッシュ値算出を行うことで、ハッシュ値ｈ２を得る（ステップＳ１７）。
【００７９】
つづいて、比較部１７は、ハッシュ値ｈ１およびハッシュ値ｈ２が同一数値であるか否かを比較し、結果を出力し（ステップＳ１８）、処理を終了する。
【００８０】
次に、図１３を用いて、変換処理について説明する。図１３は、変換処理を例示するフローチャートである。図１３に示すように、まず、解析部１２は、２つのソースコードＳＣａ、ＳＣｂ毎に構文解析し、抽象構文木（以下、ＡＳＴと記載）を得る（ステップＳ１０１）。
【００８１】
つづいて、変換部１３は、ＡＳＴの根の各子要素（MethodDeclaration）に対し、その要素ｍを引数に第１処理（ＭＤ）を実行し（ステップＳ１０２）、変換処理を終了する。
【００８２】
次に、図１４を用いて、第１処理（ＭＤ）について説明する。図１４は、第１処理（ＭＤ）を例示するフローチャートである。図１４に示すように、変換部１３は、渡された要素ｍの２番目の子要素（Identifier）の文字列を属性値とする主ノード「Ｄ」（例えば、図８の主ノードｎ１ａ）を作る（ステップＳ１１０）。
【００８３】
つづいて、変換部１３は、要素ｍの子要素（Parameters）を引数に第２処理（Ｐｓ）を実行し、返されたリストＬｐを保持する（ステップＳ１１１）。つづいて、変換部１３は、主ノード「ＢＮ」（例えば、図８の主ノードｎ１ｂ）を作る（ステップＳ１１２）。
【００８４】
つづいて変換部１３は、主ノード「Ｄ」の端子「１」（例えば、図８の端子ｎ２ａ）から主ノード「ＢＮ」の端子「−１」（例えば、図８の端子ｎ３ｂ）へのエッジを作る（ステップＳ１１３）。つづいて、変換部１３は、主ノード「ＢＸ」（例えば、図８の主ノードｎ１ｌ）を作り、主ノード「ＢＸ」の端子「１」（例えば、図８の端子ｎ２ｌ）から主ノード「Ｄ」の端子「−１」へのエッジｅを作る（ステップＳ１１４）。
【００８５】
つづいて、変換部１３は、子要素（MethodBody）の子要素（Block）と主ノード「ＢＮ」の端子「１」とリストＬｐと主ノード「Ｄ」とを引数に第３処理（Ｂ）を実行し、返された主ノードの端子「１」から主ノード「ＢＸ」の端子「−１」へのエッジを作る（ステップＳ１１５）このとき、返された端子があれば、かかる端子から主ノード「Ｄ」の端子「−２」へのエッジｅを作り、第１処理を終了する。
【００８６】
次に、図１５を用いて、第２処理（ＰＳ）について説明する。図１５は、第２処理（ＰＳ）を例示するフローチャートである。図１５に示すように、変換部１３は、まず、リストＬｐを空にする（ステップＳ１２０）。
【００８７】
つづいて、変換部１３は、渡された要素の各子要素（Parameter）の子要素（Identifier）の文字列をリストＬｐに追加する（ステップＳ１２１）。つづいて、変換部１３は、リストＬｐを第１処理へ返し（ステップＳ１２２）、処理を終了する。
【００８８】
次に、図１６を用いて、第３処理（Ｂ）について説明する。図１６は、第３処理（Ｂ）を例示するフローチャートである。図１６に示すように、変換部１３は、渡された要素（Block）の子要素のリストをＬｃ、渡された端子をｔ、リストをＬｐ、主ノードをｍとする（ステップＳ１３０）。
【００８９】
つづいて、変換部１３は、Ｌｃが空であるか否を判定する（ステップＳ１３１）。つづいて、変換部１３は、Ｌｃが空ではない場合（ステップＳ１３１；Ｎｏ）、Ｌｃの先頭の要素ｃを取り出す（ステップＳ１３２）。このとき、端子ｖを「未設定」にする。
【００９０】
つづいて、変換部１３は、要素ｃが子要素（LocalVariableDeclaration）であるか否かを判定する（ステップＳ１３３）。つづいて、変換部１３は、要素ｃが子要素（LocalVariableDeclaration）ではない場合（ステップＳ１３３；Ｎｏ）、要素ｃが子要素（MethodInvocationExpr）であるか否かを判定する（ステップＳ１３４）。
【００９１】
つづいて、変換部１３は、要素ｃが子要素（MethodInvocationExpr）である場合（ステップＳ１３４；Ｙｅｓ）、要素ｃと端子ｔとリストＬｐと主ノードｍとを引数に第６処理（ＭＩＸ）を実行する（ステップＳ１３５）。
【００９２】
つづいて、変換部１３は、返された主ノードをｅに設定し、ｅの端子「１」をｔに設定し（ステップＳ１３６）。処理をステップＳ１３１に移行する。
【００９３】
一方、ステップＳ１３１において、変換部１３は、Ｌｃが空であった場合（ステップＳ１３１；Ｙｅｓ）、ｅと、ｖとを第１処理へ返し（ステップＳ１３７）、処理を終了する。
【００９４】
また、ステップＳ１３３において、変換部１３は、要素ｃが子要素（LocalVariableDeclaration）であった場合（ステップＳ１３３；Ｙｅｓ）、要素ｃと端子ｔとリストＬｐと主ノードｍを引数に第４処理（ＬＶＤ）を実行し（ステップＳ１３８）、処理をステップＳ１３６に移行する。
【００９５】
また、ステップＳ１３４において、変換部１３は、要素ｃが子要素（MethodInvocationExpr）でない場合（ステップＳ１３４；Ｎｏ）、要素ｃが子要素（ReturnStatement）であるか否かを判定する（ステップＳ１３９）。
【００９６】
変換部１３は、要素ｃが子要素（ReturnStatement）であった場合（ステップＳ１３９；Ｙｅｓ）、要素ｃと端子ｔとリストＬｐと主ノードｍを引数に第５処理（ＲＳ）を実行する（ステップＳ１４０）。つづいて、変換部１３は、返された端子をｖに設定し（ステップＳ１４１）、処理をステップＳ１３６に移行する。
【００９７】
一方、変換部１３は、要素ｃが子要素（ReturnStatement）でない場合（ステップＳ１３９；Ｎｏ）、処理をステップＳ１３１に移行する。
【００９８】
次に、図１７を用いて、第４処理（ＬＶＤ）について説明する。図１７は、第４処理（ＬＶＤ）を例示するフローチャートである。図１７に示すように、変換部１３は、渡された要素ｃの子要素（Identifier）の文字列ｓを属性値とする主ノード「ＤＬ」（例えば、図８の主ノードｎ１ｄ）を作り、渡された端子ｔから「ＤＬ」の端子「−１」へのエッジｅを作る（ステップＳ１５０）。
【００９９】
つづいて、変換部１３は、要素ｃの子要素（Expr）と「ＤＬ」の端子「１」と渡されたリストＬｐと主ノードｍを引数に第７処理（Ｘ）を実行し、返された主ノードをｄとする(ステップＳ１５１)。
【０１００】
つづいて、変換部１３は、ｓを属性値とする主ノード「ＷＬ」（例えば、図８の主ノードｎ１ｉ）を作り、ｄの端子「１」から「ＷＬ」の端子「−１」へのエッジｅを作り、ｄの端子「２」から「ＷＬ」の端子「−２」へのエッジｅを作る（ステップＳ１５２）。つづいて、変換部１３は、「ＷＬ」を第３処理へ返し（ステップＳ１５３）、処理を終了する。
【０１０１】
次に、図１８を用いて、第５処理（ＲＳ）について説明する。図１８は、第５処理（ＲＳ）を例示するフローチャートである。図１８に示すように、変換部１３は、渡された要素ｃの子要素（Expr）と渡された端子ｔとリストＬｐと主ノードｍを引数に第７処理（Ｘ）を実行する（ステップＳ１６０）。つづいて、変換部１３は、返された主ノードｄとｄの端子「２」を第３処理に返し（ステップＳ１６１）、処理を終了する。
【０１０２】
次に、図１９を用いて、第６処理（ＭＩＸ）について説明する。図１９は、第６処理（ＭＩＸ）を例示するフローチャートである。図１９に示すように、変換部１３は、渡された要素ｃの子要素（Expr）のリストをＬｘとするとともに、端子ｔをｅに設定し、端子のキューＱｒを空にする（ステップＳ１７０）。
【０１０３】
つづいて、変換部１３は、Ｌｘが空であるか否かを判定する（ステップＳ１７１）。つづいて、変換部１３は、Ｌｘが空でない場合（ステップＳ１７１；Ｎｏ）、Ｌｘの先頭の要素ｘを取り出す（ステップＳ１７２）。
【０１０４】
つづいて、変換部１３は、要素ｘと端子ｅと渡されたリストＬｐと主ノードｍを引数に第７処理（Ｘ）を実行し、返された主ノードｄの端子「２」をＱｒに追加し、ｄの端子「１」をｅに設定し（ステップＳ１７３）、処理をステップＳ１７１に移行する。
【０１０５】
一方、変換部１３は、Ｌｘが空であった場合（ステップＳ１７１；Ｙｅｓ）、要素ｃの子要素（Identifier）の文字列を属性値とする主ノード「Ｃ」（例えば、図８の主ノードｎ１ｇ）を作り、端子ｅから「Ｃ」の端子「−１」へのエッジｅを作る（ステップＳ１７４）。
【０１０６】
つづいて、変換部１３は、Ｑｒの各要素ｒを先頭から順に「Ｃ」の端子「−２」「−３」・・・へ接続するエッジｅを作る（ステップＳ１７５）。つづいて、変換部１３は、「Ｃ」を第３処理へ返し（ステップＳ１７６）、処理を終了する。
【０１０７】
次に、図２０を用いて、第７処理（Ｘ）について説明する。図２０は、第７処理（Ｘ）を例示するフローチャートである。図２０に示すように、変換部１３は、渡された要素ｘが子要素（MethodInvocationExpr）であるか否かを判定する（ステップＳ１８０）。
【０１０８】
つづいて、変換部１３は、要素ｘが子要素（MethodInvocationExpr）でない場合（ステップ１８０；Ｎｏ）、要素ｘが子要素（Identifier）であるか否かを判定する（ステップＳ１８１）。
【０１０９】
つづいて、変換部１３は、要素ｘが子要素（Identifier）である場合（ステップＳ１８１；Ｙｅｓ）、ｘの文字列ｓがリストＬｐの第ｉ番目に現れるか否かを判定する（ステップＳ１８２）。
【０１１０】
つづいて、変換部１３は、ｘの文字列ｓがリストＬｐの第ｉ番目に現れない場合（ステップＳ１８２；Ｎｏ）、ｓを属性値とする主ノード「ＲＬ」（例えば、主ノードｎ１ｊ）を作り、渡された端子ｔから「ＲＬ」の端子「−１」へのエッジを作る（ステップＳ１８３）。つづいて、変換部１３は、主ノード「ＲＬ」を第５処理に返し（ステップＳ１８４）、処理を終了する。
【０１１１】
一方、ステップＳ１８０において、変換部１３は、渡された要素ｘが子要素（MethodInvocationExpr）であった場合（ステップＳ１８０；Ｙｅｓ）、要素ｘと渡された端子ｔとリストＬｐと主ノードｍとを引数に第６処理を実行し、返された主ノードを「Ｃ」とする（ステップＳ１８５）。つづいて、変換部１３は、主ノード「Ｃ」を第５処理に返し（ステップＳ１８６）、処理を終了する。
【０１１２】
一方、ステップＳ１８１において、変換部１３は、要素ｘが子要素（Identifier）でない場合（ステップＳ１８１；Ｎｏ）、要素ｘが子要素（Literal）であるか否かを判定する（ステップＳ１８７）。
【０１１３】
つづいて、変換部１３は、要素ｘが子要素（Literal）である場合（ステップＳ１８７；Ｙｅｓ）、要素ｘの文字列を属性値とする主ノード「ＩＶ」（例えば、図８のｎ１ｃ）を作り、渡された端子ｔから「ＩＶ」の端子「−１」へのエッジを作る（ステップＳ１８８）。つづいて、変換部１３は、主ノード「ＩＶ」を第５処理へ返し（ステップＳ１８９）、処理を終了する。
【０１１４】
一方、ステップＳ１８７において、変換部１３は、要素ｘが子要素（Literal）でない場合（ステップＳ１８７；Ｎｏ）、エラーを提示して停止し（ステップ１９０）、処理を終了する。
【０１１５】
また、ステップＳ１８２において、変換部１３は、ｘの文字列ｓがリストＬｐの第ｉ番目に現れる場合（ステップＳ１８２；Ｙｅｓ）、主ノード「ＩＤ」（例えば、図８の主ノードｎ１ｆ）を作り、渡された主ノードｍの端子「ｉ＋１」から「ＩＤ」の端子「−２」へのエッジを作り、渡された端子ｔから「ＩＤ」の端子「−１」へのエッジを作る（ステップＳ１９１）。つづいて、変換部１３は、主ノード「ＩＤ」を第５処理へ返し（ステップＳ１９２）、処理を終了する。
【０１１６】
次に、図２１を用いて、結合処理について説明する。図２１は、結合処理を例示するフローチャートである。図２１に示すように、結合部１４は、指定された格納位置のソースコードＳＣに対する３部グラフ１３０から属性値が指定されたメソッド名ｋとなっている主ノード「Ｄ」を見つける（ステップＳ２０１）。
【０１１７】
つづいて、結合部１４は、主ノード「Ｄ」（属性ｋ）を含む部分グラフ１３０ａ，１３０ｂを３部グラフ格納部１１３から、結合グラフ格納部１１４へコピーする（ステップＳ２０２）。
【０１１８】
つづいて、結合部１４は、端子リストＬを主ノード「Ｄ」（属性ｋ）から出る端子すべてを含むリストに設定し、主ノードの集合Ｓを空に設定する（ステップＳ２０３）。つづいて、結合部１４は、リストＬが空であるか否かを判定する（ステップＳ２０４）。
【０１１９】
つづいて、結合部１４は、リストＬが空でない場合（ステップＳ２０４；Ｎｏ）、リストＬから、１つの端子ｔを取り出し、端子ｔから出るエッジを２ホップたどった位置にある主ノードをｎとする（ステップＳ２０５）。
【０１２０】
つづいて、結合部１４は、ｎが集合Ｓに含まれない、かつ、ｎが主ノード「Ｃ」であるか否かを判定する（ステップＳ２０６）。結合部１４は、ｎが集合Ｓに含まれない、かつ、ｎが主ノード「Ｃ」である場合（ステップＳ２０６；Ｙｅｓ）、ｎの属性をｍとし、３部グラフ格納部１１３の３部グラフ１３０全体から主ノード「Ｄ」（属性ｍ）を含む部分グラフ１３０ａ、１３０ｂを探す（ステップＳ２０７）。
【０１２１】
つづいて、結合部１４は、主ノード「Ｄ」（属性ｍ）を含む部分グラフ１３０ａ、１３０ｂが見つかったか否かを判定する（ステップＳ２０８）。結合部１４は、主ノード「Ｄ」（属性ｍ）を含む部分グラフ１３０ａ、１３０ｂが見つかった場合（ステップＳ２０８；Ｙｅｓ）、見つけた部分グラフ１３０ａ、１３０ｂを結合グラフ格納部１１４にコピーする（ステップＳ２０９）。
【０１２２】
つづいて、結合部１４は、ｎの各端子ｉが他の端子と接する各エッジｉ→ｔ（またはｉ
←ｔ）について、コピーしたグラフ上の「Ｄ」の端子―ｉが他の端子と接する各エッジーｉ←ｓ（またはーｉ→ｓ）に対し、エッジｓ→ｔ（またはｓ←ｔ）を作る（ステップＳ２１０）。
【０１２３】
つづいて、結合部１４は、主ノード「Ｄ」（属性ｍ）と主ノードｎ、これらの主ノードと接する端子、それらのノードと接するエッジを削除する（ステップＳ２１１）。つづいて、結合部１４は、ｔから出るエッジを２ホップたどった位置にある主ノードを新たなｎとして設定し（ステップＳ２１２）。処理をステップＳ２０６へ移行する。
【０１２４】
一方、ステップＳ２０４において、結合部１４は、リストＬが空であった場合（ステップＳ２０４；Ｙｅｓ）、処理を終了する。
【０１２５】
また、ステップＳ２０６において、結合部１４は、ｎがＳに含まれない、かつ、ｎが主ノード「Ｃ」であることがどちらか一方でも否定される場合（ステップＳ２０６；Ｎｏ）、ｎが主ノード「Ｄ」（属性ｋ）ではなく、かつ、ｎがＳに含まれないなら、ｎから出る端子全てをリストＬに追加し、ｎを集合Ｓに追加し（ステップＳ２１３）、処理をステップＳ２０４に移行する。
【０１２６】
また、ステップＳ２０８において、結合部１４は、主ノード「Ｄ」（属性ｍ）を含む部分グラフ１３０ａ、１３０ｂが見つからなかった場合（ステップＳ２０８；Ｎｏ）、処理をステップＳ２１３に移行する。
【０１２７】
次に、図２２を用いて、縮約処理について説明する。図２２は、縮約処理を例示するフローチャートである。図２２に示すように、縮約部１５は、結合グラフ格納部１１４の内容を縮約グラフ格納部１１５へコピーする（ステップＳ３０１）。
【０１２８】
つづいて、縮約部１５は、ノードリストＬｄの内容を、主ノード「Ｄ」全てが含まれるリストに設定し、フラグｍを「ｆａｌｓｅ」に設定する（ステップＳ３０２）。つづいて、縮約部１５は、Ｌｄが空であるか否かを判定する（ステップＳ３０３）。
【０１２９】
縮約部１５は、Ｌｄが空ではない場合（ステップＳ３０３；Ｎｏ）、Ｌｄから主ノードｄを１つ取り出す（ステップＳ３０４）。つづいて、縮約部１５は、リストＬｒの内容を、全ての縮約ルールのＩＤが含まれるリストに設定する（ステップＳ３０５）。
【０１３０】
つづいて、縮約部１５は、Ｌｒが空であるか否かを判定する（ステップＳ３０６）。縮約部１５は、Ｌｒが空ではない場合（ステップＳ３０６；Ｎｏ）、ＬｒからルールのＩＤを１つ取り出し、そのＩＤのルールをｒとする（ステップＳ３０７）。
【０１３１】
つづいて、縮約部１５は、主ノードｄとルールｒを引数に第１処理（ルール適用）を実行する（ステップＳ３０８）。つづいて、縮約部１５は、ルールｒの実行でグラフ（縮約グラフ１５０ａ〜１５０ｇ）が変化したらフラグｍを「ｔｒｕｅ」に設定し（ステップＳ３０９）、処理をステップＳ３０６に移行する。
【０１３２】
一方、ステップＳ３０３において、縮約部１５は、Ｌｄから空であった場合（ステップＳ３０３；Ｙｅｓ）、ｍが「ｔｒｕｅ」であるか否かを判定する（ステップＳ３１０）。縮約部１５は、ｍが「ｔｒｕｅ」でない場合（ステップＳ３１０；Ｎｏ）、処理を終了する。
【０１３３】
また、縮約部１５は、ｍが「ｔｒｕｅ」である場合（ステップＳ３１０；Ｙｅｓ）、処理をステップＳ３０２に移行する。また、ステップＳ３０６において、縮約部１５は、Ｌｒが空であった場合（ステップＳ３０６；Ｙｅｓ）、処理をステップＳ３０３に移行する。
【０１３４】
次に、図２３を用いて、縮約処理における第１処理（ルール適用）について説明する。図２３は、第１処理（ルール適用）を例示するフローチャートである。図２３に示すように、縮約部１５は、ノードリストＬｎの内容を渡された主ノードｄのみからなるリストにする（ステップＳ３２０）。
【０１３５】
つづいて、縮約部１５は、Ｌｎが空であるか否かを判定する（ステップＳ３２１）。縮約部１５は、Ｌｎが空ではない場合（ステップＳ３２１；Ｎｏ）、Ｌｎから主ノードｎを１つ取り出す（ステップＳ３２２）。
【０１３６】
つづいて、縮約部１５は、ｎから出るエッジを３ホップたどった位置にある主ノード全て（「Ｄ」を除く）をＬｎに追加する（ステップＳ３２３）。つづいて、縮約部１５は、渡されたルールｒの対象主ノードの種類を渡された主ノードｄと比較する（ステップＳ３２４）。
【０１３７】
つづいて、縮約部１５は、比較した結果、合致したか否かを判定する（ステップＳ３２５）。縮約部１５は、合致した場合（ステップＳ３２５；Ｙｅｓ）、ｎはｒの条件を満たすか否かを判定する（ステップＳ３２６）。
【０１３８】
つづいて、縮約部１５は、ｎがｒの条件を満たす場合（ステップＳ３２６；Ｙｅｓ）、ｒの処理を実施し（ステップＳ３２７）、処理をステップＳ３２１に移行する。
【０１３９】
一方、ステップＳ３２１において、縮約部１５は、Ｌｎが空である場合（ステップＳ３２１；Ｙｅｓ）、処理を終了する。また、ステップＳ３２５において、縮約部１５は、合致しない場合（ステップＳ３２５；Ｎｏ）、処理をステップＳ３２１に移行する。また、ステップＳ３２６において、縮約部１５は、ｎがｒの条件を満たさない場合（ステップＳ３２６；Ｎｏ）、処理をステップＳ３２１に移行する。
【０１４０】
次に、図２４を用いて、縮約処理におけるノードスキップ処理について説明する。図２４は、縮約処理におけるノードスキップ処理を例示するフローチャートである。図２４では、ノードスキップ処理の対象が主ノードｎである場合について説明する。
【０１４１】
図２４に示すように、縮約部１５は、主ノードｎの端子「１」に接する端子ｔそれぞれについて、主ノードｎの端子「−１」に接する各端子ｓからエッジｓ→ｔを追加する（ステップＳ３３０）。
【０１４２】
つづいて、縮約部１５は、主ノードｎの各端子が接するエッジを削除する（ステップＳ３３１）。つづいて、縮約部１５は、主ノードｎの各端子を削除する（ステップＳ３３２）。つづいて、縮約部１５は、主ノードｎを削除し（ステップＳ３３３）、処理を終了する。
【０１４３】
次に、図２５を用いて、ハッシュ値の算出処理について説明する。図２５は、算出処理を例示するフローチャートである。図２５に示すように、算出部１６は、渡された主ノードｎに接する第３ノード（端子）を、空のスタックＴｔに、その属性数値（端子番号）の絶対値の大きい順にプッシュする（ステップＳ４０１）。
【０１４４】
つづいて、算出部１６は、ｐを空文字列に設定し、集合Ｓｖを｛ｎ｝に設定する（ステップＳ４０２）。つづいて、縮約部１５は、Ｔｔが空であるか否かを判定する（ステップＳ４０３）。
【０１４５】
算出部１６は、Ｔｔが空ではない場合（ステップＳ４０３；Ｎｏ）、Ｔｔから端子ｔをホップする（ステップＳ４０４）。つづいて、算出部１６は、ｔに向かうエッジｓ→ｔがあるか否かを判定する（ステップＳ４０５）。
【０１４６】
算出部１６は、ｔに向かうエッジｓ→ｔがある場合（ステップＳ４０５；Ｙｅｓ）、ｔに接する主ノードをｄ、ｓに接する主ノードをｃとして、次の文字列「「dの種類名」「dの属性値」“。”「ｔの属性値」“←”、「ｃの種類名」「ｃの属性値」“。”「ｓの属性値」“；”」をｐに追加する（ステップＳ４０６）。
【０１４７】
つづいて、算出部１６は、ｃがＳｖに含まれるか否かを判定する（ステップＳ４０７）。つづいて、算出部１６は、ｃがＳｖに含まれない場合（ステップＳ４０７；Ｎｏ）、Ｓｖにｃを加える（ステップＳ４０８）。つづいて、算出部１６は、主ノードｃに接する第３ノード（端子）を、空のスタックＴｔに、その属性数値（端子番号）の絶対値の大きい順にプッシュし（ステップＳ４０９）、処理をステップＳ４０３に移行する。
【０１４８】
一方、ステップＳ４０３において、算出部１６は、Ｔｔが空であった場合（ステップＳ４０３；Ｙｅｓ）、ｍｄ５（ｐ）を算出したハッシュ値として返し（ステップＳ４１０）、処理を終了する。
【０１４９】
また、ステップＳ４０５において、算出部１６は、ｔに向かうエッジｓ→ｔがない場合（ステップＳ４０５；Ｎｏ）、処理をステップＳ４０３に移行する。また、ステップＳ４０７において、算出部１６は、ｃがＳｖに含まれる場合（ステップＳ４０７；Ｙｅｓ）、処理をステップＳ４０３に移行する。
【０１５０】
上述したように、実施形態に係る解析装置１は、解析部１２と、変換部１３と、縮約部１５と、比較部１７とを有する。解析部１２は、比較対象の２つのソースコードＳＣａ、ＳＣｂを取得し、取得したソースコードＳＣ毎に解析して２つのソースコードＳＣａ、ＳＣｂの抽象構文木を生成する。変換部１３は、生成した抽象構文木に基づき、２つのソースコードＳＣａ、ＳＣｂにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する。縮約部１５は、所定のルールに基づき、グラフ化された２つのソースコードＳＣａ、ＳＣｂにおける各グラフの冗長部分を縮約する。比較部１７は、縮約された各グラフを比較して２つのソースコードＳＣａ、ＳＣｂの差異を出力する。
【０１５１】
これにより、メソッドの分割やメソッドの結合によるソースコードＳＣａ、ＳＣｂの変更の影響を除外できるため、リファクタリングを行った際に、プログラムの振舞いが変わったと誤検知することを防止できる。
【０１５２】
また、図示した各部の各構成要素は、必ずしも物理的に図示の如く構成されていることを要しない。すなわち、各部の分散・統合の具体的形態は図示のものに限られず、その全部または一部を、各種の負荷や使用状況等に応じて、任意の単位で機能的または物理的に分散・統合して構成することができる。例えば、解析部１２と変換部１３とを統合してもよい。また、図示した各処理は、上記の順番に限定されるものではなく、処理内容を矛盾させない範囲において、同時に実施してもよく、順序を入れ替えて実施してもよい。
【０１５３】
さらに、各装置で行われる各種処理機能は、ＣＰＵ（又はＭＰＵ、ＭＣＵ（Micro  Controller  Unit）等のマイクロ・コンピュータ）上で、その全部または任意の一部を実行するようにしてもよい。また、各種処理機能は、ＣＰＵ（またはＭＰＵ、ＭＣＵ等のマイクロ・コンピュータ）で解析実行されるプログラム上、またはワイヤードロジックによるハードウェア上で、その全部又は任意の一部を実行するようにしてもよいことは言うまでもない。
【０１５４】
ところで、上記の各実施例で説明した各種の処理は、予め用意されたプログラムをコンピュータで実行することで実現できる。そこで、以下では、上記の各実施例と同様の機能を有するプログラムを実行するコンピュータの一例を説明する。図２６は、解析プログラムを実行するコンピュータの一例を示す図である。
【０１５５】
図２６に示すように、コンピュータ３００は、各種演算処理を実行するＣＰＵ３７０と、データ入力を受け付ける入力装置３１０と、出力装置３２０とを有する。また、コンピュータ３００は、記憶媒体からプログラム等を読み取る媒体読取装置３４０と、各種装置との間でデータの授受を行う通信インターフェース（ＩＦ）３３０とを有する。また、コンピュータ３００は、各種情報を一時記憶するＲＡＭ３６０と、ハードディスク装置（ＨＤＤ）３５０とを有する。また、各装置３１０〜３７０は、バス３８０に接続される。  
【０１５６】
ＨＤＤ３５０には、図１に示した受付部１１、解析部１２、変換部１３、結合部１４、縮約部１５、算出部１６および比較部１７の各処理部と同様の機能を有する解析プログラム３５１が記憶される。また、ＨＤＤ３５０には、ソースコードファイル群格納部１１１と、抽象構文木格納部１１２と、３部グラフ格納部１１３と、結合グラフ格納部１１４と、縮約グラフ格納部１１５と、ハッシュ値格納部１１６、および、解析プログラム３５１を実現するための各種データが記憶される。入力装置３１０は、例えば、コンピュータ３００の管理者から各種情報の入力を受け付ける。出力装置３２０は、例えば、コンピュータ３００の管理者に対して各種画面を表示する。通信ＩＦ３３０は、図示しないネットワークと接続され、各種装置と各種情報をやりとりする。  
【０１５７】
ＣＰＵ３７０は、ＨＤＤ３５０に記憶された各プログラムを読み出して、ＲＡＭ３６０に展開して実行することで、解析プロセス３７１を行う。また、これらのプログラムは、コンピュータ３００を図１に示した解析部１２、変換部１３、結合部１４、縮約部１５、算出部１６および比較部１７として機能させることができる。  
【０１５８】
なお、上記の解析プログラム３５１は、必ずしもＨＤＤ３５０に記憶されている必要はない。例えば、コンピュータ３００が読み取り可能な記憶媒体に記憶されたプログラムを、コンピュータ３００が読み出して実行するようにしてもよい。コンピュータ３００が読み取り可能な記憶媒体は、例えば、ＣＤ−ＲＯＭやＤＶＤディスク、ＵＳＢ（Universal  Serial  Bus）メモリ等の可搬型記録媒体、フラッシュメモリ等の半導体メモリ、ハードディスクドライブ等が対応する。また、公衆回線、インターネット、ＬＡＮ等に接続された装置にこの解析プログラムを記憶させておき、コンピュータ３００がこれらから解析プログラムを読み出して実行するようにしてもよい。
【０１５９】
以上の実施形態に関し、さらに以下の付記を開示する。
【０１６０】
（付記１）比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成する解析部と、
生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化する変換部と、
所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約する縮約部と、
縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する比較部と
を有することを特徴とする解析装置。
【０１６１】
（付記２）前記変換部は、
前記処理に対応する第１ノードと、前記データの参照に対応する第２ノードと、前記データの設定に対応する第３ノードとの接続関係を示す３部グラフに変換する
ことを特徴とする付記１に記載の解析装置。
【０１６２】
（付記３）グラフ化された前記２つのソースコードにおける前記各グラフの部分グラフを結合して、所定のメソッドの定義の部分グラフを生成する結合部をさらに備える、
ことを特徴とする付記１または２に記載の解析装置。
【０１６３】
（付記４）縮約された前記各グラフに基づいてハッシュ値を算出する算出部をさらに備え、
前記比較部は、
前記各グラフの前記ハッシュ値を比較して前記差異を出力する
ことを特徴とする付記１〜３のいずれか一に記載の解析装置。
【０１６４】
（付記５）前記算出部は、
前記各グラフを前記処理の流れおよび前記データの流れの方向とは逆向きに辿って前記ハッシュ値を算出する
ことを特徴とする付記４に記載の解析装置。
【０１６５】
（付記６）前記比較部は、
算出された前記ハッシュ値同士が一致する場合に、前記２つのソースコードの前記差異が無いことを示す情報を出力する
ことを特徴とする付記４または５に記載の解析装置。
【０１６６】
（付記７）コンピュータに、
比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成し、
生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化し、
所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約し、
縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する
処理を実行させることを特徴とする解析プログラム。
【０１６７】
（付記８）前記グラフ化する処理は、
前記処理に対応する第１ノードと、前記データの参照に対応する第２ノードと、前記データの設定に対応する第３ノードとの接続関係を示す３部グラフに変換する
ことを特徴とする付記７に記載の解析プログラム。
【０１６８】
（付記９）グラフ化された前記２つのソースコードにおける前記各グラフの部分グラフを結合して、所定のメソッドの定義の部分グラフを生成する処理をさらにコンピュータに実行させる、
ことを特徴とする付記７または８に記載の解析プログラム。
【０１６９】
（付記１０）縮約された前記各グラフに基づいてハッシュ値を算出する処理をさらにコンピュータに実行させ、
前記出力する処理は、
前記各グラフの前記ハッシュ値を比較して前記差異を出力する
ことを特徴とする付記７〜９のいずれか一に記載の解析プログラム。
【０１７０】
（付記１１）前記算出する処理は、
前記各グラフを前記処理の流れおよび前記データの流れの方向とは逆向きに辿って前記ハッシュ値を算出する
ことを特徴とする付記１０に記載の解析プログラム。
【０１７１】
（付記１２）前記出力する処理は、
算出された前記ハッシュ値同士が一致する場合に、前記２つのソースコードの前記差異が無いことを示す情報を出力する
ことを特徴とする付記１０または１１に記載の解析プログラム。
【０１７２】
（付記１３）コンピュータが、
比較対象の２つのソースコードを取得し、取得した前記ソースコード毎に解析して前記２つのソースコードの抽象構文木を生成し、
生成した前記抽象構文木に基づき、前記２つのソースコードにおけるメソッド内およびメソッド間の処理の流れおよびデータの流れをグラフ化し、
所定のルールに基づき、グラフ化された前記２つのソースコードにおける各グラフの冗長部分を縮約し、
縮約された前記各グラフを比較して前記２つのソースコードの差異を出力する
処理を実行することを特徴とする解析方法。
【０１７３】
（付記１４）前記グラフ化する処理は、
前記処理に対応する第１ノードと、前記データの参照に対応する第２ノードと、前記データの設定に対応する第３ノードとの接続関係を示す３部グラフに変換する
ことを特徴とする付記１３に記載の解析方法。
【０１７４】
（付記１５）グラフ化された前記２つのソースコードにおける前記各グラフの部分グラフを結合して、所定のメソッドの定義の部分グラフを生成する処理をさらにコンピュータが実行する、
ことを特徴とする付記１３または１４に記載の解析方法。
【０１７５】
（付記１６）縮約された前記各グラフに基づいてハッシュ値を算出する処理をさらにコンピュータが実行し、
前記出力する処理は、
前記各グラフの前記ハッシュ値を比較して前記差異を出力する
ことを特徴とする付記１３〜１５のいずれか一に記載の解析方法。
【０１７６】
（付記１７）前記算出する処理は、
前記各グラフを前記処理の流れおよび前記データの流れの方向とは逆向きに辿って前記ハッシュ値を算出する
ことを特徴とする付記１６に記載の解析方法。
【０１７７】
（付記１８）前記出力する処理は、
算出された前記ハッシュ値同士が一致する場合に、前記２つのソースコードの前記差異が無いことを示す情報を出力する
ことを特徴とする付記１６または１７に記載の解析方法。
【符号の説明】
【０１７８】
１    解析装置
１１  受付部
１２  解析部
１３  変換部
１４  結合部
１５  縮約部
１６  算出部
１７  比較部
１１１  ソースコードファイル群格納部
１１２  抽象構文木格納部
１１３  ３部グラフ格納部
１１４  結合グラフ格納部
１１５  縮約グラフ格納部
１１６  ハッシュ値格納部
ＳＣ，ＳＣａ，ＳＣｂ  ソースコード
【図１】
2019003385.tif 000003
【図２】
2019003385.tif 000004
【図３】
2019003385.tif 000005
【図４】
2019003385.tif 000006
【図５】
2019003385.tif 000007
【図６】
2019003385.tif 000008
【図７】
2019003385.tif 000009
【図８】
2019003385.tif 000010
【図９】
2019003385.tif 000011
【図１０】
2019003385.tif 000012
【図１１】
2019003385.tif 000013
【図１２】
2019003385.tif 000014
【図１３】
2019003385.tif 000015
【図１４】
2019003385.tif 000016
【図１５】
2019003385.tif 000017
【図１６】
2019003385.tif 000018
【図１７】
2019003385.tif 000019
【図１８】
2019003385.tif 000020
【図１９】
2019003385.tif 000021
【図２０】
2019003385.tif 000022
【図２１】
2019003385.tif 000023
【図２２】
2019003385.tif 000024
【図２３】
2019003385.tif 000025
【図２４】
2019003385.tif 000026
【図２５】
2019003385.tif 000027
【図２６】
2019003385.tif 000028