diff --git a/.mvn/jvm.config b/.mvn/jvm.config
index 7fecadb38e..e465a14f8e 100644
--- a/.mvn/jvm.config
+++ b/.mvn/jvm.config
@@ -1 +1,11 @@
-Dfile.encoding=UTF-8
+--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
diff --git a/cucumber-bom/pom.xml b/cucumber-bom/pom.xml
index c6ac71b25e..90b241742c 100644
--- a/cucumber-bom/pom.xml
+++ b/cucumber-bom/pom.xml
@@ -13,19 +13,19 @@
Cucumber-JVM: Bill of Materials
- 12.0.0
- 18.0.1
- 0.3.0
- 36.1.0
- 22.0.0
- 0.10.0
- 30.1.0
- 2.4.1
- 14.6.0
- 8.0.0
- 0.2.0
- 0.7.0
- 0.1.0
+ 13.0.0-SNAPSHOT
+ 19.0.0-SNAPSHOT
+ 0.4.0-SNAPSHOT
+ 38.0.0-SNAPSHOT
+ 23.0.0-SNAPSHOT
+ 0.12.0-SNAPSHOT
+ 32.0.0-SNAPSHOT
+ 3.0.0-SNAPSHOT
+ 15.0.0-SNAPSHOT
+ 9.0.0-SNAPSHOT
+ 0.3.0-SNAPSHOT
+ 0.8.0-SNAPSHOT
+ 0.2.0-SNAPSHOT
diff --git a/cucumber-cdi2/src/main/java/io/cucumber/cdi2/package-info.java b/cucumber-cdi2/src/main/java/io/cucumber/cdi2/package-info.java
new file mode 100644
index 0000000000..69a0f5bbde
--- /dev/null
+++ b/cucumber-cdi2/src/main/java/io/cucumber/cdi2/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.cdi2;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/cucumber/api/cli/Main.java b/cucumber-core/src/main/java/cucumber/api/cli/Main.java
index ef0267ca6a..acedbdd5a4 100644
--- a/cucumber-core/src/main/java/cucumber/api/cli/Main.java
+++ b/cucumber-core/src/main/java/cucumber/api/cli/Main.java
@@ -7,9 +7,13 @@
* @deprecated use {@link io.cucumber.core.cli.Main} instead.
*/
@Deprecated
-public class Main {
+public final class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
+
+ private Main(){
+ /* no-op */
+ }
public static void main(String[] argv) {
byte exitStatus = run(argv, Thread.currentThread().getContextClassLoader());
diff --git a/cucumber-core/src/main/java/cucumber/api/cli/package-info.java b/cucumber-core/src/main/java/cucumber/api/cli/package-info.java
new file mode 100644
index 0000000000..fe5f58ed50
--- /dev/null
+++ b/cucumber-core/src/main/java/cucumber/api/cli/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package cucumber.api.cli;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/api/TypeRegistry.java b/cucumber-core/src/main/java/io/cucumber/core/api/TypeRegistry.java
deleted file mode 100644
index b1122bb787..0000000000
--- a/cucumber-core/src/main/java/io/cucumber/core/api/TypeRegistry.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.cucumber.core.api;
-
-import io.cucumber.cucumberexpressions.ParameterByTypeTransformer;
-import io.cucumber.cucumberexpressions.ParameterType;
-import io.cucumber.datatable.DataTableType;
-import io.cucumber.datatable.TableCellByTypeTransformer;
-import io.cucumber.datatable.TableEntryByTypeTransformer;
-import io.cucumber.docstring.DocStringType;
-import org.apiguardian.api.API;
-import org.apiguardian.api.API.Status;
-
-/**
- * The type registry records defines parameter types, data table types and
- * docstring transformers.
- *
- * @deprecated use the dedicated type annotations to register data table and
- * parameter types instead
- */
-@API(status = Status.STABLE)
-@Deprecated
-public interface TypeRegistry {
-
- /**
- * Defines a new parameter type.
- *
- * @param parameterType The new parameter type.
- */
- void defineParameterType(ParameterType> parameterType);
-
- /**
- * Defines a new docstring type.
- *
- * @param docStringType The new docstring type.
- */
- void defineDocStringType(DocStringType docStringType);
-
- /**
- * Defines a new data table type.
- *
- * @param tableType The new table type.
- */
- void defineDataTableType(DataTableType tableType);
-
- /**
- * Set default transformer for parameters which are not defined by
- * {@code defineParameterType(ParameterType>))}
- *
- * @param defaultParameterByTypeTransformer default transformer
- */
- void setDefaultParameterTransformer(ParameterByTypeTransformer defaultParameterByTypeTransformer);
-
- /**
- * Set default transformer for entries which are not defined by
- * {@code defineDataTableType(new DataTableType(Class,TableEntryTransformer))}
- *
- * @param tableEntryByTypeTransformer default transformer
- */
- void setDefaultDataTableEntryTransformer(TableEntryByTypeTransformer tableEntryByTypeTransformer);
-
- /**
- * Set default transformer for cells which are not defined by
- * {@code defineDataTableType(new DataTableType(Class,TableEntryTransformer))}
- *
- * @param tableCellByTypeTransformer default transformer
- */
- void setDefaultDataTableCellTransformer(TableCellByTypeTransformer tableCellByTypeTransformer);
-
-}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/Backend.java b/cucumber-core/src/main/java/io/cucumber/core/backend/Backend.java
index 676fd43cbc..d178594f94 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/Backend.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/Backend.java
@@ -1,6 +1,7 @@
package io.cucumber.core.backend;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import java.net.URI;
import java.util.List;
@@ -15,7 +16,9 @@ public interface Backend {
* @param glue Glue that provides the steps to be executed.
* @param gluePaths The locations for the glue to be loaded.
*/
- void loadGlue(Glue glue, List gluePaths);
+ default void loadGlue(Glue glue, List gluePaths){
+
+ }
/**
* Invoked before a new scenario starts. Implementations should do any
@@ -23,13 +26,20 @@ public interface Backend {
* step definitions can be loaded here. These step definitions should
* implement {@link ScenarioScoped}
*/
- void buildWorld();
+ default void buildWorld() {
+
+ }
/**
* Invoked at the end of a scenario, after hooks
*/
- void disposeWorld();
-
- Snippet getSnippet();
+ default void disposeWorld(){
+
+ }
+
+ @Nullable
+ default Snippet getSnippet(){
+ return null;
+ }
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/HookDefinition.java b/cucumber-core/src/main/java/io/cucumber/core/backend/HookDefinition.java
index f1aed8f08d..999777d717 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/HookDefinition.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/HookDefinition.java
@@ -25,6 +25,6 @@ enum HookType {
BEFORE_STEP,
- AFTER_STEP;
+ AFTER_STEP
}
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/Located.java b/cucumber-core/src/main/java/io/cucumber/core/backend/Located.java
index 57005ad9c4..80dbc6f076 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/Located.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/Located.java
@@ -8,9 +8,10 @@
public interface Located {
/**
+ * Return true if this matches the location. This is used to filter stack traces.
+ *
* @param stackTraceElement The location of the step.
- * @return Return true if this matches the location. This
- * is used to filter stack traces.
+ * @return Return true if this matches the location.
*/
boolean isDefinedAt(StackTraceElement stackTraceElement);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/Snippet.java b/cucumber-core/src/main/java/io/cucumber/core/backend/Snippet.java
index 88392e4245..6b8a260d7c 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/Snippet.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/Snippet.java
@@ -12,30 +12,35 @@ public interface Snippet {
/**
* The language of the generated snippet.
- *
- * @see io.cucumber.messages.types.Snippet#getLanguage()
+ *
* @return the language of the generated snippet.
+ * @see io.cucumber.messages.types.Snippet#getLanguage()
*/
default Optional language() {
return Optional.empty();
}
/**
- * @return a {@link java.text.MessageFormat} template used to generate a
- * snippet. The template can access the following variables:
- *
- *
{0} : Step Keyword
- *
{1} : Value of {@link #escapePattern(String)}
- *
{2} : Function name
- *
{3} : Value of {@link #arguments(Map)}
- *
{4} : Regexp hint comment
- *
{5} : value of {@link #tableHint()} if the step has a
- * table
- *
+ * Returns a {@link java.text.MessageFormat} template used to generate a snippet.
+ *
+ *
The template can access the following variables:
+ *
+ *
{0} : Step Keyword
+ *
{1} : Value of {@link #escapePattern(String)}
+ *
{2} : Function name
+ *
{3} : Value of {@link #arguments(Map)}
+ *
{4} : Regexp hint comment
+ *
{5} : value of {@link #tableHint()} if the step has a
+ * table
+ *
+ *
+ * @return a template used to generate a snippet.
*/
MessageFormat template();
/**
+ * Returns a hint about alternative ways to declare a table argument
+ *
* @return a hint about alternative ways to declare a table argument
*/
String tableHint();
@@ -45,15 +50,17 @@ default Optional language() {
* should accept. The arguments are provided a map of (suggested) names and
* types. The arguments are ordered by their position.
*
- * @param arguments ordered pairs of names and types
- * @return a string representation of the arguments
+ * @param arguments ordered pairs of names and types
+ * @return a string representation of the arguments
*/
String arguments(Map arguments);
/**
- * @param pattern the computed pattern that will match an undefined step
- * @return an escaped representation of the pattern, if escaping is
- * necessary.
+ * Escape representation of the pattern, if escaping is necessary.
+ *
+ * @param pattern the computed pattern that will match an undefined step
+ * @return an escaped representation of the pattern, if escaping is
+ * necessary.
*/
String escapePattern(String pattern);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/StackTraceElementReference.java b/cucumber-core/src/main/java/io/cucumber/core/backend/StackTraceElementReference.java
index 06219e8778..267c04bb34 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/StackTraceElementReference.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/StackTraceElementReference.java
@@ -5,7 +5,7 @@
import static java.util.Objects.requireNonNull;
-public class StackTraceElementReference implements SourceReference {
+public final class StackTraceElementReference implements SourceReference {
private final String className;
private final String methodName;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/StepDefinition.java b/cucumber-core/src/main/java/io/cucumber/core/backend/StepDefinition.java
index e59cbe381b..1787287987 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/StepDefinition.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/StepDefinition.java
@@ -11,7 +11,7 @@ public interface StepDefinition extends Located {
* Invokes the step definition. The method should raise a Throwable if the
* invocation fails, which will cause the step to fail.
*
- * @param args The arguments for the step
+ * @param args The arguments for the step
* @throws CucumberBackendException of a failure to invoke the step
* @throws CucumberInvocationTargetException in case of a failure in the
* step.
@@ -19,13 +19,16 @@ public interface StepDefinition extends Located {
void execute(Object[] args) throws CucumberBackendException, CucumberInvocationTargetException;
/**
+ * Return parameter information.
+ *
* @return parameter information, may not return null
*/
List parameterInfos();
/**
- * @return the pattern associated with this instance. Used for error
- * reporting only.
+ * Return the pattern associated with this instance. Used for error reporting only.
+ *
+ * @return the pattern associated with this instance.
*/
String getPattern();
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/backend/package-info.java
new file mode 100644
index 0000000000..17cc474d10
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.backend;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/cli/Main.java b/cucumber-core/src/main/java/io/cucumber/core/cli/Main.java
index 7f4c398932..69f97821c0 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/cli/Main.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/cli/Main.java
@@ -24,8 +24,12 @@
* {@link CommandlineOptions}.
*/
@API(status = API.Status.STABLE)
-public class Main {
+public final class Main {
+ private Main(){
+ /* no-op */
+ }
+
public static void main(String... argv) {
byte exitStatus = run(argv, Thread.currentThread().getContextClassLoader());
System.exit(exitStatus);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/cli/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/cli/package-info.java
new file mode 100644
index 0000000000..dc79e3d780
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/cli/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.cli;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventBus.java b/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventBus.java
index ba6cee4558..20c7fa54fa 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventBus.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventBus.java
@@ -2,11 +2,21 @@
public abstract class AbstractEventBus extends AbstractEventPublisher implements EventBus {
+ /**
+ * Send all events.
+ *
+ *
May be overridden, but must be called.
+ */
@Override
public void sendAll(Iterable queue) {
super.sendAll(queue);
}
+ /**
+ * Send a single event.
+ *
+ *
May be overridden, but must be called.
+ */
@Override
public void send(T event) {
super.send(event);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventPublisher.java b/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventPublisher.java
index 0d67fb5f6a..df420df14b 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventPublisher.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/eventbus/AbstractEventPublisher.java
@@ -31,12 +31,22 @@ public final void removeHandlerFor(Class eventType, EventHandler handl
}
}
+ /**
+ * Send all events.
+ *
+ *
May be overridden, but must be called.
+ */
protected void sendAll(Iterable events) {
for (T event : events) {
send(event);
}
}
+ /**
+ * Send a single event.
+ *
+ *
May be overridden, but must be called.
+ */
protected void send(T event) {
if (handlers.containsKey(Event.class) && event instanceof Event) {
for (EventHandler handler : handlers.get(Event.class)) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/eventbus/IncrementingUuidGenerator.java b/cucumber-core/src/main/java/io/cucumber/core/eventbus/IncrementingUuidGenerator.java
index e11d6d07cc..4479455472 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/eventbus/IncrementingUuidGenerator.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/eventbus/IncrementingUuidGenerator.java
@@ -130,7 +130,8 @@ public UUID generateId() {
" capacity. Please generate using a new instance or use another " +
UuidGenerator.class.getSimpleName() + "implementation.");
}
- long leastSigBits = counterValue | 0x8000000000000000L; // set variant
+ // set variant
+ long leastSigBits = counterValue | 0x8000000000000000L;
return new UUID(msb, leastSigBits);
}
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/eventbus/RandomUuidGenerator.java b/cucumber-core/src/main/java/io/cucumber/core/eventbus/RandomUuidGenerator.java
index 76f34deb39..5df8aa6c8c 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/eventbus/RandomUuidGenerator.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/eventbus/RandomUuidGenerator.java
@@ -6,7 +6,12 @@
* UUID generator based on random numbers. The generator is thread-safe and
* supports multi-jvm usage of Cucumber.
*/
-public class RandomUuidGenerator implements UuidGenerator {
+public final class RandomUuidGenerator implements UuidGenerator {
+
+ public RandomUuidGenerator(){
+ /* no-op */
+ }
+
@Override
public UUID generateId() {
return UUID.randomUUID();
diff --git a/cucumber-core/src/main/java/io/cucumber/core/eventbus/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/eventbus/package-info.java
new file mode 100644
index 0000000000..5bc0cb5209
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/eventbus/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.eventbus;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/exception/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/exception/package-info.java
new file mode 100644
index 0000000000..999d929df0
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/exception/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.exception;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureIdentifier.java b/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureIdentifier.java
index 84d7391f33..33b4f3c298 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureIdentifier.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureIdentifier.java
@@ -11,12 +11,12 @@
*
* @see FeatureWithLines
*/
-public class FeatureIdentifier {
+public final class FeatureIdentifier {
private static final String FEATURE_FILE_SUFFIX = ".feature";
private FeatureIdentifier() {
-
+ /* no-op */
}
public static URI parse(String featureIdentifier) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/feature/FeaturePath.java b/cucumber-core/src/main/java/io/cucumber/core/feature/FeaturePath.java
index 23302be33b..1c0a546754 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/feature/FeaturePath.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/feature/FeaturePath.java
@@ -27,7 +27,7 @@
* @see FeatureIdentifier
* @see FeatureWithLines
*/
-public class FeaturePath {
+public final class FeaturePath {
private FeaturePath() {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureWithLines.java b/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureWithLines.java
index 4d69ba217e..16a1ff02c8 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureWithLines.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/feature/FeatureWithLines.java
@@ -28,7 +28,7 @@
* a {@link FeatureIdentifier} followed by a sequence of line numbers each
* preceded by a colon.
*/
-public class FeatureWithLines implements Serializable {
+public final class FeatureWithLines implements Serializable {
private static final long serialVersionUID = 20190126L;
private static final Pattern FEATURE_WITH_LINES_FILE_FORMAT = Pattern.compile("(?m:^| |)(.*?\\.feature(?::\\d+)*)");
diff --git a/cucumber-core/src/main/java/io/cucumber/core/feature/GluePath.java b/cucumber-core/src/main/java/io/cucumber/core/feature/GluePath.java
index 601fd9c41d..8139601cbf 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/feature/GluePath.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/feature/GluePath.java
@@ -32,7 +32,7 @@
*
* It is recommended to always use the package name form.
*/
-public class GluePath {
+public final class GluePath {
private static final Logger log = LoggerFactory.getLogger(GluePath.class);
@@ -133,6 +133,7 @@ private static boolean isProbablyPackage(String gluePath) {
&& !gluePath.contains(RESOURCE_SEPARATOR_STRING);
}
+ @SuppressWarnings("UnnecessaryParentheses")
private static boolean isValidIdentifier(String schemeSpecificPart) {
for (String part : schemeSpecificPart.split("/")) {
for (int i = 0; i < part.length(); i++) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/feature/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/feature/package-info.java
new file mode 100644
index 0000000000..dcec86ab24
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/feature/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.feature;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/filter/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/filter/package-info.java
new file mode 100644
index 0000000000..d9b6789037
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/filter/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.filter;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/logging/LoggerFactory.java b/cucumber-core/src/main/java/io/cucumber/core/logging/LoggerFactory.java
index 7dade586cb..674d91772e 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/logging/LoggerFactory.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/logging/LoggerFactory.java
@@ -133,7 +133,8 @@ private LogRecord createLogRecord(Level level, Throwable throwable, Supplier properties) {
return parse(properties::get);
}
@@ -110,7 +114,8 @@ public RuntimeOptionsBuilder parse(CucumberPropertiesProvider properties) {
parse(properties,
PLUGIN_PUBLISH_TOKEN_PROPERTY_NAME,
- identity(), // No validation - validated on server
+ // No validation - validated on server
+ identity(),
builder::setPublishToken);
parse(properties,
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/PickleOrderParser.java b/cucumber-core/src/main/java/io/cucumber/core/options/PickleOrderParser.java
index 3c8c8a42b3..f6701a8fc9 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/PickleOrderParser.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/PickleOrderParser.java
@@ -14,6 +14,10 @@ final class PickleOrderParser {
private static final Logger log = LoggerFactory.getLogger(PickleOrderParser.class);
private static final Pattern RANDOM_AND_SEED_PATTERN = Pattern.compile("random(?::(\\d+))?");
+
+ private PickleOrderParser(){
+ /* no-op */
+ }
static PickleOrder parse(String argument) {
if ("reverse".equals(argument)) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/PluginOption.java b/cucumber-core/src/main/java/io/cucumber/core/options/PluginOption.java
index f95dbe0f10..a62d0c487a 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/PluginOption.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/PluginOption.java
@@ -20,7 +20,6 @@
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.EventListener;
import io.cucumber.plugin.Plugin;
-import io.cucumber.plugin.SummaryPrinter;
import java.util.HashMap;
import java.util.HashSet;
@@ -35,7 +34,7 @@
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;
-public class PluginOption implements Options.Plugin {
+public final class PluginOption implements Options.Plugin {
private static final Logger log = LoggerFactory.getLogger(PluginOption.class);
@@ -204,10 +203,6 @@ boolean isEventListener() {
|| ConcurrentEventListener.class.isAssignableFrom(pluginClass);
}
- boolean isSummaryPrinter() {
- return SummaryPrinter.class.isAssignableFrom(pluginClass);
- }
-
@Override
public boolean equals(Object o) {
if (this == o)
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/RerunPath.java b/cucumber-core/src/main/java/io/cucumber/core/options/RerunPath.java
index bf88121f56..e5cd7f25a6 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/RerunPath.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/RerunPath.java
@@ -17,7 +17,11 @@
* Either a path to a rerun file or a directory containing exclusively rerun
* files.
*/
-class RerunPath {
+final class RerunPath {
+
+ private RerunPath() {
+ /* no-op */
+ }
static Collection parse(Path rerunFileOrDirectory) {
return listRerunFiles(rerunFileOrDirectory).stream()
@@ -29,6 +33,7 @@ static Collection parse(Path rerunFileOrDirectory) {
private static Set listRerunFiles(Path path) {
class FileCollector extends SimpleFileVisitor {
final Set paths = new HashSet<>();
+
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (!Files.isDirectory(file)) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptionsBuilder.java b/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptionsBuilder.java
index 58b6792bc5..1207c8d7eb 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptionsBuilder.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/RuntimeOptionsBuilder.java
@@ -66,7 +66,7 @@ public RuntimeOptionsBuilder addNameFilter(Pattern pattern) {
public RuntimeOptionsBuilder addPluginName(String pluginSpecification) {
PluginOption pluginOption = PluginOption.parse(pluginSpecification);
- if (pluginOption.isEventListener() || pluginOption.isSummaryPrinter()) {
+ if (pluginOption.isEventListener()) {
plugins.add(pluginOption);
} else {
throw new CucumberException("Unrecognized plugin: " + pluginSpecification);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/ShellWords.java b/cucumber-core/src/main/java/io/cucumber/core/options/ShellWords.java
index aed166ee6b..253d585c26 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/options/ShellWords.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/ShellWords.java
@@ -5,11 +5,12 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-class ShellWords {
+final class ShellWords {
private static final Pattern SHELLWORDS_PATTERN = Pattern.compile("[^\\s'\"]+|[']([^']*)[']|[\"]([^\"]*)[\"]");
private ShellWords() {
+ /* no-op */
}
static List parse(String cmdline) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/options/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/options/package-info.java
new file mode 100644
index 0000000000..3b757b67f1
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/options/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.options;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/order/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/order/package-info.java
new file mode 100644
index 0000000000..9e73eed23d
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/order/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.order;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/Banner.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/Banner.java
index ed8a1fe45f..70a7307a94 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/Banner.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/Banner.java
@@ -11,45 +11,13 @@
final class Banner {
private final boolean monochrome;
-
- static final class Line {
- private final List spans;
-
- Line(Span... spans) {
- this.spans = asList(spans);
- }
-
- Line(String text, AnsiEscapes... escapes) {
- this(new Span(text, escapes));
- }
-
- int length() {
- return spans.stream().map(span -> span.text.length()).mapToInt(Integer::intValue).sum();
- }
- }
-
- static final class Span {
- private final String text;
- private final AnsiEscapes[] escapes;
-
- Span(String text) {
- this.text = text;
- this.escapes = new AnsiEscapes[0];
- }
-
- Span(String text, AnsiEscapes... escapes) {
- this.text = text;
- this.escapes = escapes;
- }
- }
-
private final PrintStream out;
Banner(PrintStream out, boolean monochrome) {
this.out = out;
this.monochrome = monochrome;
}
-
+
void print(List lines, AnsiEscapes... border) {
int maxLength = lines.stream().map(Line::length).max(comparingInt(a -> a))
.orElseThrow(NoSuchElementException::new);
@@ -82,4 +50,36 @@ void print(List lines, AnsiEscapes... border) {
private String times(char c, int count) {
return new String(new char[count]).replace('\0', c);
}
+
+ static final class Line {
+ private final List spans;
+
+ Line(Span... spans) {
+ this.spans = asList(spans);
+ }
+
+ Line(String text, AnsiEscapes... escapes) {
+ this(new Span(text, escapes));
+ }
+
+ int length() {
+ return spans.stream().map(span -> span.text.length()).mapToInt(Integer::intValue).sum();
+ }
+ }
+
+ static final class Span {
+ private final String text;
+ private final AnsiEscapes[] escapes;
+
+ Span(String text) {
+ this.text = text;
+ this.escapes = new AnsiEscapes[0];
+ }
+
+ Span(String text, AnsiEscapes... escapes) {
+ this.text = text;
+ this.escapes = escapes;
+ }
+ }
+
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/Format.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/Format.java
index db8dece806..b932cbfee3 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/Format.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/Format.java
@@ -34,7 +34,7 @@ public String text(String text) {
}
- class Monochrome implements Format {
+ final class Monochrome implements Format {
private Monochrome() {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/HtmlFormatter.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/HtmlFormatter.java
index 64ca508010..4f8f277688 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/HtmlFormatter.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/HtmlFormatter.java
@@ -12,9 +12,12 @@ public final class HtmlFormatter implements ConcurrentEventListener {
private final MessagesToHtmlWriter writer;
- @SuppressWarnings("WeakerAccess") // Used by PluginFactory
- public HtmlFormatter(OutputStream out) throws IOException {
- this.writer = new MessagesToHtmlWriter(out, Jackson.OBJECT_MAPPER::writeValue);
+ // Used by PluginFactory
+ @SuppressWarnings("WeakerAccess")
+ public HtmlFormatter(OutputStream out) {
+ this.writer = MessagesToHtmlWriter //
+ .builder(Jackson.OBJECT_MAPPER::writeValue) //
+ .build(out);
}
@Override
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/PluginFactory.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/PluginFactory.java
index 4a978c6669..5f46036dbd 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/PluginFactory.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/PluginFactory.java
@@ -69,7 +69,8 @@ Plugin create(Options.Plugin plugin) {
private T instantiate(String pluginString, Class pluginClass, String argument)
throws IOException, URISyntaxException {
Map, Constructor> singleArgConstructors = findSingleArgConstructors(pluginClass);
- if (argument == null) {// No argument passed
+ // No argument passed
+ if (argument == null) {
Constructor outputStreamConstructor = singleArgConstructors.get(OutputStream.class);
if (outputStreamConstructor != null) {
return newInstance(outputStreamConstructor, defaultOutOrFailIfAlreadyUsed(pluginString));
@@ -105,7 +106,8 @@ private Map, Constructor> findSingleArgConstructors(Class plu
for (Class> ctorArgClass : CTOR_PARAMETERS) {
try {
result.put(ctorArgClass, pluginClass.getConstructor(ctorArgClass));
- } catch (NoSuchMethodException ignore) {
+ } catch (NoSuchMethodException ignored) {
+ /* no-op */
}
}
return result;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/Plugins.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/Plugins.java
index 7c13621240..97a879aa3c 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/Plugins.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/Plugins.java
@@ -4,7 +4,6 @@
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.EventListener;
import io.cucumber.plugin.Plugin;
-import io.cucumber.plugin.StrictAware;
import io.cucumber.plugin.event.Event;
import io.cucumber.plugin.event.EventPublisher;
@@ -40,7 +39,6 @@ private List createPlugins() {
private void addPlugin(List plugins, Plugin plugin) {
plugins.add(plugin);
setMonochromeOnColorAwarePlugins(plugin);
- setStrictOnStrictAwarePlugins(plugin);
}
private void setMonochromeOnColorAwarePlugins(Plugin plugin) {
@@ -50,13 +48,6 @@ private void setMonochromeOnColorAwarePlugins(Plugin plugin) {
}
}
- private void setStrictOnStrictAwarePlugins(Plugin plugin) {
- if (plugin instanceof StrictAware) {
- StrictAware strictAware = (StrictAware) plugin;
- strictAware.setStrict(true);
- }
- }
-
public List getPlugins() {
return plugins;
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/RerunFormatter.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/RerunFormatter.java
index f9dc9ee416..793176abe8 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/RerunFormatter.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/RerunFormatter.java
@@ -23,7 +23,6 @@
import java.util.TreeSet;
import java.util.stream.Collector;
-import static io.cucumber.query.Repository.RepositoryFeature.INCLUDE_GHERKIN_DOCUMENTS;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
@@ -36,7 +35,6 @@ public final class RerunFormatter implements ConcurrentEventListener {
private final PrintWriter writer;
private final Repository repository = Repository.builder()
- .feature(INCLUDE_GHERKIN_DOCUMENTS, true)
.build();
private final Query query = new Query(repository);
@@ -46,9 +44,9 @@ public RerunFormatter(OutputStream out) {
private static PrintWriter createPrintWriter(OutputStream out) {
return new PrintWriter(
- new OutputStreamWriter(
- requireNonNull(out),
- StandardCharsets.UTF_8));
+ new OutputStreamWriter(
+ requireNonNull(out),
+ StandardCharsets.UTF_8));
}
static URI relativize(URI uri) {
@@ -77,23 +75,6 @@ public void setEventPublisher(EventPublisher publisher) {
});
}
- private static final class UriAndLine {
- private final String uri;
- private final Long line;
-
- private UriAndLine(String uri, Long line) {
- this.uri = uri;
- this.line = line;
- }
-
- public String getUri() {
- return uri;
- }
-
- public Long getLine() {
- return line;
- }
- }
private void finishReport() {
query.findAllTestCaseStarted().stream()
@@ -107,25 +88,25 @@ private void finishReport() {
writer.close();
}
- private void printUriWithLines(String uri, TreeSet lines) {
+ private void printUriWithLines(String uri, TreeSet lines) {
writer.println(renderFeatureWithLines(uri, lines));
}
- private static Collector>> groupByUriAndThenCollectLines() {
+ private static Collector>> groupByUriAndThenCollectLines() {
return groupingBy(
- UriAndLine::getUri,
- // Sort URIs
- TreeMap::new,
- mapping(
- UriAndLine::getLine,
- // Sort lines
- toCollection(TreeSet::new)));
+ UriAndLine::getUri,
+ // Sort URIs
+ TreeMap::new,
+ mapping(
+ UriAndLine::getLine,
+ // Sort lines
+ toCollection(TreeSet::new)));
}
- private static StringBuilder renderFeatureWithLines(String uri, TreeSet lines) {
+ private static StringBuilder renderFeatureWithLines(String uri, TreeSet lines) {
String path = relativize(URI.create(uri)).toString();
StringBuilder builder = new StringBuilder(path);
- for (Long line : lines) {
+ for (Integer line : lines) {
builder.append(':');
builder.append(line);
}
@@ -134,7 +115,7 @@ private static StringBuilder renderFeatureWithLines(String uri, TreeSet li
private UriAndLine createUriAndLine(Pickle pickle) {
String uri = pickle.getUri();
- Long line = query.findLocationOf(pickle).map(Location::getLine).orElse(null);
+ Integer line = pickle.getLocation().map(Location::getLine).orElse(null);
return new UriAndLine(uri, line);
}
@@ -146,4 +127,22 @@ private boolean isNotPassingOrSkipped(TestCaseStarted event) {
.isPresent();
}
+ private static final class UriAndLine {
+ private final String uri;
+ private final Integer line;
+
+ private UriAndLine(String uri, Integer line) {
+ this.uri = uri;
+ this.line = line;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public Integer getLine() {
+ return line;
+ }
+ }
+
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java
index 9a4102a8cb..d587eb57ca 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java
@@ -18,12 +18,13 @@
* href=https://www.jetbrains.com/help/teamcity/service-messages.html>TeamCity
* - Service Messages
*/
-public class TeamCityPlugin implements ConcurrentEventListener {
+public final class TeamCityPlugin implements ConcurrentEventListener {
private final OutputStream out;
private MessagesToTeamCityWriter writer;
- @SuppressWarnings("unused") // Used by PluginFactory
+ // Used by PluginFactory
+ @SuppressWarnings("unused")
public TeamCityPlugin() {
// This plugin prints markers for Team City and IntelliJ IDEA that
// allows them to associate the output to specific test cases. Printing
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/TestSourcesModel.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/TestSourcesModel.java
deleted file mode 100644
index 19d13b8008..0000000000
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/TestSourcesModel.java
+++ /dev/null
@@ -1,262 +0,0 @@
-package io.cucumber.core.plugin;
-
-import io.cucumber.gherkin.GherkinParser;
-import io.cucumber.messages.types.Background;
-import io.cucumber.messages.types.Envelope;
-import io.cucumber.messages.types.Examples;
-import io.cucumber.messages.types.Feature;
-import io.cucumber.messages.types.FeatureChild;
-import io.cucumber.messages.types.GherkinDocument;
-import io.cucumber.messages.types.Rule;
-import io.cucumber.messages.types.RuleChild;
-import io.cucumber.messages.types.Scenario;
-import io.cucumber.messages.types.Source;
-import io.cucumber.messages.types.SourceMediaType;
-import io.cucumber.messages.types.Step;
-import io.cucumber.messages.types.TableRow;
-import io.cucumber.plugin.event.TestSourceRead;
-
-import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-/**
- * Internal class, still used by Serenity.
- *
- * @see cucumber/cucumber-jvm#3076
- * @deprecated for removal, use messages + query.
- */
-@SuppressWarnings("unused")
-@Deprecated
-final class TestSourcesModel {
-
- private final Map pathToReadEventMap = new HashMap<>();
- private final Map pathToAstMap = new HashMap<>();
- private final Map> pathToNodeMap = new HashMap<>();
-
- static Scenario getScenarioDefinition(AstNode astNode) {
- AstNode candidate = astNode;
- while (candidate != null && !(candidate.node instanceof Scenario)) {
- candidate = candidate.parent;
- }
- return candidate == null ? null : (Scenario) candidate.node;
- }
-
- static boolean isBackgroundStep(AstNode astNode) {
- return astNode.parent.node instanceof Background;
- }
-
- static String calculateId(AstNode astNode) {
- Object node = astNode.node;
- if (node instanceof Rule) {
- return calculateId(astNode.parent) + ";" + convertToId(((Rule) node).getName());
- }
- if (node instanceof Scenario) {
- return calculateId(astNode.parent) + ";" + convertToId(((Scenario) node).getName());
- }
- if (node instanceof ExamplesRowWrapperNode) {
- return calculateId(astNode.parent) + ";" + (((ExamplesRowWrapperNode) node).bodyRowIndex + 2);
- }
- if (node instanceof TableRow) {
- return calculateId(astNode.parent) + ";" + 1;
- }
- if (node instanceof Examples) {
- return calculateId(astNode.parent) + ";" + convertToId(((Examples) node).getName());
- }
- if (node instanceof Feature) {
- return convertToId(((Feature) node).getName());
- }
- return "";
- }
-
- private static final Pattern replacementPattern = Pattern.compile("[\\s'_,!]");
-
- static String convertToId(String name) {
- return replacementPattern.matcher(name).replaceAll("-").toLowerCase();
- }
-
- static URI relativize(URI uri) {
- if (!"file".equals(uri.getScheme())) {
- return uri;
- }
- if (!uri.isAbsolute()) {
- return uri;
- }
-
- try {
- URI root = new File("").toURI();
- URI relative = root.relativize(uri);
- // Scheme is lost by relativize
- return new URI("file", relative.getSchemeSpecificPart(), relative.getFragment());
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e.getMessage(), e);
- }
- }
-
- void addTestSourceReadEvent(URI path, TestSourceRead event) {
- pathToReadEventMap.put(path, event);
- }
-
- Feature getFeature(URI path) {
- if (!pathToAstMap.containsKey(path)) {
- parseGherkinSource(path);
- }
- if (pathToAstMap.containsKey(path)) {
- return pathToAstMap.get(path).getFeature().orElse(null);
- }
- return null;
- }
-
- private void parseGherkinSource(URI path) {
- if (!pathToReadEventMap.containsKey(path)) {
- return;
- }
- String source = pathToReadEventMap.get(path).getSource();
-
- GherkinParser parser = GherkinParser.builder()
- .build();
-
- Stream envelopes = parser.parse(
- Envelope.of(new Source(path.toString(), source, SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN)));
-
- // TODO: What about empty gherkin docs?
- GherkinDocument gherkinDocument = envelopes
- .map(Envelope::getGherkinDocument)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .findFirst()
- .orElse(null);
-
- pathToAstMap.put(path, gherkinDocument);
- Map nodeMap = new HashMap<>();
- // TODO: What about gherkin docs with no features?
- Feature feature = gherkinDocument.getFeature().get();
- AstNode currentParent = new AstNode(feature, null);
- for (FeatureChild child : feature.getChildren()) {
- processFeatureDefinition(nodeMap, child, currentParent);
- }
- pathToNodeMap.put(path, nodeMap);
-
- }
-
- private void processFeatureDefinition(Map nodeMap, FeatureChild child, AstNode currentParent) {
- child.getBackground().ifPresent(background -> processBackgroundDefinition(nodeMap, background, currentParent));
- child.getScenario().ifPresent(scenario -> processScenarioDefinition(nodeMap, scenario, currentParent));
- child.getRule().ifPresent(rule -> {
- AstNode childNode = new AstNode(rule, currentParent);
- nodeMap.put(rule.getLocation().getLine(), childNode);
- rule.getChildren().forEach(ruleChild -> processRuleDefinition(nodeMap, ruleChild, childNode));
- });
- }
-
- private void processBackgroundDefinition(
- Map nodeMap, Background background, AstNode currentParent
- ) {
- AstNode childNode = new AstNode(background, currentParent);
- nodeMap.put(background.getLocation().getLine(), childNode);
- for (Step step : background.getSteps()) {
- nodeMap.put(step.getLocation().getLine(), new AstNode(step, childNode));
- }
- }
-
- private void processScenarioDefinition(Map nodeMap, Scenario child, AstNode currentParent) {
- AstNode childNode = new AstNode(child, currentParent);
- nodeMap.put(child.getLocation().getLine(), childNode);
- for (io.cucumber.messages.types.Step step : child.getSteps()) {
- nodeMap.put(step.getLocation().getLine(), new AstNode(step, childNode));
- }
- if (!child.getExamples().isEmpty()) {
- processScenarioOutlineExamples(nodeMap, child, childNode);
- }
- }
-
- private void processRuleDefinition(Map nodeMap, RuleChild child, AstNode currentParent) {
- child.getBackground().ifPresent(background -> processBackgroundDefinition(nodeMap, background, currentParent));
- child.getScenario().ifPresent(scenario -> processScenarioDefinition(nodeMap, scenario, currentParent));
- }
-
- private void processScenarioOutlineExamples(
- Map nodeMap, Scenario scenarioOutline, AstNode parent
- ) {
- for (Examples examples : scenarioOutline.getExamples()) {
- AstNode examplesNode = new AstNode(examples, parent);
- // TODO: Can tables without headers even exist?
- TableRow headerRow = examples.getTableHeader().get();
- AstNode headerNode = new AstNode(headerRow, examplesNode);
- nodeMap.put(headerRow.getLocation().getLine(), headerNode);
- for (int i = 0; i < examples.getTableBody().size(); ++i) {
- TableRow examplesRow = examples.getTableBody().get(i);
- Object rowNode = new ExamplesRowWrapperNode(examplesRow, i);
- AstNode expandedScenarioNode = new AstNode(rowNode, examplesNode);
- nodeMap.put(examplesRow.getLocation().getLine(), expandedScenarioNode);
- }
- }
- }
-
- AstNode getAstNode(URI path, int line) {
- if (!pathToNodeMap.containsKey(path)) {
- parseGherkinSource(path);
- }
- if (pathToNodeMap.containsKey(path)) {
- return pathToNodeMap.get(path).get((long) line);
- }
- return null;
- }
-
- boolean hasBackground(URI path, int line) {
- if (!pathToNodeMap.containsKey(path)) {
- parseGherkinSource(path);
- }
- if (pathToNodeMap.containsKey(path)) {
- AstNode astNode = pathToNodeMap.get(path).get((long) line);
- return getBackgroundForTestCase(astNode).isPresent();
- }
- return false;
- }
-
- static Optional getBackgroundForTestCase(AstNode astNode) {
- Feature feature = getFeatureForTestCase(astNode);
- return feature.getChildren()
- .stream()
- .map(FeatureChild::getBackground)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .findFirst();
- }
-
- private static Feature getFeatureForTestCase(AstNode astNode) {
- while (astNode.parent != null) {
- astNode = astNode.parent;
- }
- return (Feature) astNode.node;
- }
-
- static class ExamplesRowWrapperNode {
-
- final int bodyRowIndex;
-
- ExamplesRowWrapperNode(Object examplesRow, int bodyRowIndex) {
- this.bodyRowIndex = bodyRowIndex;
- }
-
- }
-
- static class AstNode {
-
- final Object node;
- final AstNode parent;
-
- AstNode(Object node, AstNode parent) {
- this.node = node;
- this.parent = parent;
- }
-
- }
-
-}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/TimelineFormatter.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/TimelineFormatter.java
index 40ff501507..b94210863e 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/TimelineFormatter.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/TimelineFormatter.java
@@ -74,9 +74,10 @@ public final class TimelineFormatter implements ConcurrentEventListener {
.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
- @SuppressWarnings({ "unused", "RedundantThrows" }) // Used by PluginFactory
+ // Used by PluginFactory
+ @SuppressWarnings({"unused", "RedundantThrows", "ResultOfMethodCallIgnored"})
public TimelineFormatter(File reportDir) throws FileNotFoundException {
- boolean dontCare = reportDir.mkdirs();
+ reportDir.mkdirs();
if (!reportDir.isDirectory()) {
throw new CucumberException(String.format("The %s needs an existing directory. Not a directory: %s",
getClass().getName(), reportDir.getAbsolutePath()));
@@ -282,7 +283,8 @@ static class TimeLineItem {
private String scenario;
private long start;
private String group;
- private String content = ""; // Replaced in JS file
+ // Replaced in JS file
+ private String content = "";
private String tags;
private long end;
private String className;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/UnusedStepsSummaryPrinter.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/UnusedStepsSummaryPrinter.java
index 7f348f8931..7f20b1c78c 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/UnusedStepsSummaryPrinter.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/UnusedStepsSummaryPrinter.java
@@ -10,6 +10,8 @@
import java.io.IOException;
import java.io.OutputStream;
+import static io.cucumber.usageformatter.MessagesToUsageWriter.builder;
+
/**
* Formatter to measure performance of steps. Includes average and median step
* duration.
@@ -18,10 +20,10 @@ public final class UnusedStepsSummaryPrinter implements ColorAware, ConcurrentEv
private final MessagesToUsageWriter writer;
- @SuppressWarnings("WeakerAccess") // Used by PluginFactory
+ // Used by PluginFactory
+ @SuppressWarnings("WeakerAccess")
public UnusedStepsSummaryPrinter(OutputStream out) {
- this.writer = MessagesToUsageWriter.builder(new UnusedReportSerializer())
- .build(out);
+ this.writer = builder(new UnusedReportSerializer()).build(out);
}
@Override
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/UrlReporter.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/UrlReporter.java
index 04515654ef..aef25ee290 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/UrlReporter.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/UrlReporter.java
@@ -8,11 +8,11 @@ final class UrlReporter implements ColorAware {
private final PrintStream out;
private boolean monochrome;
- public UrlReporter(PrintStream out) {
+ UrlReporter(PrintStream out) {
this.out = out;
}
- public void report(String message) {
+ void report(String message) {
if (monochrome) {
message = message.replaceAll("\u001B\\[[;\\d]*m", "");
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/UsageJsonFormatter.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/UsageJsonFormatter.java
index cc030ff3b9..1ef929fed9 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/plugin/UsageJsonFormatter.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/UsageJsonFormatter.java
@@ -16,7 +16,8 @@ public final class UsageJsonFormatter implements Plugin, ConcurrentEventListener
private final MessagesToUsageWriter writer;
- @SuppressWarnings("WeakerAccess") // Used by PluginFactory
+ // Used by PluginFactory
+ @SuppressWarnings("WeakerAccess")
public UsageJsonFormatter(OutputStream out) {
this.writer = MessagesToUsageWriter.builder(Jackson.OBJECT_MAPPER::writeValue)
.build(out);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/package-info.java
new file mode 100644
index 0000000000..174565c969
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.plugin;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/resource/ClasspathSupport.java b/cucumber-core/src/main/java/io/cucumber/core/resource/ClasspathSupport.java
index 42ade80f36..f9a863fda3 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/resource/ClasspathSupport.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/resource/ClasspathSupport.java
@@ -70,7 +70,8 @@ public static String resourceNameOfPackageName(String packageName) {
static String determinePackageName(Path baseDir, String basePackageName, Path classFile) {
String subPackageName = determineSubpackageName(baseDir, classFile);
return of(basePackageName, subPackageName)
- .filter(value -> !value.isEmpty()) // default package
+ // default package
+ .filter(value -> !value.isEmpty())
.collect(joining(PACKAGE_SEPARATOR_STRING));
}
@@ -84,7 +85,8 @@ static URI determineClasspathResourceUri(Path baseDir, String basePackagePath, P
String subPackageName = determineSubpackagePath(baseDir, resource);
String resourceName = resource.getFileName().toString();
String classpathResourcePath = of(basePackagePath, subPackageName, resourceName)
- .filter(value -> !value.isEmpty()) // default package .
+ // default package .
+ .filter(value -> !value.isEmpty())
.collect(joining(RESOURCE_SEPARATOR_STRING));
return classpathResourceUri(classpathResourcePath);
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/resource/CloseablePath.java b/cucumber-core/src/main/java/io/cucumber/core/resource/CloseablePath.java
index 73583f11e4..8eb99b4c1e 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/resource/CloseablePath.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/resource/CloseablePath.java
@@ -6,7 +6,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
-class CloseablePath implements Closeable {
+final class CloseablePath implements Closeable {
private static final Closeable NULL_CLOSEABLE = () -> {
};
diff --git a/cucumber-core/src/main/java/io/cucumber/core/resource/JarUriFileSystemService.java b/cucumber-core/src/main/java/io/cucumber/core/resource/JarUriFileSystemService.java
index 2af2320d14..bcc05d7385 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/resource/JarUriFileSystemService.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/resource/JarUriFileSystemService.java
@@ -16,7 +16,7 @@
import static io.cucumber.core.resource.ClasspathSupport.nestedJarEntriesExplanation;
import static java.util.Collections.emptyMap;
-class JarUriFileSystemService {
+final class JarUriFileSystemService {
private static final String FILE_URI_SCHEME = "file";
private static final String JAR_URI_SCHEME = "jar";
@@ -27,6 +27,10 @@ class JarUriFileSystemService {
private static final Map openFiles = new HashMap<>();
private static final Map referenceCount = new HashMap<>();
+ private JarUriFileSystemService(){
+ /* no-op */
+ }
+
private static CloseablePath open(URI jarUri, Function pathProvider)
throws IOException {
FileSystem fileSystem = openFileSystem(jarUri);
diff --git a/cucumber-core/src/main/java/io/cucumber/core/resource/PathScanner.java b/cucumber-core/src/main/java/io/cucumber/core/resource/PathScanner.java
index a4ec320864..3543d2d7ae 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/resource/PathScanner.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/resource/PathScanner.java
@@ -2,7 +2,6 @@
import io.cucumber.core.logging.Logger;
import io.cucumber.core.logging.LoggerFactory;
-import org.apiguardian.api.API;
import java.io.IOException;
import java.net.URI;
@@ -21,13 +20,15 @@
import static java.nio.file.FileVisitResult.CONTINUE;
import static java.nio.file.Files.exists;
import static java.nio.file.Files.walkFileTree;
-import static org.apiguardian.api.API.Status.INTERNAL;
-@API(status = INTERNAL)
-public class PathScanner {
+public final class PathScanner {
private static final Logger log = LoggerFactory.getLogger(PathScanner.class);
+ public PathScanner(){
+ /* no-op */
+ }
+
void findResourcesForUri(URI baseUri, Predicate filter, Function> consumer) {
try (CloseablePath closeablePath = open(baseUri)) {
Path baseDir = closeablePath.getPath();
diff --git a/cucumber-core/src/main/java/io/cucumber/core/resource/Resources.java b/cucumber-core/src/main/java/io/cucumber/core/resource/Resources.java
index ea08d5f424..bad3980892 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/resource/Resources.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/resource/Resources.java
@@ -11,10 +11,10 @@
import static io.cucumber.core.resource.ClasspathSupport.determineClasspathResourceUri;
import static io.cucumber.core.resource.ClasspathSupport.resourceNameOfPackageName;
-class Resources {
+final class Resources {
private Resources() {
-
+ /* no-op */
}
static BiFunction createPackageResource(String packageName) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/resource/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/resource/package-info.java
new file mode 100644
index 0000000000..2b222a1c4b
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/resource/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.resource;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java b/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java
index fbdbd66d52..fd3c7003ea 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java
@@ -396,7 +396,7 @@ private SourceReference createSourceReference(io.cucumber.core.backend.SourceRef
// source file
stackReference.fileName().orElse("Unknown"),
stackReference.methodName());
- Location location = new Location((long) stackReference.lineNumber(), null);
+ Location location = new Location(stackReference.lineNumber(), null);
return new SourceReference(null, null, stackTraceElement, location);
}
return emptySourceReference();
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/CoreHookDefinition.java b/cucumber-core/src/main/java/io/cucumber/core/runner/CoreHookDefinition.java
index 88b3d4c7bd..24c289e4f6 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/CoreHookDefinition.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/CoreHookDefinition.java
@@ -74,8 +74,12 @@ String getTagExpression() {
Optional getHookType() {
return delegate.getHookType();
}
-
- static class ScenarioScopedCoreHookDefinition extends CoreHookDefinition implements ScenarioScoped {
+
+ Optional getDefinitionLocation() {
+ return delegate.getSourceReference();
+ }
+
+ static final class ScenarioScopedCoreHookDefinition extends CoreHookDefinition implements ScenarioScoped {
private ScenarioScopedCoreHookDefinition(UUID id, HookDefinition delegate) {
super(id, delegate);
@@ -91,7 +95,5 @@ public void dispose() {
}
- Optional getDefinitionLocation() {
- return delegate.getSourceReference();
- }
+
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java b/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java
index dbf6b6d15d..f5346ec4b5 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/Runner.java
@@ -84,7 +84,7 @@ public void runPickle(Pickle pickle) {
private Locale localeForPickle(Pickle pickle) {
String language = pickle.getLanguage();
- return localeCache.computeIfAbsent(language, (lang) -> new Locale(language));
+ return localeCache.computeIfAbsent(language, lang -> new Locale(language));
}
public void runBeforeAllHooks() {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java b/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java
index a013455a73..459d21df24 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/TestCase.java
@@ -57,7 +57,7 @@ final class TestCase implements io.cucumber.plugin.event.TestCase {
private static io.cucumber.messages.types.Group makeMessageGroup(
Group group
) {
- long start = group.getStart();
+ int start = group.getStart();
return new io.cucumber.messages.types.Group(
group.getChildren().stream()
.map(TestCase::makeMessageGroup)
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/TestStepResultStatusMapper.java b/cucumber-core/src/main/java/io/cucumber/core/runner/TestStepResultStatusMapper.java
index 223541431a..6c062edbb2 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/TestStepResultStatusMapper.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/TestStepResultStatusMapper.java
@@ -15,7 +15,7 @@
import static io.cucumber.messages.types.TestStepResultStatus.UNDEFINED;
import static io.cucumber.messages.types.TestStepResultStatus.UNKNOWN;
-class TestStepResultStatusMapper {
+final class TestStepResultStatusMapper {
private static final Map STATUS;
@@ -28,7 +28,7 @@ class TestStepResultStatusMapper {
status.put(Status.SKIPPED, SKIPPED);
status.put(Status.AMBIGUOUS, AMBIGUOUS);
STATUS = Collections.unmodifiableMap(status);
- };
+ }
private TestStepResultStatusMapper() {
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/runner/package-info.java
new file mode 100644
index 0000000000..fb33c9de9e
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.runner;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runtime/CucumberExecutionContext.java b/cucumber-core/src/main/java/io/cucumber/core/runtime/CucumberExecutionContext.java
index dd413010d7..067dfcb4d8 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runtime/CucumberExecutionContext.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runtime/CucumberExecutionContext.java
@@ -47,11 +47,6 @@ public CucumberExecutionContext(EventBus bus, ExitStatus exitStatus, RunnerSuppl
this.runnerSupplier = runnerSupplier;
}
- @FunctionalInterface
- public interface ThrowingRunnable {
- void run() throws Throwable;
- }
-
public void startTestRun() {
emitMeta();
emitTestRunStarted();
@@ -166,4 +161,10 @@ private void execute(ThrowingRunnable runnable) {
}
}
+ @FunctionalInterface
+ public interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+
+
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runtime/Runtime.java b/cucumber-core/src/main/java/io/cucumber/core/runtime/Runtime.java
index 87fdf4503e..95e355bf88 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runtime/Runtime.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runtime/Runtime.java
@@ -112,7 +112,7 @@ public byte exitStatus() {
return exitStatus.exitStatus();
}
- public static class Builder {
+ public static final class Builder {
private EventBus eventBus;
private Supplier classLoader = ClassLoaders::getDefaultClassLoader;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runtime/TestCaseFailed.java b/cucumber-core/src/main/java/io/cucumber/core/runtime/TestCaseFailed.java
index 15a9cac13d..bf729928c0 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runtime/TestCaseFailed.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runtime/TestCaseFailed.java
@@ -14,7 +14,7 @@
*/
class TestCaseFailed extends RuntimeException {
- public TestCaseFailed(Throwable throwable) {
+ TestCaseFailed(Throwable throwable) {
super(throwable);
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runtime/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/runtime/package-info.java
new file mode 100644
index 0000000000..18500f4e59
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/runtime/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.runtime;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/snippets/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/snippets/package-info.java
new file mode 100644
index 0000000000..c3471e4223
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/snippets/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.snippets;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepExpression.java b/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepExpression.java
index 7c18760626..426db7fd94 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepExpression.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepExpression.java
@@ -42,11 +42,7 @@ public List match(String text, List> cells, Type... types
}
public List match(String text, Type... types) {
- List> match = expression.match(text, types);
- if (match == null) {
- return null;
- }
- return wrapPlusOne(match);
+ return expression.match(text, types).map(StepExpression::wrapPlusOne).orElse(null);
}
private static List wrapPlusOne(List> match) {
diff --git a/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepTypeRegistry.java b/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepTypeRegistry.java
index e59a013647..68a6f6b78f 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepTypeRegistry.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/stepexpression/StepTypeRegistry.java
@@ -12,7 +12,7 @@
import java.util.Locale;
-public final class StepTypeRegistry implements io.cucumber.core.api.TypeRegistry {
+public final class StepTypeRegistry {
private final ParameterTypeRegistry parameterTypeRegistry;
@@ -38,34 +38,28 @@ public DocStringTypeRegistry docStringTypeRegistry() {
return docStringTypeRegistry;
}
- @Override
public void defineParameterType(ParameterType> parameterType) {
parameterTypeRegistry.defineParameterType(parameterType);
}
- @Override
public void defineDocStringType(DocStringType docStringType) {
docStringTypeRegistry.defineDocStringType(docStringType);
}
- @Override
public void defineDataTableType(DataTableType tableType) {
dataTableTypeRegistry.defineDataTableType(tableType);
}
- @Override
public void setDefaultParameterTransformer(ParameterByTypeTransformer defaultParameterByTypeTransformer) {
parameterTypeRegistry.setDefaultParameterTransformer(defaultParameterByTypeTransformer);
}
- @Override
public void setDefaultDataTableEntryTransformer(
TableEntryByTypeTransformer defaultDataTableEntryByTypeTransformer
) {
dataTableTypeRegistry.setDefaultDataTableEntryTransformer(defaultDataTableEntryByTypeTransformer);
}
- @Override
public void setDefaultDataTableCellTransformer(TableCellByTypeTransformer defaultDataTableByTypeTransformer) {
dataTableTypeRegistry.setDefaultDataTableCellTransformer(defaultDataTableByTypeTransformer);
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/stepexpression/package-info.java b/cucumber-core/src/main/java/io/cucumber/core/stepexpression/package-info.java
new file mode 100644
index 0000000000..a9aa3aa005
--- /dev/null
+++ b/cucumber-core/src/main/java/io/cucumber/core/stepexpression/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.stepexpression;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/DefaultObjectFactoryTest.java b/cucumber-core/src/test/java/io/cucumber/core/backend/DefaultObjectFactoryTest.java
index 7a1579259a..29bca9690d 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/DefaultObjectFactoryTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/DefaultObjectFactoryTest.java
@@ -50,13 +50,13 @@ void shouldThrowForNonZeroArgPublicConstructors() {
" * ...etc\n"));
}
- public static class StepDefinition {
+ public static final class StepDefinition {
// we just test the instances
}
- public static class NoAccessibleConstructor {
+ public static final class NoAccessibleConstructor {
private NoAccessibleConstructor() {
-
+ /* no-op */
}
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/StubBackendProviderService.java b/cucumber-core/src/test/java/io/cucumber/core/backend/StubBackendProviderService.java
index 366893fc26..6defe9ee77 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/StubBackendProviderService.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/StubBackendProviderService.java
@@ -2,11 +2,9 @@
import io.cucumber.core.snippets.TestSnippet;
-import java.net.URI;
-import java.util.List;
import java.util.function.Supplier;
-public class StubBackendProviderService implements BackendProviderService {
+public final class StubBackendProviderService implements BackendProviderService {
@Override
public Backend create(Lookup lookup, Container container, Supplier classLoader) {
@@ -15,21 +13,6 @@ public Backend create(Lookup lookup, Container container, Supplier
static class StubBackend implements Backend {
- @Override
- public void loadGlue(Glue glue, List gluePaths) {
-
- }
-
- @Override
- public void buildWorld() {
-
- }
-
- @Override
- public void disposeWorld() {
-
- }
-
@Override
public Snippet getSnippet() {
return new TestSnippet();
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/StubHookDefinition.java b/cucumber-core/src/test/java/io/cucumber/core/backend/StubHookDefinition.java
index 67622e671b..3201a7bb6c 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/StubHookDefinition.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/StubHookDefinition.java
@@ -3,7 +3,7 @@
import java.util.Optional;
import java.util.function.Consumer;
-public class StubHookDefinition implements HookDefinition {
+public final class StubHookDefinition implements HookDefinition {
private static final String STUBBED_LOCATION_WITH_DETAILS = "{stubbed location with details}";
private final Located location;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/StubLocation.java b/cucumber-core/src/test/java/io/cucumber/core/backend/StubLocation.java
index 7263313f06..aa9ed330f7 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/StubLocation.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/StubLocation.java
@@ -3,7 +3,7 @@
import java.lang.reflect.Method;
import java.util.Optional;
-public class StubLocation implements Located {
+public final class StubLocation implements Located {
private final String location;
private final SourceReference sourceReference;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/StubPendingException.java b/cucumber-core/src/test/java/io/cucumber/core/backend/StubPendingException.java
index 4485cd1e77..7d43d13ef0 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/StubPendingException.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/StubPendingException.java
@@ -1,7 +1,5 @@
package io.cucumber.core.backend;
-import io.cucumber.core.backend.Pending;
-
import java.io.PrintStream;
import java.io.PrintWriter;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/StubStaticHookDefinition.java b/cucumber-core/src/test/java/io/cucumber/core/backend/StubStaticHookDefinition.java
index 361f74e90b..b6c7c7c3a7 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/StubStaticHookDefinition.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/StubStaticHookDefinition.java
@@ -1,6 +1,6 @@
package io.cucumber.core.backend;
-public class StubStaticHookDefinition implements StaticHookDefinition {
+public final class StubStaticHookDefinition implements StaticHookDefinition {
private static final String STUBBED_LOCATION_WITH_DETAILS = "{stubbed location with details}";
private final String location;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/backend/StubStepDefinition.java b/cucumber-core/src/test/java/io/cucumber/core/backend/StubStepDefinition.java
index afa3830dde..57d59c5fc1 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/backend/StubStepDefinition.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/backend/StubStepDefinition.java
@@ -9,7 +9,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
-public class StubStepDefinition implements StepDefinition {
+public final class StubStepDefinition implements StepDefinition {
private static final String STUBBED_LOCATION_WITH_DETAILS = "{stubbed location with details}";
private final List parameterInfos;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/cli/MainDemo.java b/cucumber-core/src/test/java/io/cucumber/core/cli/MainDemo.java
index 9d99bd7c65..a3831e8e07 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/cli/MainDemo.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/cli/MainDemo.java
@@ -1,6 +1,10 @@
package io.cucumber.core.cli;
-public class MainDemo {
+public final class MainDemo {
+
+ private MainDemo(){
+ /* no-op */
+ }
public static void main(String[] args) {
// Main.main("--i18n");
diff --git a/cucumber-core/src/test/java/io/cucumber/core/eventbus/IncrementingUuidGeneratorTest.java b/cucumber-core/src/test/java/io/cucumber/core/eventbus/IncrementingUuidGeneratorTest.java
index 1b50506f5c..8875bb3edb 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/eventbus/IncrementingUuidGeneratorTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/eventbus/IncrementingUuidGeneratorTest.java
@@ -321,7 +321,7 @@ private static UuidGenerator getUuidGeneratorFromOtherClassloader(Integer classl
*/
private static class NonCachingClassLoader extends ClassLoader {
- public NonCachingClassLoader() {
+ NonCachingClassLoader() {
}
@Override
diff --git a/cucumber-core/src/test/java/io/cucumber/core/feature/TestFeatureParser.java b/cucumber-core/src/test/java/io/cucumber/core/feature/TestFeatureParser.java
index ed67eab5cb..98b3dc8916 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/feature/TestFeatureParser.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/feature/TestFeatureParser.java
@@ -10,8 +10,12 @@
import static java.nio.charset.StandardCharsets.UTF_8;
-public class TestFeatureParser {
+public final class TestFeatureParser {
+ private TestFeatureParser(){
+ /* no-op */
+ }
+
public static Feature parse(final String source) {
return parse("file:test.feature", source);
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/logging/WithLogRecordListener.java b/cucumber-core/src/test/java/io/cucumber/core/logging/WithLogRecordListener.java
index 46bc820d1b..7b8fc0e4bb 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/logging/WithLogRecordListener.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/logging/WithLogRecordListener.java
@@ -18,9 +18,9 @@
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
-@ExtendWith({ WithLogRecordListener.Extension.class })
+@ExtendWith(WithLogRecordListener.Extension.class)
public @interface WithLogRecordListener {
- class Extension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
+ final class Extension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
private ExtensionContext.Store getContextStore(ExtensionContext context) {
Namespace namespace = create(Extension.class, context.getRequiredTestMethod());
return context.getStore(namespace);
diff --git a/cucumber-core/src/test/java/io/cucumber/core/options/CommandlineOptionsParserTest.java b/cucumber-core/src/test/java/io/cucumber/core/options/CommandlineOptionsParserTest.java
index 881e650ef5..40477f26dc 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/options/CommandlineOptionsParserTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/options/CommandlineOptionsParserTest.java
@@ -14,7 +14,6 @@
import io.cucumber.plugin.ColorAware;
import io.cucumber.plugin.EventListener;
import io.cucumber.plugin.Plugin;
-import io.cucumber.plugin.StrictAware;
import io.cucumber.plugin.event.EventPublisher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
@@ -195,9 +194,8 @@ void assigns_filters_from_tags() {
@Test
void throws_runtime_exception_on_malformed_tag_expression() {
- RuntimeException e = assertThrows(RuntimeException.class, () -> {
- RuntimeOptions options = parser
- .parse("--tags", ")")
+ assertThrows(RuntimeException.class, () -> {
+ parser.parse("--tags", ")")
.build();
});
}
@@ -439,19 +437,6 @@ void set_monochrome_on_color_aware_formatters() {
assertThat(formatter.isMonochrome(), is(true));
}
- @Test
- void set_strict_on_strict_aware_formatters() {
- RuntimeOptions options = parser
- .parse("--plugin", AwareFormatter.class.getName())
- .build();
- Plugins plugins = new Plugins(new PluginFactory(), options);
- plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID));
-
- AwareFormatter formatter = (AwareFormatter) plugins.getPlugins().get(0);
- assertThat(formatter.isStrict(), is(true));
-
- }
-
@Test
void ensure_default_snippet_type_is_underscore() {
RuntimeOptions runtimeOptions = parser
@@ -575,20 +560,10 @@ public void stop() {
}
- public static final class AwareFormatter implements StrictAware, ColorAware, EventListener {
+ public static final class AwareFormatter implements ColorAware, EventListener {
- private boolean strict;
private boolean monochrome;
- private boolean isStrict() {
- return strict;
- }
-
- @Override
- public void setStrict(boolean strict) {
- this.strict = strict;
- }
-
boolean isMonochrome() {
return monochrome;
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptions.java b/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptions.java
index cf4457c7f2..c880a73586 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptions.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptions.java
@@ -8,7 +8,7 @@
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.TYPE })
+@Target(ElementType.TYPE)
public @interface CucumberOptions {
boolean dryRun() default false;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptionsAnnotationParserTest.java b/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptionsAnnotationParserTest.java
index 17010a0451..3ada038e78 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptionsAnnotationParserTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/options/CucumberOptionsAnnotationParserTest.java
@@ -260,17 +260,17 @@ void uuid_generator() {
}
@CucumberOptions(snippets = SnippetType.CAMELCASE)
- private static class Snippets {
+ private static final class Snippets {
// empty
}
@CucumberOptions(name = { "name1", "name2" })
- private static class MultipleNames {
+ private static final class MultipleNames {
// empty
}
@CucumberOptions(tags = "@cucumber or @gherkin")
- private static class TagExpression {
+ private static final class TagExpression {
// empty
}
@@ -279,12 +279,12 @@ private static class ClassWithInvalidTagExpression {
// empty
}
- private static class ClassWithInheredInvalidTagExpression extends ClassWithInvalidTagExpression {
+ private static final class ClassWithInheredInvalidTagExpression extends ClassWithInvalidTagExpression {
// empty
}
@CucumberOptions
- private static class NoName {
+ private static final class NoName {
// empty
}
@@ -293,16 +293,16 @@ private static class WithoutOptions {
}
@CucumberOptions
- private static class WithDefaultOptions {
+ private static final class WithDefaultOptions {
// empty
}
- private static class WithoutOptionsWithBaseClassWithoutOptions extends WithoutOptions {
+ private static final class WithoutOptionsWithBaseClassWithoutOptions extends WithoutOptions {
// empty
}
@CucumberOptions(plugin = "pretty")
- private static class SubClassWithFormatter extends BaseClassWithFormatter {
+ private static final class SubClassWithFormatter extends BaseClassWithFormatter {
// empty
}
@@ -312,7 +312,7 @@ private static class BaseClassWithFormatter {
}
@CucumberOptions(monochrome = true)
- private static class SubClassWithMonoChromeTrue extends BaseClassWithMonoChromeFalse {
+ private static final class SubClassWithMonoChromeTrue extends BaseClassWithMonoChromeFalse {
// empty
}
@@ -322,22 +322,22 @@ private static class BaseClassWithMonoChromeFalse {
}
@CucumberOptions(objectFactory = TestObjectFactory.class)
- private static class ClassWithCustomObjectFactory {
+ private static final class ClassWithCustomObjectFactory {
// empty
}
@CucumberOptions(publish = true)
- private static class ClassWithPublish {
+ private static final class ClassWithPublish {
// empty
}
@CucumberOptions(plugin = "io.cucumber.core.plugin.AnyStepDefinitionReporter")
- private static class ClassWithNoFormatterPlugin {
+ private static final class ClassWithNoFormatterPlugin {
// empty
}
@CucumberOptions(junit = { "option1", "option2=value" })
- private static class ClassWithJunitOption {
+ private static final class ClassWithJunitOption {
// empty
}
@@ -352,12 +352,12 @@ private static class ClassWithExtraGlue {
}
@CucumberOptions(extraGlue = "app.features.user.hooks")
- private static class SubClassWithExtraGlueOfExtraGlue extends ClassWithExtraGlue {
+ private static final class SubClassWithExtraGlueOfExtraGlue extends ClassWithExtraGlue {
// empty
}
@CucumberOptions(extraGlue = "app.features.user.hooks")
- private static class SubClassWithExtraGlueOfGlue extends ClassWithGlue {
+ private static final class SubClassWithExtraGlueOfGlue extends ClassWithGlue {
// empty
}
@@ -366,12 +366,12 @@ private static class SubClassWithExtraGlueOfGlue extends ClassWithGlue {
extraGlue = "app.features.hooks"
)
- private static class ClassWithGlueAndExtraGlue {
+ private static final class ClassWithGlueAndExtraGlue {
// empty
}
@CucumberOptions(uuidGenerator = IncrementingUuidGenerator.class)
- private static class ClassWithUuidGenerator extends ClassWithGlue {
+ private static final class ClassWithUuidGenerator extends ClassWithGlue {
// empty
}
@@ -444,7 +444,7 @@ public Class extends UuidGenerator> uuidGenerator() {
}
}
- private static class CoreCucumberOptionsProvider implements CucumberOptionsAnnotationParser.OptionsProvider {
+ private static final class CoreCucumberOptionsProvider implements CucumberOptionsAnnotationParser.OptionsProvider {
@Override
public CucumberOptionsAnnotationParser.CucumberOptions getOptions(Class> clazz) {
diff --git a/cucumber-core/src/test/java/io/cucumber/core/options/TestPluginOption.java b/cucumber-core/src/test/java/io/cucumber/core/options/TestPluginOption.java
deleted file mode 100644
index 98242a05c6..0000000000
--- a/cucumber-core/src/test/java/io/cucumber/core/options/TestPluginOption.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.cucumber.core.options;
-
-public class TestPluginOption {
-
- public static PluginOption parse(String pluginArgumentPattern) {
- return PluginOption.parse(pluginArgumentPattern);
- }
-
-}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/Bytes.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/Bytes.java
index 2736c176d4..883dade609 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/Bytes.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/Bytes.java
@@ -9,6 +9,10 @@
import static java.nio.charset.StandardCharsets.UTF_8;
final class Bytes {
+
+ private Bytes(){
+ /* no-op */
+ }
static DiagnosingMatcher bytes(Matcher expected) {
return new DiagnosingMatcher() {
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/IsEqualCompressingLineSeparators.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/IsEqualCompressingLineSeparators.java
index 300b2d20c8..38b6c30156 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/IsEqualCompressingLineSeparators.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/IsEqualCompressingLineSeparators.java
@@ -6,7 +6,7 @@
import java.util.Objects;
-public class IsEqualCompressingLineSeparators extends TypeSafeMatcher {
+public final class IsEqualCompressingLineSeparators extends TypeSafeMatcher {
private final String expected;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginFactoryTest.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginFactoryTest.java
index 2e4b88c5d4..fdd86170d4 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginFactoryTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginFactoryTest.java
@@ -25,7 +25,6 @@
import java.nio.file.Path;
import java.util.Objects;
-import static io.cucumber.core.options.TestPluginOption.parse;
import static io.cucumber.messages.Convertor.toMessage;
import static java.nio.file.Files.readAllLines;
import static java.time.Duration.ZERO;
@@ -49,6 +48,10 @@ class PluginFactoryTest {
@TempDir
Path tmp;
+ public static PluginOption parse(String pluginArgumentPattern) {
+ return PluginOption.parse(pluginArgumentPattern);
+ }
+
@AfterEach
void cleanUp() {
if (plugin != null) {
@@ -261,70 +264,81 @@ void fails_to_instantiate_plugin_that_declares_two_single_arg_constructors_when_
"You must supply an output argument to io.cucumber.core.plugin.PluginFactoryTest$WantsFileOrURL. Like so: io.cucumber.core.plugin.PluginFactoryTest$WantsFileOrURL:DIR|FILE|URL")));
}
- public static class WantsOutputStream extends StubFormatter {
+ private void releaseResources(Object plugin) {
+ FakeTestRunEventsPublisher fakeTestRun = new FakeTestRunEventsPublisher();
+ if (plugin instanceof EventListener eventListener) {
+ eventListener.setEventPublisher(fakeTestRun);
+ fakeTestRun.fakeTestRunEvents();
+ } else if (plugin instanceof ConcurrentEventListener concurrentEventListener) {
+ concurrentEventListener.setEventPublisher(fakeTestRun);
+ fakeTestRun.fakeTestRunEvents();
+ }
+ }
- public OutputStream out;
+ static class WantsOutputStream extends StubFormatter {
- public WantsOutputStream(OutputStream out) {
+ OutputStream out;
+
+ WantsOutputStream(OutputStream out) {
this.out = Objects.requireNonNull(out);
}
}
- public static class WantsFileOrEmpty extends StubFormatter {
+ static class WantsFileOrEmpty extends StubFormatter {
- public File out = null;
+ File out = null;
- public WantsFileOrEmpty(File out) {
+ WantsFileOrEmpty(File out) {
this.out = Objects.requireNonNull(out);
}
- public WantsFileOrEmpty() {
+ WantsFileOrEmpty() {
}
}
- public static class WantsFile extends StubFormatter {
+ static class WantsFile extends StubFormatter {
- public final File out;
+ final File out;
- public WantsFile(File out) {
+ WantsFile(File out) {
this.out = Objects.requireNonNull(out);
}
}
- public static class WantsFileOrURL extends StubFormatter {
+ static class WantsFileOrURL extends StubFormatter {
- public WantsFileOrURL(File out) {
+ WantsFileOrURL(File out) {
Objects.requireNonNull(out);
}
- public WantsFileOrURL(URL out) {
+ WantsFileOrURL(URL out) {
Objects.requireNonNull(out);
}
}
- public static class WantsString extends StubFormatter {
+ static class WantsString extends StubFormatter {
- public final String arg;
+ final String arg;
- public WantsString(String arg) {
+ WantsString(String arg) {
this.arg = Objects.requireNonNull(arg);
}
}
- public static class WantsAppendable extends StubFormatter {
+ static class WantsAppendable extends StubFormatter {
- public final Appendable out;
+ final Appendable out;
- public WantsAppendable(Appendable out) {
+ WantsAppendable(Appendable out) {
this.out = Objects.requireNonNull(out);
}
- public void writeAndClose(String s) throws IOException {
+ void writeAndClose(String s) throws IOException {
out.append(s);
if (out instanceof Closeable) {
Closeable closeable = (Closeable) out;
@@ -334,18 +348,18 @@ public void writeAndClose(String s) throws IOException {
}
- public static class WantsNothing extends StubFormatter {
+ static class WantsNothing extends StubFormatter {
}
- public static class WantsTooMuch extends StubFormatter {
+ static class WantsTooMuch extends StubFormatter {
- public WantsTooMuch(String too, String much) {
+ WantsTooMuch(String too, String much) {
}
}
- private static class FakeTestRunEventsPublisher implements EventPublisher {
+ private static final class FakeTestRunEventsPublisher implements EventPublisher {
private EventHandler startHandler;
private EventHandler finishedHandler;
private EventHandler envelopeHandler;
@@ -353,13 +367,13 @@ private static class FakeTestRunEventsPublisher implements EventPublisher {
@Override
public void registerHandlerFor(Class eventType, EventHandler handler) {
if (eventType == TestRunStarted.class) {
- startHandler = ((EventHandler) handler);
+ startHandler = (EventHandler) handler;
}
if (eventType == TestRunFinished.class) {
- finishedHandler = ((EventHandler) handler);
+ finishedHandler = (EventHandler) handler;
}
if (eventType == Envelope.class) {
- envelopeHandler = ((EventHandler) handler);
+ envelopeHandler = (EventHandler) handler;
}
}
@@ -367,7 +381,7 @@ public void registerHandlerFor(Class eventType, EventHandler handler)
public void removeHandlerFor(Class eventType, EventHandler handler) {
}
- public void fakeTestRunEvents() {
+ void fakeTestRunEvents() {
if (startHandler != null) {
startHandler.receive(new TestRunStarted(now()));
}
@@ -383,15 +397,5 @@ public void fakeTestRunEvents() {
}
- private void releaseResources(Object plugin) {
- FakeTestRunEventsPublisher fakeTestRun = new FakeTestRunEventsPublisher();
- if (plugin instanceof EventListener) {
- ((EventListener) plugin).setEventPublisher(fakeTestRun);
- fakeTestRun.fakeTestRunEvents();
- } else if (plugin instanceof ConcurrentEventListener) {
- ((ConcurrentEventListener) plugin).setEventPublisher(fakeTestRun);
- fakeTestRun.fakeTestRunEvents();
- }
- }
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginsTest.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginsTest.java
index e4233eb0ae..db9d0828cc 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginsTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/PluginsTest.java
@@ -4,16 +4,14 @@
import io.cucumber.plugin.ColorAware;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.EventListener;
-import io.cucumber.plugin.StrictAware;
import io.cucumber.plugin.event.Event;
import io.cucumber.plugin.event.EventPublisher;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
@@ -23,7 +21,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-@ExtendWith({ MockitoExtension.class })
+@MockitoSettings
class PluginsTest {
private final PluginFactory pluginFactory = new PluginFactory();
@@ -32,15 +30,6 @@ class PluginsTest {
@Captor
private ArgumentCaptor eventPublisher;
- @Test
- void shouldSetStrictOnPlugin() {
- RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
- Plugins plugins = new Plugins(pluginFactory, runtimeOptions);
- StrictAware plugin = mock(StrictAware.class);
- plugins.addPlugin(plugin);
- verify(plugin).setStrict(true);
- }
-
@Test
void shouldSetMonochromeOnPlugin() {
RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/StubException.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/StubException.java
index 1517227783..c406565b91 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/StubException.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/StubException.java
@@ -14,19 +14,19 @@ private StubException(String className, String message, String stacktrace) {
this.stacktrace = stacktrace;
}
- public StubException() {
+ StubException() {
this("stub exception");
}
- public StubException(String message) {
+ StubException(String message) {
this(null, message, null);
}
- public StubException withClassName() {
+ StubException withClassName() {
return new StubException(StubException.class.getName(), getMessage(), stacktrace);
}
- public StubException withStacktrace(String stacktrace) {
+ StubException withStacktrace(String stacktrace) {
return new StubException(className, getMessage(), stacktrace);
}
@@ -51,7 +51,7 @@ private void printStackTrace(PrintWriterOrStream p) {
}
}
- private static class PrintWriterOrStream {
+ private static final class PrintWriterOrStream {
private final PrintWriter writer;
private final PrintStream stream;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/TimelineFormatterTest.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/TimelineFormatterTest.java
index b712d03c47..b188573597 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/TimelineFormatterTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/TimelineFormatterTest.java
@@ -55,15 +55,6 @@ class TimelineFormatterTest {
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
.build();
- // private final Gson gson = new GsonBuilder().registerTypeAdapter(
- // Instant.class,
- // (JsonDeserializer) (json, type, jsonDeserializationContext) ->
- // json.isJsonObject()
- // ?
- // Instant.ofEpochSecond(json.getAsJsonObject().get("seconds").getAsLong())
- // : Instant.ofEpochMilli(json.getAsLong()))
- // .create();
-
private final Feature failingFeature = TestFeatureParser.parse("some/path/failing.feature", "" +
"Feature: Failing Feature\n" +
" Background:\n" +
@@ -80,28 +71,28 @@ class TimelineFormatterTest {
" When step_02\n" +
" Then step_03");
- private final Feature successfulFeature = TestFeatureParser.parse("some/path/successful.feature", "" +
- "Feature: Successful Feature\n" +
- " Background:\n" +
- " Given bg_1\n" +
- " When bg_2\n" +
- " Then bg_3\n" +
- " @TagB @TagC\n" +
- " Scenario: Scenario 3\n" +
- " Given step_10\n" +
- " When step_20\n" +
- " Then step_30");
-
- private final Feature pendingFeature = TestFeatureParser.parse("some/path/pending.feature", "" +
- "Feature: Pending Feature\n" +
- " Background:\n" +
- " Given bg_1\n" +
- " When bg_2\n" +
- " Then bg_3\n" +
- " Scenario: Scenario 4\n" +
- " Given step_10\n" +
- " When step_20\n" +
- " Then step_50");
+ private final Feature successfulFeature = TestFeatureParser.parse("some/path/successful.feature", """
+ Feature: Successful Feature
+ Background:
+ Given bg_1
+ When bg_2
+ Then bg_3
+ @TagB @TagC
+ Scenario: Scenario 3
+ Given step_10
+ When step_20
+ Then step_30""");
+
+ private final Feature pendingFeature = TestFeatureParser.parse("some/path/pending.feature", """
+ Feature: Pending Feature
+ Background:
+ Given bg_1
+ When bg_2
+ Then bg_3
+ Scenario: Scenario 4
+ Given step_10
+ When step_20
+ Then step_50""");
@TempDir
Path reportDir;
@@ -195,48 +186,49 @@ void shouldWriteItemsCorrectlyToReportJsWhenRunInParallel() throws Throwable {
}
private TimeLineItem[] getExpectedTestData() throws JsonProcessingException {
- String expectedJson = ("[\n" +
- " {\n" +
- " \"feature\": \"Failing Feature\",\n" +
- " \"scenario\": \"Scenario 1\",\n" +
- " \"start\": 0,\n" +
- " \"end\": 6000,\n" +
- " \"group\": \"main\",\n" +
- " \"content\": \"\",\n" +
- " \"tags\": \"@taga,\",\n" +
- " \"className\": \"failed\"\n" +
- " },\n" +
- " {\n" +
- " \"feature\": \"Failing Feature\",\n" +
- " \"scenario\": \"Scenario 2\",\n" +
- " \"start\": 6000,\n" +
- " \"end\": 12000,\n" +
- " \"group\": \"main\",\n" +
- " \"content\": \"\",\n" +
- " \"tags\": \"\",\n" +
- " \"className\": \"failed\"\n" +
- " },\n" +
- " {\n" +
- " \"feature\": \"Successful Feature\",\n" +
- " \"scenario\": \"Scenario 3\",\n" +
- " \"start\": 18000,\n" +
- " \"end\": 24000,\n" +
- " \"group\": \"main\",\n" +
- " \"content\": \"\",\n" +
- " \"tags\": \"@tagb,@tagc,\",\n" +
- " \"className\": \"passed\"\n" +
- " },\n" +
- " {\n" +
- " \"scenario\": \"Scenario 4\",\n" +
- " \"feature\": \"Pending Feature\",\n" +
- " \"start\": 12000,\n" +
- " \"end\": 18000,\n" +
- " \"group\": \"main\",\n" +
- " \"content\": \"\",\n" +
- " \"tags\": \"\",\n" +
- " \"className\": \"undefined\"\n" +
- " }\n" +
- "]");
+ String expectedJson = """
+ [
+ {
+ "feature": "Failing Feature",
+ "scenario": "Scenario 1",
+ "start": 0,
+ "end": 6000,
+ "group": "main",
+ "content": "",
+ "tags": "@taga,",
+ "className": "failed"
+ },
+ {
+ "feature": "Failing Feature",
+ "scenario": "Scenario 2",
+ "start": 6000,
+ "end": 12000,
+ "group": "main",
+ "content": "",
+ "tags": "",
+ "className": "failed"
+ },
+ {
+ "feature": "Successful Feature",
+ "scenario": "Scenario 3",
+ "start": 18000,
+ "end": 24000,
+ "group": "main",
+ "content": "",
+ "tags": "@tagb,@tagc,",
+ "className": "passed"
+ },
+ {
+ "scenario": "Scenario 4",
+ "feature": "Pending Feature",
+ "start": 12000,
+ "end": 18000,
+ "group": "main",
+ "content": "",
+ "tags": "",
+ "className": "undefined"
+ }
+ ]""";
return objectMapper.readValue(expectedJson, TimeLineItem[].class);
}
@@ -323,12 +315,13 @@ void shouldWriteItemsAndGroupsCorrectlyToReportJs() throws Throwable {
TimeLineItem[] expectedTests = getExpectedTestData();
TimeLineGroup[] expectedGroups = objectMapper.readValue(
- ("[\n" +
- " {\n" +
- " \"id\": \"main\",\n" +
- " \"content\": \"groupName\"\n" +
- " }\n" +
- "]")
+ """
+ [
+ {
+ "id": "main",
+ "content": "groupName"
+ }
+ ]"""
.replaceAll("groupName", groupName),
TimeLineGroup[].class);
diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/UrlOutputStreamTest.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/UrlOutputStreamTest.java
index d9ead04832..3bbccd90f0 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/plugin/UrlOutputStreamTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/UrlOutputStreamTest.java
@@ -29,7 +29,7 @@
import static org.hamcrest.Matchers.nullValue;
@ExtendWith(VertxExtension.class)
-public class UrlOutputStreamTest {
+class UrlOutputStreamTest {
private static final int TIMEOUT_SECONDS = 15;
private int port;
@@ -154,7 +154,7 @@ void sets_request_headers(Vertx vertx, VertxTestContext testContext) {
verifyRequest(url, testServer, vertx, testContext, requestBody);
}
- public static class TestServer extends AbstractVerticle {
+ static final class TestServer extends AbstractVerticle {
private final int port;
private final VertxTestContext testContext;
@@ -166,7 +166,7 @@ public static class TestServer extends AbstractVerticle {
private final String responseBody;
private final Buffer receivedBody = Buffer.buffer(0);
- public TestServer(
+ TestServer(
int port,
VertxTestContext testContext,
String expectedBody,
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/CachingGlueTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/CachingGlueTest.java
index b5efe306d2..de7186c815 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/CachingGlueTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/CachingGlueTest.java
@@ -617,7 +617,9 @@ void prepareGlue_cache_evicted_when_docString_added() {
assertThat(stepTypeRegistry1 == stepTypeRegistry2, is(true));
}
- private static class MockedScenarioScopedStepDefinition extends StubStepDefinition implements ScenarioScoped {
+ private static final class MockedScenarioScopedStepDefinition extends StubStepDefinition implements ScenarioScoped {
+
+ private boolean disposed;
MockedScenarioScopedStepDefinition(String pattern, Type... types) {
super(pattern, types);
@@ -626,7 +628,6 @@ private static class MockedScenarioScopedStepDefinition extends StubStepDefiniti
MockedScenarioScopedStepDefinition(String pattern, boolean transposed, Type... types) {
super(pattern, transposed, types);
}
- private boolean disposed;
@Override
public void dispose() {
@@ -639,7 +640,7 @@ public boolean isDisposed() {
}
- private static class MockedDataTableTypeDefinition implements DataTableTypeDefinition, ScenarioScoped {
+ private static final class MockedDataTableTypeDefinition implements DataTableTypeDefinition, ScenarioScoped {
@Override
public DataTableType dataTableType() {
@@ -669,7 +670,7 @@ public boolean isDisposed() {
}
- private static class MockedParameterTypeDefinition implements ParameterTypeDefinition, ScenarioScoped {
+ private static final class MockedParameterTypeDefinition implements ParameterTypeDefinition, ScenarioScoped {
@Override
public ParameterType> parameterType() {
@@ -699,7 +700,7 @@ public boolean isDisposed() {
}
- private static class MockedParameterTypeDefinitionWithSourceReference extends MockedParameterTypeDefinition {
+ private static final class MockedParameterTypeDefinitionWithSourceReference extends MockedParameterTypeDefinition {
@Override
public Optional getSourceReference() {
return Optional.of(SourceReference.fromStackTraceElement(new StackTraceElement(
@@ -710,7 +711,7 @@ public Optional getSourceReference() {
}
}
- private static class MockedHookDefinition implements HookDefinition {
+ private static final class MockedHookDefinition implements HookDefinition {
private final int order;
@@ -749,7 +750,7 @@ public int getOrder() {
}
- private static class MockedScenarioScopedHookDefinition implements HookDefinition, ScenarioScoped {
+ private static final class MockedScenarioScopedHookDefinition implements HookDefinition, ScenarioScoped {
private final int order;
@@ -815,7 +816,7 @@ private static class MockedStepDefinition extends StubStepDefinition {
}
- private static class MockedDefaultParameterTransformer
+ private static final class MockedDefaultParameterTransformer
implements DefaultParameterTransformerDefinition, ScenarioScoped {
@Override
@@ -846,7 +847,7 @@ public boolean isDisposed() {
}
- private static class MockedDefaultDataTableCellTransformer
+ private static final class MockedDefaultDataTableCellTransformer
implements DefaultDataTableCellTransformerDefinition, ScenarioScoped {
@Override
@@ -877,7 +878,7 @@ public boolean isDisposed() {
}
- private static class MockedDefaultDataTableEntryTransformer
+ private static final class MockedDefaultDataTableEntryTransformer
implements DefaultDataTableEntryTransformerDefinition, ScenarioScoped {
@Override
@@ -913,7 +914,7 @@ public boolean isDisposed() {
}
- private static class MockedDocStringTypeDefinition implements DocStringTypeDefinition, ScenarioScoped {
+ private static final class MockedDocStringTypeDefinition implements DocStringTypeDefinition, ScenarioScoped {
@Override
public DocStringType docStringType() {
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/CamelCaseConverterTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/CamelCaseConverterTest.java
index 843b0caa2f..6d78ba5dc0 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/CamelCaseConverterTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/CamelCaseConverterTest.java
@@ -36,7 +36,7 @@ void convert_to_camel_case(String header) {
"threeWordsString", "ThreeWordsString", "three Words String",
"Three Words String", "Three words String", "Three Words string",
"Three words string", "three Words string", "three words String",
- "threeWords string", "three WordsString", "three wordsString",
+ "threeWords string", "three WordsString", "three wordsString"
})
void convert_three_words_to_camel_case(String header) {
assertThat(
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/ClockStub.java b/cucumber-core/src/test/java/io/cucumber/core/runner/ClockStub.java
deleted file mode 100644
index 5047b31775..0000000000
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/ClockStub.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.cucumber.core.runner;
-
-import java.time.Clock;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.ZoneId;
-
-public class ClockStub extends Clock {
-
- private final Duration duration;
- private final ThreadLocal currentInstant = new ThreadLocal<>();
-
- public ClockStub(Duration duration) {
- this.duration = duration;
- }
-
- @Override
- public ZoneId getZone() {
- return null;
- }
-
- @Override
- public Clock withZone(ZoneId zone) {
- return null;
- }
-
- @Override
- public Instant instant() {
- Instant result = currentInstant.get();
- result = result != null ? result : Instant.EPOCH;
- currentInstant.set(result.plus(duration));
- return result;
- }
-
-}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/StepDefinitionMatchTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/StepDefinitionMatchTest.java
index 2dfdd8e8ba..da81f336f2 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/StepDefinitionMatchTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/StepDefinitionMatchTest.java
@@ -215,13 +215,15 @@ void throws_could_not_convert_exception_for_transformer_and_capture_group_mismat
"itemQuantity",
"(few|some|lots of) (cukes|gherkins)",
ItemQuantity.class,
- (String s) -> null // Wrong number of capture groups
+ // Wrong number of capture groups
+ (String s) -> null
));
- Feature feature = TestFeatureParser.parse("" +
- "Feature: Test feature\n" +
- " Scenario: Test scenario\n" +
- " Given I have some cukes in my belly\n");
+ Feature feature = TestFeatureParser.parse("""
+ Feature: Test feature
+ Scenario: Test scenario
+ Given I have some cukes in my belly
+ """);
Step step = feature.getPickles().get(0).getSteps().get(0);
StepDefinition stepDefinition = new StubStepDefinition("I have {itemQuantity} in my belly", ItemQuantity.class);
StepExpression expression = stepExpressionFactory.createExpression(stepDefinition);
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/StepDurationTimeService.java b/cucumber-core/src/test/java/io/cucumber/core/runner/StepDurationTimeService.java
index 289554d536..3bfa3d7175 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/StepDurationTimeService.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/StepDurationTimeService.java
@@ -12,7 +12,7 @@
import java.util.Arrays;
import java.util.List;
-public class StepDurationTimeService extends Clock implements ConcurrentEventListener {
+public final class StepDurationTimeService extends Clock implements ConcurrentEventListener {
private final ThreadLocal currentInstant = new ThreadLocal<>();
private final List stepDuration;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/StubStepDefinition.java b/cucumber-core/src/test/java/io/cucumber/core/runner/StubStepDefinition.java
index 0996378309..f70ff548bf 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/StubStepDefinition.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/StubStepDefinition.java
@@ -63,6 +63,17 @@ public String getLocation() {
return "{stubbed location with details}";
}
+
+ @Override
+ public Optional getSourceReference() {
+ try {
+ Method method = getClass().getMethod("getSourceReference");
+ return Optional.of(SourceReference.fromMethod(method));
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
private final class StubParameterInfo implements ParameterInfo {
private final Type type;
@@ -88,14 +99,4 @@ public TypeResolver getTypeResolver() {
}
- @Override
- public Optional getSourceReference() {
- try {
- Method method = getClass().getMethod("getSourceReference");
- return Optional.of(SourceReference.fromMethod(method));
- } catch (NoSuchMethodException e) {
- throw new IllegalStateException(e);
- }
- }
-
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestAbortedExceptionsTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestAbortedExceptionsTest.java
index bd8346db65..b64bbd1a6b 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestAbortedExceptionsTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestAbortedExceptionsTest.java
@@ -8,9 +8,7 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-public class TestAbortedExceptionsTest {
- static class TestAbortedExceptionSubClass extends TestAbortedException {
- }
+class TestAbortedExceptionsTest {
@Test
void testPredicate() {
@@ -21,4 +19,6 @@ void testPredicate() {
assertTrue(isTestAbortedExceptionPredicate.test(new TestAbortedExceptionSubClass()));
}
+ static class TestAbortedExceptionSubClass extends TestAbortedException {
+ }
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestBackendSupplier.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestBackendSupplier.java
index 9c68e83b58..6f46d0de11 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestBackendSupplier.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestBackendSupplier.java
@@ -11,22 +11,12 @@
public abstract class TestBackendSupplier implements Backend, BackendSupplier {
@Override
- public void buildWorld() {
-
- }
-
- @Override
- public void disposeWorld() {
-
- }
-
- @Override
- public Snippet getSnippet() {
+ public final Snippet getSnippet() {
return new TestSnippet();
}
@Override
- public Collection extends Backend> get() {
+ public final Collection extends Backend> get() {
return Collections.singleton(this);
}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java
index f1082fe48e..bc85ea2774 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestCaseStateResultTest.java
@@ -162,8 +162,8 @@ private static final class EmbedEventMatcher implements ArgumentMatcher createArguments(List match) {
- return DefinitionArgument.createArguments(match);
- }
-
-}
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runner/TestRunnerSupplier.java b/cucumber-core/src/test/java/io/cucumber/core/runner/TestRunnerSupplier.java
index d2ebd6dada..8810c798bb 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runner/TestRunnerSupplier.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runner/TestRunnerSupplier.java
@@ -14,7 +14,7 @@
import static java.util.Collections.singleton;
-public class TestRunnerSupplier implements Backend, RunnerSupplier, ObjectFactory {
+public final class TestRunnerSupplier implements Backend, RunnerSupplier, ObjectFactory {
private final EventBus bus;
private final RuntimeOptions runtimeOptions;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runtime/CucumberExecutionContextTest.java b/cucumber-core/src/test/java/io/cucumber/core/runtime/CucumberExecutionContextTest.java
index fb9057e9e8..3113fa69b8 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runtime/CucumberExecutionContextTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runtime/CucumberExecutionContextTest.java
@@ -60,7 +60,7 @@ public void rethrows_but_does_not_collect_failures_in_test_case() {
r.assertTestCasePassed(
Exception::new,
Function.identity(),
- (suggestions) -> new Exception(),
+ suggestions -> new Exception(),
Function.identity());
}
}));
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runtime/DryRunTest.java b/cucumber-core/src/test/java/io/cucumber/core/runtime/DryRunTest.java
index 24686b9ccd..d8ca17ce7d 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runtime/DryRunTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runtime/DryRunTest.java
@@ -237,7 +237,7 @@ void dry_run_passes_failed_step() {
" PASSED\n"));
}
- private static class StepStatusSpy implements EventListener {
+ private static final class StepStatusSpy implements EventListener {
private final StringBuilder calls = new StringBuilder();
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runtime/RuntimeTest.java b/cucumber-core/src/test/java/io/cucumber/core/runtime/RuntimeTest.java
index f7167191e8..ed0b0aeee2 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runtime/RuntimeTest.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runtime/RuntimeTest.java
@@ -600,7 +600,7 @@ public String getLocation() {
}
- private static class MockedStaticHookDefinition implements StaticHookDefinition {
+ private final static class MockedStaticHookDefinition implements StaticHookDefinition {
private final Runnable runnable;
@@ -629,7 +629,7 @@ public String getLocation() {
}
}
- private static class FormatterSpy implements EventListener {
+ private static final class FormatterSpy implements EventListener {
private final StringBuilder calls = new StringBuilder();
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runtime/ServiceLoaderTestClassLoader.java b/cucumber-core/src/test/java/io/cucumber/core/runtime/ServiceLoaderTestClassLoader.java
index f02b8c8980..24c16a970a 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runtime/ServiceLoaderTestClassLoader.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runtime/ServiceLoaderTestClassLoader.java
@@ -16,7 +16,7 @@
* Testing classloader for ServiceLoader. This classloader overrides the
* META-INF/services/interface-class-name file with a custom definition.
*/
-public class ServiceLoaderTestClassLoader extends URLClassLoader {
+final class ServiceLoaderTestClassLoader extends URLClassLoader {
Class> metaInfInterface;
Class>[] implementingClasses;
@@ -25,7 +25,7 @@ public class ServiceLoaderTestClassLoader extends URLClassLoader {
*
* @param metaInfInterface ServiceLoader interface
*/
- public ServiceLoaderTestClassLoader(Class> metaInfInterface) {
+ ServiceLoaderTestClassLoader(Class> metaInfInterface) {
this(metaInfInterface, (Class>[]) null);
}
@@ -39,7 +39,7 @@ public ServiceLoaderTestClassLoader(Class> metaInfInterface) {
* @param implementingClasses potential subclasses of the ServiceLoader
* metaInfInterface
*/
- public ServiceLoaderTestClassLoader(Class> metaInfInterface, Class>... implementingClasses) {
+ ServiceLoaderTestClassLoader(Class> metaInfInterface, Class>... implementingClasses) {
super(new URL[0], metaInfInterface.getClassLoader());
if (!metaInfInterface.isInterface()) {
throw new IllegalArgumentException("the META-INF service " + metaInfInterface + " should be an interface");
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runtime/StubBackendSupplier.java b/cucumber-core/src/test/java/io/cucumber/core/runtime/StubBackendSupplier.java
index b8a8ae5c10..7ddc35b37e 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runtime/StubBackendSupplier.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runtime/StubBackendSupplier.java
@@ -14,7 +14,7 @@
import java.util.Collections;
import java.util.List;
-public class StubBackendSupplier implements BackendSupplier {
+public final class StubBackendSupplier implements BackendSupplier {
private final List beforeAll;
private final List before;
@@ -78,16 +78,6 @@ public void loadGlue(Glue glue, List gluePaths) {
afterAll.forEach(glue::addAfterAllHook);
}
- @Override
- public void buildWorld() {
-
- }
-
- @Override
- public void disposeWorld() {
-
- }
-
@Override
public Snippet getSnippet() {
return new TestSnippet();
diff --git a/cucumber-core/src/test/java/io/cucumber/core/runtime/StubFeatureSupplier.java b/cucumber-core/src/test/java/io/cucumber/core/runtime/StubFeatureSupplier.java
index daed6522e7..80253f043c 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/runtime/StubFeatureSupplier.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/runtime/StubFeatureSupplier.java
@@ -5,7 +5,7 @@
import java.util.Arrays;
import java.util.List;
-public class StubFeatureSupplier implements FeatureSupplier {
+public final class StubFeatureSupplier implements FeatureSupplier {
private final List features;
diff --git a/cucumber-core/src/test/java/io/cucumber/core/snippets/TestSnippet.java b/cucumber-core/src/test/java/io/cucumber/core/snippets/TestSnippet.java
index b1e34193a2..c577d71bf4 100644
--- a/cucumber-core/src/test/java/io/cucumber/core/snippets/TestSnippet.java
+++ b/cucumber-core/src/test/java/io/cucumber/core/snippets/TestSnippet.java
@@ -7,7 +7,7 @@
import java.util.Map;
import java.util.Optional;
-public class TestSnippet implements Snippet {
+public final class TestSnippet implements Snippet {
@Override
public Optional language() {
diff --git a/cucumber-deltaspike/src/main/java/io/cucumber/deltaspike/package-info.java b/cucumber-deltaspike/src/main/java/io/cucumber/deltaspike/package-info.java
new file mode 100644
index 0000000000..dca913215c
--- /dev/null
+++ b/cucumber-deltaspike/src/main/java/io/cucumber/deltaspike/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.deltaspike;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/CucumberQuery.java b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/CucumberQuery.java
index 273c4ade92..1c5f23533b 100644
--- a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/CucumberQuery.java
+++ b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/CucumberQuery.java
@@ -10,6 +10,7 @@
import io.cucumber.messages.types.Scenario;
import io.cucumber.messages.types.Step;
import io.cucumber.messages.types.TableRow;
+import org.jspecify.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
@@ -44,7 +45,7 @@ private void updateBackground(Background background) {
updateStep(background.getSteps());
}
- private void updateScenario(Feature feature, Rule rule, Scenario scenario) {
+ private void updateScenario(Feature feature, @Nullable Rule rule, Scenario scenario) {
gherkinScenarioById.put(requireNonNull(scenario.getId()), scenario);
locationBySourceId.put(requireNonNull(scenario.getId()), scenario.getLocation());
updateStep(scenario.getSteps());
diff --git a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesDocStringArgument.java b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesDocStringArgument.java
index 0de6bd54ac..00d98e3bdb 100644
--- a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesDocStringArgument.java
+++ b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesDocStringArgument.java
@@ -2,6 +2,7 @@
import io.cucumber.core.gherkin.DocStringArgument;
import io.cucumber.messages.types.PickleDocString;
+import org.jspecify.annotations.Nullable;
final class GherkinMessagesDocStringArgument implements DocStringArgument {
@@ -19,12 +20,13 @@ public String getContent() {
}
@Override
- public String getContentType() {
+ @Deprecated
+ public @Nullable String getContentType() {
return getMediaType();
}
@Override
- public String getMediaType() {
+ public @Nullable String getMediaType() {
String mediaType = docString.getMediaType().orElse(null);
if ("".equals(mediaType)) {
return null;
diff --git a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesLocation.java b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesLocation.java
index a0353dbbae..6b1e240034 100644
--- a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesLocation.java
+++ b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesLocation.java
@@ -4,8 +4,12 @@
final class GherkinMessagesLocation {
+ private GherkinMessagesLocation() {
+ /* no-op */
+ }
+
static Location from(io.cucumber.messages.types.Location location) {
- return new Location(Math.toIntExact(location.getLine()), Math.toIntExact(location.getColumn().orElse(0L)));
+ return new Location(Math.toIntExact(location.getLine()), Math.toIntExact(location.getColumn().orElse(0)));
}
}
diff --git a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesStep.java b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesStep.java
index 9616d403f4..b373253fc8 100644
--- a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesStep.java
+++ b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/GherkinMessagesStep.java
@@ -8,32 +8,33 @@
import io.cucumber.messages.types.PickleStep;
import io.cucumber.messages.types.PickleTable;
import io.cucumber.plugin.event.Location;
+import org.jspecify.annotations.Nullable;
final class GherkinMessagesStep implements Step {
private final PickleStep pickleStep;
- private final Argument argument;
- private final String keyWord;
+ private final @Nullable Argument argument;
+ private final String keyword;
private final StepType stepType;
- private final String previousGwtKeyWord;
+ private final String previousGwtKeyword;
private final Location location;
GherkinMessagesStep(
PickleStep pickleStep,
GherkinDialect dialect,
- String previousGwtKeyWord,
+ String previousGwtKeyword,
Location location,
String keyword
) {
this.pickleStep = pickleStep;
this.argument = extractArgument(pickleStep, location);
- this.keyWord = keyword;
- this.stepType = extractKeyWordType(keyWord, dialect);
- this.previousGwtKeyWord = previousGwtKeyWord;
+ this.keyword = keyword;
+ this.stepType = extractKeyWordType(this.keyword, dialect);
+ this.previousGwtKeyword = previousGwtKeyword;
this.location = location;
}
- private static Argument extractArgument(PickleStep pickleStep, Location location) {
+ private static @Nullable Argument extractArgument(PickleStep pickleStep, Location location) {
return pickleStep.getArgument()
.map(argument -> {
if (argument.getDocString().isPresent()) {
@@ -49,31 +50,31 @@ private static Argument extractArgument(PickleStep pickleStep, Location location
}).orElse(null);
}
- private static StepType extractKeyWordType(String keyWord, GherkinDialect dialect) {
- if (StepType.isAstrix(keyWord)) {
+ private static StepType extractKeyWordType(String keyword, GherkinDialect dialect) {
+ if (StepType.isAstrix(keyword)) {
return StepType.OTHER;
}
- if (dialect.getGivenKeywords().contains(keyWord)) {
+ if (dialect.getGivenKeywords().contains(keyword)) {
return StepType.GIVEN;
}
- if (dialect.getWhenKeywords().contains(keyWord)) {
+ if (dialect.getWhenKeywords().contains(keyword)) {
return StepType.WHEN;
}
- if (dialect.getThenKeywords().contains(keyWord)) {
+ if (dialect.getThenKeywords().contains(keyword)) {
return StepType.THEN;
}
- if (dialect.getAndKeywords().contains(keyWord)) {
+ if (dialect.getAndKeywords().contains(keyword)) {
return StepType.AND;
}
- if (dialect.getButKeywords().contains(keyWord)) {
+ if (dialect.getButKeywords().contains(keyword)) {
return StepType.BUT;
}
- throw new IllegalStateException("Keyword " + keyWord + " was neither given, when, then, and, but nor *");
+ throw new IllegalStateException("Keyword " + keyword + " was neither given, when, then, and, but nor *");
}
@Override
public String getKeyword() {
- return keyWord;
+ return keyword;
}
@Override
@@ -93,7 +94,7 @@ public StepType getType() {
@Override
public String getPreviousGivenWhenThenKeyword() {
- return previousGwtKeyWord;
+ return previousGwtKeyword;
}
@Override
@@ -102,7 +103,7 @@ public String getId() {
}
@Override
- public Argument getArgument() {
+ public @Nullable Argument getArgument() {
return argument;
}
diff --git a/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/package-info.java b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/package-info.java
new file mode 100644
index 0000000000..bdb8784f55
--- /dev/null
+++ b/cucumber-gherkin-messages/src/main/java/io/cucumber/core/gherkin/messages/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.gherkin.messages;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-gherkin-messages/src/test/java/io/cucumber/core/gherkin/messages/FeatureParserTest.java b/cucumber-gherkin-messages/src/test/java/io/cucumber/core/gherkin/messages/FeatureParserTest.java
index ca6f8feea6..2406fb13ef 100644
--- a/cucumber-gherkin-messages/src/test/java/io/cucumber/core/gherkin/messages/FeatureParserTest.java
+++ b/cucumber-gherkin-messages/src/test/java/io/cucumber/core/gherkin/messages/FeatureParserTest.java
@@ -19,7 +19,7 @@
import java.util.Optional;
import java.util.UUID;
-import static java.nio.file.Files.readAllBytes;
+import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -33,9 +33,10 @@ class FeatureParserTest {
final URI uri = URI.create("classpath:com/example.feature");
@Test
+ @Deprecated
void can_parse_with_deprecated_method() throws IOException {
- String source = new String(
- readAllBytes(Paths.get("src/test/resources/io/cucumber/core/gherkin/messages/no-pickles.feature")));
+ String source = Files
+ .readString(Paths.get("src/test/resources/io/cucumber/core/gherkin/messages/no-pickles.feature"));
Optional feature = parser.parse(uri, source, UUID::randomUUID);
assertTrue(feature.isPresent());
assertEquals(0, feature.get().getPickles().size());
@@ -95,7 +96,7 @@ void empty_table_is_parsed() throws IOException {
Feature feature = parser.parse(uri, source, UUID::randomUUID).get();
Pickle pickle = feature.getPickles().get(0);
Step step = pickle.getSteps().get(0);
- DataTableArgument argument = (DataTableArgument) step.getArgument();
+ DataTableArgument argument = (DataTableArgument) requireNonNull(step.getArgument());
assertEquals(5, argument.getLine());
}
}
@@ -109,9 +110,11 @@ void empty_doc_string_media_type_is_null() throws IOException {
Pickle pickle = feature.getPickles().get(0);
List steps = pickle.getSteps();
+ DocStringArgument argument0 = (DocStringArgument) requireNonNull(steps.get(0).getArgument());
+ DocStringArgument argument1 = (DocStringArgument) requireNonNull(steps.get(1).getArgument());
assertAll(() -> {
- assertNull(((DocStringArgument) steps.get(0).getArgument()).getContentType());
- assertEquals("text/plain", ((DocStringArgument) steps.get(1).getArgument()).getContentType());
+ assertNull(argument0.getContentType());
+ assertEquals("text/plain", argument1.getContentType());
});
}
}
@@ -133,13 +136,13 @@ void lexer_error_throws_exception() throws IOException {
Paths.get("src/test/resources/io/cucumber/core/gherkin/messages/lexer-error.feature"))) {
FeatureParserException exception = assertThrows(FeatureParserException.class,
() -> parser.parse(uri, source, UUID::randomUUID));
- assertEquals("" +
- "Failed to parse resource at: classpath:com/example.feature\n" +
- "(1:1): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Feature FA'\n" +
- "(3:3): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Scenario SA'\n" +
- "(4:5): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Given GA'\n" +
- "(5:5): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'When GA'\n" +
- "(6:5): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Then TA'",
+ assertEquals("""
+ Failed to parse resource at: classpath:com/example.feature
+ (1:1): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Feature FA'
+ (3:3): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Scenario SA'
+ (4:5): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Given GA'
+ (5:5): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'When GA'
+ (6:5): expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'Then TA'""",
exception.getMessage());
}
}
diff --git a/cucumber-gherkin/pom.xml b/cucumber-gherkin/pom.xml
index db1ad09c7d..6b54997e17 100644
--- a/cucumber-gherkin/pom.xml
+++ b/cucumber-gherkin/pom.xml
@@ -36,6 +36,11 @@
+
+ org.jspecify
+ jspecify
+ 1.0.0
+ io.cucumbercucumber-plugin
diff --git a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/DocStringArgument.java b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/DocStringArgument.java
index 8d0344dd10..2082f05f29 100644
--- a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/DocStringArgument.java
+++ b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/DocStringArgument.java
@@ -1,14 +1,19 @@
package io.cucumber.core.gherkin;
+import org.jspecify.annotations.Nullable;
+
public interface DocStringArgument extends Argument, io.cucumber.plugin.event.DocStringArgument {
@Override
String getContent();
@Override
+ @Deprecated
+ @Nullable
String getContentType();
@Override
+ @Nullable
String getMediaType();
@Override
diff --git a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/FeatureParser.java b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/FeatureParser.java
index 89230527f2..4e5fe925e9 100644
--- a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/FeatureParser.java
+++ b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/FeatureParser.java
@@ -16,13 +16,13 @@ public interface FeatureParser {
Optional parse(URI path, String source, Supplier idGenerator);
default Optional parse(URI path, InputStream source, Supplier idGenerator) throws IOException {
- final byte[] buffer = new byte[2 * 1024]; // 2KB
+ final byte[] buffer = new byte[2 * 1024];
int read;
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
while (-1 != (read = source.read(buffer, 0, buffer.length))) {
outputStream.write(buffer, 0, read);
}
- String s = new String(outputStream.toByteArray(), UTF_8);
+ String s = outputStream.toString(UTF_8);
return parse(path, s, idGenerator);
}
}
diff --git a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/Step.java b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/Step.java
index 20411cbfe7..30959bc485 100644
--- a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/Step.java
+++ b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/Step.java
@@ -1,5 +1,7 @@
package io.cucumber.core.gherkin;
+import org.jspecify.annotations.Nullable;
+
public interface Step extends io.cucumber.plugin.event.Step {
StepType getType();
@@ -9,6 +11,7 @@ public interface Step extends io.cucumber.plugin.event.Step {
String getId();
@Override
+ @Nullable
Argument getArgument();
}
diff --git a/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/package-info.java b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/package-info.java
new file mode 100644
index 0000000000..b2922374f5
--- /dev/null
+++ b/cucumber-gherkin/src/main/java/io/cucumber/core/gherkin/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.core.gherkin;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-guice/src/main/java/io/cucumber/guice/package-info.java b/cucumber-guice/src/main/java/io/cucumber/guice/package-info.java
index b3a5345566..28847c8136 100644
--- a/cucumber-guice/src/main/java/io/cucumber/guice/package-info.java
+++ b/cucumber-guice/src/main/java/io/cucumber/guice/package-info.java
@@ -24,4 +24,7 @@
* precedence if the same class is also bound using a scope annotation.
*
*/
+@NullMarked
package io.cucumber.guice;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-jakarta-cdi/src/main/java/io/cucumber/jakarta/cdi/package-info.java b/cucumber-jakarta-cdi/src/main/java/io/cucumber/jakarta/cdi/package-info.java
new file mode 100644
index 0000000000..04dcf11a46
--- /dev/null
+++ b/cucumber-jakarta-cdi/src/main/java/io/cucumber/jakarta/cdi/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.jakarta.cdi;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-jakarta-openejb/src/main/java/io/cucumber/jakarta/openejb/package-info.java b/cucumber-jakarta-openejb/src/main/java/io/cucumber/jakarta/openejb/package-info.java
index d1dd71e47e..ae06320d46 100644
--- a/cucumber-jakarta-openejb/src/main/java/io/cucumber/jakarta/openejb/package-info.java
+++ b/cucumber-jakarta-openejb/src/main/java/io/cucumber/jakarta/openejb/package-info.java
@@ -4,4 +4,7 @@
* By including the cucumber-jakarta-openejb on your
* CLASSPATH your step definitions will be instantiated by OpenEJB.
*/
+@NullMarked
package io.cucumber.jakarta.openejb;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-java/src/main/java/io/cucumber/java/package-info.java b/cucumber-java/src/main/java/io/cucumber/java/package-info.java
new file mode 100644
index 0000000000..3fccd3fd6c
--- /dev/null
+++ b/cucumber-java/src/main/java/io/cucumber/java/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.java;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-java8/src/main/java/io/cucumber/java8/package-info.java b/cucumber-java8/src/main/java/io/cucumber/java8/package-info.java
new file mode 100644
index 0000000000..b9e2346b81
--- /dev/null
+++ b/cucumber-java8/src/main/java/io/cucumber/java8/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.java8;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/package-info.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/package-info.java
new file mode 100644
index 0000000000..1d165c1931
--- /dev/null
+++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.junit.platform.engine;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-junit-platform-engine/src/main/java9/module-info.java b/cucumber-junit-platform-engine/src/main/java/module-info.java
similarity index 100%
rename from cucumber-junit-platform-engine/src/main/java9/module-info.java
rename to cucumber-junit-platform-engine/src/main/java/module-info.java
diff --git a/cucumber-junit/src/main/java/io/cucumber/junit/package-info.java b/cucumber-junit/src/main/java/io/cucumber/junit/package-info.java
new file mode 100644
index 0000000000..037955768e
--- /dev/null
+++ b/cucumber-junit/src/main/java/io/cucumber/junit/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.junit;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-openejb/src/main/java/io/cucumber/openejb/package-info.java b/cucumber-openejb/src/main/java/io/cucumber/openejb/package-info.java
index 3bf4ee736d..4f1df1f827 100644
--- a/cucumber-openejb/src/main/java/io/cucumber/openejb/package-info.java
+++ b/cucumber-openejb/src/main/java/io/cucumber/openejb/package-info.java
@@ -4,4 +4,7 @@
* By including the cucumber-openejb on your CLASSPATH
* your step definitions will be instantiated by OpenEJB.
*/
+@NullMarked
package io.cucumber.openejb;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-picocontainer/src/main/java/io/cucumber/picocontainer/package-info.java b/cucumber-picocontainer/src/main/java/io/cucumber/picocontainer/package-info.java
index 9812425a59..e59c3f2e85 100644
--- a/cucumber-picocontainer/src/main/java/io/cucumber/picocontainer/package-info.java
+++ b/cucumber-picocontainer/src/main/java/io/cucumber/picocontainer/package-info.java
@@ -5,4 +5,7 @@
* CLASSPATH your step definitions will be instantiated by
* PicoContainer.
*/
+@NullMarked
package io.cucumber.picocontainer;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-plugin/pom.xml b/cucumber-plugin/pom.xml
index 2c99ab22ff..e37e0a8f83 100644
--- a/cucumber-plugin/pom.xml
+++ b/cucumber-plugin/pom.xml
@@ -42,6 +42,11 @@
apiguardian-api${apiguardian-api.version}
+
+ org.jspecify
+ jspecify
+ 1.0.0
+ org.junit.jupiterjunit-jupiter
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/StrictAware.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/StrictAware.java
deleted file mode 100755
index 5c8e91ba03..0000000000
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/StrictAware.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.cucumber.plugin;
-
-import org.apiguardian.api.API;
-
-/**
- * Interface for Plugins that need to know if the Runtime is strict.
- *
- * @deprecated strict mode is enabled by default and will be removed.
- */
-@Deprecated
-@API(status = API.Status.STABLE)
-public interface StrictAware extends Plugin {
-
- /**
- * When set to strict the plugin should indicate failure for undefined and
- * pending steps
- *
- * @param strict true if the runtime is in strict mode
- */
- void setStrict(boolean strict);
-
-}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/SummaryPrinter.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/SummaryPrinter.java
deleted file mode 100644
index b799f4ffff..0000000000
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/SummaryPrinter.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.cucumber.plugin;
-
-import org.apiguardian.api.API;
-
-/**
- * Interface for plugins that print a summary after test execution. Deprecated
- * use the {@link EventListener} or {@link ConcurrentEventListener} interface
- * instead.
- *
- * @see Plugin
- */
-@API(status = API.Status.STABLE)
-@Deprecated
-public interface SummaryPrinter extends Plugin {
-
-}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/DocStringArgument.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/DocStringArgument.java
index 0345ecf434..8d4b36acff 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/DocStringArgument.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/DocStringArgument.java
@@ -1,6 +1,7 @@
package io.cucumber.plugin.event;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
/**
* Represents a Gherkin doc string argument.
@@ -14,8 +15,10 @@ public interface DocStringArgument extends StepArgument {
* @deprecated use {@link #getMediaType()} instead.
*/
@Deprecated
+ @Nullable
String getContentType();
+ @Nullable
String getMediaType();
int getLine();
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/EmbedEvent.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/EmbedEvent.java
index 2e2619fc46..8131256903 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/EmbedEvent.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/EmbedEvent.java
@@ -1,6 +1,7 @@
package io.cucumber.plugin.event;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import java.time.Instant;
@@ -9,7 +10,7 @@
@API(status = API.Status.STABLE)
public final class EmbedEvent extends TestCaseEvent {
- public final String name;
+ public final @Nullable String name;
private final byte[] data;
private final String mediaType;
@@ -17,7 +18,7 @@ public EmbedEvent(Instant timeInstant, TestCase testCase, byte[] data, String me
this(timeInstant, testCase, data, mediaType, null);
}
- public EmbedEvent(Instant timeInstant, TestCase testCase, byte[] data, String mediaType, String name) {
+ public EmbedEvent(Instant timeInstant, TestCase testCase, byte[] data, String mediaType, @Nullable String name) {
super(timeInstant, testCase);
this.data = requireNonNull(data);
this.mediaType = requireNonNull(mediaType);
@@ -41,7 +42,7 @@ public String getMimeType() {
return mediaType;
}
- public String getName() {
+ public @Nullable String getName() {
return name;
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Location.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Location.java
index b85a6e5db2..180c937a68 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Location.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Location.java
@@ -48,4 +48,12 @@ public int compareTo(Location o) {
}
return Integer.compare(column, o.column);
}
+
+ @Override
+ public String toString() {
+ return "Location{" +
+ "line=" + line +
+ ", column=" + column +
+ '}';
+ }
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Node.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Node.java
index 79d3a44a06..b9cd91d978 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Node.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Node.java
@@ -38,7 +38,7 @@ public interface Node {
default URI getUri() {
throw new UnsupportedOperationException("Not yet implemented");
- };
+ }
Location getLocation();
@@ -76,24 +76,23 @@ default T map(
BiFunction mapExamples,
BiFunction mapExample
) {
- if (this instanceof Scenario) {
- return mapScenario.apply((Scenario) this, parent);
- } else if (this instanceof Example) {
- return mapExample.apply((Example) this, parent);
- } else if (this instanceof Container) {
+ if (this instanceof Scenario scenario) {
+ return mapScenario.apply(scenario, parent);
+ } else if (this instanceof Example example) {
+ return mapExample.apply(example, parent);
+ } else if (this instanceof Container> container) {
final T mapped;
- if (this instanceof Feature) {
- mapped = mapFeature.apply((Feature) this, parent);
- } else if (this instanceof Rule) {
- mapped = mapRule.apply((Rule) this, parent);
- } else if (this instanceof ScenarioOutline) {
- mapped = mapScenarioOutline.apply((ScenarioOutline) this, parent);
- } else if (this instanceof Examples) {
- mapped = mapExamples.apply((Examples) this, parent);
+ if (this instanceof Feature feature) {
+ mapped = mapFeature.apply(feature, parent);
+ } else if (this instanceof Rule rule) {
+ mapped = mapRule.apply(rule, parent);
+ } else if (this instanceof ScenarioOutline scenarioOutline) {
+ mapped = mapScenarioOutline.apply(scenarioOutline, parent);
+ } else if (this instanceof Examples examples) {
+ mapped = mapExamples.apply(examples, parent);
} else {
throw new IllegalArgumentException(this.getClass().getName());
}
- Container> container = (Container>) this;
container.elements().forEach(node -> node.map(mapped, mapFeature, mapRule, mapScenario, mapScenarioOutline,
mapExamples, mapExample));
return mapped;
@@ -142,9 +141,8 @@ default Optional> findPathTo(Predicate predicate) {
path.add(candidate);
return Optional.of(path);
}
- if (candidate instanceof Container) {
+ if (candidate instanceof Container> container) {
path.add(candidate);
- Container> container = (Container>) candidate;
toSearch.addLast(new ArrayDeque<>(container.elements()));
}
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Result.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Result.java
index 77802e2f18..08fb833e12 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Result.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Result.java
@@ -1,6 +1,7 @@
package io.cucumber.plugin.event;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import java.time.Duration;
import java.util.Objects;
@@ -15,7 +16,7 @@ public final class Result {
private final Status status;
private final Duration duration;
- private final Throwable error;
+ private final @Nullable Throwable error;
/**
* Creates a new result.
@@ -24,7 +25,7 @@ public final class Result {
* @param duration the duration
* @param error the error that caused the failure if any
*/
- public Result(Status status, Duration duration, Throwable error) {
+ public Result(Status status, Duration duration, @Nullable Throwable error) {
this.status = requireNonNull(status);
this.duration = requireNonNull(duration);
this.error = error;
@@ -47,7 +48,7 @@ public Duration getDuration() {
*
* @return the error encountered while executing a step or scenario or null.
*/
- public Throwable getError() {
+ public @Nullable Throwable getError() {
return error;
}
@@ -72,7 +73,7 @@ public boolean equals(Object o) {
public String toString() {
return "Result{" +
"status=" + status +
- ", duration=" + duration.getSeconds() +
+ ", duration=" + duration.toSeconds() +
", error=" + error +
'}';
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Step.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Step.java
index 5ac6bb5ac7..15783536c2 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Step.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/Step.java
@@ -1,6 +1,7 @@
package io.cucumber.plugin.event;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
/**
* Represents a step in a scenario.
@@ -14,6 +15,7 @@ public interface Step {
*
* @return a step argument, null if absent
*/
+ @Nullable
StepArgument getArgument();
/**
@@ -22,6 +24,7 @@ public interface Step {
* @return step key word
* @deprecated use {@link #getKeyword()} instead
*/
+ @Deprecated
default String getKeyWord() {
return getKeyword();
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/StepDefinition.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/StepDefinition.java
index 1add47b80c..684c90519f 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/StepDefinition.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/StepDefinition.java
@@ -24,8 +24,10 @@ public String getLocation() {
}
/**
- * @return the pattern associated with this instance. Used for error
- * reporting only.
+ * Returns the pattern associated with this instance. Used for error
+ * reporting only.
+ *
+ * @return the pattern associated with this instance.
*/
public String getPattern() {
return pattern;
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCase.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCase.java
index 490561c482..26fee7c80c 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCase.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCase.java
@@ -14,7 +14,8 @@ public interface TestCase {
* is an example in a Scenario Outline the method wil return the line of the
* example.
*
- * @return the line of this scenario.
+ * @return the line of this scenario.
+ * @deprecated use {@link #getLocation()} instead.
*/
@Deprecated
Integer getLine();
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCaseEvent.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCaseEvent.java
index 4cfc03c267..947c82125a 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCaseEvent.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestCaseEvent.java
@@ -15,6 +15,9 @@ public abstract class TestCaseEvent extends TimeStampedEvent {
this.testCase = Objects.requireNonNull(testCase);
}
+ /**
+ * Returns the test case for this event.
+ */
public TestCase getTestCase() {
return testCase;
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestRunFinished.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestRunFinished.java
index 6facfa8398..277a64cc6c 100644
--- a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestRunFinished.java
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/TestRunFinished.java
@@ -1,6 +1,7 @@
package io.cucumber.plugin.event;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import java.time.Instant;
import java.util.Objects;
@@ -8,7 +9,7 @@
@API(status = API.Status.STABLE)
public final class TestRunFinished extends TimeStampedEvent {
- private final Result result;
+ private final @Nullable Result result;
@Deprecated
public TestRunFinished(Instant timeInstant) {
@@ -21,7 +22,7 @@ public TestRunFinished(Instant timeInstant, Result result) {
this.result = Objects.requireNonNull(result);
}
- public Result getResult() {
+ public @Nullable Result getResult() {
return result;
}
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/event/package-info.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/package-info.java
new file mode 100644
index 0000000000..644055de5d
--- /dev/null
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/event/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.plugin.event;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-plugin/src/main/java/io/cucumber/plugin/package-info.java b/cucumber-plugin/src/main/java/io/cucumber/plugin/package-info.java
new file mode 100644
index 0000000000..6f1ad75054
--- /dev/null
+++ b/cucumber-plugin/src/main/java/io/cucumber/plugin/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.plugin;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-plugin/src/test/java/io/cucumber/plugin/event/NodeTest.java b/cucumber-plugin/src/test/java/io/cucumber/plugin/event/NodeTest.java
index b84298de06..dbdd026e90 100644
--- a/cucumber-plugin/src/test/java/io/cucumber/plugin/event/NodeTest.java
+++ b/cucumber-plugin/src/test/java/io/cucumber/plugin/event/NodeTest.java
@@ -1,5 +1,6 @@
package io.cucumber.plugin.event;
+import org.jspecify.annotations.NullUnmarked;
import org.junit.jupiter.api.Test;
import java.net.URI;
@@ -11,6 +12,7 @@
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
+@NullUnmarked
class NodeTest {
private final Node.Example example1 = new Node.Example() {
diff --git a/cucumber-spring/src/main/java/io/cucumber/spring/package-info.java b/cucumber-spring/src/main/java/io/cucumber/spring/package-info.java
index ab6089556a..f02bb4ceb3 100644
--- a/cucumber-spring/src/main/java/io/cucumber/spring/package-info.java
+++ b/cucumber-spring/src/main/java/io/cucumber/spring/package-info.java
@@ -4,4 +4,7 @@
* By including the cucumber-spring on your CLASSPATH
* your step definitions will be instantiated by Spring.
*/
+@NullMarked
package io.cucumber.spring;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cucumber-testng/src/main/java/io/cucumber/testng/package-info.java b/cucumber-testng/src/main/java/io/cucumber/testng/package-info.java
new file mode 100644
index 0000000000..962934b91e
--- /dev/null
+++ b/cucumber-testng/src/main/java/io/cucumber/testng/package-info.java
@@ -0,0 +1,4 @@
+@NullMarked
+package io.cucumber.testng;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/datatable-matchers/pom.xml b/datatable-matchers/pom.xml
index d1886d0e34..ba1424d7e0 100644
--- a/datatable-matchers/pom.xml
+++ b/datatable-matchers/pom.xml
@@ -45,7 +45,13 @@
apiguardian-api${apiguardian-api.version}
-
+
+
+ org.jspecify
+ jspecify
+ 1.0.0
+
+
io.cucumberdatatable
diff --git a/datatable-matchers/src/main/java/io/cucumber/datatable/matchers/package-info.java b/datatable-matchers/src/main/java/io/cucumber/datatable/matchers/package-info.java
new file mode 100644
index 0000000000..16a45eabfa
--- /dev/null
+++ b/datatable-matchers/src/main/java/io/cucumber/datatable/matchers/package-info.java
@@ -0,0 +1,3 @@
+@NullMarked
+package io.cucumber.datatable.matchers;
+
diff --git a/datatable/pom.xml b/datatable/pom.xml
index a0437bb537..d559a0f0ff 100644
--- a/datatable/pom.xml
+++ b/datatable/pom.xml
@@ -56,6 +56,12 @@
${apiguardian-api.version}
+
+ org.jspecify
+ jspecify
+ 1.0.0
+
+
com.googlecode.java-diff-utilsdiffutils
diff --git a/datatable/src/main/java/io/cucumber/datatable/ConversionRequired.java b/datatable/src/main/java/io/cucumber/datatable/ConversionRequired.java
index 70817c1721..e63b91f507 100644
--- a/datatable/src/main/java/io/cucumber/datatable/ConversionRequired.java
+++ b/datatable/src/main/java/io/cucumber/datatable/ConversionRequired.java
@@ -9,11 +9,13 @@
final class ConversionRequired implements TableConverter {
@Override
+ @SuppressWarnings("TypeParameterUnusedInFormals")
public T convert(DataTable dataTable, Type type) {
return convert(dataTable, type, false);
}
@Override
+ @SuppressWarnings("TypeParameterUnusedInFormals")
public T convert(DataTable dataTable, Type type, boolean transposed) {
throw new CucumberDataTableException(String
.format("Can't convert DataTable to %s. You have to write the conversion for it in this method", type));
diff --git a/datatable/src/main/java/io/cucumber/datatable/CucumberDataTableException.java b/datatable/src/main/java/io/cucumber/datatable/CucumberDataTableException.java
index 3a09d90703..386b344b82 100644
--- a/datatable/src/main/java/io/cucumber/datatable/CucumberDataTableException.java
+++ b/datatable/src/main/java/io/cucumber/datatable/CucumberDataTableException.java
@@ -1,6 +1,7 @@
package io.cucumber.datatable;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import java.lang.reflect.Type;
@@ -13,8 +14,8 @@ public class CucumberDataTableException extends RuntimeException {
super(message);
}
- CucumberDataTableException(String s, Throwable throwable) {
- super(s, throwable);
+ CucumberDataTableException(@Nullable String message, Throwable throwable) {
+ super(message, throwable);
}
static CucumberDataTableException cantConvertTo(Type type, String message) {
@@ -28,7 +29,7 @@ private static CucumberDataTableException cantConvertToMap(Type keyType, Type va
}
static CucumberDataTableException duplicateKeyException(
- Type keyType, Type valueType, K key, V value, V replaced
+ Type keyType, Type valueType, @Nullable K key, @Nullable V value, @Nullable V replaced
) {
return cantConvertToMap(keyType, valueType,
format("Encountered duplicate key %s with values %s and %s", key, replaced, value));
@@ -63,17 +64,17 @@ static CucumberDataTableException keyValueMismatchException(
static CucumberDataTableException keysImplyTableEntryTransformer(Type keyType, Type valueType) {
return cantConvertToMap(keyType, valueType,
- format("The first cell was either blank or you have registered a TableEntryTransformer for the key type.\n"
- +
- "\n" +
- "This requires that there is a TableEntryTransformer for the value type but I couldn't find any.\n"
- +
- "\n" +
- "You can either:\n" +
- "\n" +
- " 1) Use a DataTableType that uses a TableEntryTransformer for %s\n" +
- "\n" +
- " 2) Add a key to the first cell and use a DataTableType that uses a TableEntryTransformer for %s",
+ format(
+ """
+ The first cell was either blank or you have registered a TableEntryTransformer for the key type.
+
+ This requires that there is a TableEntryTransformer for the value type but I couldn't find any.
+
+ You can either:
+
+ 1) Use a DataTableType that uses a TableEntryTransformer for %s
+
+ 2) Add a key to the first cell and use a DataTableType that uses a TableEntryTransformer for %s""",
valueType, keyType));
}
diff --git a/datatable/src/main/java/io/cucumber/datatable/DataTable.java b/datatable/src/main/java/io/cucumber/datatable/DataTable.java
index 67e1e84ed1..d413406339 100644
--- a/datatable/src/main/java/io/cucumber/datatable/DataTable.java
+++ b/datatable/src/main/java/io/cucumber/datatable/DataTable.java
@@ -1,6 +1,7 @@
package io.cucumber.datatable;
import org.apiguardian.api.API;
+import org.jspecify.annotations.Nullable;
import java.io.IOException;
import java.lang.reflect.Type;
@@ -16,6 +17,7 @@
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
+import static java.util.Objects.requireNonNull;
/**
* A m-by-n table of string values. For example:
@@ -29,7 +31,7 @@
* A table is either empty or contains one or more values. As such if a table
* has zero height it must have zero width and vice versa.
*
- * The first row of the the table may be referred to as the table header. The
+ * The first row of the table may be referred to as the table header. The
* remaining cells as the table body.
*
* A table can be converted into an object of an arbitrary type by a
@@ -43,7 +45,7 @@
@API(status = API.Status.STABLE)
public final class DataTable {
- private final List> raw;
+ private final List> raw;
private final TableConverter tableConverter;
/**
@@ -56,13 +58,9 @@ public final class DataTable {
* @param tableConverter to transform the table
* @throws NullPointerException if either raw or tableConverter is null
*/
- private DataTable(List> raw, TableConverter tableConverter) {
- if (raw == null)
- throw new NullPointerException("cells can not be null");
- if (tableConverter == null)
- throw new NullPointerException("tableConverter can not be null");
- this.raw = raw;
- this.tableConverter = tableConverter;
+ private DataTable(List> raw, TableConverter tableConverter) {
+ this.raw = requireNonNull(raw);
+ this.tableConverter = requireNonNull(tableConverter);
}
/**
@@ -76,7 +74,7 @@ private DataTable(List> raw, TableConverter tableConverter) {
* @throws IllegalArgumentException when the table is not rectangular or
* contains null values.
*/
- public static DataTable create(List> raw) {
+ public static DataTable create(List> raw) {
return create(raw, new NoConverterDefined());
}
@@ -91,26 +89,26 @@ public static DataTable create(List> raw) {
* @throws IllegalArgumentException when the table is not rectangular or
* contains null values
*/
- public static DataTable create(List> raw, TableConverter tableConverter) {
+ public static DataTable create(List> raw, TableConverter tableConverter) {
return new DataTable(copy(requireRectangularTable(raw)), tableConverter);
}
- private static List> copy(List> balanced) {
- List> rawCopy = new ArrayList<>(balanced.size());
- for (List row : balanced) {
+ private static List> copy(List> balanced) {
+ List> rawCopy = new ArrayList<>(balanced.size());
+ for (List<@Nullable String> row : balanced) {
// A table without columns is an empty table and has no rows.
if (row.isEmpty()) {
return emptyList();
}
- List rowCopy = new ArrayList<>(row.size());
+ List<@Nullable String> rowCopy = new ArrayList<>(row.size());
rowCopy.addAll(row);
rawCopy.add(unmodifiableList(rowCopy));
}
return unmodifiableList(rawCopy);
}
- private static List> requireRectangularTable(List> table) {
+ private static List> requireRectangularTable(List> table) {
int columns = table.isEmpty() ? 0 : table.get(0).size();
for (List row : table) {
if (columns != row.size()) {
@@ -173,7 +171,7 @@ public void unorderedDiff(DataTable actual) throws TableDiffException {
*
* @return the values of the table
*/
- public List values() {
+ public List<@Nullable String> values() {
return new ListView();
}
@@ -183,7 +181,7 @@ public List values() {
* @return a list of strings
* @see TableConverter#toList(DataTable, Type)
*/
- public List asList() {
+ public List<@Nullable String> asList() {
return asList(String.class);
}
@@ -195,7 +193,7 @@ public List asList() {
* @return a list of objects
* @see TableConverter#toList(DataTable, Type)
*/
- public List asList(Class itemType) {
+ public List<@Nullable T> asList(Class itemType) {
return tableConverter.toList(this, itemType);
}
@@ -207,17 +205,17 @@ public List asList(Class itemType) {
* @return a list of objects
* @see TableConverter#toList(DataTable, Type)
*/
- public List asList(Type itemType) {
+ public List<@Nullable T> asList(Type itemType) {
return tableConverter.toList(this, itemType);
}
/**
* Converts the table to a list of lists of {@code String}s.
*
- * @return a list of list of strings
+ * @return a list-of-list-of strings
* @see TableConverter#toLists(DataTable, Type)
*/
- public List> asLists() {
+ public List> asLists() {
return asLists(String.class);
}
@@ -229,7 +227,7 @@ public List> asLists() {
* @return a list of list of objects
* @see TableConverter#toLists(DataTable, Type)
*/
- public List> asLists(Class itemType) {
+ public List> asLists(Class itemType) {
return tableConverter.toLists(this, itemType);
}
@@ -241,7 +239,7 @@ public List> asLists(Class itemType) {
* @return a list of list of objects
* @see TableConverter#toLists(DataTable, Type)
*/
- public List> asLists(Type itemType) {
+ public List> asLists(Type itemType) {
return tableConverter.toLists(this, itemType);
}
@@ -255,7 +253,7 @@ public List> asLists(Type itemType) {
* @return a map
* @see TableConverter#toMap(DataTable, Type, Type)
*/
- public Map asMap() {
+ public Map<@Nullable String, @Nullable String> asMap() {
return asMap(String.class, String.class);
}
@@ -274,7 +272,7 @@ public Map asMap() {
* @return a map
* @see TableConverter#toMap(DataTable, Type, Type)
*/
- public Map asMap(Class keyType, Class valueType) {
+ public Map<@Nullable K, @Nullable V> asMap(Class keyType, Class valueType) {
return tableConverter.toMap(this, keyType, valueType);
}
@@ -293,7 +291,7 @@ public Map asMap(Class keyType, Class valueType) {
* @return a map
* @see TableConverter#toMap(DataTable, Type, Type)
*/
- public Map asMap(Type keyType, Type valueType) {
+ public Map<@Nullable K, @Nullable V> asMap(Type keyType, Type valueType) {
return tableConverter.toMap(this, keyType, valueType);
}
@@ -303,16 +301,16 @@ public Map asMap(Type keyType, Type valueType) {
*
* @return a view of the entries in a table.
*/
- public List