Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:40

0001 //===--- RawCommentList.h - Classes for processing raw comments -*- 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_AST_RAWCOMMENTLIST_H
0010 #define LLVM_CLANG_AST_RAWCOMMENTLIST_H
0011 
0012 #include "clang/Basic/CommentOptions.h"
0013 #include "clang/Basic/SourceLocation.h"
0014 #include "llvm/ADT/ArrayRef.h"
0015 #include "llvm/ADT/DenseMap.h"
0016 #include "llvm/Support/Allocator.h"
0017 #include <map>
0018 
0019 namespace clang {
0020 
0021 class ASTContext;
0022 class ASTReader;
0023 class Decl;
0024 class DiagnosticsEngine;
0025 class Preprocessor;
0026 class SourceManager;
0027 
0028 namespace comments {
0029   class FullComment;
0030 } // end namespace comments
0031 
0032 class RawComment {
0033 public:
0034   enum CommentKind {
0035     RCK_Invalid,      ///< Invalid comment
0036     RCK_OrdinaryBCPL, ///< Any normal BCPL comments
0037     RCK_OrdinaryC,    ///< Any normal C comment
0038     RCK_BCPLSlash,    ///< \code /// stuff \endcode
0039     RCK_BCPLExcl,     ///< \code //! stuff \endcode
0040     RCK_JavaDoc,      ///< \code /** stuff */ \endcode
0041     RCK_Qt,           ///< \code /*! stuff */ \endcode, also used by HeaderDoc
0042     RCK_Merged        ///< Two or more documentation comments merged together
0043   };
0044 
0045   RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { }
0046 
0047   RawComment(const SourceManager &SourceMgr, SourceRange SR,
0048              const CommentOptions &CommentOpts, bool Merged);
0049 
0050   CommentKind getKind() const LLVM_READONLY {
0051     return (CommentKind) Kind;
0052   }
0053 
0054   bool isInvalid() const LLVM_READONLY {
0055     return Kind == RCK_Invalid;
0056   }
0057 
0058   bool isMerged() const LLVM_READONLY {
0059     return Kind == RCK_Merged;
0060   }
0061 
0062   /// Is this comment attached to any declaration?
0063   bool isAttached() const LLVM_READONLY {
0064     return IsAttached;
0065   }
0066 
0067   void setAttached() {
0068     IsAttached = true;
0069   }
0070 
0071   /// Returns true if it is a comment that should be put after a member:
0072   /// \code ///< stuff \endcode
0073   /// \code //!< stuff \endcode
0074   /// \code /**< stuff */ \endcode
0075   /// \code /*!< stuff */ \endcode
0076   bool isTrailingComment() const LLVM_READONLY {
0077     return IsTrailingComment;
0078   }
0079 
0080   /// Returns true if it is a probable typo:
0081   /// \code //< stuff \endcode
0082   /// \code /*< stuff */ \endcode
0083   bool isAlmostTrailingComment() const LLVM_READONLY {
0084     return IsAlmostTrailingComment;
0085   }
0086 
0087   /// Returns true if this comment is not a documentation comment.
0088   bool isOrdinary() const LLVM_READONLY {
0089     return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC));
0090   }
0091 
0092   /// Returns true if this comment any kind of a documentation comment.
0093   bool isDocumentation() const LLVM_READONLY {
0094     return !isInvalid() && !isOrdinary();
0095   }
0096 
0097   /// Returns raw comment text with comment markers.
0098   StringRef getRawText(const SourceManager &SourceMgr) const {
0099     if (RawTextValid)
0100       return RawText;
0101 
0102     RawText = getRawTextSlow(SourceMgr);
0103     RawTextValid = true;
0104     return RawText;
0105   }
0106 
0107   SourceRange getSourceRange() const LLVM_READONLY { return Range; }
0108   SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
0109   SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
0110 
0111   const char *getBriefText(const ASTContext &Context) const {
0112     if (BriefTextValid)
0113       return BriefText;
0114 
0115     return extractBriefText(Context);
0116   }
0117 
0118   bool hasUnsupportedSplice(const SourceManager &SourceMgr) const {
0119     if (!isInvalid())
0120       return false;
0121     StringRef Text = getRawText(SourceMgr);
0122     if (Text.size() < 6 || Text[0] != '/')
0123       return false;
0124     if (Text[1] == '*')
0125       return Text[Text.size() - 1] != '/' || Text[Text.size() - 2] != '*';
0126     return Text[1] != '/';
0127   }
0128 
0129   /// Returns sanitized comment text, suitable for presentation in editor UIs.
0130   /// E.g. will transform:
0131   ///     // This is a long multiline comment.
0132   ///     //   Parts of it  might be indented.
0133   ///     /* The comments styles might be mixed. */
0134   ///  into
0135   ///     "This is a long multiline comment.\n"
0136   ///     "  Parts of it  might be indented.\n"
0137   ///     "The comments styles might be mixed."
0138   /// Also removes leading indentation and sanitizes some common cases:
0139   ///     /* This is a first line.
0140   ///      *   This is a second line. It is indented.
0141   ///      * This is a third line. */
0142   /// and
0143   ///     /* This is a first line.
0144   ///          This is a second line. It is indented.
0145   ///     This is a third line. */
0146   /// will both turn into:
0147   ///     "This is a first line.\n"
0148   ///     "  This is a second line. It is indented.\n"
0149   ///     "This is a third line."
0150   std::string getFormattedText(const SourceManager &SourceMgr,
0151                                DiagnosticsEngine &Diags) const;
0152 
0153   struct CommentLine {
0154     std::string Text;
0155     PresumedLoc Begin;
0156     PresumedLoc End;
0157 
0158     CommentLine(StringRef Text, PresumedLoc Begin, PresumedLoc End)
0159         : Text(Text), Begin(Begin), End(End) {}
0160   };
0161 
0162   /// Returns sanitized comment text as separated lines with locations in
0163   /// source, suitable for further processing and rendering requiring source
0164   /// locations.
0165   std::vector<CommentLine> getFormattedLines(const SourceManager &SourceMgr,
0166                                              DiagnosticsEngine &Diags) const;
0167 
0168   /// Parse the comment, assuming it is attached to decl \c D.
0169   comments::FullComment *parse(const ASTContext &Context,
0170                                const Preprocessor *PP, const Decl *D) const;
0171 
0172 private:
0173   SourceRange Range;
0174 
0175   mutable StringRef RawText;
0176   mutable const char *BriefText = nullptr;
0177 
0178   LLVM_PREFERRED_TYPE(bool)
0179   mutable unsigned RawTextValid : 1;
0180   LLVM_PREFERRED_TYPE(bool)
0181   mutable unsigned BriefTextValid : 1;
0182 
0183   LLVM_PREFERRED_TYPE(CommentKind)
0184   unsigned Kind : 3;
0185 
0186   /// True if comment is attached to a declaration in ASTContext.
0187   LLVM_PREFERRED_TYPE(bool)
0188   unsigned IsAttached : 1;
0189 
0190   LLVM_PREFERRED_TYPE(bool)
0191   unsigned IsTrailingComment : 1;
0192   LLVM_PREFERRED_TYPE(bool)
0193   unsigned IsAlmostTrailingComment : 1;
0194 
0195   /// Constructor for AST deserialization.
0196   RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
0197              bool IsAlmostTrailingComment) :
0198     Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
0199     IsAttached(false), IsTrailingComment(IsTrailingComment),
0200     IsAlmostTrailingComment(IsAlmostTrailingComment)
0201   { }
0202 
0203   StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
0204 
0205   const char *extractBriefText(const ASTContext &Context) const;
0206 
0207   friend class ASTReader;
0208 };
0209 
0210 /// This class represents all comments included in the translation unit,
0211 /// sorted in order of appearance in the translation unit.
0212 class RawCommentList {
0213 public:
0214   RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
0215 
0216   void addComment(const RawComment &RC, const CommentOptions &CommentOpts,
0217                   llvm::BumpPtrAllocator &Allocator);
0218 
0219   /// \returns A mapping from an offset of the start of the comment to the
0220   /// comment itself, or nullptr in case there are no comments in \p File.
0221   const std::map<unsigned, RawComment *> *getCommentsInFile(FileID File) const;
0222 
0223   bool empty() const;
0224 
0225   unsigned getCommentBeginLine(RawComment *C, FileID File,
0226                                unsigned Offset) const;
0227   unsigned getCommentEndOffset(RawComment *C) const;
0228 
0229 private:
0230   SourceManager &SourceMgr;
0231   // mapping: FileId -> comment begin offset -> comment
0232   llvm::DenseMap<FileID, std::map<unsigned, RawComment *>> OrderedComments;
0233   mutable llvm::DenseMap<RawComment *, unsigned> CommentBeginLine;
0234   mutable llvm::DenseMap<RawComment *, unsigned> CommentEndOffset;
0235 
0236   friend class ASTReader;
0237   friend class ASTWriter;
0238 };
0239 
0240 } // end namespace clang
0241 
0242 #endif