[clang-tidy][NFC] Convert Lexer utils to use std::optional<Token> (#174809)
This bring a more unified api and avoid caveats like "return ``tok::unknown`` if not found.", which makes easier to forget error checking. --------- Co-authored-by: mitchell <zeyi2@nekoarch.cc>
This commit is contained in:
parent
1658456ccf
commit
c951d76fd0
@ -127,16 +127,16 @@ static std::vector<std::pair<SourceLocation, StringRef>>
|
||||
getCommentsBeforeLoc(ASTContext *Ctx, SourceLocation Loc) {
|
||||
std::vector<std::pair<SourceLocation, StringRef>> Comments;
|
||||
while (Loc.isValid()) {
|
||||
const clang::Token Tok = utils::lexer::getPreviousToken(
|
||||
const std::optional<Token> Tok = utils::lexer::getPreviousToken(
|
||||
Loc, Ctx->getSourceManager(), Ctx->getLangOpts(),
|
||||
/*SkipComments=*/false);
|
||||
if (Tok.isNot(tok::comment))
|
||||
if (!Tok || Tok->isNot(tok::comment))
|
||||
break;
|
||||
Loc = Tok.getLocation();
|
||||
Loc = Tok->getLocation();
|
||||
Comments.emplace_back(
|
||||
Loc,
|
||||
Lexer::getSourceText(CharSourceRange::getCharRange(
|
||||
Loc, Loc.getLocWithOffset(Tok.getLength())),
|
||||
Loc, Loc.getLocWithOffset(Tok->getLength())),
|
||||
Ctx->getSourceManager(), Ctx->getLangOpts()));
|
||||
}
|
||||
return Comments;
|
||||
|
||||
@ -141,10 +141,11 @@ void OptionalValueConversionCheck::check(
|
||||
}
|
||||
if (const auto *CallExpr =
|
||||
Result.Nodes.getNodeAs<CXXMemberCallExpr>("member-call")) {
|
||||
const SourceLocation Begin =
|
||||
utils::lexer::getPreviousToken(CallExpr->getExprLoc(),
|
||||
*Result.SourceManager, getLangOpts())
|
||||
.getLocation();
|
||||
const std::optional<Token> Tok = utils::lexer::getPreviousToken(
|
||||
CallExpr->getExprLoc(), *Result.SourceManager, getLangOpts());
|
||||
if (!Tok)
|
||||
return;
|
||||
const SourceLocation Begin = Tok->getLocation();
|
||||
auto Diag =
|
||||
diag(CallExpr->getExprLoc(),
|
||||
"remove call to %0 to silence this warning", DiagnosticIDs::Note);
|
||||
|
||||
@ -37,16 +37,16 @@ void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
return;
|
||||
|
||||
ASTContext &Ctxt = *Result.Context;
|
||||
auto Token = utils::lexer::getPreviousToken(LocStart, Ctxt.getSourceManager(),
|
||||
Ctxt.getLangOpts());
|
||||
auto &SM = *Result.SourceManager;
|
||||
const auto &SM = *Result.SourceManager;
|
||||
const unsigned SemicolonLine = SM.getSpellingLineNumber(LocStart);
|
||||
|
||||
const auto *Statement = Result.Nodes.getNodeAs<Stmt>("stmt");
|
||||
const bool IsIfStmt = isa<IfStmt>(Statement);
|
||||
|
||||
if (!IsIfStmt &&
|
||||
SM.getSpellingLineNumber(Token.getLocation()) != SemicolonLine)
|
||||
const std::optional<Token> PrevTok = utils::lexer::getPreviousToken(
|
||||
LocStart, Ctxt.getSourceManager(), Ctxt.getLangOpts());
|
||||
if (!PrevTok || (!IsIfStmt && SM.getSpellingLineNumber(
|
||||
PrevTok->getLocation()) != SemicolonLine))
|
||||
return;
|
||||
|
||||
const SourceLocation LocEnd = Semicolon->getEndLoc();
|
||||
@ -55,6 +55,7 @@ void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
Lexer Lexer(SM.getLocForStartOfFile(FID), Ctxt.getLangOpts(),
|
||||
Buffer.getBufferStart(), SM.getCharacterData(LocEnd) + 1,
|
||||
Buffer.getBufferEnd());
|
||||
Token Token;
|
||||
if (Lexer.LexFromRawLexer(Token))
|
||||
return;
|
||||
|
||||
|
||||
@ -149,18 +149,20 @@ struct InitializerInsertion {
|
||||
"insertion represents a new initializer list.");
|
||||
SourceLocation Location;
|
||||
switch (Placement) {
|
||||
case InitializerPlacement::New:
|
||||
Location = utils::lexer::getPreviousToken(
|
||||
Constructor.getBody()->getBeginLoc(),
|
||||
Context.getSourceManager(), Context.getLangOpts())
|
||||
.getLocation();
|
||||
case InitializerPlacement::New: {
|
||||
const std::optional<Token> Tok = utils::lexer::getPreviousToken(
|
||||
Constructor.getBody()->getBeginLoc(), Context.getSourceManager(),
|
||||
Context.getLangOpts());
|
||||
Location = Tok ? Tok->getLocation() : SourceLocation{};
|
||||
break;
|
||||
case InitializerPlacement::Before:
|
||||
Location = utils::lexer::getPreviousToken(
|
||||
Where->getSourceRange().getBegin(),
|
||||
Context.getSourceManager(), Context.getLangOpts())
|
||||
.getLocation();
|
||||
}
|
||||
case InitializerPlacement::Before: {
|
||||
const std::optional<Token> Tok = utils::lexer::getPreviousToken(
|
||||
Where->getSourceRange().getBegin(), Context.getSourceManager(),
|
||||
Context.getLangOpts());
|
||||
Location = Tok ? Tok->getLocation() : SourceLocation{};
|
||||
break;
|
||||
}
|
||||
case InitializerPlacement::After:
|
||||
Location = Where->getRParenLoc();
|
||||
break;
|
||||
|
||||
@ -318,11 +318,11 @@ static std::optional<std::string> getConditionText(const Expr *ConditionExpr,
|
||||
return std::nullopt;
|
||||
|
||||
const bool SkipComments = false;
|
||||
Token PrevToken;
|
||||
std::optional<Token> PrevToken;
|
||||
std::tie(PrevToken, PrevTokenLoc) = utils::lexer::getPreviousTokenAndStart(
|
||||
PrevTokenLoc, SM, LangOpts, SkipComments);
|
||||
const bool EndsWithDoubleSlash =
|
||||
PrevToken.is(tok::comment) &&
|
||||
PrevToken && PrevToken->is(tok::comment) &&
|
||||
Lexer::getSourceText(CharSourceRange::getCharRange(
|
||||
PrevTokenLoc, PrevTokenLoc.getLocWithOffset(2)),
|
||||
SM, LangOpts) == "//";
|
||||
|
||||
@ -144,13 +144,15 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
SourceLocation EndLoc = MatchedDecl->getLocation();
|
||||
|
||||
while (true) {
|
||||
const Token Prev = utils::lexer::getPreviousToken(StartLoc, SM, LO);
|
||||
const std::optional<Token> Prev =
|
||||
utils::lexer::getPreviousToken(StartLoc, SM, LO);
|
||||
const std::optional<Token> Next =
|
||||
utils::lexer::findNextTokenSkippingComments(EndLoc, SM, LO);
|
||||
if (Prev.isNot(tok::l_paren) || !Next || Next->isNot(tok::r_paren))
|
||||
if (!Prev || Prev->isNot(tok::l_paren) || !Next ||
|
||||
Next->isNot(tok::r_paren))
|
||||
break;
|
||||
|
||||
StartLoc = Prev.getLocation();
|
||||
StartLoc = Prev->getLocation();
|
||||
EndLoc = Next->getLocation();
|
||||
}
|
||||
|
||||
|
||||
@ -52,16 +52,18 @@ void DeleteNullPointerCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
auto Diag = diag(
|
||||
IfWithDelete->getBeginLoc(),
|
||||
"'if' statement is unnecessary; deleting null pointer has no effect");
|
||||
if (IfWithDelete->getElse())
|
||||
if (IfWithDelete->hasElseStorage())
|
||||
return;
|
||||
// FIXME: generate fixit for this case.
|
||||
|
||||
const std::optional<Token> PrevTok = utils::lexer::getPreviousToken(
|
||||
IfWithDelete->getThen()->getBeginLoc(), *Result.SourceManager,
|
||||
Result.Context->getLangOpts());
|
||||
if (!PrevTok)
|
||||
return;
|
||||
|
||||
Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
|
||||
IfWithDelete->getBeginLoc(),
|
||||
utils::lexer::getPreviousToken(IfWithDelete->getThen()->getBeginLoc(),
|
||||
*Result.SourceManager,
|
||||
Result.Context->getLangOpts())
|
||||
.getLocation()));
|
||||
IfWithDelete->getBeginLoc(), PrevTok->getLocation()));
|
||||
|
||||
if (Compound) {
|
||||
Diag << FixItHint::CreateRemoval(
|
||||
|
||||
@ -157,8 +157,8 @@ declRanges(const DeclStmt *DS, const SourceManager &SM,
|
||||
if (Start.isInvalid() || Start.isMacroID())
|
||||
break;
|
||||
|
||||
const Token T = getPreviousToken(Start, SM, LangOpts);
|
||||
if (T.is(tok::l_paren)) {
|
||||
const std::optional<Token> T = getPreviousToken(Start, SM, LangOpts);
|
||||
if (T && T->is(tok::l_paren)) {
|
||||
Start = findPreviousTokenStart(Start, SM, LangOpts);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -21,16 +21,16 @@ namespace clang::tidy::readability {
|
||||
static SourceRange
|
||||
getFullInitRangeInclWhitespaces(SourceRange Range, const SourceManager &SM,
|
||||
const LangOptions &LangOpts) {
|
||||
const Token PrevToken =
|
||||
const std::optional<Token> PrevToken =
|
||||
utils::lexer::getPreviousToken(Range.getBegin(), SM, LangOpts, false);
|
||||
if (PrevToken.is(tok::unknown))
|
||||
if (!PrevToken)
|
||||
return Range;
|
||||
|
||||
if (PrevToken.isNot(tok::equal))
|
||||
return {PrevToken.getEndLoc(), Range.getEnd()};
|
||||
if (PrevToken->isNot(tok::equal))
|
||||
return {PrevToken->getEndLoc(), Range.getEnd()};
|
||||
|
||||
return getFullInitRangeInclWhitespaces(
|
||||
{PrevToken.getLocation(), Range.getEnd()}, SM, LangOpts);
|
||||
{PrevToken->getLocation(), Range.getEnd()}, SM, LangOpts);
|
||||
}
|
||||
|
||||
void RedundantMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
||||
|
||||
@ -19,15 +19,15 @@ namespace clang::tidy::utils::fixit {
|
||||
|
||||
FixItHint changeVarDeclToReference(const VarDecl &Var, ASTContext &Context) {
|
||||
SourceLocation AmpLocation = Var.getLocation();
|
||||
auto Token = utils::lexer::getPreviousToken(
|
||||
const std::optional<Token> Token = utils::lexer::getPreviousToken(
|
||||
AmpLocation, Context.getSourceManager(), Context.getLangOpts());
|
||||
|
||||
// For parameter packs the '&' must go before the '...' token
|
||||
if (Token.is(tok::ellipsis))
|
||||
return FixItHint::CreateInsertion(Token.getLocation(), "&");
|
||||
if (Token && Token->is(tok::ellipsis))
|
||||
return FixItHint::CreateInsertion(Token->getLocation(), "&");
|
||||
|
||||
if (!Token.is(tok::unknown))
|
||||
AmpLocation = Lexer::getLocForEndOfToken(Token.getLocation(), 0,
|
||||
if (Token)
|
||||
AmpLocation = Lexer::getLocForEndOfToken(Token->getLocation(), 0,
|
||||
Context.getSourceManager(),
|
||||
Context.getLangOpts());
|
||||
return FixItHint::CreateInsertion(AmpLocation, "&");
|
||||
@ -53,10 +53,9 @@ skipLParensBackwards(SourceLocation Start, const ASTContext &Context) {
|
||||
return std::nullopt;
|
||||
|
||||
auto PreviousTokenLParen = [&Start, &Context]() {
|
||||
Token T;
|
||||
T = lexer::getPreviousToken(Start, Context.getSourceManager(),
|
||||
Context.getLangOpts());
|
||||
return T.is(tok::l_paren);
|
||||
const std::optional<Token> T = lexer::getPreviousToken(
|
||||
Start, Context.getSourceManager(), Context.getLangOpts());
|
||||
return T && T->is(tok::l_paren);
|
||||
};
|
||||
|
||||
while (Start.isValid() && PreviousTokenLParen())
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
namespace clang::tidy::utils::lexer {
|
||||
|
||||
std::pair<Token, SourceLocation>
|
||||
std::pair<std::optional<Token>, SourceLocation>
|
||||
getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
|
||||
const LangOptions &LangOpts, bool SkipComments) {
|
||||
const std::optional<Token> Tok =
|
||||
@ -22,13 +22,13 @@ getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
|
||||
if (Tok.has_value())
|
||||
return {*Tok, Lexer::GetBeginningOfToken(Tok->getLocation(), SM, LangOpts)};
|
||||
|
||||
Token Token;
|
||||
Token.setKind(tok::unknown);
|
||||
return {Token, SourceLocation()};
|
||||
return {std::nullopt, SourceLocation()};
|
||||
}
|
||||
|
||||
Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
|
||||
const LangOptions &LangOpts, bool SkipComments) {
|
||||
std::optional<Token> getPreviousToken(SourceLocation Location,
|
||||
const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
bool SkipComments) {
|
||||
auto [Token, Start] =
|
||||
getPreviousTokenAndStart(Location, SM, LangOpts, SkipComments);
|
||||
return Token;
|
||||
|
||||
@ -21,10 +21,13 @@ class Stmt;
|
||||
|
||||
namespace tidy::utils::lexer {
|
||||
|
||||
/// Returns previous token or ``tok::unknown`` if not found.
|
||||
Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
|
||||
const LangOptions &LangOpts, bool SkipComments = true);
|
||||
std::pair<Token, SourceLocation>
|
||||
/// Returns previous token or ``std::nullopt`` if not found.
|
||||
std::optional<Token> getPreviousToken(SourceLocation Location,
|
||||
const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
bool SkipComments = true);
|
||||
|
||||
std::pair<std::optional<Token>, SourceLocation>
|
||||
getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
|
||||
const LangOptions &LangOpts, bool SkipComments = true);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user