aboutsummaryrefslogtreecommitdiff
path: root/clangd/ClangdUnitStore.h
blob: cf7f1fb729258ec0f5e1793963792e804549d3d3 (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
//===--- ClangdUnitStore.h - A container of CppFiles -------------*-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 {

class Logger;

/// Thread-safe mapping from FileNames to CppFile.
class CppFileCollection {
public:
  std::shared_ptr<CppFile> getOrCreateFile(
      PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
      std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger) {
    std::lock_guard<std::mutex> Lock(Mutex);

    auto It = OpenedFiles.find(File);
    if (It == OpenedFiles.end()) {
      auto Command = getCompileCommand(CDB, File, ResourceDir);

      It = OpenedFiles
               .try_emplace(File, CppFile::Create(File, std::move(Command),
                                                  std::move(PCHs), Logger))
               .first;
    }
    return It->second;
  }

  struct RecreateResult {
    /// A CppFile, stored in this CppFileCollection for the corresponding
    /// filepath after calling recreateFileIfCompileCommandChanged.
    std::shared_ptr<CppFile> FileInCollection;
    /// If a new CppFile had to be created to account for changed
    /// CompileCommand, a previous CppFile instance will be returned in this
    /// field.
    std::shared_ptr<CppFile> RemovedFile;
  };

  /// Similar to getOrCreateFile, but will replace a current CppFile for \p File
  /// with a new one if CompileCommand, provided by \p CDB has changed.
  /// If a currently stored CppFile had to be replaced, the previous instance
  /// will be returned in RecreateResult.RemovedFile.
  RecreateResult recreateFileIfCompileCommandChanged(
      PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
      std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);

  std::shared_ptr<CppFile> getFile(PathRef File) {
    std::lock_guard<std::mutex> Lock(Mutex);

    auto It = OpenedFiles.find(File);
    if (It == OpenedFiles.end())
      return nullptr;
    return It->second;
  }

  /// Removes a CppFile, stored for \p File, if it's inside collection and
  /// returns it.
  std::shared_ptr<CppFile> removeIfPresent(PathRef File);

private:
  tooling::CompileCommand getCompileCommand(GlobalCompilationDatabase &CDB,
                                            PathRef File, PathRef ResourceDir);

  bool compileCommandsAreEqual(tooling::CompileCommand const &LHS,
                               tooling::CompileCommand const &RHS);

  std::mutex Mutex;
  llvm::StringMap<std::shared_ptr<CppFile>> OpenedFiles;
};
} // namespace clangd
} // namespace clang

#endif