1238104Sdes//===- JSONCompilationDatabase.h --------------------------------*- C++ -*-===//
2238104Sdes//
3238104Sdes// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4238104Sdes// See https://llvm.org/LICENSE.txt for license information.
5238104Sdes// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6238104Sdes//
7238104Sdes//===----------------------------------------------------------------------===//
8238104Sdes//
9238104Sdes//  The JSONCompilationDatabase finds compilation databases supplied as a file
10238104Sdes//  'compile_commands.json'.
11238104Sdes//
12238104Sdes//===----------------------------------------------------------------------===//
13238104Sdes
14238104Sdes#ifndef LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
15238104Sdes#define LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
16238104Sdes
17238104Sdes#include "clang/Basic/LLVM.h"
18238104Sdes#include "clang/Tooling/CompilationDatabase.h"
19238104Sdes#include "clang/Tooling/FileMatchTrie.h"
20238104Sdes#include "llvm/ADT/ArrayRef.h"
21238104Sdes#include "llvm/ADT/StringMap.h"
22238104Sdes#include "llvm/ADT/StringRef.h"
23238104Sdes#include "llvm/Support/MemoryBuffer.h"
24238104Sdes#include "llvm/Support/SourceMgr.h"
25238104Sdes#include "llvm/Support/YAMLParser.h"
26238104Sdes#include <memory>
27238104Sdes#include <string>
28238104Sdes#include <tuple>
29238104Sdes#include <utility>
30238104Sdes#include <vector>
31238104Sdes
32238104Sdesnamespace clang {
33238104Sdesnamespace tooling {
34238104Sdes
35238104Sdes/// A JSON based compilation database.
36238104Sdes///
37238104Sdes/// JSON compilation database files must contain a list of JSON objects which
38238104Sdes/// provide the command lines in the attributes 'directory', 'command',
39238104Sdes/// 'arguments' and 'file':
40238104Sdes/// [
41238104Sdes///   { "directory": "<working directory of the compile>",
42238104Sdes///     "command": "<compile command line>",
43238104Sdes///     "file": "<path to source file>"
44238104Sdes///   },
45238104Sdes///   { "directory": "<working directory of the compile>",
46238104Sdes///     "arguments": ["<raw>", "<command>" "<line>" "<parameters>"],
47238104Sdes///     "file": "<path to source file>"
48238104Sdes///   },
49238104Sdes///   ...
50238104Sdes/// ]
51238104Sdes/// Each object entry defines one compile action. The specified file is
52238104Sdes/// considered to be the main source file for the translation unit.
53238104Sdes///
54238104Sdes/// 'command' is a full command line that will be unescaped.
55238104Sdes///
56238104Sdes/// 'arguments' is a list of command line arguments that will not be unescaped.
57238104Sdes///
58238104Sdes/// JSON compilation databases can for example be generated in CMake projects
59238104Sdes/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
60238104Sdesenum class JSONCommandLineSyntax { Windows, Gnu, AutoDetect };
61238104Sdesclass JSONCompilationDatabase : public CompilationDatabase {
62238104Sdespublic:
63238104Sdes  /// Loads a JSON compilation database from the specified file.
64238104Sdes  ///
65238104Sdes  /// Returns NULL and sets ErrorMessage if the database could not be
66238104Sdes  /// loaded from the given file.
67238104Sdes  static std::unique_ptr<JSONCompilationDatabase>
68238104Sdes  loadFromFile(StringRef FilePath, std::string &ErrorMessage,
69238104Sdes               JSONCommandLineSyntax Syntax);
70238104Sdes
71238104Sdes  /// Loads a JSON compilation database from a data buffer.
72238104Sdes  ///
73238104Sdes  /// Returns NULL and sets ErrorMessage if the database could not be loaded.
74238104Sdes  static std::unique_ptr<JSONCompilationDatabase>
75238104Sdes  loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage,
76238104Sdes                 JSONCommandLineSyntax Syntax);
77238104Sdes
78238104Sdes  /// Returns all compile commands in which the specified file was
79238104Sdes  /// compiled.
80238104Sdes  ///
81238104Sdes  /// FIXME: Currently FilePath must be an absolute path inside the
82238104Sdes  /// source directory which does not have symlinks resolved.
83238104Sdes  std::vector<CompileCommand>
84238104Sdes  getCompileCommands(StringRef FilePath) const override;
85238104Sdes
86238104Sdes  /// Returns the list of all files available in the compilation database.
87238104Sdes  ///
88238104Sdes  /// These are the 'file' entries of the JSON objects.
89238104Sdes  std::vector<std::string> getAllFiles() const override;
90238104Sdes
91238104Sdes  /// Returns all compile commands for all the files in the compilation
92238104Sdes  /// database.
93238104Sdes  std::vector<CompileCommand> getAllCompileCommands() const override;
94238104Sdes
95238104Sdesprivate:
96238104Sdes  /// Constructs a JSON compilation database on a memory buffer.
97238104Sdes  JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database,
98238104Sdes                          JSONCommandLineSyntax Syntax)
99238104Sdes      : Database(std::move(Database)), Syntax(Syntax),
100238104Sdes        YAMLStream(this->Database->getBuffer(), SM) {}
101238104Sdes
102238104Sdes  /// Parses the database file and creates the index.
103238104Sdes  ///
104238104Sdes  /// Returns whether parsing succeeded. Sets ErrorMessage if parsing
105238104Sdes  /// failed.
106238104Sdes  bool parse(std::string &ErrorMessage);
107238104Sdes
108238104Sdes  // Tuple (directory, filename, commandline, output) where 'commandline'
109238104Sdes  // points to the corresponding scalar nodes in the YAML stream.
110238104Sdes  // If the command line contains a single argument, it is a shell-escaped
111238104Sdes  // command line.
112238104Sdes  // Otherwise, each entry in the command line vector is a literal
113238104Sdes  // argument to the compiler.
114238104Sdes  // The output field may be a nullptr.
115238104Sdes  using CompileCommandRef =
116238104Sdes      std::tuple<llvm::yaml::ScalarNode *, llvm::yaml::ScalarNode *,
117238104Sdes                 std::vector<llvm::yaml::ScalarNode *>,
118238104Sdes                 llvm::yaml::ScalarNode *>;
119238104Sdes
120238104Sdes  /// Converts the given array of CompileCommandRefs to CompileCommands.
121238104Sdes  void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
122238104Sdes                   std::vector<CompileCommand> &Commands) const;
123238104Sdes
124238104Sdes  // Maps file paths to the compile command lines for that file.
125238104Sdes  llvm::StringMap<std::vector<CompileCommandRef>> IndexByFile;
126238104Sdes
127238104Sdes  /// All the compile commands in the order that they were provided in the
128238104Sdes  /// JSON stream.
129238104Sdes  std::vector<CompileCommandRef> AllCommands;
130238104Sdes
131238104Sdes  FileMatchTrie MatchTrie;
132238104Sdes
133238104Sdes  std::unique_ptr<llvm::MemoryBuffer> Database;
134238104Sdes  JSONCommandLineSyntax Syntax;
135238104Sdes  llvm::SourceMgr SM;
136238104Sdes  llvm::yaml::Stream YAMLStream;
137238104Sdes};
138238104Sdes
139238104Sdes} // namespace tooling
140238104Sdes} // namespace clang
141238104Sdes
142238104Sdes#endif // LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
143238104Sdes