tools/reduce: better handling of #include

This commit is contained in:
Daniel Marjamäki 2013-01-01 16:18:06 +01:00
parent e824f76ed7
commit f2f8780504
1 changed files with 110 additions and 83 deletions

View File

@ -11,31 +11,31 @@
class CppcheckExecutor : public ErrorLogger { class CppcheckExecutor : public ErrorLogger {
private: private:
CppCheck cppcheck; CppCheck cppcheck;
const std::string line; std::string pattern;
bool foundLine; bool foundLine;
public: public:
CppcheckExecutor(const std::string &l) CppcheckExecutor(int linenr)
: ErrorLogger() : ErrorLogger()
, cppcheck(*this,false) , cppcheck(*this,false)
, line(':' + l + ']')
, foundLine(false) { , foundLine(false) {
std::ostringstream ostr;
ostr << linenr;
pattern = ":" + ostr.str() + "]";
cppcheck.settings().addEnabled("all");
cppcheck.settings().inconclusive = true;
cppcheck.settings()._force = true;
} }
bool run(const char filename[]) { bool run(const char filename[]) {
foundLine = false; foundLine = false;
Settings settings;
settings.addEnabled("all");
settings.inconclusive = true;
settings._force = true;
cppcheck.settings() = settings;
cppcheck.check(filename); cppcheck.check(filename);
return foundLine; return foundLine;
} }
void reportOut(const std::string &outmsg) { } void reportOut(const std::string &outmsg) { }
void reportErr(const ErrorLogger::ErrorMessage &msg) { void reportErr(const ErrorLogger::ErrorMessage &msg) {
if (msg.toString(false).find(line) != std::string::npos) { if (msg.toString(false).find(pattern) != std::string::npos) {
foundLine = true; foundLine = true;
cppcheck.terminate(); cppcheck.terminate();
} }
@ -44,7 +44,7 @@ public:
}; };
static bool test(CppcheckExecutor &cppcheck, const char *filename, const std::vector<std::string> &filedata, const std::size_t line1, const std::size_t line2) static bool test(const char *filename, int linenr, const std::vector<std::string> &filedata, const std::size_t line1, const std::size_t line2)
{ {
std::string path(filename); std::string path(filename);
if (path.find_first_of("\\/") != std::string::npos) if (path.find_first_of("\\/") != std::string::npos)
@ -57,12 +57,14 @@ static bool test(CppcheckExecutor &cppcheck, const char *filename, const std::ve
for (std::size_t i = 0; i < filedata.size(); i++) for (std::size_t i = 0; i < filedata.size(); i++)
fout << ((i>=line1 && i<=line2) ? "" : filedata[i]) << std::endl; fout << ((i>=line1 && i<=line2) ? "" : filedata[i]) << std::endl;
fout.close(); fout.close();
CppcheckExecutor cppcheck(linenr);
return cppcheck.run(tempfilename.c_str()); return cppcheck.run(tempfilename.c_str());
} }
static bool test(CppcheckExecutor &cppcheck, const char *filename, const std::vector<std::string> &filedata, const std::size_t line) static bool test(const char *filename, int linenr, const std::vector<std::string> &filedata, const std::size_t line)
{ {
return test(cppcheck, filename, filedata, line, line); return test(filename, linenr, filedata, line, line);
} }
static void printstr(const std::vector<std::string> &filedata, int i1, int i2) static void printstr(const std::vector<std::string> &filedata, int i1, int i2)
@ -72,31 +74,10 @@ static void printstr(const std::vector<std::string> &filedata, int i1, int i2)
std::cout << i << ":" << filedata[i] << std::endl; std::cout << i << ":" << filedata[i] << std::endl;
} }
int main(int argc, char *argv[]) static std::vector<std::string> readfile(const std::string &filename)
{ {
std::cout << "cppcheck tool that reduce code for a false positive" << std::endl;
if (argc != 3) {
std::cerr << "Syntax: " << argv[0] << " filename line" << std::endl;
return EXIT_FAILURE;
}
const char * const filename = argv[1];
const char * const linenr = argv[2];
std::cout << "make sure false positive can be reproduced" << std::endl;
// Execute Cppcheck on the file..
CppcheckExecutor cppcheck(linenr);
if (!cppcheck.run(filename)) {
std::cerr << "Can't reproduce false positive at line " << linenr << std::endl;
return EXIT_FAILURE;
}
// Read file..
std::vector<std::string> filedata; std::vector<std::string> filedata;
{ std::ifstream fin(filename.c_str());
std::ifstream fin(filename);
std::string line; std::string line;
bool blockComment = false; bool blockComment = false;
while (std::getline(fin,line)) { while (std::getline(fin,line)) {
@ -153,23 +134,69 @@ int main(int argc, char *argv[])
filedata.push_back(line); filedata.push_back(line);
} }
return filedata;
}
int main(int argc, char *argv[])
{
std::cout << "cppcheck tool that reduce code for a false positive" << std::endl;
if (argc != 3) {
std::cerr << "Syntax: " << argv[0] << " filename line" << std::endl;
return EXIT_FAILURE;
} }
const char * const filename = argv[1];
int linenr = std::atoi(argv[2]);
std::cout << "make sure false positive can be reproduced" << std::endl;
// Execute Cppcheck on the file..
{
CppcheckExecutor cppcheck(linenr);
if (!cppcheck.run(filename)) {
std::cerr << "Can't reproduce false positive at line " << linenr << std::endl;
return EXIT_FAILURE;
}
}
// Read file..
std::vector<std::string> filedata(readfile(filename));
// Write resulting code.. // Write resulting code..
if (!test(cppcheck, filename, filedata, ~0)) { if (!test(filename, linenr, filedata, ~0)) {
std::cerr << "Cleanup failed." << std::endl; std::cerr << "Cleanup failed." << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Remove includes.. // Remove includes..
std::set<std::string> headers;
for (std::size_t i = 0; i < filedata.size(); i++) { for (std::size_t i = 0; i < filedata.size(); i++) {
if (filedata[i].compare(0,8,"#include")==0) { if (filedata[i].compare(0,8,"#include")==0) {
if (test(cppcheck, filename, filedata, i)) { if (test(filename, linenr, filedata, i)) {
std::cout << "removed #include : " << filedata[i] << std::endl;
filedata[i].clear(); filedata[i].clear();
std::cout << "removed #include at line " << i << std::endl;
} else { } else {
std::cout << "kept #include at line " << i << std::endl; std::string header = filedata[i];
header = header.substr(1U + header.find_first_of("\"<"));
header = header.erase(header.find_last_of("\">"));
if (headers.find(header) != headers.end()) {
std::cerr << "Failed to reduce headers" << std::endl;
return EXIT_FAILURE;
}
headers.insert(header);
std::string path(filename);
if (path.find_first_of("\\/") != std::string::npos)
path = path.erase(1 + path.find_last_of("\\/"));
else
path.clear();
std::cout << "expand #include : " << (path+header) << std::endl;
std::vector<std::string> data(readfile(path+header));
if (!data.empty()) {
filedata[i].clear();
filedata.insert(filedata.begin()+i, data.begin(), data.end());
linenr += data.size();
}
} }
} }
} }
@ -185,7 +212,7 @@ int main(int argc, char *argv[])
// some kind of single line declaration // some kind of single line declaration
if (std::isalpha(startChar) && endChar==';') { if (std::isalpha(startChar) && endChar==';') {
if (test(cppcheck, filename, filedata, i)) { if (test(filename, linenr, filedata, i)) {
filedata[i].clear(); filedata[i].clear();
std::cout << "removed declaration at line " << i << std::endl; std::cout << "removed declaration at line " << i << std::endl;
} else { } else {
@ -229,7 +256,7 @@ int main(int argc, char *argv[])
// does block of code end with a '}' // does block of code end with a '}'
if ((pos2 < filedata.size()) && (filedata[pos2] == "}" || filedata[pos2] == "};")) { if ((pos2 < filedata.size()) && (filedata[pos2] == "}" || filedata[pos2] == "};")) {
if (test(cppcheck, filename, filedata, pos, pos2)) { if (test(filename, linenr, filedata, pos, pos2)) {
for (i = pos; i <= pos2; i++) for (i = pos; i <= pos2; i++)
filedata[i].clear(); filedata[i].clear();
std::cout << "removed block of code at lines " << pos << "-" << pos2 << std::endl; std::cout << "removed block of code at lines " << pos << "-" << pos2 << std::endl;