を呼び出して、私はこのようなソースコードが見つかりました:のstd ::文字列、この関数内で自動的に同一の連続したSTDを検出::文字列::見つける()は、コードレビューの際
void f_odd(std::string &className, std::string &testName)
{
if (className.find("::") != std::string::npos)
{
testName = className.substr(className.find("::") + 2);
(void)className.erase(className.find("::"), std::string::npos);
}
}
を::見つける()であります同じパターン(ここでは "::")で3回呼ばれます。
このコードはもちろん、検索は一度だけ呼び出され
void f(std::string &className, std::string &testName)
{
const size_t endOfClassNamePos = className.find("::");
if (endOfClassNamePos != std::string::npos)
{
testName = className.substr(endOfClassNamePos + 2);
(void)className.erase(endOfClassNamePos, std::string::npos);
}
}
にリファクタリングすることができます。
質問
誰もがこのようなパターンを検出するための戦略を知っていますか?私はこのパターンを見つけようとしている巨大なコードベースを持っています。 私は、WindowsまたはLinux環境を使用する予定です。
潜在的な戦略
- 使用/奇妙これらの種類を検出するcppcheckのように、静的コード解析ツールを適応させます。
- コードベース内で正規表現で検索します。
- このパターンの検出には、/ clang-tidyを使用してください。
- これらの問題を検出する言語(Pythonなど)でカスタムチェッカーを作成します。この場合、チェックは事前処理されたコードで実行する必要があります。
ノーゴーの
- マニュアルレビュー
更新は1
私は、潜在的な戦略1)を開始することを決めました。私はこの問題を捕まえるためにcppcheckを適応させる予定です。
Cppcheckは、PCRE正規表現に基づいてカスタマイズされたルールを書くことができます。このためには、cppcheckをPCREサポートを有効にしてコンパイルする必要があります。以下のようなツールをコンパイルしてインストールし、その後
git clone https://github.com/danmar/cppcheck.git && cd cppcheck
:現在のテスト環境はLinuxベースされているので、次のコマンドはcppcheckの最新バージョンをダウンロードするために使用することができ
sudo make install HAVE_RULES=yes
これで基本的なツールの設定が完了しました。 cppcheckルールを開発するために、私はこの記事の最初のセクションのサンプルコードに似た単純なテストケース(file:test.cpp)を用意しました。このファイルには3つの関数が含まれており、cppcheck-ruleはf_odd
とf_odd1
で連続して同じstd::string::find
呼び出しについての警告を発するものとします。
試験。cpp:
#include <string>
void f(std::string &className, std::string &testName)
{
const size_t endOfClassNamePos = className.find("::");
if (endOfClassNamePos != std::string::npos)
{
testName = className.substr(endOfClassNamePos + 2);
(void)className.erase(endOfClassNamePos, std::string::npos);
}
}
void f_odd(std::string &className, std::string &testName)
{
if (className.find("::") != std::string::npos)
{
testName = className.substr(className.find("::") + 2);
(void)className.erase(className.find("::"), std::string::npos);
}
}
#define A "::"
#define B "::"
#define C "::"
void f_odd1(std::string &className, std::string &testName)
{
if (className.find(A) != std::string::npos)
{
testName = className.substr(className.find(B) + 2);
(void)className.erase(className.find(C), std::string::npos);
}
}
これまでのところとても良いです。連続して同じstd::string::find
コールを受信するには、cppcheckを調整する必要があります。このファイルには、新しいチェックについてcppcheckを拡張するために使用することができます
<?xml version="1.0"?>
<rule>
<tokenlist>normal</tokenlist>
<pattern><![CDATA[([a-zA-Z][a-zA-Z0-9]*)(\s*\.\s*find)(\s*\(\s*\"[ -~]*\"\s*\))[ -\{\n]*(\1\2\3)+[ -z\n]]]></pattern>
<message>
<severity>style</severity>
<summary>Found identical consecutive std::string::find calls.</summary>
</message>
:。このために私は連続で同じstd::string::find
呼び出しにマッチする正規表現が含まれているcppcheck_rule-fileを作成しました
cppcheck --rule-file=rules/rule.xml test/test.cpp
の出力は次に、同じ連続std::string::find
コールはC/C++コードで検出することができる
Checking test/test.cpp...
[test/test.cpp:14]: (style) Found identical consecutive std::string::find calls.
[test/test.cpp:26]: (style) Found identical consecutive std::string::find calls.
ある: が試すことができます。誰かがより良い/より効率的な、あるいはより巧妙な解決策を知っていますか?
参考文献:
これを検出するには、独自の[clang-tidy](http://clang.llvm.org/extra/clang-tidy/)チェックを書くことができます。 – Jonas
@Jonasありがとうclang-tidyは、仕事をすることができるもう一つの強力なツールです。潜在的なソリューションのセクションを更新します。 – orbitcowboy
あなたの質問をツールの推奨事項のように表示されないように修正することはできますか?これらは、このサイトの[明示的にオフトピック](https://stackoverflow.com/help/on-topic)です。 – 5gon12eder