[clang-tools-extra] r318905 - clang-tidy/rename_check.py: support for moving between modules
Alexander Kornienko via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 23 04:08:53 PST 2017
Author: alexfh
Date: Thu Nov 23 04:08:53 2017
New Revision: 318905
URL: http://llvm.org/viewvc/llvm-project?rev=318905&view=rev
Log:
clang-tidy/rename_check.py: support for moving between modules
Modified:
clang-tools-extra/trunk/clang-tidy/rename_check.py
Modified: clang-tools-extra/trunk/clang-tidy/rename_check.py
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/rename_check.py?rev=318905&r1=318904&r2=318905&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/rename_check.py (original)
+++ clang-tools-extra/trunk/clang-tidy/rename_check.py Thu Nov 23 04:08:53 2017
@@ -9,9 +9,10 @@
#
#===------------------------------------------------------------------------===#
-import os
-import glob
import argparse
+import glob
+import os
+import re
def replaceInFile(fileName, sFrom, sTo):
@@ -25,7 +26,7 @@ def replaceInFile(fileName, sFrom, sTo):
return
txt = txt.replace(sFrom, sTo)
- print("Replace '%s' -> '%s' in '%s'" % (sFrom, sTo, fileName))
+ print("Replacing '%s' -> '%s' in '%s'..." % (sFrom, sTo, fileName))
with open(fileName, "w") as f:
f.write(txt)
@@ -47,13 +48,28 @@ def generateCommentLineSource(filename):
def fileRename(fileName, sFrom, sTo):
- if sFrom not in fileName:
+ if sFrom not in fileName or sFrom == sTo:
return fileName
newFileName = fileName.replace(sFrom, sTo)
- print("Rename '%s' -> '%s'" % (fileName, newFileName))
+ print("Renaming '%s' -> '%s'..." % (fileName, newFileName))
os.rename(fileName, newFileName)
return newFileName
+def deleteMatchingLines(fileName, pattern):
+ lines = None
+ with open(fileName, "r") as f:
+ lines = f.readlines()
+
+ not_matching_lines = [l for l in lines if not re.search(pattern, l)]
+ if not_matching_lines.count == lines.count:
+ return False
+
+ print("Removing lines matching '%s' in '%s'..." % (pattern, fileName))
+ print(' ' + ' '.join([l for l in lines if re.search(pattern, l)]))
+ with open(fileName, "w") as f:
+ f.writelines(not_matching_lines)
+
+ return True
def getListOfFiles(clang_tidy_path):
files = glob.glob(os.path.join(clang_tidy_path, '*'))
@@ -66,43 +82,170 @@ def getListOfFiles(clang_tidy_path):
'clang-tidy', 'checks', '*'))
return [filename for filename in files if os.path.isfile(filename)]
+# Adapts the module's CMakelist file. Returns 'True' if it could add a new entry
+# and 'False' if the entry already existed.
+def adapt_cmake(module_path, check_name_camel):
+ filename = os.path.join(module_path, 'CMakeLists.txt')
+ with open(filename, 'r') as f:
+ lines = f.readlines()
+
+ cpp_file = check_name_camel + '.cpp'
+
+ # Figure out whether this check already exists.
+ for line in lines:
+ if line.strip() == cpp_file:
+ return False
+
+ print('Updating %s...' % filename)
+ with open(filename, 'wb') as f:
+ cpp_found = False
+ file_added = False
+ for line in lines:
+ cpp_line = line.strip().endswith('.cpp')
+ if (not file_added) and (cpp_line or cpp_found):
+ cpp_found = True
+ if (line.strip() > cpp_file) or (not cpp_line):
+ f.write(' ' + cpp_file + '\n')
+ file_added = True
+ f.write(line)
+
+ return True
+
+# Modifies the module to include the new check.
+def adapt_module(module_path, module, check_name, check_name_camel):
+ modulecpp = filter(lambda p: p.lower() == module.lower() + 'tidymodule.cpp',
+ os.listdir(module_path))[0]
+ filename = os.path.join(module_path, modulecpp)
+ with open(filename, 'r') as f:
+ lines = f.readlines()
+
+ print('Updating %s...' % filename)
+ with open(filename, 'wb') as f:
+ header_added = False
+ header_found = False
+ check_added = False
+ check_decl = (' CheckFactories.registerCheck<' + check_name_camel +
+ '>(\n "' + check_name + '");\n')
+
+ for line in lines:
+ if not header_added:
+ match = re.search('#include "(.*)"', line)
+ if match:
+ header_found = True
+ if match.group(1) > check_name_camel:
+ header_added = True
+ f.write('#include "' + check_name_camel + '.h"\n')
+ elif header_found:
+ header_added = True
+ f.write('#include "' + check_name_camel + '.h"\n')
+
+ if not check_added:
+ if line.strip() == '}':
+ check_added = True
+ f.write(check_decl)
+ else:
+ match = re.search('registerCheck<(.*)>', line)
+ if match and match.group(1) > check_name_camel:
+ check_added = True
+ f.write(check_decl)
+ f.write(line)
+
+
+# Adds a release notes entry.
+def add_release_notes(clang_tidy_path, old_check_name, new_check_name):
+ filename = os.path.normpath(os.path.join(clang_tidy_path,
+ '../docs/ReleaseNotes.rst'))
+ with open(filename, 'r') as f:
+ lines = f.readlines()
+
+ print('Updating %s...' % filename)
+ with open(filename, 'wb') as f:
+ note_added = False
+ header_found = False
+
+ for line in lines:
+ if not note_added:
+ match = re.search('Improvements to clang-tidy', line)
+ if match:
+ header_found = True
+ elif header_found:
+ if not line.startswith('----'):
+ f.write("""
+- The '%s' check was renamed to `%s
+ <http://clang.llvm.org/extra/clang-tidy/checks/%s.html>`_
+""" % (old_check_name, new_check_name, new_check_name))
+ note_added = True
+
+ f.write(line)
def main():
parser = argparse.ArgumentParser(description='Rename clang-tidy check.')
- parser.add_argument('module', type=str,
- help='Module where the renamed check is defined')
parser.add_argument('old_check_name', type=str,
help='Old check name.')
parser.add_argument('new_check_name', type=str,
help='New check name.')
args = parser.parse_args()
- args.module = args.module.lower()
+ old_module = args.old_check_name.split('-')[0]
+ new_module = args.new_check_name.split('-')[0]
check_name_camel = ''.join(map(lambda elem: elem.capitalize(),
- args.old_check_name.split('-'))) + 'Check'
- check_name_new_camel = (''.join(map(lambda elem: elem.capitalize(),
- args.new_check_name.split('-'))) +
+ args.old_check_name.split('-')[1:])) + 'Check'
+ new_check_name_camel = (''.join(map(lambda elem: elem.capitalize(),
+ args.new_check_name.split('-')[1:])) +
'Check')
clang_tidy_path = os.path.dirname(__file__)
- header_guard_old = (args.module.upper() + '_' +
- args.old_check_name.upper().replace('-', '_'))
- header_guard_new = (args.module.upper() + '_' +
- args.new_check_name.upper().replace('-', '_'))
+ header_guard_old = args.old_check_name.upper().replace('-', '_')
+ header_guard_new = args.new_check_name.upper().replace('-', '_')
+
+ old_module_path = os.path.join(clang_tidy_path, old_module)
+ new_module_path = os.path.join(clang_tidy_path, new_module)
+
+ # Remove the check from the old module.
+ cmake_lists = os.path.join(old_module_path, 'CMakeLists.txt')
+ check_found = deleteMatchingLines(cmake_lists, check_name_camel)
+ if not check_found:
+ print("Check name '%s' not found in %s. Exiting." %
+ (check_name_camel, cmake_lists))
+ return 1
+
+ modulecpp = filter(
+ lambda p: p.lower() == old_module.lower() + 'tidymodule.cpp',
+ os.listdir(old_module_path))[0]
+ deleteMatchingLines(os.path.join(old_module_path, modulecpp),
+ check_name_camel + '|' + args.old_check_name)
for filename in getListOfFiles(clang_tidy_path):
originalName = filename
filename = fileRename(filename, args.old_check_name,
args.new_check_name)
- filename = fileRename(filename, check_name_camel, check_name_new_camel)
+ filename = fileRename(filename, check_name_camel, new_check_name_camel)
replaceInFile(filename, generateCommentLineHeader(originalName),
generateCommentLineHeader(filename))
replaceInFile(filename, generateCommentLineSource(originalName),
generateCommentLineSource(filename))
replaceInFile(filename, header_guard_old, header_guard_new)
replaceInFile(filename, args.old_check_name, args.new_check_name)
- replaceInFile(filename, check_name_camel, check_name_new_camel)
+ replaceInFile(filename, check_name_camel, new_check_name_camel)
+
+ if old_module != new_module:
+ check_implementation_files = glob.glob(
+ os.path.join(old_module_path, new_check_name_camel + '*'))
+ for filename in check_implementation_files:
+ # Move check implementation to the directory of the new module.
+ filename = fileRename(filename, old_module_path, new_module_path)
+ replaceInFile(filename, 'namespace ' + old_module,
+ 'namespace ' + new_module)
+
+ # Add check to the new module.
+ adapt_cmake(new_module_path, new_check_name_camel)
+ adapt_module(new_module_path, new_module, args.new_check_name,
+ new_check_name_camel)
+
+ os.system(os.path.join(clang_tidy_path, 'add_new_check.py')
+ + ' --update-docs')
+ add_release_notes(clang_tidy_path, args.old_check_name, args.new_check_name)
if __name__ == '__main__':
main()
More information about the cfe-commits
mailing list