Während eines Code-Review, fand ich Quellcode wie folgt aus:automatisch identisch aufeinander folgenden std :: string erkennen :: find() ruft
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);
}
}
Innerhalb dieser Funktion std :: string :: find() wird dreimal mit dem gleichen Muster aufgerufen (hier "::").
Dieser Code kann natürlich
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);
}
}
wo find aufgerufen wird nur einmal
Refactoring werden.Frage
Kennt jemand eine Strategie wie dieses ein solches Muster auf das Erkennen? Ich habe eine riesige Codebasis, wo ich dieses Muster erkennen möchte. Ich möchte eine Windows- oder Linux-Umgebung verwenden.
Mögliche Strategien
- Verwendung/Anpassung eines statischen Code-Analyse-Tool, wie cppcheck diese Art von Seltsamkeiten zu erkennen.
- In der Code-Basis mit regulärem Ausdruck suchen.
- Verwenden Sie/clang-ordentlich anpassen, um dieses Muster zu erkennen.
- Schreiben Sie eine benutzerdefinierte Überprüfung in einer Sprache (z. B. Python), die diese Probleme erkennt. In diesem Fall sollte die Überprüfung auf vorverarbeitetem Code durchgeführt werden.
No Gos
- Handbuch Bewertung
Update 1
entschied ich mich mit potentieller Strategie 1) zu starten. Ich plane, cppcheck anzupassen, um dieses Problem zu finden.
Cppcheck bietet die Möglichkeit, benutzerdefinierte Regeln basierend auf regulären PCRE-Ausdrücken zu schreiben. Dazu muss cppcheck mit aktivierter PCRE-Unterstützung kompiliert werden. Da die aktuelle Testumgebung auf Linux-Basis, können die folgenden Befehle, um die neueste Version von cppcheck zum Download verwendet werden:
git clone https://github.com/danmar/cppcheck.git && cd cppcheck
Danach, kompilieren und installieren Sie das Tool wie folgt:
sudo make install HAVE_RULES=yes
Jetzt ist das grundlegende Tool Setup abgeschlossen. Um eine cppcheck-Regel zu entwickeln, habe ich einen einfachen Testfall (Datei: test.cpp) erstellt, ähnlich dem Beispielcode im ersten Abschnitt dieses Artikels. Diese Datei enthält drei Funktionen und die cppcheck-Regel soll unter f_odd
und f_odd1
über aufeinanderfolgende identische std::string::find
Aufrufe eine Warnung ausgeben.
testen.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);
}
}
So weit so gut. Jetzt muss cppcheck optimiert werden, um aufeinanderfolgende identische std::string::find
Aufrufe zu erhalten. Dazu habe ich eine cppcheck_rule-file geschaffen, die einen regulären Ausdruck enthält, die aufeinanderfolgende identische std::string::find
Anrufe übereinstimmt:
<?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>
Diese Datei verwendet werden kann cppcheck über einen neuen Scheck zu erweitern. Lets try:
cppcheck --rule-file=rules/rule.xml test/test.cpp
und der Ausgang ist
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.
nun identische aufeinanderfolgende std::string::find
Anrufe können in C/C++ Codes detektiert werden. Kennt jemand eine bessere/effizientere oder schlauere Lösung? Referenzen
:
Sie könnten Ihre eigenen [clang-ordentlich] (http://clang.llvm.org/extra/clang-tidy/) schreiben, um dies zu erkennen. – Jonas
@Jonas Danke clang-Tidy ist ein weiteres potentia Werkzeug, das den Job machen könnte. Ich werde meinen Bereich für mögliche Lösungen aktualisieren. – orbitcowboy
Können Sie Ihre Frage so umformulieren, dass sie nicht wie eine Anforderung von Toolempfehlungen aussieht? Diese sind [explizit außerhalb des Themas] (https://stackoverflow.com/help/on-topic) auf dieser Site. – 5gon12eder