Skip to content

Commit d27e618

Browse files
aslakhellesoyaurelien-reevesmpkorstanje
authored
Java optional codegen with final fields (#1879)
* Implement custom code generator for Java * Pass template as cli arg * Update tests to use new code * Update gherkin and html-formatter * Fix shading * Fix serialization * Replace custom codegen with jsonschema2pojo-maven-plugin * Remove Java code generator. Update imports. * Fix serialization * Fix compilation error * Remove Java code generator * Switch back to NON_ABSENT * Improve optional code * Revert "Remove Java code generator" This reverts commit 4a4963e. * Revert "Remove Java code generator. Update imports." This reverts commit efe26b4. * Revert "Replace custom codegen with jsonschema2pojo-maven-plugin" This reverts commit 6b86b54. * Fix compile error * Restore custom code generation with validation * Expand imports * Test validate() * Update changelog * Improve generated messages * Setters are removed * Classes without required fields have static fromXxx factory methods for each field * Only classes without required fields have a public constructor * Update changelog * Remove map lookup from enums * Rename static factories to just from * Make all lists unmodifiable * Copy list before making it unmodifiable * Add minItems * Use final fields * Remove validate() * Add Jackson parameter names module * Fix tests. Fix enum fromValue * Add shading of com.fasterxml.jackson.module:jackson-module-parameter-names * Use single-arg constructor instead of static from method * Fix Gherkin compile errors * Fix HTML Formatter compile errors * Fix another compile error * Decouple Jackson and make tests pass * Remove Gherkin Main file from jar * Rename test * Make it work with jackson - use property based constructors - ensure there is only one property based constructor - clean up unused warnings - use imports to make code not look generated * Use idiomatic java for Enum.fromValue * Use idiomatic java for serializer and deserializer * Clean up gherkin parser - Rename Gherkin to GherkinParser to reflect intent - Use builder pattern to configure parser - Push IO operations from parser to Main class. - Limit parser to parsing single envelopes * Fix test * Idiomatic java * Naming stuff * Reduce scope of gherkin parser public api * Idiomatic java * Always include parse errors No parsing would happen if neither pickles nor gherkin document were to be included in the messages stream. * Reuse pickle compiler * Idiomatic java * Signal that Messages class is generated * Nitpicking * Null checks * Null checks * Remove GenerateTokens from gherkin public api * Reduce html writer public api * Update readmes * Generate messages into separate files * Update imports * Reduce diff size * Fix imports Co-authored-by: Aurélien Reeves <[email protected]> Co-authored-by: M.P. Korstanje <[email protected]> Co-authored-by: M.P. Korstanje <[email protected]>
1 parent 14d37a0 commit d27e618

File tree

151 files changed

+5914
-909
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+5914
-909
lines changed

.templates/java/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ dependency-reduced-pom.xml
1212
.tested*
1313
.compared
1414
.built
15+
.codegen
1516
# Approval tests
1617
acceptance/

.templates/java/default.mk

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(su
1212
default: .tested
1313
.PHONY: default
1414

15+
.codegen:
16+
touch $@
17+
1518
.tested: .tested-jar-check
1619

1720
.tested-jar-check: .deps .built
1821
./scripts/check-jar.sh $(JAR)
1922
touch $@
2023

21-
.built: pom.xml $(JAVA_SOURCE_FILES)
24+
.built: pom.xml $(JAVA_SOURCE_FILES) .codegen
2225
mvn install
2326
touch $@
2427

@@ -59,7 +62,7 @@ clean: clean-java
5962
.PHONY: clean
6063

6164
clean-java:
62-
rm -rf target .deps .tested* .built acceptance
65+
rm -rf target .deps .tested* .built acceptance .codegen
6366
mvn clean
6467
.PHONY: clean-java
6568

config/java/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ dependency-reduced-pom.xml
1212
.tested*
1313
.compared
1414
.built
15+
.codegen
1516
# Approval tests
1617
acceptance/

config/java/default.mk

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(su
1212
default: .tested
1313
.PHONY: default
1414

15+
.codegen:
16+
touch $@
17+
1518
.tested: .tested-jar-check
1619

1720
.tested-jar-check: .deps .built
1821
./scripts/check-jar.sh $(JAR)
1922
touch $@
2023

21-
.built: pom.xml $(JAVA_SOURCE_FILES)
24+
.built: pom.xml $(JAVA_SOURCE_FILES) .codegen
2225
mvn install
2326
touch $@
2427

@@ -59,7 +62,7 @@ clean: clean-java
5962
.PHONY: clean
6063

6164
clean-java:
62-
rm -rf target .deps .tested* .built acceptance
65+
rm -rf target .deps .tested* .built acceptance .codegen
6366
mvn clean
6467
.PHONY: clean-java
6568

gherkin/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt
1313

1414
### Changed
1515

16+
* [Java] Replaced `Gherkin` with a `GherkinParser` that uses a builder to construct.
17+
* [Java] Made all internal classes package private
18+
1619
### Deprecated
1720

1821
### Removed
1922

23+
- [Java] the `io.cucumber.gherkin.Main` class is no longer part of the jar.
24+
2025
### Fixed
2126

2227
## [22.0.0] - 2021-09-23

gherkin/java/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ dependency-reduced-pom.xml
1212
.tested*
1313
.compared
1414
.built
15+
.codegen
1516
# Approval tests
1617
acceptance/

gherkin/java/bin/gherkin

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ if [ ! -f "${DIR}/classpath.txt" ] || [ "${DIR}/../pom.xml" -nt "${DIR}/classpat
1212
fi
1313

1414
java \
15-
-classpath "$(cat "${DIR}/classpath.txt"):${DIR}/../target/classes" \
15+
-classpath "$(cat "${DIR}/classpath.txt"):${DIR}/../target/test-classes:${DIR}/../target/classes" \
1616
io.cucumber.gherkin.Main $*

gherkin/java/bin/gherkin-generate-tokens

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ if [ ! -f "${DIR}/classpath.txt" ] || [ "${DIR}/../pom.xml" -nt "${DIR}/classpat
1212
fi
1313

1414
java \
15-
-classpath "$(cat "${DIR}/classpath.txt"):${DIR}/../target/classes" \
15+
-classpath "$(cat "${DIR}/classpath.txt"):${DIR}/../target/classes:${DIR}/../target/test-classes" \
1616
io.cucumber.gherkin.GenerateTokens $*

gherkin/java/default.mk

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(su
1212
default: .tested
1313
.PHONY: default
1414

15+
.codegen:
16+
touch $@
17+
1518
.tested: .tested-jar-check
1619

1720
.tested-jar-check: .deps .built
1821
./scripts/check-jar.sh $(JAR)
1922
touch $@
2023

21-
.built: pom.xml $(JAVA_SOURCE_FILES)
24+
.built: pom.xml $(JAVA_SOURCE_FILES) .codegen
2225
mvn install
2326
touch $@
2427

@@ -59,7 +62,7 @@ clean: clean-java
5962
.PHONY: clean
6063

6164
clean-java:
62-
rm -rf target .deps .tested* .built acceptance
65+
rm -rf target .deps .tested* .built acceptance .codegen
6366
mvn clean
6467
.PHONY: clean-java
6568

gherkin/java/gherkin-java.razor

+29-29
Original file line numberDiff line numberDiff line change
@@ -47,34 +47,34 @@ import java.util.Queue;
4747

4848
import static java.util.Arrays.asList;
4949

50-
public class @Model.ParserClassName<T> {
51-
public enum TokenType {
50+
class @Model.ParserClassName<T> {
51+
enum TokenType {
5252
None,
5353
@foreach(var rule in Model.RuleSet.TokenRules)
5454
{<text> @rule.Name.Replace("#", ""),
5555
</text>} ;
5656
}
5757

58-
public enum RuleType {
58+
enum RuleType {
5959
None,
6060
@foreach(var rule in Model.RuleSet.Where(r => !r.TempRule))
6161
{<text> @rule.Name.Replace("#", "_"), // @rule.ToString(true)
6262
</text>} ;
6363

64-
public static RuleType cast(TokenType tokenType) {
64+
static RuleType cast(TokenType tokenType) {
6565
return RuleType.values()[tokenType.ordinal()];
6666
}
6767
}
6868

6969
private final Builder<T> builder;
7070

71-
public boolean stopAtFirstError;
71+
private boolean stopAtFirstError;
7272

73-
class ParserContext {
74-
public final ITokenScanner tokenScanner;
75-
public final ITokenMatcher tokenMatcher;
76-
public final Queue<Token> tokenQueue;
77-
public final List<ParserException> errors;
73+
static class ParserContext {
74+
final ITokenScanner tokenScanner;
75+
final ITokenMatcher tokenMatcher;
76+
final Queue<Token> tokenQueue;
77+
final List<ParserException> errors;
7878

7979
ParserContext(ITokenScanner tokenScanner, ITokenMatcher tokenMatcher, Queue<Token> tokenQueue, List<ParserException> errors) {
8080
this.tokenScanner = tokenScanner;
@@ -84,39 +84,39 @@ public class @Model.ParserClassName<T> {
8484
}
8585
}
8686

87-
public Parser(Builder<T> builder) {
87+
Parser(Builder<T> builder) {
8888
this.builder = builder;
8989
}
9090

91-
public T parse(String source) {
92-
return parse(new StringReader(source));
91+
T parse(String source, String uri) {
92+
return parse(new StringReader(source), uri);
9393
}
9494

95-
public T parse(Reader source) {
96-
return parse(new TokenScanner(source));
95+
T parse(Reader source, String uri) {
96+
return parse(new TokenScanner(source), uri);
9797
}
9898

99-
public T parse(ITokenScanner tokenScanner) {
100-
return parse(tokenScanner, new TokenMatcher());
99+
T parse(ITokenScanner tokenScanner, String uri) {
100+
return parse(tokenScanner, new TokenMatcher(), uri);
101101
}
102102

103-
public T parse(String source, ITokenMatcher tokenMatcher) {
104-
return parse(new StringReader(source), tokenMatcher);
103+
T parse(String source, ITokenMatcher tokenMatcher, String uri) {
104+
return parse(new StringReader(source), tokenMatcher, uri);
105105
}
106106

107-
public T parse(Reader source, ITokenMatcher tokenMatcher) {
108-
return parse(new TokenScanner(source), tokenMatcher);
107+
T parse(Reader source, ITokenMatcher tokenMatcher, String uri) {
108+
return parse(new TokenScanner(source), tokenMatcher, uri);
109109
}
110110

111-
public T parse(ITokenScanner tokenScanner, ITokenMatcher tokenMatcher) {
112-
builder.reset();
111+
T parse(ITokenScanner tokenScanner, ITokenMatcher tokenMatcher, String uri) {
112+
builder.reset(uri);
113113
tokenMatcher.reset();
114114

115115
ParserContext context = new ParserContext(
116116
tokenScanner,
117117
tokenMatcher,
118-
new LinkedList<Token>(),
119-
new ArrayList<ParserException>()
118+
new LinkedList<>(),
119+
new ArrayList<>()
120120
);
121121

122122
startRule(context, RuleType.@Model.RuleSet.StartRule.Name);
@@ -298,19 +298,19 @@ public class @Model.ParserClassName<T> {
298298
</text>
299299
}
300300

301-
public interface Builder<T> {
301+
interface Builder<T> {
302302
void build(Token token);
303303
void startRule(RuleType ruleType);
304304
void endRule(RuleType ruleType);
305305
T getResult();
306-
void reset();
306+
void reset(String uri);
307307
}
308308

309-
public interface ITokenScanner {
309+
interface ITokenScanner {
310310
Token read();
311311
}
312312

313-
public interface ITokenMatcher {
313+
interface ITokenMatcher {
314314
@foreach(var rule in Model.RuleSet.TokenRules)
315315
{
316316
@:boolean match_@(rule.Name.Replace("#", ""))(Token token);

gherkin/java/pom.xml

+31-13
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,23 @@
2525
<tag>HEAD</tag>
2626
</scm>
2727

28+
<dependencyManagement>
29+
<dependencies>
30+
<dependency>
31+
<groupId>com.fasterxml.jackson</groupId>
32+
<artifactId>jackson-bom</artifactId>
33+
<version>2.13.1</version>
34+
<type>pom</type>
35+
<scope>import</scope>
36+
</dependency>
37+
</dependencies>
38+
</dependencyManagement>
39+
2840
<dependencies>
2941
<dependency>
3042
<groupId>io.cucumber</groupId>
3143
<artifactId>messages</artifactId>
32-
<version>[17.1.1,18.0.0)</version>
44+
<version>[17.1.2-SNAPSHOT,18.0.0)</version>
3345
</dependency>
3446

3547
<dependency>
@@ -38,6 +50,24 @@
3850
<version>0.9.5</version>
3951
</dependency>
4052

53+
<dependency>
54+
<groupId>com.fasterxml.jackson.core</groupId>
55+
<artifactId>jackson-databind</artifactId>
56+
<scope>test</scope>
57+
</dependency>
58+
59+
<dependency>
60+
<groupId>com.fasterxml.jackson.datatype</groupId>
61+
<artifactId>jackson-datatype-jdk8</artifactId>
62+
<scope>test</scope>
63+
</dependency>
64+
65+
<dependency>
66+
<groupId>com.fasterxml.jackson.module</groupId>
67+
<artifactId>jackson-module-parameter-names</artifactId>
68+
<scope>test</scope>
69+
</dependency>
70+
4171
<dependency>
4272
<groupId>junit</groupId>
4373
<artifactId>junit</artifactId>
@@ -48,18 +78,6 @@
4878

4979
<build>
5080
<plugins>
51-
<plugin>
52-
<groupId>org.apache.maven.plugins</groupId>
53-
<artifactId>maven-jar-plugin</artifactId>
54-
<configuration>
55-
<archive>
56-
<manifest>
57-
<mainClass>io.cucumber.gherkin.Main</mainClass>
58-
</manifest>
59-
</archive>
60-
</configuration>
61-
</plugin>
62-
6381
<plugin>
6482
<groupId>org.apache.maven.plugins</groupId>
6583
<artifactId>maven-shade-plugin</artifactId>

gherkin/java/src/main/java/io/cucumber/gherkin/AstNode.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import static io.cucumber.gherkin.Parser.RuleType;
1010
import static io.cucumber.gherkin.Parser.TokenType;
1111

12-
public class AstNode {
12+
class AstNode {
1313
private final Map<RuleType, List<Object>> subItems = new HashMap<RuleType, List<Object>>();
1414
public final RuleType ruleType;
1515

@@ -18,11 +18,7 @@ public AstNode(RuleType ruleType) {
1818
}
1919

2020
public void add(RuleType ruleType, Object obj) {
21-
List<Object> items = subItems.get(ruleType);
22-
if (items == null) {
23-
items = new ArrayList<Object>();
24-
subItems.put(ruleType, items);
25-
}
21+
List<Object> items = subItems.computeIfAbsent(ruleType, k -> new ArrayList<>());
2622
items.add(obj);
2723
}
2824

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package io.cucumber.gherkin;
22

3-
public interface Func<V> {
3+
interface Func<V> {
44
V call();
55
}

0 commit comments

Comments
 (0)