1d0f9a872SJulie Hockett ///===-- Representation.cpp - ClangDoc Representation -----------*- C++ -*-===// 2d0f9a872SJulie Hockett // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d0f9a872SJulie Hockett // 7d0f9a872SJulie Hockett //===----------------------------------------------------------------------===// 8d0f9a872SJulie Hockett // 9d0f9a872SJulie Hockett // This file defines the merging of different types of infos. The data in the 10d0f9a872SJulie Hockett // calling Info is preserved during a merge unless that field is empty or 11d0f9a872SJulie Hockett // default. In that case, the data from the parameter Info is used to replace 12d0f9a872SJulie Hockett // the empty or default data. 13d0f9a872SJulie Hockett // 14d0f9a872SJulie Hockett // For most fields, the first decl seen provides the data. Exceptions to this 15d0f9a872SJulie Hockett // include the location and description fields, which are collections of data on 16d0f9a872SJulie Hockett // all decls related to a given definition. All other fields are ignored in new 17d0f9a872SJulie Hockett // decls unless the first seen decl didn't, for whatever reason, incorporate 18d0f9a872SJulie Hockett // data on that field (e.g. a forward declared class wouldn't have information 19d0f9a872SJulie Hockett // on members on the forward declaration, but would have the class name). 20d0f9a872SJulie Hockett // 21d0f9a872SJulie Hockett //===----------------------------------------------------------------------===// 22d0f9a872SJulie Hockett #include "Representation.h" 23d0f9a872SJulie Hockett #include "llvm/Support/Error.h" 24d900ef0aSJulie Hockett #include "llvm/Support/Path.h" 25d0f9a872SJulie Hockett 26d0f9a872SJulie Hockett namespace clang { 27d0f9a872SJulie Hockett namespace doc { 28d0f9a872SJulie Hockett 298899c29bSJulie Hockett namespace { 308899c29bSJulie Hockett 318899c29bSJulie Hockett const SymbolID EmptySID = SymbolID(); 32d0f9a872SJulie Hockett 33d0f9a872SJulie Hockett template <typename T> 348899c29bSJulie Hockett llvm::Expected<std::unique_ptr<Info>> 358899c29bSJulie Hockett reduce(std::vector<std::unique_ptr<Info>> &Values) { 3630360d88SPaul Kirth if (Values.empty() || !Values[0]) 3718038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 3818038065SFangrui Song "no value to reduce"); 391c705d9cSJonas Devlieghere std::unique_ptr<Info> Merged = std::make_unique<T>(Values[0]->USR); 40d0f9a872SJulie Hockett T *Tmp = static_cast<T *>(Merged.get()); 41d0f9a872SJulie Hockett for (auto &I : Values) 42d0f9a872SJulie Hockett Tmp->merge(std::move(*static_cast<T *>(I.get()))); 438899c29bSJulie Hockett return std::move(Merged); 44d0f9a872SJulie Hockett } 45d0f9a872SJulie Hockett 468899c29bSJulie Hockett // Return the index of the matching child in the vector, or -1 if merge is not 478899c29bSJulie Hockett // necessary. 488899c29bSJulie Hockett template <typename T> 498899c29bSJulie Hockett int getChildIndexIfExists(std::vector<T> &Children, T &ChildToMerge) { 508899c29bSJulie Hockett for (unsigned long I = 0; I < Children.size(); I++) { 518899c29bSJulie Hockett if (ChildToMerge.USR == Children[I].USR) 528899c29bSJulie Hockett return I; 538899c29bSJulie Hockett } 548899c29bSJulie Hockett return -1; 558899c29bSJulie Hockett } 568899c29bSJulie Hockett 579470de65SPaul Kirth template <typename T> 589470de65SPaul Kirth void reduceChildren(std::vector<T> &Children, 599470de65SPaul Kirth std::vector<T> &&ChildrenToMerge) { 608899c29bSJulie Hockett for (auto &ChildToMerge : ChildrenToMerge) { 619470de65SPaul Kirth int MergeIdx = getChildIndexIfExists(Children, ChildToMerge); 629470de65SPaul Kirth if (MergeIdx == -1) { 638899c29bSJulie Hockett Children.push_back(std::move(ChildToMerge)); 64e27f778aSDiego Astiazaran continue; 65e27f778aSDiego Astiazaran } 669470de65SPaul Kirth Children[MergeIdx].merge(std::move(ChildToMerge)); 6721fb70c6SBrett Wilson } 6821fb70c6SBrett Wilson } 6921fb70c6SBrett Wilson 708899c29bSJulie Hockett } // namespace 718899c29bSJulie Hockett 72d0f9a872SJulie Hockett // Dispatch function. 73d0f9a872SJulie Hockett llvm::Expected<std::unique_ptr<Info>> 74d0f9a872SJulie Hockett mergeInfos(std::vector<std::unique_ptr<Info>> &Values) { 7530360d88SPaul Kirth if (Values.empty() || !Values[0]) 7618038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 7718038065SFangrui Song "no info values to merge"); 78d0f9a872SJulie Hockett 79d0f9a872SJulie Hockett switch (Values[0]->IT) { 80d0f9a872SJulie Hockett case InfoType::IT_namespace: 81d0f9a872SJulie Hockett return reduce<NamespaceInfo>(Values); 82d0f9a872SJulie Hockett case InfoType::IT_record: 83d0f9a872SJulie Hockett return reduce<RecordInfo>(Values); 84d0f9a872SJulie Hockett case InfoType::IT_enum: 85d0f9a872SJulie Hockett return reduce<EnumInfo>(Values); 86d0f9a872SJulie Hockett case InfoType::IT_function: 87d0f9a872SJulie Hockett return reduce<FunctionInfo>(Values); 8821fb70c6SBrett Wilson case InfoType::IT_typedef: 8921fb70c6SBrett Wilson return reduce<TypedefInfo>(Values); 90d0f9a872SJulie Hockett default: 9118038065SFangrui Song return llvm::createStringError(llvm::inconvertibleErrorCode(), 9218038065SFangrui Song "unexpected info type"); 93d0f9a872SJulie Hockett } 94d0f9a872SJulie Hockett } 95d0f9a872SJulie Hockett 96f88c6b91SJens Massberg bool CommentInfo::operator==(const CommentInfo &Other) const { 97f88c6b91SJens Massberg auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName, 98f88c6b91SJens Massberg SelfClosing, Explicit, AttrKeys, AttrValues, Args); 99f88c6b91SJens Massberg auto SecondCI = 100f88c6b91SJens Massberg std::tie(Other.Kind, Other.Text, Other.Name, Other.Direction, 101f88c6b91SJens Massberg Other.ParamName, Other.CloseName, Other.SelfClosing, 102f88c6b91SJens Massberg Other.Explicit, Other.AttrKeys, Other.AttrValues, Other.Args); 103f88c6b91SJens Massberg 104f88c6b91SJens Massberg if (FirstCI != SecondCI || Children.size() != Other.Children.size()) 105f88c6b91SJens Massberg return false; 106f88c6b91SJens Massberg 107f88c6b91SJens Massberg return std::equal(Children.begin(), Children.end(), Other.Children.begin(), 108f88c6b91SJens Massberg llvm::deref<std::equal_to<>>{}); 109f88c6b91SJens Massberg } 110f88c6b91SJens Massberg 111f88c6b91SJens Massberg bool CommentInfo::operator<(const CommentInfo &Other) const { 112f88c6b91SJens Massberg auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName, 113f88c6b91SJens Massberg SelfClosing, Explicit, AttrKeys, AttrValues, Args); 114f88c6b91SJens Massberg auto SecondCI = 115f88c6b91SJens Massberg std::tie(Other.Kind, Other.Text, Other.Name, Other.Direction, 116f88c6b91SJens Massberg Other.ParamName, Other.CloseName, Other.SelfClosing, 117f88c6b91SJens Massberg Other.Explicit, Other.AttrKeys, Other.AttrValues, Other.Args); 118f88c6b91SJens Massberg 119f88c6b91SJens Massberg if (FirstCI < SecondCI) 120f88c6b91SJens Massberg return true; 121f88c6b91SJens Massberg 122f88c6b91SJens Massberg if (FirstCI == SecondCI) { 123f88c6b91SJens Massberg return std::lexicographical_compare( 124f88c6b91SJens Massberg Children.begin(), Children.end(), Other.Children.begin(), 125f88c6b91SJens Massberg Other.Children.end(), llvm::deref<std::less<>>()); 126f88c6b91SJens Massberg } 127f88c6b91SJens Massberg 128f88c6b91SJens Massberg return false; 129f88c6b91SJens Massberg } 130f88c6b91SJens Massberg 1317003f64cSPetr Hosek static llvm::SmallString<64> 1327003f64cSPetr Hosek calculateRelativeFilePath(const InfoType &Type, const StringRef &Path, 1337003f64cSPetr Hosek const StringRef &Name, const StringRef &CurrentPath) { 1347003f64cSPetr Hosek llvm::SmallString<64> FilePath; 1357003f64cSPetr Hosek 1367003f64cSPetr Hosek if (CurrentPath != Path) { 1377003f64cSPetr Hosek // iterate back to the top 1387003f64cSPetr Hosek for (llvm::sys::path::const_iterator I = 1397003f64cSPetr Hosek llvm::sys::path::begin(CurrentPath); 1407003f64cSPetr Hosek I != llvm::sys::path::end(CurrentPath); ++I) 1417003f64cSPetr Hosek llvm::sys::path::append(FilePath, ".."); 1427003f64cSPetr Hosek llvm::sys::path::append(FilePath, Path); 1437003f64cSPetr Hosek } 1447003f64cSPetr Hosek 1457003f64cSPetr Hosek // Namespace references have a Path to the parent namespace, but 1467003f64cSPetr Hosek // the file is actually in the subdirectory for the namespace. 1477003f64cSPetr Hosek if (Type == doc::InfoType::IT_namespace) 1487003f64cSPetr Hosek llvm::sys::path::append(FilePath, Name); 1497003f64cSPetr Hosek 1507003f64cSPetr Hosek return llvm::sys::path::relative_path(FilePath); 1517003f64cSPetr Hosek } 1527003f64cSPetr Hosek 1537003f64cSPetr Hosek llvm::SmallString<64> 1547003f64cSPetr Hosek Reference::getRelativeFilePath(const StringRef &CurrentPath) const { 1557003f64cSPetr Hosek return calculateRelativeFilePath(RefType, Path, Name, CurrentPath); 1567003f64cSPetr Hosek } 1577003f64cSPetr Hosek 1587003f64cSPetr Hosek llvm::SmallString<16> Reference::getFileBaseName() const { 1597003f64cSPetr Hosek if (RefType == InfoType::IT_namespace) 1607003f64cSPetr Hosek return llvm::SmallString<16>("index"); 1617003f64cSPetr Hosek 1627003f64cSPetr Hosek return Name; 1637003f64cSPetr Hosek } 1647003f64cSPetr Hosek 1657003f64cSPetr Hosek llvm::SmallString<64> 1667003f64cSPetr Hosek Info::getRelativeFilePath(const StringRef &CurrentPath) const { 1677003f64cSPetr Hosek return calculateRelativeFilePath(IT, Path, extractName(), CurrentPath); 1687003f64cSPetr Hosek } 1697003f64cSPetr Hosek 1707003f64cSPetr Hosek llvm::SmallString<16> Info::getFileBaseName() const { 1717003f64cSPetr Hosek if (IT == InfoType::IT_namespace) 1727003f64cSPetr Hosek return llvm::SmallString<16>("index"); 1737003f64cSPetr Hosek 1747003f64cSPetr Hosek return extractName(); 1757003f64cSPetr Hosek } 1767003f64cSPetr Hosek 177e27f778aSDiego Astiazaran bool Reference::mergeable(const Reference &Other) { 178e27f778aSDiego Astiazaran return RefType == Other.RefType && USR == Other.USR; 179e27f778aSDiego Astiazaran } 180e27f778aSDiego Astiazaran 181e27f778aSDiego Astiazaran void Reference::merge(Reference &&Other) { 182e27f778aSDiego Astiazaran assert(mergeable(Other)); 183e27f778aSDiego Astiazaran if (Name.empty()) 184e27f778aSDiego Astiazaran Name = Other.Name; 185e27f778aSDiego Astiazaran if (Path.empty()) 186e27f778aSDiego Astiazaran Path = Other.Path; 187e27f778aSDiego Astiazaran } 188e27f778aSDiego Astiazaran 189d0f9a872SJulie Hockett void Info::mergeBase(Info &&Other) { 190d0f9a872SJulie Hockett assert(mergeable(Other)); 191d0f9a872SJulie Hockett if (USR == EmptySID) 192d0f9a872SJulie Hockett USR = Other.USR; 193d0f9a872SJulie Hockett if (Name == "") 194d0f9a872SJulie Hockett Name = Other.Name; 1952c1c9a24SJulie Hockett if (Path == "") 1962c1c9a24SJulie Hockett Path = Other.Path; 197d0f9a872SJulie Hockett if (Namespace.empty()) 198d0f9a872SJulie Hockett Namespace = std::move(Other.Namespace); 199d0f9a872SJulie Hockett // Unconditionally extend the description, since each decl may have a comment. 200d0f9a872SJulie Hockett std::move(Other.Description.begin(), Other.Description.end(), 201d0f9a872SJulie Hockett std::back_inserter(Description)); 2024065e921SBenjamin Kramer llvm::sort(Description); 20393a290fdSJulie Hockett auto Last = std::unique(Description.begin(), Description.end()); 20493a290fdSJulie Hockett Description.erase(Last, Description.end()); 205d0f9a872SJulie Hockett } 206d0f9a872SJulie Hockett 207d0f9a872SJulie Hockett bool Info::mergeable(const Info &Other) { 2088899c29bSJulie Hockett return IT == Other.IT && USR == Other.USR; 209d0f9a872SJulie Hockett } 210d0f9a872SJulie Hockett 211d0f9a872SJulie Hockett void SymbolInfo::merge(SymbolInfo &&Other) { 212d0f9a872SJulie Hockett assert(mergeable(Other)); 213d0f9a872SJulie Hockett if (!DefLoc) 214d0f9a872SJulie Hockett DefLoc = std::move(Other.DefLoc); 215d0f9a872SJulie Hockett // Unconditionally extend the list of locations, since we want all of them. 216d0f9a872SJulie Hockett std::move(Other.Loc.begin(), Other.Loc.end(), std::back_inserter(Loc)); 2174065e921SBenjamin Kramer llvm::sort(Loc); 21893a290fdSJulie Hockett auto Last = std::unique(Loc.begin(), Loc.end()); 21993a290fdSJulie Hockett Loc.erase(Last, Loc.end()); 220d0f9a872SJulie Hockett mergeBase(std::move(Other)); 221d0f9a872SJulie Hockett } 222d0f9a872SJulie Hockett 223f88c6b91SJens Massberg NamespaceInfo::NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path) 224f88c6b91SJens Massberg : Info(InfoType::IT_namespace, USR, Name, Path) {} 225f88c6b91SJens Massberg 226d0f9a872SJulie Hockett void NamespaceInfo::merge(NamespaceInfo &&Other) { 227d0f9a872SJulie Hockett assert(mergeable(Other)); 2288899c29bSJulie Hockett // Reduce children if necessary. 22921fb70c6SBrett Wilson reduceChildren(Children.Namespaces, std::move(Other.Children.Namespaces)); 23021fb70c6SBrett Wilson reduceChildren(Children.Records, std::move(Other.Children.Records)); 23121fb70c6SBrett Wilson reduceChildren(Children.Functions, std::move(Other.Children.Functions)); 23221fb70c6SBrett Wilson reduceChildren(Children.Enums, std::move(Other.Children.Enums)); 23321fb70c6SBrett Wilson reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs)); 234d0f9a872SJulie Hockett mergeBase(std::move(Other)); 235d0f9a872SJulie Hockett } 236d0f9a872SJulie Hockett 237f88c6b91SJens Massberg RecordInfo::RecordInfo(SymbolID USR, StringRef Name, StringRef Path) 238f88c6b91SJens Massberg : SymbolInfo(InfoType::IT_record, USR, Name, Path) {} 239f88c6b91SJens Massberg 240d0f9a872SJulie Hockett void RecordInfo::merge(RecordInfo &&Other) { 241d0f9a872SJulie Hockett assert(mergeable(Other)); 242edd690b0SVlad Serebrennikov if (!llvm::to_underlying(TagType)) 243d0f9a872SJulie Hockett TagType = Other.TagType; 24468266828SBrett Wilson IsTypeDef = IsTypeDef || Other.IsTypeDef; 245d0f9a872SJulie Hockett if (Members.empty()) 246d0f9a872SJulie Hockett Members = std::move(Other.Members); 247ba3d595fSDiego Astiazaran if (Bases.empty()) 248ba3d595fSDiego Astiazaran Bases = std::move(Other.Bases); 249d0f9a872SJulie Hockett if (Parents.empty()) 250d0f9a872SJulie Hockett Parents = std::move(Other.Parents); 251d0f9a872SJulie Hockett if (VirtualParents.empty()) 252d0f9a872SJulie Hockett VirtualParents = std::move(Other.VirtualParents); 2538899c29bSJulie Hockett // Reduce children if necessary. 25421fb70c6SBrett Wilson reduceChildren(Children.Records, std::move(Other.Children.Records)); 25521fb70c6SBrett Wilson reduceChildren(Children.Functions, std::move(Other.Children.Functions)); 25621fb70c6SBrett Wilson reduceChildren(Children.Enums, std::move(Other.Children.Enums)); 25721fb70c6SBrett Wilson reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs)); 258d0f9a872SJulie Hockett SymbolInfo::merge(std::move(Other)); 2594a68babdSBrett Wilson if (!Template) 2604a68babdSBrett Wilson Template = Other.Template; 261d0f9a872SJulie Hockett } 262d0f9a872SJulie Hockett 263d0f9a872SJulie Hockett void EnumInfo::merge(EnumInfo &&Other) { 264d0f9a872SJulie Hockett assert(mergeable(Other)); 265d0f9a872SJulie Hockett if (!Scoped) 266d0f9a872SJulie Hockett Scoped = Other.Scoped; 267d0f9a872SJulie Hockett if (Members.empty()) 268d0f9a872SJulie Hockett Members = std::move(Other.Members); 269d0f9a872SJulie Hockett SymbolInfo::merge(std::move(Other)); 270d0f9a872SJulie Hockett } 271d0f9a872SJulie Hockett 272d0f9a872SJulie Hockett void FunctionInfo::merge(FunctionInfo &&Other) { 273d0f9a872SJulie Hockett assert(mergeable(Other)); 274d0f9a872SJulie Hockett if (!IsMethod) 275d0f9a872SJulie Hockett IsMethod = Other.IsMethod; 276d0f9a872SJulie Hockett if (!Access) 277d0f9a872SJulie Hockett Access = Other.Access; 278d0f9a872SJulie Hockett if (ReturnType.Type.USR == EmptySID && ReturnType.Type.Name == "") 279d0f9a872SJulie Hockett ReturnType = std::move(Other.ReturnType); 280d0f9a872SJulie Hockett if (Parent.USR == EmptySID && Parent.Name == "") 281d0f9a872SJulie Hockett Parent = std::move(Other.Parent); 282d0f9a872SJulie Hockett if (Params.empty()) 283d0f9a872SJulie Hockett Params = std::move(Other.Params); 284d0f9a872SJulie Hockett SymbolInfo::merge(std::move(Other)); 2854a68babdSBrett Wilson if (!Template) 2864a68babdSBrett Wilson Template = Other.Template; 287d0f9a872SJulie Hockett } 288d0f9a872SJulie Hockett 28921fb70c6SBrett Wilson void TypedefInfo::merge(TypedefInfo &&Other) { 29021fb70c6SBrett Wilson assert(mergeable(Other)); 29121fb70c6SBrett Wilson if (!IsUsing) 29221fb70c6SBrett Wilson IsUsing = Other.IsUsing; 29321fb70c6SBrett Wilson if (Underlying.Type.Name == "") 29421fb70c6SBrett Wilson Underlying = Other.Underlying; 29521fb70c6SBrett Wilson SymbolInfo::merge(std::move(Other)); 29621fb70c6SBrett Wilson } 29721fb70c6SBrett Wilson 298f88c6b91SJens Massberg BaseRecordInfo::BaseRecordInfo() : RecordInfo() {} 299f88c6b91SJens Massberg 300f88c6b91SJens Massberg BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, 301f88c6b91SJens Massberg bool IsVirtual, AccessSpecifier Access, 302f88c6b91SJens Massberg bool IsParent) 303f88c6b91SJens Massberg : RecordInfo(USR, Name, Path), IsVirtual(IsVirtual), Access(Access), 304f88c6b91SJens Massberg IsParent(IsParent) {} 305f88c6b91SJens Massberg 3067dfe0bc3SDiego Astiazaran llvm::SmallString<16> Info::extractName() const { 307d900ef0aSJulie Hockett if (!Name.empty()) 308d900ef0aSJulie Hockett return Name; 309d900ef0aSJulie Hockett 310d900ef0aSJulie Hockett switch (IT) { 311d900ef0aSJulie Hockett case InfoType::IT_namespace: 312d900ef0aSJulie Hockett // Cover the case where the project contains a base namespace called 313d900ef0aSJulie Hockett // 'GlobalNamespace' (i.e. a namespace at the same level as the global 314d900ef0aSJulie Hockett // namespace, which would conflict with the hard-coded global namespace name 315d900ef0aSJulie Hockett // below.) 316d900ef0aSJulie Hockett if (Name == "GlobalNamespace" && Namespace.empty()) 317d900ef0aSJulie Hockett return llvm::SmallString<16>("@GlobalNamespace"); 318d900ef0aSJulie Hockett // The case of anonymous namespaces is taken care of in serialization, 319d900ef0aSJulie Hockett // so here we can safely assume an unnamed namespace is the global 320d900ef0aSJulie Hockett // one. 321d900ef0aSJulie Hockett return llvm::SmallString<16>("GlobalNamespace"); 322d900ef0aSJulie Hockett case InfoType::IT_record: 323d900ef0aSJulie Hockett return llvm::SmallString<16>("@nonymous_record_" + 324d900ef0aSJulie Hockett toHex(llvm::toStringRef(USR))); 325d900ef0aSJulie Hockett case InfoType::IT_enum: 326d900ef0aSJulie Hockett return llvm::SmallString<16>("@nonymous_enum_" + 327d900ef0aSJulie Hockett toHex(llvm::toStringRef(USR))); 32821fb70c6SBrett Wilson case InfoType::IT_typedef: 32921fb70c6SBrett Wilson return llvm::SmallString<16>("@nonymous_typedef_" + 33021fb70c6SBrett Wilson toHex(llvm::toStringRef(USR))); 331d900ef0aSJulie Hockett case InfoType::IT_function: 332d900ef0aSJulie Hockett return llvm::SmallString<16>("@nonymous_function_" + 333d900ef0aSJulie Hockett toHex(llvm::toStringRef(USR))); 334d900ef0aSJulie Hockett case InfoType::IT_default: 335d900ef0aSJulie Hockett return llvm::SmallString<16>("@nonymous_" + toHex(llvm::toStringRef(USR))); 336d900ef0aSJulie Hockett } 337d900ef0aSJulie Hockett llvm_unreachable("Invalid InfoType."); 338d900ef0aSJulie Hockett return llvm::SmallString<16>(""); 339d900ef0aSJulie Hockett } 340d900ef0aSJulie Hockett 341b7bb9fb2SDiego Astiazaran // Order is based on the Name attribute: case insensitive order 342b7bb9fb2SDiego Astiazaran bool Index::operator<(const Index &Other) const { 343b7bb9fb2SDiego Astiazaran // Loop through each character of both strings 344b7bb9fb2SDiego Astiazaran for (unsigned I = 0; I < Name.size() && I < Other.Name.size(); ++I) { 345b7bb9fb2SDiego Astiazaran // Compare them after converting both to lower case 346b7bb9fb2SDiego Astiazaran int D = tolower(Name[I]) - tolower(Other.Name[I]); 347b7bb9fb2SDiego Astiazaran if (D == 0) 348b7bb9fb2SDiego Astiazaran continue; 349b7bb9fb2SDiego Astiazaran return D < 0; 350b7bb9fb2SDiego Astiazaran } 351b7bb9fb2SDiego Astiazaran // If both strings have the size it means they would be equal if changed to 352b7bb9fb2SDiego Astiazaran // lower case. In here, lower case will be smaller than upper case 353b7bb9fb2SDiego Astiazaran // Example: string < stRing = true 354b7bb9fb2SDiego Astiazaran // This is the opposite of how operator < handles strings 355b7bb9fb2SDiego Astiazaran if (Name.size() == Other.Name.size()) 356b7bb9fb2SDiego Astiazaran return Name > Other.Name; 357b7bb9fb2SDiego Astiazaran // If they are not the same size; the shorter string is smaller 358b7bb9fb2SDiego Astiazaran return Name.size() < Other.Name.size(); 359b7bb9fb2SDiego Astiazaran } 360b7bb9fb2SDiego Astiazaran 3617dfe0bc3SDiego Astiazaran void Index::sort() { 3624065e921SBenjamin Kramer llvm::sort(Children); 3637dfe0bc3SDiego Astiazaran for (auto &C : Children) 3647dfe0bc3SDiego Astiazaran C.sort(); 3657dfe0bc3SDiego Astiazaran } 3667dfe0bc3SDiego Astiazaran 367665e9676SDiego Astiazaran ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx, 3683550da79SDiego Astiazaran StringRef ProjectName, bool PublicOnly, 3693550da79SDiego Astiazaran StringRef OutDirectory, StringRef SourceRoot, 3703550da79SDiego Astiazaran StringRef RepositoryUrl, 37180d1c6acSPeterChou1 std::vector<std::string> UserStylesheets) 3723550da79SDiego Astiazaran : ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly), 37380d1c6acSPeterChou1 OutDirectory(OutDirectory), UserStylesheets(UserStylesheets) { 37477dc05b9SDiego Astiazaran llvm::SmallString<128> SourceRootDir(SourceRoot); 37577dc05b9SDiego Astiazaran if (SourceRoot.empty()) 37677dc05b9SDiego Astiazaran // If no SourceRoot was provided the current path is used as the default 37777dc05b9SDiego Astiazaran llvm::sys::fs::current_path(SourceRootDir); 3782b00d449SKazu Hirata this->SourceRoot = std::string(SourceRootDir); 379665e9676SDiego Astiazaran if (!RepositoryUrl.empty()) { 380adcd0268SBenjamin Kramer this->RepositoryUrl = std::string(RepositoryUrl); 3815232cec8SNicolas van Kempen if (!RepositoryUrl.empty() && !RepositoryUrl.starts_with("http://") && 3825232cec8SNicolas van Kempen !RepositoryUrl.starts_with("https://")) 383665e9676SDiego Astiazaran this->RepositoryUrl->insert(0, "https://"); 384665e9676SDiego Astiazaran } 385665e9676SDiego Astiazaran } 386665e9676SDiego Astiazaran 387*3c9e3457SPeterChou1 void ScopeChildren::sort() { 388*3c9e3457SPeterChou1 llvm::sort(Namespaces.begin(), Namespaces.end()); 389*3c9e3457SPeterChou1 llvm::sort(Records.begin(), Records.end()); 390*3c9e3457SPeterChou1 llvm::sort(Functions.begin(), Functions.end()); 391*3c9e3457SPeterChou1 llvm::sort(Enums.begin(), Enums.end()); 392*3c9e3457SPeterChou1 llvm::sort(Typedefs.begin(), Typedefs.end()); 393*3c9e3457SPeterChou1 } 394d0f9a872SJulie Hockett } // namespace doc 395d0f9a872SJulie Hockett } // namespace clang 396