1 #include "cmConfigure.h" // IWYU pragma: keep
10 #include "cmsys/FStream.hxx"
12 #include "cmSystemTools.h"
14 class CompileCommandParser
17 class CommandType : public std::map<std::string, std::string>
20 std::string const& at(std::string const& k) const
22 auto i = this->find(k);
23 if (i != this->end()) {
26 static std::string emptyString;
30 using TranslationUnitsType = std::vector<CommandType>;
32 CompileCommandParser(std::istream& input)
39 this->NextNonWhitespace();
40 this->ParseTranslationUnits();
43 const TranslationUnitsType& GetTranslationUnits()
45 return this->TranslationUnits;
49 void ParseTranslationUnits()
51 this->TranslationUnits = TranslationUnitsType();
52 this->ExpectOrDie('[', "at start of compile command file\n");
54 this->ParseTranslationUnit();
55 this->TranslationUnits.push_back(this->Command);
56 } while (this->Expect(','));
57 this->ExpectOrDie(']', "at end of array");
60 void ParseTranslationUnit()
62 this->Command = CommandType();
63 if (!this->Expect('{')) {
66 if (this->Expect('}')) {
71 std::string name = this->String;
72 this->ExpectOrDie(':', "between name and value");
74 std::string value = this->String;
75 this->Command[name] = value;
76 } while (this->Expect(','));
77 this->ExpectOrDie('}', "at end of object");
83 if (!this->Expect('"')) {
86 while (!this->Expect('"')) {
88 this->String.append(1, this->C);
96 this->NextNonWhitespace();
102 void ExpectOrDie(char c, const std::string& message)
104 if (!this->Expect(c)) {
105 this->ErrorExit(std::string("'") + c + "' expected " + message + ".");
109 void NextNonWhitespace()
113 } while (this->IsWhitespace());
118 this->C = static_cast<char>(this->Input.get());
119 if (this->Input.bad()) {
120 this->ErrorExit("Unexpected end of file.");
124 void ErrorExit(const std::string& message)
126 std::cout << "ERROR: " << message;
130 bool IsWhitespace() const
132 return (this->C == ' ' || this->C == '\t' || this->C == '\n' ||
137 TranslationUnitsType TranslationUnits;
145 cmsys::ifstream file("compile_commands.json");
146 CompileCommandParser parser(file);
148 for (auto const& tu : parser.GetTranslationUnits()) {
149 std::vector<std::string> command;
150 cmSystemTools::ParseUnixCommandLine(tu.at("command").c_str(), command);
151 if (!cmSystemTools::RunSingleCommand(command, nullptr, nullptr, nullptr,
152 tu.at("directory").c_str())) {
153 std::cout << "ERROR: Failed to run command \"" << command[0] << "\""