Skip to content

Commit 1fc0930

Browse files
Add analyzer for tim-from-marketing concept exercise (#270)
1 parent b9815c2 commit 1fc0930

24 files changed

+366
-0
lines changed

src/main/java/analyzer/AnalyzerRoot.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import analyzer.exercises.needforspeed.NeedForSpeedAnalyzer;
1111
import analyzer.exercises.salarycalculator.SalaryCalculatorAnalyzer;
1212
import analyzer.exercises.secrets.SecretsAnalyzer;
13+
import analyzer.exercises.timfrommarketing.TimFromMarketingAnalyzer;
1314
import analyzer.exercises.twofer.TwoferAnalyzer;
1415
import analyzer.exercises.wizardsandwarriors.WizardsAndWarriorsAnalyzer;
1516

@@ -59,6 +60,7 @@ private static List<Analyzer> createAnalyzers(String slug) {
5960
case "need-for-speed" -> analyzers.add(new NeedForSpeedAnalyzer());
6061
case "salary-calculator" -> analyzers.add(new SalaryCalculatorAnalyzer());
6162
case "secrets" -> analyzers.add(new SecretsAnalyzer());
63+
case "tim-from-marketing" -> analyzers.add(new TimFromMarketingAnalyzer());
6264
case "two-fer" -> analyzers.add(new TwoferAnalyzer());
6365
case "wizards-and-warriors" -> analyzers.add(new WizardsAndWarriorsAnalyzer());
6466
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package analyzer.exercises.timfrommarketing;
2+
3+
import analyzer.Analyzer;
4+
import analyzer.OutputCollector;
5+
import analyzer.Solution;
6+
import analyzer.comments.ExemplarSolution;
7+
import analyzer.comments.PreferStringConcatenation;
8+
import com.github.javaparser.ast.body.MethodDeclaration;
9+
import com.github.javaparser.ast.expr.MethodCallExpr;
10+
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
11+
12+
public class TimFromMarketingAnalyzer extends VoidVisitorAdapter<OutputCollector> implements Analyzer {
13+
14+
private static final String EXERCISE_NAME = "Tim from Marketing";
15+
private static final String FORMAT = "format";
16+
private static final String OPTIONAL = "Optional";
17+
18+
@Override
19+
public void analyze(Solution solution, OutputCollector output) {
20+
21+
for (var compilationUnit : solution.getCompilationUnits()) {
22+
compilationUnit.accept(this, output);
23+
}
24+
25+
if (output.getComments().isEmpty()) {
26+
output.addComment(new ExemplarSolution(EXERCISE_NAME));
27+
}
28+
}
29+
30+
@Override
31+
public void visit(MethodDeclaration node, OutputCollector output) {
32+
33+
if(useOptionals(node)){
34+
output.addComment(new UseNullLiteral());
35+
}
36+
37+
if(useStringFormat(node)) {
38+
output.addComment(new PreferStringConcatenation());
39+
}
40+
41+
super.visit(node, output);
42+
}
43+
44+
private static boolean useStringFormat(MethodDeclaration node) {
45+
return node.findAll(MethodCallExpr.class).stream()
46+
.anyMatch(m -> m.getNameAsString().contains(FORMAT));
47+
}
48+
49+
50+
private static boolean useOptionals(MethodDeclaration node) {
51+
return node.findAll(MethodCallExpr.class).stream()
52+
.anyMatch(m -> m.toString().contains(OPTIONAL));
53+
}
54+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package analyzer.exercises.timfrommarketing;
2+
3+
import analyzer.Comment;
4+
5+
6+
public class UseNullLiteral extends Comment {
7+
8+
@Override
9+
public String getKey() {
10+
return "java.tim-from-marketing.use_null_literal";
11+
}
12+
13+
@Override
14+
public Type getType() {
15+
return Type.ACTIONABLE;
16+
}
17+
}

src/test/java/analyzer/AnalyzerIntegrationTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ void leap(String scenario) throws IOException {
8383
Approvals.verify(serialize(output.analysis()), Approvals.NAMES.withParameters(scenario));
8484
}
8585

86+
@ParameterizedTest
87+
@ValueSource(strings = {
88+
"ExemplarSolution",
89+
"UseOptionals",
90+
"UseStringFormat",
91+
"UseOptionalsAndStringFormat",
92+
})
93+
void timfrommarketing(String scenario) throws IOException {
94+
var path = Path.of("tim-from-marketing", scenario + ".java");
95+
var solution = new SolutionFromFiles("tim-from-marketing", SCENARIOS.resolve(path));
96+
var output = AnalyzerRoot.analyze(solution);
97+
98+
Approvals.verify(serialize(output.analysis()), Approvals.NAMES.withParameters(scenario));
99+
}
100+
86101
@ParameterizedTest
87102
@ValueSource(strings = {
88103
"HardCodedTestCases",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.general.exemplar",
5+
"params": {
6+
"exerciseName": "Tim from Marketing"
7+
},
8+
"type": "celebratory"
9+
}
10+
]
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.tim-from-marketing.use_null_literal",
5+
"params": {},
6+
"type": "actionable"
7+
},
8+
{
9+
"comment": "java.general.feedback_request",
10+
"params": {},
11+
"type": "informative"
12+
}
13+
]
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.tim-from-marketing.use_null_literal",
5+
"params": {},
6+
"type": "actionable"
7+
},
8+
{
9+
"comment": "java.general.prefer_string_concatenation",
10+
"params": {},
11+
"type": "informative"
12+
},
13+
{
14+
"comment": "java.general.feedback_request",
15+
"params": {},
16+
"type": "informative"
17+
}
18+
]
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.general.prefer_string_concatenation",
5+
"params": {},
6+
"type": "informative"
7+
},
8+
{
9+
"comment": "java.general.feedback_request",
10+
"params": {},
11+
"type": "informative"
12+
}
13+
]
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
public class Badge {
2+
3+
public String print(Integer id, String name, String department) {
4+
5+
String worksAt;
6+
7+
if (department == null) {
8+
worksAt = "OWNER";
9+
} else {
10+
worksAt = department.toUpperCase();
11+
}
12+
13+
if (id == null) {
14+
return name + " - " + worksAt;
15+
}
16+
17+
return "[" + id + "] - " + name + " - " + worksAt;
18+
}
19+
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class Badge {
2+
public String print(Integer id, String name, String department) {
3+
Optional<Integer> optionalId = Optional.ofNullable(id);
4+
Optional<String> optionalDepartment = Optional.ofNullable(department);
5+
6+
String idPart = optionalId.map(i -> "[" + i + "] - ").orElse("");
7+
String departmentPart = optionalDepartment.orElse("OWNER").toUpperCase();
8+
9+
return idPart + name + " - " + departmentPart;
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class Badge {
2+
public String print(Integer id, String name, String department) {
3+
Optional<Integer> optionalId = Optional.ofNullable(id);
4+
Optional<String> optionalDepartment = Optional.ofNullable(department);
5+
6+
String idPart = optionalId.map(i -> String.format("[%d] - ", i)).orElse("");
7+
String departmentPart = optionalDepartment.orElse("OWNER").toUpperCase();
8+
9+
return String.format("%s%s - %s", idPart, name, departmentPart);
10+
}
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
public class Badge {
2+
public String print(Integer id, String name, String department) {
3+
if (department == null) {
4+
department = "OWNER";
5+
} else {
6+
department = department.toUpperCase();
7+
}
8+
9+
if (id == null) {
10+
return String.format("%s - %s", name, department);
11+
} else {
12+
return String.format("[%d] - %s - %s", id, name, department);
13+
}
14+
}
15+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"authors": [
3+
"smcg468"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/main/java/Badge.java"
8+
],
9+
"test": [
10+
"src/test/java/BadgeTest.java"
11+
],
12+
"exemplar": [
13+
".meta/src/reference/java/Badge.java"
14+
],
15+
"invalidator": [
16+
"build.gradle"
17+
]
18+
},
19+
"forked_from": [
20+
"csharp/tim-from-marketing"
21+
],
22+
"blurb": "Learn about the null literal and nullable variables in java by printing name badges."
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.general.exemplar",
5+
"params": {
6+
"exerciseName": "Tim from Marketing"
7+
},
8+
"type": "celebratory"
9+
}
10+
]
11+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"tags": []
3+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
public class Badge {
2+
3+
public String print(Integer id, String name, String department) {
4+
5+
String worksAt;
6+
7+
if (department == null) {
8+
worksAt = "OWNER";
9+
} else {
10+
worksAt = department.toUpperCase();
11+
}
12+
13+
if (id == null) {
14+
return name + " - " + worksAt;
15+
}
16+
17+
return "[" + id + "] - " + name + " - " + worksAt;
18+
}
19+
20+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"authors": [
3+
"smcg468"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/main/java/Badge.java"
8+
],
9+
"test": [
10+
"src/test/java/BadgeTest.java"
11+
],
12+
"exemplar": [
13+
".meta/src/reference/java/Badge.java"
14+
],
15+
"invalidator": [
16+
"build.gradle"
17+
]
18+
},
19+
"forked_from": [
20+
"csharp/tim-from-marketing"
21+
],
22+
"blurb": "Learn about the null literal and nullable variables in java by printing name badges."
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.tim-from-marketing.use_null_literal",
5+
"params": {},
6+
"type": "actionable"
7+
},
8+
{
9+
"comment": "java.general.feedback_request",
10+
"params": {},
11+
"type": "informative"
12+
}
13+
]
14+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"tags": []
3+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class Badge {
2+
public String print(Integer id, String name, String department) {
3+
Optional<Integer> optionalId = Optional.ofNullable(id);
4+
Optional<String> optionalDepartment = Optional.ofNullable(department);
5+
6+
String idPart = optionalId.map(i -> "[" + i + "] - ").orElse("");
7+
String departmentPart = optionalDepartment.orElse("OWNER").toUpperCase();
8+
9+
return idPart + name + " - " + departmentPart;
10+
}
11+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"authors": [
3+
"smcg468"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/main/java/Badge.java"
8+
],
9+
"test": [
10+
"src/test/java/BadgeTest.java"
11+
],
12+
"exemplar": [
13+
".meta/src/reference/java/Badge.java"
14+
],
15+
"invalidator": [
16+
"build.gradle"
17+
]
18+
},
19+
"forked_from": [
20+
"csharp/tim-from-marketing"
21+
],
22+
"blurb": "Learn about the null literal and nullable variables in java by printing name badges."
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"comments": [
3+
{
4+
"comment": "java.general.prefer_string_concatenation",
5+
"params": {},
6+
"type": "informative"
7+
},
8+
{
9+
"comment": "java.general.feedback_request",
10+
"params": {},
11+
"type": "informative"
12+
}
13+
]
14+
}

0 commit comments

Comments
 (0)