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