Skip to content

Commit 2a3f723

Browse files
LarsEckartJayBazuziisidore
committed
*** exploring kotlin
Co-authored-by: Jay Bazuzi <[email protected]> Co-authored-by: Llewellyn Falco <[email protected]>
1 parent 5eeca1b commit 2a3f723

File tree

3 files changed

+195
-111
lines changed

3 files changed

+195
-111
lines changed

approvaltests-tests/pom.xml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
<artifactId>approvaltests-tests</artifactId>
1212
<packaging>jar</packaging>
1313

14+
<properties>
15+
<kotlin.version>2.1.21</kotlin.version>
16+
</properties>
17+
1418
<dependencies>
1519
<dependency>
1620
<groupId>jakarta.servlet</groupId>
@@ -143,10 +147,44 @@
143147
<artifactId>javaparser-core</artifactId>
144148
<version>3.27.0</version>
145149
</dependency>
150+
<dependency>
151+
<groupId>org.jetbrains.kotlin</groupId>
152+
<artifactId>kotlin-stdlib</artifactId>
153+
<version>${kotlin.version}</version>
154+
</dependency>
146155
</dependencies>
147156

148157
<build>
158+
<sourceDirectory>src/main/java</sourceDirectory>
159+
<testSourceDirectory>src/test/java</testSourceDirectory>
149160
<plugins>
161+
<plugin>
162+
<groupId>org.jetbrains.kotlin</groupId>
163+
<artifactId>kotlin-maven-plugin</artifactId>
164+
<version>${kotlin.version}</version>
165+
<executions>
166+
<execution>
167+
<id>compile</id>
168+
<phase>compile</phase>
169+
<goals>
170+
<goal>compile</goal>
171+
</goals>
172+
</execution>
173+
<execution>
174+
<id>test-compile</id>
175+
<phase>test-compile</phase>
176+
<goals>
177+
<goal>test-compile</goal>
178+
</goals>
179+
<configuration>
180+
<sourceDirs>
181+
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
182+
<sourceDir>${project.basedir}/src/test/java</sourceDir>
183+
</sourceDirs>
184+
</configuration>
185+
</execution>
186+
</executions>
187+
</plugin>
150188
<plugin>
151189
<groupId>org.apache.maven.plugins</groupId>
152190
<artifactId>maven-compiler-plugin</artifactId>
@@ -155,6 +193,30 @@
155193
<source>15</source>
156194
<target>15</target>
157195
</configuration>
196+
<executions>
197+
<execution>
198+
<id>default-compile</id>
199+
<phase>none</phase>
200+
</execution>
201+
<execution>
202+
<id>default-testCompile</id>
203+
<phase>none</phase>
204+
</execution>
205+
<execution>
206+
<id>java-compile</id>
207+
<phase>compile</phase>
208+
<goals>
209+
<goal>compile</goal>
210+
</goals>
211+
</execution>
212+
<execution>
213+
<id>java-test-compile</id>
214+
<phase>test-compile</phase>
215+
<goals>
216+
<goal>testCompile</goal>
217+
</goals>
218+
</execution>
219+
</executions>
158220
</plugin>
159221
<plugin>
160222
<artifactId>maven-surefire-plugin</artifactId>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.approvaltests.inline
2+
3+
import org.approvaltests.Approvals
4+
import org.approvaltests.core.Options
5+
import org.approvaltests.reporters.BeyondCompareReporter
6+
import org.junit.jupiter.api.Test
7+
8+
class KotlinInlineApprovalsTest {
9+
10+
@Test
11+
fun testInlineApproval() {
12+
13+
Approvals.verify("hello world", Options().inline("")
14+
.withReporter(InlineKotlinReporter(BeyondCompareReporter(), null)))
15+
}
16+
}

approvaltests/src/main/java/org/approvaltests/inline/InlineKotlinReporter.java

Lines changed: 117 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -9,121 +9,127 @@
99
import org.lambda.functions.Function3;
1010
import java.io.File;
1111

