Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- HeaderIncludes.h - Insert/Delete #includes for C++ code--*- C++-*-===//
  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. #ifndef LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
  10. #define LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
  11.  
  12. #include "clang/Basic/SourceManager.h"
  13. #include "clang/Tooling/Core/Replacement.h"
  14. #include "clang/Tooling/Inclusions/IncludeStyle.h"
  15. #include "llvm/Support/Path.h"
  16. #include "llvm/Support/Regex.h"
  17. #include <list>
  18. #include <optional>
  19. #include <unordered_map>
  20.  
  21. namespace clang {
  22. namespace tooling {
  23.  
  24. /// This class manages priorities of C++ #include categories and calculates
  25. /// priorities for headers.
  26. /// FIXME(ioeric): move this class into implementation file when clang-format's
  27. /// include sorting functions are also moved here.
  28. class IncludeCategoryManager {
  29. public:
  30.   IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName);
  31.  
  32.   /// Returns the priority of the category which \p IncludeName belongs to.
  33.   /// If \p CheckMainHeader is true and \p IncludeName is a main header, returns
  34.   /// 0. Otherwise, returns the priority of the matching category or INT_MAX.
  35.   /// NOTE: this API is not thread-safe!
  36.   int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
  37.   int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
  38.  
  39. private:
  40.   bool isMainHeader(StringRef IncludeName) const;
  41.  
  42.   const IncludeStyle Style;
  43.   bool IsMainFile;
  44.   std::string FileName;
  45.   SmallVector<llvm::Regex, 4> CategoryRegexs;
  46. };
  47.  
  48. enum class IncludeDirective { Include, Import };
  49.  
  50. /// Generates replacements for inserting or deleting #include directives in a
  51. /// file.
  52. class HeaderIncludes {
  53. public:
  54.   HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
  55.                  const IncludeStyle &Style);
  56.  
  57.   /// Inserts an #include or #import directive of \p Header into the code.
  58.   /// If \p IsAngled is true, \p Header will be quoted with <> in the directive;
  59.   /// otherwise, it will be quoted with "".
  60.   ///
  61.   /// When searching for points to insert new header, this ignores #include's
  62.   /// after the #include block(s) in the beginning of a file to avoid inserting
  63.   /// headers into code sections where new #include's should not be added by
  64.   /// default. These code sections include:
  65.   ///   - raw string literals (containing #include).
  66.   ///   - #if blocks.
  67.   ///   - Special #include's among declarations (e.g. functions).
  68.   ///
  69.   /// Returns a replacement that inserts the new header into a suitable #include
  70.   /// block of the same category. This respects the order of the existing
  71.   /// #includes in the block; if the existing #includes are not already sorted,
  72.   /// this will simply insert the #include in front of the first #include of the
  73.   /// same category in the code that should be sorted after \p IncludeName. If
  74.   /// \p IncludeName already exists (with exactly the same spelling), this
  75.   /// returns std::nullopt.
  76.   std::optional<tooling::Replacement> insert(llvm::StringRef Header,
  77.                                              bool IsAngled,
  78.                                              IncludeDirective Directive) const;
  79.  
  80.   /// Removes all existing #includes and #imports of \p Header quoted with <> if
  81.   /// \p IsAngled is true or "" if \p IsAngled is false.
  82.   /// This doesn't resolve the header file path; it only deletes #includes and
  83.   /// #imports with exactly the same spelling.
  84.   tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
  85.  
  86.   // Matches a whole #include directive.
  87.   static const llvm::Regex IncludeRegex;
  88.  
  89. private:
  90.   struct Include {
  91.     Include(StringRef Name, tooling::Range R, IncludeDirective D)
  92.         : Name(Name), R(R), Directive(D) {}
  93.  
  94.     // An include header quoted with either <> or "".
  95.     std::string Name;
  96.     // The range of the whole line of include directive including any leading
  97.     // whitespaces and trailing comment.
  98.     tooling::Range R;
  99.     // Either #include or #import.
  100.     IncludeDirective Directive;
  101.   };
  102.  
  103.   void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset);
  104.  
  105.   std::string FileName;
  106.   std::string Code;
  107.  
  108.   // Map from include name (quotation trimmed) to a list of existing includes
  109.   // (in case there are more than one) with the name in the current file. <x>
  110.   // and "x" will be treated as the same header when deleting #includes.
  111.   // std::list is used for pointers stability (see IncludesByPriority)
  112.   llvm::StringMap<std::list<Include>> ExistingIncludes;
  113.  
  114.   /// Map from priorities of #include categories to all #includes in the same
  115.   /// category. This is used to find #includes of the same category when
  116.   /// inserting new #includes. #includes in the same categories are sorted in
  117.   /// in the order they appear in the source file.
  118.   /// See comment for "FormatStyle::IncludeCategories" for details about include
  119.   /// priorities.
  120.   std::unordered_map<int, llvm::SmallVector<const Include *, 8>>
  121.       IncludesByPriority;
  122.  
  123.   int FirstIncludeOffset;
  124.   // All new headers should be inserted after this offset (e.g. after header
  125.   // guards, file comment).
  126.   unsigned MinInsertOffset;
  127.   // Max insertion offset in the original code. For example, we want to avoid
  128.   // inserting new #includes into the actual code section (e.g. after a
  129.   // declaration).
  130.   unsigned MaxInsertOffset;
  131.   IncludeCategoryManager Categories;
  132.   // Record the offset of the end of the last include in each category.
  133.   std::unordered_map<int, int> CategoryEndOffsets;
  134.  
  135.   // All possible priorities.
  136.   std::set<int> Priorities;
  137. };
  138.  
  139. } // namespace tooling
  140. } // namespace clang
  141.  
  142. #endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
  143.