18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/STLFunctionalExtras.h"
20#include "llvm/Support/Casting.h"
21#include "llvm/Support/Compiler.h"
22#include "llvm/Support/Path.h"
23#include "llvm/Support/VersionTuple.h"
36void serializeObject(Object &
Paren, StringRef Key, std::optional<Object> Obj) {
38 Paren[Key] = std::move(*Obj);
43void serializeString(Object &
Paren, StringRef Key,
44 std::optional<std::string> String) {
46 Paren[Key] = std::move(*String);
51void serializeArray(Object &
Paren, StringRef Key, std::optional<Array> Array) {
53 Paren[Key] = std::move(*Array);
72std::optional<Object> serializeSemanticVersion(
const VersionTuple &
V) {
77 Version[
"major"] =
V.getMajor();
78 Version[
"minor"] =
V.getMinor().value_or(0);
79 Version[
"patch"] =
V.getSubminor().value_or(0);
87Object serializeOperatingSystem(
const Triple &T) {
89 OS[
"name"] = T.getOSTypeName(T.getOS());
90 serializeObject(OS,
"minimumVersion",
91 serializeSemanticVersion(T.getMinimumSupportedOSVersion()));
99Object serializePlatform(
const Triple &T) {
101 Platform[
"architecture"] = T.getArchName();
102 Platform[
"vendor"] = T.getVendorName();
103 Platform[
"operatingSystem"] = serializeOperatingSystem(T);
109 assert(Loc.
isValid() &&
"invalid source position");
112 SourcePosition[
"line"] = Loc.
getLine() - 1;
113 SourcePosition[
"character"] = Loc.
getColumn() - 1;
115 return SourcePosition;
124 bool IncludeFileURI =
false) {
126 serializeObject(
SourceLocation,
"position", serializeSourcePosition(Loc));
128 if (IncludeFileURI) {
129 std::string FileURI =
"file://";
131 FileURI += sys::path::convert_to_slash(Loc.
getFilename());
142 serializeObject(
SourceRange,
"start", serializeSourcePosition(BeginLoc));
143 serializeObject(
SourceRange,
"end", serializeSourcePosition(EndLoc));
163 Array AvailabilityArray;
166 Object UnconditionallyDeprecated;
167 UnconditionallyDeprecated[
"domain"] =
"*";
168 UnconditionallyDeprecated[
"isUnconditionallyDeprecated"] =
true;
169 AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
174 for (
const auto &AvailInfo : Availabilities) {
176 Availability[
"domain"] = AvailInfo.Domain;
177 if (AvailInfo.Unavailable)
178 Availability[
"isUnconditionallyUnavailable"] =
true;
180 serializeObject(Availability,
"introduced",
181 serializeSemanticVersion(AvailInfo.Introduced));
182 serializeObject(Availability,
"deprecated",
183 serializeSemanticVersion(AvailInfo.Deprecated));
184 serializeObject(Availability,
"obsoleted",
185 serializeSemanticVersion(AvailInfo.Obsoleted));
187 AvailabilityArray.emplace_back(std::move(Availability));
190 return AvailabilityArray;
199 return "objective-c";
204 case Language::ObjCXX:
205 case Language::OpenCL:
206 case Language::OpenCLCXX:
208 case Language::RenderScript:
213 case Language::Unknown:
215 case Language::LLVM_IR:
216 llvm_unreachable(
"Unsupported language kind");
219 llvm_unreachable(
"Unhandled language kind");
250std::optional<Object> serializeDocComment(
const DocComment &Comment) {
256 for (
const auto &CommentLine : Comment) {
258 Line[
"text"] = CommentLine.Text;
259 serializeObject(Line,
"range",
260 serializeSourceRange(CommentLine.Begin, CommentLine.End));
261 LinesArray.emplace_back(std::move(Line));
263 serializeArray(
DocComment,
"lines", LinesArray);
310 Fragment[
"spelling"] = F.Spelling;
312 if (!F.PreciseIdentifier.empty())
313 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
314 Fragments.emplace_back(std::move(Fragment));
331 if (
auto *CategoryRecord =
332 dyn_cast_or_null<const ObjCCategoryRecord>(&Record))
334 (CategoryRecord->Interface.Name +
" (" +
Record.Name +
")").str();
336 Names[
"title"] =
Record.Name;
338 serializeArray(Names,
"subHeading",
339 serializeDeclarationFragments(
Record.SubHeading));
342 DeclarationFragments::FragmentKind::Identifier,
344 serializeArray(Names,
"navigator",
345 serializeDeclarationFragments(NavigatorFragments));
351 auto AddLangPrefix = [&
Lang](StringRef S) -> std::string {
358 llvm_unreachable(
"Records should have an explicit kind");
361 Kind[
"identifier"] = AddLangPrefix(
"namespace");
362 Kind[
"displayName"] =
"Namespace";
365 Kind[
"identifier"] = AddLangPrefix(
"func");
366 Kind[
"displayName"] =
"Function";
369 Kind[
"identifier"] = AddLangPrefix(
"func");
370 Kind[
"displayName"] =
"Function Template";
373 Kind[
"identifier"] = AddLangPrefix(
"func");
374 Kind[
"displayName"] =
"Function Template Specialization";
377 Kind[
"identifier"] = AddLangPrefix(
"var");
378 Kind[
"displayName"] =
"Global Variable Template";
381 Kind[
"identifier"] = AddLangPrefix(
"var");
382 Kind[
"displayName"] =
"Global Variable Template Specialization";
385 Kind[
"identifier"] = AddLangPrefix(
"var");
386 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
389 Kind[
"identifier"] = AddLangPrefix(
"var");
390 Kind[
"displayName"] =
"Global Variable";
393 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
394 Kind[
"displayName"] =
"Enumeration Case";
397 Kind[
"identifier"] = AddLangPrefix(
"enum");
398 Kind[
"displayName"] =
"Enumeration";
401 Kind[
"identifier"] = AddLangPrefix(
"property");
402 Kind[
"displayName"] =
"Instance Property";
405 Kind[
"identifier"] = AddLangPrefix(
"struct");
406 Kind[
"displayName"] =
"Structure";
409 Kind[
"identifier"] = AddLangPrefix(
"property");
410 Kind[
"displayName"] =
"Instance Property";
413 Kind[
"identifier"] = AddLangPrefix(
"union");
414 Kind[
"displayName"] =
"Union";
417 Kind[
"identifier"] = AddLangPrefix(
"type.property");
418 Kind[
"displayName"] =
"Type Property";
424 Kind[
"identifier"] = AddLangPrefix(
"class");
425 Kind[
"displayName"] =
"Class";
428 Kind[
"identifier"] = AddLangPrefix(
"method");
429 Kind[
"displayName"] =
"Method Template";
432 Kind[
"identifier"] = AddLangPrefix(
"method");
433 Kind[
"displayName"] =
"Method Template Specialization";
436 Kind[
"identifier"] = AddLangPrefix(
"property");
437 Kind[
"displayName"] =
"Template Property";
440 Kind[
"identifier"] = AddLangPrefix(
"concept");
441 Kind[
"displayName"] =
"Concept";
444 Kind[
"identifier"] = AddLangPrefix(
"type.method");
445 Kind[
"displayName"] =
"Static Method";
448 Kind[
"identifier"] = AddLangPrefix(
"method");
449 Kind[
"displayName"] =
"Instance Method";
452 Kind[
"identifier"] = AddLangPrefix(
"method");
453 Kind[
"displayName"] =
"Constructor";
456 Kind[
"identifier"] = AddLangPrefix(
"method");
457 Kind[
"displayName"] =
"Destructor";
460 Kind[
"identifier"] = AddLangPrefix(
"ivar");
461 Kind[
"displayName"] =
"Instance Variable";
464 Kind[
"identifier"] = AddLangPrefix(
"method");
465 Kind[
"displayName"] =
"Instance Method";
468 Kind[
"identifier"] = AddLangPrefix(
"type.method");
469 Kind[
"displayName"] =
"Type Method";
472 Kind[
"identifier"] = AddLangPrefix(
"property");
473 Kind[
"displayName"] =
"Instance Property";
476 Kind[
"identifier"] = AddLangPrefix(
"type.property");
477 Kind[
"displayName"] =
"Type Property";
480 Kind[
"identifier"] = AddLangPrefix(
"class");
481 Kind[
"displayName"] =
"Class";
484 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
485 Kind[
"displayName"] =
"Class Extension";
488 Kind[
"identifier"] = AddLangPrefix(
"module.extension");
489 Kind[
"displayName"] =
"Module Extension";
492 Kind[
"identifier"] = AddLangPrefix(
"protocol");
493 Kind[
"displayName"] =
"Protocol";
496 Kind[
"identifier"] = AddLangPrefix(
"macro");
497 Kind[
"displayName"] =
"Macro";
500 Kind[
"identifier"] = AddLangPrefix(
"typealias");
501 Kind[
"displayName"] =
"Type Alias";
514 return serializeSymbolKind(
Record.getKind(), Lang);
517template <
typename RecordTy>
519serializeFunctionSignatureMixinImpl(
const RecordTy &Record, std::true_type) {
520 const auto &FS =
Record.Signature;
525 serializeArray(Signature,
"returns",
526 serializeDeclarationFragments(FS.getReturnType()));
529 for (
const auto &
P : FS.getParameters()) {
532 serializeArray(
Parameter,
"declarationFragments",
533 serializeDeclarationFragments(
P.Fragments));
538 Signature[
"parameters"] = std::move(Parameters);
543template <
typename RecordTy>
545serializeFunctionSignatureMixinImpl(
const RecordTy &Record, std::false_type) {
559template <
typename RecordTy>
560void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &Record) {
561 serializeObject(
Paren,
"functionSignature",
562 serializeFunctionSignatureMixinImpl(
566template <
typename RecordTy>
567std::optional<std::string> serializeAccessMixinImpl(
const RecordTy &Record,
577template <
typename RecordTy>
578std::optional<std::string> serializeAccessMixinImpl(
const RecordTy &Record,
583template <
typename RecordTy>
584void serializeAccessMixin(Object &
Paren,
const RecordTy &Record) {
586 if (!accessLevel.has_value())
587 accessLevel =
"public";
588 serializeString(
Paren,
"accessLevel", accessLevel);
591template <
typename RecordTy>
592std::optional<Object> serializeTemplateMixinImpl(
const RecordTy &Record,
599 Array GenericParameters;
605 GenericParameters.emplace_back(std::move(
Parameter));
607 if (!GenericParameters.empty())
608 Generics[
"parameters"] = std::move(GenericParameters);
610 Array GenericConstraints;
613 Constraint[
"kind"] = Constr.Kind;
614 Constraint[
"lhs"] = Constr.LHS;
615 Constraint[
"rhs"] = Constr.RHS;
616 GenericConstraints.emplace_back(std::move(Constraint));
619 if (!GenericConstraints.empty())
620 Generics[
"constraints"] = std::move(GenericConstraints);
625template <
typename RecordTy>
626std::optional<Object> serializeTemplateMixinImpl(
const RecordTy &Record,
631template <
typename RecordTy>
632void serializeTemplateMixin(Object &
Paren,
const RecordTy &Record) {
633 serializeObject(
Paren,
"swiftGenerics",
637struct PathComponent {
643 : USR(USR), Name(Name),
Kind(
Kind) {}
646template <
typename RecordTy>
647bool generatePathComponents(
648 const RecordTy &Record,
const APISet &API,
649 function_ref<
void(
const PathComponent &)> ComponentTransformer) {
652 const auto *CurrentParent = &
Record.ParentInformation;
653 bool FailedToFindParent =
false;
654 while (CurrentParent && !CurrentParent->empty()) {
655 PathComponent CurrentParentComponent(CurrentParent->ParentUSR,
656 CurrentParent->ParentName,
657 CurrentParent->ParentKind);
659 auto *ParentRecord = CurrentParent->ParentRecord;
666 if (
auto *CategoryRecord =
667 dyn_cast_or_null<ObjCCategoryRecord>(ParentRecord)) {
668 if (!CategoryRecord->IsFromExternalModule) {
670 CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR,
671 CategoryRecord->Interface.Name,
679 FailedToFindParent =
true;
683 ReverseComponenents.push_back(std::move(CurrentParentComponent));
684 CurrentParent = &ParentRecord->ParentInformation;
687 for (
const auto &PC : reverse(ReverseComponenents))
688 ComponentTransformer(PC);
690 return FailedToFindParent;
693Object serializeParentContext(
const PathComponent &PC,
Language Lang) {
695 ParentContextElem[
"usr"] = PC.USR;
696 ParentContextElem[
"name"] = PC.Name;
697 ParentContextElem[
"kind"] = serializeSymbolKind(PC.Kind, Lang)[
"identifier"];
698 return ParentContextElem;
701template <
typename RecordTy>
702Array generateParentContexts(
const RecordTy &Record,
const APISet &API,
704 Array ParentContexts;
705 generatePathComponents(
706 Record, API, [Lang, &ParentContexts](
const PathComponent &PC) {
707 ParentContexts.push_back(serializeParentContext(PC, Lang));
710 return ParentContexts;
715const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
717Object SymbolGraphSerializer::serializeMetadata()
const {
719 serializeObject(Metadata,
"formatVersion",
720 serializeSemanticVersion(FormatVersion));
725Object SymbolGraphSerializer::serializeModule()
const {
734bool SymbolGraphSerializer::shouldSkip(
const APIRecord &Record)
const {
740 if (
Record.Availabilities.isUnconditionallyUnavailable())
745 if (
Record.Name.startswith(
"_"))
751template <
typename RecordTy>
753SymbolGraphSerializer::serializeAPIRecord(
const RecordTy &Record)
const {
754 if (shouldSkip(Record))
758 serializeObject(Obj,
"identifier",
760 serializeObject(Obj,
"kind", serializeSymbolKind(Record,
API.
getLanguage()));
761 serializeObject(Obj,
"names", serializeNames(Record));
764 serializeSourceLocation(
Record.Location,
true));
765 serializeArray(Obj,
"availability",
766 serializeAvailability(
Record.Availabilities));
767 serializeObject(Obj,
"docComment", serializeDocComment(
Record.Comment));
768 serializeArray(Obj,
"declarationFragments",
769 serializeDeclarationFragments(
Record.Declaration));
773 if (generatePathComponents(Record,
API,
774 [&PathComponentsNames](
const PathComponent &PC) {
775 PathComponentsNames.push_back(PC.Name);
779 serializeArray(Obj,
"pathComponents", Array(PathComponentsNames));
781 serializeFunctionSignatureMixin(Obj, Record);
782 serializeAccessMixin(Obj, Record);
783 serializeTemplateMixin(Obj, Record);
788template <
typename MemberTy>
789void SymbolGraphSerializer::serializeMembers(
791 const SmallVector<std::unique_ptr<MemberTy>> &Members) {
795 for (
const auto &
Member : Members) {
796 auto MemberRecord = serializeAPIRecord(*
Member);
800 Symbols.emplace_back(std::move(*MemberRecord));
810 return "inheritsFrom";
814 return "extensionTo";
816 llvm_unreachable(
"Unhandled relationship kind");
822 return "conformance";
824 return "conditionalConformance";
826 llvm_unreachable(
"Unhandled constraint kind");
829void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
833 Relationship[
"source"] = Source.
USR;
834 Relationship[
"target"] =
Target.USR;
835 Relationship[
"targetFallback"] =
Target.Name;
838 Relationships.emplace_back(std::move(Relationship));
843 auto Namespace = serializeAPIRecord(Record);
846 Symbols.emplace_back(std::move(*Namespace));
847 if (!Record.ParentInformation.empty())
849 Record.ParentInformation.ParentRecord);
854 auto Obj = serializeAPIRecord(Record);
858 Symbols.emplace_back(std::move(*Obj));
863 auto Obj = serializeAPIRecord(Record);
867 Symbols.emplace_back(std::move(*Obj));
871 auto Enum = serializeAPIRecord(Record);
875 Symbols.emplace_back(std::move(*
Enum));
876 serializeMembers(Record, Record.Constants);
880 auto Struct = serializeAPIRecord(Record);
884 Symbols.emplace_back(std::move(*
Struct));
885 serializeMembers(Record, Record.Fields);
890 auto StaticField = serializeAPIRecord(Record);
893 Symbols.emplace_back(std::move(*StaticField));
898 auto Class = serializeAPIRecord(Record);
902 Symbols.emplace_back(std::move(*
Class));
903 for (
const auto &
Base : Record.Bases)
905 if (!Record.ParentInformation.empty())
907 Record.ParentInformation.ParentRecord);
912 auto Class = serializeAPIRecord(Record);
916 Symbols.emplace_back(std::move(*
Class));
917 for (
const auto &
Base : Record.Bases)
919 if (!Record.ParentInformation.empty())
921 Record.ParentInformation.ParentRecord);
926 auto Class = serializeAPIRecord(Record);
930 Symbols.emplace_back(std::move(*
Class));
932 for (
const auto &
Base : Record.Bases)
934 if (!Record.ParentInformation.empty())
936 Record.ParentInformation.ParentRecord);
941 auto Class = serializeAPIRecord(Record);
945 Symbols.emplace_back(std::move(*
Class));
947 for (
const auto &
Base : Record.Bases)
949 if (!Record.ParentInformation.empty())
951 Record.ParentInformation.ParentRecord);
956 auto InstanceMethod = serializeAPIRecord(Record);
960 Symbols.emplace_back(std::move(*InstanceMethod));
962 Record.ParentInformation.ParentRecord);
967 auto StaticMethod = serializeAPIRecord(Record);
971 Symbols.emplace_back(std::move(*StaticMethod));
973 Record.ParentInformation.ParentRecord);
981 auto MethodTemplate = serializeAPIRecord(Record);
984 Symbols.emplace_back(std::move(*MethodTemplate));
986 Record.ParentInformation.ParentRecord);
994 auto MethodTemplateSpecialization = serializeAPIRecord(Record);
995 if (!MethodTemplateSpecialization)
997 Symbols.emplace_back(std::move(*MethodTemplateSpecialization));
999 Record.ParentInformation.ParentRecord);
1005 auto CXXField = serializeAPIRecord(Record);
1008 Symbols.emplace_back(std::move(*CXXField));
1010 Record.ParentInformation.ParentRecord);
1018 auto CXXFieldTemplate = serializeAPIRecord(Record);
1019 if (!CXXFieldTemplate)
1021 Symbols.emplace_back(std::move(*CXXFieldTemplate));
1023 Record.ParentInformation.ParentRecord);
1027 auto Concept = serializeAPIRecord(Record);
1031 Symbols.emplace_back(std::move(*Concept));
1036 auto GlobalVariableTemplate = serializeAPIRecord(Record);
1037 if (!GlobalVariableTemplate)
1039 Symbols.emplace_back(std::move(*GlobalVariableTemplate));
1044 auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record);
1045 if (!GlobalVariableTemplateSpecialization)
1047 Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization));
1053 auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record);
1054 if (!GlobalVariableTemplatePartialSpecialization)
1056 Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization));
1061 auto GlobalFunctionTemplate = serializeAPIRecord(Record);
1062 if (!GlobalFunctionTemplate)
1064 Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
1069 auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record);
1070 if (!GlobalFunctionTemplateSpecialization)
1072 Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization));
1077 auto ObjCContainer = serializeAPIRecord(Record);
1081 Symbols.emplace_back(std::move(*ObjCContainer));
1083 serializeMembers(Record, Record.Ivars);
1084 serializeMembers(Record, Record.Methods);
1085 serializeMembers(Record, Record.Properties);
1087 for (
const auto &Protocol : Record.Protocols)
1091 if (
auto *ObjCInterface = dyn_cast<ObjCInterfaceRecord>(&Record)) {
1092 if (!ObjCInterface->SuperClass.empty())
1096 ObjCInterface->SuperClass);
1100 for (
const auto *
Category : ObjCInterface->Categories) {
1101 serializeMembers(Record,
Category->Ivars);
1102 serializeMembers(Record,
Category->Methods);
1103 serializeMembers(Record,
Category->Properties);
1106 for (
const auto &Protocol :
Category->Protocols)
1114 if (!Record.IsFromExternalModule)
1121 serializeObject(Obj,
"identifier",
1123 serializeObject(Obj,
"kind",
1126 Obj[
"accessLevel"] =
"public";
1127 Symbols.emplace_back(std::move(Obj));
1130 Object Relationship;
1131 Relationship[
"source"] = Record.USR;
1132 Relationship[
"target"] = Record.Interface.USR;
1133 Relationship[
"targetFallback"] = Record.Interface.Name;
1135 Relationships.emplace_back(std::move(Relationship));
1137 auto ObjCCategory = serializeAPIRecord(Record);
1142 Symbols.emplace_back(std::move(*ObjCCategory));
1143 serializeMembers(Record, Record.Methods);
1144 serializeMembers(Record, Record.Properties);
1147 for (
const auto &Protocol : Record.Protocols)
1153 auto Macro = serializeAPIRecord(Record);
1158 Symbols.emplace_back(std::move(*Macro));
1162 switch (Record->getKind()) {
1164 llvm_unreachable(
"Records should have a known kind!");
1199 if (
auto Obj = serializeAPIRecord(*Record)) {
1200 Symbols.emplace_back(std::move(*Obj));
1201 auto &ParentInformation = Record->ParentInformation;
1202 if (!ParentInformation.empty())
1204 *ParentInformation.ParentRecord);
1213 bool ShouldDrop = Record.UnderlyingType.Name.empty();
1216 ShouldDrop |= (Record.UnderlyingType.Name == Record.Name);
1220 auto Typedef = serializeAPIRecord(Record);
1224 (*Typedef)[
"type"] = Record.UnderlyingType.USR;
1226 Symbols.emplace_back(std::move(*Typedef));
1231 return serializeCurrentGraph();
1234Object SymbolGraphSerializer::serializeCurrentGraph() {
1236 serializeObject(Root,
"metadata", serializeMetadata());
1237 serializeObject(Root,
"module", serializeModule());
1239 Root[
"symbols"] = std::move(Symbols);
1240 Root[
"relationships"] = std::move(Relationships);
1248 os << formatv(
"{0}",
Value(std::move(root))) <<
"\n";
1250 os << formatv(
"{0:2}",
Value(std::move(root))) <<
"\n";
1253std::optional<Object>
1266 serializeObject(Root,
"symbolGraph", Serializer.serializeCurrentGraph());
1269 serializeArray(Root,
"parentContexts",
1270 generateParentContexts(*Record,
API, Lang));
1272 Array RelatedSymbols;
1274 for (
const auto &Fragment : Record->Declaration.getFragments()) {
1276 if (Fragment.PreciseIdentifier.empty())
1285 Object RelatedSymbol;
1286 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1287 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1289 RelatedSymbol[
"accessLevel"] =
"public";
1294 serializeArray(RelatedSymbol,
"parentContexts",
1295 generateParentContexts(*RelatedRecord,
API, Lang));
1296 RelatedSymbols.push_back(std::move(RelatedSymbol));
1299 serializeArray(Root,
"relatedSymbols", RelatedSymbols);
This file defines the Declaration Fragments related classes.
Defines the clang::SourceLocation class and associated facilities.
This file defines the SymbolGraphSerializer class.
Defines version macros and version-related utility functions for Clang.
Describes a module or submodule.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Language
The language for the input, used to select and validate the language standard and possible actions.
@ Parameter
The parameter type of a method or function.
@ Struct
The "struct" keyword introduces the elaborated-type-specifier.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ Enum
The "enum" keyword introduces the elaborated-type-specifier.
std::string getClangFullVersion()
Retrieves a string representing the complete clang version, which includes the clang version number,...
YAML serialization mapping.