xref: /freebsd-src/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===--- Marshallers.cpp ----------------------------------------*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "Marshallers.h"
105ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
115ffd83dbSDimitry Andric #include "llvm/ADT/Optional.h"
125ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
135ffd83dbSDimitry Andric #include "llvm/Support/Regex.h"
145ffd83dbSDimitry Andric #include <string>
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric static llvm::Optional<std::string>
175ffd83dbSDimitry Andric getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed,
185ffd83dbSDimitry Andric              llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) {
195ffd83dbSDimitry Andric   if (MaxEditDistance != ~0U)
205ffd83dbSDimitry Andric     ++MaxEditDistance;
215ffd83dbSDimitry Andric   llvm::StringRef Res;
225ffd83dbSDimitry Andric   for (const llvm::StringRef &Item : Allowed) {
235ffd83dbSDimitry Andric     if (Item.equals_lower(Search)) {
245ffd83dbSDimitry Andric       assert(!Item.equals(Search) && "This should be handled earlier on.");
255ffd83dbSDimitry Andric       MaxEditDistance = 1;
265ffd83dbSDimitry Andric       Res = Item;
275ffd83dbSDimitry Andric       continue;
285ffd83dbSDimitry Andric     }
295ffd83dbSDimitry Andric     unsigned Distance = Item.edit_distance(Search);
305ffd83dbSDimitry Andric     if (Distance < MaxEditDistance) {
315ffd83dbSDimitry Andric       MaxEditDistance = Distance;
325ffd83dbSDimitry Andric       Res = Item;
335ffd83dbSDimitry Andric     }
345ffd83dbSDimitry Andric   }
355ffd83dbSDimitry Andric   if (!Res.empty())
365ffd83dbSDimitry Andric     return Res.str();
375ffd83dbSDimitry Andric   if (!DropPrefix.empty()) {
385ffd83dbSDimitry Andric     --MaxEditDistance; // Treat dropping the prefix as 1 edit
395ffd83dbSDimitry Andric     for (const llvm::StringRef &Item : Allowed) {
405ffd83dbSDimitry Andric       auto NoPrefix = Item;
415ffd83dbSDimitry Andric       if (!NoPrefix.consume_front(DropPrefix))
425ffd83dbSDimitry Andric         continue;
435ffd83dbSDimitry Andric       if (NoPrefix.equals_lower(Search)) {
445ffd83dbSDimitry Andric         if (NoPrefix.equals(Search))
455ffd83dbSDimitry Andric           return Item.str();
465ffd83dbSDimitry Andric         MaxEditDistance = 1;
475ffd83dbSDimitry Andric         Res = Item;
485ffd83dbSDimitry Andric         continue;
495ffd83dbSDimitry Andric       }
505ffd83dbSDimitry Andric       unsigned Distance = NoPrefix.edit_distance(Search);
515ffd83dbSDimitry Andric       if (Distance < MaxEditDistance) {
525ffd83dbSDimitry Andric         MaxEditDistance = Distance;
535ffd83dbSDimitry Andric         Res = Item;
545ffd83dbSDimitry Andric       }
555ffd83dbSDimitry Andric     }
565ffd83dbSDimitry Andric     if (!Res.empty())
575ffd83dbSDimitry Andric       return Res.str();
585ffd83dbSDimitry Andric   }
595ffd83dbSDimitry Andric   return llvm::None;
605ffd83dbSDimitry Andric }
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric llvm::Optional<std::string>
635ffd83dbSDimitry Andric clang::ast_matchers::dynamic::internal::ArgTypeTraits<
645ffd83dbSDimitry Andric     clang::attr::Kind>::getBestGuess(const VariantValue &Value) {
655ffd83dbSDimitry Andric   static constexpr llvm::StringRef Allowed[] = {
665ffd83dbSDimitry Andric #define ATTR(X) "attr::" #X,
675ffd83dbSDimitry Andric #include "clang/Basic/AttrList.inc"
685ffd83dbSDimitry Andric   };
695ffd83dbSDimitry Andric   if (Value.isString())
705ffd83dbSDimitry Andric     return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
715ffd83dbSDimitry Andric                           "attr::");
725ffd83dbSDimitry Andric   return llvm::None;
735ffd83dbSDimitry Andric }
745ffd83dbSDimitry Andric 
755ffd83dbSDimitry Andric llvm::Optional<std::string>
765ffd83dbSDimitry Andric clang::ast_matchers::dynamic::internal::ArgTypeTraits<
775ffd83dbSDimitry Andric     clang::CastKind>::getBestGuess(const VariantValue &Value) {
785ffd83dbSDimitry Andric   static constexpr llvm::StringRef Allowed[] = {
795ffd83dbSDimitry Andric #define CAST_OPERATION(Name) "CK_" #Name,
805ffd83dbSDimitry Andric #include "clang/AST/OperationKinds.def"
815ffd83dbSDimitry Andric   };
825ffd83dbSDimitry Andric   if (Value.isString())
835ffd83dbSDimitry Andric     return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
845ffd83dbSDimitry Andric                           "CK_");
855ffd83dbSDimitry Andric   return llvm::None;
865ffd83dbSDimitry Andric }
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric llvm::Optional<std::string>
895ffd83dbSDimitry Andric clang::ast_matchers::dynamic::internal::ArgTypeTraits<
905ffd83dbSDimitry Andric     clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) {
915ffd83dbSDimitry Andric   static constexpr llvm::StringRef Allowed[] = {
92*e8d8bef9SDimitry Andric #define GEN_CLANG_CLAUSE_CLASS
93*e8d8bef9SDimitry Andric #define CLAUSE_CLASS(Enum, Str, Class) #Enum,
94*e8d8bef9SDimitry Andric #include "llvm/Frontend/OpenMP/OMP.inc"
955ffd83dbSDimitry Andric   };
965ffd83dbSDimitry Andric   if (Value.isString())
975ffd83dbSDimitry Andric     return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
985ffd83dbSDimitry Andric                           "OMPC_");
995ffd83dbSDimitry Andric   return llvm::None;
1005ffd83dbSDimitry Andric }
1015ffd83dbSDimitry Andric 
1025ffd83dbSDimitry Andric llvm::Optional<std::string>
1035ffd83dbSDimitry Andric clang::ast_matchers::dynamic::internal::ArgTypeTraits<
1045ffd83dbSDimitry Andric     clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) {
1055ffd83dbSDimitry Andric   static constexpr llvm::StringRef Allowed[] = {
1065ffd83dbSDimitry Andric #define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
1075ffd83dbSDimitry Andric #define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
1085ffd83dbSDimitry Andric #include "clang/Basic/TokenKinds.def"
1095ffd83dbSDimitry Andric   };
1105ffd83dbSDimitry Andric   if (Value.isString())
1115ffd83dbSDimitry Andric     return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
1125ffd83dbSDimitry Andric                           "UETT_");
1135ffd83dbSDimitry Andric   return llvm::None;
1145ffd83dbSDimitry Andric }
1155ffd83dbSDimitry Andric 
1165ffd83dbSDimitry Andric static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags>
1175ffd83dbSDimitry Andric     RegexMap[] = {
1185ffd83dbSDimitry Andric         {"NoFlags", llvm::Regex::RegexFlags::NoFlags},
1195ffd83dbSDimitry Andric         {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase},
1205ffd83dbSDimitry Andric         {"Newline", llvm::Regex::RegexFlags::Newline},
1215ffd83dbSDimitry Andric         {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex},
1225ffd83dbSDimitry Andric };
1235ffd83dbSDimitry Andric 
124*e8d8bef9SDimitry Andric static llvm::Optional<llvm::Regex::RegexFlags>
125*e8d8bef9SDimitry Andric getRegexFlag(llvm::StringRef Flag) {
1265ffd83dbSDimitry Andric   for (const auto &StringFlag : RegexMap) {
1275ffd83dbSDimitry Andric     if (Flag == StringFlag.first)
1285ffd83dbSDimitry Andric       return StringFlag.second;
1295ffd83dbSDimitry Andric   }
1305ffd83dbSDimitry Andric   return llvm::None;
1315ffd83dbSDimitry Andric }
1325ffd83dbSDimitry Andric 
133*e8d8bef9SDimitry Andric static llvm::Optional<llvm::StringRef>
134*e8d8bef9SDimitry Andric getCloseRegexMatch(llvm::StringRef Flag) {
1355ffd83dbSDimitry Andric   for (const auto &StringFlag : RegexMap) {
1365ffd83dbSDimitry Andric     if (Flag.edit_distance(StringFlag.first) < 3)
1375ffd83dbSDimitry Andric       return StringFlag.first;
1385ffd83dbSDimitry Andric   }
1395ffd83dbSDimitry Andric   return llvm::None;
1405ffd83dbSDimitry Andric }
1415ffd83dbSDimitry Andric 
1425ffd83dbSDimitry Andric llvm::Optional<llvm::Regex::RegexFlags>
1435ffd83dbSDimitry Andric clang::ast_matchers::dynamic::internal::ArgTypeTraits<
1445ffd83dbSDimitry Andric     llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) {
1455ffd83dbSDimitry Andric   llvm::Optional<llvm::Regex::RegexFlags> Flag;
1465ffd83dbSDimitry Andric   SmallVector<StringRef, 4> Split;
1475ffd83dbSDimitry Andric   Flags.split(Split, '|', -1, false);
1485ffd83dbSDimitry Andric   for (StringRef OrFlag : Split) {
1495ffd83dbSDimitry Andric     if (llvm::Optional<llvm::Regex::RegexFlags> NextFlag =
1505ffd83dbSDimitry Andric             getRegexFlag(OrFlag.trim()))
1515ffd83dbSDimitry Andric       Flag = Flag.getValueOr(llvm::Regex::NoFlags) | *NextFlag;
1525ffd83dbSDimitry Andric     else
1535ffd83dbSDimitry Andric       return None;
1545ffd83dbSDimitry Andric   }
1555ffd83dbSDimitry Andric   return Flag;
1565ffd83dbSDimitry Andric }
1575ffd83dbSDimitry Andric 
1585ffd83dbSDimitry Andric llvm::Optional<std::string>
1595ffd83dbSDimitry Andric clang::ast_matchers::dynamic::internal::ArgTypeTraits<
1605ffd83dbSDimitry Andric     llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) {
1615ffd83dbSDimitry Andric   if (!Value.isString())
1625ffd83dbSDimitry Andric     return llvm::None;
1635ffd83dbSDimitry Andric   SmallVector<StringRef, 4> Split;
1645ffd83dbSDimitry Andric   llvm::StringRef(Value.getString()).split(Split, '|', -1, false);
1655ffd83dbSDimitry Andric   for (llvm::StringRef &Flag : Split) {
1665ffd83dbSDimitry Andric     if (llvm::Optional<llvm::StringRef> BestGuess =
1675ffd83dbSDimitry Andric             getCloseRegexMatch(Flag.trim()))
1685ffd83dbSDimitry Andric       Flag = *BestGuess;
1695ffd83dbSDimitry Andric     else
1705ffd83dbSDimitry Andric       return None;
1715ffd83dbSDimitry Andric   }
1725ffd83dbSDimitry Andric   if (Split.empty())
1735ffd83dbSDimitry Andric     return None;
1745ffd83dbSDimitry Andric   return llvm::join(Split, " | ");
1755ffd83dbSDimitry Andric }
176