CompilationDatabase.cpp revision 30318e6df9c8c24d080211dfb92ef8065fa7381c
1cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===--- CompilationDatabase.cpp - ----------------------------------------===//
2cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
3cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//                     The LLVM Compiler Infrastructure
4cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
5cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// This file is distributed under the University of Illinois Open Source
6cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// License. See LICENSE.TXT for details.
7cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
8cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===//
9cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
10cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//  This file contains multiple implementations for CompilationDatabases.
11cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//
12cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek//===----------------------------------------------------------------------===//
13cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
14cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "clang/Tooling/CompilationDatabase.h"
15cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "llvm/ADT/SmallString.h"
16c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek#include "llvm/Support/YAMLParser.h"
17cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "llvm/Support/Path.h"
18cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "llvm/Support/system_error.h"
19cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
20cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace clang {
21cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace tooling {
22cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
23cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimeknamespace {
24cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
25c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek/// \brief A parser for escaped strings of command line arguments.
26cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek///
27cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek/// Assumes \-escaping for quoted arguments (see the documentation of
28c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek/// unescapeCommandLine(...)).
29cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekclass CommandLineArgumentParser {
30cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek public:
31cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  CommandLineArgumentParser(StringRef CommandLine)
32cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      : Input(CommandLine), Position(Input.begin()-1) {}
33cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
34cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  std::vector<std::string> parse() {
35cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    bool HasMoreInput = true;
36cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    while (HasMoreInput && nextNonWhitespace()) {
37cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      std::string Argument;
38cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      HasMoreInput = parseStringInto(Argument);
39cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      CommandLine.push_back(Argument);
40cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    }
41cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return CommandLine;
42cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
43cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
44cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek private:
45cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  // All private methods return true if there is more input available.
46cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
47cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  bool parseStringInto(std::string &String) {
48cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    do {
49cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (*Position == '"') {
50cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        if (!parseQuotedStringInto(String)) return false;
51cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      } else {
52cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        if (!parseFreeStringInto(String)) return false;
53cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      }
54cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    } while (*Position != ' ');
55cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return true;
56cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
57cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
58cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  bool parseQuotedStringInto(std::string &String) {
59cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    if (!next()) return false;
60cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    while (*Position != '"') {
61cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (!skipEscapeCharacter()) return false;
62cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      String.push_back(*Position);
63cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (!next()) return false;
64cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    }
65cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return next();
66cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
67cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
68cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  bool parseFreeStringInto(std::string &String) {
69cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    do {
70cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (!skipEscapeCharacter()) return false;
71cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      String.push_back(*Position);
72cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (!next()) return false;
73cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    } while (*Position != ' ' && *Position != '"');
74cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return true;
75cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
76cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
77cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  bool skipEscapeCharacter() {
78cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    if (*Position == '\\') {
79cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      return next();
80cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    }
81cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return true;
82cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
83cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
84cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  bool nextNonWhitespace() {
85cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    do {
86cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (!next()) return false;
87cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    } while (*Position == ' ');
88cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return true;
89cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
90cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
91cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  bool next() {
92cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    ++Position;
93cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return Position != Input.end();
94cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
95cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
96cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  const StringRef Input;
97cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  StringRef::iterator Position;
98cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  std::vector<std::string> CommandLine;
99cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek};
100cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
101c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimekstd::vector<std::string> unescapeCommandLine(
102c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    StringRef EscapedCommandLine) {
103c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  CommandLineArgumentParser parser(EscapedCommandLine);
104cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  return parser.parse();
105cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
106cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
107cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace
108cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
109cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase::~CompilationDatabase() {}
110cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
111cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase *
112cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekCompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
113cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek                                       std::string &ErrorMessage) {
114cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::SmallString<1024> JSONDatabasePath(BuildDirectory);
115cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::sys::path::append(JSONDatabasePath, "compile_commands.json");
116cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::OwningPtr<CompilationDatabase> Database(
117cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    JSONCompilationDatabase::loadFromFile(JSONDatabasePath, ErrorMessage));
118cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (!Database) {
119cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return NULL;
120cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
121cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  return Database.take();
122cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
123cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
12430318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase *
12530318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::loadFromCommandLine(int &Argc,
12630318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek                                              const char **Argv,
12730318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek                                              Twine Directory) {
12830318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
12930318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  if (DoubleDash == Argv + Argc)
13030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek    return NULL;
13130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc);
13230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  Argc = DoubleDash - Argv;
13330318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  return new FixedCompilationDatabase(Directory, CommandLine);
13430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek}
13530318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek
13630318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::
13730318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
13830318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  std::vector<std::string> ToolCommandLine(1, "clang-tool");
13930318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  ToolCommandLine.insert(ToolCommandLine.end(),
14030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek                         CommandLine.begin(), CommandLine.end());
14130318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine));
14230318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek}
14330318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek
14430318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimekstd::vector<CompileCommand>
14530318e6df9c8c24d080211dfb92ef8065fa7381cManuel KlimekFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
14630318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  std::vector<CompileCommand> Result(CompileCommands);
14730318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  Result[0].CommandLine.push_back(FilePath);
14830318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek  return Result;
14930318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek}
15030318e6df9c8c24d080211dfb92ef8065fa7381cManuel Klimek
151cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekJSONCompilationDatabase *
152cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekJSONCompilationDatabase::loadFromFile(StringRef FilePath,
153cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek                                      std::string &ErrorMessage) {
154cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::OwningPtr<llvm::MemoryBuffer> DatabaseBuffer;
155cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::error_code Result =
156cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    llvm::MemoryBuffer::getFile(FilePath, DatabaseBuffer);
157cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (Result != 0) {
158cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    ErrorMessage = "Error while opening JSON database: " + Result.message();
159cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return NULL;
160cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
161cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::OwningPtr<JSONCompilationDatabase> Database(
162cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    new JSONCompilationDatabase(DatabaseBuffer.take()));
163cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (!Database->parse(ErrorMessage))
164cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return NULL;
165cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  return Database.take();
166cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
167cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
168cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekJSONCompilationDatabase *
169cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekJSONCompilationDatabase::loadFromBuffer(StringRef DatabaseString,
170cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek                                        std::string &ErrorMessage) {
171cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::OwningPtr<llvm::MemoryBuffer> DatabaseBuffer(
172cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      llvm::MemoryBuffer::getMemBuffer(DatabaseString));
173cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::OwningPtr<JSONCompilationDatabase> Database(
174cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    new JSONCompilationDatabase(DatabaseBuffer.take()));
175cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (!Database->parse(ErrorMessage))
176cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return NULL;
177cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  return Database.take();
178cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
179cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
180cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekstd::vector<CompileCommand>
181cb971c6726d16e12ecd2a340941d7f5c06698332Manuel KlimekJSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
182cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
183cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    CommandsRefI = IndexByFile.find(FilePath);
184cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (CommandsRefI == IndexByFile.end())
185cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return std::vector<CompileCommand>();
186cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  const std::vector<CompileCommandRef> &CommandsRef = CommandsRefI->getValue();
187cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  std::vector<CompileCommand> Commands;
188cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
189c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::SmallString<8> DirectoryStorage;
190c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::SmallString<1024> CommandStorage;
191cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    Commands.push_back(CompileCommand(
192cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      // FIXME: Escape correctly:
193c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      CommandsRef[I].first->getValue(DirectoryStorage),
194c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage))));
195cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
196cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  return Commands;
197cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
198cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
199cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekbool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
200c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  llvm::yaml::document_iterator I = YAMLStream.begin();
201c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  if (I == YAMLStream.end()) {
202c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    ErrorMessage = "Error while parsing YAML.";
203c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    return false;
204c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  }
205c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  llvm::yaml::Node *Root = I->getRoot();
206cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (Root == NULL) {
207c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    ErrorMessage = "Error while parsing YAML.";
208cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return false;
209cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
210c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  llvm::yaml::SequenceNode *Array =
211c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::dyn_cast<llvm::yaml::SequenceNode>(Root);
212cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  if (Array == NULL) {
213cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    ErrorMessage = "Expected array.";
214cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    return false;
215cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
216c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek  for (llvm::yaml::SequenceNode::iterator AI = Array->begin(),
217c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek                                          AE = Array->end();
218cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek       AI != AE; ++AI) {
219c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::yaml::MappingNode *Object =
220c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      llvm::dyn_cast<llvm::yaml::MappingNode>(&*AI);
221cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    if (Object == NULL) {
222cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      ErrorMessage = "Expected object.";
223cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      return false;
224cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    }
225c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::yaml::ScalarNode *Directory;
226c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::yaml::ScalarNode *Command;
227c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::SmallString<8> FileStorage;
228c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    llvm::StringRef File;
229c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
230c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek                                           KVE = Object->end();
231cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek         KVI != KVE; ++KVI) {
232c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      llvm::yaml::Node *Value = (*KVI).getValue();
233cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (Value == NULL) {
234cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        ErrorMessage = "Expected value.";
235cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        return false;
236cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      }
237c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      llvm::yaml::ScalarNode *ValueString =
238c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek        llvm::dyn_cast<llvm::yaml::ScalarNode>(Value);
239cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      if (ValueString == NULL) {
240cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        ErrorMessage = "Expected string as value.";
241cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        return false;
242cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      }
243c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      llvm::yaml::ScalarNode *KeyString =
244c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek        llvm::dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
245c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      llvm::SmallString<8> KeyStorage;
246c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      if (KeyString->getValue(KeyStorage) == "directory") {
247c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek        Directory = ValueString;
248c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      } else if (KeyString->getValue(KeyStorage) == "command") {
249c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek        Command = ValueString;
250c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      } else if (KeyString->getValue(KeyStorage) == "file") {
251c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek        File = ValueString->getValue(FileStorage);
252cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      } else {
253c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek        ErrorMessage = ("Unknown key: \"" +
254c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek                        KeyString->getRawValue() + "\"").str();
255cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek        return false;
256cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek      }
257cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek    }
258c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek    IndexByFile[File].push_back(
259c661f1467a84a0a3a83a396b067188b647844ee9Manuel Klimek      CompileCommandRef(Directory, Command));
260cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  }
261cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek  return true;
262cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek}
263cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
264cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace tooling
265cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // end namespace clang
266cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek
267