CompilationDatabase.h revision 30318e6df9c8c24d080211dfb92ef8065fa7381c
1//===--- CompilationDatabase.h - --------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file provides an interface and multiple implementations for
11//  CompilationDatabases.
12//
13//  While C++ refactoring and analysis tools are not compilers, and thus
14//  don't run as part of the build system, they need the exact information
15//  of a build in order to be able to correctly understand the C++ code of
16//  the project. This information is provided via the CompilationDatabase
17//  interface.
18//
19//  To create a CompilationDatabase from a build directory one can call
20//  CompilationDatabase::loadFromDirectory(), which deduces the correct
21//  compilation database from the root of the build tree.
22//
23//  See the concrete subclasses of CompilationDatabase for currently supported
24//  formats.
25//
26//===----------------------------------------------------------------------===//
27
28#ifndef LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
29#define LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
30
31#include "clang/Basic/LLVM.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/OwningPtr.h"
34#include "llvm/ADT/StringMap.h"
35#include "llvm/ADT/StringRef.h"
36#include "llvm/ADT/Twine.h"
37#include "llvm/Support/MemoryBuffer.h"
38#include "llvm/Support/SourceMgr.h"
39#include "llvm/Support/YAMLParser.h"
40#include <string>
41#include <vector>
42
43namespace clang {
44namespace tooling {
45
46/// \brief Specifies the working directory and command of a compilation.
47struct CompileCommand {
48  CompileCommand() {}
49  CompileCommand(Twine Directory, ArrayRef<std::string> CommandLine)
50    : Directory(Directory.str()), CommandLine(CommandLine) {}
51
52  /// \brief The working directory the command was executed from.
53  std::string Directory;
54
55  /// \brief The command line that was executed.
56  std::vector<std::string> CommandLine;
57};
58
59/// \brief Interface for compilation databases.
60///
61/// A compilation database allows the user to retrieve all compile command lines
62/// that a specified file is compiled with in a project.
63/// The retrieved compile command lines can be used to run clang tools over
64/// a subset of the files in a project.
65class CompilationDatabase {
66public:
67  virtual ~CompilationDatabase();
68
69  /// \brief Loads a compilation database from a build directory.
70  ///
71  /// Looks at the specified 'BuildDirectory' and creates a compilation database
72  /// that allows to query compile commands for source files in the
73  /// corresponding source tree.
74  ///
75  /// Returns NULL and sets ErrorMessage if we were not able to build up a
76  /// compilation database for the build directory.
77  ///
78  /// FIXME: Currently only supports JSON compilation databases, which
79  /// are named 'compile_commands.json' in the given directory. Extend this
80  /// for other build types (like ninja build files).
81  static CompilationDatabase *loadFromDirectory(StringRef BuildDirectory,
82                                                std::string &ErrorMessage);
83
84  /// \brief Returns all compile commands in which the specified file was
85  /// compiled.
86  ///
87  /// This includes compile comamnds that span multiple source files.
88  /// For example, consider a project with the following compilations:
89  /// $ clang++ -o test a.cc b.cc t.cc
90  /// $ clang++ -o production a.cc b.cc -DPRODUCTION
91  /// A compilation database representing the project would return both command
92  /// lines for a.cc and b.cc and only the first command line for t.cc.
93  virtual std::vector<CompileCommand> getCompileCommands(
94    StringRef FilePath) const = 0;
95};
96
97/// \brief A compilation database that returns a single compile command line.
98///
99/// Useful when we want a tool to behave more like a compiler invocation.
100class FixedCompilationDatabase : public CompilationDatabase {
101public:
102  /// \brief Creates a FixedCompilationDatabase from the arguments after "--".
103  ///
104  /// Parses the given command line for "--". If "--" is found, the rest of
105  /// the arguments will make up the command line in the returned
106  /// FixedCompilationDatabase.
107  /// The arguments after "--" must not include positional parameters or the
108  /// argv[0] of the tool. Those will be added by the FixedCompilationDatabase
109  /// when a CompileCommand is requested. The argv[0] of the returned command
110  /// line will be "clang-tool".
111  ///
112  /// Returns NULL in case "--" is not found.
113  ///
114  /// The argument list is meant to be compatible with normal llvm command line
115  /// parsing in main methods.
116  /// int main(int argc, char **argv) {
117  ///   llvm::OwningPtr<FixedCompilationDatabase> Compilations(
118  ///     FixedCompilationDatabase::loadFromCommandLine(argc, argv));
119  ///   cl::ParseCommandLineOptions(argc, argv);
120  ///   ...
121  /// }
122  ///
123  /// \param Argc The number of command line arguments - will be changed to
124  /// the number of arguments before "--", if "--" was found in the argument
125  /// list.
126  /// \param Argv Points to the command line arguments.
127  /// \param Directory The base directory used in the FixedCompilationDatabase.
128  static FixedCompilationDatabase *loadFromCommandLine(int &Argc,
129                                                       const char **Argv,
130                                                       Twine Directory = ".");
131
132  /// \brief Constructs a compilation data base from a specified directory
133  /// and command line.
134  FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
135
136  /// \brief Returns the given compile command.
137  ///
138  /// Will always return a vector with one entry that contains the directory
139  /// and command line specified at construction with "clang-tool" as argv[0]
140  /// and 'FilePath' as positional argument.
141  virtual std::vector<CompileCommand> getCompileCommands(
142    StringRef FilePath) const;
143
144private:
145  /// This is built up to contain a single entry vector to be returned from
146  /// getCompileCommands after adding the positional argument.
147  std::vector<CompileCommand> CompileCommands;
148};
149
150/// \brief A JSON based compilation database.
151///
152/// JSON compilation database files must contain a list of JSON objects which
153/// provide the command lines in the attributes 'directory', 'command' and
154/// 'file':
155/// [
156///   { "directory": "<working directory of the compile>",
157///     "command": "<compile command line>",
158///     "file": "<path to source file>"
159///   },
160///   ...
161/// ]
162/// Each object entry defines one compile action. The specified file is
163/// considered to be the main source file for the translation unit.
164///
165/// JSON compilation databases can for example be generated in CMake projects
166/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
167class JSONCompilationDatabase : public CompilationDatabase {
168public:
169  /// \brief Loads a JSON compilation database from the specified file.
170  ///
171  /// Returns NULL and sets ErrorMessage if the database could not be
172  /// loaded from the given file.
173  static JSONCompilationDatabase *loadFromFile(StringRef FilePath,
174                                               std::string &ErrorMessage);
175
176  /// \brief Loads a JSON compilation database from a data buffer.
177  ///
178  /// Returns NULL and sets ErrorMessage if the database could not be loaded.
179  static JSONCompilationDatabase *loadFromBuffer(StringRef DatabaseString,
180                                                 std::string &ErrorMessage);
181
182  /// \brief Returns all compile comamnds in which the specified file was
183  /// compiled.
184  ///
185  /// FIXME: Currently FilePath must be an absolute path inside the
186  /// source directory which does not have symlinks resolved.
187  virtual std::vector<CompileCommand> getCompileCommands(
188    StringRef FilePath) const;
189
190private:
191  /// \brief Constructs a JSON compilation database on a memory buffer.
192  JSONCompilationDatabase(llvm::MemoryBuffer *Database)
193    : Database(Database), YAMLStream(Database->getBuffer(), SM) {}
194
195  /// \brief Parses the database file and creates the index.
196  ///
197  /// Returns whether parsing succeeded. Sets ErrorMessage if parsing
198  /// failed.
199  bool parse(std::string &ErrorMessage);
200
201  // Tuple (directory, commandline) where 'commandline' pointing to the
202  // corresponding nodes in the YAML stream.
203  typedef std::pair<llvm::yaml::ScalarNode*,
204                    llvm::yaml::ScalarNode*> CompileCommandRef;
205
206  // Maps file paths to the compile command lines for that file.
207  llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile;
208
209  llvm::OwningPtr<llvm::MemoryBuffer> Database;
210  llvm::SourceMgr SM;
211  llvm::yaml::Stream YAMLStream;
212};
213
214} // end namespace tooling
215} // end namespace clang
216
217#endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H
218
219