diff --git a/cmake/Modules/CodingStandard.cmake b/cmake/Modules/CodingStandard.cmake index 646bdcdd4a..6bb607be12 100644 --- a/cmake/Modules/CodingStandard.cmake +++ b/cmake/Modules/CodingStandard.cmake @@ -15,6 +15,11 @@ if(Python3_EXECUTABLE) ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py . WORKING_DIRECTORY ${LAMMPS_DIR} COMMENT "Check for whitespace errors") + add_custom_target( + check-homepage + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/homepage.py . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Check for homepage URL errors") add_custom_target( check-permissions ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py . @@ -25,6 +30,11 @@ if(Python3_EXECUTABLE) ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py -f . WORKING_DIRECTORY ${LAMMPS_DIR} COMMENT "Fix whitespace errors") + add_custom_target( + fix-homepage + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/homepage.py -f . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Fix homepage URL errors") add_custom_target( fix-permissions ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f . diff --git a/doc/src/Build_development.rst b/doc/src/Build_development.rst index 9c5f5ea61e..2707e1fce8 100644 --- a/doc/src/Build_development.rst +++ b/doc/src/Build_development.rst @@ -447,12 +447,24 @@ The following options are available. .. code-block:: bash - make check-whitespace # generate coverage report in HTML format - make fix-whitespace # generate coverage report in XML format - make check-permissions # delete folder with HTML format coverage report - make fix-permissions # delete all collected coverage data and HTML output + make check-whitespace # search for files with whitespace issues + make fix-whitespace # correct whitespace issues in files + make check-homepage # search for files with old LAMMPS homepage URLs + make fix-homepage # correct LAMMPS homepage URLs in files + make check-permissions # search for files with permissions issues + make fix-permissions # correct permissions issues in files -For the code in the ``unittest`` tree we are using the `clang-format` -tool (Clang version 8.0 or later is required). If available, the source -code files in the ``unittest`` tree can be updated to conform to the -formatting settings using ``make format-tests``. +For the code in the ``unittest`` and ``src`` trees we are transitioning +to use the `clang-format` tool to assist with having a consistent source +code style. The `clang-format` command bundled with Clang version 8.0 +or later is required. The configuration is in files ``.clang-format`` +in the respective folders. Since the modifications from `clang-format` +can be significant and - especially for "legacy style code" - also is +not always improving readability, a large number of files currently have +a ``// clang-format off`` at the top, which will disable the processing. +Over time, files will be refactored and updated to that `clang-format` +may be applied to them (at least in part). + +If `clang-format` is available, the source code files in the ``unittest`` +tree can be updated to conform to the formatting settings using +``make format-tests`` and the files in ``src`` with ``make format-src``. diff --git a/tools/coding_standard/homepage.py b/tools/coding_standard/homepage.py new file mode 100644 index 0000000000..66a92672c7 --- /dev/null +++ b/tools/coding_standard/homepage.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# Utility for detecting incorrect LAMMPS homepage URLs +# +# Written by Richard Berger (Temple University) +import os +import sys +import glob +import re +import yaml +import argparse +import shutil + +DEFAULT_CONFIG = """ +recursive: true +include: + - cmake/** + - doc + - doc/src/** + - python + - src/** + - tools/coding_standard +patterns: + - "*.c" + - "*.cmake" + - "*.cpp" + - "*.h" + - "*.md" + - "*.py" + - "*.rst" + - "*.sh" + - ".gitignore" + - "README" + - "requirements.txt" +""" + +def check_homepage(f): + pattern = re.compile(r'.*lammps.sandia.gov.*') + lineno = 1 + errors = set() + + for line in f: + if pattern.match(line): + errors.add(lineno) + lineno += 1 + + return errors + +def check_file(path): + if path.find('homepage.py') >= 0: return { 'homepage_errors' : '' } + encoding = 'UTF-8' + whitespace_errors = set() + try: + with open(path, 'r') as f: + homepage_errors = check_homepage(f) + except UnicodeDecodeError: + encoding = 'ISO-8859-1' + try: + with open(path, 'r', encoding=encoding) as f: + homepage_errors = check_homepage(f) + except Exception: + encoding = 'unknown' + + return { + 'homepage_errors': homepage_errors, + 'encoding': encoding + } + +def fix_file(path, check_result): + if path.find('homepage.py') >= 0: return + newfile = path + ".modified" + with open(newfile, 'w', encoding='UTF-8') as out: + with open(path, 'r', encoding=check_result['encoding']) as src: + for line in src: + newline = line.replace("lammps.sandia.gov/doc/","docs.lammps.org/") + newline = newline.replace("http://lammps.sandia.gov,","https://www.lammps.org/") + newline = newline.replace("lammps.sandia.gov","www.lammps.org") + print(newline, end='', file=out) + shutil.copymode(path, newfile) + shutil.move(newfile, path) + +def check_folder(directory, config, fix=False, verbose=False): + success = True + files = [] + + for base_path in config['include']: + for pattern in config['patterns']: + path = os.path.join(directory, base_path, pattern) + files += glob.glob(path, recursive=config['recursive']) + + for f in files: + path = os.path.normpath(f) + + if verbose: + print("Checking file:", path) + + result = check_file(path) + + has_resolvable_errors = False + + for lineno in result['homepage_errors']: + print("[Error] Incorrect LAMMPS homepage @ {}:{}".format(path, lineno)) + has_resolvable_errors = True + + if has_resolvable_errors: + if fix: + print("Applying automatic fixes to file:", path) + fix_file(path, result) + else: + success = False + + return success + +def main(): + parser = argparse.ArgumentParser(description='Utility for detecting and fixing whitespace issues in LAMMPS') + parser.add_argument('-c', '--config', metavar='CONFIG_FILE', help='location of a optional configuration file') + parser.add_argument('-f', '--fix', action='store_true', help='automatically fix URLs') + parser.add_argument('-v', '--verbose', action='store_true', help='verbose output') + parser.add_argument('DIRECTORY', help='directory that should be checked') + args = parser.parse_args() + + if args.config: + with open(args.config, 'r') as cfile: + config = yaml.load(cfile, Loader=yaml.FullLoader) + else: + config = yaml.load(DEFAULT_CONFIG, Loader=yaml.FullLoader) + + if not check_folder(args.DIRECTORY, config, args.fix, args.verbose): + sys.exit(1) + +if __name__ == "__main__": + main()