Path: blob/main/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp
35292 views
//===--- Marshallers.cpp ----------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Marshallers.h"9#include "llvm/ADT/ArrayRef.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/Support/Regex.h"12#include <optional>13#include <string>1415static std::optional<std::string>16getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed,17llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) {18if (MaxEditDistance != ~0U)19++MaxEditDistance;20llvm::StringRef Res;21for (const llvm::StringRef &Item : Allowed) {22if (Item.equals_insensitive(Search)) {23assert(Item != Search && "This should be handled earlier on.");24MaxEditDistance = 1;25Res = Item;26continue;27}28unsigned Distance = Item.edit_distance(Search);29if (Distance < MaxEditDistance) {30MaxEditDistance = Distance;31Res = Item;32}33}34if (!Res.empty())35return Res.str();36if (!DropPrefix.empty()) {37--MaxEditDistance; // Treat dropping the prefix as 1 edit38for (const llvm::StringRef &Item : Allowed) {39auto NoPrefix = Item;40if (!NoPrefix.consume_front(DropPrefix))41continue;42if (NoPrefix.equals_insensitive(Search)) {43if (NoPrefix == Search)44return Item.str();45MaxEditDistance = 1;46Res = Item;47continue;48}49unsigned Distance = NoPrefix.edit_distance(Search);50if (Distance < MaxEditDistance) {51MaxEditDistance = Distance;52Res = Item;53}54}55if (!Res.empty())56return Res.str();57}58return std::nullopt;59}6061std::optional<std::string>62clang::ast_matchers::dynamic::internal::ArgTypeTraits<63clang::attr::Kind>::getBestGuess(const VariantValue &Value) {64static constexpr llvm::StringRef Allowed[] = {65#define ATTR(X) "attr::" #X,66#include "clang/Basic/AttrList.inc"67};68if (Value.isString())69return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "attr::");70return std::nullopt;71}7273std::optional<std::string>74clang::ast_matchers::dynamic::internal::ArgTypeTraits<75clang::CastKind>::getBestGuess(const VariantValue &Value) {76static constexpr llvm::StringRef Allowed[] = {77#define CAST_OPERATION(Name) "CK_" #Name,78#include "clang/AST/OperationKinds.def"79};80if (Value.isString())81return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "CK_");82return std::nullopt;83}8485std::optional<std::string>86clang::ast_matchers::dynamic::internal::ArgTypeTraits<87clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) {88static constexpr llvm::StringRef Allowed[] = {89#define GEN_CLANG_CLAUSE_CLASS90#define CLAUSE_CLASS(Enum, Str, Class) #Enum,91#include "llvm/Frontend/OpenMP/OMP.inc"92};93if (Value.isString())94return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "OMPC_");95return std::nullopt;96}9798std::optional<std::string>99clang::ast_matchers::dynamic::internal::ArgTypeTraits<100clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) {101static constexpr llvm::StringRef Allowed[] = {102#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,103#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,104#include "clang/Basic/TokenKinds.def"105};106if (Value.isString())107return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "UETT_");108return std::nullopt;109}110111static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags>112RegexMap[] = {113{"NoFlags", llvm::Regex::RegexFlags::NoFlags},114{"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase},115{"Newline", llvm::Regex::RegexFlags::Newline},116{"BasicRegex", llvm::Regex::RegexFlags::BasicRegex},117};118119static std::optional<llvm::Regex::RegexFlags>120getRegexFlag(llvm::StringRef Flag) {121for (const auto &StringFlag : RegexMap) {122if (Flag == StringFlag.first)123return StringFlag.second;124}125return std::nullopt;126}127128static std::optional<llvm::StringRef> getCloseRegexMatch(llvm::StringRef Flag) {129for (const auto &StringFlag : RegexMap) {130if (Flag.edit_distance(StringFlag.first) < 3)131return StringFlag.first;132}133return std::nullopt;134}135136std::optional<llvm::Regex::RegexFlags>137clang::ast_matchers::dynamic::internal::ArgTypeTraits<138llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) {139std::optional<llvm::Regex::RegexFlags> Flag;140SmallVector<StringRef, 4> Split;141Flags.split(Split, '|', -1, false);142for (StringRef OrFlag : Split) {143if (std::optional<llvm::Regex::RegexFlags> NextFlag =144getRegexFlag(OrFlag.trim()))145Flag = Flag.value_or(llvm::Regex::NoFlags) | *NextFlag;146else147return std::nullopt;148}149return Flag;150}151152std::optional<std::string>153clang::ast_matchers::dynamic::internal::ArgTypeTraits<154llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) {155if (!Value.isString())156return std::nullopt;157SmallVector<StringRef, 4> Split;158llvm::StringRef(Value.getString()).split(Split, '|', -1, false);159for (llvm::StringRef &Flag : Split) {160if (std::optional<llvm::StringRef> BestGuess =161getCloseRegexMatch(Flag.trim()))162Flag = *BestGuess;163else164return std::nullopt;165}166if (Split.empty())167return std::nullopt;168return llvm::join(Split, " | ");169}170171172