Add NamespaceCommentCheck to the Google module.

Summary:
This uses a bit hacky way to set the defaults for the spaces before
comments, but it's also one of the simplest ways. Fixed a bug with how the
SpacesBeforeComments option was used.

Reviewers: djasper

Reviewed By: djasper

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D5410

llvm-svn: 218240
This commit is contained in:
Alexander Kornienko 2014-09-22 10:41:39 +00:00
parent 3a3bf0bbe3
commit 33fc3db9a1
14 changed files with 160 additions and 98 deletions

View File

@ -27,4 +27,5 @@ add_subdirectory(tool)
add_subdirectory(llvm)
add_subdirectory(google)
add_subdirectory(misc)
add_subdirectory(readability)
add_subdirectory(utils)

View File

@ -11,6 +11,6 @@ CLANG_LEVEL := ../../..
LIBRARYNAME := clangTidy
include $(CLANG_LEVEL)/../../Makefile.config
DIRS = utils llvm google misc tool
DIRS = utils readability llvm google misc tool
include $(CLANG_LEVEL)/Makefile

View File

@ -21,6 +21,7 @@
#include "TodoCommentCheck.h"
#include "UnnamedNamespaceInHeaderCheck.h"
#include "UsingNamespaceDirectiveCheck.h"
#include "../readability/NamespaceCommentCheck.h"
using namespace clang::ast_matchers;
@ -52,6 +53,8 @@ public:
"google-readability-function");
CheckFactories.registerCheck<readability::TodoCommentCheck>(
"google-readability-todo");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"google-readability-namespace-comments");
}
};

View File

@ -4,7 +4,6 @@ add_clang_library(clangTidyLLVMModule
HeaderGuardCheck.cpp
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
NamespaceCommentCheck.cpp
TwineLocalCheck.cpp
LINK_LIBS
@ -13,6 +12,7 @@ add_clang_library(clangTidyLLVMModule
clangBasic
clangLex
clangTidy
clangTidyReadability
clangTidyUtils
clangTooling
)

View File

@ -12,7 +12,7 @@
#include "../ClangTidyModuleRegistry.h"
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
#include "NamespaceCommentCheck.h"
#include "../readability/NamespaceCommentCheck.h"
#include "TwineLocalCheck.h"
namespace clang {
@ -23,7 +23,7 @@ public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<LLVMHeaderGuardCheck>("llvm-header-guard");
CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
CheckFactories.registerCheck<NamespaceCommentCheck>(
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"llvm-namespace-comment");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
}

View File

@ -0,0 +1,13 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyReadability
NamespaceCommentCheck.cpp
LINK_LIBS
clangAST
clangASTMatchers
clangBasic
clangLex
clangTidy
clangTooling
)

View File

@ -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

View File

@ -17,6 +17,7 @@ using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace readability {
NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
ClangTidyContext *Context)
@ -25,7 +26,8 @@ NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
"namespace( +([a-zA-Z0-9_]+))? *(\\*/)?$",
llvm::Regex::IgnoreCase),
ShortNamespaceLines(Options.get("ShortNamespaceLines", 1u)),
SpacesBeforeComments(Options.get("SpacesBeforeComments", 1u)) {}
SpacesBeforeComments(Options.get("SpacesBeforeComments",
Name.startswith("google") ? 2u : 1u)) {}
void NamespaceCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "ShortNamespaceLines", ShortNamespaceLines);
@ -42,12 +44,10 @@ bool locationsInSameFile(const SourceManager &Sources, SourceLocation Loc1,
Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
}
std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak,
unsigned SpacesBeforeComments) {
std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak) {
std::string Fix = "// namespace";
if (!ND->isAnonymousNamespace())
Fix.append(std::string(SpacesBeforeComments, ' '))
.append(ND->getNameAsString());
Fix.append(" ").append(ND->getNameAsString());
if (InsertLineBreak)
Fix.append("\n");
return Fix;
@ -105,8 +105,7 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
diag(Loc, "namespace closing comment refers to a wrong namespace '%0'")
<< NamespaceNameInComment
<< FixItHint::CreateReplacement(
OldCommentRange,
getNamespaceComment(ND, NeedLineBreak, SpacesBeforeComments));
OldCommentRange, getNamespaceComment(ND, NeedLineBreak));
return;
}
@ -118,10 +117,11 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
}
diag(ND->getLocation(), "namespace not terminated with a closing comment")
<< FixItHint::CreateInsertion(
AfterRBrace,
" " + getNamespaceComment(ND, NeedLineBreak, SpacesBeforeComments));
<< FixItHint::CreateInsertion(AfterRBrace,
std::string(SpacesBeforeComments, ' ') +
getNamespaceComment(ND, NeedLineBreak));
}
} // namespace readability
} // namespace tidy
} // namespace clang

