xref: /llvm-project/clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp (revision e7b4b437fbbf087ac4955ed5945c3e2f3dd2b702)
1 //===--- IncludeSpeller.cpp------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang-include-cleaner/IncludeSpeller.h"
10 #include "clang-include-cleaner/Types.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/ErrorHandling.h"
14 #include "llvm/Support/Registry.h"
15 #include <memory>
16 #include <string>
17 
18 LLVM_INSTANTIATE_REGISTRY(clang::include_cleaner::IncludeSpellingStrategy)
19 
20 namespace clang::include_cleaner {
21 namespace {
22 
23 // Fallback strategy to default spelling via header search.
24 class DefaultIncludeSpeller : public IncludeSpeller {
25 public:
operator ()(const Input & Input) const26   std::string operator()(const Input &Input) const override {
27     switch (Input.H.kind()) {
28     case Header::Standard:
29       return Input.H.standard().name().str();
30     case Header::Verbatim:
31       return Input.H.verbatim().str();
32     case Header::Physical:
33       bool IsAngled = false;
34       std::string WorkingDir;
35       if (auto WD = Input.HS.getFileMgr()
36                         .getVirtualFileSystem()
37                         .getCurrentWorkingDirectory())
38         WorkingDir = *WD;
39       std::string FinalSpelling = Input.HS.suggestPathToFileForDiagnostics(
40           Input.H.physical().getName(), WorkingDir,
41           Input.Main->tryGetRealPathName(), &IsAngled);
42       return IsAngled ? "<" + FinalSpelling + ">" : "\"" + FinalSpelling + "\"";
43     }
44     llvm_unreachable("Unknown clang::include_cleaner::Header::Kind enum");
45   }
46 };
47 
48 } // namespace
49 
spellHeader(const IncludeSpeller::Input & Input)50 std::string spellHeader(const IncludeSpeller::Input &Input) {
51   static auto *Spellers = [] {
52     auto *Result =
53         new llvm::SmallVector<std::unique_ptr<include_cleaner::IncludeSpeller>>;
54     for (const auto &Strategy :
55          include_cleaner::IncludeSpellingStrategy::entries())
56       Result->push_back(Strategy.instantiate());
57     Result->push_back(std::make_unique<DefaultIncludeSpeller>());
58     return Result;
59   }();
60 
61   std::string Spelling;
62   for (const auto &Speller : *Spellers) {
63     Spelling = (*Speller)(Input);
64     if (!Spelling.empty())
65       break;
66   }
67   return Spelling;
68 }
69 
70 } // namespace clang::include_cleaner
71