================ @@ -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; ---------------- localspook wrote:
To elaborate, I'm proposing something like ```cpp SourceLocation LastEnumLoc = lexer::utils::getPreviousToken(Enum->getBraceRange().getEnd()/*.getLocWithOffset(-1)?*/, *Result.SourceManager, getLangOpts()).getLocation(); ``` I believe this gives the same result as the existing code, but without walking the enumerators, and without the extra logic to handle cases where the last enumerator has an initializer or an attribute. https://github.com/llvm/llvm-project/pull/173669 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
