summaryrefslogtreecommitdiffstats
path: root/clangd/ClangdUnitStore.cpp
blob: c92ae59ab5648955832fb8269e2c883c514d923e (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
//===--- ClangdUnitStore.cpp - 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.
//
//===----------------------------------------------------------------------===//

#include "ClangdUnitStore.h"
#include "llvm/Support/Path.h"
#include <algorithm>

using namespace clang::clangd;
using namespace clang;

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

  auto It = OpenedFiles.find(File);
  if (It == OpenedFiles.end())
    return nullptr;

  std::shared_ptr<CppFile> Result = It->second;
  OpenedFiles.erase(It);
  return Result;
}

CppFileCollection::RecreateResult
CppFileCollection::recreateFileIfCompileCommandChanged(
    PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
    bool StorePreamblesInMemory, std::shared_ptr<PCHContainerOperations> PCHs) {
  auto NewCommand = getCompileCommand(CDB, File, ResourceDir);

  std::lock_guard<std::mutex> Lock(Mutex);

  RecreateResult Result;

  auto It = OpenedFiles.find(File);
  if (It == OpenedFiles.end()) {
    It = OpenedFiles
             .try_emplace(File, CppFile::Create(File, std::move(NewCommand),
                                                StorePreamblesInMemory,
                                                std::move(PCHs)))
             .first;
  } else if (!compileCommandsAreEqual(It->second->getCompileCommand(),
                                      NewCommand)) {
    Result.RemovedFile = std::move(It->second);
    It->second = CppFile::Create(File, std::move(NewCommand),
                                 StorePreamblesInMemory, std::move(PCHs));
  }
  Result.FileInCollection = It->second;
  return Result;
}

tooling::CompileCommand
CppFileCollection::getCompileCommand(GlobalCompilationDatabase &CDB,
                                     PathRef File, PathRef ResourceDir) {
  llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
  if (!C) // FIXME: Suppress diagnostics? Let the user know?
    C = CDB.getFallbackCommand(File);

  // Inject the resource dir.
  // FIXME: Don't overwrite it if it's already there.
  C->CommandLine.push_back("-resource-dir=" + ResourceDir.str());
  return std::move(*C);
}

bool CppFileCollection::compileCommandsAreEqual(
    tooling::CompileCommand const &LHS, tooling::CompileCommand const &RHS) {
  // tooling::CompileCommand.Output is ignored, it's not relevant for clangd.
  return LHS.Directory == RHS.Directory &&
         LHS.CommandLine.size() == RHS.CommandLine.size() &&
         std::equal(LHS.CommandLine.begin(), LHS.CommandLine.end(),
                    RHS.CommandLine.begin());
}