17fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//===--- JSONCompilationDatabase.cpp - ------------------------------------===//
27fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//
37fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//                     The LLVM Compiler Infrastructure
47fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//
57fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// This file is distributed under the University of Illinois Open Source
67fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// License. See LICENSE.TXT for details.
77fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//
87fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//===----------------------------------------------------------------------===//
97fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//
107fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//  This file contains the implementation of the JSONCompilationDatabase.
117fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//
127fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper//===----------------------------------------------------------------------===//
137fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
147fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "clang/Tooling/JSONCompilationDatabase.h"
157fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "clang/Tooling/CompilationDatabase.h"
167fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
177fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "clang/Tooling/Tooling.h"
187fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "llvm/ADT/SmallString.h"
197fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "llvm/Support/Path.h"
20ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include <system_error>
217fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
227fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jaspernamespace clang {
237fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jaspernamespace tooling {
247fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
257fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jaspernamespace {
267fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
277fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper/// \brief A parser for escaped strings of command line arguments.
287fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper///
297fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper/// Assumes \-escaping for quoted arguments (see the documentation of
307fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper/// unescapeCommandLine(...)).
317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperclass CommandLineArgumentParser {
327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper public:
337fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  CommandLineArgumentParser(StringRef CommandLine)
347fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      : Input(CommandLine), Position(Input.begin()-1) {}
357fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
367fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  std::vector<std::string> parse() {
377fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    bool HasMoreInput = true;
387fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    while (HasMoreInput && nextNonWhitespace()) {
397fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      std::string Argument;
407fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      HasMoreInput = parseStringInto(Argument);
417fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      CommandLine.push_back(Argument);
427fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
437fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return CommandLine;
447fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
457fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
467fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper private:
477fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  // All private methods return true if there is more input available.
487fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
497fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  bool parseStringInto(std::string &String) {
507fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    do {
517fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (*Position == '"') {
52b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne        if (!parseDoubleQuotedStringInto(String)) return false;
53b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne      } else if (*Position == '\'') {
54b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne        if (!parseSingleQuotedStringInto(String)) return false;
557fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      } else {
567fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        if (!parseFreeStringInto(String)) return false;
577fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      }
587fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    } while (*Position != ' ');
597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return true;
607fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
617fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
62b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne  bool parseDoubleQuotedStringInto(std::string &String) {
637fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (!next()) return false;
647fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    while (*Position != '"') {
657fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (!skipEscapeCharacter()) return false;
667fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      String.push_back(*Position);
677fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (!next()) return false;
687fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
697fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return next();
707fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
717fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
72b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne  bool parseSingleQuotedStringInto(std::string &String) {
73b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne    if (!next()) return false;
74b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne    while (*Position != '\'') {
75b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne      String.push_back(*Position);
76b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne      if (!next()) return false;
77b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne    }
78b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne    return next();
79b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne  }
80b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne
817fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  bool parseFreeStringInto(std::string &String) {
827fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    do {
837fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (!skipEscapeCharacter()) return false;
847fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      String.push_back(*Position);
857fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (!next()) return false;
86b88d9480e04039188c39e49367cb13d64e644cf8Peter Collingbourne    } while (*Position != ' ' && *Position != '"' && *Position != '\'');
877fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return true;
887fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
897fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
907fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  bool skipEscapeCharacter() {
917fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (*Position == '\\') {
927fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      return next();
937fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
947fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return true;
957fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
967fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
977fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  bool nextNonWhitespace() {
987fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    do {
997fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (!next()) return false;
1007fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    } while (*Position == ' ');
1017fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return true;
1027fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
1037fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1047fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  bool next() {
1057fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    ++Position;
1067fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return Position != Input.end();
1077fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
1087fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1097fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  const StringRef Input;
1107fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  StringRef::iterator Position;
1117fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  std::vector<std::string> CommandLine;
1127fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper};
1137fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1147fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstd::vector<std::string> unescapeCommandLine(
1157fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    StringRef EscapedCommandLine) {
1167fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  CommandLineArgumentParser parser(EscapedCommandLine);
1177fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  return parser.parse();
1187fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper}
1197fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1207fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperclass JSONCompilationDatabasePlugin : public CompilationDatabasePlugin {
121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CompilationDatabase *loadFromDirectory(StringRef Directory,
122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                         std::string &ErrorMessage) override {
123cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<1024> JSONDatabasePath(Directory);
1247fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    llvm::sys::path::append(JSONDatabasePath, "compile_commands.json");
125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::unique_ptr<CompilationDatabase> Database(
1267fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        JSONCompilationDatabase::loadFromFile(JSONDatabasePath, ErrorMessage));
1277fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (!Database)
1286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return nullptr;
129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return Database.release();
1307fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
1317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper};
1327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
133bc54025b3f11edd8ef6762e36bf2855f28844fa0Craig Topper} // end namespace
134bc54025b3f11edd8ef6762e36bf2855f28844fa0Craig Topper
1357fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// Register the JSONCompilationDatabasePlugin with the
1367fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// CompilationDatabasePluginRegistry using this statically initialized variable.
1377fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstatic CompilationDatabasePluginRegistry::Add<JSONCompilationDatabasePlugin>
1387fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperX("json-compilation-database", "Reads JSON formatted compilation databases");
1397fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1407fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// This anchor is used to force the linker to link in the generated object file
1417fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper// and thus register the JSONCompilationDatabasePlugin.
142916978adb6eb36b06668a98ba7a63fbde05840caNAKAMURA Takumivolatile int JSONAnchorSource = 0;
1437fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1447fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase *
1457fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::loadFromFile(StringRef FilePath,
1467fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                      std::string &ErrorMessage) {
147ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> DatabaseBuffer =
148ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      llvm::MemoryBuffer::getFile(FilePath);
149ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  if (std::error_code Result = DatabaseBuffer.getError()) {
1507fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    ErrorMessage = "Error while opening JSON database: " + Result.message();
1516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
1527fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<JSONCompilationDatabase> Database(
154ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      new JSONCompilationDatabase(DatabaseBuffer->release()));
1557fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  if (!Database->parse(ErrorMessage))
1566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return Database.release();
1587fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper}
1597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1607fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase *
1617fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::loadFromBuffer(StringRef DatabaseString,
1627fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                        std::string &ErrorMessage) {
163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<llvm::MemoryBuffer> DatabaseBuffer(
1647fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      llvm::MemoryBuffer::getMemBuffer(DatabaseString));
165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<JSONCompilationDatabase> Database(
166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new JSONCompilationDatabase(DatabaseBuffer.release()));
1677fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  if (!Database->parse(ErrorMessage))
1686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return Database.release();
1707fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper}
1717fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1727fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstd::vector<CompileCommand>
1737fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
174cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SmallString<128> NativeFilePath;
1757fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  llvm::sys::path::native(FilePath, NativeFilePath);
176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
177d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper  std::string Error;
178d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper  llvm::raw_string_ostream ES(Error);
179d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper  StringRef Match = MatchTrie.findEquivalent(NativeFilePath.str(), ES);
1809cd506b7c983829a33ae7ac1297228d146c58a69Arnaud A. de Grandmaison  if (Match.empty())
181d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    return std::vector<CompileCommand>();
1827fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
183d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    CommandsRefI = IndexByFile.find(Match);
1847fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  if (CommandsRefI == IndexByFile.end())
1857fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return std::vector<CompileCommand>();
1867fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  std::vector<CompileCommand> Commands;
1877e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  getCommands(CommandsRefI->getValue(), Commands);
1887fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  return Commands;
1897fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper}
1907fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1917fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstd::vector<std::string>
1927fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::getAllFiles() const {
1937fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  std::vector<std::string> Result;
1947fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
1957fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
1967fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    CommandsRefI = IndexByFile.begin();
1977fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  const llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
1987fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    CommandsRefEnd = IndexByFile.end();
1997fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  for (; CommandsRefI != CommandsRefEnd; ++CommandsRefI) {
2007fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    Result.push_back(CommandsRefI->first().str());
2017fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
2027fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
2037fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  return Result;
2047fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper}
2057fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
2067e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidisstd::vector<CompileCommand>
2077e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios KyrtzidisJSONCompilationDatabase::getAllCompileCommands() const {
2087e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  std::vector<CompileCommand> Commands;
2097e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  for (llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
2107e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis        CommandsRefI = IndexByFile.begin(), CommandsRefEnd = IndexByFile.end();
2117e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis      CommandsRefI != CommandsRefEnd; ++CommandsRefI) {
2127e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis    getCommands(CommandsRefI->getValue(), Commands);
2137e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  }
2147e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  return Commands;
2157e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis}
2167e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis
2177e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidisvoid JSONCompilationDatabase::getCommands(
2187e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis                                  ArrayRef<CompileCommandRef> CommandsRef,
2197e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis                                  std::vector<CompileCommand> &Commands) const {
2207e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
221cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<8> DirectoryStorage;
222cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<1024> CommandStorage;
2237e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis    Commands.push_back(CompileCommand(
2247e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis      // FIXME: Escape correctly:
2257e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis      CommandsRef[I].first->getValue(DirectoryStorage),
2267e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis      unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage))));
2277e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis  }
2287e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis}
2297e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis
2307fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperbool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
2317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  llvm::yaml::document_iterator I = YAMLStream.begin();
2327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  if (I == YAMLStream.end()) {
2337fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    ErrorMessage = "Error while parsing YAML.";
2347fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return false;
2357fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
2367fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  llvm::yaml::Node *Root = I->getRoot();
2376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!Root) {
2387fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    ErrorMessage = "Error while parsing YAML.";
2397fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return false;
2407fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
241cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  llvm::yaml::SequenceNode *Array = dyn_cast<llvm::yaml::SequenceNode>(Root);
2426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!Array) {
2437fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    ErrorMessage = "Expected array.";
2447fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    return false;
2457fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
2467fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  for (llvm::yaml::SequenceNode::iterator AI = Array->begin(),
2477fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                          AE = Array->end();
2487fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper       AI != AE; ++AI) {
249cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&*AI);
2506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!Object) {
2517fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      ErrorMessage = "Expected object.";
2527fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      return false;
2537fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
2546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::yaml::ScalarNode *Directory = nullptr;
2556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::yaml::ScalarNode *Command = nullptr;
2566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::yaml::ScalarNode *File = nullptr;
2577fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
2587fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                                           KVE = Object->end();
2597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper         KVI != KVE; ++KVI) {
2607fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      llvm::yaml::Node *Value = (*KVI).getValue();
2616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (!Value) {
2627fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        ErrorMessage = "Expected value.";
2637fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        return false;
2647fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      }
2657fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      llvm::yaml::ScalarNode *ValueString =
266cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko          dyn_cast<llvm::yaml::ScalarNode>(Value);
2676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (!ValueString) {
2687fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        ErrorMessage = "Expected string as value.";
2697fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        return false;
2707fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      }
2717fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      llvm::yaml::ScalarNode *KeyString =
272cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko          dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
2736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (!KeyString) {
2747fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        ErrorMessage = "Expected strings as key.";
2757fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        return false;
2767fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      }
277cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko      SmallString<8> KeyStorage;
2787fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      if (KeyString->getValue(KeyStorage) == "directory") {
2797fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        Directory = ValueString;
2807fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      } else if (KeyString->getValue(KeyStorage) == "command") {
2817fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        Command = ValueString;
2827fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      } else if (KeyString->getValue(KeyStorage) == "file") {
2837fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        File = ValueString;
2847fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      } else {
2857fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        ErrorMessage = ("Unknown key: \"" +
2867fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper                        KeyString->getRawValue() + "\"").str();
2877fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper        return false;
2887fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      }
2897fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
2907fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (!File) {
2917fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      ErrorMessage = "Missing key: \"file\".";
2927fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      return false;
2937fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
2947fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (!Command) {
2957fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      ErrorMessage = "Missing key: \"command\".";
2967fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      return false;
2977fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
2987fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    if (!Directory) {
2997fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      ErrorMessage = "Missing key: \"directory\".";
3007fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper      return false;
3017fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    }
302cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<8> FileStorage;
303d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    StringRef FileName = File->getValue(FileStorage);
304cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallString<128> NativeFilePath;
305d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    if (llvm::sys::path::is_relative(FileName)) {
306cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko      SmallString<8> DirectoryStorage;
307cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko      SmallString<128> AbsolutePath(
308d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper          Directory->getValue(DirectoryStorage));
309d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper      llvm::sys::path::append(AbsolutePath, FileName);
310d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper      llvm::sys::path::native(AbsolutePath.str(), NativeFilePath);
311d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    } else {
312d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper      llvm::sys::path::native(FileName, NativeFilePath);
313d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    }
3147fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper    IndexByFile[NativeFilePath].push_back(
315d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper        CompileCommandRef(Directory, Command));
316d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper    MatchTrie.insert(NativeFilePath.str());
3177fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  }
3187fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper  return true;
3197fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper}
3207fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper
3217fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} // end namespace tooling
3227fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} // end namespace clang
323