私は2つの似た巨大プロジェクト(1000 +クラス)をマージする必要があります。二つ目は、最初の1のフォークです、そしてそれはいくつかの国固有の振る舞いが含まれています。SVNバージョン管理が非常に悪く扱われたため、二つのプロジェクトは、多くのことを発散します。
多くの場合、2つのクラスが意味的に同一であることを起こります。そのソースコードは、などの警告、import文、いくつかのメソッドや変数の順序、コードの書式設定、コメント、という点で異なります
2つのクラスが意味的に同一である場合、自動的にチェックする方法はありますか?
あなたは次のようにプログラム解析ツールを使用することを検討すべきであるすす。すすは、最良のあなたの目的に適しているコードを分析するためのいくつかの優れたAPIを持っています。例えば、二つのクラス「意味的に同一である」かどうかを確認するために、あなたはクラスの両方が同じ(または類似の方法を)持っている(1)クラスの両方が同じ(または類似のフィールド)を持っているかどうか(2)検討することができます。
フィールドは次のように表現されるSootField
すすインチ あなたには、すべての必要な情報を持っていますSootField
あなたは比較のために使用することをオブジェクト。それらの制御フローグラフ(かどうかの二つの方法の意味的な類似性をチェックするには、あなたがチェックできるのCFGが)類似またはではありません(詳細はセクション5.7であり、このガイド)。
あなたはすすを使用する方法のヒント。
ソースdirがされている場合はsrcDir
、JavaのホームがあるjavaHome
とクラスのリストがありclassNames
、その後、あなたはプログラムですすツールセットで、あなたのクラスをロードするために、次のコードスニペットを使用することができます。
String sootClassPath = srcDir + ":"
+ javaHome + "/jre/lib/rt.jar:"
+javaHome + "/jre/lib/jce.jar";
Options.v().set_output_format(Options.output_format_jimple);
Options.v().set_src_prec(Options.src_prec_java);
for (String className : classNames) { // // "className" is like a.b.Myclass
Options.v().classes().add(className);
}
Options.v().set_keep_line_number(true);
Options.v().set_allow_phantom_refs(true);
Scene.v().setSootClassPath(sootClassPath);
Scene.v().loadBasicClasses();
あなたのクラスがロードされるときは、以下のようなクラスにアクセスすることができます。
SootClass sClass = Scene.v().loadClassAndSupport(className); // "className" is like a.b.Myclass
今、あなたはフィールドとメソッドのアクセスすることができsClass
、以下のように:
Chain<SootField> fieldList = sClass.getFields(); // import soot.util.Chain;
List<SootMethod> methods = sClass.getMethods();
それの命令のリストを取得するには、以下のようなあなたは、メソッドのCFGを反復することができます
if (method.isConcrete()) {
List<Unit> instructionList = new ArrayList<>();
Body b = method.retrieveActiveBody();
DirectedGraph g = new ExceptionalUnitGraph(b);
Iterator gitr = g.iterator();
while (gitr.hasNext()) {
Unit unit = (Unit) gitr.next();
instructionList.add(unit);
}
}