From 263db337e7c13c33172bd30fb240c05a69b43c10 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Thu, 17 Jul 2025 21:36:49 +0200 Subject: [PATCH 1/8] java: Use Integers in addition to Longs Currently, messages are a bit cumbersome to use in combination with Java. The generated code currently uses long values where Java would use integers. This leads to some silly code: ```java lines.add((int) (long) location.getLine()); ``` Unfortunately, long values are needed for the timestamp and duration. So simply replacing longs with integers wouldn't work. By specifying some upper bounds the code generation can make a more informed choice about the size of number to use. The choice for 2^31 - 1 is somewhat arbitrary but matches the maximum length of strings in Java and .Net. In practice, I would expect Gherkin documents to have a much more reasonable length though. --- codegen/generators/base.rb | 16 ++-- codegen/generators/cpp.rb | 4 +- codegen/generators/dotnet.rb | 4 +- codegen/generators/go.rb | 4 +- codegen/generators/java.rb | 20 +++-- codegen/generators/markdown.rb | 4 +- codegen/generators/perl.rb | 4 +- codegen/generators/php.rb | 8 +- codegen/generators/python.rb | 14 +-- codegen/generators/ruby.rb | 4 +- codegen/generators/typescript.rb | 4 +- .../io/cucumber/messages/types/Group.java | 6 +- .../io/cucumber/messages/types/Location.java | 12 +-- jsonschema/src/Attachment.json | 10 +-- jsonschema/src/Duration.json | 4 +- jsonschema/src/GherkinDocument.json | 12 +-- jsonschema/src/Location.json | 10 ++- jsonschema/src/Meta.json | 4 +- jsonschema/src/Pickle.json | 10 +-- jsonschema/src/Source.json | 2 +- jsonschema/src/SourceReference.json | 2 +- jsonschema/src/TestCase.json | 10 ++- jsonschema/src/TestCaseStarted.json | 7 +- jsonschema/src/Timestamp.json | 4 +- perl/lib/Cucumber/Messages.pm | 78 ++++++---------- python/src/cucumber_messages/_messages.py | 90 ++++++------------- ruby/lib/cucumber/messages/attachment.rb | 15 ++-- ruby/lib/cucumber/messages/comment.rb | 3 +- ruby/lib/cucumber/messages/feature_child.rb | 3 +- .../lib/cucumber/messages/gherkin_document.rb | 6 +- ruby/lib/cucumber/messages/location.rb | 3 +- ruby/lib/cucumber/messages/meta.rb | 6 +- ruby/lib/cucumber/messages/pickle.rb | 9 +- ruby/lib/cucumber/messages/pickle_step.rb | 3 +- ruby/lib/cucumber/messages/pickle_tag.rb | 3 +- ruby/lib/cucumber/messages/rule_child.rb | 3 +- ruby/lib/cucumber/messages/source.rb | 3 +- .../lib/cucumber/messages/source_reference.rb | 3 +- .../cucumber/messages/step_match_argument.rb | 6 +- ruby/lib/cucumber/messages/tag.rb | 3 +- .../cucumber/messages/test_case_started.rb | 6 +- ruby/lib/cucumber/messages/test_step.rb | 3 +- 42 files changed, 176 insertions(+), 249 deletions(-) diff --git a/codegen/generators/base.rb b/codegen/generators/base.rb index 9f9a8468..5a0cc2c7 100644 --- a/codegen/generators/base.rb +++ b/codegen/generators/base.rb @@ -105,25 +105,23 @@ def property_type_from_ref(ref) class_name(ref) end - def property_type_from_type(parent_type_name, property_name, property, type:) + def property_type_from_type(parent_type_name, property_name, property) + type = property['type'] return array_type_for(type_for(parent_type_name, nil, property['items'])) if type == 'array' + return property_type_from_enum(enum_name(parent_type_name, property_name, property['enum'])) if property['enum'] - unless language_translations_for_data_types.key?(type) + property = select_language_translations_for_data_types(type, property) + unless property raise "No type mapping for JSONSchema type #{type}. Schema:\n#{JSON.pretty_generate(property)}" end - - if property['enum'] - property_type_from_enum(enum_name(parent_type_name, property_name, property['enum'])) - else - language_translations_for_data_types.fetch(type) - end + property end def type_for(parent_type_name, property_name, property) if property['$ref'] property_type_from_ref(property['$ref']) elsif property['type'] - property_type_from_type(parent_type_name, property_name, property, type: property['type']) + property_type_from_type(parent_type_name, property_name, property) else # Inline schema (not supported) raise "Property #{property_name} did not define 'type' or '$ref'" diff --git a/codegen/generators/cpp.rb b/codegen/generators/cpp.rb index cb80a86f..95ac3cb0 100644 --- a/codegen/generators/cpp.rb +++ b/codegen/generators/cpp.rb @@ -21,12 +21,12 @@ def format_description(raw_description, indent_string: '') private - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'std::size_t', 'string' => 'std::string', 'boolean' => 'bool' - } + }.fetch(type) end end end diff --git a/codegen/generators/dotnet.rb b/codegen/generators/dotnet.rb index 1e164c55..9d25fa87 100644 --- a/codegen/generators/dotnet.rb +++ b/codegen/generators/dotnet.rb @@ -21,12 +21,12 @@ def format_description(raw_description, indent_string: '') private - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'long', 'string' => 'string', 'boolean' => 'bool' - } + }.fetch(type) end end end diff --git a/codegen/generators/go.rb b/codegen/generators/go.rb index 659d2b49..bbeb3b5a 100644 --- a/codegen/generators/go.rb +++ b/codegen/generators/go.rb @@ -14,12 +14,12 @@ def property_type_from_ref(ref) private - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'int64', 'string' => 'string', 'boolean' => 'bool' - } + }.fetch(type) end end end diff --git a/codegen/generators/java.rb b/codegen/generators/java.rb index 6df09797..eb207af3 100644 --- a/codegen/generators/java.rb +++ b/codegen/generators/java.rb @@ -21,12 +21,20 @@ def format_description(raw_description, indent_string: '') private - def language_translations_for_data_types - { - 'integer' => 'Long', - 'string' => 'String', - 'boolean' => 'Boolean' - } + def select_language_translations_for_data_types(type, property) + if type == 'integer' + if property['maximum'] and property['maximum'] <= 2147483647 + 'Integer' + else + 'Long' + end + elsif type == 'string' + 'String' + elsif type == 'boolean' + 'Boolean' + else + nil + end end end end diff --git a/codegen/generators/markdown.rb b/codegen/generators/markdown.rb index f7389e25..94c79c44 100644 --- a/codegen/generators/markdown.rb +++ b/codegen/generators/markdown.rb @@ -20,12 +20,12 @@ def property_type_from_ref(ref) private - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'integer', 'string' => 'string', 'boolean' => 'boolean' - } + }.fetch(type) end end end diff --git a/codegen/generators/perl.rb b/codegen/generators/perl.rb index ff38bc58..11a59ae5 100644 --- a/codegen/generators/perl.rb +++ b/codegen/generators/perl.rb @@ -39,12 +39,12 @@ def default_value_for_string(property_name, enum) end end - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'number', 'string' => 'string', 'boolean' => 'boolean' - } + }[type] end end end diff --git a/codegen/generators/php.rb b/codegen/generators/php.rb index 83984775..08bf852b 100644 --- a/codegen/generators/php.rb +++ b/codegen/generators/php.rb @@ -53,11 +53,11 @@ def nullable?(property_name, schema) end def scalar?(property) - property.key?('type') && language_translations_for_data_types.key?(property['type']) + property.key?('type') && select_language_translations_for_data_types(property['type'], property) end def scalar_type_for(property) - language_translations_for_data_types[property['type']] + select_language_translations_for_data_types(property['type'], property) end private @@ -68,12 +68,12 @@ def default_value(class_name, property_name, property, schema) super(class_name, property_name, property) end - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'string' => 'string', 'integer' => 'int', 'boolean' => 'bool' - } + }[type] end def non_nullable_non_scalar_constructor(parent_type, property, property_name, schema, source) diff --git a/codegen/generators/python.rb b/codegen/generators/python.rb index ccb6a727..54257ba8 100644 --- a/codegen/generators/python.rb +++ b/codegen/generators/python.rb @@ -63,6 +63,12 @@ def format_description(raw_description, indent_string: ' ') %("""\n#{lines.join("\n")}\n#{indent_string}""") end + def select_language_translations_for_data_types(type, property) + language_translations_for_data_types[type] + end + + private + def language_translations_for_data_types { 'integer' => 'int', @@ -71,9 +77,7 @@ def language_translations_for_data_types 'array' => 'list' } end - - private - + def default_value(parent_type_name, property_name, property) if property['type'] == 'string' default_value_for_string(parent_type_name, property_name, property) @@ -109,10 +113,6 @@ def enum_name(parent_type_name, property_name, enum) end end - def property_type_from_ref(ref) - class_name(ref) - end - def class_name(ref) return ref if language_translations_for_data_types.values.include?(ref) diff --git a/codegen/generators/ruby.rb b/codegen/generators/ruby.rb index 59d99bfa..86f642c9 100644 --- a/codegen/generators/ruby.rb +++ b/codegen/generators/ruby.rb @@ -39,12 +39,12 @@ def default_value_for_string(parent_type_name, property_name, property) end end - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'number', 'string' => 'string', 'boolean' => 'boolean' - } + }[type] end def line_as_comment(line) diff --git a/codegen/generators/typescript.rb b/codegen/generators/typescript.rb index a46c241f..da58dd02 100644 --- a/codegen/generators/typescript.rb +++ b/codegen/generators/typescript.rb @@ -10,12 +10,12 @@ def array_type_for(type_name) private - def language_translations_for_data_types + def select_language_translations_for_data_types(type, property) { 'integer' => 'number', 'string' => 'string', 'boolean' => 'boolean' - } + }[type] end end end diff --git a/java/src/generated/java/io/cucumber/messages/types/Group.java b/java/src/generated/java/io/cucumber/messages/types/Group.java index 45ada355..44eb6624 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Group.java +++ b/java/src/generated/java/io/cucumber/messages/types/Group.java @@ -15,12 +15,12 @@ @SuppressWarnings("unused") public final class Group { private final java.util.List children; - private final Long start; + private final Integer start; private final String value; public Group( java.util.List children, - Long start, + Integer start, String value ) { this.children = unmodifiableList(new ArrayList<>(requireNonNull(children, "Group.children cannot be null"))); @@ -32,7 +32,7 @@ public java.util.List getChildren() { return children; } - public Optional getStart() { + public Optional getStart() { return Optional.ofNullable(start); } diff --git a/java/src/generated/java/io/cucumber/messages/types/Location.java b/java/src/generated/java/io/cucumber/messages/types/Location.java index 19abec37..65879720 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Location.java +++ b/java/src/generated/java/io/cucumber/messages/types/Location.java @@ -16,22 +16,22 @@ // Generated code @SuppressWarnings("unused") public final class Location { - private final Long line; - private final Long column; + private final Integer line; + private final Integer column; public Location( - Long line, - Long column + Integer line, + Integer column ) { this.line = requireNonNull(line, "Location.line cannot be null"); this.column = column; } - public Long getLine() { + public Integer getLine() { return line; } - public Optional getColumn() { + public Optional getColumn() { return Optional.ofNullable(column); } diff --git a/jsonschema/src/Attachment.json b/jsonschema/src/Attachment.json index 5ba885e5..0f9f8941 100644 --- a/jsonschema/src/Attachment.json +++ b/jsonschema/src/Attachment.json @@ -10,11 +10,11 @@ ], "properties": { "body": { - "description": "*\n The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment\n is simply the string. If it's `BASE64`, the string should be Base64 decoded to\n obtain the attachment.", + "description": "The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment\n is simply the string. If it's `BASE64`, the string should be Base64 decoded to\n obtain the attachment.", "type": "string" }, "contentEncoding": { - "description": "*\n Whether to interpret `body` \"as-is\" (IDENTITY) or if it needs to be Base64-decoded (BASE64).\n\n Content encoding is *not* determined by the media type, but rather by the type\n of the object being attached:\n\n - string: IDENTITY\n - byte array: BASE64\n - stream: BASE64", + "description": "Whether to interpret `body` \"as-is\" (IDENTITY) or if it needs to be Base64-decoded (BASE64).\n\n Content encoding is *not* determined by the media type, but rather by the type\n of the object being attached:\n\n - string: IDENTITY\n - byte array: BASE64\n - stream: BASE64", "enum": [ "IDENTITY", "BASE64" @@ -22,11 +22,11 @@ "type": "string" }, "fileName": { - "description": "*\n Suggested file name of the attachment. (Provided by the user as an argument to `attach`)", + "description": "Suggested file name of the attachment. (Provided by the user as an argument to `attach`)", "type": "string" }, "mediaType": { - "description": "*\n The media type of the data. This can be any valid\n [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml)\n as well as Cucumber-specific media types such as `text/x.cucumber.gherkin+plain`\n and `text/x.cucumber.stacktrace+plain`", + "description": "The media type of the data. This can be any valid\n [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml)\n as well as Cucumber-specific media types such as `text/x.cucumber.gherkin+plain`\n and `text/x.cucumber.stacktrace+plain`", "type": "string" }, "source": { @@ -41,7 +41,7 @@ "type": "string" }, "url": { - "description": "*\n A URL where the attachment can be retrieved. This field should not be set by Cucumber.\n It should be set by a program that reads a message stream and does the following for\n each Attachment message:\n\n - Writes the body (after base64 decoding if necessary) to a new file.\n - Sets `body` and `contentEncoding` to `null`\n - Writes out the new attachment message\n\n This will result in a smaller message stream, which can improve performance and\n reduce bandwidth of message consumers. It also makes it easier to process and download attachments\n separately from reports.", + "description": "A URL where the attachment can be retrieved. This field should not be set by Cucumber.\n It should be set by a program that reads a message stream and does the following for\n each Attachment message:\n\n - Writes the body (after base64 decoding if necessary) to a new file.\n - Sets `body` and `contentEncoding` to `null`\n - Writes out the new attachment message\n\n This will result in a smaller message stream, which can improve performance and\n reduce bandwidth of message consumers. It also makes it easier to process and download attachments\n separately from reports.", "type": "string" }, "testRunStartedId": { diff --git a/jsonschema/src/Duration.json b/jsonschema/src/Duration.json index 7f929228..c684fc3f 100644 --- a/jsonschema/src/Duration.json +++ b/jsonschema/src/Duration.json @@ -13,7 +13,9 @@ }, "nanos": { "description": "Non-negative fractions of a second at nanosecond resolution. Negative\n second values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", - "type": "integer" + "type": "integer", + "minimum": 0, + "maximum": 9999999999 } }, "type": "object" diff --git a/jsonschema/src/GherkinDocument.json b/jsonschema/src/GherkinDocument.json index 911644a6..a063f8b6 100644 --- a/jsonschema/src/GherkinDocument.json +++ b/jsonschema/src/GherkinDocument.json @@ -44,7 +44,7 @@ "Comment": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n A comment in a Gherkin document", + "description": "A comment in a Gherkin document", "required": [ "location", "text" @@ -204,7 +204,7 @@ "FeatureChild": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n A child node of a `Feature` node", + "description": "A child node of a `Feature` node", "properties": { "rule": { "$ref": "#/definitions/Rule" @@ -266,7 +266,7 @@ "RuleChild": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n A child node of a `Rule` node", + "description": "A child node of a `Rule` node", "properties": { "background": { "$ref": "#/definitions/Background" @@ -428,7 +428,7 @@ "Tag": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n A tag", + "description": "A tag", "required": [ "location", "name", @@ -451,13 +451,13 @@ "type": "object" } }, - "description": "*\n The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document.\n Cucumber implementations should *not* depend on `GherkinDocument` or any of its\n children for execution - use [Pickle](#io.cucumber.messages.Pickle) instead.\n\n The only consumers of `GherkinDocument` should only be formatters that produce\n \"rich\" output, resembling the original Gherkin document.", + "description": "The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document.\n Cucumber implementations should *not* depend on `GherkinDocument` or any of its\n children for execution - use [Pickle](#io.cucumber.messages.Pickle) instead.\n\n The only consumers of `GherkinDocument` should only be formatters that produce\n \"rich\" output, resembling the original Gherkin document.", "required": [ "comments" ], "properties": { "uri": { - "description": "*\n The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)\n of the source, typically a file path relative to the root directory", + "description": "The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)\n of the source, typically a file path relative to the root directory", "type": "string" }, "feature": { diff --git a/jsonschema/src/Location.json b/jsonschema/src/Location.json index d1a0fb52..0e700cac 100644 --- a/jsonschema/src/Location.json +++ b/jsonschema/src/Location.json @@ -2,13 +2,17 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "Location.json", "additionalProperties": false, - "description": "*\n Points to a line and a column in a text file", + "description": "Points to a line and a column in a text file", "properties": { "line": { - "type": "integer" + "type": "integer", + "minimum": 0, + "maximum": 2147483647 }, "column": { - "type": "integer" + "type": "integer", + "minimum": 1, + "maximum": 2147483647 } }, "required": [ diff --git a/jsonschema/src/Meta.json b/jsonschema/src/Meta.json index 4fce192c..3ca8bb37 100644 --- a/jsonschema/src/Meta.json +++ b/jsonschema/src/Meta.json @@ -71,7 +71,7 @@ "type": "object" } }, - "description": "*\n This message contains meta information about the environment. Consumers can use\n this for various purposes.", + "description": "This message contains meta information about the environment. Consumers can use\n this for various purposes.", "required": [ "protocolVersion", "implementation", @@ -81,7 +81,7 @@ ], "properties": { "protocolVersion": { - "description": "*\n The [SEMVER](https://semver.org/) version number of the protocol", + "description": "The [SEMVER](https://semver.org/) version number of the protocol", "type": "string" }, "implementation": { diff --git a/jsonschema/src/Pickle.json b/jsonschema/src/Pickle.json index 10877afe..75e514b1 100644 --- a/jsonschema/src/Pickle.json +++ b/jsonschema/src/Pickle.json @@ -21,7 +21,7 @@ "PickleStep": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n An executable step", + "description": "An executable step", "required": [ "astNodeIds", "id", @@ -120,7 +120,7 @@ "PickleTag": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n A tag", + "description": "A tag", "required": [ "name", "astNodeId" @@ -149,7 +149,7 @@ ], "properties": { "id": { - "description": "*\n A unique id for the pickle", + "description": "A unique id for the pickle", "type": "string" }, "uri": { @@ -172,14 +172,14 @@ "type": "array" }, "tags": { - "description": "*\n One or more tags. If this pickle is constructed from a Gherkin document,\n It includes inherited tags from the `Feature` as well.", + "description": "One or more tags. If this pickle is constructed from a Gherkin document,\n It includes inherited tags from the `Feature` as well.", "items": { "$ref": "#/definitions/PickleTag" }, "type": "array" }, "astNodeIds": { - "description": "*\n Points to the AST node locations of the pickle. The last one represents the unique\n id of the pickle. A pickle constructed from `Examples` will have the first\n id originating from the `Scenario` AST node, and the second from the `TableRow` AST node.", + "description": "Points to the AST node locations of the pickle. The last one represents the unique\n id of the pickle. A pickle constructed from `Examples` will have the first\n id originating from the `Scenario` AST node, and the second from the `TableRow` AST node.", "items": { "type": "string" }, diff --git a/jsonschema/src/Source.json b/jsonschema/src/Source.json index 61ca46ee..ee7fc78b 100644 --- a/jsonschema/src/Source.json +++ b/jsonschema/src/Source.json @@ -10,7 +10,7 @@ ], "properties": { "uri": { - "description": "*\n The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)\n of the source, typically a file path relative to the root directory", + "description": "The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)\n of the source, typically a file path relative to the root directory", "type": "string" }, "data": { diff --git a/jsonschema/src/SourceReference.json b/jsonschema/src/SourceReference.json index 5e9f46a5..08872ea2 100644 --- a/jsonschema/src/SourceReference.json +++ b/jsonschema/src/SourceReference.json @@ -47,7 +47,7 @@ "type": "object" } }, - "description": "*\n Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a\n [Location](#io.cucumber.messages.Location) within that file.", + "description": "Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a\n [Location](#io.cucumber.messages.Location) within that file.", "properties": { "uri": { "type": "string" diff --git a/jsonschema/src/TestCase.json b/jsonschema/src/TestCase.json index 003d9e95..8ac6aab0 100644 --- a/jsonschema/src/TestCase.json +++ b/jsonschema/src/TestCase.json @@ -18,7 +18,9 @@ "type": "array" }, "start": { - "type": "integer" + "type": "integer", + "minimum": 0, + "maximum": 2147483647 }, "value": { "type": "string" @@ -29,14 +31,14 @@ "StepMatchArgument": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n Represents a single argument extracted from a step match and passed to a step definition.\n This is used for the following purposes:\n - Construct an argument to pass to a step definition (possibly through a parameter type transform)\n - Highlight the matched parameter in rich formatters such as the HTML formatter\n\n This message closely matches the `Argument` class in the `cucumber-expressions` library.", + "description": "Represents a single argument extracted from a step match and passed to a step definition.\n This is used for the following purposes:\n - Construct an argument to pass to a step definition (possibly through a parameter type transform)\n - Highlight the matched parameter in rich formatters such as the HTML formatter\n\n This message closely matches the `Argument` class in the `cucumber-expressions` library.", "required": [ "group" ], "properties": { "group": { "$ref": "#/definitions/Group", - "description": "*\n Represents the outermost capture group of an argument. This message closely matches the\n `Group` class in the `cucumber-expressions` library." + "description": "Represents the outermost capture group of an argument. This message closely matches the\n `Group` class in the `cucumber-expressions` library." }, "parameterTypeName": { "type": "string" @@ -63,7 +65,7 @@ "TestStep": { "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "*\n A `TestStep` is derived from either a `PickleStep`\n combined with a `StepDefinition`, or from a `Hook`.", + "description": "A `TestStep` is derived from either a `PickleStep`\n combined with a `StepDefinition`, or from a `Hook`.", "required": [ "id" ], diff --git a/jsonschema/src/TestCaseStarted.json b/jsonschema/src/TestCaseStarted.json index 5800aaa4..8075df4d 100644 --- a/jsonschema/src/TestCaseStarted.json +++ b/jsonschema/src/TestCaseStarted.json @@ -10,11 +10,12 @@ ], "properties": { "attempt": { - "description": "*\n The first attempt should have value 0, and for each retry the value\n should increase by 1.", - "type": "integer" + "description": "The first attempt should have value 0, and for each retry the value\n should increase by 1.", + "type": "integer", + "minimum": 0 }, "id": { - "description": "*\n Because a `TestCase` can be run multiple times (in case of a retry),\n we use this field to group messages relating to the same attempt.", + "description": "Because a `TestCase` can be run multiple times (in case of a retry),\n we use this field to group messages relating to the same attempt.", "type": "string" }, "testCaseId": { diff --git a/jsonschema/src/Timestamp.json b/jsonschema/src/Timestamp.json index d27103b3..a63aa6f7 100644 --- a/jsonschema/src/Timestamp.json +++ b/jsonschema/src/Timestamp.json @@ -13,7 +13,9 @@ }, "nanos": { "description": "Non-negative fractions of a second at nanosecond resolution. Negative\n second values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", - "type": "integer" + "type": "integer", + "minimum": 0, + "maximum": 9999999999 } }, "type": "object" diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm index 8b6ca712..6125a328 100644 --- a/perl/lib/Cucumber/Messages.pm +++ b/perl/lib/Cucumber/Messages.pm @@ -101,8 +101,7 @@ sub _types { =head4 body -* - The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment +The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment is simply the string. If it's `BASE64`, the string should be Base64 decoded to obtain the attachment. =cut @@ -116,8 +115,7 @@ has body => =head4 content_encoding -* - Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64). +Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64). Content encoding is *not* determined by the media type, but rather by the type of the object being attached: @@ -153,8 +151,7 @@ has content_encoding => =head4 file_name -* - Suggested file name of the attachment. (Provided by the user as an argument to `attach`) +Suggested file name of the attachment. (Provided by the user as an argument to `attach`) =cut has file_name => @@ -164,8 +161,7 @@ has file_name => =head4 media_type -* - The media type of the data. This can be any valid +The media type of the data. This can be any valid [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml) as well as Cucumber-specific media types such as `text/x.cucumber.gherkin+plain` and `text/x.cucumber.stacktrace+plain` @@ -210,8 +206,7 @@ has test_step_id => =head4 url -* - A URL where the attachment can be retrieved. This field should not be set by Cucumber. +A URL where the attachment can be retrieved. This field should not be set by Cucumber. It should be set by a program that reads a message stream and does the following for each Attachment message: @@ -649,8 +644,7 @@ package Cucumber::Messages::GherkinDocument { Represents the GherkinDocument message in Cucumber's L. -* - The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. +The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. Cucumber implementations should *not* depend on `GherkinDocument` or any of its children for execution - use [Pickle](#io.cucumber.messages.Pickle) instead. @@ -682,8 +676,7 @@ sub _types { =head4 uri -* - The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) +The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the source, typically a file path relative to the root directory =cut @@ -836,8 +829,7 @@ package Cucumber::Messages::Comment { Represents the Comment message in Cucumber's L. -* - A comment in a Gherkin document +A comment in a Gherkin document =head3 ATTRIBUTES @@ -1297,8 +1289,7 @@ package Cucumber::Messages::FeatureChild { Represents the FeatureChild message in Cucumber's L. -* - A child node of a `Feature` node +A child node of a `Feature` node =head3 ATTRIBUTES @@ -1488,8 +1479,7 @@ package Cucumber::Messages::RuleChild { Represents the RuleChild message in Cucumber's L. -* - A child node of a `Rule` node +A child node of a `Rule` node =head3 ATTRIBUTES @@ -1956,8 +1946,7 @@ package Cucumber::Messages::Tag { Represents the Tag message in Cucumber's L. -* - A tag +A tag =head3 ATTRIBUTES @@ -2150,8 +2139,7 @@ package Cucumber::Messages::Location { Represents the Location message in Cucumber's L. -* - Points to a line and a column in a text file +Points to a line and a column in a text file =head3 ATTRIBUTES @@ -2208,8 +2196,7 @@ package Cucumber::Messages::Meta { Represents the Meta message in Cucumber's L. -* - This message contains meta information about the environment. Consumers can use +This message contains meta information about the environment. Consumers can use this for various purposes. =head3 ATTRIBUTES @@ -2240,8 +2227,7 @@ sub _types { =head4 protocol_version -* - The [SEMVER](https://semver.org/) version number of the protocol +The [SEMVER](https://semver.org/) version number of the protocol =cut has protocol_version => @@ -2749,8 +2735,7 @@ sub _types { =head4 id -* - A unique id for the pickle +A unique id for the pickle =cut has id => @@ -2810,8 +2795,7 @@ has steps => =head4 tags -* - One or more tags. If this pickle is constructed from a Gherkin document, +One or more tags. If this pickle is constructed from a Gherkin document, It includes inherited tags from the `Feature` as well. =cut @@ -2824,8 +2808,7 @@ has tags => =head4 ast_node_ids -* - Points to the AST node locations of the pickle. The last one represents the unique +Points to the AST node locations of the pickle. The last one represents the unique id of the pickle. A pickle constructed from `Examples` will have the first id originating from the `Scenario` AST node, and the second from the `TableRow` AST node. =cut @@ -2905,8 +2888,7 @@ package Cucumber::Messages::PickleStep { Represents the PickleStep message in Cucumber's L. -* - An executable step +An executable step =head3 ATTRIBUTES @@ -3219,8 +3201,7 @@ package Cucumber::Messages::PickleTag { Represents the PickleTag message in Cucumber's L. -* - A tag +A tag =head3 ATTRIBUTES @@ -3309,8 +3290,7 @@ sub _types { =head4 uri -* - The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) +The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the source, typically a file path relative to the root directory =cut @@ -3374,8 +3354,7 @@ package Cucumber::Messages::SourceReference { Represents the SourceReference message in Cucumber's L. -* - Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a +Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a [Location](#io.cucumber.messages.Location) within that file. =head3 ATTRIBUTES @@ -3899,8 +3878,7 @@ package Cucumber::Messages::StepMatchArgument { Represents the StepMatchArgument message in Cucumber's L. -* - Represents a single argument extracted from a step match and passed to a step definition. +Represents a single argument extracted from a step match and passed to a step definition. This is used for the following purposes: - Construct an argument to pass to a step definition (possibly through a parameter type transform) - Highlight the matched parameter in rich formatters such as the HTML formatter @@ -3931,8 +3909,7 @@ sub _types { =head4 group -* - Represents the outermost capture group of an argument. This message closely matches the +Represents the outermost capture group of an argument. This message closely matches the `Group` class in the `cucumber-expressions` library. =cut @@ -4010,8 +3987,7 @@ package Cucumber::Messages::TestStep { Represents the TestStep message in Cucumber's L. -* - A `TestStep` is derived from either a `PickleStep` +A `TestStep` is derived from either a `PickleStep` combined with a `StepDefinition`, or from a `Hook`. =head3 ATTRIBUTES @@ -4205,8 +4181,7 @@ sub _types { =head4 attempt -* - The first attempt should have value 0, and for each retry the value +The first attempt should have value 0, and for each retry the value should increase by 1. =cut @@ -4219,8 +4194,7 @@ has attempt => =head4 id -* - Because a `TestCase` can be run multiple times (in case of a retry), +Because a `TestCase` can be run multiple times (in case of a retry), we use this field to group messages relating to the same attempt. =cut diff --git a/python/src/cucumber_messages/_messages.py b/python/src/cucumber_messages/_messages.py index 1e2ad28c..cd27b8b3 100644 --- a/python/src/cucumber_messages/_messages.py +++ b/python/src/cucumber_messages/_messages.py @@ -26,16 +26,14 @@ class Attachment: """ body: str """ - * - The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment + The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment is simply the string. If it's `BASE64`, the string should be Base64 decoded to obtain the attachment. """ content_encoding: AttachmentContentEncoding """ - * - Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64). + Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64). Content encoding is *not* determined by the media type, but rather by the type of the object being attached: @@ -47,19 +45,13 @@ class Attachment: media_type: str """ - * - The media type of the data. This can be any valid + The media type of the data. This can be any valid [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml) as well as Cucumber-specific media types such as `text/x.cucumber.gherkin+plain` and `text/x.cucumber.stacktrace+plain` """ - file_name: Optional[str] = None - """ - * - Suggested file name of the attachment. (Provided by the user as an argument to `attach`) - """ - + file_name: Optional[str] = None # Suggested file name of the attachment. (Provided by the user as an argument to `attach`) source: Optional[Source] = None test_case_started_id: Optional[str] = None # The identifier of the test case attempt if the attachment was created during the execution of a test step test_run_hook_started_id: Optional[str] = None # The identifier of the test run hook execution if the attachment was created during the execution of a test run hook @@ -68,8 +60,7 @@ class Attachment: timestamp: Optional[Timestamp] = None # When the attachment was created url: Optional[str] = None """ - * - A URL where the attachment can be retrieved. This field should not be set by Cucumber. + A URL where the attachment can be retrieved. This field should not be set by Cucumber. It should be set by a program that reads a message stream and does the following for each Attachment message: @@ -146,8 +137,7 @@ class Exception: @dataclass class GherkinDocument: """ - * - The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. + The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. Cucumber implementations should *not* depend on `GherkinDocument` or any of its children for execution - use [Pickle](#io.cucumber.messages.Pickle) instead. @@ -158,8 +148,7 @@ class GherkinDocument: feature: Optional[Feature] = None uri: Optional[str] = None """ - * - The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) + The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the source, typically a file path relative to the root directory """ @@ -178,8 +167,7 @@ class Background: @dataclass class Comment: """ - * - A comment in a Gherkin document + A comment in a Gherkin document """ location: Location # The location of the comment text: str # The text of the comment @@ -225,8 +213,7 @@ class Feature: @dataclass class FeatureChild: """ - * - A child node of a `Feature` node + A child node of a `Feature` node """ background: Optional[Background] = None rule: Optional[Rule] = None @@ -247,8 +234,7 @@ class Rule: @dataclass class RuleChild: """ - * - A child node of a `Rule` node + A child node of a `Rule` node """ background: Optional[Background] = None scenario: Optional[Scenario] = None @@ -302,8 +288,7 @@ class TableRow: @dataclass class Tag: """ - * - A tag + A tag """ id: str # Unique ID to be able to reference the Tag from PickleTag location: Location # Location of the tag @@ -322,8 +307,7 @@ class Hook: @dataclass class Location: """ - * - Points to a line and a column in a text file + Points to a line and a column in a text file """ line: int column: Optional[int] = None @@ -332,19 +316,13 @@ class Location: @dataclass class Meta: """ - * - This message contains meta information about the environment. Consumers can use + This message contains meta information about the environment. Consumers can use this for various purposes. """ cpu: Product # 386, arm, amd64 etc implementation: Product # SpecFlow, Cucumber-JVM, Cucumber.js, Cucumber-Ruby, Behat etc. os: Product # Windows, Linux, MacOS etc - protocol_version: str - """ - * - The [SEMVER](https://semver.org/) version number of the protocol - """ - + protocol_version: str # The [SEMVER](https://semver.org/) version number of the protocol runtime: Product # Java, Ruby, Node.js etc ci: Optional[Ci] = None @@ -416,25 +394,18 @@ class Pickle: """ ast_node_ids: list[str] """ - * - Points to the AST node locations of the pickle. The last one represents the unique + Points to the AST node locations of the pickle. The last one represents the unique id of the pickle. A pickle constructed from `Examples` will have the first id originating from the `Scenario` AST node, and the second from the `TableRow` AST node. """ - id: str - """ - * - A unique id for the pickle - """ - + id: str # A unique id for the pickle language: str # The language of the pickle name: str # The name of the pickle steps: list[PickleStep] # One or more steps tags: list[PickleTag] """ - * - One or more tags. If this pickle is constructed from a Gherkin document, + One or more tags. If this pickle is constructed from a Gherkin document, It includes inherited tags from the `Feature` as well. """ @@ -450,8 +421,7 @@ class PickleDocString: @dataclass class PickleStep: """ - * - An executable step + An executable step """ ast_node_ids: list[str] """ @@ -498,8 +468,7 @@ class PickleTableRow: @dataclass class PickleTag: """ - * - A tag + A tag """ ast_node_id: str # Points to the AST node this was created from name: str @@ -522,8 +491,7 @@ class Source: uri: str """ - * - The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) + The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) of the source, typically a file path relative to the root directory """ @@ -532,8 +500,7 @@ class Source: @dataclass class SourceReference: """ - * - Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a + Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a [Location](#io.cucumber.messages.Location) within that file. """ java_method: Optional[JavaMethod] = None @@ -593,8 +560,7 @@ class Group: @dataclass class StepMatchArgument: """ - * - Represents a single argument extracted from a step match and passed to a step definition. + Represents a single argument extracted from a step match and passed to a step definition. This is used for the following purposes: - Construct an argument to pass to a step definition (possibly through a parameter type transform) - Highlight the matched parameter in rich formatters such as the HTML formatter @@ -603,8 +569,7 @@ class StepMatchArgument: """ group: Group """ - * - Represents the outermost capture group of an argument. This message closely matches the + Represents the outermost capture group of an argument. This message closely matches the `Group` class in the `cucumber-expressions` library. """ @@ -619,8 +584,7 @@ class StepMatchArgumentsList: @dataclass class TestStep: """ - * - A `TestStep` is derived from either a `PickleStep` + A `TestStep` is derived from either a `PickleStep` combined with a `StepDefinition`, or from a `Hook`. """ id: str @@ -647,15 +611,13 @@ class TestCaseFinished: class TestCaseStarted: attempt: int """ - * - The first attempt should have value 0, and for each retry the value + The first attempt should have value 0, and for each retry the value should increase by 1. """ id: str """ - * - Because a `TestCase` can be run multiple times (in case of a retry), + Because a `TestCase` can be run multiple times (in case of a retry), we use this field to group messages relating to the same attempt. """ diff --git a/ruby/lib/cucumber/messages/attachment.rb b/ruby/lib/cucumber/messages/attachment.rb index e81cae40..0b275c84 100644 --- a/ruby/lib/cucumber/messages/attachment.rb +++ b/ruby/lib/cucumber/messages/attachment.rb @@ -22,16 +22,14 @@ module Messages ## class Attachment < Message ## - # * - # The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment + # The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment # is simply the string. If it's `BASE64`, the string should be Base64 decoded to # obtain the attachment. ## attr_reader :body ## - # * - # Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64). + # Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64). # # Content encoding is *not* determined by the media type, but rather by the type # of the object being attached: @@ -43,14 +41,12 @@ class Attachment < Message attr_reader :content_encoding ## - # * - # Suggested file name of the attachment. (Provided by the user as an argument to `attach`) + # Suggested file name of the attachment. (Provided by the user as an argument to `attach`) ## attr_reader :file_name ## - # * - # The media type of the data. This can be any valid + # The media type of the data. This can be any valid # [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml) # as well as Cucumber-specific media types such as `text/x.cucumber.gherkin+plain` # and `text/x.cucumber.stacktrace+plain` @@ -70,8 +66,7 @@ class Attachment < Message attr_reader :test_step_id ## - # * - # A URL where the attachment can be retrieved. This field should not be set by Cucumber. + # A URL where the attachment can be retrieved. This field should not be set by Cucumber. # It should be set by a program that reads a message stream and does the following for # each Attachment message: # diff --git a/ruby/lib/cucumber/messages/comment.rb b/ruby/lib/cucumber/messages/comment.rb index db426989..f160d181 100644 --- a/ruby/lib/cucumber/messages/comment.rb +++ b/ruby/lib/cucumber/messages/comment.rb @@ -7,8 +7,7 @@ module Messages # Represents the Comment message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # A comment in a Gherkin document + # A comment in a Gherkin document ## class Comment < Message ## diff --git a/ruby/lib/cucumber/messages/feature_child.rb b/ruby/lib/cucumber/messages/feature_child.rb index 6a00543d..904ba8a1 100644 --- a/ruby/lib/cucumber/messages/feature_child.rb +++ b/ruby/lib/cucumber/messages/feature_child.rb @@ -7,8 +7,7 @@ module Messages # Represents the FeatureChild message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # A child node of a `Feature` node + # A child node of a `Feature` node ## class FeatureChild < Message attr_reader :rule diff --git a/ruby/lib/cucumber/messages/gherkin_document.rb b/ruby/lib/cucumber/messages/gherkin_document.rb index 8abd5896..ce1f34cb 100644 --- a/ruby/lib/cucumber/messages/gherkin_document.rb +++ b/ruby/lib/cucumber/messages/gherkin_document.rb @@ -7,8 +7,7 @@ module Messages # Represents the GherkinDocument message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. + # The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. # Cucumber implementations should *not* depend on `GherkinDocument` or any of its # children for execution - use [Pickle](#io.cucumber.messages.Pickle) instead. # @@ -17,8 +16,7 @@ module Messages ## class GherkinDocument < Message ## - # * - # The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) + # The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) # of the source, typically a file path relative to the root directory ## attr_reader :uri diff --git a/ruby/lib/cucumber/messages/location.rb b/ruby/lib/cucumber/messages/location.rb index 3b8319ef..8cfe963b 100644 --- a/ruby/lib/cucumber/messages/location.rb +++ b/ruby/lib/cucumber/messages/location.rb @@ -7,8 +7,7 @@ module Messages # Represents the Location message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # Points to a line and a column in a text file + # Points to a line and a column in a text file ## class Location < Message attr_reader :line diff --git a/ruby/lib/cucumber/messages/meta.rb b/ruby/lib/cucumber/messages/meta.rb index e60ae5aa..1776d1df 100644 --- a/ruby/lib/cucumber/messages/meta.rb +++ b/ruby/lib/cucumber/messages/meta.rb @@ -7,14 +7,12 @@ module Messages # Represents the Meta message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # This message contains meta information about the environment. Consumers can use + # This message contains meta information about the environment. Consumers can use # this for various purposes. ## class Meta < Message ## - # * - # The [SEMVER](https://semver.org/) version number of the protocol + # The [SEMVER](https://semver.org/) version number of the protocol ## attr_reader :protocol_version diff --git a/ruby/lib/cucumber/messages/pickle.rb b/ruby/lib/cucumber/messages/pickle.rb index b8b54ea5..6c3c58f6 100644 --- a/ruby/lib/cucumber/messages/pickle.rb +++ b/ruby/lib/cucumber/messages/pickle.rb @@ -23,8 +23,7 @@ module Messages ## class Pickle < Message ## - # * - # A unique id for the pickle + # A unique id for the pickle ## attr_reader :id @@ -49,15 +48,13 @@ class Pickle < Message attr_reader :steps ## - # * - # One or more tags. If this pickle is constructed from a Gherkin document, + # One or more tags. If this pickle is constructed from a Gherkin document, # It includes inherited tags from the `Feature` as well. ## attr_reader :tags ## - # * - # Points to the AST node locations of the pickle. The last one represents the unique + # Points to the AST node locations of the pickle. The last one represents the unique # id of the pickle. A pickle constructed from `Examples` will have the first # id originating from the `Scenario` AST node, and the second from the `TableRow` AST node. ## diff --git a/ruby/lib/cucumber/messages/pickle_step.rb b/ruby/lib/cucumber/messages/pickle_step.rb index 8b66e487..c71a3f55 100644 --- a/ruby/lib/cucumber/messages/pickle_step.rb +++ b/ruby/lib/cucumber/messages/pickle_step.rb @@ -7,8 +7,7 @@ module Messages # Represents the PickleStep message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # An executable step + # An executable step ## class PickleStep < Message attr_reader :argument diff --git a/ruby/lib/cucumber/messages/pickle_tag.rb b/ruby/lib/cucumber/messages/pickle_tag.rb index 7b44dbc9..a6e477ac 100644 --- a/ruby/lib/cucumber/messages/pickle_tag.rb +++ b/ruby/lib/cucumber/messages/pickle_tag.rb @@ -7,8 +7,7 @@ module Messages # Represents the PickleTag message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # A tag + # A tag ## class PickleTag < Message attr_reader :name diff --git a/ruby/lib/cucumber/messages/rule_child.rb b/ruby/lib/cucumber/messages/rule_child.rb index 91fa41f8..b96c9c77 100644 --- a/ruby/lib/cucumber/messages/rule_child.rb +++ b/ruby/lib/cucumber/messages/rule_child.rb @@ -7,8 +7,7 @@ module Messages # Represents the RuleChild message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # A child node of a `Rule` node + # A child node of a `Rule` node ## class RuleChild < Message attr_reader :background diff --git a/ruby/lib/cucumber/messages/source.rb b/ruby/lib/cucumber/messages/source.rb index 9aae553e..18a2f4a2 100644 --- a/ruby/lib/cucumber/messages/source.rb +++ b/ruby/lib/cucumber/messages/source.rb @@ -14,8 +14,7 @@ module Messages ## class Source < Message ## - # * - # The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) + # The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) # of the source, typically a file path relative to the root directory ## attr_reader :uri diff --git a/ruby/lib/cucumber/messages/source_reference.rb b/ruby/lib/cucumber/messages/source_reference.rb index 1a947674..5c802e07 100644 --- a/ruby/lib/cucumber/messages/source_reference.rb +++ b/ruby/lib/cucumber/messages/source_reference.rb @@ -7,8 +7,7 @@ module Messages # Represents the SourceReference message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a + # Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a # [Location](#io.cucumber.messages.Location) within that file. ## class SourceReference < Message diff --git a/ruby/lib/cucumber/messages/step_match_argument.rb b/ruby/lib/cucumber/messages/step_match_argument.rb index 3fcdd4d2..c03c4ee6 100644 --- a/ruby/lib/cucumber/messages/step_match_argument.rb +++ b/ruby/lib/cucumber/messages/step_match_argument.rb @@ -7,8 +7,7 @@ module Messages # Represents the StepMatchArgument message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # Represents a single argument extracted from a step match and passed to a step definition. + # Represents a single argument extracted from a step match and passed to a step definition. # This is used for the following purposes: # - Construct an argument to pass to a step definition (possibly through a parameter type transform) # - Highlight the matched parameter in rich formatters such as the HTML formatter @@ -17,8 +16,7 @@ module Messages ## class StepMatchArgument < Message ## - # * - # Represents the outermost capture group of an argument. This message closely matches the + # Represents the outermost capture group of an argument. This message closely matches the # `Group` class in the `cucumber-expressions` library. ## attr_reader :group diff --git a/ruby/lib/cucumber/messages/tag.rb b/ruby/lib/cucumber/messages/tag.rb index 0a00c21b..5a4d5786 100644 --- a/ruby/lib/cucumber/messages/tag.rb +++ b/ruby/lib/cucumber/messages/tag.rb @@ -7,8 +7,7 @@ module Messages # Represents the Tag message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # A tag + # A tag ## class Tag < Message ## diff --git a/ruby/lib/cucumber/messages/test_case_started.rb b/ruby/lib/cucumber/messages/test_case_started.rb index dec26f99..3f9a4e20 100644 --- a/ruby/lib/cucumber/messages/test_case_started.rb +++ b/ruby/lib/cucumber/messages/test_case_started.rb @@ -9,15 +9,13 @@ module Messages ## class TestCaseStarted < Message ## - # * - # The first attempt should have value 0, and for each retry the value + # The first attempt should have value 0, and for each retry the value # should increase by 1. ## attr_reader :attempt ## - # * - # Because a `TestCase` can be run multiple times (in case of a retry), + # Because a `TestCase` can be run multiple times (in case of a retry), # we use this field to group messages relating to the same attempt. ## attr_reader :id diff --git a/ruby/lib/cucumber/messages/test_step.rb b/ruby/lib/cucumber/messages/test_step.rb index 4da93aa3..8157fd7b 100644 --- a/ruby/lib/cucumber/messages/test_step.rb +++ b/ruby/lib/cucumber/messages/test_step.rb @@ -7,8 +7,7 @@ module Messages # Represents the TestStep message in Cucumber's {message protocol}[https://github.com/cucumber/messages]. ## # - # * - # A `TestStep` is derived from either a `PickleStep` + # A `TestStep` is derived from either a `PickleStep` # combined with a `StepDefinition`, or from a `Hook`. ## class TestStep < Message From 7bbbf009c0ac2d1ae269f9664fcdf1fb5a9ce912 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 14:51:23 +0200 Subject: [PATCH 2/8] Reduce diff --- jsonschema/src/Duration.json | 2 +- perl/lib/Cucumber/Messages.pm | 2 +- python/src/cucumber_messages/_messages.py | 2 +- ruby/lib/cucumber/messages/duration.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jsonschema/src/Duration.json b/jsonschema/src/Duration.json index 56a53780..cd14b78f 100644 --- a/jsonschema/src/Duration.json +++ b/jsonschema/src/Duration.json @@ -12,7 +12,7 @@ "type": "integer" }, "nanos": { - "description": "Non-negative fractions of a second at nanosecond resolution. Negative\n second values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", + "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", "type": "integer", "minimum": 0, "maximum": 9999999999 diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm index 1555d22d..52e83fc5 100644 --- a/perl/lib/Cucumber/Messages.pm +++ b/perl/lib/Cucumber/Messages.pm @@ -304,7 +304,7 @@ has seconds => =head4 nanos Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values +second values with fractions must still have non-negative nanos values that count forward in time. Must be from 0 to 999,999,999 inclusive. =cut diff --git a/python/src/cucumber_messages/_messages.py b/python/src/cucumber_messages/_messages.py index 76cc2059..06dc4ade 100644 --- a/python/src/cucumber_messages/_messages.py +++ b/python/src/cucumber_messages/_messages.py @@ -83,7 +83,7 @@ class Duration: nanos: int """ Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values + second values with fractions must still have non-negative nanos values that count forward in time. Must be from 0 to 999,999,999 inclusive. """ diff --git a/ruby/lib/cucumber/messages/duration.rb b/ruby/lib/cucumber/messages/duration.rb index ec1fa9ec..83ddb795 100644 --- a/ruby/lib/cucumber/messages/duration.rb +++ b/ruby/lib/cucumber/messages/duration.rb @@ -15,7 +15,7 @@ class Duration < Message ## # Non-negative fractions of a second at nanosecond resolution. Negative - # second values with fractions must still have non-negative nanos values + # second values with fractions must still have non-negative nanos values # that count forward in time. Must be from 0 to 999,999,999 # inclusive. ## From 6e677010b82b16b50cab0d46b6ab97ee47d3b7da Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 14:51:57 +0200 Subject: [PATCH 3/8] Reduce diff --- jsonschema/src/Duration.json | 2 +- perl/lib/Cucumber/Messages.pm | 2 +- python/src/cucumber_messages/_messages.py | 2 +- ruby/lib/cucumber/messages/duration.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jsonschema/src/Duration.json b/jsonschema/src/Duration.json index cd14b78f..aba6d0f7 100644 --- a/jsonschema/src/Duration.json +++ b/jsonschema/src/Duration.json @@ -12,7 +12,7 @@ "type": "integer" }, "nanos": { - "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", + "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\nthat count forward in time. Must be from 0 to 999,999,999\n inclusive.", "type": "integer", "minimum": 0, "maximum": 9999999999 diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm index 52e83fc5..5eb4fc21 100644 --- a/perl/lib/Cucumber/Messages.pm +++ b/perl/lib/Cucumber/Messages.pm @@ -305,7 +305,7 @@ has seconds => Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 +that count forward in time. Must be from 0 to 999,999,999 inclusive. =cut diff --git a/python/src/cucumber_messages/_messages.py b/python/src/cucumber_messages/_messages.py index 06dc4ade..17f63f15 100644 --- a/python/src/cucumber_messages/_messages.py +++ b/python/src/cucumber_messages/_messages.py @@ -84,7 +84,7 @@ class Duration: """ Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 + that count forward in time. Must be from 0 to 999,999,999 inclusive. """ diff --git a/ruby/lib/cucumber/messages/duration.rb b/ruby/lib/cucumber/messages/duration.rb index 83ddb795..1bdd1889 100644 --- a/ruby/lib/cucumber/messages/duration.rb +++ b/ruby/lib/cucumber/messages/duration.rb @@ -16,7 +16,7 @@ class Duration < Message ## # Non-negative fractions of a second at nanosecond resolution. Negative # second values with fractions must still have non-negative nanos values - # that count forward in time. Must be from 0 to 999,999,999 + # that count forward in time. Must be from 0 to 999,999,999 # inclusive. ## attr_reader :nanos From db27e26b5992875b898579119bfd03913cfd8f52 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 14:52:26 +0200 Subject: [PATCH 4/8] Reduce diff --- jsonschema/src/Duration.json | 2 +- perl/lib/Cucumber/Messages.pm | 2 +- python/src/cucumber_messages/_messages.py | 2 +- ruby/lib/cucumber/messages/duration.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jsonschema/src/Duration.json b/jsonschema/src/Duration.json index aba6d0f7..c111eba3 100644 --- a/jsonschema/src/Duration.json +++ b/jsonschema/src/Duration.json @@ -12,7 +12,7 @@ "type": "integer" }, "nanos": { - "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\nthat count forward in time. Must be from 0 to 999,999,999\n inclusive.", + "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\nthat count forward in time. Must be from 0 to 999,999,999\ninclusive.", "type": "integer", "minimum": 0, "maximum": 9999999999 diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm index 5eb4fc21..c99ba2b9 100644 --- a/perl/lib/Cucumber/Messages.pm +++ b/perl/lib/Cucumber/Messages.pm @@ -306,7 +306,7 @@ has seconds => Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values that count forward in time. Must be from 0 to 999,999,999 - inclusive. +inclusive. =cut has nanos => diff --git a/python/src/cucumber_messages/_messages.py b/python/src/cucumber_messages/_messages.py index 17f63f15..aa1a5e82 100644 --- a/python/src/cucumber_messages/_messages.py +++ b/python/src/cucumber_messages/_messages.py @@ -85,7 +85,7 @@ class Duration: Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values that count forward in time. Must be from 0 to 999,999,999 - inclusive. + inclusive. """ seconds: int diff --git a/ruby/lib/cucumber/messages/duration.rb b/ruby/lib/cucumber/messages/duration.rb index 1bdd1889..43bfd069 100644 --- a/ruby/lib/cucumber/messages/duration.rb +++ b/ruby/lib/cucumber/messages/duration.rb @@ -17,7 +17,7 @@ class Duration < Message # Non-negative fractions of a second at nanosecond resolution. Negative # second values with fractions must still have non-negative nanos values # that count forward in time. Must be from 0 to 999,999,999 - # inclusive. + # inclusive. ## attr_reader :nanos From b149e9da56ae76e0c4be2b7436079da453f7e4e2 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 14:59:47 +0200 Subject: [PATCH 5/8] Fix range on nanos --- .../generated/java/io/cucumber/messages/types/Duration.java | 6 +++--- .../java/io/cucumber/messages/types/Timestamp.java | 6 +++--- java/src/main/java/io/cucumber/messages/Convertor.java | 5 +++-- jsonschema/src/Duration.json | 2 +- jsonschema/src/Timestamp.json | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/java/src/generated/java/io/cucumber/messages/types/Duration.java b/java/src/generated/java/io/cucumber/messages/types/Duration.java index fd790661..f780675c 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Duration.java +++ b/java/src/generated/java/io/cucumber/messages/types/Duration.java @@ -17,11 +17,11 @@ @SuppressWarnings("unused") public final class Duration { private final Long seconds; - private final Long nanos; + private final Integer nanos; public Duration( Long seconds, - Long nanos + Integer nanos ) { this.seconds = requireNonNull(seconds, "Duration.seconds cannot be null"); this.nanos = requireNonNull(nanos, "Duration.nanos cannot be null"); @@ -37,7 +37,7 @@ public Long getSeconds() { * that count forward in time. Must be from 0 to 999,999,999 * inclusive. */ - public Long getNanos() { + public Integer getNanos() { return nanos; } diff --git a/java/src/generated/java/io/cucumber/messages/types/Timestamp.java b/java/src/generated/java/io/cucumber/messages/types/Timestamp.java index 7a550315..5142aee4 100644 --- a/java/src/generated/java/io/cucumber/messages/types/Timestamp.java +++ b/java/src/generated/java/io/cucumber/messages/types/Timestamp.java @@ -14,11 +14,11 @@ @SuppressWarnings("unused") public final class Timestamp { private final Long seconds; - private final Long nanos; + private final Integer nanos; public Timestamp( Long seconds, - Long nanos + Integer nanos ) { this.seconds = requireNonNull(seconds, "Timestamp.seconds cannot be null"); this.nanos = requireNonNull(nanos, "Timestamp.nanos cannot be null"); @@ -39,7 +39,7 @@ public Long getSeconds() { * that count forward in time. Must be from 0 to 999,999,999 * inclusive. */ - public Long getNanos() { + public Integer getNanos() { return nanos; } diff --git a/java/src/main/java/io/cucumber/messages/Convertor.java b/java/src/main/java/io/cucumber/messages/Convertor.java index fcff908f..cb4386d6 100644 --- a/java/src/main/java/io/cucumber/messages/Convertor.java +++ b/java/src/main/java/io/cucumber/messages/Convertor.java @@ -6,6 +6,7 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.time.Instant; import static java.util.Objects.requireNonNull; @@ -30,12 +31,12 @@ private static String extractStackTrace(Throwable throwable) { public static Timestamp toMessage(java.time.Instant instant) { requireNonNull(instant, "instant may not be null"); - return new Timestamp(instant.getEpochSecond(), (long) instant.getNano()); + return new Timestamp(instant.getEpochSecond(), instant.getNano()); } public static Duration toMessage(java.time.Duration duration) { requireNonNull(duration, "duration may not be null"); - return new Duration(duration.getSeconds(), (long) duration.getNano()); + return new Duration(duration.getSeconds(), duration.getNano()); } public static java.time.Instant toInstant(Timestamp timestamp) { diff --git a/jsonschema/src/Duration.json b/jsonschema/src/Duration.json index c111eba3..c3ad4dc7 100644 --- a/jsonschema/src/Duration.json +++ b/jsonschema/src/Duration.json @@ -15,7 +15,7 @@ "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\nthat count forward in time. Must be from 0 to 999,999,999\ninclusive.", "type": "integer", "minimum": 0, - "maximum": 9999999999 + "maximum": 999999999 } }, "type": "object" diff --git a/jsonschema/src/Timestamp.json b/jsonschema/src/Timestamp.json index 30510a0d..81395aa4 100644 --- a/jsonschema/src/Timestamp.json +++ b/jsonschema/src/Timestamp.json @@ -15,7 +15,7 @@ "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\nthat count forward in time. Must be from 0 to 999,999,999\ninclusive.", "type": "integer", "minimum": 0, - "maximum": 9999999999 + "maximum": 999999999 } }, "type": "object" From c2bc505cbb6e40a0682dbf94835ce467ddc788c6 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 15:01:24 +0200 Subject: [PATCH 6/8] Consistency --- codegen/generators/cpp.rb | 2 +- codegen/generators/dotnet.rb | 2 +- codegen/generators/go.rb | 2 +- codegen/generators/markdown.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/codegen/generators/cpp.rb b/codegen/generators/cpp.rb index 95ac3cb0..e201d945 100644 --- a/codegen/generators/cpp.rb +++ b/codegen/generators/cpp.rb @@ -26,7 +26,7 @@ def select_language_translations_for_data_types(type, property) 'integer' => 'std::size_t', 'string' => 'std::string', 'boolean' => 'bool' - }.fetch(type) + }[type] end end end diff --git a/codegen/generators/dotnet.rb b/codegen/generators/dotnet.rb index 9d25fa87..10af3cf7 100644 --- a/codegen/generators/dotnet.rb +++ b/codegen/generators/dotnet.rb @@ -26,7 +26,7 @@ def select_language_translations_for_data_types(type, property) 'integer' => 'long', 'string' => 'string', 'boolean' => 'bool' - }.fetch(type) + }[type] end end end diff --git a/codegen/generators/go.rb b/codegen/generators/go.rb index bbeb3b5a..de899650 100644 --- a/codegen/generators/go.rb +++ b/codegen/generators/go.rb @@ -19,7 +19,7 @@ def select_language_translations_for_data_types(type, property) 'integer' => 'int64', 'string' => 'string', 'boolean' => 'bool' - }.fetch(type) + }[type] end end end diff --git a/codegen/generators/markdown.rb b/codegen/generators/markdown.rb index 94c79c44..d4cbe553 100644 --- a/codegen/generators/markdown.rb +++ b/codegen/generators/markdown.rb @@ -25,7 +25,7 @@ def select_language_translations_for_data_types(type, property) 'integer' => 'integer', 'string' => 'string', 'boolean' => 'boolean' - }.fetch(type) + }[type] end end end From 60ec8439843e33f002b7d47cdcea6e6b457a3721 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 19:32:45 +0200 Subject: [PATCH 7/8] Fix location.line bound --- jsonschema/src/Location.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsonschema/src/Location.json b/jsonschema/src/Location.json index 0e700cac..074d32ae 100644 --- a/jsonschema/src/Location.json +++ b/jsonschema/src/Location.json @@ -6,7 +6,7 @@ "properties": { "line": { "type": "integer", - "minimum": 0, + "minimum": 1, "maximum": 2147483647 }, "column": { From 01acc5c46c265df842ab23da26c0c8649827a85f Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 18 Jul 2025 19:36:12 +0200 Subject: [PATCH 8/8] Fix --- java/src/test/java/io/cucumber/messages/JacksonTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/test/java/io/cucumber/messages/JacksonTest.java b/java/src/test/java/io/cucumber/messages/JacksonTest.java index a8fc6f73..b7560bd3 100644 --- a/java/src/test/java/io/cucumber/messages/JacksonTest.java +++ b/java/src/test/java/io/cucumber/messages/JacksonTest.java @@ -29,7 +29,7 @@ void serialize_enums_using_value() throws JsonProcessingException { @Test void can_deserialize_envelope() throws JsonProcessingException { - Envelope source = Envelope.of(new TestRunStarted(new Timestamp(3L, 14L), UUID.randomUUID().toString())); + Envelope source = Envelope.of(new TestRunStarted(new Timestamp(3L, 14), UUID.randomUUID().toString())); String json = OBJECT_MAPPER.writeValueAsString(source); assertEquals(source, OBJECT_MAPPER.readValue(json, Envelope.class)); }