eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py

changeset 8194
b925628bf91f
parent 8192
e1157bd8b4c2
child 8195
db7f2badd374
equal deleted inserted replaced
8193:2aa8953a2145 8194:b925628bf91f
113 @type ast.For 113 @type ast.For
114 """ 114 """
115 self.__check104(node) 115 self.__check104(node)
116 self.__check110_111(node) 116 self.__check110_111(node)
117 self.__check113(node) 117 self.__check113(node)
118 self.__check118b(node) 118 self.__check118(node)
119 119
120 self.generic_visit(node) 120 self.generic_visit(node)
121 121
122 def visit_Try(self, node): 122 def visit_Try(self, node):
123 """ 123 """
158 Public method to process a Compare node. 158 Public method to process a Compare node.
159 159
160 @param node reference to the Compare node 160 @param node reference to the Compare node
161 @type ast.Compare 161 @type ast.Compare
162 """ 162 """
163 self.__check118a(node) 163 self.__check118(node)
164 164
165 self.generic_visit(node) 165 self.generic_visit(node)
166 166
167 def visit_ClassDef(self, node): 167 def visit_ClassDef(self, node):
168 """ 168 """
170 170
171 @param node reference to the ClassDef node 171 @param node reference to the ClassDef node
172 @type ast.ClassDef 172 @type ast.ClassDef
173 """ 173 """
174 self.__check119(node) 174 self.__check119(node)
175 self.__check120(node)
175 176
176 self.generic_visit(node) 177 self.generic_visit(node)
177 178
178 ############################################################# 179 #############################################################
179 ## Helper methods for the various checkers below 180 ## Helper methods for the various checkers below
485 """ 486 """
486 # if a: 487 # if a:
487 # b = c 488 # b = c
488 # else: 489 # else:
489 # b = d 490 # b = d
491 #
492 # but not:
493 # if a:
494 # b = c
495 # elif c:
496 # b = e
497 # else:
498 # b = d
490 if ( 499 if (
491 len(node.body) == 1 and 500 len(node.body) == 1 and
492 len(node.orelse) == 1 and 501 len(node.orelse) == 1 and
493 isinstance(node.body[0], ast.Assign) and 502 isinstance(node.body[0], ast.Assign) and
494 isinstance(node.orelse[0], ast.Assign) and 503 isinstance(node.orelse[0], ast.Assign) and
495 len(node.body[0].targets) == 1 and 504 len(node.body[0].targets) == 1 and
496 len(node.orelse[0].targets) == 1 and 505 len(node.orelse[0].targets) == 1 and
497 isinstance(node.body[0].targets[0], ast.Name) and 506 isinstance(node.body[0].targets[0], ast.Name) and
498 isinstance(node.orelse[0].targets[0], ast.Name) and 507 isinstance(node.orelse[0].targets[0], ast.Name) and
499 node.body[0].targets[0].id == node.orelse[0].targets[0].id 508 node.body[0].targets[0].id == node.orelse[0].targets[0].id and
509 not isinstance(node.parent, ast.If)
500 ): 510 ):
501 assign = unparse(node.body[0].targets[0]) 511 assign = unparse(node.body[0].targets[0])
502 body = unparse(node.body[0].value) 512 body = unparse(node.body[0].value)
503 cond = unparse(node.test) 513 cond = unparse(node.test)
504 orelse = unparse(node.orelse[0].value) 514 orelse = unparse(node.orelse[0].value)
505 if len( 515 if len(
506 "{0} = {1} if {2} else {3}".format(assign, body, cond, orelse) 516 "{0} = {1} if {2} else {3}".format(assign, body, cond, orelse)
507 ) > 79: 517 ) < 79:
508 self.__error(node.lineno - 1, node.col_offset, "Y108a") 518 # don't flag an issue, if the ternary would get too complicated
509 else: 519 self.__error(node.lineno - 1, node.col_offset, "Y108",
510 self.__error(node.lineno - 1, node.col_offset, "Y108b",
511 assign, body, cond, orelse) 520 assign, body, cond, orelse)
512 521
513 def __check109(self, node): 522 def __check109(self, node):
514 """ 523 """
515 Private method to check for multiple equalities with the same value 524 Private method to check for multiple equalities with the same value
846 for withitem in node.items + node.body[0].items: 855 for withitem in node.items + node.body[0].items:
847 withItems.append(f"{unparse(withitem)}") 856 withItems.append(f"{unparse(withitem)}")
848 mergedWith = f"with {', '.join(withItems)}:" 857 mergedWith = f"with {', '.join(withItems)}:"
849 self.__error(node.lineno - 1, node.col_offset, "Y117", mergedWith) 858 self.__error(node.lineno - 1, node.col_offset, "Y117", mergedWith)
850 859
851 def __check118a(self, node): 860 def __check118(self, node):
852 """ 861 """
853 Private method to check for usages of "key in dict.keys()". 862 Private method to check for usages of "key in dict.keys()".
854 863
855 @param node reference to the AST node to be checked 864 @param node reference to the AST node to be checked
856 @type ast.Compare 865 @type ast.Compare or ast.For
857 """ 866 """
858 # key in dict.keys() 867 # Pattern 1:
868 #
869 # if key in dict.keys():
870 # # do something
871 #
872 # Pattern 2:
873 #
874 # for key in dict.keys():
875 # # do something
859 if ( 876 if (
877 isinstance(node, ast.Compare) and
860 len(node.ops) == 1 and 878 len(node.ops) == 1 and
861 isinstance(node.ops[0], ast.In) and 879 isinstance(node.ops[0], ast.In) and
862 len(node.comparators) == 1 880 len(node.comparators) == 1
863 ): 881 ):
864 callNode = node.comparators[0] 882 callNode = node.comparators[0]
865 if not isinstance(callNode, ast.Call): 883 elif (
866 return 884 isinstance(node, ast.For)
867 885 ):
868 attrNode = callNode.func 886 callNode = node.iter
869 if ( 887 else:
870 isinstance(callNode.func, ast.Attribute) and 888 callNode = None
871 callNode.func.attr == "keys" and 889
872 isinstance(callNode.func.ctx, ast.Load)
873 ):
874 keyStr = unparse(node.left)
875 dictStr = unparse(attrNode.value)
876 self.__error(node.lineno - 1, node.col_offset, "Y118",
877 keyStr, dictStr)
878
879 def __check118b(self, node):
880 """
881 Private method to check for usages of "key in dict.keys()".
882
883 @param node reference to the AST node to be checked
884 @type ast.For
885 """
886 # for key in dict.keys():
887 # # do something
888 callNode = node.iter
889 if not isinstance(callNode, ast.Call): 890 if not isinstance(callNode, ast.Call):
890 return 891 return
891 892
892 attrNode = callNode.func 893 attrNode = callNode.func
893 if ( 894 if (
894 isinstance(callNode.func, ast.Attribute) and 895 isinstance(callNode.func, ast.Attribute) and
895 callNode.func.attr == "keys" and 896 callNode.func.attr == "keys" and
896 isinstance(callNode.func.ctx, ast.Load) 897 isinstance(callNode.func.ctx, ast.Load)
897 ): 898 ):
898 keyStr = unparse(node.target) 899 if isinstance(node, ast.Compare):
900 keyStr = unparse(node.left)
901 else:
902 keyStr = unparse(node.target)
899 dictStr = unparse(attrNode.value) 903 dictStr = unparse(attrNode.value)
900 self.__error(node.lineno - 1, node.col_offset, "Y118", 904 self.__error(node.lineno - 1, node.col_offset, "Y118",
901 keyStr, dictStr) 905 keyStr, dictStr)
902 906
903 def __check119(self, node): 907 def __check119(self, node):
904 """ 908 """
905 Public method to check for classes that should be "dataclasses". 909 Private method to check for classes that should be "dataclasses".
906 910
907 @param node reference to the AST node to be checked 911 @param node reference to the AST node to be checked
908 @type ast.ClassDef 912 @type ast.ClassDef
909 """ 913 """
910 if ( 914 if (
932 sum(1 for el in node.body 936 sum(1 for el in node.body
933 if isinstance(el, ast.FunctionDef)) > 0 937 if isinstance(el, ast.FunctionDef)) > 0
934 ): 938 ):
935 self.__error(node.lineno - 1, node.col_offset, "Y119", 939 self.__error(node.lineno - 1, node.col_offset, "Y119",
936 node.name) 940 node.name)
941
942 def __check120(self, node):
943 """
944 Private method to check for classes that inherit from object.
945
946 @param node reference to the AST node to be checked
947 @type ast.ClassDef
948 """
949 # class FooBar(object):
950 # ...
951 if (
952 len(node.bases) == 1 and
953 isinstance(node.bases[0], ast.Name) and
954 node.bases[0].id == "object"
955 ):
956 self.__error(node.lineno - 1, node.col_offset, "Y120",
957 node.name)
937 958
938 # 959 #
939 # eflag: noqa = M891 960 # eflag: noqa = M891

eric ide

mercurial