Skip to content

Commit 6430576

Browse files
SONARJAVA-5494 Add quickfixes for S7477 (#5225)
1 parent d3783ce commit 6430576

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@ public class ClassNameInClassTransformCheckSample {
2020
public byte[] transformClassFileNonCompliantDesc(Path path) throws IOException {
2121
ClassFile classFile = ClassFile.of();
2222
ClassModel classModel = classFile.parse(path);
23-
return classFile.transformClass(classModel,
24-
classModel.thisClass(), // Noncompliant {{Use `transformClass` overload without the class name.}}
25-
// ^^^^^^^^^^^^^^^^^^^^^^
26-
classTransform);
23+
return classFile.transformClass(classModel, classModel.thisClass(), classTransform); // Noncompliant {{Use `transformClass` overload without the class name.}} [[quickfixes=qf1]]
24+
// ^^^^^^^^^^^^^^^^^^^^^^
25+
// fix@qf1 {{Remove second argument.}}
26+
// edit@qf1 [[sc=47;ec=73]] {{, }}
27+
2728
}
2829

2930
public byte[] transformClassFileNonCompliant(Path path) throws IOException {
3031
ClassFile classFile = ClassFile.of();
3132
ClassModel classModel = classFile.parse(path);
32-
return classFile.transformClass(classModel,
33-
classModel.thisClass().asSymbol(), // Noncompliant {{Use `transformClass` overload without the class name.}}
34-
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35-
classTransform);
33+
return classFile.transformClass(classModel, classModel.thisClass().asSymbol(), classTransform); // Noncompliant {{Use `transformClass` overload without the class name.}} [[quickfixes=qf2]]
34+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35+
// fix@qf2 {{Remove second argument.}}
36+
// edit@qf2 [[sc=47;ec=84]] {{, }}
37+
3638
}
3739

3840
public byte[] transformClassFileNonCompliantInternalName(Path path) throws IOException {

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020
import java.util.function.Predicate;
2121

2222
import org.sonar.check.Rule;
23+
import org.sonar.java.checks.helpers.QuickFixHelper;
24+
import org.sonar.java.reporting.JavaQuickFix;
25+
import org.sonar.java.reporting.JavaTextEdit;
2326
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
2427
import org.sonar.plugins.java.api.semantic.MethodMatchers;
28+
import org.sonar.plugins.java.api.tree.Arguments;
2529
import org.sonar.plugins.java.api.tree.ExpressionTree;
2630
import org.sonar.plugins.java.api.tree.IdentifierTree;
2731
import org.sonar.plugins.java.api.tree.MemberSelectExpressionTree;
@@ -35,6 +39,7 @@ public class ClassNameInClassTransformCheck extends IssuableSubscriptionVisitor
3539
private static final String CLASS_ENTRY_CLASSNAME = "java.lang.classfile.constantpool.ClassEntry";
3640
private static final String CLASS_MODEL_CLASSNAME = "java.lang.classfile.ClassModel";
3741
private static final String CLASS_DESC_CLASSNAME = "java.lang.constant.ClassDesc";
42+
private static final String ISSUE_MESSAGE = "Use `transformClass` overload without the class name.";
3843

3944
MethodMatchers classTransformMatcher = MethodMatchers.create()
4045
.ofTypes("java.lang.classfile.ClassFile")
@@ -166,11 +171,25 @@ public void visitNode(Tree tree) {
166171
ExpressionTree classDesc = mit.arguments().get(1);
167172
if (classModel instanceof IdentifierTree classModelId &&
168173
(isThisClassOf(classModelId).test(classDesc) || isDescriptorOf(classModelId).test(classDesc))) {
169-
context.reportIssue(this, classDesc, "Use `transformClass` overload without the class name.");
174+
175+
QuickFixHelper.newIssue(context)
176+
.forRule(this)
177+
.onTree(classDesc)
178+
.withMessage(ISSUE_MESSAGE)
179+
.withQuickFix(() -> computeQuickFix(mit.arguments()))
180+
.report();
170181
}
171182
}
172183
}
173184

185+
private static JavaQuickFix computeQuickFix(Arguments arguments) {
186+
return JavaQuickFix
187+
.newQuickFix("Remove second argument.")
188+
.addTextEdit(JavaTextEdit.replaceBetweenTree(
189+
arguments.get(0), false, arguments.get(2), false, ", "))
190+
.build();
191+
}
192+
174193
/** The expression may be of the form `model.thisClass().asInternalName()` or `model.thisClass().name().stringValue(). */
175194
private Predicate<ExpressionTree> isInternalNameOf(IdentifierTree classModel) {
176195
return expression -> check(expression).calls(internalNameMatcher).onExpression().matches(isThisClassOf(classModel))

0 commit comments

Comments
 (0)