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" 207fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper#include "llvm/Support/system_error.h" 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 { 1217fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper virtual CompilationDatabase *loadFromDirectory( 1227fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper StringRef Directory, std::string &ErrorMessage) { 123cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<1024> JSONDatabasePath(Directory); 1247fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::sys::path::append(JSONDatabasePath, "compile_commands.json"); 125cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<CompilationDatabase> Database( 1267fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper JSONCompilationDatabase::loadFromFile(JSONDatabasePath, ErrorMessage)); 1277fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (!Database) 1287fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return NULL; 1297fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return Database.take(); 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) { 147cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<llvm::MemoryBuffer> DatabaseBuffer; 1487fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::error_code Result = 1497fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::MemoryBuffer::getFile(FilePath, DatabaseBuffer); 1507fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (Result != 0) { 1517fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Error while opening JSON database: " + Result.message(); 1527fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return NULL; 1537fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 154cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<JSONCompilationDatabase> Database( 1557fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper new JSONCompilationDatabase(DatabaseBuffer.take())); 1567fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (!Database->parse(ErrorMessage)) 1577fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return NULL; 1587fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return Database.take(); 1597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} 1607fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 1617fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase * 1627fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::loadFromBuffer(StringRef DatabaseString, 1637fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::string &ErrorMessage) { 164cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<llvm::MemoryBuffer> DatabaseBuffer( 1657fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::MemoryBuffer::getMemBuffer(DatabaseString)); 166cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<JSONCompilationDatabase> Database( 167cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko new JSONCompilationDatabase(DatabaseBuffer.take())); 1687fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (!Database->parse(ErrorMessage)) 1697fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return NULL; 1707fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return Database.take(); 1717fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} 1727fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 1737fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstd::vector<CompileCommand> 1747fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::getCompileCommands(StringRef FilePath) const { 175cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<128> NativeFilePath; 1767fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::sys::path::native(FilePath, NativeFilePath); 177d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper std::vector<StringRef> PossibleMatches; 178d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper std::string Error; 179d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper llvm::raw_string_ostream ES(Error); 180d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper StringRef Match = MatchTrie.findEquivalent(NativeFilePath.str(), ES); 1819cd506b7c983829a33ae7ac1297228d146c58a69Arnaud A. de Grandmaison if (Match.empty()) 182d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper return std::vector<CompileCommand>(); 1837fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator 184d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper CommandsRefI = IndexByFile.find(Match); 1857fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (CommandsRefI == IndexByFile.end()) 1867fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return std::vector<CompileCommand>(); 1877fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::vector<CompileCommand> Commands; 1887e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis getCommands(CommandsRefI->getValue(), Commands); 1897fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return Commands; 1907fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} 1917fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 1927fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperstd::vector<std::string> 1937fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel JasperJSONCompilationDatabase::getAllFiles() const { 1947fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper std::vector<std::string> Result; 1957fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 1967fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator 1977fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper CommandsRefI = IndexByFile.begin(); 1987fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper const llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator 1997fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper CommandsRefEnd = IndexByFile.end(); 2007fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper for (; CommandsRefI != CommandsRefEnd; ++CommandsRefI) { 2017fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper Result.push_back(CommandsRefI->first().str()); 2027fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2037fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 2047fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return Result; 2057fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} 2067fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 2077e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidisstd::vector<CompileCommand> 2087e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios KyrtzidisJSONCompilationDatabase::getAllCompileCommands() const { 2097e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis std::vector<CompileCommand> Commands; 2107e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis for (llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator 2117e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis CommandsRefI = IndexByFile.begin(), CommandsRefEnd = IndexByFile.end(); 2127e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis CommandsRefI != CommandsRefEnd; ++CommandsRefI) { 2137e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis getCommands(CommandsRefI->getValue(), Commands); 2147e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis } 2157e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis return Commands; 2167e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis} 2177e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis 2187e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidisvoid JSONCompilationDatabase::getCommands( 2197e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis ArrayRef<CompileCommandRef> CommandsRef, 2207e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis std::vector<CompileCommand> &Commands) const { 2217e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis for (int I = 0, E = CommandsRef.size(); I != E; ++I) { 222cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<8> DirectoryStorage; 223cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<1024> CommandStorage; 2247e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis Commands.push_back(CompileCommand( 2257e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis // FIXME: Escape correctly: 2267e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis CommandsRef[I].first->getValue(DirectoryStorage), 2277e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage)))); 2287e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis } 2297e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis} 2307e96bfb4d507700a122f270a11ce3fc0e8e36c85Argyrios Kyrtzidis 2317fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasperbool JSONCompilationDatabase::parse(std::string &ErrorMessage) { 2327fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::document_iterator I = YAMLStream.begin(); 2337fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (I == YAMLStream.end()) { 2347fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Error while parsing YAML."; 2357fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2367fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2377fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::Node *Root = I->getRoot(); 2387fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (Root == NULL) { 2397fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Error while parsing YAML."; 2407fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2417fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 242cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko llvm::yaml::SequenceNode *Array = dyn_cast<llvm::yaml::SequenceNode>(Root); 2437fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (Array == NULL) { 2447fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Expected array."; 2457fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2467fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2477fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper for (llvm::yaml::SequenceNode::iterator AI = Array->begin(), 2487fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper AE = Array->end(); 2497fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper AI != AE; ++AI) { 250cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&*AI); 2517fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (Object == NULL) { 2527fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Expected object."; 2537fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2547fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2557fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::ScalarNode *Directory = NULL; 2567fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::ScalarNode *Command = NULL; 2577fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::ScalarNode *File = NULL; 2587fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper for (llvm::yaml::MappingNode::iterator KVI = Object->begin(), 2597fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper KVE = Object->end(); 2607fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper KVI != KVE; ++KVI) { 2617fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::Node *Value = (*KVI).getValue(); 2627fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (Value == NULL) { 2637fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Expected value."; 2647fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2657fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2667fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::ScalarNode *ValueString = 267cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko dyn_cast<llvm::yaml::ScalarNode>(Value); 2687fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (ValueString == NULL) { 2697fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Expected string as value."; 2707fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2717fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2727fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper llvm::yaml::ScalarNode *KeyString = 273cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey()); 2747fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (KeyString == NULL) { 2757fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Expected strings as key."; 2767fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2777fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 278cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<8> KeyStorage; 2797fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (KeyString->getValue(KeyStorage) == "directory") { 2807fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper Directory = ValueString; 2817fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } else if (KeyString->getValue(KeyStorage) == "command") { 2827fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper Command = ValueString; 2837fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } else if (KeyString->getValue(KeyStorage) == "file") { 2847fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper File = ValueString; 2857fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } else { 2867fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = ("Unknown key: \"" + 2877fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper KeyString->getRawValue() + "\"").str(); 2887fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2897fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2907fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2917fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (!File) { 2927fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Missing key: \"file\"."; 2937fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2947fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2957fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (!Command) { 2967fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Missing key: \"command\"."; 2977fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 2987fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 2997fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper if (!Directory) { 3007fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper ErrorMessage = "Missing key: \"directory\"."; 3017fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return false; 3027fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 303cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<8> FileStorage; 304d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper StringRef FileName = File->getValue(FileStorage); 305cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<128> NativeFilePath; 306d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper if (llvm::sys::path::is_relative(FileName)) { 307cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<8> DirectoryStorage; 308cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<128> AbsolutePath( 309d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper Directory->getValue(DirectoryStorage)); 310d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper llvm::sys::path::append(AbsolutePath, FileName); 311d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper llvm::sys::path::native(AbsolutePath.str(), NativeFilePath); 312d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper } else { 313d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper llvm::sys::path::native(FileName, NativeFilePath); 314d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper } 3157fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper IndexByFile[NativeFilePath].push_back( 316d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper CompileCommandRef(Directory, Command)); 317d3420c906e3605d94c084e8b8b1f3fa490093c86Daniel Jasper MatchTrie.insert(NativeFilePath.str()); 3187fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper } 3197fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper return true; 3207fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} 3217fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper 3227fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} // end namespace tooling 3237fd90b03a28df0626fdb44d05be9ddcdb2562686Daniel Jasper} // end namespace clang 324