summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/readability
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/readability')
-rw-r--r--clang-tools-extra/clang-tidy/readability/CMakeLists.txt13
-rw-r--r--clang-tools-extra/clang-tidy/readability/Makefile12
-rw-r--r--clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp127
-rw-r--r--clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h42
4 files changed, 194 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
new file mode 100644
index 00000000000..dc805cb219c
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyReadability
+ NamespaceCommentCheck.cpp
+
+ LINK_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangLex
+ clangTidy
+ clangTooling
+ )
diff --git a/clang-tools-extra/clang-tidy/readability/Makefile b/clang-tools-extra/clang-tidy/readability/Makefile
new file mode 100644
index 00000000000..7d9e2acec7e
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/Makefile
@@ -0,0 +1,12 @@
+##===- clang-tidy/readability/Makefile ---------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+CLANG_LEVEL := ../../../..
+LIBRARYNAME := clangTidyReadability
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
new file mode 100644
index 00000000000..da29c59f5b8
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
@@ -0,0 +1,127 @@
+//===--- NamespaceCommentCheck.cpp - clang-tidy ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NamespaceCommentCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
+ "namespace( +([a-zA-Z0-9_]+))? *(\\*/)?$",
+ llvm::Regex::IgnoreCase),
+ ShortNamespaceLines(Options.get("ShortNamespaceLines", 1u)),
+ SpacesBeforeComments(Options.get("SpacesBeforeComments",
+ Name.startswith("google") ? 2u : 1u)) {}
+
+void NamespaceCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "ShortNamespaceLines", ShortNamespaceLines);
+ Options.store(Opts, "SpacesBeforeComments", SpacesBeforeComments);
+}
+
+void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(namespaceDecl().bind("namespace"), this);
+}
+
+bool locationsInSameFile(const SourceManager &Sources, SourceLocation Loc1,
+ SourceLocation Loc2) {
+ return Loc1.isFileID() && Loc2.isFileID() &&
+ Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
+}
+
+std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak) {
+ std::string Fix = "// namespace";
+ if (!ND->isAnonymousNamespace())
+ Fix.append(" ").append(ND->getNameAsString());
+ if (InsertLineBreak)
+ Fix.append("\n");
+ return Fix;
+}
+
+void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
+ const NamespaceDecl *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
+ const SourceManager &Sources = *Result.SourceManager;
+
+ if (!locationsInSameFile(Sources, ND->getLocStart(), ND->getRBraceLoc()))
+ return;
+
+ // Don't require closing comments for namespaces spanning less than certain
+ // number of lines.
+ unsigned StartLine = Sources.getSpellingLineNumber(ND->getLocStart());
+ unsigned EndLine = Sources.getSpellingLineNumber(ND->getRBraceLoc());
+ if (EndLine - StartLine + 1 <= ShortNamespaceLines)
+ return;
+
+ // Find next token after the namespace closing brace.
+ SourceLocation AfterRBrace = ND->getRBraceLoc().getLocWithOffset(1);
+ SourceLocation Loc = AfterRBrace;
+ Token Tok;
+ // Skip whitespace until we find the next token.
+ while (Lexer::getRawToken(Loc, Tok, Sources, Result.Context->getLangOpts())) {
+ Loc = Loc.getLocWithOffset(1);
+ }
+ if (!locationsInSameFile(Sources, ND->getRBraceLoc(), Loc))
+ return;
+
+ bool NextTokenIsOnSameLine = Sources.getSpellingLineNumber(Loc) == EndLine;
+ // If we insert a line comment before the token in the same line, we need
+ // to insert a line break.
+ bool NeedLineBreak = NextTokenIsOnSameLine && Tok.isNot(tok::eof);
+
+ // Try to find existing namespace closing comment on the same line.
+ if (Tok.is(tok::comment) && NextTokenIsOnSameLine) {
+ StringRef Comment(Sources.getCharacterData(Loc), Tok.getLength());
+ SmallVector<StringRef, 6> Groups;
+ if (NamespaceCommentPattern.match(Comment, &Groups)) {
+ StringRef NamespaceNameInComment = Groups.size() >= 6 ? Groups[5] : "";
+
+ // Check if the namespace in the comment is the same.
+ if ((ND->isAnonymousNamespace() && NamespaceNameInComment.empty()) ||
+ ND->getNameAsString() == NamespaceNameInComment) {
+ // FIXME: Maybe we need a strict mode, where we always fix namespace
+ // comments with different format.
+ return;
+ }
+
+ // Otherwise we need to fix the comment.
+ NeedLineBreak = Comment.startswith("/*");
+ CharSourceRange OldCommentRange = CharSourceRange::getCharRange(
+ SourceRange(Loc, Loc.getLocWithOffset(Tok.getLength())));
+ diag(Loc, "namespace closing comment refers to a wrong namespace '%0'")
+ << NamespaceNameInComment
+ << FixItHint::CreateReplacement(
+ OldCommentRange, getNamespaceComment(ND, NeedLineBreak));
+ return;
+ }
+
+ // This is not a recognized form of a namespace closing comment.
+ // Leave line comment on the same line. Move block comment to the next line,
+ // as it can be multi-line or there may be other tokens behind it.
+ if (Comment.startswith("//"))
+ NeedLineBreak = false;
+ }
+
+ diag(ND->getLocation(), "namespace not terminated with a closing comment")
+ << FixItHint::CreateInsertion(AfterRBrace,
+ std::string(SpacesBeforeComments, ' ') +
+ getNamespaceComment(ND, NeedLineBreak));
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
new file mode 100644
index 00000000000..b72eb65150d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
@@ -0,0 +1,42 @@
+//===--- NamespaceCommentCheck.h - clang-tidy -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
+
+#include "../ClangTidy.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \brief Checks that long namespaces have a closing comment.
+///
+/// http://llvm.org/docs/CodingStandards.html#namespace-indentation
+/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Namespaces
+class NamespaceCommentCheck : public ClangTidyCheck {
+public:
+ NamespaceCommentCheck(StringRef Name, ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+ llvm::Regex NamespaceCommentPattern;
+ const unsigned ShortNamespaceLines;
+ const unsigned SpacesBeforeComments;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
OpenPOWER on IntegriCloud