Code Style Checker

Sat, 03 Apr 2021 10:44:07 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 03 Apr 2021 10:44:07 +0200
changeset 8194
b925628bf91f
parent 8193
2aa8953a2145
child 8195
db7f2badd374

Code Style Checker
- completed the first set of checkers for potential code simplifications

eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleChecker.py file | annotate | diff | comparison | revisions
eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py file | annotate | diff | comparison | revisions
eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py file | annotate | diff | comparison | revisions
eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/translations.py file | annotate | diff | comparison | revisions
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleChecker.py	Sat Apr 03 09:47:25 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleChecker.py	Sat Apr 03 10:44:07 2021 +0200
@@ -444,7 +444,7 @@
             errors += pathlibChecker.errors
             
             # check for code simplifications
-            simplifyChecker =SimplifyChecker(
+            simplifyChecker = SimplifyChecker(
                 source, filename, select, ignore, [], repeatMessages)
             simplifyChecker.run()
             stats.update(simplifyChecker.counters)
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py	Sat Apr 03 09:47:25 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py	Sat Apr 03 10:44:07 2021 +0200
@@ -21,9 +21,10 @@
         # Python-specifics
         "Y101", "Y102", "Y103", "Y104", "Y105", "Y106", "Y107", "Y108",
         "Y109", "Y110", "Y111", "Y112", "Y113", "Y114", "Y115", "Y116",
-        "Y117", "Y118", "Y119"
+        "Y117", "Y118", "Y119", "Y120",
         
         # Comparations
+        "Y201"
     ]
     
     def __init__(self, source, filename, selected, ignored, expected, repeat):
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py	Sat Apr 03 09:47:25 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py	Sat Apr 03 10:44:07 2021 +0200
@@ -115,7 +115,7 @@
         self.__check104(node)
         self.__check110_111(node)
         self.__check113(node)
-        self.__check118b(node)
+        self.__check118(node)
         
         self.generic_visit(node)
     
@@ -160,7 +160,7 @@
         @param node reference to the Compare node
         @type ast.Compare
         """
-        self.__check118a(node)
+        self.__check118(node)
         
         self.generic_visit(node)
     
@@ -172,6 +172,7 @@
         @type ast.ClassDef
         """
         self.__check119(node)
+        self.__check120(node)
         
         self.generic_visit(node)
     
@@ -487,6 +488,14 @@
         #     b = c
         # else:
         #     b = d
+        #
+        # but not:
+        # if a:
+        #     b = c
+        # elif c:
+        #     b = e
+        # else:
+        #     b = d
         if (
             len(node.body) == 1 and
             len(node.orelse) == 1 and
@@ -496,7 +505,8 @@
             len(node.orelse[0].targets) == 1 and
             isinstance(node.body[0].targets[0], ast.Name) and
             isinstance(node.orelse[0].targets[0], ast.Name) and
-            node.body[0].targets[0].id == node.orelse[0].targets[0].id
+            node.body[0].targets[0].id == node.orelse[0].targets[0].id and
+            not isinstance(node.parent, ast.If)
         ):
             assign = unparse(node.body[0].targets[0])
             body = unparse(node.body[0].value)
@@ -504,10 +514,9 @@
             orelse = unparse(node.orelse[0].value)
             if len(
                 "{0} = {1} if {2} else {3}".format(assign, body, cond, orelse)
-            ) > 79:
-                self.__error(node.lineno - 1, node.col_offset, "Y108a")
-            else:
-                self.__error(node.lineno - 1, node.col_offset, "Y108b",
+            ) < 79:
+                # don't flag an issue, if the ternary would get too complicated
+                self.__error(node.lineno - 1, node.col_offset, "Y108",
                              assign, body, cond, orelse)
     
     def __check109(self, node):
@@ -848,44 +857,36 @@
             mergedWith = f"with {', '.join(withItems)}:"
             self.__error(node.lineno - 1, node.col_offset, "Y117", mergedWith)
     
-    def __check118a(self, node):
+    def __check118(self, node):
         """
         Private method to check for usages of "key in dict.keys()".
         
         @param node reference to the AST node to be checked
-        @type ast.Compare
+        @type ast.Compare or ast.For
         """
-        # key in dict.keys()
+        # Pattern 1:
+        #
+        # if key in dict.keys():
+        #     # do something
+        #
+        # Pattern 2:
+        #
+        # for key in dict.keys():
+        #     # do something
         if (
+            isinstance(node, ast.Compare) and
             len(node.ops) == 1 and
             isinstance(node.ops[0], ast.In) and
             len(node.comparators) == 1
         ):
             callNode = node.comparators[0]
