Marshallers.cpp revision 1.1.1.1
1//===--- Marshallers.cpp ----------------------------------------*- 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#include "Marshallers.h" 10#include "llvm/ADT/ArrayRef.h" 11#include "llvm/ADT/Optional.h" 12#include "llvm/ADT/StringRef.h" 13#include "llvm/Support/Regex.h" 14#include <string> 15 16static llvm::Optional<std::string> 17getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed, 18 llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) { 19 if (MaxEditDistance != ~0U) 20 ++MaxEditDistance; 21 llvm::StringRef Res; 22 for (const llvm::StringRef &Item : Allowed) { 23 if (Item.equals_lower(Search)) { 24 assert(!Item.equals(Search) && "This should be handled earlier on."); 25 MaxEditDistance = 1; 26 Res = Item; 27 continue; 28 } 29 unsigned Distance = Item.edit_distance(Search); 30 if (Distance < MaxEditDistance) { 31 MaxEditDistance = Distance; 32 Res = Item; 33 } 34 } 35 if (!Res.empty()) 36 return Res.str(); 37 if (!DropPrefix.empty()) { 38 --MaxEditDistance; // Treat dropping the prefix as 1 edit 39 for (const llvm::StringRef &Item : Allowed) { 40 auto NoPrefix = Item; 41 if (!NoPrefix.consume_front(DropPrefix)) 42 continue; 43 if (NoPrefix.equals_lower(Search)) { 44 if (NoPrefix.equals(Search)) 45 return Item.str(); 46 MaxEditDistance = 1; 47 Res = Item; 48 continue; 49 } 50 unsigned Distance = NoPrefix.edit_distance(Search); 51 if (Distance < MaxEditDistance) { 52 MaxEditDistance = Distance; 53 Res = Item; 54 } 55 } 56 if (!Res.empty()) 57 return Res.str(); 58 } 59 return llvm::None; 60} 61 62llvm::Optional<std::string> 63clang::ast_matchers::dynamic::internal::ArgTypeTraits< 64 clang::attr::Kind>::getBestGuess(const VariantValue &Value) { 65 static constexpr llvm::StringRef Allowed[] = { 66#define ATTR(X) "attr::" #X, 67#include "clang/Basic/AttrList.inc" 68 }; 69 if (Value.isString()) 70 return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), 71 "attr::"); 72 return llvm::None; 73} 74 75llvm::Optional<std::string> 76clang::ast_matchers::dynamic::internal::ArgTypeTraits< 77 clang::CastKind>::getBestGuess(const VariantValue &Value) { 78 static constexpr llvm::StringRef Allowed[] = { 79#define CAST_OPERATION(Name) "CK_" #Name, 80#include "clang/AST/OperationKinds.def" 81 }; 82 if (Value.isString()) 83 return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), 84 "CK_"); 85 return llvm::None; 86} 87 88llvm::Optional<std::string> 89clang::ast_matchers::dynamic::internal::ArgTypeTraits< 90 clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) { 91 static constexpr llvm::StringRef Allowed[] = { 92#define GEN_CLANG_CLAUSE_CLASS 93#define CLAUSE_CLASS(Enum, Str, Class) #Enum, 94#include "llvm/Frontend/OpenMP/OMP.inc" 95 }; 96 if (Value.isString()) 97 return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), 98 "OMPC_"); 99 return llvm::None; 100} 101 102llvm::Optional<std::string> 103clang::ast_matchers::dynamic::internal::ArgTypeTraits< 104 clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) { 105 static constexpr llvm::StringRef Allowed[] = { 106#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name, 107#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name, 108#include "clang/Basic/TokenKinds.def" 109 }; 110 if (Value.isString()) 111 return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), 112 "UETT_"); 113 return llvm::None; 114} 115 116static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags> 117 RegexMap[] = { 118 {"NoFlags", llvm::Regex::RegexFlags::NoFlags}, 119 {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase}, 120 {"Newline", llvm::Regex::RegexFlags::Newline}, 121 {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex}, 122}; 123 124static llvm::Optional<llvm::Regex::RegexFlags> 125getRegexFlag(llvm::StringRef Flag) { 126 for (const auto &StringFlag : RegexMap) { 127 if (Flag == StringFlag.first) 128 return StringFlag.second; 129 } 130 return llvm::None; 131} 132 133static llvm::Optional<llvm::StringRef> 134getCloseRegexMatch(llvm::StringRef Flag) { 135 for (const auto &StringFlag : RegexMap) { 136 if (Flag.edit_distance(StringFlag.first) < 3) 137 return StringFlag.first; 138 } 139 return llvm::None; 140} 141 142llvm::Optional<llvm::Regex::RegexFlags> 143clang::ast_matchers::dynamic::internal::ArgTypeTraits< 144 llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) { 145 llvm::Optional<llvm::Regex::RegexFlags> Flag; 146 SmallVector<StringRef, 4> Split; 147 Flags.split(Split, '|', -1, false); 148 for (StringRef OrFlag : Split) { 149 if (llvm::Optional<llvm::Regex::RegexFlags> NextFlag = 150 getRegexFlag(OrFlag.trim())) 151 Flag = Flag.getValueOr(llvm::Regex::NoFlags) | *NextFlag; 152 else 153 return None; 154 } 155 return Flag; 156} 157 158llvm::Optional<std::string> 159clang::ast_matchers::dynamic::internal::ArgTypeTraits< 160 llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) { 161 if (!Value.isString()) 162 return llvm::None; 163 SmallVector<StringRef, 4> Split; 164 llvm::StringRef(Value.getString()).split(Split, '|', -1, false); 165 for (llvm::StringRef &Flag : Split) { 166 if (llvm::Optional<llvm::StringRef> BestGuess = 167 getCloseRegexMatch(Flag.trim())) 168 Flag = *BestGuess; 169 else 170 return None; 171 } 172 if (Split.empty()) 173 return None; 174 return llvm::join(Split, " | "); 175} 176