summaryrefslogtreecommitdiff
path: root/clang-tools-extra/clangd/GlobalCompilationDatabase.h
blob: 70e7904165513a4b6df486c66b181f28444df63e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//===--- GlobalCompilationDatabase.h -----------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H

#include "Path.h"
#include "llvm/ADT/StringMap.h"
#include <memory>
#include <mutex>
#include <vector>

namespace clang {

namespace tooling {
class CompilationDatabase;
struct CompileCommand;
} // namespace tooling

namespace clangd {

class Logger;

/// Provides compilation arguments used for parsing C and C++ files.
class GlobalCompilationDatabase {
public:
  virtual ~GlobalCompilationDatabase() = default;

  /// If there are any known-good commands for building this file, returns one.
  virtual llvm::Optional<tooling::CompileCommand>
  getCompileCommand(PathRef File) const = 0;

  /// Makes a guess at how to build a file.
  /// The default implementation just runs clang on the file.
  /// Clangd should treat the results as unreliable.
  virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;

  /// FIXME(ibiryukov): add facilities to track changes to compilation flags of
  /// existing targets.
};

/// Gets compile args from tooling::CompilationDatabases built for parent
/// directories.
class DirectoryBasedGlobalCompilationDatabase
    : public GlobalCompilationDatabase {
public:
  DirectoryBasedGlobalCompilationDatabase(
      llvm::Optional<Path> CompileCommandsDir);
  ~DirectoryBasedGlobalCompilationDatabase() override;

  /// Scans File's parents looking for compilation databases.
  /// Any extra flags will be added.
  llvm::Optional<tooling::CompileCommand>
  getCompileCommand(PathRef File) const override;

  /// Uses the default fallback command, adding any extra flags.
  tooling::CompileCommand getFallbackCommand(PathRef File) const override;

  /// Set the compile commands directory to \p P.
  void setCompileCommandsDir(Path P);

  /// Sets the extra flags that should be added to a file.
  void setExtraFlagsForFile(PathRef File, std::vector<std::string> ExtraFlags);

private:
  tooling::CompilationDatabase *getCDBForFile(PathRef File) const;
  tooling::CompilationDatabase *getCDBInDirLocked(PathRef File) const;
  void addExtraFlags(PathRef File, tooling::CompileCommand &C) const;

  mutable std::mutex Mutex;
  /// Caches compilation databases loaded from directories(keys are
  /// directories).
  mutable llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>>
      CompilationDatabases;

  /// Stores extra flags per file.
  llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
  /// Used for command argument pointing to folder where compile_commands.json
  /// is located.
  llvm::Optional<Path> CompileCommandsDir;
};

/// A wrapper around GlobalCompilationDatabase that caches the compile commands.
/// Note that only results of getCompileCommand are cached.
class CachingCompilationDb : public GlobalCompilationDatabase {
public:
  explicit CachingCompilationDb(const GlobalCompilationDatabase &InnerCDB);

  /// Gets compile command for \p File from cache or CDB if it's not in the
  /// cache.
  llvm::Optional<tooling::CompileCommand>
  getCompileCommand(PathRef File) const override;

  /// Forwards to the inner CDB. Results of this function are not cached.
  tooling::CompileCommand getFallbackCommand(PathRef File) const override;

  /// Removes an entry for \p File if it's present in the cache.
  void invalidate(PathRef File);

  /// Removes all cached compile commands.
  void clear();

private:
  const GlobalCompilationDatabase &InnerCDB;
  mutable std::mutex Mut;
  mutable llvm::StringMap<llvm::Optional<tooling::CompileCommand>>
      Cached; /* GUARDED_BY(Mut) */
};

/// Gets compile args from an in-memory mapping based on a filepath. Typically
/// used by clients who provide the compile commands themselves.
class InMemoryCompilationDb : public GlobalCompilationDatabase {
public:
  /// Gets compile command for \p File from the stored mapping.
  llvm::Optional<tooling::CompileCommand>
  getCompileCommand(PathRef File) const override;

  /// Sets the compilation command for a particular file.
  ///
  /// \returns True if the File had no compilation command before.
  bool setCompilationCommandForFile(PathRef File,
                                    tooling::CompileCommand CompilationCommand);

  /// Removes the compilation command for \p File if it's present in the
  /// mapping.
  void invalidate(PathRef File);

private:
  mutable std::mutex Mutex;
  llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */
};

} // namespace clangd
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H