Skip to content

Commit 7608000

Browse files
committed
Reduce duplication between code and snippet generation
Fixes #3063
1 parent b5c47fc commit 7608000

File tree

4 files changed

+75
-129
lines changed

4 files changed

+75
-129
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.cucumber.core.codegen;
2+
3+
import io.cucumber.gherkin.GherkinDialect;
4+
5+
import java.text.Normalizer;
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.List;
9+
import java.util.stream.IntStream;
10+
11+
import static java.util.stream.Collectors.joining;
12+
13+
public class GherkinKeywordNormalizer {
14+
15+
private GherkinKeywordNormalizer() {
16+
}
17+
18+
public static String normalizeKeyword(String language, String keyword) {
19+
// Exception: Use the symbol names for the Emoj language.
20+
// Emoji are not legal identifiers in Java.
21+
if ("em".equals(language)) {
22+
return normalizeEmojiKeyword(keyword);
23+
}
24+
return normalizeKeyword(keyword);
25+
}
26+
27+
public static String normalizeLanguage(GherkinDialect dialect) {
28+
return dialect.getLanguage().replaceAll("[\\s-]", "_").toLowerCase();
29+
}
30+
31+
public static String capitalize(String str) {
32+
return str.substring(0, 1).toUpperCase() + str.substring(1);
33+
}
34+
35+
private static String normalizeKeyword(String keyword) {
36+
return normalize(keyword.replaceAll("[\\s',!\u00AD’]", ""));
37+
}
38+
39+
private static String normalizeEmojiKeyword(String keyword) {
40+
String titleCasedName = getCodePoints(keyword).mapToObj(Character::getName)
41+
.map(s -> s.split(" "))
42+
.flatMap(Arrays::stream)
43+
.map(String::toLowerCase)
44+
.map(GherkinKeywordNormalizer::capitalize)
45+
.collect(joining(" "));
46+
return normalizeKeyword(titleCasedName);
47+
}
48+
49+
private static String normalize(CharSequence s) {
50+
return Normalizer.normalize(s, Normalizer.Form.NFC);
51+
}
52+
53+
private static IntStream getCodePoints(String s) {
54+
int length = s.length();
55+
List<Integer> codePoints = new ArrayList<>();
56+
for (int offset = 0; offset < length;) {
57+
int codepoint = s.codePointAt(offset);
58+
codePoints.add(codepoint);
59+
offset += Character.charCount(codepoint);
60+
}
61+
return codePoints.stream().mapToInt(value -> value);
62+
}
63+
}

cucumber-core/src/main/java/io/cucumber/core/snippets/SnippetGenerator.java

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,16 @@
1212
import io.cucumber.plugin.event.StepArgument;
1313

1414
import java.lang.reflect.Type;
15-
import java.text.Normalizer;
16-
import java.util.ArrayList;
17-
import java.util.Arrays;
1815
import java.util.LinkedHashMap;
1916
import java.util.List;
2017
import java.util.Map;
2118
import java.util.Optional;
2219
import java.util.regex.Pattern;
2320
import java.util.stream.Collectors;
24-
import java.util.stream.IntStream;
2521
import java.util.stream.Stream;
2622

23+
import static io.cucumber.core.codegen.GherkinKeywordNormalizer.normalizeKeyword;
2724
import static io.cucumber.core.snippets.SnippetType.CAMELCASE;
28-
import static java.util.stream.Collectors.joining;
2925

