brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · 81bb8de Raw
102 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "IncludeInserter.h"10#include "clang/Lex/PPCallbacks.h"11#include "clang/Lex/Preprocessor.h"12#include "clang/Lex/Token.h"13#include <optional>14 15namespace clang::tidy::utils {16 17class IncludeInserterCallback : public PPCallbacks {18public:19  explicit IncludeInserterCallback(IncludeInserter *Inserter)20      : Inserter(Inserter) {}21  // Implements PPCallbacks::InclusionDirective(). Records the names and source22  // locations of the inclusions in the main source file being processed.23  void InclusionDirective(SourceLocation HashLocation,24                          const Token &IncludeToken, StringRef FileNameRef,25                          bool IsAngled, CharSourceRange FileNameRange,26                          OptionalFileEntryRef /*IncludedFile*/,27                          StringRef /*SearchPath*/, StringRef /*RelativePath*/,28                          const Module * /*SuggestedModule*/,29                          bool /*ModuleImported*/,30                          SrcMgr::CharacteristicKind /*FileType*/) override {31    Inserter->addInclude(FileNameRef, IsAngled, HashLocation,32                         IncludeToken.getEndLoc());33  }34 35private:36  IncludeInserter *Inserter;37};38 39IncludeInserter::IncludeInserter(IncludeSorter::IncludeStyle Style,40                                 bool SelfContainedDiags)41    : Style(Style), SelfContainedDiags(SelfContainedDiags) {}42 43void IncludeInserter::registerPreprocessor(Preprocessor *PP) {44  assert(PP && "PP shouldn't be null");45  SourceMgr = &PP->getSourceManager();46 47  // If this gets registered multiple times, clear the maps48  if (!IncludeSorterByFile.empty())49    IncludeSorterByFile.clear();50  if (!InsertedHeaders.empty())51    InsertedHeaders.clear();52  PP->addPPCallbacks(std::make_unique<IncludeInserterCallback>(this));53}54 55IncludeSorter &IncludeInserter::getOrCreate(FileID FileID) {56  assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call "57                      "registerPreprocessor()?");58  // std::unique_ptr is cheap to construct, so force a construction now to save59  // the lookup needed if we were to insert into the map.60  std::unique_ptr<IncludeSorter> &Entry = IncludeSorterByFile[FileID];61  if (!Entry) {62    // If it wasn't found, Entry will be default constructed to nullptr.63    Entry = std::make_unique<IncludeSorter>(64        SourceMgr, FileID,65        SourceMgr->getFilename(SourceMgr->getLocForStartOfFile(FileID)), Style);66  }67  return *Entry;68}69 70std::optional<FixItHint>71IncludeInserter::createIncludeInsertion(FileID FileID, llvm::StringRef Header) {72  const bool IsAngled = Header.consume_front("<");73  if (IsAngled != Header.consume_back(">"))74    return std::nullopt;75  // We assume the same Header will never be included both angled and not76  // angled.77  // In self contained diags mode we don't track what headers we have already78  // inserted.79  if (!SelfContainedDiags && !InsertedHeaders[FileID].insert(Header).second)80    return std::nullopt;81 82  return getOrCreate(FileID).createIncludeInsertion(Header, IsAngled);83}84 85std::optional<FixItHint>86IncludeInserter::createMainFileIncludeInsertion(StringRef Header) {87  assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call "88                      "registerPreprocessor()?");89  return createIncludeInsertion(SourceMgr->getMainFileID(), Header);90}91 92void IncludeInserter::addInclude(StringRef FileName, bool IsAngled,93                                 SourceLocation HashLocation,94                                 SourceLocation EndLocation) {95  assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call "96                      "registerPreprocessor()?");97  const FileID FileID = SourceMgr->getFileID(HashLocation);98  getOrCreate(FileID).addInclude(FileName, IsAngled, HashLocation, EndLocation);99}100 101} // namespace clang::tidy::utils102