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