diff --git a/GNUmakefile b/GNUmakefile index bc73fd564f0..15f74d746ac 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -81,9 +81,9 @@ Documentation Checking Spell Checkers This runs the spell checker from the developer tools repositor. - * check_spelling_c: Check for spelling errors (C/C++ only), - * check_spelling_osl: Check for spelling errors (OSL only). - * check_spelling_py: Check for spelling errors (Python only). + * check_spelling_c: Check for spelling errors (C/C++ only), + * check_spelling_py: Check for spelling errors (Python only). + * check_spelling_shaders: Check for spelling errors (GLSL,OSL & MSL only). Note: an additional word-list is maintained at: 'tools/check_source/check_spelling_c_config.py' @@ -492,24 +492,31 @@ check_spelling_py: .FORCE @cd "$(BUILD_DIR)" ; \ PYTHONIOENCODING=utf_8 $(PYTHON) \ "$(BLENDER_DIR)/tools/check_source/check_spelling.py" \ - "$(BLENDER_DIR)/scripts" + --cache-file=$(CHECK_SPELLING_CACHE) \ + --match=".*\.(py)$$" \ + "$(BLENDER_DIR)/scripts" \ + "$(BLENDER_DIR)/source" \ + "$(BLENDER_DIR)/tools" check_spelling_c: .FORCE @cd "$(BUILD_DIR)" ; \ PYTHONIOENCODING=utf_8 $(PYTHON) \ "$(BLENDER_DIR)/tools/check_source/check_spelling.py" \ --cache-file=$(CHECK_SPELLING_CACHE) \ + --match=".*\.(c|cc|cpp|cxx|h|hh|hpp|hxx|inl|m|mm)$$" \ "$(BLENDER_DIR)/source" \ "$(BLENDER_DIR)/intern/cycles" \ "$(BLENDER_DIR)/intern/guardedalloc" \ - "$(BLENDER_DIR)/intern/ghost" \ + "$(BLENDER_DIR)/intern/ghost" -check_spelling_osl: .FORCE +check_spelling_shaders: .FORCE @cd "$(BUILD_DIR)" ; \ PYTHONIOENCODING=utf_8 $(PYTHON) \ "$(BLENDER_DIR)/tools/check_source/check_spelling.py" \ --cache-file=$(CHECK_SPELLING_CACHE) \ - "$(BLENDER_DIR)/intern/cycles/kernel/shaders" + --match=".*\.(osl|msl|glsl)$$" \ + "$(BLENDER_DIR)/intern/" \ + "$(BLENDER_DIR)/source/" check_descriptions: .FORCE @$(BLENDER_BIN) --background -noaudio --factory-startup --python \ diff --git a/tools/check_source/check_spelling.py b/tools/check_source/check_spelling.py index 3cbf0d0f1a2..540856886d3 100755 --- a/tools/check_source/check_spelling.py +++ b/tools/check_source/check_spelling.py @@ -16,6 +16,7 @@ Currently only python source is checked. import os import argparse +import sys from typing import ( Callable, @@ -63,10 +64,30 @@ from check_spelling_c_config import ( dict_ignore_hyphenated_prefix, dict_ignore_hyphenated_suffix, files_ignore, + directories_ignore, +) + +SOURCE_EXT = ( + "c", + "cc", + "inl", + "cpp", + "cxx", + "hpp", + "hxx", + "h", + "hh", + "m", + "mm", + "msl", + "glsl", + "osl", + "py", ) BASEDIR = os.path.abspath(os.path.dirname(__file__)) ROOTDIR = os.path.normpath(os.path.join(BASEDIR, "..", "..")) +ROOTDIR_WITH_SLASH = ROOTDIR + os.sep # Ensure native slashes. files_ignore = { @@ -74,6 +95,11 @@ files_ignore = { for f in files_ignore } +directories_ignore = { + os.path.normpath(os.path.join(ROOTDIR, f.replace("/", os.sep))) + for f in directories_ignore +} + # ----------------------------------------------------------------------------- # Dictionary Utilities @@ -211,7 +237,7 @@ def words_from_text(text: str, check_type: str) -> List[Tuple[str, int]]: start, end = match.span() return re_not_newline.sub(" ", match.string[start:end]) - # Handy for checking what we ignore, incase we ignore too much and miss real errors. + # Handy for checking what we ignore, in case we ignore too much and miss real errors. # for match in re_ignore.finditer(text): # print(match.group(0)) @@ -532,11 +558,12 @@ def spell_check_file( def spell_check_file_recursive( dirpath: str, check_type: str, + regex_list: List[re.Pattern[str]], extract_type: str = 'COMMENTS', cache_data: Optional[CacheData] = None, ) -> None: import os - from os.path import join, splitext + from os.path import join def source_list( path: str, @@ -545,6 +572,9 @@ def spell_check_file_recursive( for dirpath, dirnames, filenames in os.walk(path): # Only needed so this can be matches with ignore paths. dirpath = os.path.abspath(dirpath) + if dirpath in directories_ignore: + dirnames.clear() + continue # skip '.git' dirnames[:] = [d for d in dirnames if not d.startswith(".")] for filename in filenames: @@ -558,22 +588,16 @@ def spell_check_file_recursive( yield filepath def is_source(filename: str) -> bool: - ext = splitext(filename)[1] - return (ext in { - ".c", - ".cc", - ".inl", - ".cpp", - ".cxx", - ".hpp", - ".hxx", - ".h", - ".hh", - ".m", - ".mm", - ".osl", - ".py", - }) + from os.path import splitext + filename = filename.removeprefix(ROOTDIR_WITH_SLASH) + for regex in regex_list: + if regex.match(filename) is not None: + filename + ext = splitext(filename)[1].removeprefix(".") + if ext not in SOURCE_EXT: + raise Exception("Unknown extension \".{:s}\" aborting!".format(ext)) + return True + return False for filepath in source_list(dirpath, is_source): for report in spell_check_file_with_cache_support( @@ -613,6 +637,7 @@ def spell_cache_write(cache_filepath: str, cache_store: Tuple[CacheData, Suggest def spell_check_file_with_cache_support( filepath: str, check_type: str, + *, extract_type: str = 'COMMENTS', cache_data: Optional[CacheData] = None, ) -> Generator[Report, None, None]: @@ -661,6 +686,17 @@ def argparse_create() -> argparse.ArgumentParser: description = __doc__ parser = argparse.ArgumentParser(description=description) + parser.add_argument( + "--match", + nargs='+', + default=( + r".*\.(" + "|".join(SOURCE_EXT) + ")$", + ), + required=False, + metavar="REGEX", + help="Match file paths against this expression", + ) + parser.add_argument( '--extract', dest='extract', @@ -710,13 +746,21 @@ def argparse_create() -> argparse.ArgumentParser: return parser -def main() -> None: +def main() -> int: global _suggest_map import os args = argparse_create().parse_args() + regex_list = [] + for expr in args.match: + try: + regex_list.append(re.compile(expr)) + except Exception as ex: + print("Error in expression: {!r}\n {!r}".format(expr, ex)) + return 1 + extract_type = args.extract cache_filepath = args.cache_file check_type = args.check_type @@ -730,12 +774,23 @@ def main() -> None: try: for filepath in args.paths: if os.path.isdir(filepath): + # recursive search - spell_check_file_recursive(filepath, check_type, extract_type=extract_type, cache_data=cache_data) + spell_check_file_recursive( + filepath, + check_type, + regex_list=regex_list, + extract_type=extract_type, + cache_data=cache_data, + ) else: # single file for report in spell_check_file_with_cache_support( - filepath, check_type, extract_type=extract_type, cache_data=cache_data): + filepath, + check_type, + extract_type=extract_type, + cache_data=cache_data, + ): spell_check_report(filepath, check_type, report) except KeyboardInterrupt: clear_stale_cache = False @@ -754,7 +809,8 @@ def main() -> None: del cache_data[filepath] spell_cache_write(cache_filepath, (cache_data, _suggest_map)) + return 0 if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/tools/check_source/check_spelling_c_config.py b/tools/check_source/check_spelling_c_config.py index 5aa8b5acf7a..f124fdee8bd 100644 --- a/tools/check_source/check_spelling_c_config.py +++ b/tools/check_source/check_spelling_c_config.py @@ -796,3 +796,8 @@ dict_ignore_hyphenated_suffix = { files_ignore = { "tools/utils_doc/rna_manual_reference_updater.py", # Contains language ID references. } + +directories_ignore = { + "scripts/addons", + "scripts/addons_contrib", +}