|
19 | 19 | */ |
20 | 20 | package org.sonar.python.checks; |
21 | 21 |
|
| 22 | +import com.google.common.collect.ImmutableSet; |
| 23 | +import com.sonar.sslr.api.AstNode; |
| 24 | +import com.sonar.sslr.api.AstNodeType; |
| 25 | +import java.util.HashSet; |
22 | 26 | import java.util.Set; |
23 | | - |
24 | 27 | import org.sonar.check.Rule; |
25 | 28 | import org.sonar.python.PythonCheck; |
26 | 29 | import org.sonar.python.api.PythonGrammar; |
| 30 | +import org.sonar.python.api.PythonKeyword; |
27 | 31 | import org.sonar.python.api.PythonPunctuator; |
28 | 32 | import org.sonar.sslr.ast.AstSelect; |
29 | 33 |
|
30 | | -import com.google.common.collect.ImmutableSet; |
31 | | -import com.sonar.sslr.api.AstNode; |
32 | | -import com.sonar.sslr.api.AstNodeType; |
33 | | - |
34 | 34 | @Rule(key = SelfAssignmentCheck.CHECK_KEY) |
35 | 35 | public class SelfAssignmentCheck extends PythonCheck { |
36 | 36 |
|
37 | 37 | public static final String CHECK_KEY = "S1656"; |
38 | 38 |
|
39 | 39 | public static final String MESSAGE = "Remove or correct this useless self-assignment."; |
40 | 40 |
|
| 41 | + private Set<String> importedNames = new HashSet<>(); |
| 42 | + |
| 43 | + @Override |
| 44 | + public void visitFile(AstNode node) { |
| 45 | + importedNames.clear(); |
| 46 | + } |
| 47 | + |
41 | 48 | @Override |
42 | 49 | public Set<AstNodeType> subscribedKinds() { |
43 | | - return ImmutableSet.of(PythonGrammar.EXPRESSION_STMT); |
| 50 | + return ImmutableSet.of( |
| 51 | + PythonGrammar.EXPRESSION_STMT, |
| 52 | + PythonGrammar.IMPORT_NAME, |
| 53 | + PythonGrammar.IMPORT_AS_NAME); |
44 | 54 | } |
45 | 55 |
|
46 | 56 | @Override |
47 | 57 | public void visitNode(AstNode node) { |
48 | | - for (AstNode assignOperator : node.getChildren(PythonPunctuator.ASSIGN)) { |
49 | | - if (CheckUtils.equalNodes(assignOperator.getPreviousSibling(), assignOperator.getNextSibling()) && !isException(node)) { |
50 | | - addIssue(assignOperator, MESSAGE); |
| 58 | + if (node.is(PythonGrammar.IMPORT_NAME)) { |
| 59 | + for (AstNode dottedAsName : node.select().children(PythonGrammar.DOTTED_AS_NAMES).children(PythonGrammar.DOTTED_AS_NAME)) { |
| 60 | + AstNode importedName = dottedAsName.getFirstChild().getLastChild(PythonGrammar.NAME); |
| 61 | + addImportedName(dottedAsName, importedName); |
| 62 | + } |
| 63 | + |
| 64 | + } else if (node.is(PythonGrammar.IMPORT_AS_NAME)) { |
| 65 | + AstNode importedName = node.getFirstChild(PythonGrammar.NAME); |
| 66 | + addImportedName(node, importedName); |
| 67 | + |
| 68 | + } else { |
| 69 | + for (AstNode assignOperator : node.getChildren(PythonPunctuator.ASSIGN)) { |
| 70 | + AstNode assigned = assignOperator.getPreviousSibling(); |
| 71 | + if (CheckUtils.equalNodes(assigned, assignOperator.getNextSibling()) && !isException(node, assigned)) { |
| 72 | + addIssue(assignOperator, MESSAGE); |
| 73 | + } |
51 | 74 | } |
52 | 75 | } |
53 | 76 | } |
54 | 77 |
|
55 | | - private static boolean isException(AstNode expressionStatement) { |
56 | | - AstSelect potentialFunctionCalls = expressionStatement.select() |
| 78 | + private void addImportedName(AstNode node, AstNode importedName) { |
| 79 | + AstNode name = importedName; |
| 80 | + AstNode as = node.getFirstChild(PythonKeyword.AS); |
| 81 | + if (as != null) { |
| 82 | + name = as.getNextSibling(); |
| 83 | + } |
| 84 | + importedNames.add(name.getTokenValue()); |
| 85 | + } |
| 86 | + |
| 87 | + private boolean isException(AstNode expressionStatement, AstNode assigned) { |
| 88 | + AstSelect potentialFunctionCalls = assigned.select() |
57 | 89 | .descendants(PythonGrammar.TRAILER) |
58 | 90 | .children(PythonPunctuator.LPARENTHESIS); |
59 | 91 | if (!potentialFunctionCalls.isEmpty()) { |
60 | 92 | return true; |
61 | 93 | } |
| 94 | + if (assigned.getTokens().size() == 1 && importedNames.contains(assigned.getTokenValue())) { |
| 95 | + return true; |
| 96 | + } |
62 | 97 | AstNode suite = expressionStatement.getFirstAncestor(PythonGrammar.SUITE); |
63 | 98 | return suite != null && suite.getParent().is(PythonGrammar.CLASSDEF, PythonGrammar.TRY_STMT); |
64 | 99 | } |
|
0 commit comments