================ @@ -0,0 +1,178 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TrailingCommaCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy { + +template <> +struct OptionEnumMapping<readability::TrailingCommaCheck::CommaPolicyKind> { + static llvm::ArrayRef< + std::pair<readability::TrailingCommaCheck::CommaPolicyKind, StringRef>> + getEnumMapping() { + static constexpr std::pair<readability::TrailingCommaCheck::CommaPolicyKind, + StringRef> + Mapping[] = { + {readability::TrailingCommaCheck::CommaPolicyKind::Append, + "Append"}, + {readability::TrailingCommaCheck::CommaPolicyKind::Remove, + "Remove"}, + {readability::TrailingCommaCheck::CommaPolicyKind::Ignore, + "Ignore"}, + }; + return {Mapping}; + } +}; + +} // namespace clang::tidy + +namespace clang::tidy::readability { + +static bool isSingleLine(SourceLocation Begin, SourceLocation End, + const SourceManager &SM) { + return SM.getExpansionLineNumber(Begin) == SM.getExpansionLineNumber(End); +} + +namespace { + +AST_POLYMORPHIC_MATCHER(isMacro, + AST_POLYMORPHIC_SUPPORTED_TYPES(EnumDecl, + InitListExpr)) { + return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID(); +} + +AST_MATCHER(EnumDecl, isEmptyEnum) { return Node.enumerators().empty(); } + +AST_MATCHER(InitListExpr, isEmptyInitList) { return Node.getNumInits() == 0; } + +} // namespace + +TrailingCommaCheck::TrailingCommaCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + SingleLineCommaPolicy( + Options.get("SingleLineCommaPolicy", CommaPolicyKind::Remove)), + MultiLineCommaPolicy( + Options.get("MultiLineCommaPolicy", CommaPolicyKind::Append)) {} + +void TrailingCommaCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "SingleLineCommaPolicy", SingleLineCommaPolicy); + Options.store(Opts, "MultiLineCommaPolicy", MultiLineCommaPolicy); +} + +void TrailingCommaCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + enumDecl(isDefinition(), unless(isEmptyEnum()), unless(isMacro())) + .bind("enum"), + this); + + Finder->addMatcher(initListExpr(unless(isEmptyInitList()), unless(isMacro())) + .bind("initlist"), + this); +} + +void TrailingCommaCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("enum")) + checkEnumDecl(Enum, Result); + else if (const auto *InitList = + Result.Nodes.getNodeAs<InitListExpr>("initlist")) + checkInitListExpr(InitList, Result); + else + llvm_unreachable("No matches found"); +} + +void TrailingCommaCheck::checkEnumDecl(const EnumDecl *Enum, + const MatchFinder::MatchResult &Result) { + const bool IsSingleLine = isSingleLine(Enum->getBeginLoc(), Enum->getEndLoc(), + *Result.SourceManager); + const CommaPolicyKind Policy = + IsSingleLine ? SingleLineCommaPolicy : MultiLineCommaPolicy; + + if (Policy == CommaPolicyKind::Ignore) + return; + + const EnumConstantDecl *LastEnumerator = nullptr; + for (const EnumConstantDecl *ECD : Enum->enumerators()) + LastEnumerator = ECD; ---------------- vbvictor wrote:
I think in this case we would have a bad `LastLok` to insert comma. Now I try to insert it "past last enum value", with this change, we will try to insert comma "before closing braces" that not seem ideal to me. I think looping over 1000-2000 elements is not a big deal compared to ast traversal. So better diagnostic locations are preferable. https://github.com/llvm/llvm-project/pull/173669 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
