2013年7月27日土曜日

FxCop カスタムルールの作成(配置と実行)

FxCop カスタムルールの作成(ビルドまで)」で作成したルールを実際に動かします。

本当はデバッガで動作を追っかけたいところですが、VS2012Expressではデバッガで外部ツール(プログラム)を実行させるのは難しいんですかね。残念ですがデバッガの使用はあきらめます。

ちなみに、Express以外の有償のエディションであれば、プロジェクトのプロパティで「デバッグ」を開き、「開始動作」を「外部プログラムの開始」に、「外部プログラムの開始」に「FxCopCmd.exe」へのパスを、「コマンドライン引数」に「/f:」に続いて静的分析したいアセンブリのフルパスを、さらに「/c」のスイッチを付けてコンソールに結果を出力させるようにしておくことで、作成したルールをデバッグできる「はず」です。

デバッグ時の注意点としては、VisualStudioもデバッグしたいルールアセンブリを読み込んでしまうので、修正して再配置するときは、VisualStudioを一度終了させる必要があります。面倒ですが仕方ない。

さて、ビルドしたルールアセンブリは、Program FilesのVSのフォルダの、「Team Tools\Static Analysis Tools\FxCop\Rules」のフォルダにコピーします。デバッグする場合は"pdb"ファイルも一緒にコピーします。

作成したルールアセンブリが、正しく動作するかどうかを確認するテスト用アセンブリも作っておきます。VS2012Expressで新規プロジェクトを作成し、クラスライブラリを作ります。名前は「DataTableRuleDummy」とでもします。

テスト用アセンブリには一つクラスを作ります。ルールがすべて引っかかるように、以下のようにしてみました。

public class Dummy
{
  private DataTable table;

  public Dummy(DataTable table)
  {
    this.table = table;
  }

  public int SumOfQuantity
  {
    get
    {
      int sum = 0;
      foreach (DataRow row in table.Rows)
      {
        sum += (int)row["qty"];
      }
      return sum;
    }
  }

  public int FirstOrder
  {
    get { return (int)table.Rows[0]["order"]; }
  }

  public void SetDone()
  {
    foreach (var row in table.Rows.Cast<DataRow>().Where(r => (int)r["f"] == 0))
    {
      row["f"] = 1;
      row["doneAt"] = DateTime.Now;
    }
  }
}

で、テスト用のアセンブリもビルドしておきます。

実行はここではFxCopのコマンド版で試してみます。GUI版やVisualStudioビルド統合版も多分動くはず。

コマンドプロンプトを起動し、以下のように入力します。(もちろん、実際は改行なしです。)

>"C:\Program Files\Microsoft Visual Studio 11.0\Team Tools\
Static Analysis Tools\FxCop\FxCopCmd.exe" /f:D:\Projects\Da
taTableRuleDummy\bin\Debug\DataTableRuleDummy.dll /c

これで実行してみると以下の結果となりました。



4つのルールがすべて出力されています。続いて、テスト用アセンブリを以下のように修正してビルド。その後もう一度FxCopを実行させてみます。

public class Dummy
{
  private DataTable table;

  public Dummy(DataTable table)
  {
    this.table = table;
  }

  public int SumOfQuantity
  {
    get { return table.AsEnumerable().Sum(r => r.Field<int>("qty")); }
  }

  public int FirstOrder
  {
    get { return table.AsEnumerable().First().Field<int>("order"); }
  }

  public void SetDone()
  {
    foreach (var row in table.Select("flag=0"))
    {
      row.SetField("flag", 1);
      row.SetField("doneAt", DateTime.Now);
    }
  }
}


DataTable関連の警告が出なくなりましたね。

と、とてもとても時間がかかりましたが、古式ゆかしきDataSetも、工夫次第でそれなりに使えるということを言いたかったのです。

あと、会社やプロジェクト単位でコーディングスタンダードを用意している場合、コードレビューでスタンダードに適合しているかをチェックするなんてのはやってらんないので、このようにFxCopのカスタムルールを一度作ってしまえば、スタンダードに適合しているか否かのチェックをFxCopに任せられるので、あとがずいぶん楽になります。このために参考になる方もいるのではないかなぁ。と思いました。

0 件のコメント:

コメントを投稿