Durante una revisione del codice, ho trovato il codice sorgente in questo modo:Rileva automaticamente identico std :: string consecutivo :: find() chiama
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);
}
}
All'interno di questa funzione, std :: string :: find() è chiamato tre volte con lo stesso modello (qui "::").
Questo codice può naturalmente essere riscritta per
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);
}
}
dove ritrovamento viene chiamato solo una volta.
Domanda
Qualcuno sa una strategia per il rilevamento di un tale modello come questo? Sto avendo una base di codice enorme, in cui ho intenzione di individuare questo modello. Ho intenzione di utilizzare un ambiente Windows o Linux.
possibili strategie
- Usare/adattare uno strumento di analisi statica del codice, come cppcheck per rilevare questo tipo di stranezze.
- Cerca all'interno del code base con espressione regolare.
- Utilizzare/Adattare Clang-Tidy per il rilevamento di questo modello.
- Scrivere un correttore personalizzato in una lingua (ad es. Python) che rilevi questi problemi. In questo caso, il controllo dovrebbe essere eseguito su codice preelaborato.
di No Go
- recensione Manuale
Update 1
ho deciso di iniziare con un potenziale strategia di 1). Ho intenzione di adattare cppcheck per catturare questo problema.
Cppcheck offre la possibilità di scrivere regole personalizzate, basate su espressioni regolari PCRE. Per questo, cppcheck deve essere compilato con il supporto PCRE abilitato. Dal momento che l'ambiente di test corrente è basato-Linux, i seguenti comandi possono essere utilizzati per scaricare l'ultima versione di cppcheck:
git clone https://github.com/danmar/cppcheck.git && cd cppcheck
Dopo di che, compilare e installare lo strumento come segue:
sudo make install HAVE_RULES=yes
Ora la configurazione dello strumento di base è terminata. Per sviluppare una regola cppcheck, ho preparato un semplice caso di test (file: test.cpp), simile al codice di esempio nella prima sezione di questo articolo. Questo file contiene tre funzioni e la regola cppcheck deve emettere un avviso su f_odd
e f_odd1
su chiamate identiche consecutive da 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);
}
}
Fin qui tutto bene. Ora cppcheck deve essere ottimizzato per intercettare le chiamate identiche consecutive da std::string::find
. Per questo ho creato un cppcheck_rule-file che contiene un'espressione regolare che corrisponde consecutivi identici std::string::find
chiamate:
<?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>
Questo file può essere utilizzato per estendere cppcheck su un nuovo controllo. proviamo:
cppcheck --rule-file=rules/rule.xml test/test.cpp
e l'uscita è
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.
Ora, identici consecutivi std::string::find
chiamate possono essere rilevati in codici C/C++. Qualcuno conosce una soluzione migliore/più efficiente o più intelligente?
Riferimenti:
È possibile scrivere il proprio controllo [clang-ordine] (http://clang.llvm.org/extra/clang-tidy/) per rilevare questo. – Jonas
@Jonas Grazie a clang-tidy è un altro potente strumento che potrebbe fare il lavoro. Aggiornerò la mia potenziale sezione di soluzioni. – orbitcowboy
Puoi ripetere la tua domanda in modo che non sembri una richiesta di suggerimenti sugli strumenti? Questi sono [esplicitamente off-topic] (https://stackoverflow.com/help/on-topic) su questo sito. – 5gon12eder