3026
public final class SnippetGenerator {
3127

@@ -72,7 +68,7 @@ private String createSnippet(
7268
List<String> parameterNames = toParameterNames(expression, parameterNameGenerator);
7369
Map<String, Type> arguments = arguments(step, parameterNames, expression.getParameterTypes());
7470
return snippet.template().format(new String[] {
75-
getNormalizedKeyWord(language, keyword),
71+
normalizeKeyword(language, keyword),
7672
snippet.escapePattern(source),
7773
functionName,
7874
snippet.arguments(arguments),
@@ -88,48 +84,6 @@ private List<String> toParameterNames(GeneratedExpression expression, Identifier
8884
.collect(Collectors.toList());
8985
}
9086

91-
private static String capitalize(String str) {
92-
return str.substring(0, 1).toUpperCase() + str.substring(1);
93-
}
94-
95-
private static String getNormalizedKeyWord(String language, String keyword) {
96-
// Exception: Use the symbol names for the Emoj language.
97-
// Emoji are not legal identifiers in Java.
98-
if ("em".equals(language)) {
99-
return getNormalizedEmojiKeyWord(keyword);
100-
}
101-
return getNormalizedKeyWord(keyword);
102-
}
103-
104-
private static String getNormalizedEmojiKeyWord(String keyword) {
105-
String titleCasedName = getCodePoints(keyword).mapToObj(Character::getName)
106-
.map(s -> s.split(" "))
107-
.flatMap(Arrays::stream)
108-
.map(String::toLowerCase)
109-
.map(SnippetGenerator::capitalize)
110-
.collect(joining(" "));
111-
return getNormalizedKeyWord(titleCasedName);
112-
}
113-
114-
private static IntStream getCodePoints(String s) {
115-
int length = s.length();
116-
List<Integer> codePoints = new ArrayList<>();
117-
for (int offset = 0; offset < length;) {
118-
int codepoint = s.codePointAt(offset);
119-
codePoints.add(codepoint);
120-
offset += Character.charCount(codepoint);
121-
}
122-
return codePoints.stream().mapToInt(value -> value);
123-
}
124-
125-
private static String getNormalizedKeyWord(String keyword) {
126-
return normalize(keyword.replaceAll("[\\s',!\u00AD’]", ""));
127-
}
128-
129-
static String normalize(CharSequence s) {
130-
return Normalizer.normalize(s, Normalizer.Form.NFC);
131-
}
132-
13387
private String functionName(String sentence, IdentifierGenerator functionNameGenerator) {
13488
String functionName = Stream.of(sentence)
13589
.map(DEFAULT_ARGUMENT_PATTERN::replaceMatchesWithSpace)

cucumber-java/src/codegen/java/GenerateI18n.java

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
1111
import java.nio.file.Paths;
12-
import java.text.Normalizer;
13-
import java.util.Arrays;
1412
import java.util.Collections;
1513
import java.util.LinkedHashMap;
1614
import java.util.List;
1715
import java.util.Locale;
1816
import java.util.Map;
1917

18+
import static io.cucumber.core.codegen.GherkinKeywordNormalizer.normalizeKeyword;
19+
import static io.cucumber.core.codegen.GherkinKeywordNormalizer.normalizeLanguage;
2020
import static java.nio.file.Files.newBufferedWriter;
2121
import static java.nio.file.StandardOpenOption.CREATE;
2222
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
23-
import static java.util.stream.Collectors.joining;
2423

2524
/* This class generates the cucumber-java Interfaces and package-info
2625
* based on the languages and keywords from the GherkinDialects
@@ -79,8 +78,8 @@ private void writeKeyWordAnnotations(GherkinDialect dialect) {
7978
}
8079

8180
private void writeKeyWordAnnotation(GherkinDialect dialect, String keyword) {
82-
String normalizedLanguage = getNormalizedLanguage(dialect);
83-
String normalizedKeyword = getNormalizedKeyWord(dialect, keyword);
81+
String normalizedLanguage = normalizeLanguage(dialect);
82+
String normalizedKeyword = normalizeKeyword(dialect.getLanguage(), keyword);
8483

8584
Map<String, String> binding = new LinkedHashMap<>();
8685
binding.put("lang", normalizedLanguage);
@@ -103,39 +102,8 @@ private void writeKeyWordAnnotation(GherkinDialect dialect, String keyword) {
103102
}
104103
}
105104

106-
private static String capitalize(String s) {
107-
return s.substring(0, 1).toUpperCase() + s.substring(1);
108-
}
109-
110-
private static String getNormalizedKeyWord(GherkinDialect dialect, String keyword) {
111-
// Exception: Use the symbol names for the Emoj language.
112-
// Emoji are not legal identifiers in Java.
113-
if (dialect.getLanguage().equals("em")) {
114-
return getNormalizedEmojiKeyWord(keyword);
115-
}
116-
return getNormalizedKeyWord(keyword);
117-
}
118-
119-
private static String getNormalizedEmojiKeyWord(String keyword) {
120-
String titleCasedName = keyword.codePoints().mapToObj(Character::getName)
121-
.map(s -> s.split(" "))
122-
.flatMap(Arrays::stream)
123-
.map(String::toLowerCase)
124-
.map(DialectWriter::capitalize)
125-
.collect(joining(" "));
126-
return getNormalizedKeyWord(titleCasedName);
127-
}
128-
129-
private static String getNormalizedKeyWord(String keyword) {
130-
return normalize(keyword.replaceAll("[\\s',!\u00AD’]", ""));
131-
}
132-
133-
private static String normalize(CharSequence s) {
134-
return Normalizer.normalize(s, Normalizer.Form.NFC);
135-
}
136-
137105
private void writePackageInfo(GherkinDialect dialect) {
138-
String normalizedLanguage = getNormalizedLanguage(dialect);
106+
String normalizedLanguage = normalizeLanguage(dialect);
139107
String languageName = dialect.getName();
140108
if (!dialect.getName().equals(dialect.getNativeName())) {
141109
languageName += " - " + dialect.getNativeName();
@@ -155,9 +123,5 @@ private void writePackageInfo(GherkinDialect dialect) {
155123
}
156124
}
157125

158-
private static String getNormalizedLanguage(GherkinDialect dialect) {
159-
return dialect.getLanguage().replaceAll("[\\s-]", "_").toLowerCase();
160-
}
161-
162126
}
163127
}

cucumber-java8/src/codegen/java/GenerateI18n.java

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
1111
import java.nio.file.Paths;
12-
import java.text.Normalizer;
13-
import java.util.Arrays;
1412
import java.util.Collections;
1513
import java.util.LinkedHashMap;
1614
import java.util.List;
1715
import java.util.Locale;
1816
import java.util.Map;
1917

18+
import static io.cucumber.core.codegen.GherkinKeywordNormalizer.capitalize;
19+
import static io.cucumber.core.codegen.GherkinKeywordNormalizer.normalizeKeyword;
20+
import static io.cucumber.core.codegen.GherkinKeywordNormalizer.normalizeLanguage;
2021
import static java.nio.file.Files.newBufferedWriter;
2122
import static java.nio.file.StandardOpenOption.CREATE;
2223
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
23-
import static java.util.stream.Collectors.joining;
2424
import static java.util.stream.Collectors.toList;
2525

2626
/* This class generates the cucumber-java Interfaces and package-info
@@ -69,7 +69,7 @@ void writeDialect(GherkinDialect dialect) {
6969
}
7070

7171
private void writeInterface(GherkinDialect dialect) {
72-
String normalizedLanguage = getNormalizedLanguage(dialect);
72+
String normalizedLanguage = normalizeLanguage(dialect);
7373
String languageName = dialect.getName();
7474
if (!dialect.getName().equals(dialect.getNativeName())) {
7575
languageName += " - " + dialect.getNativeName();
@@ -98,43 +98,8 @@ private static List<String> extractKeywords(GherkinDialect dialect) {
9898
.filter(it -> !it.contains(String.valueOf('*')))
9999
.filter(it -> !it.matches("^\\d.*"))
100100
.distinct()
101-
.map(keyword -> getNormalizedKeyWord(dialect, keyword))
101+
.map(keyword -> normalizeKeyword(dialect.getLanguage(), keyword))
102102
.collect(toList());
103103
}
104-
105-
private static String capitalize(String str) {
106-
return str.substring(0, 1).toUpperCase() + str.substring(1);
107-
}
108-
109-
private static String getNormalizedKeyWord(GherkinDialect dialect, String keyword) {
110-
// Exception: Use the symbol names for the Emoj language.
111-
// Emoji are not legal identifiers in Java.
112-
if (dialect.getLanguage().equals("em")) {
113-
return getNormalizedEmojiKeyWord(keyword);
114-
}
115-
return getNormalizedKeyWord(keyword);
116-
}
117-
118-
private static String getNormalizedEmojiKeyWord(String keyword) {
119-
String titleCasedName = keyword.codePoints().mapToObj(Character::getName)
120-
.map(s -> s.split(" "))
121-
.flatMap(Arrays::stream)
122-
.map(String::toLowerCase)
123-
.map(DialectWriter::capitalize)
124-
.collect(joining(" "));
125-
return getNormalizedKeyWord(titleCasedName);
126-
}
127-
128-
private static String getNormalizedKeyWord(String keyword) {
129-
return normalize(keyword.replaceAll("[\\s',!\u00AD’]", ""));
130-
}
131-
132-
static String normalize(CharSequence s) {
133-
return Normalizer.normalize(s, Normalizer.Form.NFC);
134-
}
135-
136-
private static String getNormalizedLanguage(GherkinDialect dialect) {
137-
return dialect.getLanguage().replaceAll("[\\s-]", "_").toLowerCase();
138-
}
139104
}
140105
}

0 commit comments

Comments
 (0)