在代碼審查,我發現源代碼是這樣的:自動檢測相同的連續的std :: string :: find()方法調用
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);
}
}
在這個函數中的std :: string :: find()方法是被稱爲三次相同的模式(在這裏「::」)。
此代碼當然可以重構爲
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)來檢測這些問題。在這種情況下,應該對預處理代碼執行檢查。
否Go的
- 人工審查
更新1
我決定開始與潛在的戰略1)。我計劃改編cppcheck來解決這個問題。
Cppcheck提供了基於PCRE正則表達式編寫自定義規則的可能性。爲此,必須使用啓用的PCRE支持編譯cppcheck。由於目前的測試環境是基於Linux的,下面的命令可以用來下載最新版本的cppcheck的:
git clone https://github.com/danmar/cppcheck.git && cd cppcheck
之後,編譯和安裝工具如下:
sudo make install HAVE_RULES=yes
現在基本的工具設置完成了。爲了開發一個cppcheck規則,我準備了一個簡單的測試用例(file:test.cpp),類似於本文第一部分的示例代碼。該文件包含三個功能,並且cppcheck規則將在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);
}
}
到目前爲止這麼好。現在cppcheck必須進行調整才能捕獲連續的相同std::string::find
調用。爲了這個,我已經創造了一個cppcheck_rule-file包含匹配連續的相同std::string::find
調用正則表達式:
<?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>
這個文件可以用來擴展一個新的檢查cppcheck。 讓我們試着:
cppcheck --rule-file=rules/rule.xml test/test.cpp
並且輸出是
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.
現在,相同的連續std::string::find
呼叫可以在C/C++代碼來檢測。有人知道更好/更有效或更聰明的解決方案嗎?
參考文獻:
你可以編寫你自己的[clang-tidy](http://clang.llvm.org/extra/clang-tidy/)檢查來檢測這個。 – Jonas
@Jonas謝謝clang-tidy是另一個可以完成這項工作的潛力工具。我會更新我的潛在解決方案部分。 – orbitcowboy
您是否可以重新說明您的問題,使其不會顯示爲對工具建議的請求?這些網站上的[明確脫離主題](https://stackoverflow.com/help/on-topic)。 – 5gon12eder