12-
public class InlineKotlinReporter implements ApprovalFailureReporter, ApprovalReporterWithCleanUp {
13-
private final String sourceFilePath;
14-
private final StackTraceNamer stackTraceNamer;
15-
private final Function2<String, String, String> footerCreator;
16-
private final ApprovalFailureReporter reporter;
17-
private String additionalLines = null;
18-
private Function3<String, String, String, String> createNewReceivedFileText;
19-
20-
public InlineKotlinReporter(ApprovalFailureReporter reporter, Function2<String, String, String> footerCreator) {
21-
this.reporter = reporter;
22-
this.stackTraceNamer = new StackTraceNamer();
23-
this.sourceFilePath = stackTraceNamer.getSourceFilePath();
24-
this.createNewReceivedFileText = (kotlinSourceCode, actual, methodName) ->
25-
createNewReceivedFileText(kotlinSourceCode, actual, methodName);
26-
this.footerCreator = footerCreator != null ? footerCreator : (source, actual) -> "";
27-
}
28-
29-
public InlineKotlinReporter(ApprovalFailureReporter reporter) {
30-
this(reporter, null);
31-
}
32-
33-
@Override
34-
public boolean report(String received, String approved) {
35-
additionalLines = footerCreator.call(received, approved);
36-
String sourceFile = sourceFilePath + stackTraceNamer.getInfo().getClassName() + ".kt";
37-
String newSource = createReceived(FileUtils.readFile(received));
38-
return reporter.report(newSource, sourceFile);
39-
}
40-
41-
public String createReceived(String actual) {
42-
String file = sourceFilePath + stackTraceNamer.getInfo().getClassName() + ".kt";
43-
String received = getReceivedFileName();
44-
String text = FileUtils.readFile(file);
45-
String fullText = this.createNewReceivedFileText.call(
46-
text, actual + additionalLines,
47-
this.stackTraceNamer.getInfo().getMethodName()
48-
);
49-
FileUtils.writeFile(new File(received), fullText);
50-
return received;
51-
}
52-
53-
private String getReceivedFileName() {
54-
return sourceFilePath + stackTraceNamer.getInfo().getClassName() + ".received.txt";
55-
}
56-
57-
@Override
58-
public void cleanUp(String received, String approved) {
59-
FileUtils.delete(getReceivedFileName());
12+
public class InlineKotlinReporter implements ApprovalFailureReporter, ApprovalReporterWithCleanUp
13+
{
14+
private final String sourceFilePath;
15+
private final StackTraceNamer stackTraceNamer;
16+
private final Function2<String, String, String> footerCreator;
17+
private final ApprovalFailureReporter reporter;
18+
private String additionalLines = null;
19+
private Function3<String, String, String, String> createNewReceivedFileText;
20+
public InlineKotlinReporter(ApprovalFailureReporter reporter, Function2<String, String, String> footerCreator)
21+
{
22+
this.reporter = reporter;
23+
this.stackTraceNamer = new StackTraceNamer();
24+
this.sourceFilePath = stackTraceNamer.getSourceFilePath();
25+
this.createNewReceivedFileText = (kotlinSourceCode, actual,
26+
methodName) -> createNewReceivedFileText(kotlinSourceCode, actual, methodName);
27+
this.footerCreator = footerCreator != null ? footerCreator : (source, actual) -> "";
28+
}
29+
public InlineKotlinReporter(ApprovalFailureReporter reporter)
30+
{
31+
this(reporter, null);
32+
}
33+
@Override
34+
public boolean report(String received, String approved)
35+
{
36+
additionalLines = footerCreator.call(received, approved);
37+
String sourceFile = sourceFilePath + stackTraceNamer.getInfo().getClassName() + ".kt";
38+
String newSource = createReceived(FileUtils.readFile(received));
39+
return reporter.report(newSource, sourceFile);
40+
}
41+
public String createReceived(String actual)
42+
{
43+
String file = sourceFilePath + stackTraceNamer.getInfo().getClassName() + ".kt";
44+
String received = getReceivedFileName();
45+
String text = FileUtils.readFile(file);
46+
String fullText = this.createNewReceivedFileText.call(text, actual + additionalLines,
47+
this.stackTraceNamer.getInfo().getMethodName());
48+
FileUtils.writeFile(new File(received), fullText);
49+
return received;
50+
}
51+
private String getReceivedFileName()
52+
{
53+
return sourceFilePath + stackTraceNamer.getInfo().getClassName() + ".received.txt";
54+
}
55+
@Override
56+
public void cleanUp(String received, String approved)
57+
{
58+
FileUtils.delete(getReceivedFileName());
59+
}
60+
public static String createNewReceivedFileText(String kotlinSourceCode, String actual, String methodName)
61+
{
62+
String normalizedSourceCode = kotlinSourceCode.replaceAll("\\r\\n", "\n");
63+
CodeParts codeParts = CodeParts.splitCode(normalizedSourceCode, methodName);
64+
if (codeParts.method != null && codeParts.method.contains("expected = \"\"\""))
65+
{
66+
replaceExpected(codeParts, actual);
6067
}
61-
62-
public static String createNewReceivedFileText(String kotlinSourceCode, String actual, String methodName) {
63-
String normalizedSourceCode = kotlinSourceCode.replaceAll("\\r\\n", "\n");
64-
CodeParts codeParts = CodeParts.splitCode(normalizedSourceCode, methodName);
65-
if (codeParts.method != null && codeParts.method.contains("expected = \"\"\"")) {
66-
replaceExpected(codeParts, actual);
67-
} else {
68-
addExpected(codeParts, actual);
69-
}
70-
return codeParts.getFullCode();
68+
else
69+
{
70+
addExpected(codeParts, actual);
7171
}
72-
73-
private static void addExpected(CodeParts codeParts, String actual) {
74-
int start = codeParts.method.indexOf("{") + 2;
75-
String before = codeParts.method.substring(0, start);
76-
String after = codeParts.method.substring(start);
77-
codeParts.method = before + getExpected(actual, codeParts.tab) + after;
72+
return codeParts.getFullCode();
73+
}
74+
private static void addExpected(CodeParts codeParts, String actual)
75+
{
76+
int start = codeParts.method.indexOf("{") + 2;
77+
String before = codeParts.method.substring(0, start);
78+
String after = codeParts.method.substring(start);
79+
codeParts.method = before + getExpected(actual, codeParts.tab) + after;
80+
}
81+
private static String getExpected(String actual, String tab)
82+
{
83+
return String.format("%s%sval expected = \"\"\"\n%s%s%s%s\"\"\".trimIndent()\n", tab, tab, indent(actual, tab),
84+
tab, tab, tab);
85+
}
86+
private static void replaceExpected(CodeParts codeParts, String actual)
87+
{
88+
int start = codeParts.method.indexOf("expected = \"\"\"");
89+
start = codeParts.method.substring(0, start).lastIndexOf("\n") + 1;
90+
// Find the closing """ by looking for it at the start of a line (after whitespace)
91+
int searchPos = start + "expected = \"\"\"".length();
92+
int end = -1;
93+
while (searchPos < codeParts.method.length())
94+
{
95+
int nextTripleQuote = codeParts.method.indexOf("\"\"\"", searchPos);
96+
if (nextTripleQuote == -1)
97+
break;
98+
// Check if this """ is at the start of a line (preceded only by whitespace)
99+
int lineStart = codeParts.method.lastIndexOf("\n", nextTripleQuote - 1) + 1;
100+
String textBeforeQuote = codeParts.method.substring(lineStart, nextTripleQuote);
101+
if (textBeforeQuote.trim().isEmpty())
102+
{
103+
end = nextTripleQuote;
104+
break;
105+
}
106+
searchPos = nextTripleQuote + 1;
78107
}
79-
80-
private static String getExpected(String actual, String tab) {
81-
return String.format(
82-
"%s%sval expected = \"\"\"\n%s%s%s%s\"\"\".trimIndent()\n", tab, tab, indent(actual, tab), tab, tab,
83-
tab
84-
);
108+
if (end == -1)
109+
{
110+
// Fallback to old behavior if we can't find it
111+
end = codeParts.method.indexOf("\"\"\"", start + "expected = \"\"\"".length());
85112
}
86-
87-
private static void replaceExpected(CodeParts codeParts, String actual) {
88-
int start = codeParts.method.indexOf("expected = \"\"\"");
89-
start = codeParts.method.substring(0, start).lastIndexOf("\n") + 1;
90-
// Find the closing """ by looking for it at the start of a line (after whitespace)
91-
int searchPos = start + "expected = \"\"\"".length();
92-
int end = -1;
93-
while (searchPos < codeParts.method.length()) {
94-
int nextTripleQuote = codeParts.method.indexOf("\"\"\"", searchPos);
95-
if (nextTripleQuote == -1) break;
96-
// Check if this """ is at the start of a line (preceded only by whitespace)
97-
int lineStart = codeParts.method.lastIndexOf("\n", nextTripleQuote - 1) + 1;
98-
String textBeforeQuote = codeParts.method.substring(lineStart, nextTripleQuote);
99-
if (textBeforeQuote.trim().isEmpty()) {
100-
end = nextTripleQuote;
101-
break;
102-
}
103-
searchPos = nextTripleQuote + 1;
104-
}
105-
if (end == -1) {
106-
// Fallback to old behavior if we can't find it
107-
end = codeParts.method.indexOf("\"\"\"", start + "expected = \"\"\"".length());
108-
}
109-
end += 3; // Move past the closing """
110-
// Check if there's a .trimIndent() after the closing """
111-
String afterTripleQuote = codeParts.method.substring(end);
112-
if (afterTripleQuote.startsWith(".trimIndent()")) {
113-
end += ".trimIndent()".length();
114-
}
115-
end = codeParts.method.indexOf("\n", end) + 1;
116-
String before = codeParts.method.substring(0, start);
117-
String after = codeParts.method.substring(end);
118-
codeParts.method = before + getExpected(actual, codeParts.tab) + after;
113+
end += 3; // Move past the closing """
114+
// Check if there's a .trimIndent() after the closing """
115+
String afterTripleQuote = codeParts.method.substring(end);
116+
if (afterTripleQuote.startsWith(".trimIndent()"))
117+
{
118+
end += ".trimIndent()".length();
119119
}
120-
121-
public static String indent(String actual, String tab) {
122-
String[] split = StringUtils.split(actual, "\n");
123-
String output = "";
124-
for (String line : split) {
125-
output += tab + tab + tab + line + "\n";
126-
}
127-
return output;
120+
end = codeParts.method.indexOf("\n", end) + 1;
121+
String before = codeParts.method.substring(0, start);
122+
String after = codeParts.method.substring(end);
123+
codeParts.method = before + getExpected(actual, codeParts.tab) + after;
124+
}
125+
public static String indent(String actual, String tab)
126+
{
127+
String[] split = StringUtils.split(actual, "\n");
128+
String output = "";
129+
for (String line : split)
130+
{
131+
output += tab + tab + tab + line + "\n";
128132
}
133+
return output;
134+
}
129135
}

0 commit comments

Comments
 (0)