-            if not isinstance(callNode, ast.Call):
-                return
-            
-            attrNode = callNode.func
-            if (
-                isinstance(callNode.func, ast.Attribute) and
-                callNode.func.attr == "keys" and
-                isinstance(callNode.func.ctx, ast.Load)
-            ):
-                keyStr = unparse(node.left)
-                dictStr = unparse(attrNode.value)
-                self.__error(node.lineno - 1, node.col_offset, "Y118",
-                             keyStr, dictStr)
-    
-    def __check118b(self, node):
-        """
-        Private method to check for usages of "key in dict.keys()".
+        elif (
+            isinstance(node, ast.For)
+        ):
+            callNode = node.iter
+        else:
+            callNode = None
         
-        @param node reference to the AST node to be checked
-        @type ast.For
-        """
-        # for key in dict.keys():
-        #     # do something
-        callNode = node.iter
         if not isinstance(callNode, ast.Call):
             return
         
@@ -895,14 +896,17 @@
             callNode.func.attr == "keys" and
             isinstance(callNode.func.ctx, ast.Load)
         ):
-            keyStr = unparse(node.target)
+            if isinstance(node, ast.Compare):
+                keyStr = unparse(node.left)
+            else:
+                keyStr = unparse(node.target)
             dictStr = unparse(attrNode.value)
             self.__error(node.lineno - 1, node.col_offset, "Y118",
                          keyStr, dictStr)
     
     def __check119(self, node):
         """
-        Public method to check for classes that should be "dataclasses".
+        Private method to check for classes that should be "dataclasses".
         
         @param node reference to the AST node to be checked
         @type ast.ClassDef
@@ -934,6 +938,23 @@
             ):
                 self.__error(node.lineno - 1, node.col_offset, "Y119",
                              node.name)
+    
+    def __check120(self, node):
+        """
+        Private method to check for classes that inherit from object.
+        
+        @param node reference to the AST node to be checked
+        @type ast.ClassDef
+        """
+        # class FooBar(object):
+        #     ...
+        if (
+            len(node.bases) == 1 and
+            isinstance(node.bases[0], ast.Name) and
+            node.bases[0].id == "object"
+        ):
+            self.__error(node.lineno - 1, node.col_offset, "Y120",
+                         node.name)
 
 #
 # eflag: noqa = M891
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/translations.py	Sat Apr 03 09:47:25 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/translations.py	Sat Apr 03 10:44:07 2021 +0200
@@ -34,10 +34,7 @@
     "Y107": QCoreApplication.translate(
         "SimplifyChecker",
         '''Don't use return in try/except and finally'''),
-    "Y108a": QCoreApplication.translate(
-        "SimplifyChecker",
-        '''Use ternary operator instead of if-else-block'''),
-    "Y108b": QCoreApplication.translate(
+    "Y108": QCoreApplication.translate(
         "SimplifyChecker",
         '''Use ternary operator "{0} = {1} if {2} else {3}" '''
         '''instead of if-else-block'''),
@@ -75,6 +72,9 @@
     "Y119": QCoreApplication.translate(
         "SimplifyChecker",
         '''Use a dataclass for "class {0}"'''),
+    "Y120": QCoreApplication.translate(
+        "SimplifyChecker",
+        '''Use "class {0}:" instead of "class {0}(object):"'''),
 }
 
 _simplifyMessagesSampleArgs = {
@@ -82,7 +82,7 @@
     "Y103": ["foo != bar"],
     "Y104": ["iterable"],
     "Y105": ["Exception"],
-    "Y108b": ["foo", "bar", "condition", "baz"],
+    "Y108": ["foo", "bar", "condition", "baz"],
     "Y109": ["foo", "[1, 42]", "foo == 1 or foo == 42"],
     "Y110": ["check", "foo", "iterable"],
     "Y111": ["check", "foo", "iterable"],
@@ -92,5 +92,6 @@
     "Y116": ["mapping.get(foo, 42)"],
     "Y117": ["with Foo() as foo, Bar() as bar:"],
     "Y118": ["foo", "bar_dict"],
-    "Y119": ["Foo"]
+    "Y119": ["Foo"],
+    "Y120": ["Foo"],
 }

eric ide

mercurial