brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.1 KiB · 1ae067f Raw
637 lines · c
1///===-- Representation.h - ClangDoc Representation -------------*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the internal representations of different declaration10// types for the clang-doc tool.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H15#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H16 17#include "clang/AST/Type.h"18#include "clang/Basic/Specifiers.h"19#include "clang/Tooling/Execution.h"20#include "llvm/ADT/SmallVector.h"21#include <array>22#include <optional>23#include <string>24 25namespace clang {26namespace doc {27 28// SHA1'd hash of a USR.29using SymbolID = std::array<uint8_t, 20>;30 31constexpr SymbolID GlobalNamespaceID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32                                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0};33 34struct BaseRecordInfo;35struct EnumInfo;36struct FunctionInfo;37struct Info;38struct TypedefInfo;39struct ConceptInfo;40struct VarInfo;41 42enum class InfoType {43  IT_default,44  IT_namespace,45  IT_record,46  IT_function,47  IT_enum,48  IT_typedef,49  IT_concept,50  IT_variable,51  IT_friend52};53 54enum class CommentKind {55  CK_FullComment,56  CK_ParagraphComment,57  CK_TextComment,58  CK_InlineCommandComment,59  CK_HTMLStartTagComment,60  CK_HTMLEndTagComment,61  CK_BlockCommandComment,62  CK_ParamCommandComment,63  CK_TParamCommandComment,64  CK_VerbatimBlockComment,65  CK_VerbatimBlockLineComment,66  CK_VerbatimLineComment,67  CK_Unknown68};69 70CommentKind stringToCommentKind(llvm::StringRef KindStr);71llvm::StringRef commentKindToString(CommentKind Kind);72 73// A representation of a parsed comment.74struct CommentInfo {75  CommentInfo() = default;76  CommentInfo(CommentInfo &Other) = delete;77  CommentInfo(CommentInfo &&Other) = default;78  CommentInfo &operator=(CommentInfo &&Other) = default;79 80  bool operator==(const CommentInfo &Other) const;81 82  // This operator is used to sort a vector of CommentInfos.83  // No specific order (attributes more important than others) is required. Any84  // sort is enough, the order is only needed to call std::unique after sorting85  // the vector.86  bool operator<(const CommentInfo &Other) const;87 88  CommentKind Kind = CommentKind::89      CK_Unknown; // Kind of comment (FullComment, ParagraphComment,90                  // TextComment, InlineCommandComment, HTMLStartTagComment,91                  // HTMLEndTagComment, BlockCommandComment,92                  // ParamCommandComment, TParamCommandComment,93                  // VerbatimBlockComment, VerbatimBlockLineComment,94                  // VerbatimLineComment).95  SmallString<64> Text;      // Text of the comment.96  SmallString<16> Name;      // Name of the comment (for Verbatim and HTML).97  SmallString<8> Direction;  // Parameter direction (for (T)ParamCommand).98  SmallString<16> ParamName; // Parameter name (for (T)ParamCommand).99  SmallString<16> CloseName; // Closing tag name (for VerbatimBlock).100  bool SelfClosing = false;  // Indicates if tag is self-closing (for HTML).101  bool Explicit = false; // Indicates if the direction of a param is explicit102                         // (for (T)ParamCommand).103  llvm::SmallVector<SmallString<16>, 4>104      AttrKeys; // List of attribute keys (for HTML).105  llvm::SmallVector<SmallString<16>, 4>106      AttrValues; // List of attribute values for each key (for HTML).107  llvm::SmallVector<SmallString<16>, 4>108      Args; // List of arguments to commands (for InlineCommand).109  std::vector<std::unique_ptr<CommentInfo>>110      Children; // List of child comments for this CommentInfo.111};112 113struct Reference {114  // This variant (that takes no qualified name parameter) uses the Name as the115  // QualName (very useful in unit tests to reduce verbosity). This can't use an116  // empty string to indicate the default because we need to accept the empty117  // string as a valid input for the global namespace (it will have118  // "GlobalNamespace" as the name, but an empty QualName).119  Reference(SymbolID USR = SymbolID(), StringRef Name = StringRef(),120            InfoType IT = InfoType::IT_default)121      : USR(USR), Name(Name), QualName(Name), RefType(IT) {}122  Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,123            StringRef Path = StringRef())124      : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path) {}125  Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,126            StringRef Path, SmallString<16> DocumentationFileName)127      : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path),128        DocumentationFileName(DocumentationFileName) {}129 130  bool operator==(const Reference &Other) const {131    return std::tie(USR, Name, QualName, RefType) ==132           std::tie(Other.USR, Other.Name, QualName, Other.RefType);133  }134 135  bool mergeable(const Reference &Other);136  void merge(Reference &&I);137  bool operator<(const Reference &Other) const { return Name < Other.Name; }138 139  /// Returns the path for this Reference relative to CurrentPath.140  llvm::SmallString<64> getRelativeFilePath(const StringRef &CurrentPath) const;141 142  /// Returns the basename that should be used for this Reference.143  llvm::SmallString<16> getFileBaseName() const;144 145  SymbolID USR = SymbolID(); // Unique identifier for referenced decl146 147  // Name of type (possibly unresolved). Not including namespaces or template148  // parameters (so for a std::vector<int> this would be "vector"). See also149  // QualName.150  SmallString<16> Name;151 152  // Full qualified name of this type, including namespaces and template153  // parameter (for example this could be "std::vector<int>"). Contrast to154  // Name.155  SmallString<16> QualName;156 157  InfoType RefType = InfoType::IT_default; // Indicates the type of this158                                           // Reference (namespace, record,159                                           // function, enum, default).160  // Path of directory where the clang-doc generated file will be saved161  // (possibly unresolved)162  llvm::SmallString<128> Path;163  SmallString<16> DocumentationFileName;164};165 166// Holds the children of a record or namespace.167struct ScopeChildren {168  // Namespaces and Records are references because they will be properly169  // documented in their own info, while the entirety of Functions and Enums are170  // included here because they should not have separate documentation from171  // their scope.172  //173  // Namespaces are not syntactically valid as children of records, but making174  // this general for all possible container types reduces code complexity.175  std::vector<Reference> Namespaces;176  std::vector<Reference> Records;177  std::vector<FunctionInfo> Functions;178  std::vector<EnumInfo> Enums;179  std::vector<TypedefInfo> Typedefs;180  std::vector<ConceptInfo> Concepts;181  std::vector<VarInfo> Variables;182 183  void sort();184};185 186// A base struct for TypeInfos187struct TypeInfo {188  TypeInfo() = default;189  TypeInfo(const Reference &R) : Type(R) {}190 191  // Convenience constructor for when there is no symbol ID or info type192  // (normally used for built-in types in tests).193  TypeInfo(StringRef Name, StringRef Path = StringRef())194      : Type(SymbolID(), Name, InfoType::IT_default, Name, Path) {}195 196  bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }197 198  Reference Type; // Referenced type in this info.199 200  bool IsTemplate = false;201  bool IsBuiltIn = false;202};203 204// Represents one template parameter.205//206// This is a very simple serialization of the text of the source code of the207// template parameter. It is saved in a struct so there is a place to add the208// name and default values in the future if needed.209struct TemplateParamInfo {210  TemplateParamInfo() = default;211  explicit TemplateParamInfo(StringRef Contents) : Contents(Contents) {}212 213  // The literal contents of the code for that specifies this template parameter214  // for this declaration. Typical values will be "class T" and215  // "typename T = int".216  SmallString<16> Contents;217};218 219struct TemplateSpecializationInfo {220  // Indicates the declaration that this specializes.221  SymbolID SpecializationOf;222 223  // Template parameters applying to the specialized record/function.224  std::vector<TemplateParamInfo> Params;225};226 227struct ConstraintInfo {228  ConstraintInfo() = default;229  ConstraintInfo(SymbolID USR, StringRef Name)230      : ConceptRef(USR, Name, InfoType::IT_concept) {}231  Reference ConceptRef;232 233  SmallString<16> ConstraintExpr;234};235 236// Records the template information for a struct or function that is a template237// or an explicit template specialization.238struct TemplateInfo {239  // May be empty for non-partial specializations.240  std::vector<TemplateParamInfo> Params;241 242  // Set when this is a specialization of another record/function.243  std::optional<TemplateSpecializationInfo> Specialization;244  std::vector<ConstraintInfo> Constraints;245};246 247// Info for field types.248struct FieldTypeInfo : public TypeInfo {249  FieldTypeInfo() = default;250  FieldTypeInfo(const TypeInfo &TI, StringRef Name = StringRef(),251                StringRef DefaultValue = StringRef())252      : TypeInfo(TI), Name(Name), DefaultValue(DefaultValue) {}253 254  bool operator==(const FieldTypeInfo &Other) const {255    return std::tie(Type, Name, DefaultValue) ==256           std::tie(Other.Type, Other.Name, Other.DefaultValue);257  }258 259  SmallString<16> Name; // Name associated with this info.260 261  // When used for function parameters, contains the string representing the262  // expression of the default value, if any.263  SmallString<16> DefaultValue;264};265 266// Info for member types.267struct MemberTypeInfo : public FieldTypeInfo {268  MemberTypeInfo() = default;269  MemberTypeInfo(const TypeInfo &TI, StringRef Name, AccessSpecifier Access,270                 bool IsStatic = false)271      : FieldTypeInfo(TI, Name), Access(Access), IsStatic(IsStatic) {}272 273  bool operator==(const MemberTypeInfo &Other) const {274    return std::tie(Type, Name, Access, IsStatic, Description) ==275           std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic,276                    Other.Description);277  }278 279  // Access level associated with this info (public, protected, private, none).280  // AS_public is set as default because the bitcode writer requires the enum281  // with value 0 to be used as the default.282  // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)283  AccessSpecifier Access = AccessSpecifier::AS_public;284 285  std::vector<CommentInfo> Description; // Comment description of this field.286  bool IsStatic = false;287};288 289struct Location {290  Location(int StartLineNumber = 0, int EndLineNumber = 0,291           StringRef Filename = StringRef(), bool IsFileInRootDir = false)292      : StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber),293        Filename(Filename), IsFileInRootDir(IsFileInRootDir) {}294 295  bool operator==(const Location &Other) const {296    return std::tie(StartLineNumber, EndLineNumber, Filename) ==297           std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename);298  }299 300  bool operator!=(const Location &Other) const { return !(*this == Other); }301 302  // This operator is used to sort a vector of Locations.303  // No specific order (attributes more important than others) is required. Any304  // sort is enough, the order is only needed to call std::unique after sorting305  // the vector.306  bool operator<(const Location &Other) const {307    return std::tie(StartLineNumber, EndLineNumber, Filename) <308           std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename);309  }310 311  int StartLineNumber = 0; // Line number of this Location.312  int EndLineNumber = 0;313  SmallString<32> Filename;     // File for this Location.314  bool IsFileInRootDir = false; // Indicates if file is inside root directory315};316 317/// A base struct for Infos.318struct Info {319  Info(InfoType IT = InfoType::IT_default, SymbolID USR = SymbolID(),320       StringRef Name = StringRef(), StringRef Path = StringRef())321      : USR(USR), IT(IT), Name(Name), Path(Path) {}322 323  Info(const Info &Other) = delete;324  Info(Info &&Other) = default;325 326  virtual ~Info() = default;327 328  Info &operator=(Info &&Other) = default;329 330  SymbolID USR =331      SymbolID(); // Unique identifier for the decl described by this Info.332  InfoType IT = InfoType::IT_default; // InfoType of this particular Info.333  SmallString<16> Name;               // Unqualified name of the decl.334  llvm::SmallVector<Reference, 4>335      Namespace; // List of parent namespaces for this decl.336  std::vector<CommentInfo> Description; // Comment description of this decl.337  llvm::SmallString<128> Path;          // Path of directory where the clang-doc338                                        // generated file will be saved339 340  // The name used for the file that this info is documented in.341  // In the JSON generator, infos are documented in files with mangled names.342  // Thus, we keep track of the physical filename for linking purposes.343  SmallString<16> DocumentationFileName;344 345  void mergeBase(Info &&I);346  bool mergeable(const Info &Other);347 348  llvm::SmallString<16> extractName() const;349 350  /// Returns the file path for this Info relative to CurrentPath.351  llvm::SmallString<64> getRelativeFilePath(const StringRef &CurrentPath) const;352 353  /// Returns the basename that should be used for this Info.354  llvm::SmallString<16> getFileBaseName() const;355};356 357// Info for namespaces.358struct NamespaceInfo : public Info {359  NamespaceInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(),360                StringRef Path = StringRef());361 362  void merge(NamespaceInfo &&I);363 364  ScopeChildren Children;365};366 367// Info for symbols.368struct SymbolInfo : public Info {369  SymbolInfo(InfoType IT, SymbolID USR = SymbolID(),370             StringRef Name = StringRef(), StringRef Path = StringRef())371      : Info(IT, USR, Name, Path) {}372 373  void merge(SymbolInfo &&I);374 375  bool operator<(const SymbolInfo &Other) const {376    // Sort by declaration location since we want the doc to be377    // generated in the order of the source code.378    // If the declaration location is the same, or not present379    // we sort by defined location otherwise fallback to the extracted name380    if (Loc.size() > 0 && Other.Loc.size() > 0 && Loc[0] != Other.Loc[0])381      return Loc[0] < Other.Loc[0];382 383    if (DefLoc && Other.DefLoc && *DefLoc != *Other.DefLoc)384      return *DefLoc < *Other.DefLoc;385 386    return extractName() < Other.extractName();387  }388 389  std::optional<Location> DefLoc;     // Location where this decl is defined.390  llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.391  SmallString<16> MangledName;392  bool IsStatic = false;393};394 395struct FriendInfo : SymbolInfo {396  FriendInfo() : SymbolInfo(InfoType::IT_friend) {}397  FriendInfo(SymbolID USR) : SymbolInfo(InfoType::IT_friend, USR) {}398  FriendInfo(const InfoType IT, const SymbolID &USR,399             const StringRef Name = StringRef())400      : SymbolInfo(IT, USR, Name) {}401  bool mergeable(const FriendInfo &Other);402  void merge(FriendInfo &&Other);403 404  Reference Ref;405  std::optional<TemplateInfo> Template;406  std::optional<TypeInfo> ReturnType;407  std::optional<SmallVector<FieldTypeInfo, 4>> Params;408  bool IsClass = false;409};410 411struct VarInfo : SymbolInfo {412  VarInfo() : SymbolInfo(InfoType::IT_variable) {}413  explicit VarInfo(SymbolID USR) : SymbolInfo(InfoType::IT_variable, USR) {}414 415  void merge(VarInfo &&I);416 417  TypeInfo Type;418};419 420// TODO: Expand to allow for documenting templating and default args.421// Info for functions.422struct FunctionInfo : public SymbolInfo {423  FunctionInfo(SymbolID USR = SymbolID())424      : SymbolInfo(InfoType::IT_function, USR) {}425 426  void merge(FunctionInfo &&I);427 428  bool IsMethod = false; // Indicates whether this function is a class method.429  Reference Parent;      // Reference to the parent class decl for this method.430  TypeInfo ReturnType;   // Info about the return type of this function.431  llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters.432  // Access level for this method (public, private, protected, none).433  // AS_public is set as default because the bitcode writer requires the enum434  // with value 0 to be used as the default.435  // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)436  AccessSpecifier Access = AccessSpecifier::AS_public;437 438  // Function Prototype439  SmallString<256> Prototype;440 441  // When present, this function is a template or specialization.442  std::optional<TemplateInfo> Template;443};444 445// TODO: Expand to allow for documenting templating, inheritance access,446// friend classes447// Info for types.448struct RecordInfo : public SymbolInfo {449  RecordInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(),450             StringRef Path = StringRef());451 452  void merge(RecordInfo &&I);453 454  // Type of this record (struct, class, union, interface).455  TagTypeKind TagType = TagTypeKind::Struct;456 457  // When present, this record is a template or specialization.458  std::optional<TemplateInfo> Template;459 460  // Indicates if the record was declared using a typedef. Things like anonymous461  // structs in a typedef:462  //   typedef struct { ... } foo_t;463  // are converted into records with the typedef as the Name + this flag set.464  bool IsTypeDef = false;465 466  llvm::SmallVector<MemberTypeInfo, 4>467      Members;                             // List of info about record members.468  llvm::SmallVector<Reference, 4> Parents; // List of base/parent records469                                           // (does not include virtual470                                           // parents).471  llvm::SmallVector<Reference, 4>472      VirtualParents; // List of virtual base/parent records.473 474  std::vector<BaseRecordInfo>475      Bases; // List of base/parent records; this includes inherited methods and476             // attributes477 478  std::vector<FriendInfo> Friends;479 480  ScopeChildren Children;481};482 483// Info for typedef and using statements.484struct TypedefInfo : public SymbolInfo {485  TypedefInfo(SymbolID USR = SymbolID())486      : SymbolInfo(InfoType::IT_typedef, USR) {}487 488  void merge(TypedefInfo &&I);489 490  TypeInfo Underlying;491 492  // Underlying type declaration493  SmallString<16> TypeDeclaration;494 495  /// Comment description for the typedef.496  std::vector<CommentInfo> Description;497 498  // Indicates if this is a new C++ "using"-style typedef:499  //   using MyVector = std::vector<int>500  // False means it's a C-style typedef:501  //   typedef std::vector<int> MyVector;502  bool IsUsing = false;503};504 505struct BaseRecordInfo : public RecordInfo {506  BaseRecordInfo();507  BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual,508                 AccessSpecifier Access, bool IsParent);509 510  // Indicates if base corresponds to a virtual inheritance511  bool IsVirtual = false;512  // Access level associated with this inherited info (public, protected,513  // private).514  AccessSpecifier Access = AccessSpecifier::AS_public;515  bool IsParent = false; // Indicates if this base is a direct parent516};517 518// Information for a single possible value of an enumeration.519struct EnumValueInfo {520  explicit EnumValueInfo(StringRef Name = StringRef(),521                         StringRef Value = StringRef("0"),522                         StringRef ValueExpr = StringRef())523      : Name(Name), Value(Value), ValueExpr(ValueExpr) {}524 525  bool operator==(const EnumValueInfo &Other) const {526    return std::tie(Name, Value, ValueExpr) ==527           std::tie(Other.Name, Other.Value, Other.ValueExpr);528  }529 530  SmallString<16> Name;531 532  // The computed value of the enumeration constant. This could be the result of533  // evaluating the ValueExpr, or it could be automatically generated according534  // to C rules.535  SmallString<16> Value;536 537  // Stores the user-supplied initialization expression for this enumeration538  // constant. This will be empty for implicit enumeration values.539  SmallString<16> ValueExpr;540 541  /// Comment description of this field.542  std::vector<CommentInfo> Description;543};544 545// TODO: Expand to allow for documenting templating.546// Info for types.547struct EnumInfo : public SymbolInfo {548  EnumInfo() : SymbolInfo(InfoType::IT_enum) {}549  EnumInfo(SymbolID USR) : SymbolInfo(InfoType::IT_enum, USR) {}550 551  void merge(EnumInfo &&I);552 553  // Indicates whether this enum is scoped (e.g. enum class).554  bool Scoped = false;555 556  // Set to nonempty to the type when this is an explicitly typed enum. For557  //   enum Foo : short { ... };558  // this will be "short".559  std::optional<TypeInfo> BaseType;560 561  llvm::SmallVector<EnumValueInfo, 4> Members; // List of enum members.562};563 564struct ConceptInfo : public SymbolInfo {565  ConceptInfo() : SymbolInfo(InfoType::IT_concept) {}566  ConceptInfo(SymbolID USR) : SymbolInfo(InfoType::IT_concept, USR) {}567 568  void merge(ConceptInfo &&I);569 570  bool IsType;571  TemplateInfo Template;572  SmallString<16> ConstraintExpression;573};574 575struct Index : public Reference {576  Index() = default;577  Index(StringRef Name) : Reference(SymbolID(), Name) {}578  Index(StringRef Name, StringRef JumpToSection)579      : Reference(SymbolID(), Name), JumpToSection(JumpToSection) {}580  Index(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)581      : Reference(USR, Name, IT, Name, Path) {}582  // This is used to look for a USR in a vector of Indexes using std::find583  bool operator==(const SymbolID &Other) const { return USR == Other; }584  bool operator<(const Index &Other) const;585 586  std::optional<SmallString<16>> JumpToSection;587  std::vector<Index> Children;588 589  void sort();590};591 592// TODO: Add functionality to include separate markdown pages.593 594// A standalone function to call to merge a vector of infos into one.595// This assumes that all infos in the vector are of the same type, and will fail596// if they are different.597llvm::Expected<std::unique_ptr<Info>>598mergeInfos(std::vector<std::unique_ptr<Info>> &Values);599 600struct ClangDocContext {601  ClangDocContext() = default;602  ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,603                  bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,604                  StringRef RepositoryUrl, StringRef RepositoryCodeLinePrefix,605                  StringRef Base, std::vector<std::string> UserStylesheets,606                  bool FTimeTrace = false);607  tooling::ExecutionContext *ECtx;608  std::string ProjectName; // Name of project clang-doc is documenting.609  bool PublicOnly; // Indicates if only public declarations are documented.610  bool FTimeTrace; // Indicates if ftime trace is turned on611  int Granularity; // Granularity of ftime trace612  std::string OutDirectory; // Directory for outputting generated files.613  std::string SourceRoot;   // Directory where processed files are stored. Links614                            // to definition locations will only be generated if615                            // the file is in this dir.616  // URL of repository that hosts code used for links to definition locations.617  std::optional<std::string> RepositoryUrl;618  // Prefix of line code for repository.619  std::optional<std::string> RepositoryLinePrefix;620  // Path of CSS stylesheets that will be copied to OutDirectory and used to621  // style all HTML files.622  std::vector<std::string> UserStylesheets;623  // JavaScript files that will be imported in all HTML files.624  std::vector<std::string> JsScripts;625  // Base directory for remote repositories.626  StringRef Base;627  // Maps mustache template types to specific mustache template files.628  // Ex.    comment-template -> /path/to/comment-template.mustache629  llvm::StringMap<std::string> MustacheTemplates;630  Index Idx;631};632 633} // namespace doc634} // namespace clang635 636#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H637