blob: 137bb6c41ce683af17da9282aa5d013bff7f8955 [file] [log] [blame]
Daniel Jasperd07c8402013-07-29 08:19:24 +00001//===--- LLVMTidyModule.cpp - clang-tidy ----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "LLVMTidyModule.h"
11#include "../ClangTidy.h"
12#include "../ClangTidyModule.h"
13#include "../ClangTidyModuleRegistry.h"
14#include "clang/AST/ASTContext.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000015#include "clang/ASTMatchers/ASTMatchFinder.h"
Chandler Carruth85e6e872014-01-07 20:05:01 +000016#include "clang/ASTMatchers/ASTMatchers.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000017#include "clang/Frontend/CompilerInstance.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000018#include "clang/Lex/PPCallbacks.h"
Chandler Carruth85e6e872014-01-07 20:05:01 +000019#include "clang/Lex/Preprocessor.h"
Daniel Jasperd07c8402013-07-29 08:19:24 +000020#include "llvm/Support/raw_ostream.h"
21
22using namespace clang::ast_matchers;
23
24namespace clang {
25namespace tidy {
26
27void
28NamespaceCommentCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
29 Finder->addMatcher(namespaceDecl().bind("namespace"), this);
30}
31
32void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
33 const NamespaceDecl *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
34 Token Tok;
35 SourceLocation Loc = ND->getRBraceLoc().getLocWithOffset(1);
36 while (Lexer::getRawToken(Loc, Tok, *Result.SourceManager,
37 Result.Context->getLangOpts())) {
38 Loc = Loc.getLocWithOffset(1);
39 }
40 // FIXME: Check that this namespace is "long".
41 if (Tok.is(tok::comment)) {
42 // FIXME: Check comment content.
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000043 // FIXME: Check comment placement on the same line.
Daniel Jasperd07c8402013-07-29 08:19:24 +000044 return;
45 }
46 std::string Fix = " // namespace";
47 if (!ND->isAnonymousNamespace())
48 Fix = Fix.append(" ").append(ND->getNameAsString());
49
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000050 diag(ND->getLocation(), "namespace not terminated with a closing comment")
Daniel Jasperd07c8402013-07-29 08:19:24 +000051 << FixItHint::CreateInsertion(ND->getRBraceLoc().getLocWithOffset(1),
52 Fix);
53}
54
55namespace {
56class IncludeOrderPPCallbacks : public PPCallbacks {
57public:
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000058 explicit IncludeOrderPPCallbacks(IncludeOrderCheck &Check)
59 : Check(Check) {}
Daniel Jasperd07c8402013-07-29 08:19:24 +000060
61 virtual void InclusionDirective(SourceLocation HashLoc,
62 const Token &IncludeTok, StringRef FileName,
63 bool IsAngled, CharSourceRange FilenameRange,
64 const FileEntry *File, StringRef SearchPath,
65 StringRef RelativePath,
66 const Module *Imported) {
67 // FIXME: This is a dummy implementation to show how to get at preprocessor
68 // information. Implement a real include order check.
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000069 Check.diag(HashLoc, "This is an include");
Daniel Jasperd07c8402013-07-29 08:19:24 +000070 }
71
72private:
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000073 IncludeOrderCheck &Check;
Daniel Jasperd07c8402013-07-29 08:19:24 +000074};
75} // namespace
76
77void IncludeOrderCheck::registerPPCallbacks(CompilerInstance &Compiler) {
78 Compiler.getPreprocessor()
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000079 .addPPCallbacks(new IncludeOrderPPCallbacks(*this));
Daniel Jasperd07c8402013-07-29 08:19:24 +000080}
81
82class LLVMModule : public ClangTidyModule {
83public:
84 virtual ~LLVMModule() {}
85
86 virtual void addCheckFactories(ClangTidyCheckFactories &CheckFactories) {
87 CheckFactories.addCheckFactory(
88 "llvm-include-order", new ClangTidyCheckFactory<IncludeOrderCheck>());
89 CheckFactories.addCheckFactory(
90 "llvm-namespace-comment",
91 new ClangTidyCheckFactory<NamespaceCommentCheck>());
92 }
93};
94
95// Register the LLVMTidyModule using this statically initialized variable.
96static ClangTidyModuleRegistry::Add<LLVMModule> X("llvm-module",
97 "Adds LLVM lint checks.");
98
99// This anchor is used to force the linker to link in the generated object file
100// and thus register the LLVMModule.
101volatile int LLVMModuleAnchorSource = 0;
102
103} // namespace tidy
104} // namespace clang