Skip to content

Commit c7af7b3

Browse files
SONARJAVA-6143 Repair quickFix for S1118 rule (#5477)
1 parent 675fcaf commit c7af7b3

2 files changed

Lines changed: 36 additions & 6 deletions

File tree

java-checks-test-sources/default/src/main/java/checks/UtilityClassWithPublicConstructorCheckSample.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,17 @@ public static String concatenate(String s1, String s2) {
257257
}
258258
}
259259

260+
// fix@qf4 {{Add an empty private constructor as the first member of the class.}}
261+
// edit@qf4 [[sl=+0;el=+0;sc=43;ec=43]] {{\n private StringUtilsWithBadOffsets() {\n /* This utility class should not be instantiated */\n }\n}}
262+
// fix@qf5 {{Add an empty private constructor as the last member of the class.}}
263+
// edit@qf5 [[sl=+5;el=+5;sc=6;ec=6]] {{\n\n private StringUtilsWithBadOffsets() {\n /* This utility class should not be instantiated */\n }}}
264+
// fix@qf6 {{Add an empty private constructor before the first method in the class.}}
265+
// edit@qf6 [[sl=+1;el=+1;sc=45;ec=45]] {{\n\n private StringUtilsWithBadOffsets() {\n /* This utility class should not be instantiated */\n }}}
266+
public class StringUtilsWithBadOffsets { // Noncompliant [[sc=16;ec=41;quickfixes=qf4,qf5,qf6]]
267+
public static String HELLO = "Hello world!";
268+
269+
public static String concatenate(String s1, String s2) {
270+
return s1 + s2;
271+
}
272+
}
260273
}

java-checks/src/main/java/org/sonar/java/checks/UtilityClassWithPublicConstructorCheck.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.util.List;
2222
import java.util.Set;
2323
import java.util.stream.Collectors;
24+
25+
import org.apache.commons.lang3.tuple.Pair;
2426
import org.sonar.check.Rule;
2527
import org.sonar.java.checks.helpers.AnnotationsHelper;
2628
import org.sonar.java.checks.helpers.ClassPatternsUtils;
@@ -51,6 +53,8 @@ public class UtilityClassWithPublicConstructorCheck extends IssuableSubscription
5153
"lombok.AllArgsConstructor",
5254
"lombok.RequiredArgsConstructor");
5355

56+
private static final int DEFAULT_PADDING = 2;
57+
5458
private static final Set<String> LOMBOK_CONSTRUCTOR_GENERATOR_NAMES =
5559
LOMBOK_CONSTRUCTOR_GENERATORS.stream()
5660
.map(AnnotationsHelper::annotationTypeIdentifier)
@@ -136,12 +140,7 @@ private static boolean isAccessLevelNotPublic(ExpressionTree tree) {
136140
}
137141

138142
private static List<JavaQuickFix> computeQuickFixes(ClassTree classTree) {
139-
int firstMemberColumnOffset = classTree.members().get(0).firstToken().range().start().columnOffset();
140-
int columnOffsetDiff = firstMemberColumnOffset - classTree.firstToken().range().start().columnOffset();
141-
142-
String leftPadding = " ".repeat(firstMemberColumnOffset);
143-
String constructor = leftPadding + "private " + classTree.simpleName() + "() {\n" + leftPadding + " ".repeat(columnOffsetDiff)
144-
+ "/* This utility class should not be instantiated */\n" + leftPadding + "}";
143+
String constructor = buildPrivateConstructor(classTree);
145144

146145
List<JavaQuickFix> quickFixes = new ArrayList<>();
147146
quickFixes.add(JavaQuickFix.newQuickFix("Add an empty private constructor as the first member of the class.")
@@ -163,4 +162,22 @@ private static List<JavaQuickFix> computeQuickFixes(ClassTree classTree) {
163162
return quickFixes;
164163
}
165164

165+
private static String buildPrivateConstructor(ClassTree classTree) {
166+
int classColumnOffset = classTree.firstToken().range().start().columnOffset();
167+
int firstMemberColumnOffset = classTree.members().get(0).firstToken().range().start().columnOffset();
168+
Pair<Integer, Integer> paddings = calculatePaddingAmounts(classColumnOffset, firstMemberColumnOffset);
169+
170+
String declarationPadding = " ".repeat(paddings.getRight());
171+
String bodyPadding = " ".repeat(paddings.getLeft());
172+
173+
return declarationPadding + "private " + classTree.simpleName() + "() {\n"
174+
+ declarationPadding + bodyPadding + "/* This utility class should not be instantiated */\n"
175+
+ declarationPadding + "}";
176+
}
177+
178+
private static Pair<Integer, Integer> calculatePaddingAmounts(int classColumnOffset, int firstMemberColumnOffset) {
179+
int colDiff = firstMemberColumnOffset - classColumnOffset;
180+
return Pair.of(Math.max(DEFAULT_PADDING, colDiff), colDiff > 0 ? firstMemberColumnOffset : (classColumnOffset + DEFAULT_PADDING));
181+
}
182+
166183
}

0 commit comments

Comments
 (0)