blob: 32766731586356c3dc1689c6d84ccf4a6ae6bb0c [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
Alexander Kornienkocb9272f2014-02-27 13:14:51 +000027void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
Daniel Jasperd07c8402013-07-29 08:19:24 +000028 Finder->addMatcher(namespaceDecl().bind("namespace"), this);
29}
30
31void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
32 const NamespaceDecl *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
33 Token Tok;
34 SourceLocation Loc = ND->getRBraceLoc().getLocWithOffset(1);
35 while (Lexer::getRawToken(Loc, Tok, *Result.SourceManager,
36 Result.Context->getLangOpts())) {
37 Loc = Loc.getLocWithOffset(1);
38 }
39 // FIXME: Check that this namespace is "long".
40 if (Tok.is(tok::comment)) {
41 // FIXME: Check comment content.
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000042 // FIXME: Check comment placement on the same line.
Daniel Jasperd07c8402013-07-29 08:19:24 +000043 return;
44 }
45 std::string Fix = " // namespace";
46 if (!ND->isAnonymousNamespace())
47 Fix = Fix.append(" ").append(ND->getNameAsString());
48
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000049 diag(ND->getLocation(), "namespace not terminated with a closing comment")
Daniel Jasperd07c8402013-07-29 08:19:24 +000050 << FixItHint::CreateInsertion(ND->getRBraceLoc().getLocWithOffset(1),
51 Fix);
52}
53
54namespace {
55class IncludeOrderPPCallbacks : public PPCallbacks {
56public:
Alexander Kornienkocb9272f2014-02-27 13:14:51 +000057 explicit IncludeOrderPPCallbacks(IncludeOrderCheck &Check) : Check(Check) {}
Daniel Jasperd07c8402013-07-29 08:19:24 +000058
Alexander Kornienkocb9272f2014-02-27 13:14:51 +000059 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
60 StringRef FileName, bool IsAngled,
61 CharSourceRange FilenameRange, const FileEntry *File,
62 StringRef SearchPath, StringRef RelativePath,
Craig Toppera3dbe842014-03-02 10:20:11 +000063 const Module *Imported) override {
Daniel Jasperd07c8402013-07-29 08:19:24 +000064 // FIXME: This is a dummy implementation to show how to get at preprocessor
65 // information. Implement a real include order check.
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000066 Check.diag(HashLoc, "This is an include");
Daniel Jasperd07c8402013-07-29 08:19:24 +000067 }
68
69private:
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000070 IncludeOrderCheck &Check;
Daniel Jasperd07c8402013-07-29 08:19:24 +000071};
72} // namespace
73
74void IncludeOrderCheck::registerPPCallbacks(CompilerInstance &Compiler) {
75 Compiler.getPreprocessor()
Alexander Kornienko41bfe8d2014-01-13 10:50:51 +000076 .addPPCallbacks(new IncludeOrderPPCallbacks(*this));
Daniel Jasperd07c8402013-07-29 08:19:24 +000077}
78
79class LLVMModule : public ClangTidyModule {
80public:
Alexander Kornienko21f3b772014-03-05 13:01:24 +000081 void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
Daniel Jasperd07c8402013-07-29 08:19:24 +000082 CheckFactories.addCheckFactory(
83 "llvm-include-order", new ClangTidyCheckFactory<IncludeOrderCheck>());
84 CheckFactories.addCheckFactory(
85 "llvm-namespace-comment",
86 new ClangTidyCheckFactory<NamespaceCommentCheck>());
87 }
88};
89
90// Register the LLVMTidyModule using this statically initialized variable.
91static ClangTidyModuleRegistry::Add<LLVMModule> X("llvm-module",
92 "Adds LLVM lint checks.");
93
94// This anchor is used to force the linker to link in the generated object file
95// and thus register the LLVMModule.
96volatile int LLVMModuleAnchorSource = 0;
97
98} // namespace tidy
99} // namespace clang