23

コードベース全体で使用されているメソッドのシグネチャを変更する必要があります。

具体的には、メソッドvoid log(String)は 2 つの追加の引数 ( Class c, String methodName) を受け取ります。これらは、呼び出されるメソッドに応じて、呼び出し元が提供する必要があります。私は単に合格することはできませんnull

範囲を把握するために、Eclipse はそのメソッドへの 7000 の参照を見つけたので、それを変更するとプロジェクト全体がダウンします。手動で修正するには数週間かかります。

私が知る限り、Eclipse の Eclipse のリファクタリング プラグインはそのタスクに対応していませんが、本当に自動化したいのです。
では、どうすれば仕事を成し遂げることができますか?

4

12 に答える 12

22

すばらしい、以前の回答をコピーできます。少し編集するだけです。


これを行うには、 javaparserのようなソース コード パーサーを使用する必要があると思います。

すべての Java ソース ファイルについて、それを CompilationUnit に解析し、おそらくModifierVisitorを基本クラスとして使用して Visitor を作成し、 (少なくとも) オーバーライドします。次に、変更された CompilationUnit を新しいファイルに書き込み、その後 diff を実行します。visit(MethodCallExpr, arg)

元のソース ファイルを変更しないことをお勧めしますが、シャドウ ファイル ツリーを作成することをお勧めします (例: old file: src/main/java/com/mycompany/MyClass.java、 new file src/main/refactored/com/mycompany/MyClass.java、そうすればディレクトリ全体を比較できます)。

于 2010-10-11T13:26:06.767 に答える
6

Eclipse は、Refactor -> Change Method signatureを使用してそれを実行し、新しいパラメーターのデフォルト値を提供できます。

クラス パラメータの場合、defaultValue は this.getClass() である必要がありますが、メソッド名パラメータの方法がわかりません。

于 2010-10-11T12:57:41.297 に答える
3

IntelliJ IDEAはこれで何の問題もありません。

私は Java の専門家ではありませんが、このような方法でうまくいく可能性があります。これは完璧な解決策ではありません (非常に悪い解決策でさえあるかもしれません) が、次のように始めることができます。

IntelliJ のリファクタリング ツールを使用してメソッド シグネチャを変更し、2 つの新しいパラメーターのデフォルト値を指定します。

c: self.getClass()
methodName: Thread.currentThread().getStackTrace()[1].getMethodName()

または、単にデフォルト値としてnullを指定するだけです。

于 2010-10-11T12:35:54.140 に答える
2

呼び出しコードとメソッド シグネチャを本当に変更する必要がありますか? 私が得ているのは、追加されたパラメーターが、ログ データに追加する呼び出しクラスとメソッドを提供することを意図しているように見えるということです。唯一の要件が呼び出し元のクラス/メソッドをログ データに追加することだけである場合は、Thread.currentThread().getStackTrace() が機能するはずです。StackTraceElement[] を取得したら、呼び出し元のクラス名とメソッド名を取得できます。

于 2010-10-11T15:03:47.913 に答える
2

たぶん私は素朴ですが、メソッド名をオーバーロードできないのはなぜですか?

void thing(paramA) {
    thing(paramA, THE_DEFAULT_B, THE_DEFAULT_C)
}

void thing(paramA, paramB, paramC) {
    // new method
}
于 2010-10-11T13:31:28.990 に答える
2

これは単なる技術的な問題ではなく「状況」であるため、これに対処するにはいくつかの手順があると思います。

  1. リスクがあるため、短期間で行うことは拒否してください。
  2. 標準的なフレームワークを使用せず、車輪の再発明によって引き起こされる問題を指摘してください (Paul のように)。
  3. 変更を行う場合は、Log4j または同等の使用を主張してください。
  4. 賢明なチャンクで Eclipse リファクタリングを使用して、変更を行い、さまざまなデフォルトに対処します。

古い臭いコードを修正するために、非常に大きな変更に対してEclipseリファクタリングを使用しました-最近ではかなり堅牢です。

于 2010-10-11T13:26:39.107 に答える
1

