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