Skip to content

Commit f783b18

Browse files
committed
[Core] Delegate encoding and BOM handling to gherkin
Previously before handing over a feature file to the Gherkin parser, Cucumber would remove any Byte Order Markers (BOM) and determine the encoding of the feature file based on the `#encoding: <encoding>` comment. With cucumber/common#2018 this can now be handled by Gherkin. Removing it simplifies Cucumber a little. Unfortunately the `FeatureParser` doesn't take a `InputStream` as an argument. So we need to add a default interface to avoid breaking semver.
1 parent 41b5deb commit f783b18

File tree

8 files changed

+135
-211
lines changed

8 files changed

+135
-211
lines changed

cucumber-core/src/main/java/io/cucumber/core/feature/EncodingParser.java

-73
This file was deleted.

cucumber-core/src/main/java/io/cucumber/core/feature/FeatureParser.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package io.cucumber.core.feature;
22

33
import io.cucumber.core.gherkin.Feature;
4+
import io.cucumber.core.gherkin.FeatureParserException;
45
import io.cucumber.core.resource.Resource;
56

7+
import java.io.IOException;
8+
import java.io.InputStream;
69
import java.net.URI;
710
import java.util.ArrayList;
811
import java.util.Collections;
@@ -19,8 +22,6 @@
1922

2023
public final class FeatureParser {
2124

22-
private final EncodingParser encodingParser = new EncodingParser();
23-
2425
private final Supplier<UUID> idGenerator;
2526

2627
public FeatureParser(Supplier<UUID> idGenerator) {
@@ -31,8 +32,6 @@ public Optional<Feature> parseResource(Resource resource) {
3132
requireNonNull(resource);
3233
URI uri = resource.getUri();
3334

34-
String source = encodingParser.parse(resource);
35-
3635
ServiceLoader<io.cucumber.core.gherkin.FeatureParser> services = ServiceLoader
3736
.load(io.cucumber.core.gherkin.FeatureParser.class);
3837
Iterator<io.cucumber.core.gherkin.FeatureParser> iterator = services.iterator();
@@ -42,7 +41,13 @@ public Optional<Feature> parseResource(Resource resource) {
4241
}
4342
Comparator<io.cucumber.core.gherkin.FeatureParser> version = comparing(
4443
io.cucumber.core.gherkin.FeatureParser::version);
45-
return Collections.max(parser, version).parse(uri, source, idGenerator);
44+
45+
try (InputStream source = resource.getInputStream()) {
46+
return Collections.max(parser, version).parse(uri, source, idGenerator);
47+
48+
} catch (IOException e) {
49+
throw new FeatureParserException("Failed to parse resource at: " + uri, e);
50+
}
4651
}
4752

4853
}

cucumber-core/src/test/java/io/cucumber/core/feature/EncodingParserTest.java

-44
This file was deleted.

cucumber-core/src/test/resources/io/cucumber/core/feature/UTF_8_BOM_Encoded.feature

-8
This file was deleted.

cucumber-core/src/test/resources/io/cucumber/core/feature/UTF_8_Encoded.feature

-8
This file was deleted.

cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesFeatureParser.java

+23-3
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,36 @@
1212
import io.cucumber.messages.types.ParseError;
1313
import io.cucumber.messages.types.Source;
1414

15+
import java.io.ByteArrayInputStream;
16+
import java.io.IOException;
17+
import java.io.InputStream;
1518
import java.net.URI;
1619
import java.util.List;
1720
import java.util.Optional;
1821
import java.util.UUID;
1922
import java.util.function.Supplier;
2023

21-
import static io.cucumber.messages.types.SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN;
24+
import static java.nio.charset.StandardCharsets.UTF_8;
2225
import static java.util.stream.Collectors.toList;
2326

2427
public final class GherkinMessagesFeatureParser implements FeatureParser {
2528

29+
@Deprecated
2630
@Override
2731
public Optional<Feature> parse(URI path, String source, Supplier<UUID> idGenerator) {
32+
try (InputStream is = new ByteArrayInputStream(source.getBytes(UTF_8))) {
33+
return parse(path, is, idGenerator);
34+
} catch (IOException e) {
35+
throw new FeatureParserException("Failed to parse resource at: " + path, e);
36+
}
37+
}
38+
39+
@Override
40+
public Optional<Feature> parse(URI path, InputStream source, Supplier<UUID> idGenerator) throws IOException {
2841
List<Envelope> envelopes = GherkinParser.builder()
2942
.idGenerator(() -> idGenerator.get().toString())
3043
.build()
31-
.parse(Envelope.of(new Source(path.toString(), source, TEXT_X_CUCUMBER_GHERKIN_PLAIN)))
44+
.parse(path.toString(), source)
3245
.collect(toList());
3346

3447
List<String> errors = envelopes.stream()
@@ -70,10 +83,17 @@ public Optional<Feature> parse(URI path, String source, Supplier<UUID> idGenerat
7083
.map(pickle -> new GherkinMessagesPickle(pickle, path, dialect, cucumberQuery))
7184
.collect(toList());
7285

86+
Source sourceMessage = envelopes.stream()
87+
.map(Envelope::getSource)
88+
.filter(Optional::isPresent)
89+
.map(Optional::get)
90+
.findFirst()
91+
.orElseThrow(() -> new IllegalStateException("source message was not emitted by parser"));
92+
7393
return new GherkinMessagesFeature(
7494
feature,
7595
path,
76-
source,
96+
sourceMessage.getData(),
7797
pickles,
7898
envelopes);
7999
});

0 commit comments

Comments
 (0)