diff --git a/src/main/java/analyzer/AnalyzerRoot.java b/src/main/java/analyzer/AnalyzerRoot.java index 42937686..ecb0815e 100644 --- a/src/main/java/analyzer/AnalyzerRoot.java +++ b/src/main/java/analyzer/AnalyzerRoot.java @@ -6,6 +6,7 @@ import analyzer.exercises.hamming.HammingAnalyzer; import analyzer.exercises.lasagna.LasagnaAnalyzer; import analyzer.exercises.leap.LeapAnalyzer; +import analyzer.exercises.loglevels.LogLevelsAnalyzer; import analyzer.exercises.needforspeed.NeedForSpeedAnalyzer; import analyzer.exercises.twofer.TwoferAnalyzer; @@ -51,6 +52,7 @@ private static List createAnalyzers(String slug) { case "hamming" -> analyzers.add(new HammingAnalyzer()); case "lasagna" -> analyzers.add(new LasagnaAnalyzer()); case "leap" -> analyzers.add(new LeapAnalyzer()); + case "log-levels" -> analyzers.add(new LogLevelsAnalyzer()); case "need-for-speed" -> analyzers.add(new NeedForSpeedAnalyzer()); case "two-fer" -> analyzers.add(new TwoferAnalyzer()); } diff --git a/src/main/java/analyzer/comments/PreferStringConcatenation.java b/src/main/java/analyzer/comments/PreferStringConcatenation.java new file mode 100644 index 00000000..03e7ea0f --- /dev/null +++ b/src/main/java/analyzer/comments/PreferStringConcatenation.java @@ -0,0 +1,19 @@ +package analyzer.comments; + +import analyzer.Comment; + +/** + * @see Markdown Template + */ +public class PreferStringConcatenation extends Comment { + + @Override + public String getKey() { + return "java.general.prefer_string_concatenation"; + } + + @Override + public Type getType() { + return Type.INFORMATIVE; + } +} diff --git a/src/main/java/analyzer/exercises/lasagna/ReuseCode.java b/src/main/java/analyzer/comments/ReuseCode.java similarity index 72% rename from src/main/java/analyzer/exercises/lasagna/ReuseCode.java rename to src/main/java/analyzer/comments/ReuseCode.java index 7a2fdf89..8119b342 100644 --- a/src/main/java/analyzer/exercises/lasagna/ReuseCode.java +++ b/src/main/java/analyzer/comments/ReuseCode.java @@ -1,24 +1,24 @@ -package analyzer.exercises.lasagna; +package analyzer.comments; import analyzer.Comment; import java.util.Map; /** - * @see Markdown Template + * @see Markdown Template */ -class ReuseCode extends Comment { +public class ReuseCode extends Comment { private final String callingMethod; private final String methodToCall; - ReuseCode(String callingMethod, String methodToCall) { + public ReuseCode(String callingMethod, String methodToCall) { this.callingMethod = callingMethod; this.methodToCall = methodToCall; } @Override public String getKey() { - return "java.lasagna.reuse_code"; + return "java.general.reuse_code"; } @Override diff --git a/src/main/java/analyzer/exercises/lasagna/LasagnaAnalyzer.java b/src/main/java/analyzer/exercises/lasagna/LasagnaAnalyzer.java index 3efd5fc7..325c720d 100644 --- a/src/main/java/analyzer/exercises/lasagna/LasagnaAnalyzer.java +++ b/src/main/java/analyzer/exercises/lasagna/LasagnaAnalyzer.java @@ -5,6 +5,8 @@ import analyzer.Solution; import analyzer.comments.ExemplarSolution; import analyzer.comments.RemoveTodoComments; +import analyzer.comments.ReuseCode; + import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.comments.LineComment; diff --git a/src/main/java/analyzer/exercises/loglevels/LogLevelsAnalyzer.java b/src/main/java/analyzer/exercises/loglevels/LogLevelsAnalyzer.java new file mode 100644 index 00000000..7107f522 --- /dev/null +++ b/src/main/java/analyzer/exercises/loglevels/LogLevelsAnalyzer.java @@ -0,0 +1,86 @@ +package analyzer.exercises.loglevels; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.StringLiteralExpr; +import com.github.javaparser.ast.visitor.VoidVisitorAdapter; + +import analyzer.Analyzer; +import analyzer.OutputCollector; +import analyzer.Solution; +import analyzer.comments.AvoidHardCodedTestCases; +import analyzer.comments.ExemplarSolution; +import analyzer.comments.PreferStringConcatenation; +import analyzer.comments.ReuseCode; + +import java.util.List; + +/** + * The {@link LogLevelsAnalyzer} is the analyzer implementation for the {@code log-levels} practice exercise. + * It extends from the {@link VoidVisitorAdapter} and uses the visitor pattern to traverse each compilation unit. + * + * @see The log-levels exercise on the Java track + */ +public class LogLevelsAnalyzer extends VoidVisitorAdapter implements Analyzer { + private static final String EXERCISE_NAME = "Log Levels"; + private static final String REFORMAT = "reformat"; + private static final String MESSAGE = "message"; + private static final String LOG_LEVEL = "logLevel"; + private static final String SUBSTRING = "substring"; + private static final String FORMAT = "format"; + + @Override + public void analyze(Solution solution, OutputCollector output) { + for (CompilationUnit compilationUnit : solution.getCompilationUnits()) { + compilationUnit.accept(this, output); + } + + if (output.getComments().isEmpty()) { + output.addComment(new ExemplarSolution(EXERCISE_NAME)); + } + } + + @Override + public void visit(MethodDeclaration node, OutputCollector output) { + if (containsHarcodedString(node)) { + output.addComment(new AvoidHardCodedTestCases()); + return; + } + + if (!node.getNameAsString().equals(REFORMAT) && doesNotCallMethod(node, SUBSTRING)) { + output.addComment(new UseSubstringMethod()); + return; + } + + if (node.getNameAsString().equals(REFORMAT) && doesNotCallMethod(node, MESSAGE)) { + output.addComment(new ReuseCode(REFORMAT, MESSAGE)); + } + + if (node.getNameAsString().equals(REFORMAT) && doesNotCallMethod(node, LOG_LEVEL)) { + output.addComment(new ReuseCode(REFORMAT, LOG_LEVEL)); + } + + if (node.getNameAsString().equals(REFORMAT) && callsMethod(node, FORMAT)) { + output.addComment(new PreferStringConcatenation()); + } + + super.visit(node, output); + } + + private static boolean containsHarcodedString(MethodDeclaration node) { + List hardcodedStrings = node.findAll(StringLiteralExpr.class, + x -> x.getValue().contains("ERROR") || x.getValue().contains("WARNING") + || x.getValue().contains("INFO")); + + return hardcodedStrings.size() > 1; + } + + private static boolean doesNotCallMethod(MethodDeclaration node, String otherMethodName) { + return node.findAll(MethodCallExpr.class, x -> x.getNameAsString().contains(otherMethodName)).isEmpty(); + } + + private static boolean callsMethod(MethodDeclaration node, String otherMethodName) { + return !node.findAll(MethodCallExpr.class, x -> x.getNameAsString().contains(otherMethodName)).isEmpty(); + } +} diff --git a/src/main/java/analyzer/exercises/loglevels/UseSubstringMethod.java b/src/main/java/analyzer/exercises/loglevels/UseSubstringMethod.java new file mode 100644 index 00000000..c7388bf9 --- /dev/null +++ b/src/main/java/analyzer/exercises/loglevels/UseSubstringMethod.java @@ -0,0 +1,19 @@ +package analyzer.exercises.loglevels; + +import analyzer.Comment; + +/** + * @see Markdown Template + */ +class UseSubstringMethod extends Comment { + + @Override + public String getKey() { + return "java.log-levels.use_substring_method"; + } + + @Override + public Type getType() { + return Type.ACTIONABLE; + } +} diff --git a/src/test/java/analyzer/AnalyzerIntegrationTest.java b/src/test/java/analyzer/AnalyzerIntegrationTest.java index 17af176d..d81f363b 100644 --- a/src/test/java/analyzer/AnalyzerIntegrationTest.java +++ b/src/test/java/analyzer/AnalyzerIntegrationTest.java @@ -113,7 +113,7 @@ public void annalynsinfiltration(String scenario) throws IOException { Approvals.verify(serialize(output.analysis()), Approvals.NAMES.withParameters(scenario)); } - + @ParameterizedTest @ValueSource(strings = { "ExemplarSolution", @@ -126,7 +126,27 @@ void needforspeed(String scenario) throws IOException { var path = Path.of("need-for-speed", scenario + ".java"); var solution = new SolutionFromFiles("need-for-speed", SCENARIOS.resolve(path)); var output = AnalyzerRoot.analyze(solution); - + + Approvals.verify(serialize(output.analysis()), Approvals.NAMES.withParameters(scenario)); + } + + @ParameterizedTest + @ValueSource(strings = { + "ExemplarSolution", + "HardCodingLogLevels", + "NoReuseLogLevel", + "NoReuseMessage", + "NoReuseOfBothMethods", + "NotUsingSubstringOnLogLevel", + "NotUsingSubstringOnMessage", + "NotUsingSubstringOnBothMethods", + "UsingStringFormat" + }) + void loglevels(String scenario) throws IOException { + var path = Path.of("log-levels", scenario + ".java"); + var solution = new SolutionFromFiles("log-levels", SCENARIOS.resolve(path)); + var output = AnalyzerRoot.analyze(solution); + Approvals.verify(serialize(output.analysis()), Approvals.NAMES.withParameters(scenario)); } } diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfBothMethods.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfBothMethods.approved.txt index f9f74609..7070ea23 100644 --- a/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfBothMethods.approved.txt +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfBothMethods.approved.txt @@ -1,7 +1,7 @@ { "comments": [ { - "comment": "java.lasagna.reuse_code", + "comment": "java.general.reuse_code", "params": { "callingMethod": "remainingMinutesInOven", "methodToCall": "expectedMinutesInOven" @@ -9,7 +9,7 @@ "type": "actionable" }, { - "comment": "java.lasagna.reuse_code", + "comment": "java.general.reuse_code", "params": { "callingMethod": "totalTimeInMinutes", "methodToCall": "preparationTimeInMinutes" diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfExpectedMinutesInOven.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfExpectedMinutesInOven.approved.txt index d5dcc6e9..76eed184 100644 --- a/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfExpectedMinutesInOven.approved.txt +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfExpectedMinutesInOven.approved.txt @@ -1,7 +1,7 @@ { "comments": [ { - "comment": "java.lasagna.reuse_code", + "comment": "java.general.reuse_code", "params": { "callingMethod": "remainingMinutesInOven", "methodToCall": "expectedMinutesInOven" diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfPreparationTimeInMinutes.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfPreparationTimeInMinutes.approved.txt index 3ad37e36..f80fd3e7 100644 --- a/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfPreparationTimeInMinutes.approved.txt +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.lasagna.NoReuseOfPreparationTimeInMinutes.approved.txt @@ -1,7 +1,7 @@ { "comments": [ { - "comment": "java.lasagna.reuse_code", + "comment": "java.general.reuse_code", "params": { "callingMethod": "totalTimeInMinutes", "methodToCall": "preparationTimeInMinutes" diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.ExemplarSolution.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.ExemplarSolution.approved.txt new file mode 100644 index 00000000..e8df7b83 --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.ExemplarSolution.approved.txt @@ -0,0 +1,11 @@ +{ + "comments": [ + { + "comment": "java.general.exemplar", + "params": { + "exerciseName": "Log Levels" + }, + "type": "celebratory" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.HardCodingLogLevels.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.HardCodingLogLevels.approved.txt new file mode 100644 index 00000000..723cbd96 --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.HardCodingLogLevels.approved.txt @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.general.avoid_hard_coded_test_cases", + "params": {}, + "type": "essential" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseLogLevel.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseLogLevel.approved.txt new file mode 100644 index 00000000..fe5b1056 --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseLogLevel.approved.txt @@ -0,0 +1,17 @@ +{ + "comments": [ + { + "comment": "java.general.reuse_code", + "params": { + "callingMethod": "reformat", + "methodToCall": "logLevel" + }, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseMessage.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseMessage.approved.txt new file mode 100644 index 00000000..88b0b3bd --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseMessage.approved.txt @@ -0,0 +1,17 @@ +{ + "comments": [ + { + "comment": "java.general.reuse_code", + "params": { + "callingMethod": "reformat", + "methodToCall": "message" + }, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseOfBothMethods.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseOfBothMethods.approved.txt new file mode 100644 index 00000000..6ea6c232 --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NoReuseOfBothMethods.approved.txt @@ -0,0 +1,25 @@ +{ + "comments": [ + { + "comment": "java.general.reuse_code", + "params": { + "callingMethod": "reformat", + "methodToCall": "message" + }, + "type": "actionable" + }, + { + "comment": "java.general.reuse_code", + "params": { + "callingMethod": "reformat", + "methodToCall": "logLevel" + }, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnBothMethods.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnBothMethods.approved.txt new file mode 100644 index 00000000..4874f89c --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnBothMethods.approved.txt @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.log-levels.use_substring_method", + "params": {}, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnLogLevel.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnLogLevel.approved.txt new file mode 100644 index 00000000..4874f89c --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnLogLevel.approved.txt @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.log-levels.use_substring_method", + "params": {}, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnMessage.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnMessage.approved.txt new file mode 100644 index 00000000..4874f89c --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.NotUsingSubstringOnMessage.approved.txt @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.log-levels.use_substring_method", + "params": {}, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.UsingStringFormat.approved.txt b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.UsingStringFormat.approved.txt new file mode 100644 index 00000000..b01ad7f7 --- /dev/null +++ b/src/test/resources/analyzer/AnalyzerIntegrationTest.loglevels.UsingStringFormat.approved.txt @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.general.prefer_string_concatenation", + "params": {}, + "type": "informative" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/scenarios/log-levels/ExemplarSolution.java b/src/test/resources/scenarios/log-levels/ExemplarSolution.java new file mode 100644 index 00000000..854765fd --- /dev/null +++ b/src/test/resources/scenarios/log-levels/ExemplarSolution.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/HardCodingLogLevels.java b/src/test/resources/scenarios/log-levels/HardCodingLogLevels.java new file mode 100644 index 00000000..6ca112ed --- /dev/null +++ b/src/test/resources/scenarios/log-levels/HardCodingLogLevels.java @@ -0,0 +1,23 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + if (logLine.contains("[ERROR]:")) { + return logLine.replace("[ERROR]:", "").trim(); + } else if (logLine.contains("[WARNING]:")) { + return logLine.replace("[WARNING]:", "").trim(); + } else if (logLine.contains("[INFO]:")) { + return logLine.replace("[INFO]:", "").trim(); + } else { + return ""; + } + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/NoReuseLogLevel.java b/src/test/resources/scenarios/log-levels/NoReuseLogLevel.java new file mode 100644 index 00000000..0c69218a --- /dev/null +++ b/src/test/resources/scenarios/log-levels/NoReuseLogLevel.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLine.substring(1, logLine.indexOf("]")).toLowerCase() + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/NoReuseMessage.java b/src/test/resources/scenarios/log-levels/NoReuseMessage.java new file mode 100644 index 00000000..48b169e6 --- /dev/null +++ b/src/test/resources/scenarios/log-levels/NoReuseMessage.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim() + " (" + logLevel(logLine) + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/NoReuseOfBothMethods.java b/src/test/resources/scenarios/log-levels/NoReuseOfBothMethods.java new file mode 100644 index 00000000..85afdaf0 --- /dev/null +++ b/src/test/resources/scenarios/log-levels/NoReuseOfBothMethods.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim() + " (" + logLine.substring(1, logLine.indexOf("]")).toLowerCase() + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/NotUsingSubstringOnBothMethods.java b/src/test/resources/scenarios/log-levels/NotUsingSubstringOnBothMethods.java new file mode 100644 index 00000000..987a15cb --- /dev/null +++ b/src/test/resources/scenarios/log-levels/NotUsingSubstringOnBothMethods.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.split("]: ")[1].trim(); + } + + public static String logLevel(String logLine) { + return logLine.split("]: ")[0].replace("[", "").toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/NotUsingSubstringOnLogLevel.java b/src/test/resources/scenarios/log-levels/NotUsingSubstringOnLogLevel.java new file mode 100644 index 00000000..c66e22dc --- /dev/null +++ b/src/test/resources/scenarios/log-levels/NotUsingSubstringOnLogLevel.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.split("]: ")[0].replace("[", "").toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/NotUsingSubstringOnMessage.java b/src/test/resources/scenarios/log-levels/NotUsingSubstringOnMessage.java new file mode 100644 index 00000000..79ae75cc --- /dev/null +++ b/src/test/resources/scenarios/log-levels/NotUsingSubstringOnMessage.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.split("]: ")[1].trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/src/test/resources/scenarios/log-levels/UsingStringFormat.java b/src/test/resources/scenarios/log-levels/UsingStringFormat.java new file mode 100644 index 00000000..5e0b3228 --- /dev/null +++ b/src/test/resources/scenarios/log-levels/UsingStringFormat.java @@ -0,0 +1,15 @@ +package scenarios.loglevels; + +public class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return String.format("%s (%s)", message(logLine), logLevel(logLine)); + } +} diff --git a/tests/lasagna/no-code-reuse/expected_analysis.json b/tests/lasagna/no-code-reuse/expected_analysis.json index f9f74609..7070ea23 100644 --- a/tests/lasagna/no-code-reuse/expected_analysis.json +++ b/tests/lasagna/no-code-reuse/expected_analysis.json @@ -1,7 +1,7 @@ { "comments": [ { - "comment": "java.lasagna.reuse_code", + "comment": "java.general.reuse_code", "params": { "callingMethod": "remainingMinutesInOven", "methodToCall": "expectedMinutesInOven" @@ -9,7 +9,7 @@ "type": "actionable" }, { - "comment": "java.lasagna.reuse_code", + "comment": "java.general.reuse_code", "params": { "callingMethod": "totalTimeInMinutes", "methodToCall": "preparationTimeInMinutes" diff --git a/tests/log-levels/examplar-solution/.meta/config.json b/tests/log-levels/examplar-solution/.meta/config.json new file mode 100644 index 00000000..637efd79 --- /dev/null +++ b/tests/log-levels/examplar-solution/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "mirkoperillo" + ], + "files": { + "solution": [ + "src/main/java/LogLevels.java" + ], + "test": [ + "src/test/java/LogLevelsTest.java" + ], + "exemplar": [ + ".meta/src/reference/java/LogLevels.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "forked_from": [ + "csharp/log-levels" + ], + "blurb": "Learn about strings by processing logs." +} \ No newline at end of file diff --git a/tests/log-levels/examplar-solution/expected_analysis.json b/tests/log-levels/examplar-solution/expected_analysis.json new file mode 100644 index 00000000..8901e1b8 --- /dev/null +++ b/tests/log-levels/examplar-solution/expected_analysis.json @@ -0,0 +1,11 @@ +{ + "comments": [ + { + "comment": "java.general.exemplar", + "params": { + "exerciseName": "Log Levels" + }, + "type": "celebratory" + } + ] +} \ No newline at end of file diff --git a/tests/log-levels/examplar-solution/expected_tags.json b/tests/log-levels/examplar-solution/expected_tags.json new file mode 100644 index 00000000..eb25b190 --- /dev/null +++ b/tests/log-levels/examplar-solution/expected_tags.json @@ -0,0 +1,3 @@ +{ + "tags": [] +} \ No newline at end of file diff --git a/tests/log-levels/examplar-solution/src/main/java/LogLevels.java b/tests/log-levels/examplar-solution/src/main/java/LogLevels.java new file mode 100644 index 00000000..4f16871b --- /dev/null +++ b/tests/log-levels/examplar-solution/src/main/java/LogLevels.java @@ -0,0 +1,13 @@ +class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/tests/log-levels/hardcode-log-levels/.meta/config.json b/tests/log-levels/hardcode-log-levels/.meta/config.json new file mode 100644 index 00000000..637efd79 --- /dev/null +++ b/tests/log-levels/hardcode-log-levels/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "mirkoperillo" + ], + "files": { + "solution": [ + "src/main/java/LogLevels.java" + ], + "test": [ + "src/test/java/LogLevelsTest.java" + ], + "exemplar": [ + ".meta/src/reference/java/LogLevels.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "forked_from": [ + "csharp/log-levels" + ], + "blurb": "Learn about strings by processing logs." +} \ No newline at end of file diff --git a/tests/log-levels/hardcode-log-levels/expected_analysis.json b/tests/log-levels/hardcode-log-levels/expected_analysis.json new file mode 100644 index 00000000..e5fab09b --- /dev/null +++ b/tests/log-levels/hardcode-log-levels/expected_analysis.json @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.general.avoid_hard_coded_test_cases", + "params": {}, + "type": "essential" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/tests/log-levels/hardcode-log-levels/expected_tags.json b/tests/log-levels/hardcode-log-levels/expected_tags.json new file mode 100644 index 00000000..eb25b190 --- /dev/null +++ b/tests/log-levels/hardcode-log-levels/expected_tags.json @@ -0,0 +1,3 @@ +{ + "tags": [] +} \ No newline at end of file diff --git a/tests/log-levels/hardcode-log-levels/src/main/java/LogLevels.java b/tests/log-levels/hardcode-log-levels/src/main/java/LogLevels.java new file mode 100644 index 00000000..ea1272ef --- /dev/null +++ b/tests/log-levels/hardcode-log-levels/src/main/java/LogLevels.java @@ -0,0 +1,21 @@ +class LogLevels { + public static String message(String logLine) { + if (logLine.contains("[ERROR]:")) { + return logLine.replace("[ERROR]:", "").trim(); + } else if (logLine.contains("[WARNING]:")) { + return logLine.replace("[WARNING]:", "").trim(); + } else if (logLine.contains("[INFO]:")) { + return logLine.replace("[INFO]:", "").trim(); + } else { + return ""; + } + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/tests/log-levels/no-reuse-code/.meta/config.json b/tests/log-levels/no-reuse-code/.meta/config.json new file mode 100644 index 00000000..637efd79 --- /dev/null +++ b/tests/log-levels/no-reuse-code/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "mirkoperillo" + ], + "files": { + "solution": [ + "src/main/java/LogLevels.java" + ], + "test": [ + "src/test/java/LogLevelsTest.java" + ], + "exemplar": [ + ".meta/src/reference/java/LogLevels.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "forked_from": [ + "csharp/log-levels" + ], + "blurb": "Learn about strings by processing logs." +} \ No newline at end of file diff --git a/tests/log-levels/no-reuse-code/expected_analysis.json b/tests/log-levels/no-reuse-code/expected_analysis.json new file mode 100644 index 00000000..d9db4feb --- /dev/null +++ b/tests/log-levels/no-reuse-code/expected_analysis.json @@ -0,0 +1,17 @@ +{ + "comments": [ + { + "comment": "java.general.reuse_code", + "params": { + "callingMethod": "reformat", + "methodToCall": "logLevel" + }, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/tests/log-levels/no-reuse-code/expected_tags.json b/tests/log-levels/no-reuse-code/expected_tags.json new file mode 100644 index 00000000..eb25b190 --- /dev/null +++ b/tests/log-levels/no-reuse-code/expected_tags.json @@ -0,0 +1,3 @@ +{ + "tags": [] +} \ No newline at end of file diff --git a/tests/log-levels/no-reuse-code/src/main/java/LogLevels.java b/tests/log-levels/no-reuse-code/src/main/java/LogLevels.java new file mode 100644 index 00000000..4703671c --- /dev/null +++ b/tests/log-levels/no-reuse-code/src/main/java/LogLevels.java @@ -0,0 +1,13 @@ +class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLine.substring(1, logLine.indexOf("]")).toLowerCase() + ")"; + } +} diff --git a/tests/log-levels/no-substring-used/.meta/config.json b/tests/log-levels/no-substring-used/.meta/config.json new file mode 100644 index 00000000..637efd79 --- /dev/null +++ b/tests/log-levels/no-substring-used/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "mirkoperillo" + ], + "files": { + "solution": [ + "src/main/java/LogLevels.java" + ], + "test": [ + "src/test/java/LogLevelsTest.java" + ], + "exemplar": [ + ".meta/src/reference/java/LogLevels.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "forked_from": [ + "csharp/log-levels" + ], + "blurb": "Learn about strings by processing logs." +} \ No newline at end of file diff --git a/tests/log-levels/no-substring-used/expected_analysis.json b/tests/log-levels/no-substring-used/expected_analysis.json new file mode 100644 index 00000000..0e0173d7 --- /dev/null +++ b/tests/log-levels/no-substring-used/expected_analysis.json @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.log-levels.use_substring_method", + "params": {}, + "type": "actionable" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/tests/log-levels/no-substring-used/expected_tags.json b/tests/log-levels/no-substring-used/expected_tags.json new file mode 100644 index 00000000..eb25b190 --- /dev/null +++ b/tests/log-levels/no-substring-used/expected_tags.json @@ -0,0 +1,3 @@ +{ + "tags": [] +} \ No newline at end of file diff --git a/tests/log-levels/no-substring-used/src/main/java/LogLevels.java b/tests/log-levels/no-substring-used/src/main/java/LogLevels.java new file mode 100644 index 00000000..3ada8452 --- /dev/null +++ b/tests/log-levels/no-substring-used/src/main/java/LogLevels.java @@ -0,0 +1,14 @@ +class LogLevels { + public static String message(String logLine) { + return logLine.split("]: ")[1] + .trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return message(logLine) + " (" + logLevel(logLine) + ")"; + } +} diff --git a/tests/log-levels/using-string-format/.meta/config.json b/tests/log-levels/using-string-format/.meta/config.json new file mode 100644 index 00000000..637efd79 --- /dev/null +++ b/tests/log-levels/using-string-format/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "mirkoperillo" + ], + "files": { + "solution": [ + "src/main/java/LogLevels.java" + ], + "test": [ + "src/test/java/LogLevelsTest.java" + ], + "exemplar": [ + ".meta/src/reference/java/LogLevels.java" + ], + "invalidator": [ + "build.gradle" + ] + }, + "forked_from": [ + "csharp/log-levels" + ], + "blurb": "Learn about strings by processing logs." +} \ No newline at end of file diff --git a/tests/log-levels/using-string-format/expected_analysis.json b/tests/log-levels/using-string-format/expected_analysis.json new file mode 100644 index 00000000..2b150682 --- /dev/null +++ b/tests/log-levels/using-string-format/expected_analysis.json @@ -0,0 +1,14 @@ +{ + "comments": [ + { + "comment": "java.general.prefer_string_concatenation", + "params": {}, + "type": "informative" + }, + { + "comment": "java.general.feedback_request", + "params": {}, + "type": "informative" + } + ] +} \ No newline at end of file diff --git a/tests/log-levels/using-string-format/expected_tags.json b/tests/log-levels/using-string-format/expected_tags.json new file mode 100644 index 00000000..eb25b190 --- /dev/null +++ b/tests/log-levels/using-string-format/expected_tags.json @@ -0,0 +1,3 @@ +{ + "tags": [] +} \ No newline at end of file diff --git a/tests/log-levels/using-string-format/src/main/java/LogLevels.java b/tests/log-levels/using-string-format/src/main/java/LogLevels.java new file mode 100644 index 00000000..626d614d --- /dev/null +++ b/tests/log-levels/using-string-format/src/main/java/LogLevels.java @@ -0,0 +1,13 @@ +class LogLevels { + public static String message(String logLine) { + return logLine.substring(logLine.indexOf(":") + 1).trim(); + } + + public static String logLevel(String logLine) { + return logLine.substring(1, logLine.indexOf("]")).toLowerCase(); + } + + public static String reformat(String logLine) { + return String.format("%s (%s)", message(logLine), logLevel(logLine)); + } +}