From 5dda9f98cefc18d3d3c3e05e0a3d452b3584134d Mon Sep 17 00:00:00 2001 From: erwan-serandour-sonarsource Date: Mon, 6 Nov 2023 11:58:49 +0100 Subject: [PATCH] SONARJAVA-4540 Support Record's Compact Constructors in MethodTreeImpl (#4522) --- .../checks/IndentationCheck_default.java | 12 ++++++ .../java}/checks/IndentationCheck_custom.java | 37 ++++++++++--------- .../java/checks/IndentationCheckTest.java | 5 ++- .../model/declaration/MethodTreeImpl.java | 12 +++++- .../model/declaration/ClassTreeImplTest.java | 2 + .../model/declaration/MethodTreeImplTest.java | 15 ++++++++ 6 files changed, 63 insertions(+), 20 deletions(-) rename {java-checks/src/test/files => java-checks-test-sources/src/main/files/non-compiling}/checks/IndentationCheck_default.java (97%) rename {java-checks/src/test/files => java-checks-test-sources/src/main/java}/checks/IndentationCheck_custom.java (79%) diff --git a/java-checks/src/test/files/checks/IndentationCheck_default.java b/java-checks-test-sources/src/main/files/non-compiling/checks/IndentationCheck_default.java similarity index 97% rename from java-checks/src/test/files/checks/IndentationCheck_default.java rename to java-checks-test-sources/src/main/files/non-compiling/checks/IndentationCheck_default.java index b180ddd44b8..59b85ced348 100644 --- a/java-checks/src/test/files/checks/IndentationCheck_default.java +++ b/java-checks-test-sources/src/main/files/non-compiling/checks/IndentationCheck_default.java @@ -1,6 +1,18 @@ import java.util.stream.IntStream; class TestSwitch { + + public record QonId(String value) { + public QonId { // Noncompliant + Objects.requireNonNull(value, "QonId value cannot be null"); + } + } + + public record QonId_(String value) { + public QonId_ { // compliant + Objects.requireNonNull(value, "QonId value cannot be null"); + } + } enum Color { RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, BLACK, WHITE, ORANGE, BROWN, LIME, PURPLE, GREY, CRIMSON, NAVY, OLIVE, diff --git a/java-checks/src/test/files/checks/IndentationCheck_custom.java b/java-checks-test-sources/src/main/java/checks/IndentationCheck_custom.java similarity index 79% rename from java-checks/src/test/files/checks/IndentationCheck_custom.java rename to java-checks-test-sources/src/main/java/checks/IndentationCheck_custom.java index cc87312d79b..081e64f477d 100644 --- a/java-checks/src/test/files/checks/IndentationCheck_custom.java +++ b/java-checks-test-sources/src/main/java/checks/IndentationCheck_custom.java @@ -1,6 +1,10 @@ +package checks; + +import java.util.List; +import java.util.NoSuchElementException; import java.util.stream.IntStream; -class Foo { +class FooIdentation { int a; // Noncompliant {{Make this line start after 4 spaces instead of 2 in order to indent the code consistently. (Indentation level is at 4.)}} int b; // Compliant - already reported int c; // Compliant - already reported @@ -39,7 +43,7 @@ class Foo { // Noncompliant {{Make this line start after 4 s } } -enum Bar { +enum BarIdentation { A, B, C; @@ -51,7 +55,7 @@ public void foo2() { // Compliant } } -interface Qix { +interface QixIdentation { void foo1(); // Noncompliant @@ -59,26 +63,26 @@ interface Qix { } -class Baz { +class BazIdentation { void foo() { // Noncompliant {{Make this line start after 4 spaces instead of 2 in order to indent the code consistently. (Indentation level is at 4.)}} - new MyInterface() { // Noncompliant {{Make this line start after 8 spaces instead of 4 in order to indent the code consistently. (Indentation level is at 4.)}} - public void foo() { // Compliant + new QixIdentation() { // Noncompliant {{Make this line start after 8 spaces instead of 4 in order to indent the code consistently. (Indentation level is at 4.)}} + public void foo1() { // Compliant } - public void bar() { // Noncompliant + public void foo2() { // Noncompliant } }; } - int[] foo = new int[] { + Object[] foo = new Object[] { 0, - new Foo() + new FooIdentation() }; } - class Qiz { // Noncompliant - public void foo() { // Noncompliant + class QizIndentation { // Noncompliant + public void foo(int foo) { // Noncompliant switch (0) { // Noncompliant case 0: System.out.println(); System.out.println(); // Noncompliant @@ -105,13 +109,12 @@ public void foo() { // Noncompliant : case 3: break; // Compliant } }; + static List list = List.of(1,2,3); static { try{ // Noncompliant {{Make this line start after 8 spaces instead of 4 in order to indent the code consistently. (Indentation level is at 4.)}} - while (keys.hasMoreElements()) { // Noncompliant {{Make this line start after 12 spaces instead of 7 in order to indent the code consistently. (Indentation level is at 4.)}} - s = keys.nextElement(); // Noncompliant {{Make this line start after 16 spaces instead of 8 in order to indent the code consistently. (Indentation level is at 4.)}} - rId = (String) s; - cName = (String) exceptionClassNames.get(rId); - exceptionRepositoryIds.put (cName, rId); + while (list.isEmpty()) { // Noncompliant {{Make this line start after 12 spaces instead of 7 in order to indent the code consistently. (Indentation level is at 4.)}} + int s = list.get(0); // Noncompliant {{Make this line start after 16 spaces instead of 8 in order to indent the code consistently. (Indentation level is at 4.)}} + String k = "hello"; } } catch (NoSuchElementException e) { } } @@ -122,7 +125,7 @@ public static class Inner { // Noncompliant {{Make this line } } -class Lambda { +class LambdaIndentation { void foo() { IntStream .range(1, 5) diff --git a/java-checks/src/test/java/org/sonar/java/checks/IndentationCheckTest.java b/java-checks/src/test/java/org/sonar/java/checks/IndentationCheckTest.java index 71566cd2505..c61b6359336 100644 --- a/java-checks/src/test/java/org/sonar/java/checks/IndentationCheckTest.java +++ b/java-checks/src/test/java/org/sonar/java/checks/IndentationCheckTest.java @@ -23,13 +23,14 @@ import org.sonar.java.checks.verifier.CheckVerifier; import static org.sonar.java.checks.verifier.TestUtils.mainCodeSourcesPath; +import static org.sonar.java.checks.verifier.TestUtils.nonCompilingTestSourcesPath; class IndentationCheckTest { @Test void detected_default_indentation_level() { CheckVerifier.newVerifier() - .onFile("src/test/files/checks/IndentationCheck_default.java") + .onFile(nonCompilingTestSourcesPath("checks/IndentationCheck_default.java")) .withCheck(new IndentationCheck()) .verifyIssues(); } @@ -39,7 +40,7 @@ void detected_custom_level() { IndentationCheck check = new IndentationCheck(); check.indentationLevel = 4; CheckVerifier.newVerifier() - .onFile("src/test/files/checks/IndentationCheck_custom.java") + .onFile(mainCodeSourcesPath("checks/IndentationCheck_custom.java")) .withCheck(check) .verifyIssues(); } diff --git a/java-frontend/src/main/java/org/sonar/java/model/declaration/MethodTreeImpl.java b/java-frontend/src/main/java/org/sonar/java/model/declaration/MethodTreeImpl.java index ffbe82abce6..1dd42942dd8 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/declaration/MethodTreeImpl.java +++ b/java-frontend/src/main/java/org/sonar/java/model/declaration/MethodTreeImpl.java @@ -30,6 +30,7 @@ import org.sonar.java.ast.parser.QualifiedIdentifierListTreeImpl; import org.sonar.java.ast.parser.TypeParameterListTreeImpl; import org.sonar.java.cfg.CFG; +import org.sonar.java.model.InternalSyntaxToken; import org.sonar.java.model.JUtils; import org.sonar.java.model.JavaTree; import org.sonar.java.model.ModifiersUtils; @@ -233,7 +234,16 @@ public void accept(TreeVisitor visitor) { @Override public int getLine() { - return parameters.openParenToken().getLine(); + InternalSyntaxToken token = parameters.openParenToken(); + if (token != null) { + return token.getLine(); + } else { + // type cast may fail, it is fine. We will just add a new case if it happens. + // could first try with type cast and fallback parameters + // but cannot reach full coverage + InternalSyntaxToken name = (InternalSyntaxToken) simpleName().identifierToken(); + return name.getLine(); + } } @Nullable diff --git a/java-frontend/src/test/java/org/sonar/java/model/declaration/ClassTreeImplTest.java b/java-frontend/src/test/java/org/sonar/java/model/declaration/ClassTreeImplTest.java index 95ef5d7b29e..c0138b97364 100644 --- a/java-frontend/src/test/java/org/sonar/java/model/declaration/ClassTreeImplTest.java +++ b/java-frontend/src/test/java/org/sonar/java/model/declaration/ClassTreeImplTest.java @@ -87,6 +87,7 @@ public void visitVariable(VariableTree tree) { void records_members_order() { ClassTree classTree = (ClassTree) JParserTestUtils.parse( "record Output(String title, String summary, String text) {\n" + + " public Output {}" + " public static final String CONST_1 = \"abc\";\n" + " boolean isTooLong() { return true; }\n" + " public static final int CONST_2 = 42;\n" @@ -100,6 +101,7 @@ void records_members_order() { assertThat(classTree).is(Tree.Kind.RECORD); List membersKinds = classTree.members().stream().map(Tree::kind).map(Tree.Kind::name).collect(Collectors.toList()); assertThat(membersKinds).containsExactly( + "CONSTRUCTOR", "VARIABLE", "METHOD", "VARIABLE", diff --git a/java-frontend/src/test/java/org/sonar/java/model/declaration/MethodTreeImplTest.java b/java-frontend/src/test/java/org/sonar/java/model/declaration/MethodTreeImplTest.java index 9feb9c407c5..b51ca3c0414 100644 --- a/java-frontend/src/test/java/org/sonar/java/model/declaration/MethodTreeImplTest.java +++ b/java-frontend/src/test/java/org/sonar/java/model/declaration/MethodTreeImplTest.java @@ -219,6 +219,21 @@ void has_all_syntax_token() { assertThat(method.closeParenToken()).isNotNull(); assertThat(method.semicolonToken()).isNotNull(); assertThat(method.throwsToken()).isNull(); + + method = getUniqueMethod("record Output(String title) { public Output {} }"); + assertThat(method.openParenToken()).isNull(); + assertThat(method.closeParenToken()).isNull(); + assertThat(method.semicolonToken()).isNull(); + assertThat(method.throwsToken()).isNull(); + } + + @Test + void getLine_return_line_of_method_declaration() { + MethodTreeImpl method = getUniqueMethod("class A { public void foo(int arg) throws Exception {} }"); + assertThat(method.getLine()).isEqualTo(1); + + method = getUniqueMethod("record Output(String title) { public Output {} }"); + assertThat(method.getLine()).isEqualTo(1); } @Test