Javaファイル用のDiffツール作ってみた


概要

前に(というか昨日)書いたやつの続きです。

該当記事はこちらからどうぞ!

Javaソースの解析ツールをJavaで書いてみた…い
https://qiita.com/banana5388/items/cd8a549d1885aa6dd039

前回の記事のコメントで「単純なことから始めてみましょう」というご指摘を頂いたので、まずは単純に2つのソースコードの差異ステップ数を取得するところから始めてみました。

(車輪の再開発なんて言わないで!!!!なんか作ってたら楽しくなっちゃったんだもの!!!!)

ということで今回作成するもののインプットとアウトプットはこんな感じ。

INPUT : 比較元と比較先の絶対パス
OUTPUT: コードに差異があったステップ数

仕様

とりあえず考えていたものはざっとこんな感じ。

  1. 比較元、比較先それぞれ取得したコードを一文字ずつ解析する
  2. 比較元と比較先で違う文字が出現した場合、比較元を現在の文字位置で停止し、比較先の文字を次の文字解析へ
  3. また比較先で比較元と同じ文字が出現した場合に、比較元の文字解析を再開
  4. 比較元の文字解析が停止している状態で比較先に改行文字が出現した場合、差異ステップ数を1足す
  5. [2. - 4.]の処理を比較元か比較先の文字が終了するまで続ける
  6. 解析の結果、何行違う行があったかを出力する

とりあえずこれをそのまま実装しました。

主要な部分の実装はこんな感じ。

JavaCodeDifference.java

   /**
     * 2つのコードの比較を行い、一致した行数を返却
     *
     * @param origCode      比較元コード(行ごとにリストで格納されています)
     * @param destCode      比較先コード(行ごとにリストで格納されています)
     * @return 比較一致行数
     */
    public static int countCodeDiff(List<String> origCode, List<String> destCode) {

        int cnt = 0;

        // 文字列用イテレータの生成

        // メソッド「getNotIncludeIgnoreCode」は、リストに格納されている一行ごとのコード情報から
        // 半角スペース、全角スペース、タブ文字、改行文字を消去し、末尾に改行文字を入れた上で
        // 最終的に一つの文字列(String型)として返却するメソッドです。
        StringCharacterIterator origCodeIterator =  new StringCharacterIterator(getNotIncludeIgnoreCode(origCode));
        StringCharacterIterator destCodeIterator =  new StringCharacterIterator(getNotIncludeIgnoreCode(destCode));

        // 比較元または比較先のどちらかの文字が終了するまで実行
        while (origCodeIterator.current() != StringCharacterIterator.DONE &&
                destCodeIterator.current() != StringCharacterIterator.DONE) {

            // 比較元と比較先で違うコード文字が含まれ、かつ比較先の方が先に改行していた場合にカウントを増やす
            if (origCodeIterator.current() == destCodeIterator.current()) {
                destCodeIterator.next();
                origCodeIterator.next();
            } else {
                if (destCodeIterator.current() == '\n') {
                    cnt++;
                }
                destCodeIterator.next();
            }
        }

        return cnt;
    }

うむ、いい感じじゃないか??

テスト

テスト1つ目

テスト用にテキストを用意した。

test1.java
aaaa
iiii
uuuu
test2.java
aaaa
iiii
uuuu

全然javaファイルじゃないけどとりあえずテスト用なんでこれでいいですかね。
さーて出力は。。。

> Number of different lines: 0

うん、よさそうですね。

テスト2つ目

もういっちょテスト

test1.java
aaaa
iiii
uuuu
test2.java
aaa
iii
uuu

さーて出力は。。。

> Difference Code Line Count:3

これもよさそう。

感想

とりあえず仕様通りの動きはしているので満足。

というか割と仕様がガバガバですね…もうちょい使えるように今後実装し直してしていきたいと思います。

ソース公開してます

はーい。
https://github.com/satodaiki/DiffTool

更新履歴

2018/12/2 初版
2018/12/3 ソースに一部誤りがあったので修正しました。