clang-tools  9.0.0
Representation.h
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the internal representations of different declaration
10 // types for the clang-doc tool.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
15 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
16 
17 #include "clang/AST/Type.h"
18 #include "clang/Basic/Specifiers.h"
19 #include "clang/Tooling/StandaloneExecution.h"
20 #include "llvm/ADT/Optional.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include <array>
24 #include <string>
25 
26 namespace clang {
27 namespace doc {
28 
29 // SHA1'd hash of a USR.
30 using SymbolID = std::array<uint8_t, 20>;
31 
32 struct Info;
33 struct FunctionInfo;
34 struct EnumInfo;
35 
36 enum class InfoType {
37  IT_default,
39  IT_record,
41  IT_enum
42 };
43 
44 // A representation of a parsed comment.
45 struct CommentInfo {
46  CommentInfo() = default;
47  CommentInfo(CommentInfo &Other) = delete;
48  CommentInfo(CommentInfo &&Other) = default;
49  CommentInfo &operator=(CommentInfo &&Other) = default;
50 
51  bool operator==(const CommentInfo &Other) const {
52  auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
53  SelfClosing, Explicit, AttrKeys, AttrValues, Args);
54  auto SecondCI =
55  std::tie(Other.Kind, Other.Text, Other.Name, Other.Direction,
56  Other.ParamName, Other.CloseName, Other.SelfClosing,
57  Other.Explicit, Other.AttrKeys, Other.AttrValues, Other.Args);
58 
59  if (FirstCI != SecondCI || Children.size() != Other.Children.size())
60  return false;
61 
62  return std::equal(Children.begin(), Children.end(), Other.Children.begin(),
63  llvm::deref<llvm::equal>{});
64  }
65 
66  // This operator is used to sort a vector of CommentInfos.
67  // No specific order (attributes more important than others) is required. Any
68  // sort is enough, the order is only needed to call std::unique after sorting
69  // the vector.
70  bool operator<(const CommentInfo &Other) const {
71  auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
72  SelfClosing, Explicit, AttrKeys, AttrValues, Args);
73  auto SecondCI =
74  std::tie(Other.Kind, Other.Text, Other.Name, Other.Direction,
75  Other.ParamName, Other.CloseName, Other.SelfClosing,
76  Other.Explicit, Other.AttrKeys, Other.AttrValues, Other.Args);
77 
78  if (FirstCI < SecondCI)
79  return true;
80 
81  if (FirstCI == SecondCI) {
82  return std::lexicographical_compare(
83  Children.begin(), Children.end(), Other.Children.begin(),
84  Other.Children.end(), llvm::deref<llvm::less>());
85  }
86 
87  return false;
88  }
89 
90  SmallString<16>
91  Kind; // Kind of comment (FullComment, ParagraphComment, TextComment,
92  // InlineCommandComment, HTMLStartTagComment, HTMLEndTagComment,
93  // BlockCommandComment, ParamCommandComment,
94  // TParamCommandComment, VerbatimBlockComment,
95  // VerbatimBlockLineComment, VerbatimLineComment).
96  SmallString<64> Text; // Text of the comment.
97  SmallString<16> Name; // Name of the comment (for Verbatim and HTML).
98  SmallString<8> Direction; // Parameter direction (for (T)ParamCommand).
99  SmallString<16> ParamName; // Parameter name (for (T)ParamCommand).
100  SmallString<16> CloseName; // Closing tag name (for VerbatimBlock).
101  bool SelfClosing = false; // Indicates if tag is self-closing (for HTML).
102  bool Explicit = false; // Indicates if the direction of a param is explicit
103  // (for (T)ParamCommand).
104  llvm::SmallVector<SmallString<16>, 4>
105  AttrKeys; // List of attribute keys (for HTML).
106  llvm::SmallVector<SmallString<16>, 4>
107  AttrValues; // List of attribute values for each key (for HTML).
108  llvm::SmallVector<SmallString<16>, 4>
109  Args; // List of arguments to commands (for InlineCommand).
110  std::vector<std::unique_ptr<CommentInfo>>
111  Children; // List of child comments for this CommentInfo.
112 };
113 
114 struct Reference {
115  Reference() = default;
116  Reference(llvm::StringRef Name) : Name(Name) {}
117  Reference(llvm::StringRef Name, StringRef Path) : Name(Name), Path(Path) {}
118  Reference(SymbolID USR, StringRef Name, InfoType IT)
119  : USR(USR), Name(Name), RefType(IT) {}
120  Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
121  : USR(USR), Name(Name), RefType(IT), Path(Path) {}
122 
123  bool operator==(const Reference &Other) const {
124  return std::tie(USR, Name, RefType) ==
125  std::tie(Other.USR, Other.Name, Other.RefType);
126  }
127 
128  SymbolID USR = SymbolID(); // Unique identifer for referenced decl
129  SmallString<16> Name; // Name of type (possibly unresolved).
130  InfoType RefType = InfoType::IT_default; // Indicates the type of this
131  // Reference (namespace, record,
132  // function, enum, default).
133  llvm::SmallString<128> Path; // Path of directory where the clang-doc
134  // generated file will be saved
135 };
136 
137 // A base struct for TypeInfos
138 struct TypeInfo {
139  TypeInfo() = default;
140  TypeInfo(SymbolID Type, StringRef Field, InfoType IT)
141  : Type(Type, Field, IT) {}
142  TypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path)
143  : Type(Type, Field, IT, Path) {}
144  TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
145  TypeInfo(llvm::StringRef RefName, StringRef Path) : Type(RefName, Path) {}
146 
147  bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
148 
149  Reference Type; // Referenced type in this info.
150 };
151 
152 // Info for field types.
153 struct FieldTypeInfo : public TypeInfo {
154  FieldTypeInfo() = default;
155  FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
156  llvm::StringRef Name)
157  : TypeInfo(Type, Field, IT, Path), Name(Name) {}
158  FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
159  : TypeInfo(RefName), Name(Name) {}
160  FieldTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name)
161  : TypeInfo(RefName, Path), Name(Name) {}
162 
163  bool operator==(const FieldTypeInfo &Other) const {
164  return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
165  }
166 
167  SmallString<16> Name; // Name associated with this info.
168 };
169 
170 // Info for member types.
171 struct MemberTypeInfo : public FieldTypeInfo {
172  MemberTypeInfo() = default;
173  MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
174  llvm::StringRef Name, AccessSpecifier Access)
175  : FieldTypeInfo(Type, Field, IT, Path, Name), Access(Access) {}
176  MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name,
177  AccessSpecifier Access)
178  : FieldTypeInfo(RefName, Name), Access(Access) {}
179  MemberTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name,
180  AccessSpecifier Access)
181  : FieldTypeInfo(RefName, Path, Name), Access(Access) {}
182 
183  bool operator==(const MemberTypeInfo &Other) const {
184  return std::tie(Type, Name, Access) ==
185  std::tie(Other.Type, Other.Name, Other.Access);
186  }
187 
188  AccessSpecifier Access = AccessSpecifier::AS_none; // Access level associated
189  // with this info (public,
190  // protected, private,
191  // none).
192 };
193 
194 struct Location {
195  Location() = default;
196  Location(int LineNumber, SmallString<16> Filename)
197  : LineNumber(LineNumber), Filename(std::move(Filename)) {}
198 
199  bool operator==(const Location &Other) const {
200  return std::tie(LineNumber, Filename) ==
201  std::tie(Other.LineNumber, Other.Filename);
202  }
203 
204  // This operator is used to sort a vector of Locations.
205  // No specific order (attributes more important than others) is required. Any
206  // sort is enough, the order is only needed to call std::unique after sorting
207  // the vector.
208  bool operator<(const Location &Other) const {
209  return std::tie(LineNumber, Filename) <
210  std::tie(Other.LineNumber, Other.Filename);
211  }
212 
213  int LineNumber; // Line number of this Location.
214  SmallString<32> Filename; // File for this Location.
215 };
216 
217 /// A base struct for Infos.
218 struct Info {
219  Info() = default;
220  Info(InfoType IT) : IT(IT) {}
221  Info(InfoType IT, SymbolID USR) : USR(USR), IT(IT) {}
222  Info(InfoType IT, SymbolID USR, StringRef Name)
223  : USR(USR), IT(IT), Name(Name) {}
224  Info(const Info &Other) = delete;
225  Info(Info &&Other) = default;
226 
227  virtual ~Info() = default;
228 
229  SymbolID USR =
230  SymbolID(); // Unique identifier for the decl described by this Info.
231  const InfoType IT = InfoType::IT_default; // InfoType of this particular Info.
232  SmallString<16> Name; // Unqualified name of the decl.
233  llvm::SmallVector<Reference, 4>
234  Namespace; // List of parent namespaces for this decl.
235  std::vector<CommentInfo> Description; // Comment description of this decl.
236  llvm::SmallString<128> Path; // Path of directory where the clang-doc
237  // generated file will be saved
238 
239  void mergeBase(Info &&I);
240  bool mergeable(const Info &Other);
241 
242  llvm::SmallString<16> extractName();
243 
244  // Returns a reference to the parent scope (that is, the immediate parent
245  // namespace or class in which this decl resides).
246  llvm::Expected<Reference> getEnclosingScope();
247 };
248 
249 // Info for namespaces.
250 struct NamespaceInfo : public Info {
253  NamespaceInfo(SymbolID USR, StringRef Name)
254  : Info(InfoType::IT_namespace, USR, Name) {}
255 
256  void merge(NamespaceInfo &&I);
257 
258  // Namespaces and Records are references because they will be properly
259  // documented in their own info, while the entirety of Functions and Enums are
260  // included here because they should not have separate documentation from
261  // their scope.
262  std::vector<Reference> ChildNamespaces;
263  std::vector<Reference> ChildRecords;
264  std::vector<FunctionInfo> ChildFunctions;
265  std::vector<EnumInfo> ChildEnums;
266 };
267 
268 // Info for symbols.
269 struct SymbolInfo : public Info {
270  SymbolInfo(InfoType IT) : Info(IT) {}
271  SymbolInfo(InfoType IT, SymbolID USR) : Info(IT, USR) {}
272  SymbolInfo(InfoType IT, SymbolID USR, StringRef Name) : Info(IT, USR, Name) {}
273 
274  void merge(SymbolInfo &&I);
275 
276  llvm::Optional<Location> DefLoc; // Location where this decl is defined.
277  llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
278 };
279 
280 // TODO: Expand to allow for documenting templating and default args.
281 // Info for functions.
282 struct FunctionInfo : public SymbolInfo {
285 
286  void merge(FunctionInfo &&I);
287 
288  bool IsMethod = false; // Indicates whether this function is a class method.
289  Reference Parent; // Reference to the parent class decl for this method.
290  TypeInfo ReturnType; // Info about the return type of this function.
291  llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters.
292  // Access level for this method (public, private, protected, none).
293  AccessSpecifier Access = AccessSpecifier::AS_none;
294 };
295 
296 // TODO: Expand to allow for documenting templating, inheritance access,
297 // friend classes
298 // Info for types.
299 struct RecordInfo : public SymbolInfo {
302  RecordInfo(SymbolID USR, StringRef Name)
303  : SymbolInfo(InfoType::IT_record, USR, Name) {}
304 
305  void merge(RecordInfo &&I);
306 
307  TagTypeKind TagType = TagTypeKind::TTK_Struct; // Type of this record
308  // (struct, class, union,
309  // interface).
310  bool IsTypeDef = false; // Indicates if record was declared using typedef
311  llvm::SmallVector<MemberTypeInfo, 4>
312  Members; // List of info about record members.
313  llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
314  // (does not include virtual
315  // parents).
316  llvm::SmallVector<Reference, 4>
317  VirtualParents; // List of virtual base/parent records.
318 
319  // Records are references because they will be properly
320  // documented in their own info, while the entirety of Functions and Enums are
321  // included here because they should not have separate documentation from
322  // their scope.
323  std::vector<Reference> ChildRecords;
324  std::vector<FunctionInfo> ChildFunctions;
325  std::vector<EnumInfo> ChildEnums;
326 };
327 
328 // TODO: Expand to allow for documenting templating.
329 // Info for types.
330 struct EnumInfo : public SymbolInfo {
331  EnumInfo() : SymbolInfo(InfoType::IT_enum) {}
332  EnumInfo(SymbolID USR) : SymbolInfo(InfoType::IT_enum, USR) {}
333 
334  void merge(EnumInfo &&I);
335 
336  bool Scoped =
337  false; // Indicates whether this enum is scoped (e.g. enum class).
338  llvm::SmallVector<SmallString<16>, 4> Members; // List of enum members.
339 };
340 
341 // TODO: Add functionality to include separate markdown pages.
342 
343 // A standalone function to call to merge a vector of infos into one.
344 // This assumes that all infos in the vector are of the same type, and will fail
345 // if they are different.
346 llvm::Expected<std::unique_ptr<Info>>
347 mergeInfos(std::vector<std::unique_ptr<Info>> &Values);
348 
350  tooling::ExecutionContext *ECtx;
352 };
353 
354 } // namespace doc
355 } // namespace clang
356 
357 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
llvm::SmallVector< Reference, 4 > Namespace
MemberTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name, AccessSpecifier Access)
Info(InfoType IT, SymbolID USR)
std::string Text
SymbolInfo(InfoType IT, SymbolID USR)
SmallString< 16 > Name
llvm::Optional< Location > DefLoc
NamespaceInfo(SymbolID USR, StringRef Name)
Reference(llvm::StringRef Name, StringRef Path)
std::vector< FunctionInfo > ChildFunctions
FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path, llvm::StringRef Name)
llvm::SmallVector< Location, 2 > Loc
bool operator==(const TypeInfo &Other) const
std::vector< FunctionInfo > ChildFunctions
MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path, llvm::StringRef Name, AccessSpecifier Access)
std::vector< EnumInfo > ChildEnums
std::vector< HeaderHandle > Path
bool operator==(const Reference &Other) const
std::vector< Reference > ChildRecords
Reference(llvm::StringRef Name)
bool operator==(const MemberTypeInfo &Other) const
llvm::SmallVector< Reference, 4 > VirtualParents
BindArgumentKind Kind
RecordInfo(SymbolID USR)
MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name, AccessSpecifier Access)
Location(int LineNumber, SmallString< 16 > Filename)
llvm::SmallVector< FieldTypeInfo, 4 > Params
std::string Filename
Filename as a string.
llvm::SmallVector< SmallString< 16 >, 4 > Members
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
SymbolInfo(InfoType IT, SymbolID USR, StringRef Name)
bool operator<(const Location &Other) const
std::vector< CommentInfo > Description
bool SelfClosing
llvm::SmallVector< SmallString< 16 >, 4 > Args
llvm::Expected< std::unique_ptr< Info > > mergeInfos(std::vector< std::unique_ptr< Info >> &Values)
RecordInfo(SymbolID USR, StringRef Name)
SmallString< 16 > Name
static constexpr llvm::StringLiteral Name
FieldTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name)
TypeInfo(llvm::StringRef RefName, StringRef Path)
A base struct for Infos.
llvm::SmallString< 128 > Path
llvm::SmallVector< Reference, 4 > Parents
bool operator<(const CommentInfo &Other) const
Reference(SymbolID USR, StringRef Name, InfoType IT)
std::vector< std::unique_ptr< HTMLNode > > Children
bool operator==(const Location &Other) const
SmallString< 16 > ParamName
tooling::ExecutionContext * ECtx
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
SmallString< 16 > Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
SmallString< 16 > Name
TypeInfo(SymbolID Type, StringRef Field, InfoType IT)
std::vector< Reference > ChildNamespaces
SmallString< 16 > CloseName
std::vector< Reference > ChildRecords
SmallString< 32 > Filename
SmallString< 8 > Direction
std::vector< EnumInfo > ChildEnums
bool operator==(const FieldTypeInfo &Other) const
EnumInfo(SymbolID USR)
llvm::SmallVector< MemberTypeInfo, 4 > Members
SmallString< 16 > Kind
Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
TypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path)
std::vector< std::unique_ptr< CommentInfo > > Children
SmallString< 64 > Text
std::array< uint8_t, 20 > SymbolID
llvm::SmallString< 128 > Path
NodeType Type
Info(InfoType IT, SymbolID USR, StringRef Name)
FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
bool operator==(const CommentInfo &Other) const
TypeInfo(llvm::StringRef RefName)
Info(InfoType IT)