Home | History | Annotate | Line # | Download | only in Dynamic
      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 
     16 static llvm::Optional<std::string>
     17 getBestGuess(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 
     62 llvm::Optional<std::string>
     63 clang::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 
     75 llvm::Optional<std::string>
     76 clang::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 
     88 llvm::Optional<std::string>
     89 clang::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 
    102 llvm::Optional<std::string>
    103 clang::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 
    116 static 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 
    124 static llvm::Optional<llvm::Regex::RegexFlags>
    125 getRegexFlag(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 
    133 static llvm::Optional<llvm::StringRef>
    134 getCloseRegexMatch(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 
    142 llvm::Optional<llvm::Regex::RegexFlags>
    143 clang::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 
    158 llvm::Optional<std::string>
    159 clang::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