View File

@ -7,18 +7,20 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_NAMESPACE_COMMENT_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_NAMESPACE_COMMENT_CHECK_H
#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.
///
/// see: http://llvm.org/docs/CodingStandards.html#namespace-indentation
/// 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);
@ -33,7 +35,8 @@ private:
const unsigned SpacesBeforeComments;
};
} // namespace readability
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_NAMESPACE_COMMENT_CHECK_H
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H

View File

@ -0,0 +1,15 @@
// RUN: $(dirname %s)/check_clang_tidy_fix.sh %s google-readability-namespace-comments %t
// REQUIRES: shell
// CHECK-MESSAGES: :[[@LINE+2]]:11: warning: namespace not terminated with a closing comment [google-readability-namespace-comments]
// CHECK-MESSAGES: :[[@LINE+2]]:11: warning: namespace not terminated with a closing comment [google-readability-namespace-comments]
namespace n1 {
namespace n2 {
}
}
// CHECK-FIXES: } // namespace n2
// CHECK-FIXES: } // namespace n1
namespace short1 { namespace short2 { } }

View File

@ -10,6 +10,7 @@ add_extra_unittest(ClangTidyTests
ClangTidyDiagnosticConsumerTest.cpp
ClangTidyOptionsTest.cpp
LLVMModuleTest.cpp
ReadabilityChecksTest.cpp
GoogleModuleTest.cpp
MiscModuleTest.cpp)
@ -22,5 +23,6 @@ target_link_libraries(ClangTidyTests
clangTidyGoogleModule
clangTidyLLVMModule
clangTidyMiscModule
clangTidyReadability
clangTooling
)

View File

