20 filename = os.path.join(module_path,
'CMakeLists.txt')
21 with open(filename,
'r') as f:
24 cpp_file = check_name_camel + '.cpp'
28 if line.strip() == cpp_file:
31 print(
'Updating %s...' % filename)
32 with open(filename,
'wb')
as f:
36 cpp_line = line.strip().endswith(
'.cpp')
37 if (
not file_added)
and (cpp_line
or cpp_found):
39 if (line.strip() > cpp_file)
or (
not cpp_line):
40 f.write(
' ' + cpp_file +
'\n')
48 def write_header(module_path, module, check_name, check_name_camel):
49 check_name_dashes = module +
'-' + check_name
50 filename = os.path.join(module_path, check_name_camel) +
'.h'
51 print(
'Creating %s...' % filename)
52 with open(filename,
'wb')
as f:
53 header_guard = (
'LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_' + module.upper() +
54 '_' + check_name.upper().replace(
'-',
'_') +
'_H')
56 f.write(os.path.basename(filename))
57 f.write(
' - clang-tidy')
58 f.write(
'-' * max(0, 43 - len(os.path.basename(filename))))
59 f.write(
'*- C++ -*-===//')
62 // The LLVM Compiler Infrastructure
64 // This file is distributed under the University of Illinois Open Source
65 // License. See LICENSE.TXT for details.
67 //===----------------------------------------------------------------------===//
69 #ifndef %(header_guard)s
70 #define %(header_guard)s
72 #include "../ClangTidy.h"
76 namespace %(module)s {
78 /// FIXME: Write a short description.
80 /// For the user-facing documentation see:
81 /// http://clang.llvm.org/extra/clang-tidy/checks/%(check_name_dashes)s.html
82 class %(check_name)s : public ClangTidyCheck {
84 %(check_name)s(StringRef Name, ClangTidyContext *Context)
85 : ClangTidyCheck(Name, Context) {}
86 void registerMatchers(ast_matchers::MatchFinder *Finder) override;
87 void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
90 } // namespace %(module)s
94 #endif // %(header_guard)s
95 """ % {
'header_guard': header_guard,
96 'check_name': check_name_camel,
97 'check_name_dashes': check_name_dashes,
103 filename = os.path.join(module_path, check_name_camel) +
'.cpp'
104 print(
'Creating %s...' % filename)
105 with open(filename,
'wb')
as f:
107 f.write(os.path.basename(filename))
108 f.write(
' - clang-tidy')
109 f.write(
'-' * max(0, 52 - len(os.path.basename(filename))))
113 // The LLVM Compiler Infrastructure
115 // This file is distributed under the University of Illinois Open Source
116 // License. See LICENSE.TXT for details.
118 //===----------------------------------------------------------------------===//
120 #include "%(check_name)s.h"
121 #include "clang/AST/ASTContext.h"
122 #include "clang/ASTMatchers/ASTMatchFinder.h"
124 using namespace clang::ast_matchers;
128 namespace %(module)s {
130 void %(check_name)s::registerMatchers(MatchFinder *Finder) {
131 // FIXME: Add matchers.
132 Finder->addMatcher(functionDecl().bind("x"), this);
135 void %(check_name)s::check(const MatchFinder::MatchResult &Result) {
136 // FIXME: Add callback implementation.
137 const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x");
138 if (MatchedDecl->getName().startswith("awesome_"))
140 diag(MatchedDecl->getLocation(), "function '%%0' is insufficiently awesome")
141 << MatchedDecl->getName()
142 << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
145 } // namespace %(module)s
148 """ % {
'check_name': check_name_camel,
154 modulecpp = filter(
lambda p: p.lower() == module.lower() +
"tidymodule.cpp", os.listdir(module_path))[0]
155 filename = os.path.join(module_path, modulecpp)
156 with open(filename,
'r') as f:
157 lines = f.readlines()
159 print('Updating %s...' % filename)
160 with open(filename,
'wb')
as f:
164 check_decl = (
' CheckFactories.registerCheck<' + check_name_camel +
165 '>(\n "' + module +
'-' + check_name +
'");\n')
169 match = re.search(
'#include "(.*)"', line)
172 if match.group(1) > check_name_camel:
174 f.write(
'#include "' + check_name_camel +
'.h"\n')
177 f.write(
'#include "' + check_name_camel +
'.h"\n')
180 if line.strip() ==
'}':
184 match = re.search(
'registerCheck<(.*)>', line)
185 if match
and match.group(1) > check_name_camel:
193 check_name_dashes = module +
'-' + check_name
194 filename = os.path.normpath(
195 os.path.join(module_path,
'../../test/clang-tidy',
196 check_name_dashes +
'.cpp'))
197 print(
'Creating %s...' % filename)
198 with open(filename,
'wb')
as f:
200 """// RUN: %%check_clang_tidy %%s %(check_name_dashes)s %%t
202 // FIXME: Add something that triggers the check here.
204 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [%(check_name_dashes)s]
206 // FIXME: Verify the applied fix.
207 // * Make the CHECK patterns specific enough and try to make verified lines
208 // unique to avoid incorrect matches.
209 // * Use {{}} for regular expressions.
210 // CHECK-FIXES: {{^}}void awesome_f();{{$}}
212 // FIXME: Add something that doesn't trigger the check here.
214 """ % {
"check_name_dashes" : check_name_dashes})
218 docs_dir = os.path.join(module_path,
'../../docs/clang-tidy/checks')
219 filename = os.path.normpath(os.path.join(docs_dir,
'list.rst'))
220 with open(filename,
'r') as f:
221 lines = f.readlines()
223 lambda s: s.endswith(
'.rst')
and s !=
'list.rst',
224 os.listdir(docs_dir))
227 def format_link(doc_file):
228 check_name = doc_file.replace(
'.rst',
'')
229 with open(os.path.join(docs_dir, doc_file),
'r') as doc:
230 match = re.search('.*:http-equiv=refresh: \d+;URL=(.*).html.*', doc.read())
232 return ' %(check)s (redirects to %(target)s) <%(check)s>\n' % {
233 'check' : check_name,
'target' : match.group(1) }
234 return ' %s\n' % check_name
236 checks = map(format_link, doc_files)
238 print(
'Updating %s...' % filename)
239 with open(filename,
'wb')
as f:
242 if line.startswith(
'.. toctree::'):
248 check_name_dashes = module +
'-' + check_name
249 filename = os.path.normpath(
250 os.path.join(module_path,
'../../docs/clang-tidy/checks/',
251 check_name_dashes +
'.rst'))
252 print(
'Creating %s...' % filename)
253 with open(filename,
'wb')
as f:
255 """.. title:: clang-tidy - %(check_name_dashes)s
257 %(check_name_dashes)s
260 FIXME: Describe what patterns does the check detect and why. Give examples.
261 """ % {
"check_name_dashes" : check_name_dashes,
262 "underline" :
"=" * len(check_name_dashes)})
265 if len(sys.argv) != 3:
266 print 'Usage: add_new_check.py <module> <check>, e.g.\n'
267 print 'add_new_check.py misc awesome-functions\n'
271 check_name = sys.argv[2]
272 check_name_camel =
''.join(map(
lambda elem: elem.capitalize(),
273 check_name.split(
'-'))) +
'Check'
274 clang_tidy_path = os.path.dirname(sys.argv[0])
275 module_path = os.path.join(clang_tidy_path, module)
279 write_header(module_path, module, check_name, check_name_camel)
281 adapt_module(module_path, module, check_name, check_name_camel)
285 print(
'Done. Now it\'s your turn!')
287 if __name__ ==
'__main__':