From eb350a61874a8233e9d33da1ee6a8c842fac73af Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 22:41:28 +0100 Subject: [PATCH 01/11] Add basic analyzer for Leap --- .../exercises/leap/DoNotUseJavaTime.java | 19 ++++++++++ .../analyzer/exercises/leap/LeapAnalyzer.java | 31 +++++++++++++++ .../exercises/leap/LeapAnalyzerTest.java | 38 +++++++++++++++++++ .../analyzer/exercises/leap/Optimal.java | 5 +++ .../analyzer/exercises/leap/UsesJavaTime.java | 7 ++++ 5 files changed, 100 insertions(+) create mode 100644 src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java create mode 100644 src/main/java/analyzer/exercises/leap/LeapAnalyzer.java create mode 100644 src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java create mode 100644 src/test/resources/analyzer/exercises/leap/Optimal.java create mode 100644 src/test/resources/analyzer/exercises/leap/UsesJavaTime.java diff --git a/src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java b/src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java new file mode 100644 index 00000000..376deaf9 --- /dev/null +++ b/src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java @@ -0,0 +1,19 @@ +package analyzer.exercises.leap; + +import analyzer.Comment; +import analyzer.CommentType; + +/** + * @see Markdown Template + */ +class DoNotUseJavaTime extends Comment { + @Override + public String getKey() { + return "java.leap.do_not_use_java_time"; + } + + @Override + public CommentType getType() { + return CommentType.ESSENTIAL; + } +} diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java new file mode 100644 index 00000000..3b241a9f --- /dev/null +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -0,0 +1,31 @@ +package analyzer.exercises.leap; + +import analyzer.Analysis; +import analyzer.Analyzer; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.visitor.VoidVisitorAdapter; + +import java.util.List; + +public class LeapAnalyzer extends VoidVisitorAdapter implements Analyzer { + private Analysis analysis; + + @Override + public void analyze(List compilationUnits, Analysis analysis) { + this.analysis = analysis; + + for (CompilationUnit compilationUnit : compilationUnits) { + compilationUnit.accept(this, null); + } + } + + @Override + public void visit(MethodCallExpr n, Void arg) { + if (n.toString().contains("Year.isLeap")) { + analysis.addComment(new DoNotUseJavaTime()); + } + + super.visit(n, arg); + } +} diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java new file mode 100644 index 00000000..2b6bbe7b --- /dev/null +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -0,0 +1,38 @@ +package analyzer.exercises.leap; + +import analyzer.Analyzer; +import analyzer.AnalyzerTest; +import analyzer.Comment; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LeapAnalyzerTest extends AnalyzerTest { + @Override + protected Analyzer getAnalyzer() { + return new LeapAnalyzer(); + } + + private static Stream testCases() { + return Stream.of( + Arguments.of("Optimal.java", new Comment[0]), + Arguments.of("UsesJavaTime.java", new Comment[]{new DoNotUseJavaTime()}) + ); + } + + @MethodSource("testCases") + @ParameterizedTest(name = "{0}") + public void testCommentsOnSolution(String solutionFile, Comment... expectedComments) { + var actual = analyzeResourceFile(getResourceFileName(solutionFile)); + + assertThat(actual.getComments()).containsExactly(expectedComments); + } + + private static String getResourceFileName(String testFileName) { + return "/analyzer/exercises/leap/" + testFileName; + } +} diff --git a/src/test/resources/analyzer/exercises/leap/Optimal.java b/src/test/resources/analyzer/exercises/leap/Optimal.java new file mode 100644 index 00000000..2987c90a --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/Optimal.java @@ -0,0 +1,5 @@ +class Leap { + boolean isLeapYear(int year) { + return year % 400 == 0 || year % 100 != 0 && year % 4 == 0; + } +} diff --git a/src/test/resources/analyzer/exercises/leap/UsesJavaTime.java b/src/test/resources/analyzer/exercises/leap/UsesJavaTime.java new file mode 100644 index 00000000..e3957535 --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/UsesJavaTime.java @@ -0,0 +1,7 @@ +import java.time.Year; + +class Leap { + boolean isLeapYear(int year) { + return Year.isLeap(year); + } +} From b6fd3b99292d647371194d96b86ca2ea1f536ba1 Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 22:45:21 +0100 Subject: [PATCH 02/11] Add golden test for Leap --- src/main/java/analyzer/AnalyzerRoot.java | 2 ++ tests/leap/expected_analysis.json | 10 ++++++++++ tests/leap/expected_tags.json | 1 + tests/leap/src/main/java/Leap.java | 7 +++++++ 4 files changed, 20 insertions(+) create mode 100644 tests/leap/expected_analysis.json create mode 100644 tests/leap/expected_tags.json create mode 100644 tests/leap/src/main/java/Leap.java diff --git a/src/main/java/analyzer/AnalyzerRoot.java b/src/main/java/analyzer/AnalyzerRoot.java index 57a37914..4d063f0f 100644 --- a/src/main/java/analyzer/AnalyzerRoot.java +++ b/src/main/java/analyzer/AnalyzerRoot.java @@ -3,6 +3,7 @@ import analyzer.comments.FeedbackRequest; import analyzer.exercises.GlobalAnalyzer; import analyzer.exercises.hamming.HammingAnalyzer; +import analyzer.exercises.leap.LeapAnalyzer; import analyzer.exercises.twofer.TwoferAnalyzer; import com.github.javaparser.ast.CompilationUnit; @@ -30,6 +31,7 @@ private static List createAnalyzers(String slug) { switch (slug) { case "hamming" -> analyzers.add(new HammingAnalyzer()); + case "leap" -> analyzers.add(new LeapAnalyzer()); case "two-fer" -> analyzers.add(new TwoferAnalyzer()); } diff --git a/tests/leap/expected_analysis.json b/tests/leap/expected_analysis.json new file mode 100644 index 00000000..2c4fd09b --- /dev/null +++ b/tests/leap/expected_analysis.json @@ -0,0 +1,10 @@ +{"comments": [ + { + "comment": "java.leap.do_not_use_java_time", + "type": "essential" + }, + { + "comment": "java.general.feedback_request", + "type": "informative" + } +]} \ No newline at end of file diff --git a/tests/leap/expected_tags.json b/tests/leap/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/leap/src/main/java/Leap.java b/tests/leap/src/main/java/Leap.java new file mode 100644 index 00000000..e3957535 --- /dev/null +++ b/tests/leap/src/main/java/Leap.java @@ -0,0 +1,7 @@ +import java.time.Year; + +class Leap { + boolean isLeapYear(int year) { + return Year.isLeap(year); + } +} From 1cd6abeac94acf443525a6853f423b83420cb6c3 Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 22:59:23 +0100 Subject: [PATCH 03/11] Catch hard-coded test cases in Leap --- .../analyzer/exercises/leap/LeapAnalyzer.java | 30 ++++++++++++++++++- .../exercises/leap/LeapAnalyzerTest.java | 4 ++- .../exercises/leap/HardCodedTestCases.java | 5 ++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java index 3b241a9f..e3ebf684 100644 --- a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -2,13 +2,20 @@ import analyzer.Analysis; import analyzer.Analyzer; +import analyzer.comments.AvoidHardCodedTestCases; import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.IntegerLiteralExpr; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class LeapAnalyzer extends VoidVisitorAdapter implements Analyzer { + private static final Set TEST_CASES = Set.of(1960, 1996, 2000, 2400); + + private final Set intLiterals = new HashSet<>(); private Analysis analysis; @Override @@ -20,10 +27,31 @@ public void analyze(List compilationUnits, Analysis analysis) { } } + @Override + public void visit(CompilationUnit n, Void arg) { + // Reset state for each compilation unit + this.intLiterals.clear(); + + super.visit(n, arg); + } + @Override public void visit(MethodCallExpr n, Void arg) { if (n.toString().contains("Year.isLeap")) { - analysis.addComment(new DoNotUseJavaTime()); + this.analysis.addComment(new DoNotUseJavaTime()); + } + + super.visit(n, arg); + } + + @Override + public void visit(IntegerLiteralExpr n, Void arg) { + if (n.asNumber() instanceof Integer i) { + this.intLiterals.add(i); + } + + if (this.intLiterals.containsAll(TEST_CASES)) { + this.analysis.addComment(new AvoidHardCodedTestCases()); } super.visit(n, arg); diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java index 2b6bbe7b..fb2bb0c6 100644 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -3,6 +3,7 @@ import analyzer.Analyzer; import analyzer.AnalyzerTest; import analyzer.Comment; +import analyzer.comments.AvoidHardCodedTestCases; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -20,7 +21,8 @@ protected Analyzer getAnalyzer() { private static Stream testCases() { return Stream.of( Arguments.of("Optimal.java", new Comment[0]), - Arguments.of("UsesJavaTime.java", new Comment[]{new DoNotUseJavaTime()}) + Arguments.of("UsesJavaTime.java", new Comment[]{new DoNotUseJavaTime()}), + Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}) ); } diff --git a/src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java b/src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java new file mode 100644 index 00000000..84e26b16 --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java @@ -0,0 +1,5 @@ +class Leap { + boolean isLeapYear(int year) { + return year == 1960 || year == 2000 || year == 2400 || year == 1996; + } +} From 9178e662b3dc0d269800ab258cb22215c4c694fa Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 23:18:05 +0100 Subject: [PATCH 04/11] Catch use of `GregorianCalendar.isLeapYear` --- ...NotUseJavaTime.java => AvoidBuiltInMethods.java} | 6 +++--- .../java/analyzer/exercises/leap/LeapAnalyzer.java | 13 +++++++++---- .../analyzer/exercises/leap/LeapAnalyzerTest.java | 3 ++- .../exercises/leap/UsesGregorianCalendar.java | 9 +++++++++ 4 files changed, 23 insertions(+), 8 deletions(-) rename src/main/java/analyzer/exercises/leap/{DoNotUseJavaTime.java => AvoidBuiltInMethods.java} (63%) create mode 100644 src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java diff --git a/src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java b/src/main/java/analyzer/exercises/leap/AvoidBuiltInMethods.java similarity index 63% rename from src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java rename to src/main/java/analyzer/exercises/leap/AvoidBuiltInMethods.java index 376deaf9..e74faf8f 100644 --- a/src/main/java/analyzer/exercises/leap/DoNotUseJavaTime.java +++ b/src/main/java/analyzer/exercises/leap/AvoidBuiltInMethods.java @@ -4,12 +4,12 @@ import analyzer.CommentType; /** - * @see Markdown Template + * @see Markdown Template */ -class DoNotUseJavaTime extends Comment { +class AvoidBuiltInMethods extends Comment { @Override public String getKey() { - return "java.leap.do_not_use_java_time"; + return "java.leap.avoid_built_in_methods"; } @Override diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java index e3ebf684..b06b28ec 100644 --- a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -4,8 +4,8 @@ import analyzer.Analyzer; import analyzer.comments.AvoidHardCodedTestCases; import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.ImportDeclaration; import com.github.javaparser.ast.expr.IntegerLiteralExpr; -import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import java.util.HashSet; @@ -14,6 +14,10 @@ public class LeapAnalyzer extends VoidVisitorAdapter implements Analyzer { private static final Set TEST_CASES = Set.of(1960, 1996, 2000, 2400); + private static final Set DISALLOWED_IMPORTS = Set.of( + "java.time", + "java.util.GregorianCalendar" + ); private final Set intLiterals = new HashSet<>(); private Analysis analysis; @@ -36,9 +40,10 @@ public void visit(CompilationUnit n, Void arg) { } @Override - public void visit(MethodCallExpr n, Void arg) { - if (n.toString().contains("Year.isLeap")) { - this.analysis.addComment(new DoNotUseJavaTime()); + public void visit(ImportDeclaration n, Void arg) { + var name = n.getNameAsString(); + if (DISALLOWED_IMPORTS.stream().anyMatch(name::contains)) { + this.analysis.addComment(new AvoidBuiltInMethods()); } super.visit(n, arg); diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java index fb2bb0c6..512cbc3c 100644 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -21,7 +21,8 @@ protected Analyzer getAnalyzer() { private static Stream testCases() { return Stream.of( Arguments.of("Optimal.java", new Comment[0]), - Arguments.of("UsesJavaTime.java", new Comment[]{new DoNotUseJavaTime()}), + Arguments.of("UsesJavaTime.java", new Comment[]{new AvoidBuiltInMethods()}), + Arguments.of("UsesGregorianCalendar.java", new Comment[]{new AvoidBuiltInMethods()}), Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}) ); } diff --git a/src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java b/src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java new file mode 100644 index 00000000..8f5c80b1 --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java @@ -0,0 +1,9 @@ +import java.util.Calendar; +import java.util.GregorianCalendar; + +class Leap { + boolean isLeapYear(int year) { + var calendar = new GregorianCalendar(Calendar.ALL_STYLES); + return calendar.isLeapYear(year); + } +} \ No newline at end of file From 6d637c5c806c5286512006db5e337d09e23d2109 Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 23:20:09 +0100 Subject: [PATCH 05/11] Update expected analysis --- tests/leap/expected_analysis.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/leap/expected_analysis.json b/tests/leap/expected_analysis.json index 2c4fd09b..63855ef8 100644 --- a/tests/leap/expected_analysis.json +++ b/tests/leap/expected_analysis.json @@ -1,6 +1,6 @@ {"comments": [ { - "comment": "java.leap.do_not_use_java_time", + "comment": "java.leap.avoid_built_in_methods", "type": "essential" }, { From 46320898bd342e9dd83b3b4a5bf0ab2631d37606 Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 23:27:32 +0100 Subject: [PATCH 06/11] Rename comment key --- src/main/java/analyzer/exercises/leap/LeapAnalyzer.java | 2 +- .../{AvoidBuiltInMethods.java => NoBuiltInMethods.java} | 6 +++--- src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java | 4 ++-- tests/leap/expected_analysis.json | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/main/java/analyzer/exercises/leap/{AvoidBuiltInMethods.java => NoBuiltInMethods.java} (63%) diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java index b06b28ec..bba4bde0 100644 --- a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -43,7 +43,7 @@ public void visit(CompilationUnit n, Void arg) { public void visit(ImportDeclaration n, Void arg) { var name = n.getNameAsString(); if (DISALLOWED_IMPORTS.stream().anyMatch(name::contains)) { - this.analysis.addComment(new AvoidBuiltInMethods()); + this.analysis.addComment(new NoBuiltInMethods()); } super.visit(n, arg); diff --git a/src/main/java/analyzer/exercises/leap/AvoidBuiltInMethods.java b/src/main/java/analyzer/exercises/leap/NoBuiltInMethods.java similarity index 63% rename from src/main/java/analyzer/exercises/leap/AvoidBuiltInMethods.java rename to src/main/java/analyzer/exercises/leap/NoBuiltInMethods.java index e74faf8f..d7181cf7 100644 --- a/src/main/java/analyzer/exercises/leap/AvoidBuiltInMethods.java +++ b/src/main/java/analyzer/exercises/leap/NoBuiltInMethods.java @@ -4,12 +4,12 @@ import analyzer.CommentType; /** - * @see Markdown Template + * @see Markdown Template */ -class AvoidBuiltInMethods extends Comment { +class NoBuiltInMethods extends Comment { @Override public String getKey() { - return "java.leap.avoid_built_in_methods"; + return "java.leap.no_built_in_methods"; } @Override diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java index 512cbc3c..68914496 100644 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -21,8 +21,8 @@ protected Analyzer getAnalyzer() { private static Stream testCases() { return Stream.of( Arguments.of("Optimal.java", new Comment[0]), - Arguments.of("UsesJavaTime.java", new Comment[]{new AvoidBuiltInMethods()}), - Arguments.of("UsesGregorianCalendar.java", new Comment[]{new AvoidBuiltInMethods()}), + Arguments.of("UsesJavaTime.java", new Comment[]{new NoBuiltInMethods()}), + Arguments.of("UsesGregorianCalendar.java", new Comment[]{new NoBuiltInMethods()}), Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}) ); } diff --git a/tests/leap/expected_analysis.json b/tests/leap/expected_analysis.json index 63855ef8..d7466506 100644 --- a/tests/leap/expected_analysis.json +++ b/tests/leap/expected_analysis.json @@ -1,6 +1,6 @@ {"comments": [ { - "comment": "java.leap.avoid_built_in_methods", + "comment": "java.leap.no_built_in_methods", "type": "essential" }, { From 59dc03fd5af9ff8a4df829034e3234a8068a385d Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sat, 20 Jan 2024 23:48:22 +0100 Subject: [PATCH 07/11] Suggest to not use conditional logic --- .../exercises/leap/AvoidConditionalLogic.java | 19 +++++++++++++++++++ .../analyzer/exercises/leap/LeapAnalyzer.java | 14 ++++++++++++++ .../exercises/leap/LeapAnalyzerTest.java | 4 +++- .../exercises/leap/UsesIfStatements.java | 8 ++++++++ .../analyzer/exercises/leap/UsesTernary.java | 5 +++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/main/java/analyzer/exercises/leap/AvoidConditionalLogic.java create mode 100644 src/test/resources/analyzer/exercises/leap/UsesIfStatements.java create mode 100644 src/test/resources/analyzer/exercises/leap/UsesTernary.java diff --git a/src/main/java/analyzer/exercises/leap/AvoidConditionalLogic.java b/src/main/java/analyzer/exercises/leap/AvoidConditionalLogic.java new file mode 100644 index 00000000..ce79baab --- /dev/null +++ b/src/main/java/analyzer/exercises/leap/AvoidConditionalLogic.java @@ -0,0 +1,19 @@ +package analyzer.exercises.leap; + +import analyzer.Comment; +import analyzer.CommentType; + +/** + * @see Markdown Template + */ +class AvoidConditionalLogic extends Comment { + @Override + public String getKey() { + return "java.leap.avoid_conditional_logic"; + } + + @Override + public CommentType getType() { + return CommentType.ACTIONABLE; + } +} diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java index bba4bde0..038d7c14 100644 --- a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -5,7 +5,9 @@ import analyzer.comments.AvoidHardCodedTestCases; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.ImportDeclaration; +import com.github.javaparser.ast.expr.ConditionalExpr; import com.github.javaparser.ast.expr.IntegerLiteralExpr; +import com.github.javaparser.ast.stmt.IfStmt; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import java.util.HashSet; @@ -61,4 +63,16 @@ public void visit(IntegerLiteralExpr n, Void arg) { super.visit(n, arg); } + + @Override + public void visit(IfStmt n, Void arg) { + this.analysis.addComment(new AvoidConditionalLogic()); + super.visit(n, arg); + } + + @Override + public void visit(ConditionalExpr n, Void arg) { + this.analysis.addComment(new AvoidConditionalLogic()); + super.visit(n, arg); + } } diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java index 68914496..93099a7f 100644 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -23,7 +23,9 @@ private static Stream testCases() { Arguments.of("Optimal.java", new Comment[0]), Arguments.of("UsesJavaTime.java", new Comment[]{new NoBuiltInMethods()}), Arguments.of("UsesGregorianCalendar.java", new Comment[]{new NoBuiltInMethods()}), - Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}) + Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}), + Arguments.of("UsesIfStatements.java", new Comment[]{new AvoidConditionalLogic()}), + Arguments.of("UsesTernary.java", new Comment[]{new AvoidConditionalLogic()}) ); } diff --git a/src/test/resources/analyzer/exercises/leap/UsesIfStatements.java b/src/test/resources/analyzer/exercises/leap/UsesIfStatements.java new file mode 100644 index 00000000..939da788 --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/UsesIfStatements.java @@ -0,0 +1,8 @@ +class Leap { + boolean isLeapYear(int year) { + if (year % 400 == 0) return true; + if (year % 100 == 0) return false; + if (year % 4 == 0) return true; + return false; + } +} \ No newline at end of file diff --git a/src/test/resources/analyzer/exercises/leap/UsesTernary.java b/src/test/resources/analyzer/exercises/leap/UsesTernary.java new file mode 100644 index 00000000..c6a484c9 --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/UsesTernary.java @@ -0,0 +1,5 @@ +class Leap { + boolean isLeapYear(int year) { + return (year % 400 == 0) ? true : (year % 100 == 0) ? false : (year % 4 == 0) ? true : false; + } +} \ No newline at end of file From fd6f664b83f6eedce39b3d251a91eb40f515d4b7 Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sun, 21 Jan 2024 00:10:18 +0100 Subject: [PATCH 08/11] Suggest to use no more than 3 checks --- .../analyzer/exercises/leap/LeapAnalyzer.java | 25 +++++++++++++++++-- .../leap/UseMinimumNumberOfChecks.java | 19 ++++++++++++++ .../exercises/leap/LeapAnalyzerTest.java | 5 ++-- .../exercises/leap/TooManyChecks.java | 5 ++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/main/java/analyzer/exercises/leap/UseMinimumNumberOfChecks.java create mode 100644 src/test/resources/analyzer/exercises/leap/TooManyChecks.java diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java index 038d7c14..acd66a7e 100644 --- a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -5,6 +5,8 @@ import analyzer.comments.AvoidHardCodedTestCases; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.ImportDeclaration; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.BinaryExpr; import com.github.javaparser.ast.expr.ConditionalExpr; import com.github.javaparser.ast.expr.IntegerLiteralExpr; import com.github.javaparser.ast.stmt.IfStmt; @@ -43,8 +45,7 @@ public void visit(CompilationUnit n, Void arg) { @Override public void visit(ImportDeclaration n, Void arg) { - var name = n.getNameAsString(); - if (DISALLOWED_IMPORTS.stream().anyMatch(name::contains)) { + if (isUsingBuiltInMethods(n)) { this.analysis.addComment(new NoBuiltInMethods()); } @@ -75,4 +76,24 @@ public void visit(ConditionalExpr n, Void arg) { this.analysis.addComment(new AvoidConditionalLogic()); super.visit(n, arg); } + + @Override + public void visit(MethodDeclaration n, Void arg) { + if (n.getNameAsString().equals("isLeapYear") && hasMoreThanThreeChecks(n)) { + this.analysis.addComment(new UseMinimumNumberOfChecks()); + } + super.visit(n, arg); + } + + private static boolean isUsingBuiltInMethods(ImportDeclaration node) { + var name = node.getNameAsString(); + return DISALLOWED_IMPORTS.stream().anyMatch(name::contains); + } + + private static boolean hasMoreThanThreeChecks(MethodDeclaration node) { + var booleanOperators = node.findAll(BinaryExpr.class, + x -> x.getOperator() == BinaryExpr.Operator.AND || x.getOperator() == BinaryExpr.Operator.OR); + + return booleanOperators.size() > 2; + } } diff --git a/src/main/java/analyzer/exercises/leap/UseMinimumNumberOfChecks.java b/src/main/java/analyzer/exercises/leap/UseMinimumNumberOfChecks.java new file mode 100644 index 00000000..7a909b0a --- /dev/null +++ b/src/main/java/analyzer/exercises/leap/UseMinimumNumberOfChecks.java @@ -0,0 +1,19 @@ +package analyzer.exercises.leap; + +import analyzer.Comment; +import analyzer.CommentType; + +/** + * @see Markdown Template + */ +class UseMinimumNumberOfChecks extends Comment { + @Override + public String getKey() { + return "java.leap.use_minimum_number_of_checks"; + } + + @Override + public CommentType getType() { + return CommentType.ACTIONABLE; + } +} diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java index 93099a7f..f807bddc 100644 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -25,7 +25,8 @@ private static Stream testCases() { Arguments.of("UsesGregorianCalendar.java", new Comment[]{new NoBuiltInMethods()}), Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}), Arguments.of("UsesIfStatements.java", new Comment[]{new AvoidConditionalLogic()}), - Arguments.of("UsesTernary.java", new Comment[]{new AvoidConditionalLogic()}) + Arguments.of("UsesTernary.java", new Comment[]{new AvoidConditionalLogic()}), + Arguments.of("TooManyChecks.java", new Comment[]{new UseMinimumNumberOfChecks()}) ); } @@ -34,7 +35,7 @@ private static Stream testCases() { public void testCommentsOnSolution(String solutionFile, Comment... expectedComments) { var actual = analyzeResourceFile(getResourceFileName(solutionFile)); - assertThat(actual.getComments()).containsExactly(expectedComments); + assertThat(actual.getComments()).contains(expectedComments); } private static String getResourceFileName(String testFileName) { diff --git a/src/test/resources/analyzer/exercises/leap/TooManyChecks.java b/src/test/resources/analyzer/exercises/leap/TooManyChecks.java new file mode 100644 index 00000000..ce273627 --- /dev/null +++ b/src/test/resources/analyzer/exercises/leap/TooManyChecks.java @@ -0,0 +1,5 @@ +class Leap { + boolean isLeapYear(int year) { + return year % 4 == 0 && year % 100 != 0 || year % 100 == 0 && year % 400 == 0; + } +} From 1e8a9cfca10e08f70547cb2d78f43917fe70dcc6 Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sun, 21 Jan 2024 00:13:58 +0100 Subject: [PATCH 09/11] Update unit tests --- .../java/analyzer/exercises/leap/LeapAnalyzerTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java index f807bddc..a5575a03 100644 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java @@ -4,6 +4,7 @@ import analyzer.AnalyzerTest; import analyzer.Comment; import analyzer.comments.AvoidHardCodedTestCases; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -18,9 +19,15 @@ protected Analyzer getAnalyzer() { return new LeapAnalyzer(); } + @Test + public void noCommentsOnOptimalSolution() { + var actual = analyzeResourceFile(getResourceFileName("Optimal.java")); + + assertThat(actual.getComments()).isEmpty(); + } + private static Stream testCases() { return Stream.of( - Arguments.of("Optimal.java", new Comment[0]), Arguments.of("UsesJavaTime.java", new Comment[]{new NoBuiltInMethods()}), Arguments.of("UsesGregorianCalendar.java", new Comment[]{new NoBuiltInMethods()}), Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}), From c9383c1c1b893509920dd4d075dba844db12a11d Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sun, 21 Jan 2024 20:26:20 +0100 Subject: [PATCH 10/11] Refactor VoidVisitorAdapter analyzers to pass Analysis as argument --- .../analyzer/exercises/GlobalAnalyzer.java | 18 ++++--- .../analyzer/exercises/leap/LeapAnalyzer.java | 47 +++++++++---------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/main/java/analyzer/exercises/GlobalAnalyzer.java b/src/main/java/analyzer/exercises/GlobalAnalyzer.java index b35c2da1..0f31f99b 100644 --- a/src/main/java/analyzer/exercises/GlobalAnalyzer.java +++ b/src/main/java/analyzer/exercises/GlobalAnalyzer.java @@ -11,33 +11,31 @@ import java.util.List; -public class GlobalAnalyzer extends VoidVisitorAdapter implements Analyzer { - private Analysis analysis; +public class GlobalAnalyzer extends VoidVisitorAdapter implements Analyzer { @Override public void analyze(List compilationUnits, Analysis analysis) { - this.analysis = analysis; for (CompilationUnit compilationUnit : compilationUnits) { - compilationUnit.accept(this, null); + compilationUnit.accept(this, analysis); } } @Override - public void visit(MethodDeclaration n, Void arg) { - if (isMainMethod(n)) { + public void visit(MethodDeclaration node, Analysis analysis) { + if (isMainMethod(node)) { analysis.addComment(new DoNotUseMainMethod()); } - super.visit(n, arg); + super.visit(node, analysis); } @Override - public void visit(MethodCallExpr n, Void arg) { - if (isPrintStatement(n)) { + public void visit(MethodCallExpr node, Analysis analysis) { + if (isPrintStatement(node)) { analysis.addComment(new AvoidPrintStatements()); } - super.visit(n, arg); + super.visit(node, analysis); } private static boolean isMainMethod(MethodDeclaration node) { diff --git a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java index acd66a7e..fd5289cf 100644 --- a/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java +++ b/src/main/java/analyzer/exercises/leap/LeapAnalyzer.java @@ -16,7 +16,7 @@ import java.util.List; import java.util.Set; -public class LeapAnalyzer extends VoidVisitorAdapter implements Analyzer { +public class LeapAnalyzer extends VoidVisitorAdapter implements Analyzer { private static final Set TEST_CASES = Set.of(1960, 1996, 2000, 2400); private static final Set DISALLOWED_IMPORTS = Set.of( "java.time", @@ -24,65 +24,62 @@ public class LeapAnalyzer extends VoidVisitorAdapter implements Analyzer { ); private final Set intLiterals = new HashSet<>(); - private Analysis analysis; @Override public void analyze(List compilationUnits, Analysis analysis) { - this.analysis = analysis; - for (CompilationUnit compilationUnit : compilationUnits) { - compilationUnit.accept(this, null); + compilationUnit.accept(this, analysis); } } @Override - public void visit(CompilationUnit n, Void arg) { + public void visit(CompilationUnit node, Analysis analysis) { // Reset state for each compilation unit this.intLiterals.clear(); - super.visit(n, arg); + super.visit(node, analysis); } @Override - public void visit(ImportDeclaration n, Void arg) { - if (isUsingBuiltInMethods(n)) { - this.analysis.addComment(new NoBuiltInMethods()); + public void visit(ImportDeclaration node, Analysis analysis) { + if (isUsingBuiltInMethods(node)) { + analysis.addComment(new NoBuiltInMethods()); } - super.visit(n, arg); + super.visit(node, analysis); } @Override - public void visit(IntegerLiteralExpr n, Void arg) { - if (n.asNumber() instanceof Integer i) { + public void visit(IntegerLiteralExpr node, Analysis analysis) { + if (node.asNumber() instanceof Integer i) { this.intLiterals.add(i); } if (this.intLiterals.containsAll(TEST_CASES)) { - this.analysis.addComment(new AvoidHardCodedTestCases()); + analysis.addComment(new AvoidHardCodedTestCases()); } - super.visit(n, arg); + super.visit(node, analysis); } @Override - public void visit(IfStmt n, Void arg) { - this.analysis.addComment(new AvoidConditionalLogic()); - super.visit(n, arg); + public void visit(IfStmt node, Analysis analysis) { + analysis.addComment(new AvoidConditionalLogic()); + super.visit(node, analysis); } @Override - public void visit(ConditionalExpr n, Void arg) { - this.analysis.addComment(new AvoidConditionalLogic()); - super.visit(n, arg); + public void visit(ConditionalExpr node, Analysis analysis) { + analysis.addComment(new AvoidConditionalLogic()); + super.visit(node, analysis); } @Override - public void visit(MethodDeclaration n, Void arg) { - if (n.getNameAsString().equals("isLeapYear") && hasMoreThanThreeChecks(n)) { - this.analysis.addComment(new UseMinimumNumberOfChecks()); + public void visit(MethodDeclaration node, Analysis analysis) { + if (node.getNameAsString().equals("isLeapYear") && hasMoreThanThreeChecks(node)) { + analysis.addComment(new UseMinimumNumberOfChecks()); } - super.visit(n, arg); + super.visit(node, analysis); } private static boolean isUsingBuiltInMethods(ImportDeclaration node) { From 17f0bda3c79316d60817d5a65a23c93aea8d849a Mon Sep 17 00:00:00 2001 From: Sander Ploegsma Date: Sun, 21 Jan 2024 20:34:08 +0100 Subject: [PATCH 11/11] Convert Leap analyzer unit tests to golden tests --- bin/run-tests.sh | 10 ++-- .../exercises/leap/LeapAnalyzerTest.java | 51 ------------------- .../analyzer/exercises/leap/UsesJavaTime.java | 7 --- .../hard-coded-test-cases/.meta/config.json | 29 +++++++++++ .../expected_analysis.json | 14 +++++ .../expected_tags.json | 0 .../src/main/java/Leap.java | 0 tests/leap/optimal-solution/.meta/config.json | 29 +++++++++++ .../optimal-solution/expected_analysis.json | 1 + .../leap/optimal-solution/expected_tags.json | 1 + .../optimal-solution/src/main/java/Leap.java | 0 .../.meta/config.json | 29 +++++++++++ .../expected_analysis.json | 0 .../expected_tags.json | 1 + .../src/main/java/Leap.java | 0 .../using-if-statements/.meta/config.json | 29 +++++++++++ .../expected_analysis.json | 10 ++++ .../using-if-statements/expected_tags.json | 1 + .../src/main/java/Leap.java | 0 tests/leap/using-java-time/.meta/config.json | 29 +++++++++++ .../using-java-time/expected_analysis.json | 10 ++++ tests/leap/using-java-time/expected_tags.json | 1 + .../src/main/java/Leap.java | 0 tests/leap/using-ternary/.meta/config.json | 29 +++++++++++ .../leap/using-ternary/expected_analysis.json | 10 ++++ tests/leap/using-ternary/expected_tags.json | 1 + .../using-ternary/src/main/java/Leap.java | 0 .../using-too-many-checks/.meta/config.json | 29 +++++++++++ .../expected_analysis.json | 10 ++++ .../using-too-many-checks/expected_tags.json | 1 + .../src/main/java/Leap.java | 0 31 files changed, 269 insertions(+), 63 deletions(-) delete mode 100644 src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java delete mode 100644 src/test/resources/analyzer/exercises/leap/UsesJavaTime.java create mode 100644 tests/leap/hard-coded-test-cases/.meta/config.json create mode 100644 tests/leap/hard-coded-test-cases/expected_analysis.json rename tests/leap/{ => hard-coded-test-cases}/expected_tags.json (100%) rename src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java => tests/leap/hard-coded-test-cases/src/main/java/Leap.java (100%) create mode 100644 tests/leap/optimal-solution/.meta/config.json create mode 100644 tests/leap/optimal-solution/expected_analysis.json create mode 100644 tests/leap/optimal-solution/expected_tags.json rename src/test/resources/analyzer/exercises/leap/Optimal.java => tests/leap/optimal-solution/src/main/java/Leap.java (100%) create mode 100644 tests/leap/using-gregorian-calendar/.meta/config.json rename tests/leap/{ => using-gregorian-calendar}/expected_analysis.json (100%) create mode 100644 tests/leap/using-gregorian-calendar/expected_tags.json rename src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java => tests/leap/using-gregorian-calendar/src/main/java/Leap.java (100%) create mode 100644 tests/leap/using-if-statements/.meta/config.json create mode 100644 tests/leap/using-if-statements/expected_analysis.json create mode 100644 tests/leap/using-if-statements/expected_tags.json rename src/test/resources/analyzer/exercises/leap/UsesIfStatements.java => tests/leap/using-if-statements/src/main/java/Leap.java (100%) create mode 100644 tests/leap/using-java-time/.meta/config.json create mode 100644 tests/leap/using-java-time/expected_analysis.json create mode 100644 tests/leap/using-java-time/expected_tags.json rename tests/leap/{ => using-java-time}/src/main/java/Leap.java (100%) create mode 100644 tests/leap/using-ternary/.meta/config.json create mode 100644 tests/leap/using-ternary/expected_analysis.json create mode 100644 tests/leap/using-ternary/expected_tags.json rename src/test/resources/analyzer/exercises/leap/UsesTernary.java => tests/leap/using-ternary/src/main/java/Leap.java (100%) create mode 100644 tests/leap/using-too-many-checks/.meta/config.json create mode 100644 tests/leap/using-too-many-checks/expected_analysis.json create mode 100644 tests/leap/using-too-many-checks/expected_tags.json rename src/test/resources/analyzer/exercises/leap/TooManyChecks.java => tests/leap/using-too-many-checks/src/main/java/Leap.java (100%) diff --git a/bin/run-tests.sh b/bin/run-tests.sh index 8060ca08..b4d319bd 100755 --- a/bin/run-tests.sh +++ b/bin/run-tests.sh @@ -14,15 +14,15 @@ exit_code=0 # Iterate over all test directories -for test_dir in tests/*; do - test_dir_name=$(basename "${test_dir}") +for test_dir in $(find tests -name expected_analysis.json | rev | cut -d '/' -f 2- | rev); do test_dir_path=$(realpath "${test_dir}") + test_slug=$(echo "${test_dir}" | awk -F/ '{ print $2 }') - bin/run.sh "${test_dir_name}" "${test_dir_path}/" "${test_dir_path}/" + bin/run.sh "${test_slug}" "${test_dir_path}/" "${test_dir_path}/" for file in analysis.json tags.json; do expected_file="expected_${file}" - echo "${test_dir_name}: comparing ${file} to ${expected_file}" + echo "${test_dir}: comparing ${file} to ${expected_file}" if ! diff "${test_dir_path}/${file}" "${test_dir_path}/${expected_file}"; then exit_code=1 @@ -30,4 +30,4 @@ for test_dir in tests/*; do done done -exit ${exit_code} +exit ${exit_code} \ No newline at end of file diff --git a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java b/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java deleted file mode 100644 index a5575a03..00000000 --- a/src/test/java/analyzer/exercises/leap/LeapAnalyzerTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package analyzer.exercises.leap; - -import analyzer.Analyzer; -import analyzer.AnalyzerTest; -import analyzer.Comment; -import analyzer.comments.AvoidHardCodedTestCases; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; - -public class LeapAnalyzerTest extends AnalyzerTest { - @Override - protected Analyzer getAnalyzer() { - return new LeapAnalyzer(); - } - - @Test - public void noCommentsOnOptimalSolution() { - var actual = analyzeResourceFile(getResourceFileName("Optimal.java")); - - assertThat(actual.getComments()).isEmpty(); - } - - private static Stream testCases() { - return Stream.of( - Arguments.of("UsesJavaTime.java", new Comment[]{new NoBuiltInMethods()}), - Arguments.of("UsesGregorianCalendar.java", new Comment[]{new NoBuiltInMethods()}), - Arguments.of("HardCodedTestCases.java", new Comment[]{new AvoidHardCodedTestCases()}), - Arguments.of("UsesIfStatements.java", new Comment[]{new AvoidConditionalLogic()}), - Arguments.of("UsesTernary.java", new Comment[]{new AvoidConditionalLogic()}), - Arguments.of("TooManyChecks.java", new Comment[]{new UseMinimumNumberOfChecks()}) - ); - } - - @MethodSource("testCases") - @ParameterizedTest(name = "{0}") - public void testCommentsOnSolution(String solutionFile, Comment... expectedComments) { - var actual = analyzeResourceFile(getResourceFileName(solutionFile)); - - assertThat(actual.getComments()).contains(expectedComments); - } - - private static String getResourceFileName(String testFileName) { - return "/analyzer/exercises/leap/" + testFileName; - } -} diff --git a/src/test/resources/analyzer/exercises/leap/UsesJavaTime.java b/src/test/resources/analyzer/exercises/leap/UsesJavaTime.java deleted file mode 100644 index e3957535..00000000 --- a/src/test/resources/analyzer/exercises/leap/UsesJavaTime.java +++ /dev/null @@ -1,7 +0,0 @@ -import java.time.Year; - -class Leap { - boolean isLeapYear(int year) { - return Year.isLeap(year); - } -} diff --git a/tests/leap/hard-coded-test-cases/.meta/config.json b/tests/leap/hard-coded-test-cases/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/hard-coded-test-cases/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/hard-coded-test-cases/expected_analysis.json b/tests/leap/hard-coded-test-cases/expected_analysis.json new file mode 100644 index 00000000..e4934cb5 --- /dev/null +++ b/tests/leap/hard-coded-test-cases/expected_analysis.json @@ -0,0 +1,14 @@ +{"comments": [ + { + "comment": "java.general.avoid_hard_coded_test_cases", + "type": "essential" + }, + { + "comment": "java.leap.use_minimum_number_of_checks", + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "type": "informative" + } +]} \ No newline at end of file diff --git a/tests/leap/expected_tags.json b/tests/leap/hard-coded-test-cases/expected_tags.json similarity index 100% rename from tests/leap/expected_tags.json rename to tests/leap/hard-coded-test-cases/expected_tags.json diff --git a/src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java b/tests/leap/hard-coded-test-cases/src/main/java/Leap.java similarity index 100% rename from src/test/resources/analyzer/exercises/leap/HardCodedTestCases.java rename to tests/leap/hard-coded-test-cases/src/main/java/Leap.java diff --git a/tests/leap/optimal-solution/.meta/config.json b/tests/leap/optimal-solution/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/optimal-solution/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/optimal-solution/expected_analysis.json b/tests/leap/optimal-solution/expected_analysis.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/optimal-solution/expected_analysis.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/leap/optimal-solution/expected_tags.json b/tests/leap/optimal-solution/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/optimal-solution/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/test/resources/analyzer/exercises/leap/Optimal.java b/tests/leap/optimal-solution/src/main/java/Leap.java similarity index 100% rename from src/test/resources/analyzer/exercises/leap/Optimal.java rename to tests/leap/optimal-solution/src/main/java/Leap.java diff --git a/tests/leap/using-gregorian-calendar/.meta/config.json b/tests/leap/using-gregorian-calendar/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/using-gregorian-calendar/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/expected_analysis.json b/tests/leap/using-gregorian-calendar/expected_analysis.json similarity index 100% rename from tests/leap/expected_analysis.json rename to tests/leap/using-gregorian-calendar/expected_analysis.json diff --git a/tests/leap/using-gregorian-calendar/expected_tags.json b/tests/leap/using-gregorian-calendar/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/using-gregorian-calendar/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java b/tests/leap/using-gregorian-calendar/src/main/java/Leap.java similarity index 100% rename from src/test/resources/analyzer/exercises/leap/UsesGregorianCalendar.java rename to tests/leap/using-gregorian-calendar/src/main/java/Leap.java diff --git a/tests/leap/using-if-statements/.meta/config.json b/tests/leap/using-if-statements/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/using-if-statements/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/using-if-statements/expected_analysis.json b/tests/leap/using-if-statements/expected_analysis.json new file mode 100644 index 00000000..f09b4a58 --- /dev/null +++ b/tests/leap/using-if-statements/expected_analysis.json @@ -0,0 +1,10 @@ +{"comments": [ + { + "comment": "java.leap.avoid_conditional_logic", + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "type": "informative" + } +]} \ No newline at end of file diff --git a/tests/leap/using-if-statements/expected_tags.json b/tests/leap/using-if-statements/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/using-if-statements/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/test/resources/analyzer/exercises/leap/UsesIfStatements.java b/tests/leap/using-if-statements/src/main/java/Leap.java similarity index 100% rename from src/test/resources/analyzer/exercises/leap/UsesIfStatements.java rename to tests/leap/using-if-statements/src/main/java/Leap.java diff --git a/tests/leap/using-java-time/.meta/config.json b/tests/leap/using-java-time/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/using-java-time/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/using-java-time/expected_analysis.json b/tests/leap/using-java-time/expected_analysis.json new file mode 100644 index 00000000..d7466506 --- /dev/null +++ b/tests/leap/using-java-time/expected_analysis.json @@ -0,0 +1,10 @@ +{"comments": [ + { + "comment": "java.leap.no_built_in_methods", + "type": "essential" + }, + { + "comment": "java.general.feedback_request", + "type": "informative" + } +]} \ No newline at end of file diff --git a/tests/leap/using-java-time/expected_tags.json b/tests/leap/using-java-time/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/using-java-time/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/leap/src/main/java/Leap.java b/tests/leap/using-java-time/src/main/java/Leap.java similarity index 100% rename from tests/leap/src/main/java/Leap.java rename to tests/leap/using-java-time/src/main/java/Leap.java diff --git a/tests/leap/using-ternary/.meta/config.json b/tests/leap/using-ternary/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/using-ternary/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/using-ternary/expected_analysis.json b/tests/leap/using-ternary/expected_analysis.json new file mode 100644 index 00000000..f09b4a58 --- /dev/null +++ b/tests/leap/using-ternary/expected_analysis.json @@ -0,0 +1,10 @@ +{"comments": [ + { + "comment": "java.leap.avoid_conditional_logic", + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "type": "informative" + } +]} \ No newline at end of file diff --git a/tests/leap/using-ternary/expected_tags.json b/tests/leap/using-ternary/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/using-ternary/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/test/resources/analyzer/exercises/leap/UsesTernary.java b/tests/leap/using-ternary/src/main/java/Leap.java similarity index 100% rename from src/test/resources/analyzer/exercises/leap/UsesTernary.java rename to tests/leap/using-ternary/src/main/java/Leap.java diff --git a/tests/leap/using-too-many-checks/.meta/config.json b/tests/leap/using-too-many-checks/.meta/config.json new file mode 100644 index 00000000..d977953c --- /dev/null +++ b/tests/leap/using-too-many-checks/.meta/config.json @@ -0,0 +1,29 @@ +{ + "authors": [ + "sonapraneeth-a" + ], + "contributors": [ + "jmrunkle", + "lemoncurry", + "msomji", + "muzimuzhi", + "sshine" + ], + "files": { + "solution": [ + "src/main/java/Leap.java" + ], + "test": [ + "src/test/java/LeapTest.java" + ], + "example": [ + ".meta/src/reference/java/Leap.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} \ No newline at end of file diff --git a/tests/leap/using-too-many-checks/expected_analysis.json b/tests/leap/using-too-many-checks/expected_analysis.json new file mode 100644 index 00000000..55786b70 --- /dev/null +++ b/tests/leap/using-too-many-checks/expected_analysis.json @@ -0,0 +1,10 @@ +{"comments": [ + { + "comment": "java.leap.use_minimum_number_of_checks", + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "type": "informative" + } +]} \ No newline at end of file diff --git a/tests/leap/using-too-many-checks/expected_tags.json b/tests/leap/using-too-many-checks/expected_tags.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/leap/using-too-many-checks/expected_tags.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/test/resources/analyzer/exercises/leap/TooManyChecks.java b/tests/leap/using-too-many-checks/src/main/java/Leap.java similarity index 100% rename from src/test/resources/analyzer/exercises/leap/TooManyChecks.java rename to tests/leap/using-too-many-checks/src/main/java/Leap.java