Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:11

0001 //===--- HeaderIncludes.h - Insert/Delete #includes for C++ code--*- C++-*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
0010 #define LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
0011 
0012 #include "clang/Basic/SourceManager.h"
0013 #include "clang/Tooling/Core/Replacement.h"
0014 #include "clang/Tooling/Inclusions/IncludeStyle.h"
0015 #include "llvm/Support/Path.h"
0016 #include "llvm/Support/Regex.h"
0017 #include <list>
0018 #include <optional>
0019 #include <unordered_map>
0020 
0021 namespace clang {
0022 namespace tooling {
0023 
0024 /// This class manages priorities of C++ #include categories and calculates
0025 /// priorities for headers.
0026 /// FIXME(ioeric): move this class into implementation file when clang-format's
0027 /// include sorting functions are also moved here.
0028 class IncludeCategoryManager {
0029 public:
0030   IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName);
0031 
0032   /// Returns the priority of the category which \p IncludeName belongs to.
0033   /// If \p CheckMainHeader is true and \p IncludeName is a main header, returns
0034   /// 0. Otherwise, returns the priority of the matching category or INT_MAX.
0035   /// NOTE: this API is not thread-safe!
0036   int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
0037   int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
0038 
0039 private:
0040   bool isMainHeader(StringRef IncludeName) const;
0041 
0042   const IncludeStyle Style;
0043   bool IsMainFile;
0044   std::string FileName;
0045   SmallVector<llvm::Regex, 4> CategoryRegexs;
0046 };
0047 
0048 enum class IncludeDirective { Include, Import };
0049 
0050 /// Generates replacements for inserting or deleting #include directives in a
0051 /// file.
0052 class HeaderIncludes {
0053 public:
0054   HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
0055                  const IncludeStyle &Style);
0056 
0057   /// Inserts an #include or #import directive of \p Header into the code.
0058   /// If \p IsAngled is true, \p Header will be quoted with <> in the directive;
0059   /// otherwise, it will be quoted with "".
0060   ///
0061   /// When searching for points to insert new header, this ignores #include's
0062   /// after the #include block(s) in the beginning of a file to avoid inserting
0063   /// headers into code sections where new #include's should not be added by
0064   /// default. These code sections include:
0065   ///   - raw string literals (containing #include).
0066   ///   - #if blocks.
0067   ///   - Special #include's among declarations (e.g. functions).
0068   ///
0069   /// Returns a replacement that inserts the new header into a suitable #include
0070   /// block of the same category. This respects the order of the existing
0071   /// #includes in the block; if the existing #includes are not already sorted,
0072   /// this will simply insert the #include in front of the first #include of the
0073   /// same category in the code that should be sorted after \p IncludeName. If
0074   /// \p IncludeName already exists (with exactly the same spelling), this
0075   /// returns std::nullopt.
0076   std::optional<tooling::Replacement> insert(llvm::StringRef Header,
0077                                              bool IsAngled,
0078                                              IncludeDirective Directive) const;
0079 
0080   /// Removes all existing #includes and #imports of \p Header quoted with <> if
0081   /// \p IsAngled is true or "" if \p IsAngled is false.
0082   /// This doesn't resolve the header file path; it only deletes #includes and
0083   /// #imports with exactly the same spelling.
0084   tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
0085 
0086   // Matches a whole #include directive.
0087   static const llvm::Regex IncludeRegex;
0088 
0089 private:
0090   struct Include {
0091     Include(StringRef Name, tooling::Range R, IncludeDirective D)
0092         : Name(Name), R(R), Directive(D) {}
0093 
0094     // An include header quoted with either <> or "".
0095     std::string Name;
0096     // The range of the whole line of include directive including any leading
0097     // whitespaces and trailing comment.
0098     tooling::Range R;
0099     // Either #include or #import.
0100     IncludeDirective Directive;
0101   };
0102 
0103   void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset);
0104 
0105   std::string FileName;
0106   std::string Code;
0107 
0108   // Map from include name (quotation trimmed) to a list of existing includes
0109   // (in case there are more than one) with the name in the current file. <x>
0110   // and "x" will be treated as the same header when deleting #includes.
0111   // std::list is used for pointers stability (see IncludesByPriority)
0112   llvm::StringMap<std::list<Include>> ExistingIncludes;
0113 
0114   /// Map from priorities of #include categories to all #includes in the same
0115   /// category. This is used to find #includes of the same category when
0116   /// inserting new #includes. #includes in the same categories are sorted in
0117   /// in the order they appear in the source file.
0118   /// See comment for "FormatStyle::IncludeCategories" for details about include
0119   /// priorities.
0120   std::unordered_map<int, llvm::SmallVector<const Include *, 8>>
0121       IncludesByPriority;
0122 
0123   int FirstIncludeOffset;
0124   // All new headers should be inserted after this offset (e.g. after header
0125   // guards, file comment).
0126   unsigned MinInsertOffset;
0127   // Max insertion offset in the original code. For example, we want to avoid
0128   // inserting new #includes into the actual code section (e.g. after a
0129   // declaration).
0130   unsigned MaxInsertOffset;
0131   // True if we find the main-file header in the Code.
0132   bool MainIncludeFound;
0133   IncludeCategoryManager Categories;
0134   // Record the offset of the end of the last include in each category.
0135   std::unordered_map<int, int> CategoryEndOffsets;
0136 
0137   // All possible priorities.
0138   std::set<int> Priorities;
0139 };
0140 
0141 } // namespace tooling
0142 } // namespace clang
0143 
0144 #endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H