brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 37c91ab Raw
171 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Marshallers.h"10#include "llvm/ADT/ArrayRef.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/Support/Regex.h"13#include <optional>14#include <string>15 16static std::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_insensitive(Search)) {24      assert(Item != 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 edit39    for (const llvm::StringRef &Item : Allowed) {40      auto NoPrefix = Item;41      if (!NoPrefix.consume_front(DropPrefix))42        continue;43      if (NoPrefix.equals_insensitive(Search)) {44        if (NoPrefix == 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 std::nullopt;60}61 62std::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::ArrayRef(Allowed), "attr::");71  return std::nullopt;72}73 74std::optional<std::string>75clang::ast_matchers::dynamic::internal::ArgTypeTraits<76    clang::CastKind>::getBestGuess(const VariantValue &Value) {77  static constexpr llvm::StringRef Allowed[] = {78#define CAST_OPERATION(Name) "CK_" #Name,79#include "clang/AST/OperationKinds.def"80  };81  if (Value.isString())82    return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "CK_");83  return std::nullopt;84}85 86std::optional<std::string>87clang::ast_matchers::dynamic::internal::ArgTypeTraits<88    clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) {89  static constexpr llvm::StringRef Allowed[] = {90#define GEN_CLANG_CLAUSE_CLASS91#define CLAUSE_CLASS(Enum, Str, Class) #Enum,92#include "llvm/Frontend/OpenMP/OMP.inc"93  };94  if (Value.isString())95    return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "OMPC_");96  return std::nullopt;97}98 99std::optional<std::string>100clang::ast_matchers::dynamic::internal::ArgTypeTraits<101    clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) {102  static constexpr llvm::StringRef Allowed[] = {103#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,104#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,105#include "clang/Basic/TokenKinds.def"106  };107  if (Value.isString())108    return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "UETT_");109  return std::nullopt;110}111 112static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags>113    RegexMap[] = {114        {"NoFlags", llvm::Regex::RegexFlags::NoFlags},115        {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase},116        {"Newline", llvm::Regex::RegexFlags::Newline},117        {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex},118};119 120static std::optional<llvm::Regex::RegexFlags>121getRegexFlag(llvm::StringRef Flag) {122  for (const auto &StringFlag : RegexMap) {123    if (Flag == StringFlag.first)124      return StringFlag.second;125  }126  return std::nullopt;127}128 129static std::optional<llvm::StringRef> getCloseRegexMatch(llvm::StringRef Flag) {130  for (const auto &StringFlag : RegexMap) {131    if (Flag.edit_distance(StringFlag.first) < 3)132      return StringFlag.first;133  }134  return std::nullopt;135}136 137std::optional<llvm::Regex::RegexFlags>138clang::ast_matchers::dynamic::internal::ArgTypeTraits<139    llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) {140  std::optional<llvm::Regex::RegexFlags> Flag;141  SmallVector<StringRef, 4> Split;142  Flags.split(Split, '|', -1, false);143  for (StringRef OrFlag : Split) {144    if (std::optional<llvm::Regex::RegexFlags> NextFlag =145            getRegexFlag(OrFlag.trim()))146      Flag = Flag.value_or(llvm::Regex::NoFlags) | *NextFlag;147    else148      return std::nullopt;149  }150  return Flag;151}152 153std::optional<std::string>154clang::ast_matchers::dynamic::internal::ArgTypeTraits<155    llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) {156  if (!Value.isString())157    return std::nullopt;158  SmallVector<StringRef, 4> Split;159  llvm::StringRef(Value.getString()).split(Split, '|', -1, false);160  for (llvm::StringRef &Flag : Split) {161    if (std::optional<llvm::StringRef> BestGuess =162            getCloseRegexMatch(Flag.trim()))163      Flag = *BestGuess;164    else165      return std::nullopt;166  }167  if (Split.empty())168    return std::nullopt;169  return llvm::join(Split, " | ");170}171