10 #include "clang/Tooling/FixIt.h" 11 #include "llvm/ADT/IndexedMap.h" 22 return static_cast<unsigned>(Scale);
27 static llvm::Optional<llvm::APSInt>
29 double Value = FloatLiteral.getValueAsApproximateDouble();
30 if (std::fmod(Value, 1) == 0) {
31 if (Value >= static_cast<double>(1u << 31))
34 return llvm::APSInt::get(static_cast<int64_t>(Value));
39 const std::pair<llvm::StringRef, llvm::StringRef> &
41 static const llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
46 llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
50 InverseMap[DurationScale::Hours] =
51 std::make_pair(
"::absl::ToDoubleHours",
"::absl::ToInt64Hours");
52 InverseMap[DurationScale::Minutes] =
53 std::make_pair(
"::absl::ToDoubleMinutes",
"::absl::ToInt64Minutes");
54 InverseMap[DurationScale::Seconds] =
55 std::make_pair(
"::absl::ToDoubleSeconds",
"::absl::ToInt64Seconds");
56 InverseMap[DurationScale::Milliseconds] = std::make_pair(
57 "::absl::ToDoubleMilliseconds",
"::absl::ToInt64Milliseconds");
58 InverseMap[DurationScale::Microseconds] = std::make_pair(
59 "::absl::ToDoubleMicroseconds",
"::absl::ToInt64Microseconds");
60 InverseMap[DurationScale::Nanoseconds] = std::make_pair(
61 "::absl::ToDoubleNanoseconds",
"::absl::ToInt64Nanoseconds");
65 return InverseMap[Scale];
70 static llvm::Optional<std::string>
73 const std::pair<llvm::StringRef, llvm::StringRef> &InverseFunctions =
75 if (
const auto *MaybeCallArg = selectFirst<const Expr>(
77 match(callExpr(callee(functionDecl(hasAnyName(
78 InverseFunctions.first, InverseFunctions.second))),
79 hasArgument(0, expr().bind(
"e"))),
80 Node, *Result.Context))) {
81 return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
89 static llvm::Optional<std::string>
93 if (
const auto *MaybeCallArg = selectFirst<const Expr>(
94 "e",
match(callExpr(callee(functionDecl(hasName(InverseFunction))),
95 hasArgument(0, expr().bind(
"e"))),
96 Node, *Result.Context))) {
97 return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
106 case DurationScale::Hours:
107 return "absl::Hours";
108 case DurationScale::Minutes:
109 return "absl::Minutes";
110 case DurationScale::Seconds:
111 return "absl::Seconds";
112 case DurationScale::Milliseconds:
113 return "absl::Milliseconds";
114 case DurationScale::Microseconds:
115 return "absl::Microseconds";
116 case DurationScale::Nanoseconds:
117 return "absl::Nanoseconds";
119 llvm_unreachable(
"unknown scaling factor");
124 case DurationScale::Hours:
125 return "absl::FromUnixHours";
126 case DurationScale::Minutes:
127 return "absl::FromUnixMinutes";
128 case DurationScale::Seconds:
129 return "absl::FromUnixSeconds";
130 case DurationScale::Milliseconds:
131 return "absl::FromUnixMillis";
132 case DurationScale::Microseconds:
133 return "absl::FromUnixMicros";
134 case DurationScale::Nanoseconds:
135 return "absl::FromUnixNanos";
137 llvm_unreachable(
"unknown scaling factor");
143 case DurationScale::Hours:
144 return "absl::ToUnixHours";
145 case DurationScale::Minutes:
146 return "absl::ToUnixMinutes";
147 case DurationScale::Seconds:
148 return "absl::ToUnixSeconds";
149 case DurationScale::Milliseconds:
150 return "absl::ToUnixMillis";
151 case DurationScale::Microseconds:
152 return "absl::ToUnixMicros";
153 case DurationScale::Nanoseconds:
154 return "absl::ToUnixNanos";
156 llvm_unreachable(
"unknown scaling factor");
160 bool IsLiteralZero(
const MatchFinder::MatchResult &Result,
const Expr &Node) {
162 anyOf(integerLiteral(equals(0)), floatLiteral(equals(0.0)));
165 if (selectFirst<const clang::Expr>(
166 "val",
match(expr(ignoringImpCasts(ZeroMatcher)).bind(
"val"), Node,
167 *Result.Context)) !=
nullptr)
172 if (selectFirst<const clang::Expr>(
173 "val",
match(cxxFunctionalCastExpr(
175 anyOf(isInteger(), realFloatingPointType())),
176 hasSourceExpression(initListExpr(
177 hasInit(0, ignoringParenImpCasts(ZeroMatcher)))))
179 Node, *Result.Context)) !=
nullptr)
185 llvm::Optional<std::string>
188 if (
const Expr *MaybeCastArg = selectFirst<const Expr>(
190 match(expr(anyOf(cxxStaticCastExpr(
191 hasDestinationType(realFloatingPointType()),
192 hasSourceExpression(expr().bind(
"cast_arg"))),
194 hasDestinationType(realFloatingPointType()),
195 hasSourceExpression(expr().bind(
"cast_arg"))),
196 cxxFunctionalCastExpr(
197 hasDestinationType(realFloatingPointType()),
198 hasSourceExpression(expr().bind(
"cast_arg"))))),
199 Node, *Result.Context)))
200 return tooling::fixit::getText(*MaybeCastArg, *Result.Context).str();
205 llvm::Optional<std::string>
208 if (
const auto *LitFloat = llvm::dyn_cast<FloatingLiteral>(&Node))
211 return IntValue->toString(10);
219 if (llvm::Optional<std::string> MaybeArg =
stripFloatCast(Result, Node))
223 if (llvm::Optional<std::string> MaybeArg =
228 return tooling::fixit::getText(Node, *Result.Context).str();
232 static const llvm::StringMap<DurationScale> ScaleMap(
233 {{
"ToDoubleHours", DurationScale::Hours},
234 {
"ToInt64Hours", DurationScale::Hours},
235 {
"ToDoubleMinutes", DurationScale::Minutes},
236 {
"ToInt64Minutes", DurationScale::Minutes},
237 {
"ToDoubleSeconds", DurationScale::Seconds},
238 {
"ToInt64Seconds", DurationScale::Seconds},
239 {
"ToDoubleMilliseconds", DurationScale::Milliseconds},
240 {
"ToInt64Milliseconds", DurationScale::Milliseconds},
241 {
"ToDoubleMicroseconds", DurationScale::Microseconds},
242 {
"ToInt64Microseconds", DurationScale::Microseconds},
243 {
"ToDoubleNanoseconds", DurationScale::Nanoseconds},
244 {
"ToInt64Nanoseconds", DurationScale::Nanoseconds}});
246 auto ScaleIter = ScaleMap.find(std::string(Name));
247 if (ScaleIter == ScaleMap.end())
250 return ScaleIter->second;
254 static const llvm::StringMap<DurationScale> ScaleMap(
255 {{
"ToUnixHours", DurationScale::Hours},
256 {
"ToUnixMinutes", DurationScale::Minutes},
257 {
"ToUnixSeconds", DurationScale::Seconds},
258 {
"ToUnixMillis", DurationScale::Milliseconds},
259 {
"ToUnixMicros", DurationScale::Microseconds},
260 {
"ToUnixNanos", DurationScale::Nanoseconds}});
262 auto ScaleIter = ScaleMap.find(std::string(Name));
263 if (ScaleIter == ScaleMap.end())
266 return ScaleIter->second;
270 const ast_matchers::MatchFinder::MatchResult &Result,
DurationScale Scale,
272 const Expr &RootNode = *Node->IgnoreParenImpCasts();
275 if (llvm::Optional<std::string> MaybeRewrite =
277 return *MaybeRewrite;
280 return std::string(
"absl::ZeroDuration()");
288 const ast_matchers::MatchFinder::MatchResult &Result,
DurationScale Scale,
290 const Expr &RootNode = *Node->IgnoreParenImpCasts();
293 if (llvm::Optional<std::string> MaybeRewrite =
295 return *MaybeRewrite;
298 return std::string(
"absl::UnixEpoch()");
301 tooling::fixit::getText(RootNode, *Result.Context) +
")")
305 bool isInMacro(
const MatchFinder::MatchResult &Result,
const Expr *
E) {
306 if (!E->getBeginLoc().isMacroID())
309 SourceLocation
Loc = E->getBeginLoc();
312 while (Result.SourceManager->isMacroArgExpansion(Loc)) {
317 Loc = Result.SourceManager->getImmediateMacroCallerLoc(Loc);
319 return Loc.isMacroID();
SourceLocation Loc
'#' location in the include directive
llvm::Optional< DurationScale > getScaleForDurationInverse(llvm::StringRef Name)
Given the name of an inverse Duration function (e.g., ToDoubleSeconds), return its DurationScale...
std::string rewriteExprFromNumberToDuration(const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale, const Expr *Node)
Assuming Node has type double or int representing a time interval of Scale, return the expression to ...
static llvm::Optional< std::string > rewriteInverseDurationCall(const MatchFinder::MatchResult &Result, DurationScale Scale, const Expr &Node)
If Node is a call to the inverse of Scale, return that inverse's argument, otherwise None...
unsigned operator()(DurationScale Scale) const
bool isInMacro(const MatchFinder::MatchResult &Result, const Expr *E)
std::vector< std::string > match(const SymbolIndex &I, const FuzzyFindRequest &Req, bool *Incomplete)
const std::pair< llvm::StringRef, llvm::StringRef > & getDurationInverseForScale(DurationScale Scale)
Given a Scale return the fully qualified inverse functions for it.
static constexpr llvm::StringLiteral Name
std::string simplifyDurationFactoryArg(const MatchFinder::MatchResult &Result, const Expr &Node)
static llvm::Optional< std::string > rewriteInverseTimeCall(const MatchFinder::MatchResult &Result, DurationScale Scale, const Expr &Node)
If Node is a call to the inverse of Scale, return that inverse's argument, otherwise None...
llvm::StringRef getTimeInverseForScale(DurationScale scale)
Returns the Time factory function name for a given Scale.
llvm::StringRef getTimeFactoryForScale(DurationScale Scale)
Given a 'Scale', return the appropriate factory function call for constructing a Time for that scale...
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< DurationScale > getScaleForTimeInverse(llvm::StringRef Name)
Given the name of an inverse Time function (e.g., ToUnixSeconds), return its DurationScale, or None if a match is not found.
static llvm::Optional< llvm::APSInt > truncateIfIntegral(const FloatingLiteral &FloatLiteral)
Returns an integer if the fractional part of a FloatingLiteral is 0.
std::string rewriteExprFromNumberToTime(const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale, const Expr *Node)
Assuming Node has a type int representing a time instant of Scale since The Epoch, return the expression to make it a suitable Time.
llvm::Optional< std::string > stripFloatCast(const ast_matchers::MatchFinder::MatchResult &Result, const Expr &Node)
Possibly strip a floating point cast expression.
llvm::Optional< std::string > stripFloatLiteralFraction(const MatchFinder::MatchResult &Result, const Expr &Node)
llvm::StringRef getDurationFactoryForScale(DurationScale Scale)
Returns the factory function name for a given Scale.
bool IsLiteralZero(const MatchFinder::MatchResult &Result, const Expr &Node)
Returns true if Node is a value which evaluates to a literal 0.
DurationScale
Duration factory and conversion scales.