ImportProject: Fixed compile_commands.json problems

This commit is contained in:
Daniel Marjamäki 2020-12-25 14:45:48 +01:00
parent 87379683e0
commit f700d81e59
2 changed files with 42 additions and 18 deletions

View File

@ -220,21 +220,26 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
static std::string readUntil(const std::string &command, std::string::size_type *pos, const char until[]) static std::string readUntil(const std::string &command, std::string::size_type *pos, const char until[])
{ {
std::string ret; std::string ret;
bool escapedString = false;
bool str = false; bool str = false;
bool escape = false; bool escape = false;
for (; *pos < command.size() && (str || !std::strchr(until, command[*pos])); (*pos)++) { for (; *pos < command.size() && (str || !std::strchr(until, command[*pos])); (*pos)++) {
if (escape) { if (escape)
escape = false; escape = false;
if (!std::strchr("\\\"\'", command[*pos])) else if (command[*pos] == '\\') {
ret += '\\'; if (str)
ret += command[*pos]; escape = true;
} else if (str && command[*pos] == '\\') else if (command[*pos + 1] == '"') {
escape = true; if (escapedString)
else { return ret + "\\\"";
if (command[*pos] == '\"') escapedString = true;
str = !str; ret += "\\\"";
ret += command[*pos]; (*pos)++;
} continue;
}
} else if (command[*pos] == '\"')
str = !str;
ret += command[*pos];
} }
return ret; return ret;
} }
@ -246,6 +251,8 @@ static std::string unescape(const std::string &in)
for (char c: in) { for (char c: in) {
if (escape) { if (escape) {
escape = false; escape = false;
if (!std::strchr("\\\"\'",c))
out += "\\";
out += c; out += c;
} else if (c == '\\') } else if (c == '\\')
escape = true; escape = true;
@ -259,8 +266,6 @@ void ImportProject::FileSettings::parseCommand(std::string command)
{ {
std::string defs; std::string defs;
command = unescape(command);
// Parse command.. // Parse command..
std::string::size_type pos = 0; std::string::size_type pos = 0;
while (std::string::npos != (pos = command.find(' ',pos))) { while (std::string::npos != (pos = command.find(' ',pos))) {
@ -280,8 +285,12 @@ void ImportProject::FileSettings::parseCommand(std::string command)
} }
const std::string fval = readUntil(command, &pos, " ="); const std::string fval = readUntil(command, &pos, " =");
if (F=='D') { if (F=='D') {
const std::string defval = readUntil(command, &pos, " "); std::string defval = readUntil(command, &pos, " ");
defs += fval; defs += fval;
if (defval.size() >= 3 && defval.compare(0,2,"=\"")==0 && defval.back()=='\"')
defval = "=" + unescape(defval.substr(2, defval.size() - 3));
else if (defval.size() >= 5 && defval.compare(0,3,"=\\\"")==0 && endsWith(defval,"\\\"",2))
defval = "=\"" + unescape(defval.substr(3, defval.size() - 5)) + "\"";
if (!defval.empty()) if (!defval.empty())
defs += defval; defs += defval;
defs += ';'; defs += ';';

View File

@ -50,6 +50,7 @@ private:
TEST_CASE(importCompileCommands5); // Windows/CMake/Ninja generated comile_commands.json TEST_CASE(importCompileCommands5); // Windows/CMake/Ninja generated comile_commands.json
TEST_CASE(importCompileCommands6); // Windows/CMake/Ninja generated comile_commands.json with spaces TEST_CASE(importCompileCommands6); // Windows/CMake/Ninja generated comile_commands.json with spaces
TEST_CASE(importCompileCommands7); // linux: "/home/danielm/cppcheck 2" TEST_CASE(importCompileCommands7); // linux: "/home/danielm/cppcheck 2"
TEST_CASE(importCompileCommands8); // Windows: "C:\Users\danielm\cppcheck"
TEST_CASE(importCompileCommandsArgumentsSection); // Handle arguments section TEST_CASE(importCompileCommandsArgumentsSection); // Handle arguments section
TEST_CASE(importCompileCommandsNoCommandSection); // gracefully handles malformed json TEST_CASE(importCompileCommandsNoCommandSection); // gracefully handles malformed json
TEST_CASE(importCppcheckGuiProject); TEST_CASE(importCppcheckGuiProject);
@ -153,7 +154,6 @@ private:
} }
void importCompileCommands5() const { void importCompileCommands5() const {
/* TODO I am not sure if these are escaped properly
const char json[] = const char json[] =
R"([{ R"([{
"directory": "C:/Users/dan/git/build-test-cppcheck-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug", "directory": "C:/Users/dan/git/build-test-cppcheck-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug",
@ -170,11 +170,9 @@ private:
importer.importCompileCommands(istr); importer.importCompileCommands(istr);
ASSERT_EQUALS(2, importer.fileSettings.size()); ASSERT_EQUALS(2, importer.fileSettings.size());
ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/src/", importer.fileSettings.begin()->includePaths.front()); ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/src/", importer.fileSettings.begin()->includePaths.front());
*/
} }
void importCompileCommands6() const { void importCompileCommands6() const {
/* TODO I am not sure if these are escaped properly
const char json[] = const char json[] =
R"([{ R"([{
"directory": "C:/Users/dan/git/build-test-cppcheck-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug", "directory": "C:/Users/dan/git/build-test-cppcheck-Desktop_Qt_5_15_0_MSVC2019_64bit-Debug",
@ -191,7 +189,6 @@ private:
importer.importCompileCommands(istr); importer.importCompileCommands(istr);
ASSERT_EQUALS(2, importer.fileSettings.size()); ASSERT_EQUALS(2, importer.fileSettings.size());
ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/second src/", importer.fileSettings.begin()->includePaths.front()); ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/second src/", importer.fileSettings.begin()->includePaths.front());
*/
} }
@ -213,6 +210,24 @@ private:
// TODO ASSERT_EQUALS("/home/danielm/cppcheck 2/externals/", importer.fileSettings.begin()->includePaths.back()); // TODO ASSERT_EQUALS("/home/danielm/cppcheck 2/externals/", importer.fileSettings.begin()->includePaths.back());
} }
void importCompileCommands8() const {
// cmake -DFILESDIR="C:\Program Files\Cppcheck" -G"NMake Makefiles" ..
const char json[] =
R"([{
"directory": "C:/Users/danielm/cppcheck/build/lib",
"command": "C:\\PROGRA~2\\MICROS~2\\2017\\COMMUN~1\\VC\\Tools\\MSVC\\1412~1.258\\bin\\Hostx64\\x64\\cl.exe /nologo /TP -DFILESDIR=\"\\\"C:\\Program Files\\Cppcheck\\\"\" -IC:\\Users\\danielm\\cppcheck\\build\\lib -IC:\\Users\\danielm\\cppcheck\\lib -c C:\\Users\\danielm\\cppcheck\\lib\\astutils.cpp",
"file": "C:/Users/danielm/cppcheck/lib/astutils.cpp"
}])";
std::istringstream istr(json);
TestImporter importer;
importer.importCompileCommands(istr);
ASSERT_EQUALS(1, importer.fileSettings.size());
ASSERT_EQUALS("FILESDIR=\"C:\\Program Files\\Cppcheck\"", importer.fileSettings.begin()->defines);
ASSERT_EQUALS(2, importer.fileSettings.begin()->includePaths.size());
ASSERT_EQUALS("C:/Users/danielm/cppcheck/build/lib/", importer.fileSettings.begin()->includePaths.front());
ASSERT_EQUALS("C:/Users/danielm/cppcheck/lib/", importer.fileSettings.begin()->includePaths.back());
}
void importCompileCommandsArgumentsSection() const { void importCompileCommandsArgumentsSection() const {
const char json[] = "[ { \"directory\": \"/tmp/\"," const char json[] = "[ { \"directory\": \"/tmp/\","
"\"arguments\": [\"gcc\", \"-c\", \"src.c\"]," "\"arguments\": [\"gcc\", \"-c\", \"src.c\"],"