Skip to content

Commit aaf14c7

Browse files
SONARPY-1024: Fix Quickfix for sets, parameters and improve format (ImplicitStringConcatenation) (#1149)
1 parent b1c71c0 commit aaf14c7

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

python-checks/src/main/java/org/sonar/python/checks/ImplicitStringConcatenationCheck.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import org.sonar.python.quickfix.IssueWithQuickFix;
3131
import org.sonar.python.quickfix.PythonQuickFix;
3232

33-
import static org.sonar.python.quickfix.PythonTextEdit.insertAfter;
33+
import static org.sonar.python.quickfix.PythonTextEdit.replaceRange;
3434

3535
@Rule(key = "S5799")
3636
public class ImplicitStringConcatenationCheck extends PythonSubscriptionCheck {
@@ -67,12 +67,12 @@ private static void checkStringLiteral(StringLiteral stringLiteral, Subscription
6767
continue;
6868
}
6969
if (current.firstToken().line() == previous.firstToken().line()) {
70-
createQuickFix(ctx.addIssue(previous.firstToken(), MESSAGE_SINGLE_LINE).secondary(current.firstToken(), null), previous);
70+
createQuickFix(ctx.addIssue(previous.firstToken(), MESSAGE_SINGLE_LINE).secondary(current.firstToken(), null), previous, current);
7171
// Only raise 1 issue per string literal
7272
return;
7373
}
7474
if ((isWithinCollection(stringLiteral) && !isException(previous, current))) {
75-
createQuickFix(ctx.addIssue(previous.firstToken(), MESSAGE_MULTIPLE_LINES).secondary(current.firstToken(), null), previous);
75+
createQuickFix(ctx.addIssue(previous.firstToken(), MESSAGE_MULTIPLE_LINES).secondary(current.firstToken(), null), previous, current);
7676
return;
7777
}
7878
}
@@ -94,26 +94,31 @@ private static boolean haveSameQuotes(StringElement first, StringElement second)
9494
first.value().charAt(first.value().length() - 1) == second.value().charAt(second.value().length() - 1);
9595
}
9696

97-
private static boolean isInFunctionOrArrayOrTupleOrExpression(StringElement token) {
97+
private static boolean isInFunctionOrArrayOrTupleOrExpressionOrSet(StringElement token) {
9898
Tree t = token;
9999
while (t.parent().is(Tree.Kind.STRING_LITERAL)) {
100100
t = t.parent();
101101
}
102-
return t.parent().is(Tree.Kind.ARG_LIST, Tree.Kind.EXPRESSION_LIST, Tree.Kind.PARAMETER_LIST, Tree.Kind.TUPLE);
102+
Tree parent = t.parent();
103+
104+
return parent.is(Tree.Kind.EXPRESSION_LIST, Tree.Kind.PLUS, Tree.Kind.REGULAR_ARGUMENT,
105+
Tree.Kind.SET_LITERAL, Tree.Kind.TUPLE);
103106
}
104107

105-
private static void createQuickFix(PreciseIssue issueRaised, StringElement stringElement) {
108+
private static void createQuickFix(PreciseIssue issueRaised, StringElement start, StringElement end) {
106109
IssueWithQuickFix issue = (IssueWithQuickFix) issueRaised;
110+
String textStart = start.value();
111+
String textEnd = end.value();
107112

108-
if (isInFunctionOrArrayOrTupleOrExpression(stringElement)) {
113+
if (isInFunctionOrArrayOrTupleOrExpressionOrSet(start)) {
109114
PythonQuickFix quickFix = PythonQuickFix.newQuickFix("Add the comma between string or byte tokens.")
110-
.addTextEdit(insertAfter(stringElement, ","))
115+
.addTextEdit(replaceRange(start, end, textStart + ", " + textEnd))
111116
.build();
112117
issue.addQuickFix(quickFix);
113118
}
114119

115120
PythonQuickFix quickFix = PythonQuickFix.newQuickFix("Make the addition sign between string or byte tokens explicit.")
116-
.addTextEdit(insertAfter(stringElement, "+"))
121+
.addTextEdit(replaceRange(start, end, textStart + " + " + textEnd))
117122
.build();
118123
issue.addQuickFix(quickFix);
119124
}

python-checks/src/test/java/org/sonar/python/checks/ImplicitStringConcatenationCheckTest.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ public void test() {
3636
@Test
3737
public void simple_expression_quickfix() {
3838
String codeWithIssue = "a = '1' '2'";
39-
String codeFixed1 = "a = '1'+ '2'";
39+
String codeFixed1 = "a = '1' + '2'";
4040
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1);
4141

4242
codeWithIssue = "a = ['1' '2']";
4343
codeFixed1 = "a = ['1', '2']";
44-
String codeFixed2 = "a = ['1'+ '2']";
44+
String codeFixed2 = "a = ['1' + '2']";
4545
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1, codeFixed2);
4646
}
4747

@@ -52,7 +52,51 @@ public void complex_expression_quickfix() {
5252
String codeFixed1 = "def a():\n" +
5353
" b = ['1', '2']\n";
5454
String codeFixed2 = "def a():\n" +
55-
" b = ['1'+ '2']\n";
55+
" b = ['1' + '2']\n";
56+
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1, codeFixed2);
57+
}
58+
59+
@Test
60+
public void concat_expression() {
61+
String codeWithIssue = "def a():\n" +
62+
" b = ['1'+'2' '3'+'4']\n";
63+
String codeFixed1 = "def a():\n" +
64+
" b = ['1'+'2', '3'+'4']\n";
65+
String codeFixed2 = "def a():\n" +
66+
" b = ['1'+'2' + '3'+'4']\n";
67+
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1, codeFixed2);
68+
}
69+
70+
@Test
71+
public void sets() {
72+
String codeWithIssue = "def a():\n" +
73+
" {'1' '2', '3'}\n";
74+
String codeFixed1 = "def a():\n" +
75+
" {'1', '2', '3'}\n";
76+
String codeFixed2 = "def a():\n" +
77+
" {'1' + '2', '3'}\n";
78+
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1, codeFixed2);
79+
}
80+
81+
@Test
82+
public void parameters() {
83+
String codeWithIssue = "def a():\n" +
84+
" print('1' '2', '3')\n";
85+
String codeFixed1 = "def a():\n" +
86+
" print('1', '2', '3')\n";
87+
String codeFixed2 = "def a():\n" +
88+
" print('1' + '2', '3')\n";
89+
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1, codeFixed2);
90+
}
91+
92+
@Test
93+
public void parameters2() {
94+
String codeWithIssue = "def a():\n" +
95+
" foo('1' '2', '3')\n";
96+
String codeFixed1 = "def a():\n" +
97+
" foo('1', '2', '3')\n";
98+
String codeFixed2 = "def a():\n" +
99+
" foo('1' + '2', '3')\n";
56100
PythonQuickFixVerifier.verify(check, codeWithIssue, codeFixed1, codeFixed2);
57101
}
58102

0 commit comments

Comments
 (0)