1 //===--- Marshallers.cpp ----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "Marshallers.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/Regex.h"
16 static std::optional
<std::string
>
17 getBestGuess(llvm::StringRef Search
, llvm::ArrayRef
<llvm::StringRef
> Allowed
,
18 llvm::StringRef DropPrefix
= "", unsigned MaxEditDistance
= 3) {
19 if (MaxEditDistance
!= ~0U)
22 for (const llvm::StringRef
&Item
: Allowed
) {
23 if (Item
.equals_insensitive(Search
)) {
24 assert(!Item
.equals(Search
) && "This should be handled earlier on.");
29 unsigned Distance
= Item
.edit_distance(Search
);
30 if (Distance
< MaxEditDistance
) {
31 MaxEditDistance
= Distance
;
37 if (!DropPrefix
.empty()) {
38 --MaxEditDistance
; // Treat dropping the prefix as 1 edit
39 for (const llvm::StringRef
&Item
: Allowed
) {
41 if (!NoPrefix
.consume_front(DropPrefix
))
43 if (NoPrefix
.equals_insensitive(Search
)) {
44 if (NoPrefix
.equals(Search
))
50 unsigned Distance
= NoPrefix
.edit_distance(Search
);
51 if (Distance
< MaxEditDistance
) {
52 MaxEditDistance
= Distance
;
62 std::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"
70 return ::getBestGuess(Value
.getString(), llvm::ArrayRef(Allowed
), "attr::");
74 std::optional
<std::string
>
75 clang::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"
82 return ::getBestGuess(Value
.getString(), llvm::ArrayRef(Allowed
), "CK_");
86 std::optional
<std::string
>
87 clang::ast_matchers::dynamic::internal::ArgTypeTraits
<
88 clang::OpenMPClauseKind
>::getBestGuess(const VariantValue
&Value
) {
89 static constexpr llvm::StringRef Allowed
[] = {
90 #define GEN_CLANG_CLAUSE_CLASS
91 #define CLAUSE_CLASS(Enum, Str, Class) #Enum,
92 #include "llvm/Frontend/OpenMP/OMP.inc"
95 return ::getBestGuess(Value
.getString(), llvm::ArrayRef(Allowed
), "OMPC_");
99 std::optional
<std::string
>
100 clang::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"
107 if (Value
.isString())
108 return ::getBestGuess(Value
.getString(), llvm::ArrayRef(Allowed
), "UETT_");
112 static constexpr std::pair
<llvm::StringRef
, llvm::Regex::RegexFlags
>
114 {"NoFlags", llvm::Regex::RegexFlags::NoFlags
},
115 {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase
},
116 {"Newline", llvm::Regex::RegexFlags::Newline
},
117 {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex
},
120 static std::optional
<llvm::Regex::RegexFlags
>
121 getRegexFlag(llvm::StringRef Flag
) {
122 for (const auto &StringFlag
: RegexMap
) {
123 if (Flag
== StringFlag
.first
)
124 return StringFlag
.second
;
129 static 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
;
137 std::optional
<llvm::Regex::RegexFlags
>
138 clang::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
;
153 std::optional
<std::string
>
154 clang::ast_matchers::dynamic::internal::ArgTypeTraits
<
155 llvm::Regex::RegexFlags
>::getBestGuess(const VariantValue
&Value
) {
156 if (!Value
.isString())
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()))
169 return llvm::join(Split
, " | ");