src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py

branch
eric7
changeset 11140
b823386f7591
parent 11138
1f743bad6fd3
child 11142
2f0fb22c1d63
equal deleted inserted replaced
11139:cd22e8e705f4 11140:b823386f7591
245 "M851", 245 "M851",
246 "M852", 246 "M852",
247 "M853", 247 "M853",
248 ## commented code 248 ## commented code
249 "M891", 249 "M891",
250 ## structural pattern matching
251 "M901",
252 "M902",
250 ] 253 ]
251 254
252 Formatter = Formatter() 255 Formatter = Formatter()
253 FormatFieldRegex = re.compile(r"^((?:\s|.)*?)(\..*|\[.*\])?$") 256 FormatFieldRegex = re.compile(r"^((?:\s|.)*?)(\..*|\[.*\])?$")
254 257
450 (self.__checkReturn, ("M831", "M832", "M833", "M834")), 453 (self.__checkReturn, ("M831", "M832", "M833", "M834")),
451 (self.__checkLineContinuation, ("M841",)), 454 (self.__checkLineContinuation, ("M841",)),
452 (self.__checkImplicitStringConcat, ("M851", "M852")), 455 (self.__checkImplicitStringConcat, ("M851", "M852")),
453 (self.__checkExplicitStringConcat, ("M853",)), 456 (self.__checkExplicitStringConcat, ("M853",)),
454 (self.__checkCommentedCode, ("M891",)), 457 (self.__checkCommentedCode, ("M891",)),
458 (self.__checkDefaultMatchCase, ("M901", "M902")),
455 ] 459 ]
456 460
457 # the eradicate whitelist 461 # the eradicate whitelist
458 commentedCodeCheckerArgs = self.__args.get( 462 commentedCodeCheckerArgs = self.__args.get(
459 "CommentedCodeChecker", 463 "CommentedCodeChecker",
1500 for operand in (node.left, node.right) 1504 for operand in (node.left, node.right)
1501 ) 1505 )
1502 ): 1506 ):
1503 self.__error(node.lineno - 1, node.col_offset, "M853") 1507 self.__error(node.lineno - 1, node.col_offset, "M853")
1504 1508
1509 #################################################################################
1510 ## The following method checks default match cases.
1511 #################################################################################
1512
1513 def __checkDefaultMatchCase(self):
1514 """
1515 Private method to check the default match case.
1516 """
1517 visitor = DefaultMatchCaseVisitor()
1518 visitor.visit(self.__tree)
1519 for violation in visitor.violations:
1520 node = violation[0]
1521 reason = violation[1]
1522 self.__error(node.lineno - 1, node.col_offset, reason)
1523
1505 1524
1506 class TextVisitor(ast.NodeVisitor): 1525 class TextVisitor(ast.NodeVisitor):
1507 """ 1526 """
1508 Class implementing a node visitor for bytes and str instances. 1527 Class implementing a node visitor for bytes and str instances.
1509 1528
4235 class SysVersionVisitor(ast.NodeVisitor): 4254 class SysVersionVisitor(ast.NodeVisitor):
4236 """ 4255 """
4237 Class implementing a node visitor to check the use of sys.version and 4256 Class implementing a node visitor to check the use of sys.version and
4238 sys.version_info. 4257 sys.version_info.
4239 4258
4240 Note: This class is modeled after flake8-2020 checker. 4259 Note: This class is modeled after flake8-2020 v1.8.1.
4241 """ 4260 """
4242 4261
4243 def __init__(self): 4262 def __init__(self):
4244 """ 4263 """
4245 Constructor 4264 Constructor
4416 self.violations.append((node, "M412")) 4435 self.violations.append((node, "M412"))
4417 4436
4418 self.generic_visit(node) 4437 self.generic_visit(node)
4419 4438
4420 4439
4440 class DefaultMatchCaseVisitor(ast.NodeVisitor):
4441 """
4442 Class implementing a node visitor to check default match cases.
4443
4444 Note: This class is modeled after flake8-spm v0.0.1.
4445 """
4446
4447 def __init__(self):
4448 """
4449 Constructor
4450 """
4451 super().__init__()
4452
4453 self.violations = []
4454
4455 def visit_Match(self, node):
4456 """
4457 Public method to handle Match nodes.
4458
4459 @param node reference to the node to be processed
4460 @type ast.Match
4461 """
4462 for badNode, issueCode in self.__badNodes(node):
4463 self.violations.append((badNode, issueCode))
4464
4465 self.generic_visit(node)
4466
4467 def __badNodes(self, node):
4468 """
4469 Private method to yield bad match nodes.
4470
4471 @param node reference to the node to be processed
4472 @type ast.Match
4473 @yield tuple containing a reference to bad match case node and the corresponding
4474 issue code
4475 @ytype tyuple of (ast.AST, str)
4476 """
4477 for case in node.cases:
4478 if self.__emptyMatchDefault(case):
4479 if self.__lastStatementDoesNotRaise(case):
4480 yield self.__findBadNode(case), "M901"
4481 elif self.__returnPrecedesExceptionRaising(case):
4482 yield self.__findBadNode(case), "M902"
4483
4484 def __emptyMatchDefault(self, case):
4485 """
4486 Private method to check for an empty default match case.
4487
4488 @param case reference to the node to be processed
4489 @type ast.match_case
4490 @return flag indicating an empty default match case
4491 @rtype bool
4492 """
4493 pattern = case.pattern
4494 return isinstance(pattern, ast.MatchAs) and (
4495 pattern.pattern is None
4496 or (
4497 isinstance(pattern.pattern, ast.MatchAs)
4498 and pattern.pattern.pattern is None
4499 )
4500 )
4501
4502 def __lastStatementDoesNotRaise(self, case):
4503 """
4504 Private method to check that the last case statement does not raise an
4505 exception.
4506
4507 @param case reference to the node to be processed
4508 @type ast.match_case
4509 @return flag indicating that the last case statement does not raise an
4510 exception
4511 @rtype bool
4512 """
4513 return not isinstance(case.body[-1], ast.Raise)
4514
4515 def __returnPrecedesExceptionRaising(self, case):
4516 """
4517 Private method to check that no return precedes an exception raising.
4518
4519 @param case reference to the node to be processed
4520 @type ast.match_case
4521 @return flag indicating that a return precedes an exception raising
4522 @rtype bool
4523 """
4524 returnIndex = -1
4525 raiseIndex = -1
4526 for index, body in enumerate(case.body):
4527 if isinstance(body, ast.Return):
4528 returnIndex = index
4529 elif isinstance(body, ast.Raise):
4530 raiseIndex = index
4531 return returnIndex >= 0 and returnIndex < raiseIndex
4532
4533 def __findBadNode(self, case) -> ast.AST:
4534 """
4535 Private method returning a reference to the bad node of a case node.
4536
4537 @param case reference to the node to be processed
4538 @type ast.match_case
4539 @return reference to the bad node
4540 @rtype ast.AST
4541 """
4542 for body in case.body:
4543 # Handle special case when return precedes exception raising.
4544 # In this case the bad node is that with the return statement.
4545 if isinstance(body, ast.Return):
4546 return body
4547
4548 return case.body[-1]
4549
4550
4421 # 4551 #
4422 # eflag: noqa = M891 4552 # eflag: noqa = M891

eric ide

mercurial