10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 17 namespace readability {
20 ASTContext *Context,
const IfStmt *If) {
21 auto parents = Context->getParents(*If);
22 if (parents.size() != 1)
24 if (
const auto *PrecedingIf = parents[0].get<IfStmt>()) {
25 SourceLocation PreviousElseLoc = PrecedingIf->getElseLoc();
26 if (SM.getExpansionLineNumber(PreviousElseLoc) ==
27 SM.getExpansionLineNumber(If->getIfLoc()))
33 void MisleadingIndentationCheck::danglingElseCheck(
const SourceManager &SM,
36 SourceLocation IfLoc = If->getIfLoc();
37 SourceLocation ElseLoc = If->getElseLoc();
39 if (IfLoc.isMacroID() || ElseLoc.isMacroID())
42 if (SM.getExpansionLineNumber(If->getThen()->getEndLoc()) ==
43 SM.getExpansionLineNumber(ElseLoc))
47 for (
auto PrecedingIf =
getPrecedingIf(SM, Context, If); PrecedingIf;
49 IfLoc = PrecedingIf->getIfLoc();
51 if (SM.getExpansionColumnNumber(IfLoc) !=
52 SM.getExpansionColumnNumber(ElseLoc))
53 diag(ElseLoc,
"different indentation for 'if' and corresponding 'else'");
56 void MisleadingIndentationCheck::missingBracesCheck(
const SourceManager &SM,
57 const CompoundStmt *CStmt) {
58 const static StringRef StmtNames[] = {
"if",
"for",
"while"};
59 for (
unsigned int i = 0; i < CStmt->size() - 1; i++) {
60 const Stmt *CurrentStmt = CStmt->body_begin()[i];
61 const Stmt *Inner =
nullptr;
64 if (
const auto *CurrentIf = dyn_cast<IfStmt>(CurrentStmt)) {
67 CurrentIf->getElse() ? CurrentIf->getElse() : CurrentIf->getThen();
68 }
else if (
const auto *CurrentFor = dyn_cast<ForStmt>(CurrentStmt)) {
70 Inner = CurrentFor->getBody();
71 }
else if (
const auto *CurrentWhile = dyn_cast<WhileStmt>(CurrentStmt)) {
73 Inner = CurrentWhile->getBody();
78 if (isa<CompoundStmt>(Inner))
81 SourceLocation InnerLoc = Inner->getBeginLoc();
82 SourceLocation OuterLoc = CurrentStmt->getBeginLoc();
84 if (InnerLoc.isInvalid() || InnerLoc.isMacroID() || OuterLoc.isInvalid() ||
88 if (SM.getExpansionLineNumber(InnerLoc) ==
89 SM.getExpansionLineNumber(OuterLoc))
92 const Stmt *NextStmt = CStmt->body_begin()[i + 1];
93 SourceLocation NextLoc = NextStmt->getBeginLoc();
95 if (NextLoc.isInvalid() || NextLoc.isMacroID())
98 if (SM.getExpansionColumnNumber(InnerLoc) ==
99 SM.getExpansionColumnNumber(NextLoc)) {
100 diag(NextLoc,
"misleading indentation: statement is indented too deeply");
101 diag(OuterLoc,
"did you mean this line to be inside this '%0'",
103 << StmtNames[StmtKind];
108 void MisleadingIndentationCheck::registerMatchers(MatchFinder *Finder) {
109 Finder->addMatcher(ifStmt(hasElse(stmt())).bind(
"if"),
this);
111 compoundStmt(has(stmt(anyOf(ifStmt(), forStmt(), whileStmt()))))
116 void MisleadingIndentationCheck::check(
const MatchFinder::MatchResult &
Result) {
117 if (
const auto *If = Result.Nodes.getNodeAs<IfStmt>(
"if"))
118 danglingElseCheck(*Result.SourceManager, Result.Context, If);
120 if (
const auto *CStmt = Result.Nodes.getNodeAs<CompoundStmt>(
"compound"))
121 missingBracesCheck(*Result.SourceManager, CStmt);
static const IfStmt * getPrecedingIf(const SourceManager &SM, ASTContext *Context, const IfStmt *If)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result