Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: flake8-eyeo/flake8_eyeo.py

Issue 29634555: NoIssue - Detect redundant comparisons Base URL: https://hg.adblockplus.org/codingtools
Patch Set: Created Dec. 10, 2017, 6:10 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 # This file is part of Adblock Plus <https://adblockplus.org/>, 1 # This file is part of Adblock Plus <https://adblockplus.org/>,
2 # Copyright (C) 2006-present eyeo GmbH 2 # Copyright (C) 2006-present eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 'unordered data')) 280 'unordered data'))
281 281
282 consts_first = single and not membership or symmetric 282 consts_first = single and not membership or symmetric
283 if consts_first and is_const(left) and not is_const(right): 283 if consts_first and is_const(left) and not is_const(right):
284 self.errors.append((left, 'A103 yoda condition')) 284 self.errors.append((left, 'A103 yoda condition'))
285 285
286 left = right 286 left = right
287 287
288 self.generic_visit(node) 288 self.generic_visit(node)
289 289
290 def visit_BoolOp(self, node):
291 if isinstance(node.op, ast.Or):
292 left = node.values[0]
293 right = node.values[1]
Sebastian Noack 2017/12/10 23:19:57 What if there is another condition in between? E.g
294 if (isinstance(left, ast.Compare) and
295 isinstance(right, ast.Compare)):
296 if (isinstance(left.ops[0], ast.Eq) and
297 isinstance(left.ops[0], ast.Eq) or
Sebastian Noack 2017/12/10 23:19:57 This expression is the same as the left-hand side
298 (isinstance(left.ops[0], ast.NotEq) and
299 isinstance(left.ops[0], ast.NotEq))):
300 value1names = []
301 value2names = []
302 # Gather variable names from the left comparison
303 if isinstance(left.left, ast.Name):
Sebastian Noack 2017/12/10 23:19:57 What if it is an Attribute node? E.g: x.a == 1 or
304 value1names.append(left.left.id)
305 if isinstance(left.comparators[0], ast.Name):
306 value1names.append(left.comparators[0].id)
307 # Gather variable names from the right comparison
308 if isinstance(right.left, ast.Name):
309 value2names.append(right.left.id)
310 if isinstance(right.comparators[0], ast.Name):
311 value2names.append(right.comparators[0].id)
312 # Check for duplicates
313 for i in value1names:
314 if i in value2names:
315 self.errors.append((node, 'A208 `{} == x or {} == '
316 'y` should be `{} in {{x'
317 ', y}}`'.format(i, i,
318 i)))
319
290 def _check_deprecated(self, node, name): 320 def _check_deprecated(self, node, name):
291 substitute = DISCOURAGED_APIS.get(name) 321 substitute = DISCOURAGED_APIS.get(name)
292 if substitute: 322 if substitute:
293 self.errors.append((node, 'A301 use {}() instead of ' 323 self.errors.append((node, 'A301 use {}() instead of '
294 '{}()'.format(substitute, name))) 324 '{}()'.format(substitute, name)))
295 325
296 def visit_Call(self, node): 326 def visit_Call(self, node):
297 func = get_identifier(node.func) 327 func = get_identifier(node.func)
298 arg = next(iter(node.args), None) 328 arg = next(iter(node.args), None)
299 redundant_literal = False 329 redundant_literal = False
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 def check_quotes(logical_line, tokens, previous_logical, checker_state): 414 def check_quotes(logical_line, tokens, previous_logical, checker_state):
385 first_token = True 415 first_token = True
386 416
387 token_strings = [t[1] for t in tokens] 417 token_strings = [t[1] for t in tokens]
388 future_import = token_strings[:3] == ['from', '__future__', 'import'] 418 future_import = token_strings[:3] == ['from', '__future__', 'import']
389 419
390 if future_import and 'unicode_literals' in token_strings: 420 if future_import and 'unicode_literals' in token_strings:
391 checker_state['has_unicode_literals'] = True 421 checker_state['has_unicode_literals'] = True
392 422
393 for kind, token, start, end, _ in tokens: 423 for kind, token, start, end, _ in tokens:
394 if kind == tokenize.INDENT or kind == tokenize.DEDENT: 424 if kind in {tokenize.INDENT, tokenize.DEDENT}:
395 continue 425 continue
396 426
397 if kind == tokenize.STRING: 427 if kind == tokenize.STRING:
398 match = re.search(r'^([rub]*)([\'"]{1,3})(.*)\2$', 428 match = re.search(r'^([rub]*)([\'"]{1,3})(.*)\2$',
399 token, re.IGNORECASE | re.DOTALL) 429 token, re.IGNORECASE | re.DOTALL)
400 prefixes, quote, text = match.groups() 430 prefixes, quote, text = match.groups()
401 prefixes = prefixes.lower() 431 prefixes = prefixes.lower()
402 432
403 if 'u' in prefixes: 433 if 'u' in prefixes:
404 yield (start, 'A112 use "from __future__ import ' 434 yield (start, 'A112 use "from __future__ import '
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 if is_tuple or is_nested_op or is_compare_in_assign: 521 if is_tuple or is_nested_op or is_compare_in_assign:
492 continue 522 continue
493 523
494 yield (pos[0], pos[1], 'A111 redundant parenthesis', None) 524 yield (pos[0], pos[1], 'A111 redundant parenthesis', None)
495 525
496 526
497 for checker in [check_ast, check_non_default_encoding, 527 for checker in [check_ast, check_non_default_encoding,
498 check_quotes, check_redundant_parenthesis]: 528 check_quotes, check_redundant_parenthesis]:
499 checker.name = 'eyeo' 529 checker.name = 'eyeo'
500 checker.version = __version__ 530 checker.version = __version__
OLDNEW
« no previous file with comments | « flake8-eyeo/README.md ('k') | flake8-eyeo/tests/A208.py » ('j') | flake8-eyeo/tests/A208.py » ('J')

Powered by Google App Engine
This is Rietveld