/
ClangdUnitStore.h
109 lines (93 loc) · 4.12 KB
/
ClangdUnitStore.h
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
//===--- ClangdUnitStore.h - A ClangdUnits container -------------*-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_CLANGDUNITSTORE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNITSTORE_H
#include <mutex>
#include "ClangdUnit.h"
#include "GlobalCompilationDatabase.h"
#include "Path.h"
#include "clang/Tooling/CompilationDatabase.h"
namespace clang {
namespace clangd {
/// Thread-safe collection of ASTs built for specific files. Provides
/// synchronized access to ASTs.
class ClangdUnitStore {
public:
/// Run specified \p Action on the ClangdUnit for \p File.
/// If the file is not present in ClangdUnitStore, a new ClangdUnit will be
/// created from the \p FileContents. If the file is already present in the
/// store, ClangdUnit::reparse will be called with the new contents before
/// running \p Action.
template <class Func>
void runOnUnit(PathRef File, StringRef FileContents, StringRef ResourceDir,
GlobalCompilationDatabase &CDB,
std::shared_ptr<PCHContainerOperations> PCHs,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) {
runOnUnitImpl(File, FileContents, ResourceDir, CDB, PCHs,
/*ReparseBeforeAction=*/true, VFS,
std::forward<Func>(Action));
}
/// Run specified \p Action on the ClangdUnit for \p File.
/// If the file is not present in ClangdUnitStore, a new ClangdUnit will be
/// created from the \p FileContents. If the file is already present in the
/// store, the \p Action will be run directly on it.
template <class Func>
void runOnUnitWithoutReparse(PathRef File, StringRef FileContents,
StringRef ResourceDir,
GlobalCompilationDatabase &CDB,
std::shared_ptr<PCHContainerOperations> PCHs,
IntrusiveRefCntPtr<vfs::FileSystem> VFS,
Func Action) {
runOnUnitImpl(File, FileContents, ResourceDir, CDB, PCHs,
/*ReparseBeforeAction=*/false, VFS,
std::forward<Func>(Action));
}
/// Run the specified \p Action on the ClangdUnit for \p File.
/// Unit for \p File should exist in the store.
template <class Func> void runOnExistingUnit(PathRef File, Func Action) {
std::lock_guard<std::mutex> Lock(Mutex);
auto It = OpenedFiles.find(File);
assert(It != OpenedFiles.end() && "File is not in OpenedFiles");
Action(It->second);
}
/// Remove ClangdUnit for \p File, if any
void removeUnitIfPresent(PathRef File);
private:
/// Run specified \p Action on the ClangdUnit for \p File.
template <class Func>
void runOnUnitImpl(PathRef File, StringRef FileContents,
StringRef ResourceDir, GlobalCompilationDatabase &CDB,
std::shared_ptr<PCHContainerOperations> PCHs,
bool ReparseBeforeAction,
IntrusiveRefCntPtr<vfs::FileSystem> VFS, Func Action) {
std::lock_guard<std::mutex> Lock(Mutex);
auto Commands = getCompileCommands(CDB, File);
assert(!Commands.empty() &&
"getCompileCommands should add default command");
VFS->setCurrentWorkingDirectory(Commands.front().Directory);
auto It = OpenedFiles.find(File);
if (It == OpenedFiles.end()) {
It = OpenedFiles
.insert(std::make_pair(File, ClangdUnit(File, FileContents,
ResourceDir, PCHs,
Commands, VFS)))
.first;
} else if (ReparseBeforeAction) {
It->second.reparse(FileContents, VFS);
}
return Action(It->second);
}
std::vector<tooling::CompileCommand>
getCompileCommands(GlobalCompilationDatabase &CDB, PathRef File);
std::mutex Mutex;
llvm::StringMap<ClangdUnit> OpenedFiles;
};
} // namespace clangd
} // namespace clang
#endif