Skip to content

Commit 533f709

Browse files
committed
[Java] Make CucumberExpressionParser.parse public
Fixes: #51 By doing this we're exposing the public API surface. If #41 ever gets implemented, it may require a change to the AST. We can live with that.
1 parent 2fdb916 commit 533f709

File tree

7 files changed

+54
-30
lines changed

7 files changed

+54
-30
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
9+
### Added
10+
[Java] Make CucumberExpressionParser.parse public ([#340](https://github.com/cucumber/cucumber-expressions/pull/340))
911

1012
## [18.0.1] - 2024-10-28
1113
### Fixed

java/src/main/java/io/cucumber/cucumberexpressions/Ast.java

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44
import java.util.Objects;
55
import java.util.StringJoiner;
66

7-
import static java.util.Arrays.asList;
87
import static java.util.Objects.requireNonNull;
98
import static java.util.stream.Collectors.joining;
109

11-
final class Ast {
10+
public final class Ast {
1211

13-
private static final char escapeCharacter = '\\';
14-
private static final char alternationCharacter = '/';
15-
private static final char beginParameterCharacter = '{';
16-
private static final char endParameterCharacter = '}';
17-
private static final char beginOptionalCharacter = '(';
18-
private static final char endOptionalCharacter = ')';
12+
public static final char escapeCharacter = '\\';
13+
public static final char alternationCharacter = '/';
14+
public static final char beginParameterCharacter = '{';
15+
public static final char endParameterCharacter = '}';
16+
public static final char beginOptionalCharacter = '(';
17+
public static final char endOptionalCharacter = ')';
1918

2019
interface Located {
2120
int start();
@@ -24,7 +23,7 @@ interface Located {
2423

2524
}
2625

27-
static final class Node implements Located {
26+
public static final class Node implements Located {
2827

2928
private final Type type;
3029
private final List<Node> nodes;
@@ -33,11 +32,11 @@ static final class Node implements Located {
3332
private final int end;
3433

3534
Node(Type type, int start, int end, String token) {
36-
this(type, start, end, null, token);
35+
this(type, start, end, null, requireNonNull(token));
3736
}
3837

3938
Node(Type type, int start, int end, List<Node> nodes) {
40-
this(type, start, end, nodes, null);
39+
this(type, start, end, requireNonNull(nodes), null);
4140
}
4241

4342
private Node(Type type, int start, int end, List<Node> nodes, String token) {
@@ -48,7 +47,7 @@ private Node(Type type, int start, int end, List<Node> nodes, String token) {
4847
this.end = end;
4948
}
5049

51-
enum Type {
50+
public enum Type {
5251
TEXT_NODE,
5352
OPTIONAL_NODE,
5453
ALTERNATION_NODE,
@@ -65,14 +64,24 @@ public int end() {
6564
return end;
6665
}
6766

68-
List<Node> nodes() {
67+
/**
68+
* @return child nodes, {@code null} if a leaf-node
69+
*/
70+
public List<Node> nodes() {
6971
return nodes;
7072
}
7173

72-
Type type() {
74+
public Type type() {
7375
return type;
7476
}
7577

78+
/**
79+
* @return the text contained with in this node, {@code null} if not a leaf-node
80+
*/
81+
public String token() {
82+
return token;
83+
}
84+
7685
String text() {
7786
if (nodes == null)
7887
return token;
@@ -106,13 +115,13 @@ private StringBuilder toString(int depth) {
106115
if (nodes != null) {
107116
sb.append(", \"nodes\": ");
108117
if (!nodes.isEmpty()) {
109-
StringBuilder padding = new StringBuilder();
110-
for (int i = 0; i < depth; i++) {
111-
padding.append(" ");
112-
}
113-
sb.append(nodes.stream()
114-
.map(node -> node.toString(depth + 1))
115-
.collect(joining(",\n", "[\n", "\n" +padding + "]")));
118+
StringBuilder padding = new StringBuilder();
119+
for (int i = 0; i < depth; i++) {
120+
padding.append(" ");
121+
}
122+
sb.append(nodes.stream()
123+
.map(node -> node.toString(depth + 1))
124+
.collect(joining(",\n", "[\n", "\n" + padding + "]")));
116125

117126
} else {
118127
sb.append("[]");
@@ -224,10 +233,10 @@ public int hashCode() {
224233

225234
@Override
226235
public String toString() {
227-
return new StringJoiner(", ", "" + "{", "}")
236+
return new StringJoiner(", ", "{", "}")
228237
.add("\"type\": \"" + type + "\"")
229-
.add("\"start\": " + start + "")
230-
.add("\"end\": " + end + "")
238+
.add("\"start\": " + start)
239+
.add("\"end\": " + end)
231240
.add("\"text\": \"" + text + "\"")
232241
.toString();
233242
}

java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpressionParser.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
import static java.util.Arrays.asList;
2929
import static java.util.Collections.singletonList;
3030

31-
final class CucumberExpressionParser {
31+
/**
32+
* A parser for Cucumber expressions
33+
*/
34+
public final class CucumberExpressionParser {
3235

3336
/*
3437
* text := whitespace | ')' | '}' | .
@@ -160,7 +163,13 @@ final class CucumberExpressionParser {
160163
)
161164
);
162165

163-
Node parse(String expression) {
166+
/**
167+
* Parses as Cucumber expression into an AST of {@link Node nodes}.
168+
* @param expression the expression to parse
169+
* @return an AST of nodes
170+
* @throws CucumberExpressionException if the expression could not be parsed
171+
*/
172+
public Node parse(String expression) {
164173
CucumberExpressionTokenizer tokenizer = new CucumberExpressionTokenizer();
165174
List<Token> tokens = tokenizer.tokenize(expression);
166175
Result result = cucumberExpressionParser.parse(expression, tokens, 0);

java/src/main/java/io/cucumber/cucumberexpressions/GroupBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ final class GroupBuilder {
99
private final List<GroupBuilder> groupBuilders = new ArrayList<>();
1010
private boolean capturing = true;
1111
private String source;
12-
private int startIndex;
12+
private final int startIndex;
1313
private int endIndex;
1414

1515
GroupBuilder(int startIndex) {

java/src/main/java/io/cucumber/cucumberexpressions/RegularExpression.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public List<Argument<?>> match(String text, Type... typeHints) {
4848

4949
// When there is a conflict between the type hint from the regular expression and the method
5050
// prefer the parameter type associated with the regular expression. This ensures we will
51-
// use the internal/user registered parameter transformer rather then the default.
51+
// use the internal/user registered parameter transformer rather than the default.
5252
//
5353
// Unless the parameter type indicates it is the stronger type hint.
5454
if (parameterType != null && hasTypeHint && !parameterType.useRegexpMatchAsStrongTypeHint()) {

java/src/main/java/io/cucumber/cucumberexpressions/TreeRegexp.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Group match(CharSequence s) {
9191
return groupBuilder.build(matcher, IntStream.rangeClosed(0, matcher.groupCount()).iterator());
9292
}
9393

94-
public GroupBuilder getGroupBuilder() {
94+
GroupBuilder getGroupBuilder() {
9595
return groupBuilder;
9696
}
9797

java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.lang.reflect.Type;
1616
import java.math.BigDecimal;
1717
import java.math.BigInteger;
18+
import java.nio.file.DirectoryStream;
1819
import java.nio.file.Path;
1920
import java.nio.file.Paths;
2021
import java.util.ArrayList;
@@ -38,7 +39,10 @@ class CucumberExpressionTest {
3839

3940
private static List<Path> acceptance_tests_pass() throws IOException {
4041
List<Path> paths = new ArrayList<>();
41-
newDirectoryStream(Paths.get("..", "testdata", "cucumber-expression", "matching")).forEach(paths::add);
42+
Path path = Paths.get("..", "testdata", "cucumber-expression", "matching");
43+
try (DirectoryStream<Path> directories = newDirectoryStream(path)){
44+
directories.forEach(paths::add);
45+
}
4246
paths.sort(Comparator.naturalOrder());
4347
return paths;
4448
}

0 commit comments

Comments
 (0)