@ -1,91 +1,12 @@
#include "ClangTidyTest.h"
#include "llvm/HeaderGuardCheck.h"
#include "llvm/IncludeOrderCheck.h"
#include "llvm/NamespaceCommentCheck.h"
#include "gtest/gtest.h"
namespace clang {
namespace tidy {
namespace test {
TEST(NamespaceCommentCheckTest, Basic) {
EXPECT_EQ("namespace i {\n} // namespace i",
runCheckOnCode<NamespaceCommentCheck>("namespace i {\n}"));
EXPECT_EQ("namespace {\n} // namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n}"));
EXPECT_EQ(
"namespace i { namespace j {\n} // namespace j\n } // namespace i",
runCheckOnCode<NamespaceCommentCheck>("namespace i { namespace j {\n} }"));
}
TEST(NamespaceCommentCheckTest, SingleLineNamespaces) {
EXPECT_EQ(
"namespace i { namespace j { } }",
runCheckOnCode<NamespaceCommentCheck>("namespace i { namespace j { } }"));
}
TEST(NamespaceCommentCheckTest, CheckExistingComments) {
EXPECT_EQ("namespace i { namespace j {\n"
"} /* namespace j */ } // namespace i\n"
" /* random comment */",
runCheckOnCode<NamespaceCommentCheck>(
"namespace i { namespace j {\n"
"} /* namespace j */ } /* random comment */"));
EXPECT_EQ("namespace {\n"
"} // namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // namespace"));
EXPECT_EQ("namespace {\n"
"} //namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} //namespace"));
EXPECT_EQ("namespace {\n"
"} // anonymous namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // anonymous namespace"));
EXPECT_EQ(
"namespace My_NameSpace123 {\n"
"} // namespace My_NameSpace123",
runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n"
"} // namespace My_NameSpace123"));
EXPECT_EQ(
"namespace My_NameSpace123 {\n"
"} //namespace My_NameSpace123",
runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n"
"} //namespace My_NameSpace123"));
EXPECT_EQ("namespace My_NameSpace123 {\n"
"} // end namespace My_NameSpace123",
runCheckOnCode<NamespaceCommentCheck>(
"namespace My_NameSpace123 {\n"
"} // end namespace My_NameSpace123"));
// Understand comments only on the same line.
EXPECT_EQ("namespace {\n"
"} // namespace\n"
"// namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"}\n"
"// namespace"));
// Leave unknown comments.
EXPECT_EQ("namespace {\n"
"} // namespace // random text",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // random text"));
}
TEST(NamespaceCommentCheckTest, FixWrongComments) {
EXPECT_EQ("namespace i { namespace jJ0_ {\n"
"} // namespace jJ0_\n"
" } // namespace i\n"
" /* random comment */",
runCheckOnCode<NamespaceCommentCheck>(
"namespace i { namespace jJ0_ {\n"
"} /* namespace qqq */ } /* random comment */"));
EXPECT_EQ("namespace {\n"
"} // namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // namespace asdf"));
}
// FIXME: It seems this might be incompatible to dos path. Investigating.
#if !defined(_WIN32)
static std::string runHeaderGuardCheck(StringRef Code, const Twine &Filename,

View File

@ -14,7 +14,8 @@ TESTNAME = ClangTidy
LINK_COMPONENTS := asmparser bitreader support MC MCParser option \
TransformUtils
USEDLIBS = clangTidy.a clangTidyLLVMModule.a clangTidyGoogleModule.a \
clangTidyMiscModule.a clangTidy.a clangTidyUtils.a \
clangTidyMiscModule.a clangTidyReadability.a clangTidy.a \
clangTidyUtils.a \
clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
clangStaticAnalyzerCore.a \
clangFormat.a clangTooling.a clangFrontend.a clangSerialization.a \

View File

@ -0,0 +1,91 @@
#include "ClangTidyTest.h"
#include "readability/NamespaceCommentCheck.h"
#include "gtest/gtest.h"
namespace clang {
namespace tidy {
namespace test {
using readability::NamespaceCommentCheck;
TEST(NamespaceCommentCheckTest, Basic) {
EXPECT_EQ("namespace i {\n} // namespace i",
runCheckOnCode<NamespaceCommentCheck>("namespace i {\n}"));
EXPECT_EQ("namespace {\n} // namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n}"));
EXPECT_EQ(
"namespace i { namespace j {\n} // namespace j\n } // namespace i",
runCheckOnCode<NamespaceCommentCheck>("namespace i { namespace j {\n} }"));
}
TEST(NamespaceCommentCheckTest, SingleLineNamespaces) {
EXPECT_EQ(
"namespace i { namespace j { } }",
runCheckOnCode<NamespaceCommentCheck>("namespace i { namespace j { } }"));
}
TEST(NamespaceCommentCheckTest, CheckExistingComments) {
EXPECT_EQ("namespace i { namespace j {\n"
"} /* namespace j */ } // namespace i\n"
" /* random comment */",
runCheckOnCode<NamespaceCommentCheck>(
"namespace i { namespace j {\n"
"} /* namespace j */ } /* random comment */"));
EXPECT_EQ("namespace {\n"
"} // namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // namespace"));
EXPECT_EQ("namespace {\n"
"} //namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} //namespace"));
EXPECT_EQ("namespace {\n"
"} // anonymous namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // anonymous namespace"));
EXPECT_EQ(
"namespace My_NameSpace123 {\n"
"} // namespace My_NameSpace123",
runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n"
"} // namespace My_NameSpace123"));
EXPECT_EQ(
"namespace My_NameSpace123 {\n"
"} //namespace My_NameSpace123",
runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n"
"} //namespace My_NameSpace123"));
EXPECT_EQ("namespace My_NameSpace123 {\n"
"} // end namespace My_NameSpace123",
runCheckOnCode<NamespaceCommentCheck>(
"namespace My_NameSpace123 {\n"
"} // end namespace My_NameSpace123"));
// Understand comments only on the same line.
EXPECT_EQ("namespace {\n"
"} // namespace\n"
"// namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"}\n"
"// namespace"));
// Leave unknown comments.
EXPECT_EQ("namespace {\n"
"} // namespace // random text",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // random text"));
}
TEST(NamespaceCommentCheckTest, FixWrongComments) {
EXPECT_EQ("namespace i { namespace jJ0_ {\n"
"} // namespace jJ0_\n"
" } // namespace i\n"
" /* random comment */",
runCheckOnCode<NamespaceCommentCheck>(
"namespace i { namespace jJ0_ {\n"
"} /* namespace qqq */ } /* random comment */"));
EXPECT_EQ("namespace {\n"
"} // namespace",
runCheckOnCode<NamespaceCommentCheck>("namespace {\n"
"} // namespace asdf"));
}
} // namespace test
} // namespace tidy
} // namespace clang