Json: Use simple json library picojson to read compile databases

This commit is contained in:
Daniel Marjamäki 2019-01-05 17:45:07 +01:00
parent 615903c6be
commit 5f5c33baf2
3 changed files with 1085 additions and 91 deletions

1010
externals/picojson.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
#include "tokenize.h" #include "tokenize.h"
#include "tokenlist.h" #include "tokenlist.h"
#include "utils.h" #include "utils.h"
#include "../externals/picojson.h"
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
@ -192,41 +193,29 @@ ImportProject::Type ImportProject::import(const std::string &filename)
return UNKNOWN; return UNKNOWN;
} }
void ImportProject::importCompileCommands(std::istream &istr) static std::string readUntil(const std::string &command, std::string::size_type *pos, const char until[])
{ {
std::map<std::string, std::string> values; std::string ret;
bool str = false;
// TODO: Use a JSON parser while (*pos < command.size() && (str || !std::strchr(until, command[*pos]))) {
if (command[*pos] == '\\')
Settings settings; ++*pos;
TokenList tokenList(&settings); if (*pos < command.size())
tokenList.createTokens(istr); ret += command[(*pos)++];
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { if (endsWith(ret, '\"'))
if (Token::Match(tok, "%str% : %str% [,}]")) { str = !str;
const std::string& key = tok->str();
const std::string& value = tok->strAt(2);
values[key.substr(1, key.size() - 2U)] = value.substr(1, value.size() - 2U);
} }
return ret;
}
else if (Token::Match(tok, "%str% : [ %str%") && tok->str() == "\"arguments\"") { void ImportProject::FileSettings::parseCommand(const std::string &command)
std::string cmd; {
tok = tok->tokAt(2); std::string defs;
while (Token::Match(tok, ",|[ %str%")) {
const std::string &s = tok->next()->str();
cmd += ' ' + s.substr(1, s.size() - 2);
tok = tok->tokAt(2);
}
values["command"] = cmd.substr(1);
}
else if (tok->str() == "}") { // Parse command..
if (!values["file"].empty() && !values["command"].empty()) {
struct FileSettings fs;
fs.filename = Path::fromNativeSeparators(values["file"]);
const std::string& command = values["command"];
const std::string directory = Path::fromNativeSeparators(values["directory"]);
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))) {
while (pos < command.size() && command[pos] == ' ')
pos++; pos++;
if (pos >= command.size()) if (pos >= command.size())
break; break;
@ -240,54 +229,48 @@ void ImportProject::importCompileCommands(std::istream &istr)
while (pos < command.size() && command[pos] == ' ') while (pos < command.size() && command[pos] == ' ')
++pos; ++pos;
} }
std::string fval; const std::string fval = readUntil(command, &pos, " =");
while (pos < command.size() && command[pos] != ' ' && command[pos] != '=') {
if (command[pos] != '\\')
fval += command[pos];
pos++;
}
if (F=='D') { if (F=='D') {
std::string defval; const std::string defval = readUntil(command, &pos, " ");
bool str = false; defs += fval;
while (pos < command.size() && (str || command[pos] != ' ')) {
if (command.compare(pos, 4, "\\\\\\\"") == 0) {
defval += '\"';
str = !str;
pos += 4;
} else {
defval += command[pos];
pos++;
}
}
fs.defines += fval;
if (!defval.empty()) if (!defval.empty())
fs.defines += defval; defs += defval;
fs.defines += ';'; defs += ';';
} else if (F=='U') } else if (F=='U')
fs.undefs.insert(fval); undefs.insert(fval);
else if (F=='I') else if (F=='I')
fs.includePaths.push_back(fval); includePaths.push_back(fval);
else if (F=='s' && fval.compare(0,3,"td=") == 0) else if (F=='s' && fval.compare(0,3,"td=") == 0)
fs.standard = fval.substr(3); standard = fval.substr(3);
else if (F == 'i' && fval == "system") { else if (F == 'i' && fval == "system") {
++pos; ++pos;
std::string isystem; const std::string isystem = readUntil(command, &pos, " ");
while (pos < command.size() && command[pos] != ' ') { systemIncludePaths.push_back(isystem);
if (command[pos] != '\\')
isystem += command[pos];
pos++;
}
fs.systemIncludePaths.push_back(isystem);
} }
} }
setDefines(defs);
}
void ImportProject::importCompileCommands(std::istream &istr)
{
picojson::value v;
istr >> v;
if (!v.is<picojson::array>())
return;
for (const picojson::value &fileInfo : v.get<picojson::array>()) {
picojson::object obj = fileInfo.get<picojson::object>();
const std::string directory = Path::fromNativeSeparators(obj["directory"].get<std::string>());
const std::string command = obj["command"].get<std::string>();
const std::string file = Path::fromNativeSeparators(obj["file"].get<std::string>());
struct FileSettings fs;
fs.filename = file;
fs.parseCommand(command); // read settings; -D, -I, -U, -std
std::map<std::string, std::string, cppcheck::stricmp> variables; std::map<std::string, std::string, cppcheck::stricmp> variables;
fs.setIncludePaths(directory, fs.includePaths, variables); fs.setIncludePaths(directory, fs.includePaths, variables);
fs.setDefines(fs.defines);
fileSettings.push_back(fs); fileSettings.push_back(fs);
} }
values.clear();
}
}
} }
void ImportProject::importSln(std::istream &istr, const std::string &path) void ImportProject::importSln(std::istream &istr, const std::string &path)

View File

@ -73,6 +73,7 @@ public:
bool msc; bool msc;
bool useMfc; bool useMfc;
void parseCommand(const std::string &command);
void setDefines(std::string defs); void setDefines(std::string defs);
void setIncludePaths(const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables); void setIncludePaths(const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables);
}; };