diff -r fc45672fae42 -r 73d80859079c src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Naming/NamingStyleChecker.py --- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Naming/NamingStyleChecker.py Thu Feb 27 09:22:15 2025 +0100 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Naming/NamingStyleChecker.py Thu Feb 27 14:42:39 2025 +0100 @@ -9,7 +9,6 @@ import ast import collections -import copy import functools import os @@ -18,9 +17,10 @@ except AttributeError: ast.AsyncFunctionDef = ast.FunctionDef +from CodeStyleTopicChecker import CodeStyleTopicChecker -# TODO: change this to a checker like the others -class NamingStyleChecker: + +class NamingStyleChecker(CodeStyleTopicChecker): """ Class implementing a checker for naming conventions. """ @@ -46,6 +46,7 @@ "N-823", "N-831", ] + Category = "N" def __init__(self, source, filename, tree, select, ignore, expected, repeat, args): """ @@ -68,23 +69,20 @@ @param args dictionary of arguments for the various checks @type dict """ - self.__select = tuple(select) - self.__ignore = tuple(ignore) - self.__expected = expected[:] - self.__repeat = repeat - self.__filename = filename - self.__source = source[:] - self.__tree = copy.deepcopy(tree) - self.__args = args + super().__init__( + NamingStyleChecker.Category, + source, + filename, + tree, + select, + ignore, + expected, + repeat, + args, + ) self.__parents = collections.deque() - # statistics counters - self.counters = {} - - # collection of detected errors - self.errors = [] - self.__checkersWithCodes = { "classdef": [ (self.__checkClassName, ("N-801", "N-818")), @@ -130,32 +128,19 @@ self.__checkers = collections.defaultdict(list) for key, checkers in self.__checkersWithCodes.items(): for checker, codes in checkers: - if any(not (code and self.__ignoreCode(code)) for code in codes): + if any(not (code and self._ignoreCode(code)) for code in codes): self.__checkers[key].append(checker) - def __ignoreCode(self, code): + def addErrorFromNode(self, node, msgCode): """ - Private method to check if the message code should be ignored. - - @param code message code to check for - @type str - @return flag indicating to ignore the given code - @rtype bool - """ - return code in self.__ignore or ( - code.startswith(self.__ignore) and not code.startswith(self.__select) - ) - - def __error(self, node, code): - """ - Private method to build the error information. + Public method to build the error information. @param node AST node to report an error for @type ast.AST - @param code error code to report + @param msgCode message code @type str """ - if self.__ignoreCode(code): + if self._ignoreCode(msgCode): return if isinstance(node, ast.Module): @@ -171,41 +156,21 @@ lineno += len(node.decorator_list) offset += 4 - # record the issue with one based line number - errorInfo = { - "file": self.__filename, - "line": lineno, - "offset": offset, - "code": code, - "args": [], - } - - if errorInfo not in self.errors: - # this issue was not seen before - if code in self.counters: - self.counters[code] += 1 - else: - self.counters[code] = 1 - - # Don't care about expected codes - if code in self.__expected: - return - - if code and (self.counters[code] == 1 or self.__repeat): - self.errors.append(errorInfo) + self.addError(lineno, offset, msgCode, []) def run(self): """ - Public method run by the pycodestyle.py checker. + Public method to execute the relevant checks. + """ + if not self.filename: + # don't do anything, if essential data is missing + return - @return tuple giving line number, offset within line, code and - checker function - @rtype tuple of (int, int, str, function) - """ - if self.__tree and self.__checkers: - return self.__visitTree(self.__tree) - else: - return () + if not self.__checkers: + # don't do anything, if no codes were selected + return + + self.__visitTree(self.tree) def __visitTree(self, node): """ @@ -338,13 +303,13 @@ if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): name = node.name if self.__isNameToBeAvoided(name): - self.__error(node, "N-831") + self.addErrorFromNode(node, "N-831") elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): argNames = self.__getArgNames(node) for arg in argNames: if self.__isNameToBeAvoided(arg): - self.__error(node, "N-831") + self.addErrorFromNode(node, "N-831") elif isinstance(node, (ast.Assign, ast.NamedExpr, ast.AnnAssign)): if isinstance(node, ast.Assign): @@ -355,14 +320,14 @@ if isinstance(target, ast.Name): name = target.id if bool(name) and self.__isNameToBeAvoided(name): - self.__error(node, "N-831") + self.addErrorFromNode(node, "N-831") elif isinstance(target, (ast.Tuple, ast.List)): for element in target.elts: if isinstance(element, ast.Name): name = element.id if bool(name) and self.__isNameToBeAvoided(name): - self.__error(node, "N-831") + self.addErrorFromNode(node, "N-831") def __getClassdef(self, name, parents): """ @@ -425,11 +390,11 @@ name = node.name strippedName = name.strip("_") if not strippedName[:1].isupper() or "_" in strippedName: - self.__error(node, "N-801") + self.addErrorFromNode(node, "N-801") superClasses = self.__superClassNames(name, parents) if "Exception" in superClasses and not name.endswith("Error"): - self.__error(node, "N-818") + self.addErrorFromNode(node, "N-818") def __checkFunctionName(self, node, _parents): """ @@ -454,9 +419,9 @@ return if name.lower() != name: - self.__error(node, "N-802") + self.addErrorFromNode(node, "N-802") if functionType == "function" and name[:2] == "__" and name[-2:] == "__": - self.__error(node, "N-809") + self.addErrorFromNode(node, "N-809") def __checkFunctionArgumentNames(self, node, _parents): """ @@ -475,12 +440,12 @@ if node.args.kwarg is not None: kwarg = node.args.kwarg.arg if kwarg.lower() != kwarg: - self.__error(node, "N-803") + self.addErrorFromNode(node, "N-803") elif node.args.vararg is not None: vararg = node.args.vararg.arg if vararg.lower() != vararg: - self.__error(node, "N-803") + self.addErrorFromNode(node, "N-803") else: argNames = self.__getArgNames(node) @@ -488,19 +453,19 @@ if not argNames: if functionType == "method": - self.__error(node, "N-805") + self.addErrorFromNode(node, "N-805") elif functionType == "classmethod": - self.__error(node, "N-804") + self.addErrorFromNode(node, "N-804") elif functionType == "method" and argNames[0] != "self": - self.__error(node, "N-805") + self.addErrorFromNode(node, "N-805") elif functionType == "classmethod" and argNames[0] != "cls": - self.__error(node, "N-804") + self.addErrorFromNode(node, "N-804") elif functionType == "staticmethod" and argNames[0] in ("cls", "self"): - self.__error(node, "N-806") + self.addErrorFromNode(node, "N-806") for arg in argNames: if arg.lower() != arg: - self.__error(node, "N-803") + self.addErrorFromNode(node, "N-803") break def __checkVariableNames(self, node, parents): @@ -563,7 +528,7 @@ for name in self.__extractNames(assignmentTarget): errorCode = checker(name) if errorCode: - self.__error(assignmentTarget, errorCode) + self.addErrorFromNode(assignmentTarget, errorCode) def __extractNames(self, assignmentTarget): """ @@ -678,13 +643,13 @@ if self.__filename: moduleName = os.path.splitext(os.path.basename(self.__filename))[0] if moduleName.lower() != moduleName: - self.__error(node, "N-807") + self.addErrorFromNode(node, "N-807") if moduleName == "__init__": # we got a package packageName = os.path.split(os.path.dirname(self.__filename))[1] if packageName.lower() != packageName: - self.__error(node, "N-808") + self.addErrorFromNode(node, "N-808") def __checkImportAs(self, node, _parents): """ @@ -704,14 +669,14 @@ originalName = name.name if originalName.isupper(): if not asname.isupper(): - self.__error(node, "N-811") + self.addErrorFromNode(node, "N-811") elif originalName.islower(): if asname.lower() != asname: - self.__error(node, "N-812") + self.addErrorFromNode(node, "N-812") elif asname.islower(): - self.__error(node, "N-813") + self.addErrorFromNode(node, "N-813") elif asname.isupper(): if "".join(filter(str.isupper, originalName)) == asname: - self.__error(node, "N-815") + self.addErrorFromNode(node, "N-815") else: - self.__error(node, "N-814") + self.addErrorFromNode(node, "N-814")