intellij を使用してリファクタリングしてみてください。SSR(Structural Search and Replace)と呼ばれる機能があります。コンテキストのクラス、メソッド名などを参照できます。(シーナイザーの答えはより有望です、私はそれを支持しました)

于 2010-10-11T14:50:56.147 に答える
1

Java を解析できるツールが必要だという Seanizer の回答に同意します。これは必要ですが、十分ではありません。あなたが本当に欲しいのは、信頼できる大量変更を実行できるツールです。

これを行うには、Java を解析し、解析されたコードに対してパターン マッチを行い、置換呼び出しをインストールし、残りのソース コードを破壊することなく答えを吐き出すことができるツールが必要です。

当社のDMS Software Reengineering Toolkitは、Java を含むさまざまな言語でこれらすべてを実行できます。ソースの完全なJava システムを解析し、抽象構文ツリーを構築します (コードのセット全体)。

DMS は、パターン指向のソースからソースへの変換を適用して、目的の変更を実現できます。

OP の効果を達成するために、彼は次のプログラム変換を適用します。

 rule replace_legacy_log(s:STRING): expression -> expression
    " log(\s) " -> " log( \s, \class\(\), \method\(\) ) "

このルールが言っていることは、1 つの文字列引数を持つ log の呼び出しを見つけ、それを、補助関数classmethodによって決定される 2 つの追加の引数を持つ log の呼び出しに置き換えること です。

これらの関数は、ルールが一致を検出した AST ノード ルートの包含メソッド名と包含クラス名を決定します。

ルールは「ソース形式」で記述されていますが、実際には AST と照合し、見つかった AST を変更された AST に置き換えます。

変更されたソースを元に戻すには、DMS に単に prettyprint (適切なレイアウトを作成するため) または fidelity print (古いコードのレイアウトを維持したい場合) を依頼します。DMS はコメント、基数などを保持します。\

既存のアプリケーションに「ログ」関数の定義が複数ある場合は、修飾子を追加する必要があります。

... if IsDesiredLog().

IsDesiredLogは、DMS のシンボル テーブルと継承情報を使用して、特定のログが対象の定義を参照しているかどうかを判断します

于 2010-10-12T07:43:11.560 に答える
1

置換が必要な行が少数のカテゴリに分類される場合、必要なのは Perl です。

find -name '*.java' | xargs perl -pi -e 's/log\(([^,)]*?)\)/log(\1, "foo", "bar")/g'

クラス名 (ファイル名から派生したもの) を 2 番目の引数として入れるスクリプトをハックするのはそれほど難しくないと思います。3 番目の引数としてメソッド名を取得することは、読者の課題として残されています。

于 2010-10-11T13:10:07.700 に答える
0

「このログはどこから来たのですか?」にクラスとメソッド名が必要な場合 データを入力してから、別のオプションとして、ログメソッドでスタックトレースを出力します。例えば

public void log(String text)
{
   StringWriter sw = new StringWriter();
   PrintWriter pw = new PrintWriter(sw, true);
   new Throwable.printStackTrace(pw);
   pw.flush();
   sw.flush();
   String stackTraceAsLog = sw.toString();
   //do something with text and stackTraceAsLog
}
于 2010-10-11T14:31:44.340 に答える
0

実際、あなたの問題は、すべての発生を置き換えることができるクリックアンドプレイエンジンを使用しないことです

log("some weird message");

log(this.getClass(), new Exception().getStackTrace()[1].getMethodName());

さまざまなケース (例として静的メソッドなど) に取り組む機会がほとんどないためです。

スプーンをご覧になることをお勧めします。このツールを使用すると、ソース コードの解析と変換が可能になり、明らかにコード ベースの低速で制御された操作で操作を実行できます。

ただし、実際のメソッドを 1 つの調査スタック トレースで情報を取得するように変換することを検討することもできます。さらに良いのは、log4j と正しい情報を表示するログ フォーマッタを内部的に使用することです。

于 2010-10-11T12:41:55.040 に答える
0

log(私は検索して置き換えますlog(@class, @methodname,

次に、任意の言語 (Java を含む) で小さなスクリプトを作成して、クラス名とメソッド名を検索し、@class トークンと @method トークンを置き換えます...

幸運を

于 2010-10-11T13:29:52.630 に答える