2019年7月16日火曜日

[Visual Studio] ステップフィルターのカスタマイズでデバッグを楽にする

かなり前に Visualizer を紹介しましたが、今回はステップフィルターの紹介をします。
ブログズミ: [Visual Studio] デバッガー変数表示のカスタマイズ

Visual Studio ではステップインする際に、
特定の関数には入っていかないようにする設定がユーザー定義でできるようになっています。
Customize C++ stepping behavior independent of Just My Code settings

それを設定して何が便利なのか?
よくある事例で見てみましょう。

まずは設定なし。

そして、設定あり。


どちらも UnitTestSource::GetInstance().Initialize(); の Initialize にステップインしようとしている様子です。
いかがでしょう?
前者のように GetInstance にいちいちステップインしちゃうのが煩わしく感じてる人は多いのではないでしょうか?

ステップフィルターを設定した後者は GetInstance() の中に入っていかなかったですね。
このように、1行に複数の関数呼び出しがある場合に、興味がない関数へのステップインをしないようにするとデバッグがしやすくなると思います。

今回紹介する .natstepfilter を使って、この煩わしさから開放されましょう!


設定の仕方
.natstepfilter 拡張子のファイルを作成し、
「%VsInstallDirectory%\Common7\Packages\Debugger\Visualizers」もしくは「%USERPROFILE%\My Documents\\Visualizers」に保存するだけです。

ファイルのフォーマットは xml になっています。
この xml で関数の指定とその関数に対して、ステップインするか、しないかの設定を行います。
以下は GetInstance にステップインしないようにする .natstepfilter の例です。

<Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>

.natstepfilter は複数のファイルに分けて書くことができますので、stl.natstepfiler と iutest.natstepfilter のように namespace や用途に合わせて分けておくと便利だと思います。



iutest の例
さて、上記で iutest での GetInstance の事例を紹介しましたが、
iutest では、テスティングフレームワークの利用者はフレームワークの内部実装には興味がなく、テストコードにのみ興味があるはずという考えのもと、テストコードから内部実装にステップインしないようにした natstepfilter を提供しています。

<?xml version="1.0" encoding="utf-8"?>  
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">  
    <Function>
        <Name>iutest::TestEnv::environments</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestSource::Run</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionSuccess</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionFailure</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionResult.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionHelper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertPred.*Helper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::PrintToString.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::WithParamInterface.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::Test::RecordProperty.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestImpl::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::detail::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iuutil::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::matchers.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::internal::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>std::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
</StepFilter>

ユーザーが集中したいコードにのみ、ステップインするのでテストコードのデバッグがしやすくなったのではないか、と思ってます。

Resharper C++ をインストールしていると利用できない
https://pleiades.io/help/resharper/Reference_Options_Tools_Debugger_CPP.html
Resharper C++ にステップフィルターの機能があるため、すべてそちらの管理になります。
そのため、.natstepfilter の設定は引き継がれません。(継承かインポートできると嬉しいですが・・・)

Resharper 使っている方はご注意くださいmm


最後に
Visual Studio は "知っていれば" 便利な機能が結構あります。
ツールは使ってなんぼ。ただ使ってるだけじゃもったいないです。

これまでもいくつか機能を紹介してきましたが、今後も Visual Studio にはお世話になると思うので、また便利な機能を知ったら紹介したいと思います。

では。

2019年7月11日木曜日

[GitHub] Squash and merge したブランチを自動でまとめて消す



PR を普通にマージしたときは、merged なブランチを列挙して branch -d すればよかったのですが、
(こんな感じ: git branch --merged | grep -v \\* | grep / | xargs -I % git branch -d %)
「Squash and merge」すると、実際にブランチをマージしているわけではないので、branch --merged に列挙されず、上記方法でお掃除できずに困ってました。

結構、ローカルブランチが溜まってきたのでお掃除したいなーと思い、調べてみたらドンピシャな記事がありました。
GitHub で Squash merge されたブランチを削除する · ryym.log

詳しいことは、こちらの記事を読んでいただければと思います。


で、これで終わると、この記事自体の内容がないよう、となってしまうので、自分好みにカスタムした alias をおいておきます。

del-squashed-branch = "!f(){ base_branch=${1:-master} && echo ${base_branch} && git checkout -q ${base_branch} && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base origin/${base_branch} $branch) && [[ $(git cherry origin/${base_branch} $(git commit-tree $(git rev-parse $branch^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done; git checkout -q -;};f"
  del-sq = !git del-squashed-branch `git def-branch`
  def-branch = !git ls-remote --symref origin HEAD | head -n 1 | cut -f 1 | cut -d "/" -f 3-

もとの shell command だと master との比較になってましたが、他のブランチを指定できるようにしました。
iutest の開発中は develop に PR 出して、ある程度安定したら master にマージするようにしているので、
develop ブランチを指定して、お掃除したかったのでこうしました。

また、短いエイリアスの方はデフォルトブランチを指定するようにしました。
(これは仕事のときに使うことを想定してこうした)

今回は以上です。


追記
git symbolic-ref --short refs/remotes/origin/HEAD | cut -d "/" -f 2
では正しく GitHub のデフォルトブランチを取得できてませんでした。
git ls-remote --symref origin HEAD | head -n 1 | cut -f 1 | cut -d "/" -f 3-
に修正しました。


2019年7月5日金曜日

[Blogger][AdSense] 「ads.txt ファイルが含まれていないサイトがあります」 に対応した

このブログでは Google AdSense で広告掲載をしています。
たまーにレポートを眺めに AdSense を見に行くのですが、いつの間にか以下のような警告文が出るようになってました。
「要注意 - ads.txt ファイルが含まれていないサイトがあります。収益に重大な影響が出ないよう、この問題を今すぐ修正してください。」



収益にこだわりはないのですが、警告は無視できない体質なので対応しました。

ads.txt とは?
警告文のヘルプを開くと以下のようなことが書かれています。


Blogger に ads.txt を設定する
Blogger の場合のヘルプもちゃんとあります。


ヘルプに従えば問題なく設定できると思います。





ここに書く内容は、AdSense のヘルプを参考に以下のように入力します。

google.com, pub-0000000000000000, DIRECT, f08c47fec0942fa0

「pub-0000000000000000」の部分は、サイト運営者ID に置き換えてください。
サイト運営者 ID を確認する - AdSense ヘルプ

入力ができたら、「変更を保存」で設定完了です。
再び、AdSense にログインしてみたところ、警告が消えました!

よかったよかった。