1 //===- JSONCompilationDatabase.h --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // The JSONCompilationDatabase finds compilation databases supplied as a file 10 // 'compile_commands.json'. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H 15 #define LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H 16 17 #include "clang/Basic/LLVM.h" 18 #include "clang/Tooling/CompilationDatabase.h" 19 #include "clang/Tooling/FileMatchTrie.h" 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/ADT/StringMap.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 #include "llvm/Support/SourceMgr.h" 25 #include "llvm/Support/YAMLParser.h" 26 #include <memory> 27 #include <string> 28 #include <tuple> 29 #include <utility> 30 #include <vector> 31 32 namespace clang { 33 namespace tooling { 34 35 /// A JSON based compilation database. 36 /// 37 /// JSON compilation database files must contain a list of JSON objects which 38 /// provide the command lines in the attributes 'directory', 'command', 39 /// 'arguments' and 'file': 40 /// [ 41 /// { "directory": "<working directory of the compile>", 42 /// "command": "<compile command line>", 43 /// "file": "<path to source file>" 44 /// }, 45 /// { "directory": "<working directory of the compile>", 46 /// "arguments": ["<raw>", "<command>" "<line>" "<parameters>"], 47 /// "file": "<path to source file>" 48 /// }, 49 /// ... 50 /// ] 51 /// Each object entry defines one compile action. The specified file is 52 /// considered to be the main source file for the translation unit. 53 /// 54 /// 'command' is a full command line that will be unescaped. 55 /// 56 /// 'arguments' is a list of command line arguments that will not be unescaped. 57 /// 58 /// JSON compilation databases can for example be generated in CMake projects 59 /// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS. 60 enum class JSONCommandLineSyntax { Windows, Gnu, AutoDetect }; 61 class JSONCompilationDatabase : public CompilationDatabase { 62 public: 63 /// Loads a JSON compilation database from the specified file. 64 /// 65 /// Returns NULL and sets ErrorMessage if the database could not be 66 /// loaded from the given file. 67 static std::unique_ptr<JSONCompilationDatabase> 68 loadFromFile(StringRef FilePath, std::string &ErrorMessage, 69 JSONCommandLineSyntax Syntax); 70 71 /// Loads a JSON compilation database from a data buffer. 72 /// 73 /// Returns NULL and sets ErrorMessage if the database could not be loaded. 74 static std::unique_ptr<JSONCompilationDatabase> 75 loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage, 76 JSONCommandLineSyntax Syntax); 77 78 /// Returns all compile commands in which the specified file was 79 /// compiled. 80 /// 81 /// FIXME: Currently FilePath must be an absolute path inside the 82 /// source directory which does not have symlinks resolved. 83 std::vector<CompileCommand> 84 getCompileCommands(StringRef FilePath) const override; 85 86 /// Returns the list of all files available in the compilation database. 87 /// 88 /// These are the 'file' entries of the JSON objects. 89 std::vector<std::string> getAllFiles() const override; 90 91 /// Returns all compile commands for all the files in the compilation 92 /// database. 93 std::vector<CompileCommand> getAllCompileCommands() const override; 94 95 private: 96 /// Constructs a JSON compilation database on a memory buffer. JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database,JSONCommandLineSyntax Syntax)97 JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database, 98 JSONCommandLineSyntax Syntax) 99 : Database(std::move(Database)), Syntax(Syntax), 100 YAMLStream(this->Database->getBuffer(), SM) {} 101 102 /// Parses the database file and creates the index. 103 /// 104 /// Returns whether parsing succeeded. Sets ErrorMessage if parsing 105 /// failed. 106 bool parse(std::string &ErrorMessage); 107 108 // Tuple (directory, filename, commandline, output) where 'commandline' 109 // points to the corresponding scalar nodes in the YAML stream. 110 // If the command line contains a single argument, it is a shell-escaped 111 // command line. 112 // Otherwise, each entry in the command line vector is a literal 113 // argument to the compiler. 114 // The output field may be a nullptr. 115 using CompileCommandRef = 116 std::tuple<llvm::yaml::ScalarNode *, llvm::yaml::ScalarNode *, 117 std::vector<llvm::yaml::ScalarNode *>, 118 llvm::yaml::ScalarNode *>; 119 120 /// Converts the given array of CompileCommandRefs to CompileCommands. 121 void getCommands(ArrayRef<CompileCommandRef> CommandsRef, 122 std::vector<CompileCommand> &Commands) const; 123 124 // Maps file paths to the compile command lines for that file. 125 llvm::StringMap<std::vector<CompileCommandRef>> IndexByFile; 126 127 /// All the compile commands in the order that they were provided in the 128 /// JSON stream. 129 std::vector<CompileCommandRef> AllCommands; 130 131 FileMatchTrie MatchTrie; 132 133 std::unique_ptr<llvm::MemoryBuffer> Database; 134 JSONCommandLineSyntax Syntax; 135 llvm::SourceMgr SM; 136 llvm::yaml::Stream YAMLStream; 137 }; 138 139 } // namespace tooling 140 } // namespace clang 141 142 #endif // LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H 143