From 5ebc186856114c508f28203b19654658e87045e7 Mon Sep 17 00:00:00 2001 From: Fokko Driesprong Date: Thu, 11 Feb 2021 22:00:55 +0100 Subject: [PATCH 0001/1479] AVRO-3043: Remove redundant casts --- .../avro/compiler/specific/templates/java/classic/record.vm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm index 0eac87bbc4d..a40dfb5dad0 100755 --- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm +++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm @@ -53,10 +53,10 @@ static { #if (!$schema.isError()) private static final BinaryMessageEncoder<${this.mangle($schema.getName())}> ENCODER = - new BinaryMessageEncoder<${this.mangle($schema.getName())}>(MODEL$, SCHEMA$); + new BinaryMessageEncoder<>(MODEL$, SCHEMA$); private static final BinaryMessageDecoder<${this.mangle($schema.getName())}> DECODER = - new BinaryMessageDecoder<${this.mangle($schema.getName())}>(MODEL$, SCHEMA$); + new BinaryMessageDecoder<>(MODEL$, SCHEMA$); /** * Return the BinaryMessageEncoder instance used by this class. @@ -80,7 +80,7 @@ static { * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore */ public static BinaryMessageDecoder<${this.mangle($schema.getName())}> createDecoder(SchemaStore resolver) { - return new BinaryMessageDecoder<${this.mangle($schema.getName())}>(MODEL$, SCHEMA$, resolver); + return new BinaryMessageDecoder<>(MODEL$, SCHEMA$, resolver); } /** From dee5e32f8581107c28f73dc95fff74c0b4efc6f1 Mon Sep 17 00:00:00 2001 From: Tim Perkins Date: Tue, 12 Oct 2021 08:29:07 -0400 Subject: [PATCH 0002/1479] AVRO-2903: Ruby: accept BigDecimal datum for float and double (#1364) Co-authored-by: jjlee --- lang/ruby/lib/avro/schema_validator.rb | 2 +- lang/ruby/test/test_io.rb | 14 ++++++++++++++ lang/ruby/test/test_schema_validator.rb | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lang/ruby/lib/avro/schema_validator.rb b/lang/ruby/lib/avro/schema_validator.rb index 30022bb99b7..8e463941a8b 100644 --- a/lang/ruby/lib/avro/schema_validator.rb +++ b/lang/ruby/lib/avro/schema_validator.rb @@ -133,7 +133,7 @@ def validate_simple(expected_schema, logical_datum, path, result, options) fail TypeMismatchError unless datum.is_a?(Integer) result.add_error(path, "out of bound value #{datum}") unless LONG_RANGE.cover?(datum) when :float, :double - fail TypeMismatchError unless datum.is_a?(Float) || datum.is_a?(Integer) + fail TypeMismatchError unless datum.is_a?(Float) || datum.is_a?(Integer) || datum.is_a?(BigDecimal) when :fixed if datum.is_a? String result.add_error(path, fixed_string_message(expected_schema.size, datum)) unless datum.bytesize == expected_schema.size diff --git a/lang/ruby/test/test_io.rb b/lang/ruby/test/test_io.rb index c85135743a7..afbd81e477e 100644 --- a/lang/ruby/test/test_io.rb +++ b/lang/ruby/test/test_io.rb @@ -490,6 +490,20 @@ def test_aliased assert_equal(datum_read, { 'field2' => 1 }) end + def test_big_decimal_datum_for_float + writers_schema = Avro::Schema.parse('"float"') + writer, * = write_datum(BigDecimal('1.2'), writers_schema) + datum_read = read_datum(writer, writers_schema) + assert_in_delta(1.2, datum_read) + end + + def test_big_decimal_datum_for_double + writers_schema = Avro::Schema.parse('"double"') + writer, * = write_datum(BigDecimal("1.2"), writers_schema) + datum_read = read_datum(writer, writers_schema) + assert_in_delta(1.2, datum_read) + end + def test_snappy_backward_compat # a snappy-compressed block payload without the checksum # this has no back-references, just one literal so the last 9 diff --git a/lang/ruby/test/test_schema_validator.rb b/lang/ruby/test/test_schema_validator.rb index 8d100efa23e..8b120927929 100644 --- a/lang/ruby/test/test_schema_validator.rb +++ b/lang/ruby/test/test_schema_validator.rb @@ -170,13 +170,13 @@ def test_validate_long def test_validate_float schema = hash_to_schema(type: 'float', name: 'name') - assert_valid_schema(schema, [1.1, 1, Avro::Schema::LONG_MAX_VALUE], ['string'], true) + assert_valid_schema(schema, [1.1, 1, BigDecimal('1.1'), Avro::Schema::LONG_MAX_VALUE], ['string'], true) end def test_validate_double schema = hash_to_schema(type: 'double', name: 'name') - assert_valid_schema(schema, [1.1, 1, Avro::Schema::LONG_MAX_VALUE], ['string'], true) + assert_valid_schema(schema, [1.1, 1, BigDecimal('1.1'), Avro::Schema::LONG_MAX_VALUE], ['string'], true) end def test_validate_fixed From 131f2c503b38ca7513fc9657205c7c67db3ab3ba Mon Sep 17 00:00:00 2001 From: RyanSkraba Date: Tue, 12 Oct 2021 16:35:11 +0200 Subject: [PATCH 0003/1479] Preparing for 1.12.0-SNAPSHOT (#1356) --- doc/examples/java-example/pom.xml | 9 +- doc/examples/mr-example/pom.xml | 9 +- lang/java/android/pom.xml | 2 +- .../archetypes/avro-service-archetype/pom.xml | 2 +- lang/java/archetypes/pom.xml | 2 +- lang/java/avro/pom.xml | 2 +- lang/java/compiler/pom.xml | 2 +- lang/java/grpc/pom.xml | 2 +- .../integration-test/codegen-test/pom.xml | 2 +- lang/java/integration-test/pom.xml | 2 +- .../test-custom-conversions/pom.xml | 2 +- lang/java/ipc-jetty/pom.xml | 2 +- lang/java/ipc-netty/pom.xml | 2 +- lang/java/ipc/pom.xml | 2 +- lang/java/mapred/pom.xml | 2 +- lang/java/maven-plugin/pom.xml | 2 +- lang/java/perf/pom.xml | 2 +- lang/java/pom.xml | 2 +- lang/java/protobuf/pom.xml | 2 +- lang/java/thrift/pom.xml | 2 +- lang/java/tools/pom.xml | 2 +- lang/java/trevni/avro/pom.xml | 2 +- lang/java/trevni/core/pom.xml | 2 +- lang/java/trevni/doc/pom.xml | 2 +- lang/java/trevni/pom.xml | 2 +- lang/js/package-lock.json | 2268 +---------------- lang/js/package.json | 2 +- pom.xml | 2 +- share/VERSION.txt | 2 +- 29 files changed, 44 insertions(+), 2294 deletions(-) diff --git a/doc/examples/java-example/pom.xml b/doc/examples/java-example/pom.xml index d741dfe7a4f..458c6da6278 100644 --- a/doc/examples/java-example/pom.xml +++ b/doc/examples/java-example/pom.xml @@ -26,6 +26,7 @@ java-example https://maven.apache.org + 1.11.0 UTF-8 @@ -38,7 +39,7 @@ org.apache.avro avro - 1.10.2 + ${avro.version} @@ -55,7 +56,7 @@ org.apache.avro avro-maven-plugin - 1.10.2 + ${avro.version} generate-sources @@ -72,7 +73,7 @@ org.apache.maven.plugins maven-plugin - 1.10.2 + ${avro.version} 1.8 1.8 @@ -92,7 +93,7 @@ org.apache.avro avro-maven-plugin - [1.10.2,) + [${avro.version},) schema diff --git a/doc/examples/mr-example/pom.xml b/doc/examples/mr-example/pom.xml index 2f64b35ec8e..3e0fd354692 100644 --- a/doc/examples/mr-example/pom.xml +++ b/doc/examples/mr-example/pom.xml @@ -28,6 +28,7 @@ mr-example + 1.11.0 UTF-8 @@ -45,7 +46,7 @@ org.apache.avro avro-maven-plugin - 1.10.0 + ${avro.version} generate-sources @@ -73,7 +74,7 @@ org.apache.avro avro-maven-plugin - [1.10.0,) + [${avro.version},) schema @@ -94,12 +95,12 @@ org.apache.avro avro - 1.10.2 + ${avro.version} org.apache.avro avro-mapred - 1.10.2 + ${avro.version} org.apache.hadoop diff --git a/lang/java/android/pom.xml b/lang/java/android/pom.xml index e43bd5ab6e5..c56126efdb1 100644 --- a/lang/java/android/pom.xml +++ b/lang/java/android/pom.xml @@ -22,7 +22,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../pom.xml diff --git a/lang/java/archetypes/avro-service-archetype/pom.xml b/lang/java/archetypes/avro-service-archetype/pom.xml index 1b50363554b..371c312bc14 100644 --- a/lang/java/archetypes/avro-service-archetype/pom.xml +++ b/lang/java/archetypes/avro-service-archetype/pom.xml @@ -23,7 +23,7 @@ avro-archetypes-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../pom.xml diff --git a/lang/java/archetypes/pom.xml b/lang/java/archetypes/pom.xml index 27837400503..d32cfd9f9b9 100644 --- a/lang/java/archetypes/pom.xml +++ b/lang/java/archetypes/pom.xml @@ -22,7 +22,7 @@ org.apache.avro avro-parent - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../pom.xml diff --git a/lang/java/avro/pom.xml b/lang/java/avro/pom.xml index bfa8154e11f..541a73df8be 100644 --- a/lang/java/avro/pom.xml +++ b/lang/java/avro/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/compiler/pom.xml b/lang/java/compiler/pom.xml index 863af78181b..4ebd8b11e48 100644 --- a/lang/java/compiler/pom.xml +++ b/lang/java/compiler/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/grpc/pom.xml b/lang/java/grpc/pom.xml index 8317377e8b7..f04dd468fcf 100644 --- a/lang/java/grpc/pom.xml +++ b/lang/java/grpc/pom.xml @@ -23,7 +23,7 @@ org.apache.avro avro-parent - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/integration-test/codegen-test/pom.xml b/lang/java/integration-test/codegen-test/pom.xml index 8a64f83e30c..e5a7ae1d962 100644 --- a/lang/java/integration-test/codegen-test/pom.xml +++ b/lang/java/integration-test/codegen-test/pom.xml @@ -23,7 +23,7 @@ avro-integration-test org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/integration-test/pom.xml b/lang/java/integration-test/pom.xml index 2ca4071e81f..cc5db4c9194 100644 --- a/lang/java/integration-test/pom.xml +++ b/lang/java/integration-test/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/integration-test/test-custom-conversions/pom.xml b/lang/java/integration-test/test-custom-conversions/pom.xml index 73d798e70e8..94e76b94162 100644 --- a/lang/java/integration-test/test-custom-conversions/pom.xml +++ b/lang/java/integration-test/test-custom-conversions/pom.xml @@ -23,7 +23,7 @@ avro-integration-test org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/ipc-jetty/pom.xml b/lang/java/ipc-jetty/pom.xml index 17adcf1c21b..098370404a1 100644 --- a/lang/java/ipc-jetty/pom.xml +++ b/lang/java/ipc-jetty/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/ipc-netty/pom.xml b/lang/java/ipc-netty/pom.xml index 174849fd0c4..96dd0bfaaa8 100644 --- a/lang/java/ipc-netty/pom.xml +++ b/lang/java/ipc-netty/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/ipc/pom.xml b/lang/java/ipc/pom.xml index 223479f9908..5878980f5bd 100644 --- a/lang/java/ipc/pom.xml +++ b/lang/java/ipc/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/mapred/pom.xml b/lang/java/mapred/pom.xml index 737bb38bf06..23f4b88b132 100644 --- a/lang/java/mapred/pom.xml +++ b/lang/java/mapred/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/maven-plugin/pom.xml b/lang/java/maven-plugin/pom.xml index f7a1011ecc3..9f15b752ce9 100644 --- a/lang/java/maven-plugin/pom.xml +++ b/lang/java/maven-plugin/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/perf/pom.xml b/lang/java/perf/pom.xml index 8b2312f446c..035937f0716 100644 --- a/lang/java/perf/pom.xml +++ b/lang/java/perf/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/pom.xml b/lang/java/pom.xml index f96ce29defe..9689ef37d79 100644 --- a/lang/java/pom.xml +++ b/lang/java/pom.xml @@ -22,7 +22,7 @@ org.apache.avro avro-toplevel - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../../ diff --git a/lang/java/protobuf/pom.xml b/lang/java/protobuf/pom.xml index 793cd70801d..d509955f81a 100644 --- a/lang/java/protobuf/pom.xml +++ b/lang/java/protobuf/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/thrift/pom.xml b/lang/java/thrift/pom.xml index b24646832a4..64a9dfa0668 100644 --- a/lang/java/thrift/pom.xml +++ b/lang/java/thrift/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/tools/pom.xml b/lang/java/tools/pom.xml index 1f4e169ee88..1f47b58a6ae 100644 --- a/lang/java/tools/pom.xml +++ b/lang/java/tools/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/trevni/avro/pom.xml b/lang/java/trevni/avro/pom.xml index 5fa7e3914f7..5cc5f5049cb 100644 --- a/lang/java/trevni/avro/pom.xml +++ b/lang/java/trevni/avro/pom.xml @@ -22,7 +22,7 @@ trevni-java org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/trevni/core/pom.xml b/lang/java/trevni/core/pom.xml index bdab194b56c..99a12172673 100644 --- a/lang/java/trevni/core/pom.xml +++ b/lang/java/trevni/core/pom.xml @@ -22,7 +22,7 @@ trevni-java org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/java/trevni/doc/pom.xml b/lang/java/trevni/doc/pom.xml index f271b16dcf4..e12420112e0 100644 --- a/lang/java/trevni/doc/pom.xml +++ b/lang/java/trevni/doc/pom.xml @@ -22,7 +22,7 @@ trevni-java org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT .. diff --git a/lang/java/trevni/pom.xml b/lang/java/trevni/pom.xml index fd1aaed5c63..9d676bf09e8 100644 --- a/lang/java/trevni/pom.xml +++ b/lang/java/trevni/pom.xml @@ -23,7 +23,7 @@ avro-parent org.apache.avro - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../ diff --git a/lang/js/package-lock.json b/lang/js/package-lock.json index bd51550fc6b..359e7435d86 100644 --- a/lang/js/package-lock.json +++ b/lang/js/package-lock.json @@ -1,2260 +1,8 @@ { "name": "avro-js", - "version": "1.11.0-SNAPSHOT", - "lockfileVersion": 2, + "version": "1.12.0-SNAPSHOT", + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "avro-js", - "version": "1.11.0-SNAPSHOT", - "license": "Apache-2.0", - "dependencies": { - "underscore": "^1.12.0" - }, - "devDependencies": { - "coveralls": "^3.1.0", - "istanbul": "^0.4.5", - "jshint": "^2.12.0", - "mocha": "^6.2.3", - "tmp": "^0.0.28" - } - }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.2" - } - }, - "node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "dev": true, - "dependencies": { - "exit": "0.1.2", - "glob": "^7.1.1" - }, - "engines": { - "node": ">=0.2.5" - } - }, - "node_modules/cli/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "dependencies": { - "date-now": "^0.1.4" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" - }, - "bin": { - "coveralls": "bin/coveralls.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", - "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "node_modules/domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "dev": true, - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "node_modules/es-abstract": { - "version": "1.18.0-next.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.3.tgz", - "integrity": "sha512-VMzHx/Bczjg59E6jZOQjHeN3DEoptdhejpARgflAViidlqSpjdq9zA6lKwlhRRs/lOw1gHJv2xkkSFRgvEwbQg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "dev": true, - "dependencies": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", - "dev": true, - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/jshint": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.12.0.tgz", - "integrity": "sha512-TwuuaUDmra0JMkuqvqy+WGo2xGHSNjv1BA1nTIgtH2K5z1jHuAEeAgp7laaR+hLRmajRjcrM71+vByBDanCyYA==", - "dev": true, - "dependencies": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.19", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "bin": { - "jshint": "bin/jshint" - } - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", - "dev": true, - "bin": { - "lcov-parse": "bin/cli.js" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true, - "engines": { - "node": ">=0.8.6" - } - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", - "dev": true, - "dependencies": { - "mime-db": "1.46.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dev": true, - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/mocha/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", - "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true, - "bin": { - "strip-json-comments": "cli.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/tmp": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", - "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.1" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/uglify-js": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.0.tgz", - "integrity": "sha512-TWYSWa9T2pPN4DIJYbU9oAjQx+5qdV5RUDxwARg8fmJZrD/V27Zj0JngW5xg1DFz42G0uDYl2XhzF6alSzD62w==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz", - "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.0", - "has-symbols": "^1.0.0", - "which-boxed-primitive": "^1.0.1" - } - }, - "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - } - }, "dependencies": { "abbrev": { "version": "1.0.9", @@ -3665,12 +1413,6 @@ "tweetnacl": "~0.14.0" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -3701,6 +1443,12 @@ "define-properties": "^1.1.3" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/lang/js/package.json b/lang/js/package.json index bec79053017..20c3bd7a6b6 100644 --- a/lang/js/package.json +++ b/lang/js/package.json @@ -1,6 +1,6 @@ { "name": "avro-js", - "version": "1.11.0-SNAPSHOT", + "version": "1.12.0-SNAPSHOT", "author": "Avro Developers ", "description": "JavaScript Avro implementation", "contributors": [ diff --git a/pom.xml b/pom.xml index 040a4e87c18..0889ce8ea94 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.avro avro-toplevel - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT pom Apache Avro Toplevel diff --git a/share/VERSION.txt b/share/VERSION.txt index 7ed9261779e..e84fa45fa6e 100644 --- a/share/VERSION.txt +++ b/share/VERSION.txt @@ -1 +1 @@ -1.11.0-SNAPSHOT +1.12.0-SNAPSHOT \ No newline at end of file From fb398e0ddbdd67ae50909533f55defe52488e5da Mon Sep 17 00:00:00 2001 From: Martin Grigorov Date: Wed, 13 Oct 2021 12:55:02 +0300 Subject: [PATCH 0004/1479] AVRO-3171: JS: fix test failures on Node.js 16 (#1354) Add Node.js to the GitHub Actions workflow --- .github/workflows/test-lang-js.yml | 2 ++ lang/js/lib/protocols.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/test-lang-js.yml b/.github/workflows/test-lang-js.yml index 1f5bebce252..3b28dd7979d 100644 --- a/.github/workflows/test-lang-js.yml +++ b/.github/workflows/test-lang-js.yml @@ -37,6 +37,7 @@ jobs: node: - 12 - 14 + - 16 steps: - uses: actions/checkout@v2 - name: Setup Node @@ -65,6 +66,7 @@ jobs: node: - 12 - 14 + - 16 steps: - uses: actions/checkout@v2 - name: Setup Node diff --git a/lang/js/lib/protocols.js b/lang/js/lib/protocols.js index 7a5b9dea77e..f34736230d1 100644 --- a/lang/js/lib/protocols.js +++ b/lang/js/lib/protocols.js @@ -1099,6 +1099,8 @@ MessageDecoder.prototype._flush = function () { this.emit('error', new Error('trailing data')); } else if (this._empty) { this.emit('error', new Error('no message decoded')); + } else { + this.emit('finish'); } }; From 0f4197d94cb4672e756129d49af5c52591e2528f Mon Sep 17 00:00:00 2001 From: Tim Perkins Date: Thu, 14 Oct 2021 04:12:08 -0400 Subject: [PATCH 0005/1479] AVRO-2666: Ruby: remove echoe for packaging the gem (#1367) --- lang/ruby/.gitignore | 1 - lang/ruby/CHANGELOG | 1 - lang/ruby/Gemfile | 11 +++++++++-- lang/ruby/Manifest | 1 - lang/ruby/NOTICE | 2 +- lang/ruby/Rakefile | 28 +++++++++++++--------------- lang/ruby/avro.gemspec | 42 ++++++++++++++++++++++++++++++++++++++++++ lang/ruby/build.sh | 7 +++---- 8 files changed, 68 insertions(+), 25 deletions(-) delete mode 100644 lang/ruby/CHANGELOG create mode 100644 lang/ruby/avro.gemspec diff --git a/lang/ruby/.gitignore b/lang/ruby/.gitignore index 10e8df667cf..2079e4f0e20 100644 --- a/lang/ruby/.gitignore +++ b/lang/ruby/.gitignore @@ -4,7 +4,6 @@ data.avr Gemfile.lock .bundle/ .gem/ -avro.gemspec pkg/ .ruby-version .ruby-gemset diff --git a/lang/ruby/CHANGELOG b/lang/ruby/CHANGELOG deleted file mode 100644 index 16d7595606a..00000000000 --- a/lang/ruby/CHANGELOG +++ /dev/null @@ -1 +0,0 @@ -v0.0.1 stuff \ No newline at end of file diff --git a/lang/ruby/Gemfile b/lang/ruby/Gemfile index 98cade415f7..96e4449fa46 100644 --- a/lang/ruby/Gemfile +++ b/lang/ruby/Gemfile @@ -15,9 +15,16 @@ # limitations under the License. source 'https://rubygems.org' + +VERSION = File.open('../../share/VERSION.txt').read.sub('-SNAPSHOT', '.pre1').chomp +File.write("lib/avro/VERSION.txt", VERSION) + +gemspec + +# Development and optional runtime dependencies are listed below. +# Required runtime dependencies must be listed in avro.gemspec. + gem 'rake' -gem 'echoe' -gem 'multi_json' gem 'snappy' gem 'zstd-ruby' gem 'test-unit' diff --git a/lang/ruby/Manifest b/lang/ruby/Manifest index 6ce443580a0..b35500119cd 100644 --- a/lang/ruby/Manifest +++ b/lang/ruby/Manifest @@ -1,4 +1,3 @@ -CHANGELOG LICENSE NOTICE Manifest diff --git a/lang/ruby/NOTICE b/lang/ruby/NOTICE index 859ea81d74f..4ef234ec5d6 100644 --- a/lang/ruby/NOTICE +++ b/lang/ruby/NOTICE @@ -1,5 +1,5 @@ Apache Avro -Copyright 2010-2015 The Apache Software Foundation +Copyright 2010-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). diff --git a/lang/ruby/Rakefile b/lang/ruby/Rakefile index 92a826386e1..9f41c46f57c 100644 --- a/lang/ruby/Rakefile +++ b/lang/ruby/Rakefile @@ -15,23 +15,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'rubygems' -require 'echoe' -VERSION = File.open('../../share/VERSION.txt').read.sub('-SNAPSHOT', '.pre1').chomp -File.write("lib/avro/VERSION.txt", VERSION) -Echoe.new('avro', VERSION) do |p| - p.author = "Apache Software Foundation" - p.email = "dev@avro.apache.org" - p.summary = "Apache Avro for Ruby" - p.description = "Avro is a data serialization and RPC format" - p.url = "https://avro.apache.org/" - p.runtime_dependencies = ["multi_json ~>1"] - p.licenses = ["Apache-2.0"] +require "bundler/gem_tasks" +require 'rake/testtask' + +Rake::TestTask.new(:interop) do |t| + t.pattern = 'interop/test*.rb' end -t = Rake::TestTask.new(:interop) -t.pattern = 'interop/test*.rb' +Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.pattern = 'test/test_*.rb' + t.verbose = true +end +desc "Generate data for interop tests" task :generate_interop do $:.unshift(HERE + '/lib') $:.unshift(HERE + '/test') @@ -50,8 +47,9 @@ task :generate_interop do end end - HERE = File.expand_path(File.dirname(__FILE__)) SHARE = HERE + '/../../share' SCHEMAS = SHARE + '/test/schemas' BUILD = HERE + '/../../build' + +task default: :test diff --git a/lang/ruby/avro.gemspec b/lang/ruby/avro.gemspec new file mode 100644 index 00000000000..07f48180018 --- /dev/null +++ b/lang/ruby/avro.gemspec @@ -0,0 +1,42 @@ +# frozen_string_literal: true +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Gem::Specification.new do |s| + s.name = "avro" + s.version = File.read("lib/avro/VERSION.txt") + s.authors = ["Apache Software Foundation"] + s.email = "dev@avro.apache.org" + + s.summary = "Apache Avro for Ruby" + s.description = "Avro is a data serialization and RPC format" + s.homepage = "https://avro.apache.org/" + s.license = "Apache-2.0" + s.required_ruby_version = ">= 2.6" + + s.metadata["homepage_uri"] = s.homepage + s.metadata["bug_tracker_uri"] = "https://issues.apache.org/jira/browse/AVRO" + s.metadata["source_code_uri"] = "https://github.com/apache/avro" + s.metadata["documentation_uri"] = "https://avro.apache.org/docs/#{s.version}/" + + files = File.read("Manifest").split("\n") + s.files = files.reject { |f| f.start_with?("test/") } + s.rdoc_options = ["--line-numbers", "--title", "Avro"] + s.test_files = files.select { |f| f.start_with?("test/") } + s.require_paths = ["lib"] + + s.add_dependency("multi_json", "~> 1.0") +end diff --git a/lang/ruby/build.sh b/lang/ruby/build.sh index db7423684a7..baab974b55a 100755 --- a/lang/ruby/build.sh +++ b/lang/ruby/build.sh @@ -51,17 +51,16 @@ do ;; dist) - bundle exec rake build_gemspec - gem build + bundle exec rake build DIST="../../dist/ruby" mkdir -p "${DIST}" VERSION=$(cat lib/avro/VERSION.txt) - cp "avro-${VERSION}.gem" "${DIST}" + cp "pkg/avro-${VERSION}.gem" "${DIST}" ;; clean) bundle exec rake clean - rm -rf tmp avro.gemspec data.avr + rm -rf tmp data.avr lib/avro/VERSION.txt ;; *) From e5811b404ac01fac0d0d6e223d62441554c9cbe9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 10:51:33 +0200 Subject: [PATCH 0006/1479] Bump maven.version from 3.8.1 to 3.8.3 in /lang/java (#1374) Bumps `maven.version` from 3.8.1 to 3.8.3. Updates `maven-core` from 3.8.1 to 3.8.3 - [Release notes](https://github.com/apache/maven/releases) - [Commits](https://github.com/apache/maven/compare/maven-3.8.1...maven-3.8.3) Updates `maven-compat` from 3.8.1 to 3.8.3 - [Release notes](https://github.com/apache/maven/releases) - [Commits](https://github.com/apache/maven/compare/maven-3.8.1...maven-3.8.3) --- updated-dependencies: - dependency-name: org.apache.maven:maven-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.maven:maven-compat dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- lang/java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/java/pom.xml b/lang/java/pom.xml index 9689ef37d79..898d926a69b 100644 --- a/lang/java/pom.xml +++ b/lang/java/pom.xml @@ -49,7 +49,7 @@ 1.7.32 1.1.8.4 2.3 - 3.8.1 + 3.8.3 1.10.11 1.4 1.21 From 0ebd940282edfcec20c0d18faca68ea26ee31733 Mon Sep 17 00:00:00 2001 From: Zoltan Csizmadia Date: Wed, 20 Oct 2021 05:09:27 -0500 Subject: [PATCH 0007/1479] AVRO-3236: Retire .NET Core 2.1 (#1375) * Retire .NET Core 2.1 * Add Target Frameworks table Co-authored-by: Zoltan Csizmadia --- .travis/before_install.sh | 5 ++--- lang/csharp/README.md | 12 ++++++++++++ lang/csharp/src/apache/codegen/Avro.codegen.csproj | 4 ++-- lang/csharp/src/apache/main/Avro.main.csproj | 2 +- lang/csharp/src/apache/test/Avro.test.csproj | 4 ++-- .../csharp/src/apache/test/Specific/SpecificTests.cs | 7 +++++++ share/docker/Dockerfile | 2 +- 7 files changed, 27 insertions(+), 9 deletions(-) diff --git a/.travis/before_install.sh b/.travis/before_install.sh index db76c129165..08e990966ad 100755 --- a/.travis/before_install.sh +++ b/.travis/before_install.sh @@ -33,9 +33,8 @@ case "$TRAVIS_OS_NAME" in ;; "windows") # Install all (latest) SDKs which are used by multi framework projects - choco install dotnetcore-2.1-sdk # .NET Core 2.1 - choco install dotnetcore-sdk # .NET Core 3.1 - choco install dotnet-sdk # .NET 5.0 + choco install dotnetcore-3.1-sdk # .NET Core 3.1 + choco install dotnet-5.0-sdk # .NET 5.0 ;; *) echo "Invalid PLATFORM" diff --git a/lang/csharp/README.md b/lang/csharp/README.md index 39dee79bb0c..f72fd736d74 100644 --- a/lang/csharp/README.md +++ b/lang/csharp/README.md @@ -15,6 +15,18 @@ Install-Package Apache.Avro 1. Install [.NET SDK 5.0+](https://dotnet.microsoft.com/download/dotnet-core) 2. `dotnet test` +## Project Target Frameworks + +| Project | Type | .NET Framework 4.0 | .NET Standard 2.0 | .NET Standard 2.1 | .NET Core 3.1 | .NET 5.0 | +|:---------------:|:----------:|:------------------:|:------------------:|:-----------------:|:-------------:|:---------:| +| Avro.codegen | Exe | | | | ✔️ |✔️ | +| Avro.ipc | Library | ✔️ | ✔️ | | | | +| Avro.ipc.test | Unit Tests | ✔️ | | | | | +| Avro.main | Library | | ✔️ | ✔️ | | | +| Avro.msbuild | Library | ✔️ | ✔️ | | | | +| Avro.perf | Exe | ✔️ | | | |✔️ | +| Avro.test | Unit Tests | ✔️ | | | ✔️ |✔️ | + ## Dependency package version strategy 1. Use [`versions.props`](./versions.props) to specify package versions. `PackageReference` elements in `.csproj` files should use only version properties defined in [`versions.props`](./versions.props). diff --git a/lang/csharp/src/apache/codegen/Avro.codegen.csproj b/lang/csharp/src/apache/codegen/Avro.codegen.csproj index 055a20f781f..5fa56cd9ef3 100644 --- a/lang/csharp/src/apache/codegen/Avro.codegen.csproj +++ b/lang/csharp/src/apache/codegen/Avro.codegen.csproj @@ -22,12 +22,12 @@ Exe - netcoreapp2.1;netcoreapp3.1;net5.0 + netcoreapp3.1;net5.0 avrogen Avro.codegen false diff --git a/lang/csharp/src/apache/main/Avro.main.csproj b/lang/csharp/src/apache/main/Avro.main.csproj index 15cfeadde71..49925423be9 100644 --- a/lang/csharp/src/apache/main/Avro.main.csproj +++ b/lang/csharp/src/apache/main/Avro.main.csproj @@ -20,7 +20,7 @@ - netstandard2.0;netstandard2.1;netcoreapp2.1 + netstandard2.0;netstandard2.1 Avro Avro true diff --git a/lang/csharp/src/apache/test/Avro.test.csproj b/lang/csharp/src/apache/test/Avro.test.csproj index ff2cfa09fef..f3420ced698 100644 --- a/lang/csharp/src/apache/test/Avro.test.csproj +++ b/lang/csharp/src/apache/test/Avro.test.csproj @@ -19,8 +19,8 @@ - netcoreapp2.1;netcoreapp3.1;net5.0 - net461;netcoreapp2.1;netcoreapp3.1;net5.0 + netcoreapp3.1;net5.0 + net461;netcoreapp3.1;net5.0 Avro.test Avro.test false diff --git a/lang/csharp/src/apache/test/Specific/SpecificTests.cs b/lang/csharp/src/apache/test/Specific/SpecificTests.cs index 168c4d0bba5..46b93e560c8 100644 --- a/lang/csharp/src/apache/test/Specific/SpecificTests.cs +++ b/lang/csharp/src/apache/test/Specific/SpecificTests.cs @@ -16,6 +16,7 @@ * limitations under the License. */ +using System; using System.Collections; using System.IO; using NUnit.Framework; @@ -25,6 +26,12 @@ using System.Collections.Generic; using Avro.Test.Specific.@return; +#if !NETCOREAPP +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Reflection; +#endif + namespace Avro.Test { [TestFixture] diff --git a/share/docker/Dockerfile b/share/docker/Dockerfile index 988a6553894..619861e6f2c 100644 --- a/share/docker/Dockerfile +++ b/share/docker/Dockerfile @@ -174,7 +174,7 @@ RUN wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-p && dpkg -i packages-microsoft-prod.deb \ && rm packages-microsoft-prod.deb \ && apt-get update \ - && apt-get -qqy install --no-install-recommends dotnet-sdk-2.1 dotnet-sdk-3.1 dotnet-sdk-5.0 \ + && apt-get -qqy install --no-install-recommends dotnet-sdk-3.1 dotnet-sdk-5.0 \ && apt-get -qqy clean # Install Ruby From a1fce29d9675b4dd95dfee9db32cc505d0b2227c Mon Sep 17 00:00:00 2001 From: Philip Sanetra Date: Wed, 20 Oct 2021 12:46:10 +0200 Subject: [PATCH 0008/1479] AVRO-3225: AVRO-3226: Fix possible StackOverflowException and OutOfMemoryException on invalid input * AVRO-3225: Fix possible StackOverflowException on invalid input * AVRO-3226: Fix possible OutOfMemoryException on invalid input * AVRO-3226: Backport changes for netstandard2.0 --- .../main/IO/BinaryDecoder.netstandard2.0.cs | 33 ++++++- .../IO/BinaryDecoder.notnetstandard2.0.cs | 56 ++++++++--- .../src/apache/test/IO/BinaryCodecTests.cs | 95 +++++++++++++++++-- 3 files changed, 163 insertions(+), 21 deletions(-) diff --git a/lang/csharp/src/apache/main/IO/BinaryDecoder.netstandard2.0.cs b/lang/csharp/src/apache/main/IO/BinaryDecoder.netstandard2.0.cs index 91afeb57e8e..8c6cb7e5c09 100644 --- a/lang/csharp/src/apache/main/IO/BinaryDecoder.netstandard2.0.cs +++ b/lang/csharp/src/apache/main/IO/BinaryDecoder.netstandard2.0.cs @@ -16,6 +16,8 @@ * limitations under the License. */ using System; +using System.IO; +using System.Text; namespace Avro.IO { @@ -24,6 +26,11 @@ namespace Avro.IO /// public partial class BinaryDecoder { + /// + /// It is hard to find documentation about the real maximum array length in .NET Framework 4.6.1, but this seems to work :-/ + /// + private const int MaxDotNetArrayLength = 0x3FFFFFFF; + /// /// A float is written as 4 bytes. /// The float is converted into a 32-bit integer using a method equivalent to @@ -72,10 +79,28 @@ public double ReadDouble() public string ReadString() { int length = ReadInt(); - byte[] buffer = new byte[length]; - //TODO: Fix this because it's lame; - ReadFixed(buffer); - return System.Text.Encoding.UTF8.GetString(buffer); + + if (length < 0) + { + throw new AvroException("Can not deserialize a string with negative length!"); + } + + if (length > MaxDotNetArrayLength) + { + throw new AvroException("String length is not supported!"); + } + + using (var binaryReader = new BinaryReader(stream, Encoding.UTF8, true)) + { + var bytes = binaryReader.ReadBytes(length); + + if (bytes.Length != length) + { + throw new AvroException("Could not read as many bytes from stream as expected!"); + } + + return Encoding.UTF8.GetString(bytes); + } } private void Read(byte[] buffer, int start, int len) diff --git a/lang/csharp/src/apache/main/IO/BinaryDecoder.notnetstandard2.0.cs b/lang/csharp/src/apache/main/IO/BinaryDecoder.notnetstandard2.0.cs index 17bd8415a96..a3bd2174e1d 100644 --- a/lang/csharp/src/apache/main/IO/BinaryDecoder.notnetstandard2.0.cs +++ b/lang/csharp/src/apache/main/IO/BinaryDecoder.notnetstandard2.0.cs @@ -18,6 +18,7 @@ using System; using System.Buffers; using System.Buffers.Binary; +using System.IO; using System.Text; namespace Avro.IO @@ -28,6 +29,8 @@ namespace Avro.IO public partial class BinaryDecoder { private const int StackallocThreshold = 256; + private const int MaxFastReadLength = 4096; + private const int MaxDotNetArrayLength = 0x7FFFFFC7; /// /// A float is written as 4 bytes. @@ -63,23 +66,54 @@ public double ReadDouble() /// String read from the stream. public string ReadString() { - byte[] bufferArray = null; - int length = ReadInt(); - Span buffer = length <= StackallocThreshold ? - stackalloc byte[length] : - (bufferArray = ArrayPool.Shared.Rent(length)).AsSpan(0, length); - - Read(buffer); - string result = Encoding.UTF8.GetString(buffer); + if (length < 0) + { + throw new AvroException("Can not deserialize a string with negative length!"); + } - if (bufferArray != null) + if (length <= MaxFastReadLength) { - ArrayPool.Shared.Return(bufferArray); + byte[] bufferArray = null; + + try + { + Span buffer = length <= StackallocThreshold ? + stackalloc byte[length] : + (bufferArray = ArrayPool.Shared.Rent(length)).AsSpan(0, length); + + Read(buffer); + + return Encoding.UTF8.GetString(buffer); + } + finally + { + if (bufferArray != null) + { + ArrayPool.Shared.Return(bufferArray); + } + } } + else + { + if (length > MaxDotNetArrayLength) + { + throw new AvroException("String length is not supported!"); + } - return result; + using (var binaryReader = new BinaryReader(stream, Encoding.UTF8, true)) + { + var bytes = binaryReader.ReadBytes(length); + + if (bytes.Length != length) + { + throw new AvroException("Could not read as many bytes from stream as expected!"); + } + + return Encoding.UTF8.GetString(bytes); + } + } } private void Read(byte[] buffer, int start, int len) diff --git a/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs b/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs index a6a1731e2d8..f894d7bfc4f 100644 --- a/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs +++ b/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs @@ -20,6 +20,7 @@ using NUnit.Framework; using System.IO; using System.Linq; +using System.Text; using Avro.IO; namespace Avro.Test @@ -214,23 +215,105 @@ public void TestString(string n, int overhead) TestSkip(n, (Decoder d) => d.SkipString(), (Encoder e, string t) => e.WriteString(t), overhead + n.Length); } -#if NETCOREAPP3_1 +#if NETCOREAPP3_1_OR_GREATER [Test] - public void TestLargeString() + public void TestStringReadIntoArrayPool() { + const int maxFastReadLength = 4096; + // Create a 16KB buffer in the Array Pool var largeBufferToSeedPool = ArrayPool.Shared.Rent(2 << 14); ArrayPool.Shared.Return(largeBufferToSeedPool); - // Create a slightly less than 16KB buffer, which will use the 16KB buffer in the pool - var n = string.Concat(Enumerable.Repeat("1234567890", 1600)); - var overhead = 3; + var n = string.Concat(Enumerable.Repeat("A", maxFastReadLength)); + var overhead = 2; TestRead(n, (Decoder d) => d.ReadString(), (Encoder e, string t) => e.WriteString(t), overhead + n.Length); - TestSkip(n, (Decoder d) => d.SkipString(), (Encoder e, string t) => e.WriteString(t), overhead + n.Length); } + + [Test] + public void TestStringReadByBinaryReader() + { + const int overhead = 2; + const int maxFastReadLength = 4096; + const int expectedStringLength = maxFastReadLength + 1; + var n = string.Concat(Enumerable.Repeat("A", expectedStringLength)); + + TestRead(n, (Decoder d) => d.ReadString(), (Encoder e, string t) => e.WriteString(t), expectedStringLength + overhead); + } +#endif + + [Test] + public void TestInvalidInputWithNegativeStringLength() + { + using (MemoryStream iostr = new MemoryStream()) + { + Encoder e = new BinaryEncoder(iostr); + + e.WriteLong(-1); + + iostr.Flush(); + iostr.Position = 0; + Decoder d = new BinaryDecoder(iostr); + + var exception = Assert.Throws(() => d.ReadString()); + + Assert.NotNull(exception); + Assert.AreEqual("Can not deserialize a string with negative length!", exception.Message); + iostr.Close(); + } + } + + [Test] + public void TestInvalidInputWithMaxIntAsStringLength() + { + using (MemoryStream iostr = new MemoryStream()) + { + Encoder e = new BinaryEncoder(iostr); + + e.WriteLong(int.MaxValue); + e.WriteBytes(Encoding.UTF8.GetBytes("SomeSmallString")); + + iostr.Flush(); + iostr.Position = 0; + Decoder d = new BinaryDecoder(iostr); + + var exception = Assert.Throws(() => d.ReadString()); + + Assert.NotNull(exception); + Assert.AreEqual("String length is not supported!", exception.Message); + iostr.Close(); + } + } + + [Test] + public void TestInvalidInputWithMaxArrayLengthAsStringLength() + { + using (MemoryStream iostr = new MemoryStream()) + { + Encoder e = new BinaryEncoder(iostr); + +#if NETCOREAPP3_1_OR_GREATER + const int maximumArrayLength = 0x7FFFFFC7; +#else + const int maximumArrayLength = 0x7FFFFFFF / 2; #endif + e.WriteLong(maximumArrayLength); + e.WriteBytes(Encoding.UTF8.GetBytes("SomeSmallString")); + + iostr.Flush(); + iostr.Position = 0; + Decoder d = new BinaryDecoder(iostr); + + var exception = Assert.Throws(() => d.ReadString()); + + Assert.NotNull(exception); + Assert.AreEqual("Could not read as many bytes from stream as expected!", exception.Message); + iostr.Close(); + } + } + [TestCase(0, 1)] [TestCase(1, 1)] [TestCase(64, 2)] From 99547e0ee2e0a4a839253848d7b34bac7f5e4cea Mon Sep 17 00:00:00 2001 From: feroze daud Date: Tue, 16 Nov 2021 05:40:04 -0800 Subject: [PATCH 0009/1479] AVRO-2498: Add SpecificCompiler support for `uuid` logicalType (#1362) Co-authored-by: feroze daud --- .../compiler/specific/SpecificCompiler.java | 1 + .../specific/TestSpecificCompiler.java | 32 +++++++++++++++---- .../src/test/resources/logical-uuid.avsc | 30 +++++++++++++++++ 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 lang/java/compiler/src/test/resources/logical-uuid.avsc diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java index f9eb43a1386..94fb0e2e478 100644 --- a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java +++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java @@ -107,6 +107,7 @@ void addLogicalTypeConversions(SpecificData specificData) { specificData.addLogicalTypeConversion(new TimeConversions.TimestampMicrosConversion()); specificData.addLogicalTypeConversion(new TimeConversions.LocalTimestampMicrosConversion()); specificData.addLogicalTypeConversion(new TimeConversions.LocalTimestampMillisConversion()); + specificData.addLogicalTypeConversion(new Conversions.UUIDConversion()); } private final SpecificData specificData = new SpecificData(); diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java index b1400777ce1..d789779cdad 100644 --- a/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java +++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java @@ -350,7 +350,8 @@ public void testJavaTypeWithDecimalLogicalTypeEnabled() throws Exception { Assert.assertEquals("Should use LocalDateTime for local-timestamp-millis type", "java.time.LocalDateTime", compiler.javaType(localTimestampSchema)); Assert.assertEquals("Should use Java BigDecimal type", "java.math.BigDecimal", compiler.javaType(decimalSchema)); - Assert.assertEquals("Should use Java CharSequence type", "java.lang.CharSequence", compiler.javaType(uuidSchema)); + Assert.assertEquals("Should use org.apache.avro.Conversions.UUIDConversion() type", + "new org.apache.avro.Conversions.UUIDConversion()", compiler.conversionInstance(uuidSchema)); } @Test @@ -374,7 +375,8 @@ public void testJavaTypeWithDecimalLogicalTypeDisabled() throws Exception { Assert.assertEquals("Should use DateTime for timestamp-millis type", "java.time.Instant", compiler.javaType(timestampSchema)); Assert.assertEquals("Should use ByteBuffer type", "java.nio.ByteBuffer", compiler.javaType(decimalSchema)); - Assert.assertEquals("Should use Java CharSequence type", "java.lang.CharSequence", compiler.javaType(uuidSchema)); + Assert.assertEquals("Should use org.apache.avro.Conversions.UUIDConversion() type", + "new org.apache.avro.Conversions.UUIDConversion()", compiler.conversionInstance(uuidSchema)); } @Test @@ -765,8 +767,8 @@ public void testConversionInstanceWithDecimalLogicalTypeDisabled() throws Except compiler.conversionInstance(timestampSchema)); Assert.assertEquals("Should use null for decimal if the flag is off", "null", compiler.conversionInstance(decimalSchema)); - Assert.assertEquals("Should use null for decimal if the flag is off", "null", - compiler.conversionInstance(uuidSchema)); + Assert.assertEquals("Should use org.apache.avro.Conversions.UUIDConversion() for uuid if the flag is off", + "new org.apache.avro.Conversions.UUIDConversion()", compiler.conversionInstance(uuidSchema)); } @Test @@ -789,8 +791,8 @@ public void testConversionInstanceWithDecimalLogicalTypeEnabled() throws Excepti compiler.conversionInstance(timestampSchema)); Assert.assertEquals("Should use null for decimal if the flag is off", "new org.apache.avro.Conversions.DecimalConversion()", compiler.conversionInstance(decimalSchema)); - Assert.assertEquals("Should use null for decimal if the flag is off", "null", - compiler.conversionInstance(uuidSchema)); + Assert.assertEquals("Should use org.apache.avro.Conversions.UUIDConversion() for uuid if the flag is off", + "new org.apache.avro.Conversions.UUIDConversion()", compiler.conversionInstance(uuidSchema)); } @Test @@ -906,6 +908,24 @@ public void testAdditionalToolsAreInjectedIntoTemplate() throws Exception { assertEquals(1, itWorksFound); } + @Test + public void testPojoWithUUID() throws IOException { + SpecificCompiler compiler = createCompiler(); + compiler.setOptionalGettersForNullableFieldsOnly(true); + File avsc = new File("src/main/resources/logical-uuid.avsc"); + compiler.compileToDestination(avsc, OUTPUT_DIR.getRoot()); + assertTrue(this.outputFile.exists()); + try (BufferedReader reader = new BufferedReader(new FileReader(this.outputFile))) { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.contains("guid")) { + assertTrue(line.contains("java.util.UUID")); + } + } + } + } + public static class StringCustomLogicalTypeFactory implements LogicalTypes.LogicalTypeFactory { @Override public LogicalType fromSchema(Schema schema) { diff --git a/lang/java/compiler/src/test/resources/logical-uuid.avsc b/lang/java/compiler/src/test/resources/logical-uuid.avsc new file mode 100644 index 00000000000..0653a5a3bf5 --- /dev/null +++ b/lang/java/compiler/src/test/resources/logical-uuid.avsc @@ -0,0 +1,30 @@ +{ + "namespace": "schema.common", + "type": "record", + "name": "Action", + "fields": [ + { + "name": "name", + "type": "string" + }, + { + "name": "guid", + "type": { "type": "string", "logicalType": "uuid" } + }, + { + "name": "time", + "type": { + "type": "long", + "logicalType": "timestamp-millis" + } + }, + { + "name": "requestId", + "type": [ + "null", + "string" + ], + "default": null + } + ] +} From de50c244c00420825d4bd7d04c0c2d353e439367 Mon Sep 17 00:00:00 2001 From: Tim Perkins Date: Wed, 17 Nov 2021 06:50:59 -0500 Subject: [PATCH 0010/1479] AVRO-3255: Ruby: specify rubygems_mfa_required in gemspec metadata (#1405) --- lang/ruby/avro.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/lang/ruby/avro.gemspec b/lang/ruby/avro.gemspec index 07f48180018..e73fc7fd72a 100644 --- a/lang/ruby/avro.gemspec +++ b/lang/ruby/avro.gemspec @@ -31,6 +31,7 @@ Gem::Specification.new do |s| s.metadata["bug_tracker_uri"] = "https://issues.apache.org/jira/browse/AVRO" s.metadata["source_code_uri"] = "https://github.com/apache/avro" s.metadata["documentation_uri"] = "https://avro.apache.org/docs/#{s.version}/" + s.metadata["rubygems_mfa_required"] = "true" files = File.read("Manifest").split("\n") s.files = files.reject { |f| f.start_with?("test/") } From 64267e1f4e54a12551d02ff85e41c18090917e69 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Sat, 4 Dec 2021 14:35:16 +0100 Subject: [PATCH 0011/1479] AVRO-3217: Allow any identifier as annotation name (#1414) A field schema can be annotated with the property `avro.java.string`: { "name": "fieldName", "type": { "type": "string", "avro.java.string": "String" } } The corresponding IDL is: @avro.java.`string`("String") string fieldName; The IDL parser fails on the `. This change fixes that. --- .../src/main/javacc/org/apache/avro/compiler/idl/idl.jj | 7 ++++--- lang/java/compiler/src/test/idl/input/simple.avdl | 2 +- lang/java/compiler/src/test/idl/output/simple.avpr | 5 ++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index 0a2b69667cd..15d251e3437 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -1551,14 +1551,15 @@ Schema ResultType(): String PropertyName(): { Token t; + String s; StringBuilder name = new StringBuilder(); } { - t = { name.append(t.image); } + s = Identifier() { name.append(s); } ( t = { name.append(t.image); } - t = { name.append(t.image); } | + s = Identifier() { name.append(s); } | t = { name.append(t.image); } - t = { name.append(t.image); } + s = Identifier() { name.append(s); } ) * { return name.toString(); } } diff --git a/lang/java/compiler/src/test/idl/input/simple.avdl b/lang/java/compiler/src/test/idl/input/simple.avdl index 10e50c98a0a..0d092724b24 100644 --- a/lang/java/compiler/src/test/idl/input/simple.avdl +++ b/lang/java/compiler/src/test/idl/input/simple.avdl @@ -42,7 +42,7 @@ protocol Simple { /** A TestRecord. */ @my-property({"key":3}) record TestRecord { - string @order("ignore") name = "foo"; + @avro.java.`string`("String") string @order("ignore") name = "foo"; /** The kind of record. */ Kind @order("descending") kind; diff --git a/lang/java/compiler/src/test/idl/output/simple.avpr b/lang/java/compiler/src/test/idl/output/simple.avpr index ddcb626ad0d..5710f086380 100644 --- a/lang/java/compiler/src/test/idl/output/simple.avpr +++ b/lang/java/compiler/src/test/idl/output/simple.avpr @@ -26,7 +26,10 @@ "doc" : "A TestRecord.", "fields" : [ { "name" : "name", - "type" : "string", + "type" : { + "type": "string", + "avro.java.string": "String" + }, "default" : "foo", "order" : "ignore" }, { From 0332fdfdf07343f33e6c9e2c28c491cd80c0bb88 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Sat, 4 Dec 2021 14:41:18 +0100 Subject: [PATCH 0012/1479] AVRO-3256: IDL type reference with annotation throws error (#1407) * AVRO-3256: IDL type reference with annotation throws error Previous versions would alter the referenced type when encountering an annotation on (for example) a field type. This change makes references read-only. * AVRO-3256: Document new behavior of annotations Documented that references to named types cannot be annotated. Also described where annotations for named types should go. Lastly, the example has been fixed to match this change, and now also contains various types of documentation. --- doc/src/content/xdocs/idl.xml | 32 ++++++++++----- .../org/apache/avro/compiler/idl/idl.jj | 34 ++++++++-------- .../test/idl/AnnotationOnTypeReference.avdl | 31 +++++++++++++++ .../compiler/src/test/idl/input/simple.avdl | 2 +- .../compiler/src/test/idl/output/simple.avpr | 3 +- .../TestReferenceAnnotationNotAllowed.java | 39 +++++++++++++++++++ lang/java/grpc/src/test/avro/TestService.avdl | 6 +-- lang/java/tools/src/test/idl/protocol.avdl | 6 +-- 8 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 lang/java/compiler/src/test/idl/AnnotationOnTypeReference.avdl create mode 100644 lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestReferenceAnnotationNotAllowed.java diff --git a/doc/src/content/xdocs/idl.xml b/doc/src/content/xdocs/idl.xml index 52a607503b3..0d5e5da9e46 100644 --- a/doc/src/content/xdocs/idl.xml +++ b/doc/src/content/xdocs/idl.xml @@ -101,7 +101,7 @@ protocol MyProtocol {

This is equivalent to (and generates) the following JSON protocol definition:

- + { "protocol" : "MyProtocol", @@ -384,7 +384,7 @@ record MyRecord { string @order("ignore") myIgnoredField; } -

A field's type may also be preceded by annotations, e.g.:

+

A field's type (with the exception of type references) may also be preceded by annotations, e.g.:

record MyRecord { @java-class("java.util.ArrayList") array<string> myStrings; @@ -429,50 +429,62 @@ record MyRecord {

Some annotations like those listed above are handled specially. All other annotations are added as properties to the protocol, message, schema or field.

+

Note that for named types, annotations should be added to + the type definition; they cannot be added to the type references.

Complete Example -

The following is a complete example of a Avro IDL file that shows most of the above features:

+

The following is an example of an Avro IDL file that shows most of the above features:

+/* +* Header with license information. +*/ + /** * An example protocol in Avro IDL */ @namespace("org.apache.avro.test") protocol Simple { - + /** Documentation for the enum type Kind */ @aliases(["org.foo.KindOf"]) enum Kind { FOO, BAR, // the bar enum value BAZ - } + } = FOO; // For schema evolution purposes, unmatched values do not throw an error, but are resolved to FOO. + /** MD5 hash; good enough to avoid most collisions, and smaller than (for example) SHA256. */ fixed MD5(16); record TestRecord { - @order("ignore") - string name; + /** Record name; has no intrinsic order */ + string @order("ignore") name; - @order("descending") - Kind kind; + Kind @order("descending") kind; MD5 hash; - union { MD5, null} @aliases(["hash"]) nullableHash; + /* + Note that 'null' is the first union type. Just like .avsc / .avpr files, the default value must be of the first union type. + */ + union { null, MD5 } /** Optional field */ @aliases(["hash"]) nullableHash = null; array<long> arrayOfLongs; } + /** Errors are records that can be thrown from a method */ error TestError { string message; } string hello(string greeting); + /** Return what was given. Demonstrates the use of backticks to name types/fields/messages/parameters after keywords */ TestRecord echo(TestRecord `record`); int add(int arg1, int arg2); bytes echoBytes(bytes data); void `error`() throws TestError; + // The oneway keyword forces the method to return null. void ping() oneway; } diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index 15d251e3437..d4be8a57b6f 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -63,6 +63,7 @@ package org.apache.avro.compiler.idl; import java.io.*; import java.net.*; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -1068,8 +1069,7 @@ Schema UnionDefinition(): List schemata = new ArrayList(); } { - // TODO should probably disallow other unions here in the parser? - + // Don't disallow unions here: its constructor disallows nested unions and throws a descriptive exception. "union" "{" s = Type() @@ -1141,7 +1141,7 @@ List EnumBody(): } { "{" - [ EnumConstant(symbols) ( LOOKAHEAD(2) "," EnumConstant(symbols) )* ] + [ EnumConstant(symbols) ( "," EnumConstant(symbols) )* ] "}" { return symbols; @@ -1317,17 +1317,9 @@ void FieldDeclaration(List fields): Map props = new LinkedHashMap(); } { - // TODO should we be able to specify properties on any Type? - // or just on field declarations as done here - - ( SchemaProperty(props) )* type = Type() VariableDeclarator(type, fields) ( "," VariableDeclarator(type, fields) )* ";" - { - for (String key : props.keySet()) - Accessor.addProp(type, key, props.get(key)); - } } void VariableDeclarator(Schema type, List fields): @@ -1440,16 +1432,27 @@ Schema Type(): { ( SchemaProperty(props) )* + s = UnannotatedType(props) + { + for (String key : props.keySet()) + Accessor.addProp(s, key, props.get(key)); + return s; + } +} + +Schema UnannotatedType(Map props): +{ + Schema s; +} +{ ( - LOOKAHEAD(2) s = ReferenceType() + s = ReferenceType() { if (!props.isEmpty()) { throw error("Type references may not be annotated", token); } } | s = PrimitiveType() | s = UnionDefinition() | s = ArrayType() | s = MapType() ) { - for (String key : props.keySet()) - Accessor.addProp(s, key, props.get(key)); return s; } } @@ -1543,9 +1546,8 @@ Schema ResultType(): Schema schema; } { - LOOKAHEAD(2) "void" { return Schema.create(Type.NULL); } - | schema = Type() { return schema; } + | schema = UnannotatedType(Collections.emptyMap()) { return schema; } } String PropertyName(): diff --git a/lang/java/compiler/src/test/idl/AnnotationOnTypeReference.avdl b/lang/java/compiler/src/test/idl/AnnotationOnTypeReference.avdl new file mode 100644 index 00000000000..03f6f7c6f27 --- /dev/null +++ b/lang/java/compiler/src/test/idl/AnnotationOnTypeReference.avdl @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A stripped down version of a previous `simple.avdl`, keeping the part where a type reference had an annotation (this is wrong). + */ +@namespace("org.apache.avro.test") +protocol Simple { + /** An MD5 hash. */ + fixed MD5(16); + + /** A TestRecord. */ + record TestRecord { + @foo("bar") MD5 hash = "0000000000000000"; + } +} diff --git a/lang/java/compiler/src/test/idl/input/simple.avdl b/lang/java/compiler/src/test/idl/input/simple.avdl index 0d092724b24..a9f67ed141e 100644 --- a/lang/java/compiler/src/test/idl/input/simple.avdl +++ b/lang/java/compiler/src/test/idl/input/simple.avdl @@ -50,7 +50,7 @@ protocol Simple { /** The status of the record. */ Status status = "A"; - @foo("bar") MD5 hash = "0000000000000000"; + MD5 hash = "0000000000000000"; union {null, MD5} @aliases(["hash", "hsh"]) nullableHash = null; diff --git a/lang/java/compiler/src/test/idl/output/simple.avpr b/lang/java/compiler/src/test/idl/output/simple.avpr index 5710f086380..6128d442110 100644 --- a/lang/java/compiler/src/test/idl/output/simple.avpr +++ b/lang/java/compiler/src/test/idl/output/simple.avpr @@ -18,8 +18,7 @@ "type" : "fixed", "name" : "MD5", "doc" : "An MD5 hash.", - "size" : 16, - "foo" : "bar" + "size" : 16 }, { "type" : "record", "name" : "TestRecord", diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestReferenceAnnotationNotAllowed.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestReferenceAnnotationNotAllowed.java new file mode 100644 index 00000000000..2a095b0669b --- /dev/null +++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestReferenceAnnotationNotAllowed.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.compiler.idl; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class TestReferenceAnnotationNotAllowed { + + @Test + public void testReferenceAnnotationNotAllowed() { + + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); + Idl idl = new Idl(cl.getResourceAsStream("AnnotationOnTypeReference.avdl"), "UTF-8"); + + try { + idl.CompilationUnit(); + + fail("Compilation should fail: annotations on type references are not allowed."); + } catch (ParseException e) { + assertEquals("Type references may not be annotated, at line 29, column 17", e.getMessage()); + } + } +} diff --git a/lang/java/grpc/src/test/avro/TestService.avdl b/lang/java/grpc/src/test/avro/TestService.avdl index 2a4537afa19..9a4629a8f5c 100644 --- a/lang/java/grpc/src/test/avro/TestService.avdl +++ b/lang/java/grpc/src/test/avro/TestService.avdl @@ -29,11 +29,9 @@ protocol TestService { fixed MD5(4); record TestRecord { - @order("ignore") - string name; + string @order("ignore") name; - @order("descending") - Kind kind; + Kind @order("descending") kind; MD5 hash; diff --git a/lang/java/tools/src/test/idl/protocol.avdl b/lang/java/tools/src/test/idl/protocol.avdl index 89fbb2494bb..2de089701bc 100644 --- a/lang/java/tools/src/test/idl/protocol.avdl +++ b/lang/java/tools/src/test/idl/protocol.avdl @@ -32,11 +32,9 @@ protocol Simple { fixed MD5(16); record TestRecord { - @order("ignore") - string name; + string @order("ignore") name; - @order("descending") - Kind kind; + Kind @order("descending") kind; MD5 hash; From 527221aeff36587ecf5689a11114399494c2fceb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Dec 2021 14:43:14 +0100 Subject: [PATCH 0013/1479] Bump maven.version from 3.8.3 to 3.8.4 in /lang/java (#1416) Bumps `maven.version` from 3.8.3 to 3.8.4. Updates `maven-core` from 3.8.3 to 3.8.4 - [Release notes](https://github.com/apache/maven/releases) - [Commits](https://github.com/apache/maven/compare/maven-3.8.3...maven-3.8.4) Updates `maven-compat` from 3.8.3 to 3.8.4 - [Release notes](https://github.com/apache/maven/releases) - [Commits](https://github.com/apache/maven/compare/maven-3.8.3...maven-3.8.4) --- updated-dependencies: - dependency-name: org.apache.maven:maven-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.maven:maven-compat dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- lang/java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/java/pom.xml b/lang/java/pom.xml index 898d926a69b..5b90ac283b6 100644 --- a/lang/java/pom.xml +++ b/lang/java/pom.xml @@ -49,7 +49,7 @@ 1.7.32 1.1.8.4 2.3 - 3.8.3 + 3.8.4 1.10.11 1.4 1.21 From 24ab2812eae62ac921bf03e0c1c41d1993f6551c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 15:19:33 +0100 Subject: [PATCH 0014/1479] Bump grpc.version from 1.40.1 to 1.42.1 in /lang/java (#1420) Bumps `grpc.version` from 1.40.1 to 1.42.1. Updates `grpc-core` from 1.40.1 to 1.42.1 - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.40.1...v1.42.1) Updates `grpc-stub` from 1.40.1 to 1.42.1 - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.40.1...v1.42.1) Updates `grpc-netty` from 1.40.1 to 1.42.1 - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.40.1...v1.42.1) --- updated-dependencies: - dependency-name: io.grpc:grpc-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: io.grpc:grpc-stub dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: io.grpc:grpc-netty dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- lang/java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/java/pom.xml b/lang/java/pom.xml index 5b90ac283b6..23a57b93184 100644 --- a/lang/java/pom.xml +++ b/lang/java/pom.xml @@ -57,7 +57,7 @@ 1.9 4.3 2.2 - 1.40.1 + 1.42.1 1.5.0-4 3.2.0 From c1dd47e9388bc30922f043877df15caedaff23af Mon Sep 17 00:00:00 2001 From: RyanSkraba Date: Thu, 9 Dec 2021 18:45:29 +0100 Subject: [PATCH 0015/1479] AVRO-3258: Fix quoting error in python setup.cfg (#1410) --- lang/py/setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/py/setup.cfg b/lang/py/setup.cfg index 48eb6684708..487b322b0e7 100644 --- a/lang/py/setup.cfg +++ b/lang/py/setup.cfg @@ -21,7 +21,7 @@ name = avro version = file: avro/VERSION.txt description = Avro is a serialization and RPC framework. long_description = file: README.md -long_description_content_type='text/markdown' +long_description_content_type=text/markdown keywords = avro serialization From d206242f3f8438421122accb87898a28eda1ea75 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Thu, 9 Dec 2021 19:19:23 +0100 Subject: [PATCH 0016/1479] AVRO-2019: Improve documentation for logical type annotation (#1413) This is the 2017 patch from Andrew Rosca, documenting using @logicalType to allow arbitrary logical types in IDL. --- doc/src/content/xdocs/idl.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/src/content/xdocs/idl.xml b/doc/src/content/xdocs/idl.xml index 0d5e5da9e46..e8c1b81a0f4 100644 --- a/doc/src/content/xdocs/idl.xml +++ b/doc/src/content/xdocs/idl.xml @@ -252,6 +252,14 @@ record Job { time_ms submitTime; timestamp_ms finishTime; decimal(9,2) finishRatio; +} + +

Logical types can also be specified via an annotation, which is useful for logical types for which a keyword does not exist:

+ +record Job { + string jobid; + @logicalType("timestamp-micros") + long finishTime; }
From 0e74de1eedc90418731d14ce51528b84dc3caf24 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Sat, 11 Dec 2021 15:32:23 +0100 Subject: [PATCH 0017/1479] AVRO-2976: Add LogicalType parsing to the IDL (#985) * AVRO-2976: Add LogicalType parsing to IDL * AVRO-2976: Handle both Long and Integer in IDL JSON parsing The IDL parser now distinguishes numbers between Long and Integer. This is needed because the logical type decimal breaks on Long numbers for precision and scale. I chose to solve it here because the scope of this change is smaller. An alternative is to downcast a Long in the method LogicalTypes.Decimal#getInt(Schema, String). * AVRO-2976: Remove duplicate annotation processing for types. * Extend simple test to also verify annotations on arrays (the grammar alrewady supports this). * AVRO-2976: Trigger tests (build fail on unrelated part) * AVRO-2976: Revert pom.xml change. * AVRO-2976: Fix copy/paste error * AVRO-2976: Remove debugging code The removed code was used to evaluate if the test would work. * AVRO-2976: Spotless * AVRO-2976: Fix test The test worked because calling toString() on the protocol made schemas available by their unqualified name (without namespace). --- .../org/apache/avro/compiler/idl/idl.jj | 18 +++- .../compiler/src/test/idl/input/simple.avdl | 1 + .../compiler/src/test/idl/logicalTypes.avdl | 32 +++++++ .../compiler/src/test/idl/output/simple.avpr | 4 + .../avro/compiler/idl/TestLogicalTypes.java | 93 +++++++++++++++++++ 5 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 lang/java/compiler/src/test/idl/logicalTypes.avdl create mode 100644 lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestLogicalTypes.java diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index d4be8a57b6f..e6977cbc069 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -71,6 +71,7 @@ import java.util.Map; import java.net.URL; import org.apache.avro.Schema; +import org.apache.avro.LogicalType; import org.apache.avro.LogicalTypes; import org.apache.avro.Schema.*; import org.apache.avro.Protocol; @@ -1058,6 +1059,9 @@ private Schema NamedSchemaDeclaration(Map props): } else { // add all other props Accessor.addProp(s, key, props.get(key)); } + LogicalType logicalType = LogicalTypes.fromSchemaIgnoreInvalid(s); + if (logicalType != null) + logicalType.addToSchema(s); return s; } @@ -1314,7 +1318,6 @@ private void SchemaProperty(Map properties): void FieldDeclaration(List fields): { Schema type; - Map props = new LinkedHashMap(); } { type = Type() @@ -1430,12 +1433,14 @@ Schema Type(): Map props = new LinkedHashMap(); } { - ( SchemaProperty(props) )* s = UnannotatedType(props) { for (String key : props.keySet()) Accessor.addProp(s, key, props.get(key)); + LogicalType logicalType = LogicalTypes.fromSchemaIgnoreInvalid(s); + if (logicalType != null) + logicalType.addToSchema(s); return s; } } @@ -1617,7 +1622,14 @@ private JsonNode Json() : { String s; Token t; JsonNode n; } { ( s = JsonString() { n = new TextNode(s); } -| (t= { n = new LongNode(Long.parseLong(t.image)); }) +| (t= { + long longValue = Long.parseLong(t.image); + int intValue = (int)longValue; + if (intValue == longValue) + n = new IntNode(intValue); + else + n = new LongNode(longValue); +}) | (t= {n=new DoubleNode(Double.parseDouble(t.image));}) | n=JsonObject() | n=JsonArray() diff --git a/lang/java/compiler/src/test/idl/input/simple.avdl b/lang/java/compiler/src/test/idl/input/simple.avdl index a9f67ed141e..c0df9f3a988 100644 --- a/lang/java/compiler/src/test/idl/input/simple.avdl +++ b/lang/java/compiler/src/test/idl/input/simple.avdl @@ -60,6 +60,7 @@ protocol Simple { time_ms t = 0; @foo.bar("bar.foo") long l = 0; + @foo.bar.bar("foo.bar2") array a = []; union {null, @foo.foo.bar(42) @foo.foo.foo("3foo") string} prop = null; } diff --git a/lang/java/compiler/src/test/idl/logicalTypes.avdl b/lang/java/compiler/src/test/idl/logicalTypes.avdl new file mode 100644 index 00000000000..9e4a284da9b --- /dev/null +++ b/lang/java/compiler/src/test/idl/logicalTypes.avdl @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@version("1.0.5") +@namespace("org.apache.avro.test") +protocol LogicalTypeTest { + record LogicalTypeFields { + date aDate; + time_ms aTime; + timestamp_ms aTimestamp; + local_timestamp_ms aLocalTimestamp; + decimal(6,2) pocketMoney; + uuid identifier; + @logicalType("timestamp-micros") long anotherTimestamp; + @logicalType("decimal") @precision(6) @scale(2) bytes allowance; + @logicalType("decimal") @precision(3000000000) @scale(0) bytes byteArray; + } +} diff --git a/lang/java/compiler/src/test/idl/output/simple.avpr b/lang/java/compiler/src/test/idl/output/simple.avpr index 6128d442110..ab1c03c3d4b 100644 --- a/lang/java/compiler/src/test/idl/output/simple.avpr +++ b/lang/java/compiler/src/test/idl/output/simple.avpr @@ -70,6 +70,10 @@ "name": "l", "type": {"type": "long", "foo.bar": "bar.foo"}, "default": 0 + } , { + "name": "a", + "type": {"type": "array", "items": "string", "foo.bar.bar": "foo.bar2"}, + "default": [] } , { "name": "prop", "type": [ "null" , {"type":"string", "foo.foo.bar": 42, "foo.foo.foo": "3foo"} ], diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestLogicalTypes.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestLogicalTypes.java new file mode 100644 index 00000000000..77cda5c3f03 --- /dev/null +++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestLogicalTypes.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.compiler.idl; + +import org.apache.avro.LogicalType; +import org.apache.avro.LogicalTypes; +import org.apache.avro.Protocol; +import org.apache.avro.Schema; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TestLogicalTypes { + private Schema logicalTypeFields; + + @Before + public void setup() throws ParseException { + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); + Idl idl = new Idl(cl.getResourceAsStream("logicalTypes.avdl"), "UTF-8"); + Protocol protocol = idl.CompilationUnit(); + + logicalTypeFields = protocol.getType("org.apache.avro.test.LogicalTypeFields"); + } + + @Test + public void testDateBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.date(), logicalTypeOfField("aDate")); + } + + @Test + public void testTimeMsBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.timeMillis(), logicalTypeOfField("aTime")); + } + + @Test + public void testTimestampMsBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.timestampMillis(), logicalTypeOfField("aTimestamp")); + } + + @Test + public void testLocalTimestampMsBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.localTimestampMillis(), logicalTypeOfField("aLocalTimestamp")); + } + + @Test + public void testDecimalBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.decimal(6, 2), logicalTypeOfField("pocketMoney")); + } + + @Test + public void testUuidBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.uuid(), logicalTypeOfField("identifier")); + } + + @Test + public void testAnnotatedLongBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.timestampMicros(), logicalTypeOfField("anotherTimestamp")); + } + + @Test + public void testAnnotatedBytesFieldBecomesLogicalType() { + Assert.assertEquals(LogicalTypes.decimal(6, 2), logicalTypeOfField("allowance")); + } + + @Test + public void testIncorrectlyAnnotatedBytesFieldHasNoLogicalType() { + Schema fieldSchema = logicalTypeFields.getField("byteArray").schema(); + + Assert.assertNull(fieldSchema.getLogicalType()); + Assert.assertEquals("decimal", fieldSchema.getObjectProp("logicalType")); + Assert.assertEquals(3000000000L, fieldSchema.getObjectProp("precision")); // Not an int, so not a valid precision + Assert.assertEquals(0, fieldSchema.getObjectProp("scale")); + } + + private LogicalType logicalTypeOfField(String name) { + return logicalTypeFields.getField(name).schema().getLogicalType(); + } +} From 7d851528a5e833c5bb10a54b080b8c347cdcb2c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Dec 2021 15:36:05 +0100 Subject: [PATCH 0018/1479] Bump netty-bom from 4.1.68.Final to 4.1.70.Final in /lang/java (#1419) Bumps [netty-bom](https://github.com/netty/netty) from 4.1.68.Final to 4.1.70.Final. - [Release notes](https://github.com/netty/netty/releases) - [Commits](https://github.com/netty/netty/compare/netty-4.1.68.Final...netty-4.1.70.Final) --- updated-dependencies: - dependency-name: io.netty:netty-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- lang/java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/java/pom.xml b/lang/java/pom.xml index 23a57b93184..d83003c22bd 100644 --- a/lang/java/pom.xml +++ b/lang/java/pom.xml @@ -43,7 +43,7 @@ 9.4.43.v20210629 5.0.4 4.13.2 - 4.1.68.Final + 4.1.70.Final 3.17.3 0.15.0 1.7.32 From 7e97a1084e11851a2614677dc088734758594049 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Sun, 12 Dec 2021 12:12:42 +0100 Subject: [PATCH 0019/1479] AVRO-3239: IDL parsing silently ignores dangling documentation comments (#1377) * AVRO-3239: Add warnings for ignored doc comments * AVRO-3239: Add mock Maven Log implementation * AVRO-3239: Log parser warnings in Maven IDL mojo * AVRO-3239: Log parser warnings in the IDL tools * AVRO-3239: Document new (public) parser method * AVRO-3239: Undo merge error and fix build * AVRO-3239: Extract helper class for doc comments The helper class allows better testing of and documentation for handling doc comments. The .avpr changes all dedented comments. * AVRO-3239: Add missing license * AVRO-3239: Fix documentation comment * AVRO-3239: Fix tests * AVRO-3239: Apply review comments --- .../avro/compiler/idl/DocCommentHelper.java | 127 +++++++++++++++++ .../org/apache/avro/compiler/idl/idl.jj | 38 +++--- .../compiler/src/test/idl/input/comments.avdl | 67 +++++++++ .../src/test/idl/output/baseball.avpr | 2 +- .../src/test/idl/output/comments.avpr | 62 +++++++++ .../compiler/src/test/idl/output/import.avpr | 2 +- .../compiler/src/test/idl/output/interop.avpr | 4 +- .../src/test/idl/output/mr_events.avpr | 2 +- .../src/test/idl/output/namespaces.avpr | 4 +- .../src/test/idl/output/nestedimport.avpr | 4 +- .../src/test/idl/output/reservedwords.avpr | 4 +- .../compiler/src/test/idl/output/simple.avpr | 2 +- .../compiler/src/test/idl/output/unicode.avpr | 4 +- .../compiler/src/test/idl/output/uuid.avpr | 4 +- .../compiler/idl/DocCommentHelperTest.java | 88 ++++++++++++ .../org/apache/avro/compiler/idl/TestIdl.java | 56 +++++++- .../org/apache/avro/mojo/IDLProtocolMojo.java | 3 + .../src/test/avro/AvdlClasspathImport.avdl | 2 + .../apache/avro/mojo/TestIDLProtocolMojo.java | 13 ++ .../java/org/apache/avro/mojo/TestLog.java | 128 ++++++++++++++++++ .../apache/avro/tool/IdlToSchemataTool.java | 8 +- .../java/org/apache/avro/tool/IdlTool.java | 4 + lang/java/tools/src/test/idl/protocol.avpr | 90 ++++++++++++ .../avro/tool/TestIdlToSchemataTool.java | 34 ++++- .../org/apache/avro/tool/TestIdlTool.java | 80 +++++++++++ 25 files changed, 795 insertions(+), 37 deletions(-) create mode 100644 lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/DocCommentHelper.java create mode 100644 lang/java/compiler/src/test/idl/input/comments.avdl create mode 100644 lang/java/compiler/src/test/idl/output/comments.avpr create mode 100644 lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/DocCommentHelperTest.java create mode 100644 lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestLog.java create mode 100644 lang/java/tools/src/test/idl/protocol.avpr create mode 100644 lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlTool.java diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/DocCommentHelper.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/DocCommentHelper.java new file mode 100644 index 00000000000..1ccc101a0b0 --- /dev/null +++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/DocCommentHelper.java @@ -0,0 +1,127 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.compiler.idl; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class with {@code ThreadLocal} fields that allow the generated + * classes {@link Idl} and {@link IdlTokenManager} to exchange documentation + * comments without forcing explicit parsing of documentation comments. + * + * The reason this works is that all calls to this class happen within a call to + * the method {@link Idl#CompilationUnit()} (either directly or indirectly). + */ +public class DocCommentHelper { + /** + * Pattern to match the common whitespace indents in a multi-line String. + * Doesn't match a single-line String, fully matches any multi-line String. + * + * To use: match on a {@link String#trim() trimmed} String, and then replace all + * newlines followed by the group "indent" with a newline. + */ + private static final Pattern WS_INDENT = Pattern.compile("(?U).*\\R(?\\h*).*(?:\\R\\k.*)*"); + /** + * Pattern to match the whitespace indents plus common stars (1 or 2) in a + * multi-line String. If a String fully matches, replace all occurrences of a + * newline followed by whitespace and then the group "stars" with a newline. + * + * Note: partial matches are invalid. + */ + private static final Pattern STAR_INDENT = Pattern.compile("(?U)(?\\*{1,2}).*(?:\\R\\h*\\k.*)*"); + + private static final ThreadLocal DOC = new ThreadLocal<>(); + private static final ThreadLocal> WARNINGS = ThreadLocal.withInitial(ArrayList::new); + + /** + * Return all warnings that were encountered while parsing, once. Subsequent + * calls before parsing again will return an empty list. + */ + static List getAndClearWarnings() { + List warnings = WARNINGS.get(); + WARNINGS.remove(); + return warnings; + } + + static void setDoc(Token token) { + DocComment newDocComment = new DocComment(token); + DocComment oldDocComment = DOC.get(); + if (oldDocComment != null) { + WARNINGS.get() + .add(String.format( + "Found documentation comment at line %d, column %d. Ignoring previous one at line %d, column %d: \"%s\"\n" + + "Did you mean to use a multiline comment ( /* ... */ ) instead?", + newDocComment.line, newDocComment.column, oldDocComment.line, oldDocComment.column, oldDocComment.text)); + } + DOC.set(newDocComment); + } + + static void clearDoc() { + DocComment oldDocComment = DOC.get(); + if (oldDocComment != null) { + WARNINGS.get() + .add(String.format( + "Ignoring out-of-place documentation comment at line %d, column %d: \"%s\"\n" + + "Did you mean to use a multiline comment ( /* ... */ ) instead?", + oldDocComment.line, oldDocComment.column, oldDocComment.text)); + } + DOC.remove(); + } + + static String getDoc() { + DocComment docComment = DOC.get(); + DOC.remove(); + return docComment == null ? null : docComment.text; + } + + /* Package private to facilitate testing */ + static String stripIndents(String doc) { + Matcher starMatcher = STAR_INDENT.matcher(doc); + if (starMatcher.matches()) { + return doc.replaceAll("(?U)(?:^|(\\R)\\h*)\\Q" + starMatcher.group("stars") + "\\E\\h?", "$1"); + } + + Matcher whitespaceMatcher = WS_INDENT.matcher(doc); + if (whitespaceMatcher.matches()) { + return doc.replaceAll("(?U)(\\R)" + whitespaceMatcher.group("indent"), "$1"); + } + + return doc; + } + + private static class DocComment { + private final String text; + private final int line; + private final int column; + + DocComment(Token token) { + // The token is everything after the initial '/**', including all + // whitespace and the ending '*/' + int tokenLength = token.image.length(); + this.text = stripIndents(token.image.substring(0, tokenLength - 2).trim()); + this.line = token.beginLine; + // The preceding token was "/**", and the current token includes + // everything since (also all whitespace). Thus, we can safely subtract 3 + // from the token column to get the start of the doc comment. + this.column = token.beginColumn - 3; + } + } +} diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index e6977cbc069..667eece37cb 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -97,12 +97,12 @@ public class Idl implements Closeable { String namespace; Map names = new LinkedHashMap(); - private static final ThreadLocal DOC = new ThreadLocal(); - static void setDoc(String doc) { DOC.set(doc.trim()); } - static String getDoc() { - String doc = DOC.get(); - DOC.set(null); - return doc; + private List parserWarnings = Collections.emptyList(); + /** + * Return all warnings that were encountered while parsing. + */ + public List getWarningsAfterParsing() { + return parserWarnings; } public Idl(File inputFile) throws IOException { @@ -221,7 +221,7 @@ MORE : SPECIAL_TOKEN : { - <"*/" > {Idl.setDoc(image.substring(0, image.length()-2));} : DEFAULT + <"*/" > {DocCommentHelper.setDoc(matchedToken);} : DEFAULT } @@ -1021,13 +1021,17 @@ TOKEN : Protocol CompilationUnit(): { Protocol p; + DocCommentHelper.getAndClearWarnings(); // Throw away previous results. } { p = ProtocolDeclaration() ( < "\u001a" > )? ( )? - { return SchemaResolver.resolve(p); } + { + parserWarnings = DocCommentHelper.getAndClearWarnings(); + return SchemaResolver.resolve(p); + } } /* @@ -1056,7 +1060,7 @@ private Schema NamedSchemaDeclaration(Map props): } else if ("aliases".equals(key)) { // aliases for (String alias : getTextProps("aliases", props, token)) s.addAlias(alias); - } else { // add all other props + } else { // add all other properties Accessor.addProp(s, key, props.get(key)); } LogicalType logicalType = LogicalTypes.fromSchemaIgnoreInvalid(s); @@ -1106,10 +1110,10 @@ Protocol ProtocolDeclaration(): "protocol" name = Identifier() { - p = new Protocol(name, getDoc(), namespace); + p = new Protocol(name, DocCommentHelper.getDoc(), namespace); for (String key : props.keySet()) if ("namespace".equals(key)) { // already handled: ignore - } else { // add all other props + } else { // add all other properties Accessor.addProp(p, key, props.get(key)); } } @@ -1127,7 +1131,7 @@ Schema EnumDeclaration(): String defaultSymbol = null; } { - "enum" { String doc = getDoc(); } + "enum" { String doc = DocCommentHelper.getDoc(); } name = Identifier() symbols = EnumBody() [ defaultSymbol=Identifier() ] @@ -1267,7 +1271,7 @@ Schema FixedDeclaration(): "fixed" name = Identifier() "(" sizeTok = ")" ";" { - Schema s = Schema.createFixed(name, getDoc(), this.namespace, + Schema s = Schema.createFixed(name, DocCommentHelper.getDoc(), this.namespace, Integer.parseInt(sizeTok.image)); names.put(s.getFullName(), s); return s; @@ -1288,7 +1292,7 @@ Schema RecordDeclaration(): name = Identifier() { Schema result = Schema.createRecord( - name, getDoc(), this.namespace, isError); + name, DocCommentHelper.getDoc(), this.namespace, isError); names.put(result.getFullName(), result); } "{" @@ -1345,13 +1349,13 @@ void VariableDeclarator(Schema type, List fields): order = Field.Order.valueOf(getTextProp(key,props,token).toUpperCase()); boolean validate = !SchemaResolver.isUnresolvedSchema(type); - Field field = Accessor.createField(name, type, getDoc(), defaultValue, validate, order); + Field field = Accessor.createField(name, type, DocCommentHelper.getDoc(), defaultValue, validate, order); for (String key : props.keySet()) if ("order".equals(key)) { // already handled: ignore } else if ("aliases".equals(key)) { // aliases for (String alias : getTextProps("aliases", props, token)) field.addAlias(alias); - } else { // add all other props + } else { // add all other properties Accessor.addProp(field, key, props.get(key)); } fields.add(field); @@ -1364,7 +1368,7 @@ String MessageDocumentation(): { // Don't parse anything, just return the doc string { - return getDoc(); + return DocCommentHelper.getDoc(); } } diff --git a/lang/java/compiler/src/test/idl/input/comments.avdl b/lang/java/compiler/src/test/idl/input/comments.avdl new file mode 100644 index 00000000000..5c619965ba4 --- /dev/null +++ b/lang/java/compiler/src/test/idl/input/comments.avdl @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@namespace("testing") +protocol Comments { + /** Documented Enum */ + enum /** Dangling Enum1 */ DocumentedEnum /** Dangling Enum2 */ { + /** Dangling Enum3 */ A, + /** Dangling Enum4 */ B, + /** Dangling Enum5 */ C + /** Dangling Enum6 */} + /** Dangling Enum7 */= + /** Dangling Enum8 */ A + /** Dangling Enum9 */; + + // The "Dangling Enum9" doc comment above will be attributed to this enum. + enum NotUndocumentedEnum {D,E} + + /** Dangling Fixed1 */ fixed + /** Dangling Fixed2 */ DocumentedFixed + /** Dangling Fixed3 */( + /** Dangling Fixed4 */ 16 + /** Dangling Fixed5 */) + /** Documented Fixed Type */; + + fixed UndocumentedFixed(16); + + /** Dangling Error1 */ error + /** Documented Error */ DocumentedError + /** Dangling Field1 */{ + /** Dangling Field2 */string + /** Dangling Field3 */reason + /** Documented Field */; + /** Dangling Error2 */} + + // The "Dangling Error2" doc comment above will be attributed to this record. + record NotUndocumentedRecord { + string description; + } + + /** Documented Method */ void + /** Dangling Param1 */ documentedMethod + /** Dangling Param2 */( + /** Dangling Param3 */ string + /** Dangling Param4 */ message + /** Documented Parameter */) + /** Dangling Method1 */ throws + /** Dangling Method2 */ DocumentedError + /** Dangling Method3 */; + + // The "Dangling Method3" doc comment above will be attributed to this method. + void notUndocumentedMethod(string message); +} diff --git a/lang/java/compiler/src/test/idl/output/baseball.avpr b/lang/java/compiler/src/test/idl/output/baseball.avpr index d14c90624e8..715cdde8847 100644 --- a/lang/java/compiler/src/test/idl/output/baseball.avpr +++ b/lang/java/compiler/src/test/idl/output/baseball.avpr @@ -1,7 +1,7 @@ { "protocol" : "Baseball", "namespace" : "avro.examples.baseball", - "doc" : "* Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license agreements. See the NOTICE file\n * distributed with this work for additional information\n * regarding copyright ownership. The ASF licenses this file\n * to you under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance\n * with the License. You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.", + "doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", "types" : [ { "type" : "enum", "name" : "Position", diff --git a/lang/java/compiler/src/test/idl/output/comments.avpr b/lang/java/compiler/src/test/idl/output/comments.avpr new file mode 100644 index 00000000000..2d98962a576 --- /dev/null +++ b/lang/java/compiler/src/test/idl/output/comments.avpr @@ -0,0 +1,62 @@ +{ + "protocol" : "Comments", + "namespace" : "testing", + "types" : [ { + "type" : "enum", + "name" : "DocumentedEnum", + "doc" : "Documented Enum", + "symbols" : [ "A", "B", "C" ], + "default" : "A" + }, { + "type" : "enum", + "name" : "NotUndocumentedEnum", + "doc" : "Dangling Enum9", + "symbols" : [ "D", "E" ] + }, { + "type" : "fixed", + "name" : "DocumentedFixed", + "doc" : "Documented Fixed Type", + "size" : 16 + }, { + "type" : "fixed", + "name" : "UndocumentedFixed", + "size" : 16 + }, { + "type" : "error", + "name" : "DocumentedError", + "doc" : "Documented Error", + "fields" : [ { + "name" : "reason", + "type" : "string", + "doc" : "Documented Field" + } ] + }, { + "type" : "record", + "name" : "NotUndocumentedRecord", + "doc" : "Dangling Error2", + "fields" : [ { + "name" : "description", + "type" : "string" + } ] + } ], + "messages" : { + "documentedMethod" : { + "doc" : "Documented Method", + "request" : [ { + "name" : "message", + "type" : "string", + "doc" : "Documented Parameter" + } ], + "response" : "null", + "errors" : [ "DocumentedError" ] + }, + "notUndocumentedMethod" : { + "doc" : "Dangling Method3", + "request" : [ { + "name" : "message", + "type" : "string" + } ], + "response" : "null" + } + } +} diff --git a/lang/java/compiler/src/test/idl/output/import.avpr b/lang/java/compiler/src/test/idl/output/import.avpr index d2cc0d05956..1cb95394035 100644 --- a/lang/java/compiler/src/test/idl/output/import.avpr +++ b/lang/java/compiler/src/test/idl/output/import.avpr @@ -1,7 +1,7 @@ { "protocol" : "Import", "namespace" : "org.foo", - "doc" : "* Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license agreements. See the NOTICE file\n * distributed with this work for additional information\n * regarding copyright ownership. The ASF licenses this file\n * to you under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance\n * with the License. You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.", + "doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", "types" : [ { "type" : "enum", "name" : "Position", diff --git a/lang/java/compiler/src/test/idl/output/interop.avpr b/lang/java/compiler/src/test/idl/output/interop.avpr index 496fca57b27..6e56c7c9cee 100644 --- a/lang/java/compiler/src/test/idl/output/interop.avpr +++ b/lang/java/compiler/src/test/idl/output/interop.avpr @@ -1,7 +1,7 @@ { "protocol" : "InteropProtocol", "namespace" : "org.apache.avro", - "doc" : "* Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license agreements. See the NOTICE file\n * distributed with this work for additional information\n * regarding copyright ownership. The ASF licenses this file\n * to you under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance\n * with the License. You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.", + "doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", "types" : [ { "type" : "record", "name" : "Foo", @@ -91,4 +91,4 @@ } ] } ], "messages" : { } -} \ No newline at end of file +} diff --git a/lang/java/compiler/src/test/idl/output/mr_events.avpr b/lang/java/compiler/src/test/idl/output/mr_events.avpr index e9a32e16e07..8c6343664d6 100644 --- a/lang/java/compiler/src/test/idl/output/mr_events.avpr +++ b/lang/java/compiler/src/test/idl/output/mr_events.avpr @@ -1,7 +1,7 @@ { "protocol" : "Events", "namespace" : "org.apache.hadoop.mapreduce.jobhistory", - "doc" : "* Genavro format for a particular protocol found in Hadoop MapReduce.\n * Used as a test case/example to show that we can express real-world stuff more\n * succinctly.", + "doc" : "Genavro format for a particular protocol found in Hadoop MapReduce.\nUsed as a test case/example to show that we can express real-world stuff more\nsuccinctly.", "types" : [ { "type" : "record", "name" : "JhCounter", diff --git a/lang/java/compiler/src/test/idl/output/namespaces.avpr b/lang/java/compiler/src/test/idl/output/namespaces.avpr index ff12a3b4045..22ec760d5bf 100644 --- a/lang/java/compiler/src/test/idl/output/namespaces.avpr +++ b/lang/java/compiler/src/test/idl/output/namespaces.avpr @@ -1,7 +1,7 @@ { "protocol" : "TestNamespace", "namespace" : "avro.test.protocol", - "doc" : "* Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license agreements. See the NOTICE file\n * distributed with this work for additional information\n * regarding copyright ownership. The ASF licenses this file\n * to you under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance\n * with the License. You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.", + "doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", "types" : [ { "type" : "fixed", "name" : "FixedInOtherNamespace", @@ -48,4 +48,4 @@ } ], "messages" : { } -} \ No newline at end of file +} diff --git a/lang/java/compiler/src/test/idl/output/nestedimport.avpr b/lang/java/compiler/src/test/idl/output/nestedimport.avpr index ae763a8d68a..d421da416bb 100644 --- a/lang/java/compiler/src/test/idl/output/nestedimport.avpr +++ b/lang/java/compiler/src/test/idl/output/nestedimport.avpr @@ -1,7 +1,7 @@ { "protocol" : "nestedimport", "namespace" : "org.apache.avro.ipc.specific", - "doc" : "* Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license agreements. See the NOTICE file\n * distributed with this work for additional information\n * regarding copyright ownership. The ASF licenses this file\n * to you under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance\n * with the License. You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.", + "doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", "version" : "1.0.5", "types" : [ { "type" : "enum", @@ -50,4 +50,4 @@ "response" : "null" } } -} \ No newline at end of file +} diff --git a/lang/java/compiler/src/test/idl/output/reservedwords.avpr b/lang/java/compiler/src/test/idl/output/reservedwords.avpr index e01d23aa01b..79827202d30 100644 --- a/lang/java/compiler/src/test/idl/output/reservedwords.avpr +++ b/lang/java/compiler/src/test/idl/output/reservedwords.avpr @@ -1,7 +1,7 @@ { "protocol" : "Foo", "namespace" : null, - "doc" : "* Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license agreements. See the NOTICE file\n * distributed with this work for additional information\n * regarding copyright ownership. The ASF licenses this file\n * to you under the Apache License, Version 2.0 (the\n * \"License\"); you may not use this file except in compliance\n * with the License. You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.", + "doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements. See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership. The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at\n\n https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.", "types" : [ ], "messages" : { "error" : { @@ -13,4 +13,4 @@ "response" : "null" } } -} \ No newline at end of file +} diff --git a/lang/java/compiler/src/test/idl/output/simple.avpr b/lang/java/compiler/src/test/idl/output/simple.avpr index ab1c03c3d4b..438a4bd04e4 100644 --- a/lang/java/compiler/src/test/idl/output/simple.avpr +++ b/lang/java/compiler/src/test/idl/output/simple.avpr @@ -1,7 +1,7 @@ { "protocol" : "Simple", "namespace" : "org.apache.avro.test", - "doc" : "* A simple test case.", + "doc" : "A simple test case.", "version" : "1.0.5", "types" : [ { "type" : "enum", diff --git a/lang/java/compiler/src/test/idl/output/unicode.avpr b/lang/java/compiler/src/test/idl/output/unicode.avpr index 4809f6ad57a..67642e2189a 100644 --- a/lang/java/compiler/src/test/idl/output/unicode.avpr +++ b/lang/java/compiler/src/test/idl/output/unicode.avpr @@ -1,7 +1,7 @@ { "protocol" : "Протоколы", "namespace" : null, - "doc" : "* This is a test that UTF8 functions correctly.\n* このテストでは、UTF - 8で正しく機能している。\n* 这是一个测试,UTF - 8的正常运行。", + "doc" : "This is a test that UTF8 functions correctly.\nこのテストでは、UTF - 8で正しく機能している。\n这是一个测试,UTF - 8的正常运行。", "types" : [ { "type" : "record", "name" : "Структура", @@ -15,4 +15,4 @@ } ], "messages" : { } -} \ No newline at end of file +} diff --git a/lang/java/compiler/src/test/idl/output/uuid.avpr b/lang/java/compiler/src/test/idl/output/uuid.avpr index cffdba89335..c7a1e72d8b1 100644 --- a/lang/java/compiler/src/test/idl/output/uuid.avpr +++ b/lang/java/compiler/src/test/idl/output/uuid.avpr @@ -11,14 +11,14 @@ "type" : "string", "logicalType" : "uuid" }, - "doc" : "* Documentation must be provided for each attribute" + "doc" : "Documentation must be provided for each attribute" }, { "name" : "optionalString", "type" : [ "null", { "type" : "string", "logicalType" : "uuid" } ], - "doc" : "* a nullable uuid field" + "doc" : "a nullable uuid field" } ] } ], "messages" : { } diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/DocCommentHelperTest.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/DocCommentHelperTest.java new file mode 100644 index 00000000000..f88f8c3a8ff --- /dev/null +++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/DocCommentHelperTest.java @@ -0,0 +1,88 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.compiler.idl; + +import junit.framework.TestCase; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +public class DocCommentHelperTest extends TestCase { + public void testNoWarnings() { + DocCommentHelper.getAndClearWarnings(); // Clear warnings + + DocCommentHelper.setDoc(token(1, 1, "This is a token.")); + assertEquals(DocCommentHelper.getDoc(), "This is a token."); + DocCommentHelper.clearDoc(); // Should be a no-op. If not, it adds a warning. + assertEquals("There should be no warnings", emptyList(), DocCommentHelper.getAndClearWarnings()); + } + + /** + * Create a doc comment token. Does not include the initial '/**'. + * + * @param line the line where the comment starts + * @param column the column where the comment starts (the position + * of the '/**') + * @param tokenWithoutSuffix the comment content (without the trailing + * '*/') + * @return a mock token + */ + private Token token(int line, int column, String tokenWithoutSuffix) { + final Token token = new Token(); + token.image = tokenWithoutSuffix + "*/"; + token.beginLine = line; + token.beginColumn = column + 3; + return token; + } + + public void testWarningAfterSecondDoc() { + DocCommentHelper.getAndClearWarnings(); // Clear warnings + + DocCommentHelper.setDoc(token(3, 2, "This is the first token.")); + DocCommentHelper.setDoc(token(5, 4, "This is the second token.")); + assertEquals(DocCommentHelper.getDoc(), "This is the second token."); + assertEquals("There should be a warning", singletonList( + "Found documentation comment at line 5, column 4. Ignoring previous one at line 3, column 2: \"This is the first token.\"\n" + + "Did you mean to use a multiline comment ( /* ... */ ) instead?"), + DocCommentHelper.getAndClearWarnings()); + } + + public void testWarningAfterUnusedDoc() { + DocCommentHelper.getAndClearWarnings(); // Clear warnings + + DocCommentHelper.setDoc(token(3, 2, "This is a token.")); + DocCommentHelper.clearDoc(); + assertNull(DocCommentHelper.getDoc()); + assertEquals("There should be a warning", + singletonList("Ignoring out-of-place documentation comment at line 3, column 2: \"This is a token.\"\n" + + "Did you mean to use a multiline comment ( /* ... */ ) instead?"), + DocCommentHelper.getAndClearWarnings()); + } + + public void testStripIndentsFromDocCommentWithStars() { + String parsedComment = "* First line\n\t * Second Line\n\t * * Third Line\n\t *\n\t * Fifth Line"; + String schemaComment = "First line\nSecond Line\n* Third Line\n\nFifth Line"; + assertEquals(schemaComment, DocCommentHelper.stripIndents(parsedComment)); + } + + public void testStripIndentsFromDocCommentWithoutStars() { + String parsedComment = "First line\n\t Second Line\n\t * Third Line\n\t \n\t Fifth Line"; + String schemaComment = "First line\nSecond Line\n * Third Line\n \n Fifth Line"; + assertEquals(schemaComment, DocCommentHelper.stripIndents(parsedComment)); + } +} diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java index cb72bdb7da1..7e609ba5c7a 100644 --- a/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java +++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.avro.Protocol; +import org.apache.avro.Schema; import org.junit.Before; import org.junit.Test; @@ -32,10 +33,13 @@ import java.io.InputStreamReader; import java.net.URL; import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -110,6 +114,54 @@ public void writeTests() throws Exception { } } + @Test + public void testDocCommentsAndWarnings() throws Exception { + try (Idl parser = new Idl(new File(TEST_INPUT_DIR, "comments.avdl"))) { + final Protocol protocol = parser.CompilationUnit(); + final List warnings = parser.getWarningsAfterParsing(); + + assertEquals("Documented Enum", protocol.getType("testing.DocumentedEnum").getDoc()); + assertEquals("Dangling Enum9", protocol.getType("testing.NotUndocumentedEnum").getDoc()); // Arguably a bug + assertEquals("Documented Fixed Type", protocol.getType("testing.DocumentedFixed").getDoc()); + assertNull(protocol.getType("testing.UndocumentedFixed").getDoc()); + final Schema documentedError = protocol.getType("testing.DocumentedError"); + assertEquals("Documented Error", documentedError.getDoc()); + assertEquals("Documented Field", documentedError.getField("reason").doc()); + assertEquals("Dangling Error2", protocol.getType("testing.NotUndocumentedRecord").getDoc()); // Arguably a bug + final Map messages = protocol.getMessages(); + assertEquals("Documented Method", messages.get("documentedMethod").getDoc()); + assertEquals("Documented Parameter", messages.get("documentedMethod").getRequest().getField("message").doc()); + assertEquals("Dangling Method3", messages.get("notUndocumentedMethod").getDoc()); // Arguably a bug + + assertEquals(23, warnings.size()); + final String pattern = "Found documentation comment at line %d, column %d. Ignoring previous one at line %d, column %d: \"%s\"" + + "\nDid you mean to use a multiline comment ( /* ... */ ) instead?"; + assertEquals(String.format(pattern, 21, 47, 21, 10, "Dangling Enum1"), warnings.get(0)); + assertEquals(String.format(pattern, 22, 9, 21, 47, "Dangling Enum2"), warnings.get(1)); + assertEquals(String.format(pattern, 23, 9, 22, 9, "Dangling Enum3"), warnings.get(2)); + assertEquals(String.format(pattern, 24, 9, 23, 9, "Dangling Enum4"), warnings.get(3)); + assertEquals(String.format(pattern, 25, 5, 24, 9, "Dangling Enum5"), warnings.get(4)); + assertEquals(String.format(pattern, 26, 5, 25, 5, "Dangling Enum6"), warnings.get(5)); + assertEquals(String.format(pattern, 27, 5, 26, 5, "Dangling Enum7"), warnings.get(6)); + assertEquals(String.format(pattern, 28, 5, 27, 5, "Dangling Enum8"), warnings.get(7)); + assertEquals(String.format(pattern, 34, 5, 33, 5, "Dangling Fixed1"), warnings.get(8)); + assertEquals(String.format(pattern, 35, 5, 34, 5, "Dangling Fixed2"), warnings.get(9)); + assertEquals(String.format(pattern, 36, 5, 35, 5, "Dangling Fixed3"), warnings.get(10)); + assertEquals(String.format(pattern, 37, 5, 36, 5, "Dangling Fixed4"), warnings.get(11)); + assertEquals(String.format(pattern, 38, 5, 37, 5, "Dangling Fixed5"), warnings.get(12)); + assertEquals(String.format(pattern, 43, 5, 42, 5, "Dangling Error1"), warnings.get(13)); + assertEquals(String.format(pattern, 45, 5, 44, 5, "Dangling Field1"), warnings.get(14)); + assertEquals(String.format(pattern, 46, 5, 45, 5, "Dangling Field2"), warnings.get(15)); + assertEquals(String.format(pattern, 47, 5, 46, 5, "Dangling Field3"), warnings.get(16)); + assertEquals(String.format(pattern, 57, 5, 56, 5, "Dangling Param1"), warnings.get(17)); + assertEquals(String.format(pattern, 58, 9, 57, 5, "Dangling Param2"), warnings.get(18)); + assertEquals(String.format(pattern, 59, 9, 58, 9, "Dangling Param3"), warnings.get(19)); + assertEquals(String.format(pattern, 60, 5, 59, 9, "Dangling Param4"), warnings.get(20)); + assertEquals(String.format(pattern, 62, 5, 61, 5, "Dangling Method1"), warnings.get(21)); + assertEquals(String.format(pattern, 63, 5, 62, 5, "Dangling Method2"), warnings.get(22)); + } + } + /** * An individual comparison test */ @@ -148,9 +200,9 @@ public void write() throws Exception { } private static String slurp(File f) throws IOException { - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8")); + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8)); - String line = null; + String line; StringBuilder builder = new StringBuilder(); while ((line = in.readLine()) != null) { builder.append(line); diff --git a/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/IDLProtocolMojo.java b/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/IDLProtocolMojo.java index 9ed90576141..0c9228c6133 100644 --- a/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/IDLProtocolMojo.java +++ b/lang/java/maven-plugin/src/main/java/org/apache/avro/mojo/IDLProtocolMojo.java @@ -85,6 +85,9 @@ protected void doCompile(String filename, File sourceDirectory, File outputDirec try (Idl parser = new Idl(new File(sourceDirectory, filename), projPathLoader)) { Protocol p = parser.CompilationUnit(); + for (String warning : parser.getWarningsAfterParsing()) { + getLog().warn(warning); + } String json = p.toString(true); Protocol protocol = Protocol.parse(json); final SpecificCompiler compiler = new SpecificCompiler(protocol); diff --git a/lang/java/maven-plugin/src/test/avro/AvdlClasspathImport.avdl b/lang/java/maven-plugin/src/test/avro/AvdlClasspathImport.avdl index 68b6dc4a85d..fd799d3dda5 100644 --- a/lang/java/maven-plugin/src/test/avro/AvdlClasspathImport.avdl +++ b/lang/java/maven-plugin/src/test/avro/AvdlClasspathImport.avdl @@ -19,6 +19,8 @@ protocol IdlClasspathImportTest { import idl "avro/User.avdl"; + /** Ignored Doc Comment */ + /** IDL User */ record IdlUserWrapper { union { null, test.IdlUser } wrapped; } diff --git a/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestIDLProtocolMojo.java b/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestIDLProtocolMojo.java index 7dabdd0324f..226ca6de09d 100644 --- a/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestIDLProtocolMojo.java +++ b/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestIDLProtocolMojo.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -37,6 +38,8 @@ public class TestIDLProtocolMojo extends AbstractAvroMojoTest { @Test public void testIdlProtocolMojo() throws Exception { final IDLProtocolMojo mojo = (IDLProtocolMojo) lookupMojo("idl-protocol", testPom); + final TestLog log = new TestLog(); + mojo.setLog(log); assertNotNull(mojo); mojo.execute(); @@ -48,11 +51,18 @@ public void testIdlProtocolMojo() throws Exception { final String idlUserContent = FileUtils.fileRead(new File(outputDir, "IdlUser.java")); assertTrue(idlUserContent.contains("java.time.Instant")); + + assertEquals(Collections.singletonList( + "[WARN] Found documentation comment at line 23, column 5. Ignoring previous one at line 22, column 5: \"Ignored Doc Comment\"" + + "\nDid you mean to use a multiline comment ( /* ... */ ) instead?"), + log.getLogEntries()); } @Test public void testSetCompilerVelocityAdditionalTools() throws Exception { final IDLProtocolMojo mojo = (IDLProtocolMojo) lookupMojo("idl-protocol", injectingVelocityToolsTestPom); + final TestLog log = new TestLog(); + mojo.setLog(log); assertNotNull(mojo); mojo.execute(); @@ -65,5 +75,8 @@ public void testSetCompilerVelocityAdditionalTools() throws Exception { final String schemaUserContent = FileUtils.fileRead(new File(outputDir, "IdlUser.java")); assertTrue(schemaUserContent.contains("It works!")); + + // The previous test already verifies the warnings. + assertFalse(log.getLogEntries().isEmpty()); } } diff --git a/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestLog.java b/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestLog.java new file mode 100644 index 00000000000..6de25ca9fdc --- /dev/null +++ b/lang/java/maven-plugin/src/test/java/org/apache/avro/mojo/TestLog.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.avro.mojo; + +import org.apache.maven.plugin.logging.Log; +import org.apache.velocity.util.StringBuilderWriter; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +public class TestLog implements Log { + + private final List logEntries = new ArrayList<>(); + + public List getLogEntries() { + return logEntries; + } + + private void log(String level, CharSequence content, Throwable error) { + StringBuilder buffer = new StringBuilder(); + buffer.append('[').append(level).append("]"); + if (content != null) { + buffer.append(' ').append(content); + } + if (error != null) { + buffer.append(content == null ? " " : System.lineSeparator()); + error.printStackTrace(new PrintWriter(new StringBuilderWriter(buffer))); + } + logEntries.add(buffer.toString()); + } + + @Override + public boolean isDebugEnabled() { + return true; + } + + @Override + public void debug(CharSequence content) { + debug(content, null); + } + + @Override + public void debug(CharSequence content, Throwable error) { + log("DEBUG", content, error); + } + + @Override + public void debug(Throwable error) { + debug(null, error); + } + + @Override + public boolean isInfoEnabled() { + return true; + } + + @Override + public void info(CharSequence content) { + info(content, null); + } + + @Override + public void info(CharSequence content, Throwable error) { + log("INFO", content, error); + } + + @Override + public void info(Throwable error) { + info(null, error); + } + + @Override + public boolean isWarnEnabled() { + return true; + } + + @Override + public void warn(CharSequence content) { + warn(content, null); + } + + @Override + public void warn(CharSequence content, Throwable error) { + log("WARN", content, error); + } + + @Override + public void warn(Throwable error) { + warn(null, error); + } + + @Override + public boolean isErrorEnabled() { + return true; + } + + @Override + public void error(CharSequence content) { + error(content, null); + } + + @Override + public void error(CharSequence content, Throwable error) { + log("ERROR", content, error); + } + + @Override + public void error(Throwable error) { + error(null, error); + } +} diff --git a/lang/java/tools/src/main/java/org/apache/avro/tool/IdlToSchemataTool.java b/lang/java/tools/src/main/java/org/apache/avro/tool/IdlToSchemataTool.java index fadd0f95c21..df43d6d2ac7 100644 --- a/lang/java/tools/src/main/java/org/apache/avro/tool/IdlToSchemataTool.java +++ b/lang/java/tools/src/main/java/org/apache/avro/tool/IdlToSchemataTool.java @@ -18,6 +18,7 @@ package org.apache.avro.tool; +import org.apache.avro.Protocol; import org.apache.avro.Schema; import org.apache.avro.compiler.idl.Idl; @@ -46,7 +47,12 @@ public int run(InputStream in, PrintStream out, PrintStream err, List ar Idl parser = new Idl(new File(args.get(0))); File outputDirectory = getOutputDirectory(args); - for (Schema schema : parser.CompilationUnit().getTypes()) { + final Protocol protocol = parser.CompilationUnit(); + final List warnings = parser.getWarningsAfterParsing(); + for (String warning : warnings) { + err.println("Warning: " + warning); + } + for (Schema schema : protocol.getTypes()) { print(schema, outputDirectory, pretty); } parser.close(); diff --git a/lang/java/tools/src/main/java/org/apache/avro/tool/IdlTool.java b/lang/java/tools/src/main/java/org/apache/avro/tool/IdlTool.java index e3e9af28263..b32b0db76a8 100644 --- a/lang/java/tools/src/main/java/org/apache/avro/tool/IdlTool.java +++ b/lang/java/tools/src/main/java/org/apache/avro/tool/IdlTool.java @@ -59,6 +59,10 @@ public int run(InputStream in, PrintStream out, PrintStream err, List ar } Protocol p = parser.CompilationUnit(); + final List warnings = parser.getWarningsAfterParsing(); + for (String warning : warnings) { + err.println("Warning: " + warning); + } try { parseOut.print(p.toString(true)); } finally { diff --git a/lang/java/tools/src/test/idl/protocol.avpr b/lang/java/tools/src/test/idl/protocol.avpr new file mode 100644 index 00000000000..1070c65dab7 --- /dev/null +++ b/lang/java/tools/src/test/idl/protocol.avpr @@ -0,0 +1,90 @@ +{ + "protocol" : "Simple", + "namespace" : "org.apache.avro.test", + "doc" : "An example protocol in Avro IDL", + "types" : [ { + "type" : "enum", + "name" : "Kind", + "symbols" : [ "FOO", "BAR", "BAZ" ], + "aliases" : [ "org.foo.KindOf" ] + }, { + "type" : "fixed", + "name" : "MD5", + "size" : 16 + }, { + "type" : "record", + "name" : "TestRecord", + "fields" : [ { + "name" : "name", + "type" : "string", + "order" : "ignore" + }, { + "name" : "kind", + "type" : "Kind", + "order" : "descending" + }, { + "name" : "hash", + "type" : "MD5" + }, { + "name" : "nullableHash", + "type" : [ "MD5", "null" ], + "aliases" : [ "hash" ] + }, { + "name" : "arrayOfLongs", + "type" : { + "type" : "array", + "items" : "long" + } + } ] + }, { + "type" : "error", + "name" : "TestError", + "fields" : [ { + "name" : "message", + "type" : "string" + } ] + } ], + "messages" : { + "hello" : { + "request" : [ { + "name" : "greeting", + "type" : "string" + } ], + "response" : "string" + }, + "echo" : { + "request" : [ { + "name" : "record", + "type" : "TestRecord" + } ], + "response" : "TestRecord" + }, + "add" : { + "request" : [ { + "name" : "arg1", + "type" : "int" + }, { + "name" : "arg2", + "type" : "int" + } ], + "response" : "int" + }, + "echoBytes" : { + "request" : [ { + "name" : "data", + "type" : "bytes" + } ], + "response" : "bytes" + }, + "error" : { + "request" : [ ], + "response" : "null", + "errors" : [ "TestError" ] + }, + "ping" : { + "request" : [ ], + "response" : "null", + "one-way" : true + } + } +} diff --git a/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlToSchemataTool.java b/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlToSchemataTool.java index b2223c96e10..b6264f8a81a 100644 --- a/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlToSchemataTool.java +++ b/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlToSchemataTool.java @@ -19,9 +19,16 @@ import static org.junit.Assert.assertEquals; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.junit.Test; @@ -32,10 +39,35 @@ public void testSplitIdlIntoSchemata() throws Exception { String idl = "src/test/idl/protocol.avdl"; String outdir = "target/test-split"; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); List arglist = Arrays.asList(idl, outdir); - new IdlToSchemataTool().run(null, null, null, arglist); + new IdlToSchemataTool().run(null, null, new PrintStream(buffer), arglist); String[] files = new File(outdir).list(); assertEquals(4, files.length); + + String warnings = readPrintStreamBuffer(buffer); + assertEquals( + "Warning: Found documentation comment at line 19, column 1. Ignoring previous one at line 1, column 1: \"" + + "Licensed to the Apache Software Foundation (ASF) under one\n" + + "or more contributor license agreements. See the NOTICE file\n" + + "distributed with this work for additional information\n" + + "regarding copyright ownership. The ASF licenses this file\n" + + "to you under the Apache License, Version 2.0 (the\n" + + "\"License\"); you may not use this file except in compliance\n" + + "with the License. You may obtain a copy of the License at\n\n" + + " https://www.apache.org/licenses/LICENSE-2.0\n\n" + + "Unless required by applicable law or agreed to in writing, software\n" + + "distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + "See the License for the specific language governing permissions and\n" + "limitations under the License." + + "\"\nDid you mean to use a multiline comment ( /* ... */ ) instead?", + warnings); + } + + private String readPrintStreamBuffer(ByteArrayOutputStream buffer) { + BufferedReader reader = new BufferedReader( + new InputStreamReader(new ByteArrayInputStream(buffer.toByteArray()), Charset.defaultCharset())); + return reader.lines().collect(Collectors.joining("\n")); } } diff --git a/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlTool.java b/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlTool.java new file mode 100644 index 00000000000..715655fbe15 --- /dev/null +++ b/lang/java/tools/src/test/java/org/apache/avro/tool/TestIdlTool.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.tool; + +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +public class TestIdlTool { + + @Test + public void testWriteIdlAsProtocol() throws Exception { + String idl = "src/test/idl/protocol.avdl"; + String protocol = "src/test/idl/protocol.avpr"; + String outfile = "target/test-protocol.avpr"; + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + List arglist = Arrays.asList(idl, outfile); + new IdlTool().run(null, null, new PrintStream(buffer), arglist); + + assertEquals(readFileAsString(protocol), readFileAsString(outfile)); + + String warnings = readPrintStreamBuffer(buffer); + assertEquals( + "Warning: Found documentation comment at line 19, column 1. Ignoring previous one at line 1, column 1: \"" + + "Licensed to the Apache Software Foundation (ASF) under one\n" + + "or more contributor license agreements. See the NOTICE file\n" + + "distributed with this work for additional information\n" + + "regarding copyright ownership. The ASF licenses this file\n" + + "to you under the Apache License, Version 2.0 (the\n" + + "\"License\"); you may not use this file except in compliance\n" + + "with the License. You may obtain a copy of the License at\n\n" + + " https://www.apache.org/licenses/LICENSE-2.0\n\n" + + "Unless required by applicable law or agreed to in writing, software\n" + + "distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + "See the License for the specific language governing permissions and\n" + "limitations under the License." + + "\"\nDid you mean to use a multiline comment ( /* ... */ ) instead?", + warnings); + } + + private String readFileAsString(String filePath) throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + return reader.lines().collect(Collectors.joining("\n")); + } + } + + private String readPrintStreamBuffer(ByteArrayOutputStream buffer) { + BufferedReader reader = new BufferedReader( + new InputStreamReader(new ByteArrayInputStream(buffer.toByteArray()), Charset.defaultCharset())); + return reader.lines().collect(Collectors.joining("\n")); + } +} From 69acacd50e06e489e953f8948ee6a36759c814a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 19:06:58 +0100 Subject: [PATCH 0020/1479] Bump protobuf-java from 3.17.3 to 3.19.1 in /lang/java (#1421) Bumps [protobuf-java](https://github.com/protocolbuffers/protobuf) from 3.17.3 to 3.19.1. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/master/generate_changelog.py) - [Commits](https://github.com/protocolbuffers/protobuf/compare/v3.17.3...v3.19.1) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- lang/java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/java/pom.xml b/lang/java/pom.xml index d83003c22bd..12e78d122e9 100644 --- a/lang/java/pom.xml +++ b/lang/java/pom.xml @@ -44,7 +44,7 @@ 5.0.4 4.13.2 4.1.70.Final - 3.17.3 + 3.19.1 0.15.0 1.7.32 1.1.8.4 From d568e6d618e87ce176ba4f4dce29f44dc6da0507 Mon Sep 17 00:00:00 2001 From: RyanSkraba Date: Tue, 14 Dec 2021 18:48:24 +0100 Subject: [PATCH 0021/1479] AVRO-3268: Fix whitespace error in PHP lint (#1428) --- lang/php/lib/Datum/AvroIOBinaryDecoder.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lang/php/lib/Datum/AvroIOBinaryDecoder.php b/lang/php/lib/Datum/AvroIOBinaryDecoder.php index 7bf17e77ae3..870f56bd48b 100644 --- a/lang/php/lib/Datum/AvroIOBinaryDecoder.php +++ b/lang/php/lib/Datum/AvroIOBinaryDecoder.php @@ -34,7 +34,6 @@ */ class AvroIOBinaryDecoder { - /** * @var AvroIO */ From c528cfd7582ccb67da5789bc6b114294f89805f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20E=2E=20Hern=C3=A1ndez=20Cuervo?= Date: Tue, 14 Dec 2021 13:12:06 -0500 Subject: [PATCH 0022/1479] AVRO-3269: Add missing dependencies to Perl Test workflow (#1430) --- .github/workflows/test-lang-perl.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-lang-perl.yml b/.github/workflows/test-lang-perl.yml index bed6c367023..a73533c0eee 100644 --- a/.github/workflows/test-lang-perl.yml +++ b/.github/workflows/test-lang-perl.yml @@ -63,7 +63,11 @@ jobs: Module::Install::Repository \ Regexp::Common \ Try::Tiny \ - inc::Module::Install + inc::Module::Install \ + Module::Install::ReadmeFromPod \ + Test::Exception \ + IO::String \ + Object::Tiny - name: Lint run: ./build.sh lint From 8a5fc3cd17bdf6211097daf237e1e149efa78b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20E=2E=20Hern=C3=A1ndez=20Cuervo?= Date: Wed, 15 Dec 2021 18:27:09 +0100 Subject: [PATCH 0023/1479] AVRO-3263: Fix warning in Perl encoder when validating a long field (#1422) * AVRO-3258: Fix warning in Perl encoder when validating a long field - Disable warnings in the limited scope of "long" validation that uses pack and unpack. It is unnecessary as warnings don't affect the validation outcome and in some scenarios this validation is expected to fail. - Add test cases to validate the fix * AVRO-3258: Fix warning in Perl encoder when validating a long field - Check explicitly and return early if $data is undefined. --- lang/perl/lib/Avro/Schema.pm | 1 + lang/perl/t/02_bin_encode.t | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lang/perl/lib/Avro/Schema.pm b/lang/perl/lib/Avro/Schema.pm index 356c5ba0823..5240caed3ea 100644 --- a/lang/perl/lib/Avro/Schema.pm +++ b/lang/perl/lib/Avro/Schema.pm @@ -284,6 +284,7 @@ sub is_data_valid { } if ($type eq 'long') { if ($Config{use64bitint}) { + return 0 unless defined $data; my $packed_int = pack "q", $data; my $unpacked_int = unpack "q", $packed_int; return $unpacked_int eq $data ? 1 : 0; diff --git a/lang/perl/t/02_bin_encode.t b/lang/perl/t/02_bin_encode.t index d84aecfeaee..d64b15bf997 100644 --- a/lang/perl/t/02_bin_encode.t +++ b/lang/perl/t/02_bin_encode.t @@ -153,4 +153,34 @@ EOJ is $enc, "\x00\x02\x61", "Binary_Encodings.Complex_Types.Unions-a"; } +# unions other cases +{ + my $schema = Avro::Schema->parse(<encode( + schema => $schema, + data => { dim => 10 }, + emit_cb => sub { + $enc .= ${ $_[0] } + }, + ); + is $enc, "\x02\x14", "Binary_Encodings.Complex_Types.Unions-record-with-long-field"; + is $warning, 0, "Binary_Encodings.Complex_Types.Unions-record-with-long-field-nowarning"; +} + done_testing; From 895cdc8e2ebbf0341f292ff4ea684bf9cfbc68cb Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Sat, 18 Dec 2021 00:45:12 +0000 Subject: [PATCH 0024/1479] AVRO-3252: Add hasattr check for mode attr in DataFileReader (#1406) The DataFileWriter class constructor checks for the presence of a mode attribute before accessing it, but the DataFileReader does not. This means that it is possible to use the DataFileWriter to write data to in memory binary streams using io.BytesIO, but it is not possible to read from them in the same manner. This commit adds the same check to the DataFileReader class. --- lang/py/avro/datafile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/py/avro/datafile.py b/lang/py/avro/datafile.py index 22bf2dd60da..11d9a3c099b 100644 --- a/lang/py/avro/datafile.py +++ b/lang/py/avro/datafile.py @@ -315,7 +315,7 @@ class DataFileReader(_DataFileMetadata): # TODO(hammer): allow user to specify the encoder def __init__(self, reader: IO[AnyStr], datum_reader: avro.io.DatumReader) -> None: - if "b" not in reader.mode: + if hasattr(reader, "mode") and "b" not in reader.mode: warnings.warn(avro.errors.AvroWarning(f"Reader binary data from a reader {reader!r} that's opened for text")) bytes_reader = getattr(reader, "buffer", reader) self._reader = bytes_reader From a946ea706b933606540bc2afae4b81cf14cdbeb0 Mon Sep 17 00:00:00 2001 From: "Michael A. Smith" Date: Fri, 17 Dec 2021 20:41:16 -0500 Subject: [PATCH 0025/1479] AVRO-3721 Support Python 3.10; Fix Annotations (#1432) * Add Python 3.10 to Tox to test the latest version of Python. * Fix Type Checks * Implement Github Actions for Python 3.10 * Add Python 3.10 in Dockerfile, BUILD.md, and setup.cfg. --- .github/workflows/test-lang-py.yml | 6 ++++-- BUILD.md | 2 +- lang/py/avro/__main__.py | 5 ++++- lang/py/avro/datafile.py | 12 ++++++------ lang/py/avro/io.py | 14 +++++++------- lang/py/setup.cfg | 1 + lang/py/tox.ini | 1 + share/docker/Dockerfile | 9 +++++---- 8 files changed, 29 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test-lang-py.yml b/.github/workflows/test-lang-py.yml index 19522c01b7e..b8f9800d3cd 100644 --- a/.github/workflows/test-lang-py.yml +++ b/.github/workflows/test-lang-py.yml @@ -36,6 +36,7 @@ jobs: fail-fast: false matrix: python: + - '3.10' - '3.9' - '3.8' - '3.7' @@ -64,11 +65,11 @@ jobs: python3 -m pip install --upgrade pip setuptools tox-wheel - name: Lint - if: ${{ matrix.python == '3.9' }} + if: ${{ matrix.python == '3.10' }} run: python3 -m tox -e lint - name: Typechecks - if: ${{ matrix.python == '3.9' }} + if: ${{ matrix.python == '3.10' }} run: python3 -m tox -e typechecks - name: Test @@ -81,6 +82,7 @@ jobs: fail-fast: false matrix: python: + - '3.10' - '3.9' - '3.8' - '3.7' diff --git a/BUILD.md b/BUILD.md index c09994e67fb..196456f0b56 100644 --- a/BUILD.md +++ b/BUILD.md @@ -6,7 +6,7 @@ The following packages must be installed before Avro can be built: - Java: JDK 1.8, Maven 3 or better, protobuf-compile - PHP: php7, phpunit, php7-gmp - - Python 3: 3.5 or greater + - Python 3: 3.6 or greater - C: gcc, cmake, asciidoc, source-highlight, Jansson, pkg-config - C++: cmake 3.7.2 or greater, g++, flex, bison, libboost-dev - C#: .NET Core 2.2 SDK diff --git a/lang/py/avro/__main__.py b/lang/py/avro/__main__.py index 423de59ed63..44fda88252b 100755 --- a/lang/py/avro/__main__.py +++ b/lang/py/avro/__main__.py @@ -171,7 +171,10 @@ def convert_union(value: str, field: avro.schema.Field) -> Union[int, float, str def iter_csv(info: IO[AnyStr], schema: avro.schema.RecordSchema) -> Generator[Dict[str, object], None, None]: header = [field.name for field in schema.fields] - for row in csv.reader(getattr(i, "decode", lambda: i)() for i in info): + # If i is bytes, decode into a string. + # If i is a string, no need to decode. + csv_data = (cast(str, getattr(i, "decode", lambda: i)()) for i in info) + for row in csv.reader(csv_data): values = [convert(v, f) for v, f in zip(row, schema.fields)] yield dict(zip(header, values)) diff --git a/lang/py/avro/datafile.py b/lang/py/avro/datafile.py index 11d9a3c099b..d39a91131e3 100644 --- a/lang/py/avro/datafile.py +++ b/lang/py/avro/datafile.py @@ -160,7 +160,7 @@ class DataFileWriter(_DataFileMetadata): _datum_writer: avro.io.DatumWriter _encoder: avro.io.BinaryEncoder _header_written: bool - _writer: BinaryIO + _writer: IO[bytes] block_count: int sync_marker: bytes @@ -170,7 +170,7 @@ def __init__( """If the schema is not present, presume we're appending.""" if hasattr(writer, "mode") and "b" not in writer.mode: warnings.warn(avro.errors.AvroWarning(f"Writing binary data to a writer {writer!r} that's opened for text")) - bytes_writer = getattr(writer, "buffer", writer) + bytes_writer = cast(IO[bytes], getattr(writer, "buffer", writer)) self._writer = bytes_writer self._encoder = avro.io.BinaryEncoder(bytes_writer) self._datum_writer = datum_writer @@ -202,7 +202,7 @@ def __init__( self.datum_writer.writers_schema = writers_schema @property - def writer(self) -> BinaryIO: + def writer(self) -> IO[bytes]: return self._writer @property @@ -307,7 +307,7 @@ class DataFileReader(_DataFileMetadata): _datum_reader: avro.io.DatumReader _file_length: int _raw_decoder: avro.io.BinaryDecoder - _reader: BinaryIO + _reader: IO[bytes] block_count: int sync_marker: bytes @@ -317,7 +317,7 @@ class DataFileReader(_DataFileMetadata): def __init__(self, reader: IO[AnyStr], datum_reader: avro.io.DatumReader) -> None: if hasattr(reader, "mode") and "b" not in reader.mode: warnings.warn(avro.errors.AvroWarning(f"Reader binary data from a reader {reader!r} that's opened for text")) - bytes_reader = getattr(reader, "buffer", reader) + bytes_reader = cast(IO[bytes], getattr(reader, "buffer", reader)) self._reader = bytes_reader self._raw_decoder = avro.io.BinaryDecoder(bytes_reader) self._datum_decoder = None # Maybe reset at every block. @@ -337,7 +337,7 @@ def __iter__(self) -> "DataFileReader": return self @property - def reader(self) -> BinaryIO: + def reader(self) -> IO[bytes]: return self._reader @property diff --git a/lang/py/avro/io.py b/lang/py/avro/io.py index d8b0f94128d..59628b0a13d 100644 --- a/lang/py/avro/io.py +++ b/lang/py/avro/io.py @@ -90,7 +90,7 @@ import struct import warnings from typing import ( - BinaryIO, + IO, Deque, Generator, Iterable, @@ -206,16 +206,16 @@ def _map_iterator(node: ValidationNode) -> ValidationNodeGeneratorType: class BinaryDecoder: """Read leaf values.""" - _reader: BinaryIO + _reader: IO[bytes] - def __init__(self, reader: BinaryIO) -> None: + def __init__(self, reader: IO[bytes]) -> None: """ reader is a Python object on which we can call read, seek, and tell. """ self._reader = reader @property - def reader(self) -> BinaryIO: + def reader(self) -> IO[bytes]: return self._reader def read(self, n: int) -> bytes: @@ -410,16 +410,16 @@ def skip(self, n: int) -> None: class BinaryEncoder: """Write leaf values.""" - _writer: BinaryIO + _writer: IO[bytes] - def __init__(self, writer: BinaryIO) -> None: + def __init__(self, writer: IO[bytes]) -> None: """ writer is a Python object on which we can call write. """ self._writer = writer @property - def writer(self) -> BinaryIO: + def writer(self) -> IO[bytes]: return self._writer def write(self, datum: bytes) -> None: diff --git a/lang/py/setup.cfg b/lang/py/setup.cfg index 487b322b0e7..adbeb0ff85e 100644 --- a/lang/py/setup.cfg +++ b/lang/py/setup.cfg @@ -37,6 +37,7 @@ classifiers = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 Development Status :: 5 - Production/Stable [bdist_wheel] diff --git a/lang/py/tox.ini b/lang/py/tox.ini index bbd42d6ee86..ab2ceaa2e91 100644 --- a/lang/py/tox.ini +++ b/lang/py/tox.ini @@ -24,6 +24,7 @@ envlist = py37 py38 py39 + py310 pypy3.6 pypy3.7 diff --git a/share/docker/Dockerfile b/share/docker/Dockerfile index 619861e6f2c..7b8ce55a1f7 100644 --- a/share/docker/Dockerfile +++ b/share/docker/Dockerfile @@ -66,7 +66,11 @@ RUN apt-get -qqy update \ valgrind \ vim \ wget \ - python3.6 python3.7 python3.8 python3.9 \ + python3.6 \ + python3.7 \ + python3.8 \ + python3.9 \ + python3.10 \ && apt-get -qqy clean # Install PHP @@ -194,7 +198,4 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --de ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/ ENV PATH $JAVA_HOME/bin:$PATH - -RUN apt-get -qqy install python3.6 python3.7 python3.9 - CMD ["/bin/bash", "-i"] From 57e0bbf961d0bffafe6dceddadc65f0defd84d80 Mon Sep 17 00:00:00 2001 From: Vegard Solberg <39623480+vegraux@users.noreply.github.com> Date: Sat, 18 Dec 2021 02:59:46 +0100 Subject: [PATCH 0026/1479] AVRO-3218 Fix parsing of logicalType = decimal (#1350) Co-authored-by: Vegard Solberg --- lang/py/avro/schema.py | 2 +- lang/py/avro/test/test_schema.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/py/avro/schema.py b/lang/py/avro/schema.py index 1d3b36966c1..73371d5d4dd 100644 --- a/lang/py/avro/schema.py +++ b/lang/py/avro/schema.py @@ -1067,7 +1067,7 @@ def get_other_props(all_props: Mapping[str, object], reserved_props: Sequence[st def make_bytes_decimal_schema(other_props): """Make a BytesDecimalSchema from just other_props.""" - return BytesDecimalSchema(other_props.get("precision"), other_props.get("scale", 0)) + return BytesDecimalSchema(other_props.get("precision"), other_props.get("scale", 0), other_props) def make_logical_schema(logical_type, type_, other_props): diff --git a/lang/py/avro/test/test_schema.py b/lang/py/avro/test/test_schema.py index 2015727d369..25426173959 100644 --- a/lang/py/avro/test/test_schema.py +++ b/lang/py/avro/test/test_schema.py @@ -642,16 +642,16 @@ def test_decimal_valid_type(self): } ) - bytes_decimal_schema = ValidTestSchema({"type": "bytes", "logicalType": "decimal", "precision": 4}) - fixed_decimal = fixed_decimal_schema.parse() self.assertEqual(4, fixed_decimal.get_prop("precision")) self.assertEqual(2, fixed_decimal.get_prop("scale")) self.assertEqual(2, fixed_decimal.get_prop("size")) + bytes_decimal_schema = ValidTestSchema({"type": "bytes", "logicalType": "decimal", "precision": 4}) bytes_decimal = bytes_decimal_schema.parse() self.assertEqual(4, bytes_decimal.get_prop("precision")) self.assertEqual(0, bytes_decimal.get_prop("scale")) + self.assertEqual("decimal", bytes_decimal.get_prop("logicalType")) def test_fixed_decimal_valid_max_precision(self): # An 8 byte number can represent any 18 digit number. From 33d86a61a9d225d83349ffbda21d2b31eeefe7ac Mon Sep 17 00:00:00 2001 From: Martin Grigorov Date: Mon, 20 Dec 2021 19:47:14 +0200 Subject: [PATCH 0027/1479] AVRO-3243: Workaround JDK-8161372 - perf issue in ConcurrentHashMap#computeIfAbsent() (#1392) --- .../org/apache/avro/reflect/ReflectData.java | 6 ++- .../apache/avro/specific/SpecificData.java | 6 ++- .../java/org/apache/avro/util/MapUtil.java | 45 +++++++++++++++++++ .../apache/avro/grpc/ServiceDescriptor.java | 5 ++- 4 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 lang/java/avro/src/main/java/org/apache/avro/util/MapUtil.java diff --git a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java index 4ead6b888f4..1af25817713 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java +++ b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java @@ -36,6 +36,7 @@ import org.apache.avro.specific.FixedSize; import org.apache.avro.specific.SpecificData; import org.apache.avro.util.ClassUtils; +import org.apache.avro.util.MapUtil; import java.io.IOException; import java.lang.annotation.Annotation; @@ -63,6 +64,7 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** Utilities to use existing Java classes and interfaces via reflection. */ public class ReflectData extends SpecificData { @@ -826,11 +828,11 @@ public static Schema makeNullable(Schema schema) { } } - private static final Map, Field[]> FIELDS_CACHE = new ConcurrentHashMap<>(); + private static final ConcurrentMap, Field[]> FIELDS_CACHE = new ConcurrentHashMap<>(); // Return of this class and its superclasses to serialize. private static Field[] getCachedFields(Class recordClass) { - return FIELDS_CACHE.computeIfAbsent(recordClass, rc -> getFields(rc, true)); + return MapUtil.computeIfAbsent(FIELDS_CACHE, recordClass, rc -> getFields(rc, true)); } private static Field[] getFields(Class recordClass, boolean excludeJava) { diff --git a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java index 5b539395b8e..8efd904b285 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java +++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java @@ -30,6 +30,7 @@ import org.apache.avro.io.DecoderFactory; import org.apache.avro.io.EncoderFactory; import org.apache.avro.util.ClassUtils; +import org.apache.avro.util.MapUtil; import org.apache.avro.util.internal.ClassValueCache; import java.io.ObjectInput; @@ -48,6 +49,7 @@ import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.function.Function; /** Utilities for generated Java classes and interfaces. */ @@ -228,7 +230,7 @@ protected Schema getEnumSchema(Object datum) { return (datum instanceof Enum) ? getSchema(datum.getClass()) : super.getEnumSchema(datum); } - private Map classCache = new ConcurrentHashMap<>(); + private final ConcurrentMap classCache = new ConcurrentHashMap<>(); private static final Class NO_CLASS = new Object() { }.getClass(); @@ -251,7 +253,7 @@ public Class getClass(Schema schema) { String name = schema.getFullName(); if (name == null) return null; - Class c = classCache.computeIfAbsent(name, n -> { + Class c = MapUtil.computeIfAbsent(classCache, name, n -> { try { return ClassUtils.forName(getClassLoader(), getClassName(schema)); } catch (ClassNotFoundException e) { diff --git a/lang/java/avro/src/main/java/org/apache/avro/util/MapUtil.java b/lang/java/avro/src/main/java/org/apache/avro/util/MapUtil.java new file mode 100644 index 00000000000..1bdbfaf9a0a --- /dev/null +++ b/lang/java/avro/src/main/java/org/apache/avro/util/MapUtil.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.util; + +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + +public class MapUtil { + + private MapUtil() { + super(); + } + + /** + * A temporary workaround for Java 8 specific performance issue JDK-8161372 + * .
+ * This class should be removed once we drop Java 8 support. + * + * @see JDK-8161372 + */ + public static V computeIfAbsent(ConcurrentMap map, K key, Function mappingFunction) { + V value = map.get(key); + if (value != null) { + return value; + } + return map.computeIfAbsent(key, mappingFunction::apply); + } + +} diff --git a/lang/java/grpc/src/main/java/org/apache/avro/grpc/ServiceDescriptor.java b/lang/java/grpc/src/main/java/org/apache/avro/grpc/ServiceDescriptor.java index 0984473546f..bfb8ec2de7a 100644 --- a/lang/java/grpc/src/main/java/org/apache/avro/grpc/ServiceDescriptor.java +++ b/lang/java/grpc/src/main/java/org/apache/avro/grpc/ServiceDescriptor.java @@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentMap; import io.grpc.MethodDescriptor; +import org.apache.avro.util.MapUtil; import static io.grpc.MethodDescriptor.generateFullMethodName; @@ -49,7 +50,7 @@ private ServiceDescriptor(Class iface, String serviceName) { */ public static ServiceDescriptor create(Class iface) { String serviceName = AvroGrpcUtils.getServiceName(iface); - return SERVICE_DESCRIPTORS.computeIfAbsent(serviceName, key -> new ServiceDescriptor(iface, serviceName)); + return MapUtil.computeIfAbsent(SERVICE_DESCRIPTORS, serviceName, key -> new ServiceDescriptor(iface, serviceName)); } /** @@ -67,7 +68,7 @@ public String getServiceName() { * @return a {@link MethodDescriptor} */ public MethodDescriptor getMethod(String methodName, MethodDescriptor.MethodType methodType) { - return methods.computeIfAbsent(methodName, + return MapUtil.computeIfAbsent(methods, methodName, key -> MethodDescriptor.newBuilder() .setFullMethodName(generateFullMethodName(serviceName, methodName)).setType(methodType) .setRequestMarshaller(new AvroRequestMarshaller(protocol.getMessages().get(methodName))) From 28f54cb35af3fab56985b710892cf9469aa7022d Mon Sep 17 00:00:00 2001 From: "Michael A. Smith" Date: Tue, 21 Dec 2021 12:18:02 -0500 Subject: [PATCH 0028/1479] AVRO-3229: Raise Exception on Invalid Enum Default (#1433) --- lang/py/avro/errors.py | 4 ++++ lang/py/avro/schema.py | 5 +++++ lang/py/avro/test/test_schema.py | 1 + 3 files changed, 10 insertions(+) diff --git a/lang/py/avro/errors.py b/lang/py/avro/errors.py index 5ff36032898..b8828d02417 100644 --- a/lang/py/avro/errors.py +++ b/lang/py/avro/errors.py @@ -40,6 +40,10 @@ class InvalidName(SchemaParseException): """User attempted to parse a schema with an invalid name.""" +class InvalidDefault(SchemaParseException): + """User attempted to parse a schema with an invalid default.""" + + class AvroWarning(UserWarning): """Base class for warnings.""" diff --git a/lang/py/avro/schema.py b/lang/py/avro/schema.py index 73371d5d4dd..0793ce6c851 100644 --- a/lang/py/avro/schema.py +++ b/lang/py/avro/schema.py @@ -583,6 +583,11 @@ def __init__( if doc is not None: self.set_prop("doc", doc) + if other_props and "default" in other_props: + default = other_props["default"] + if default not in symbols: + raise avro.errors.InvalidDefault(f"Enum default '{default}' is not a valid member of symbols '{symbols}'") + @property def symbols(self) -> Sequence[str]: symbols = self.get_prop("symbols") diff --git a/lang/py/avro/test/test_schema.py b/lang/py/avro/test/test_schema.py index 25426173959..b5906d25e77 100644 --- a/lang/py/avro/test/test_schema.py +++ b/lang/py/avro/test/test_schema.py @@ -85,6 +85,7 @@ class InvalidTestSchema(TestSchema): ENUM_EXAMPLES = [ ValidTestSchema({"type": "enum", "name": "Test", "symbols": ["A", "B"]}), ValidTestSchema({"type": "enum", "name": "AVRO2174", "symbols": ["nowhitespace"]}), + InvalidTestSchema({"type": "enum", "name": "bad_default", "symbols": ["A"], "default": "B"}, comment="AVRO-3229"), InvalidTestSchema({"type": "enum", "name": "Status", "symbols": "Normal Caution Critical"}), InvalidTestSchema({"type": "enum", "name": [0, 1, 1, 2, 3, 5, 8], "symbols": ["Golden", "Mean"]}), InvalidTestSchema({"type": "enum", "symbols": ["I", "will", "fail", "no", "name"]}), From e7e48170a62c6060d7e532f7198756781f1d60d8 Mon Sep 17 00:00:00 2001 From: Martin Grigorov Date: Tue, 21 Dec 2021 20:47:11 +0200 Subject: [PATCH 0029/1479] Minor non functional changes (#1378) * Spelling fixes in comments * Ignore Maven JVM config file and IDEA Run configurations --- .gitignore | 2 ++ lang/c++/test/CodecTests.cc | 2 +- lang/csharp/build.sh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fd46be4f46f..437a035f0b3 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ test-output vendor composer.lock .phpunit.result.cache +.mvn/jvm.config # Maven JVM settings +**/*.run.xml # Intellij IDEA Run configurations diff --git a/lang/c++/test/CodecTests.cc b/lang/c++/test/CodecTests.cc index a99cdd67498..7d114160266 100644 --- a/lang/c++/test/CodecTests.cc +++ b/lang/c++/test/CodecTests.cc @@ -68,7 +68,7 @@ static const unsigned int count = 10; * promote data type, convert from union to plain data type and vice versa, * insert or remove fields in records or reorder fields in a record. * - * To test Json encoder and decoder, we use the same technqiue with only + * To test Json encoder and decoder, we use the same technique with only * one difference - we use JsonEncoder and JsonDecoder. * * We also use the same infrastructure to test GenericReader and GenericWriter. diff --git a/lang/csharp/build.sh b/lang/csharp/build.sh index fefbe28e9ba..5e62ad2a79c 100755 --- a/lang/csharp/build.sh +++ b/lang/csharp/build.sh @@ -35,7 +35,7 @@ do test) dotnet build --configuration Release Avro.sln - # AVRO-2442: Explictly set LANG to work around ICU bug in `dotnet test` + # AVRO-2442: Explicitly set LANG to work around ICU bug in `dotnet test` LANG=en_US.UTF-8 dotnet test --configuration Release --no-build \ --filter "TestCategory!=Interop" Avro.sln ;; From 1aa963c44d1b9da3dfcf74acb3eeed56439332a0 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Wed, 22 Dec 2021 08:58:43 +0100 Subject: [PATCH 0030/1479] AVRO-2867: Fix NullPointerException on record-valued defaults (#1412) If the IDL file defines the schema of a field after the field, record valued defaults cause a NullPointerException. This PR fixes that. The fix addresses two situations: 1. The field schema itself is a forward reference (tested by fixing the missing default value in `forward_ref.avpr`) 2. The field schema contains a forward reference (tested by the `echo` message in the updated `simple.avdl`) --- .../src/main/java/org/apache/avro/Schema.java | 12 ++++ .../compiler/idl/IsResolvedSchemaVisitor.java | 62 +++++++++++++++++++ .../avro/compiler/idl/ResolvingVisitor.java | 5 +- .../avro/compiler/idl/SchemaResolver.java | 14 +++++ .../apache/avro/compiler/schema/Schemas.java | 6 +- .../org/apache/avro/compiler/idl/idl.jj | 2 +- .../compiler/src/test/idl/input/simple.avdl | 6 +- .../src/test/idl/output/forward_ref.avpr | 2 +- .../compiler/src/test/idl/output/simple.avpr | 12 ++-- 9 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/IsResolvedSchemaVisitor.java diff --git a/lang/java/avro/src/main/java/org/apache/avro/Schema.java b/lang/java/avro/src/main/java/org/apache/avro/Schema.java index 76ee2ee3be5..fec08e1d7d3 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/Schema.java +++ b/lang/java/avro/src/main/java/org/apache/avro/Schema.java @@ -281,6 +281,13 @@ public List getFields() { throw new AvroRuntimeException("Not a record: " + this); } + /** + * If this is a record, returns whether the fields have been set. + */ + public boolean hasFields() { + throw new AvroRuntimeException("Not a record: " + this); + } + /** * If this is a record, set its fields. The fields can be set only once in a * schema. @@ -904,6 +911,11 @@ public List getFields() { return fields; } + @Override + public boolean hasFields() { + return fields != null; + } + @Override public void setFields(List fields) { if (this.fields != null) { diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/IsResolvedSchemaVisitor.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/IsResolvedSchemaVisitor.java new file mode 100644 index 00000000000..6006ad5f82f --- /dev/null +++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/IsResolvedSchemaVisitor.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.avro.compiler.idl; + +import org.apache.avro.Schema; +import org.apache.avro.compiler.schema.SchemaVisitor; +import org.apache.avro.compiler.schema.SchemaVisitorAction; + +/** + * This visitor checks if the current schema is fully resolved. + */ +public final class IsResolvedSchemaVisitor implements SchemaVisitor { + boolean hasUnresolvedParts; + + IsResolvedSchemaVisitor() { + hasUnresolvedParts = false; + } + + @Override + public SchemaVisitorAction visitTerminal(Schema terminal) { + hasUnresolvedParts = SchemaResolver.isUnresolvedSchema(terminal); + return hasUnresolvedParts ? SchemaVisitorAction.TERMINATE : SchemaVisitorAction.CONTINUE; + } + + @Override + public SchemaVisitorAction visitNonTerminal(Schema nonTerminal) { + hasUnresolvedParts = SchemaResolver.isUnresolvedSchema(nonTerminal); + if (hasUnresolvedParts) { + return SchemaVisitorAction.TERMINATE; + } + if (nonTerminal.getType() == Schema.Type.RECORD && !nonTerminal.hasFields()) { + // We're still initializing the type... + return SchemaVisitorAction.SKIP_SUBTREE; + } + return SchemaVisitorAction.CONTINUE; + } + + @Override + public SchemaVisitorAction afterVisitNonTerminal(Schema nonTerminal) { + return SchemaVisitorAction.CONTINUE; + } + + @Override + public Boolean get() { + return !hasUnresolvedParts; + } +} diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/ResolvingVisitor.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/ResolvingVisitor.java index c00252ea7ca..1c7175461cc 100644 --- a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/ResolvingVisitor.java +++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/ResolvingVisitor.java @@ -139,10 +139,7 @@ public SchemaVisitorAction afterVisitNonTerminal(final Schema nt) { List fields = nt.getFields(); List newFields = new ArrayList<>(fields.size()); for (Schema.Field field : fields) { - Schema.Field newField = new Schema.Field(field.name(), replace.get(field.schema()), field.doc(), - field.defaultVal(), field.order()); - copyAllProperties(field, newField); - newFields.add(newField); + newFields.add(new Field(field, replace.get(field.schema()))); } newSchema.setFields(newFields); } diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java index 2da4944640d..193f871178b 100644 --- a/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java +++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/idl/SchemaResolver.java @@ -83,6 +83,20 @@ static String getUnresolvedSchemaName(final Schema schema) { return schema.getProp(UR_SCHEMA_ATTR); } + /** + * Is this a unresolved schema. + * + * @param schema + * @return + */ + static boolean isFullyResolvedSchema(final Schema schema) { + if (isUnresolvedSchema(schema)) { + return false; + } else { + return Schemas.visit(schema, new IsResolvedSchemaVisitor()); + } + } + /** * Will clone the provided protocol while resolving all unreferenced schemas * diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/schema/Schemas.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/schema/Schemas.java index 91232f0f5ac..b35adbd9313 100644 --- a/lang/java/compiler/src/main/java/org/apache/avro/compiler/schema/Schemas.java +++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/schema/Schemas.java @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.Deque; import java.util.IdentityHashMap; -import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.function.Supplier; @@ -141,9 +140,8 @@ public static T visit(final Schema start, final SchemaVisitor visitor) { visited.put(schema, schema); break; case RECORD: - Iterator reverseSchemas = schema.getFields().stream().map(Field::schema) - .collect(Collectors.toCollection(ArrayDeque::new)).descendingIterator(); - terminate = visitNonTerminal(visitor, schema, dq, () -> reverseSchemas); + terminate = visitNonTerminal(visitor, schema, dq, () -> schema.getFields().stream().map(Field::schema) + .collect(Collectors.toCollection(ArrayDeque::new)).descendingIterator()); visited.put(schema, schema); break; case UNION: diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index 667eece37cb..32fc2fa1b17 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -1348,7 +1348,7 @@ void VariableDeclarator(Schema type, List fields): if ("order".equals(key)) order = Field.Order.valueOf(getTextProp(key,props,token).toUpperCase()); - boolean validate = !SchemaResolver.isUnresolvedSchema(type); + boolean validate = SchemaResolver.isFullyResolvedSchema(type); Field field = Accessor.createField(name, type, DocCommentHelper.getDoc(), defaultValue, validate, order); for (String key : props.keySet()) if ("order".equals(key)) { // already handled: ignore diff --git a/lang/java/compiler/src/test/idl/input/simple.avdl b/lang/java/compiler/src/test/idl/input/simple.avdl index c0df9f3a988..5208c7ee4cb 100644 --- a/lang/java/compiler/src/test/idl/input/simple.avdl +++ b/lang/java/compiler/src/test/idl/input/simple.avdl @@ -36,9 +36,6 @@ protocol Simple { C } = C; - /** An MD5 hash. */ - fixed MD5(16); - /** A TestRecord. */ @my-property({"key":3}) record TestRecord { @@ -64,6 +61,9 @@ protocol Simple { union {null, @foo.foo.bar(42) @foo.foo.foo("3foo") string} prop = null; } + /** An MD5 hash. */ + fixed MD5(16); + error TestError { string message; } diff --git a/lang/java/compiler/src/test/idl/output/forward_ref.avpr b/lang/java/compiler/src/test/idl/output/forward_ref.avpr index 06531b55479..a349206a37f 100644 --- a/lang/java/compiler/src/test/idl/output/forward_ref.avpr +++ b/lang/java/compiler/src/test/idl/output/forward_ref.avpr @@ -8,7 +8,7 @@ "fields": [ { "name":"name", "type": "string", "doc":"the name" }, { "name": "value", "type": "string", "doc": "the value" }, - { "name": "type", "type": { "type": "enum", "name":"ValueType", "symbols": ["JSON","BASE64BIN","PLAIN"] } } + { "name": "type", "type": { "type": "enum", "name":"ValueType", "symbols": ["JSON","BASE64BIN","PLAIN"] }, "default": "PLAIN" } ] } ], diff --git a/lang/java/compiler/src/test/idl/output/simple.avpr b/lang/java/compiler/src/test/idl/output/simple.avpr index 438a4bd04e4..5e86c6c5b93 100644 --- a/lang/java/compiler/src/test/idl/output/simple.avpr +++ b/lang/java/compiler/src/test/idl/output/simple.avpr @@ -14,11 +14,6 @@ "name" : "Status", "symbols" : [ "A", "B", "C" ], "default" : "C" - }, { - "type" : "fixed", - "name" : "MD5", - "doc" : "An MD5 hash.", - "size" : 16 }, { "type" : "record", "name" : "TestRecord", @@ -43,7 +38,12 @@ "default" : "A" }, { "name" : "hash", - "type" : "MD5", + "type" : { + "type" : "fixed", + "name" : "MD5", + "doc" : "An MD5 hash.", + "size" : 16 + }, "default" : "0000000000000000" }, { "name" : "nullableHash", From 7c5d8df3fb282b1dffa6d11169756ed5593de838 Mon Sep 17 00:00:00 2001 From: Oscar Westra van Holthe - Kind Date: Wed, 22 Dec 2021 18:16:08 +0100 Subject: [PATCH 0031/1479] AVRO-3257: IDL support for nullable types (#1411) * AVRO-3256: IDL type reference with annotation throws error Previous versions would alter the referenced type when encountering an annotation on (for example) a field type. This change makes references read-only. * AVRO-3256: Document new behavior of annotations Documented that references to named types cannot be annotated. Also described where annotations for named types should go. Lastly, the example has been fixed to match this change, and now also contains various types of documentation. * AVRO-3257: Add syntax for unions of null with a type Added Kotlin-style syntax for optional types. `MyType?` compiles to the same result as `union { null, MyType }`. This commit includes the documentation update. * AVRO-3257: Remove unused variable from JavaCC grammar * AVRO-3257: Fluid unions for optional types The syntax for optional types now put the null type in the unions based on the default value (if any). This commit includes the documentation update. * AVRO-3257: Add comments explaining features * Fix typo in HTML Co-authored-by: Ryan Skraba Co-authored-by: Ryan Skraba --- doc/src/content/xdocs/idl.xml | 23 +++++- .../org/apache/avro/compiler/idl/idl.jj | 79 ++++++++++++++++--- .../compiler/src/test/idl/input/simple.avdl | 13 ++- .../compiler/src/test/idl/output/simple.avpr | 2 +- 4 files changed, 101 insertions(+), 16 deletions(-) diff --git a/doc/src/content/xdocs/idl.xml b/doc/src/content/xdocs/idl.xml index e8c1b81a0f4..760680368d5 100644 --- a/doc/src/content/xdocs/idl.xml +++ b/doc/src/content/xdocs/idl.xml @@ -309,17 +309,36 @@ record Card {
Unions

Union types are denoted as union { typeA, typeB, typeC, ... }. For example, - this record contains a string field that is optional (unioned with null): + this record contains a string field that is optional (unioned with null), and + a field containing either a precise or a imprecise number:

record RecordWithUnion { union { null, string } optionalString; + union { decimal(12, 6), float } number; }

Note that the same restrictions apply to Avro IDL unions as apply to unions defined in the - JSON format; namely, a record may not contain multiple elements of the same type. + JSON format; namely, a record may not contain multiple elements of the same type. Also, + fields/parameters that use the union type and have a default parameter must specify a + default value of the same type as the first union type.

+

Because it occurs so often, there is a special shorthand to denote a union of + null with another type. In the following snippet, the first three fields have + identical types: +

+ +record RecordWithUnion { + union { null, string } optionalString1 = null; + string? optionalString2 = null; + string? optionalString3; // No default value + string? optionalString4 = "something"; +} + +

Note that unlike explicit unions, the position of the null type is fluid; it will be + the first or last type depending on the default value (if any). So in the example above, all fields + are valid.

diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index 32fc2fa1b17..d62faff204d 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -91,6 +91,7 @@ import org.apache.commons.lang3.StringEscapeUtils; */ public class Idl implements Closeable { static JsonNodeFactory FACTORY = JsonNodeFactory.instance; + private static final String OPTIONAL_NULLABLE_TYPE_PROPERTY = "org.apache.avro.compiler.idl.Idl.NullableType.optional"; URI inputDir; ClassLoader resourceLoader = null; @@ -183,6 +184,32 @@ public class Idl implements Closeable { return result; } + /** + * For "optional schemas" (recognized by the marker property the NullableType + * production adds), ensure the null schema is in the right place. + * + * @param schema a schema + * @param defaultValue the intended default value + * @return the schema, or an optional schema with null in the right place + */ + private static Schema fixOptionalSchema(Schema schema, JsonNode defaultValue) { + final Object optionalType = schema.getObjectProp(OPTIONAL_NULLABLE_TYPE_PROPERTY); + if (optionalType != null) { + // The schema is a union schema with 2 types: "null" and a non-"null" schema + Schema nullSchema = schema.getTypes().get(0); + Schema nonNullSchema = schema.getTypes().get(1); + boolean nonNullDefault = defaultValue != null && !defaultValue.isNull(); + + // Always return a new schema: this drops the marker property. + if (nonNullDefault) { + return Schema.createUnion(nonNullSchema, nullSchema); + } else { + return Schema.createUnion(nullSchema, nonNullSchema); + } + } + return schema; + } + } PARSER_END(Idl) @@ -1000,6 +1027,7 @@ TOKEN : | < EQUALS: "=" > | < DOT: "." > | < DASH: "-" > +| < QUESTION_MARK: "?" > } TOKEN : @@ -1349,7 +1377,8 @@ void VariableDeclarator(Schema type, List fields): order = Field.Order.valueOf(getTextProp(key,props,token).toUpperCase()); boolean validate = SchemaResolver.isFullyResolvedSchema(type); - Field field = Accessor.createField(name, type, DocCommentHelper.getDoc(), defaultValue, validate, order); + Schema fieldType = fixOptionalSchema(type, defaultValue); + Field field = Accessor.createField(name, fieldType, DocCommentHelper.getDoc(), defaultValue, validate, order); for (String key : props.keySet()) if ("order".equals(key)) { // already handled: ignore } else if ("aliases".equals(key)) { // aliases @@ -1440,11 +1469,6 @@ Schema Type(): ( SchemaProperty(props) )* s = UnannotatedType(props) { - for (String key : props.keySet()) - Accessor.addProp(s, key, props.get(key)); - LogicalType logicalType = LogicalTypes.fromSchemaIgnoreInvalid(s); - if (logicalType != null) - logicalType.addToSchema(s); return s; } } @@ -1453,15 +1477,50 @@ Schema UnannotatedType(Map props): { Schema s; } +{ + ( + s = NullableType(props) + | ( + s = UnionDefinition() + | s = ArrayType() + | s = MapType() + ) + { + // NullableType also applies properties, inside any union with null it may create. + for (String key : props.keySet()) + Accessor.addProp(s, key, props.get(key)); + LogicalType logicalType = LogicalTypes.fromSchemaIgnoreInvalid(s); + if (logicalType != null) + logicalType.addToSchema(s); + } + ) + { + return s; + } +} + +Schema NullableType(Map props): +{ + Schema s; + boolean optional = false; +} { ( s = ReferenceType() { if (!props.isEmpty()) { throw error("Type references may not be annotated", token); } } | s = PrimitiveType() - | s = UnionDefinition() - | s = ArrayType() - | s = MapType() - ) + ) [ { optional = true; } ] { + // By applying the properties here (before creating the union), type annotations modify the optional type instead of the union. + for (String key : props.keySet()) + Accessor.addProp(s, key, props.get(key)); + LogicalType logicalType = LogicalTypes.fromSchemaIgnoreInvalid(s); + if (logicalType != null) + logicalType.addToSchema(s); + if (optional) { + s = Schema.createUnion(Schema.create(Schema.Type.NULL), s); + // Add a marker property to the union (it will be removed when creating fields) + Accessor.addProp(s, OPTIONAL_NULLABLE_TYPE_PROPERTY, BooleanNode.TRUE); + } return s; } } diff --git a/lang/java/compiler/src/test/idl/input/simple.avdl b/lang/java/compiler/src/test/idl/input/simple.avdl index 5208c7ee4cb..715bbd07d7a 100644 --- a/lang/java/compiler/src/test/idl/input/simple.avdl +++ b/lang/java/compiler/src/test/idl/input/simple.avdl @@ -34,11 +34,12 @@ protocol Simple { A, B, C - } = C; + } = C; // C is the default value used when reading unknown values from another schema version (without it, reading throws an exception). /** A TestRecord. */ @my-property({"key":3}) record TestRecord { + // Tests that keywords can also appear in identifiers. @avro.java.`string`("String") string @order("ignore") name = "foo"; /** The kind of record. */ @@ -49,16 +50,21 @@ protocol Simple { MD5 hash = "0000000000000000"; + // A traditional optional field union {null, MD5} @aliases(["hash", "hsh"]) nullableHash = null; + // These two fields parse correctly, but will brewak (be changed to strings) when serializing the protocol/schema as JSON. double value = NaN; float average = -Infinity; date d = 0; - time_ms t = 0; + // An optional type with a non-null default value (results in a union with null last). + time_ms? t = 0; @foo.bar("bar.foo") long l = 0; + // Arrays (and maps) may also have properties @foo.bar.bar("foo.bar2") array a = []; - union {null, @foo.foo.bar(42) @foo.foo.foo("3foo") string} prop = null; + // An optional type with a null default value (results in a union with null first). + @foo.foo.bar(42) @foo.foo.foo("3foo") string? prop = null; } /** An MD5 hash. */ @@ -70,6 +76,7 @@ protocol Simple { /** method 'hello' takes @parameter 'greeting' */ string hello(string greeting); + // The value of TestRecord also contains defaults for fields not mentioned. TestRecord echo(TestRecord `record` = {"name":"bar","kind":"BAR"}); /** method 'add' takes @parameter 'arg1' @parameter 'arg2' */ @specialProp("test") diff --git a/lang/java/compiler/src/test/idl/output/simple.avpr b/lang/java/compiler/src/test/idl/output/simple.avpr index 5e86c6c5b93..0ec9edb4c24 100644 --- a/lang/java/compiler/src/test/idl/output/simple.avpr +++ b/lang/java/compiler/src/test/idl/output/simple.avpr @@ -64,7 +64,7 @@ "default": 0 }, { "name": "t", - "type": {"type": "int", "logicalType": "time-millis"}, + "type": [ {"type": "int", "logicalType": "time-millis"}, "null" ], "default": 0 } , { "name": "l", From d97e81f96e11cf0b550234d7c76045bea1734ab3 Mon Sep 17 00:00:00 2001 From: Martin Grigorov Date: Wed, 22 Dec 2021 19:32:34 +0200 Subject: [PATCH 0032/1479] AVRO-3251: AVDL files containing fields called "uuid" no longer compile. (#1395) * AVRO-3251 AVDL files containing fields called "uuid" no longer compile. * AVRO-3251 Accept idl, import, oneway and null as identifiers in .avdl files --- .../org/apache/avro/compiler/idl/idl.jj | 5 +++++ .../src/test/idl/input/reservedwords.avdl | 5 +++++ .../compiler/src/test/idl/input/uuid.avdl | 5 +++++ .../compiler/src/test/idl/output/import.avpr | 20 +++++++++++++++++++ .../src/test/idl/output/nestedimport.avpr | 20 +++++++++++++++++++ .../src/test/idl/output/reservedwords.avpr | 20 +++++++++++++++++++ .../compiler/src/test/idl/output/uuid.avpr | 4 ++++ 7 files changed, 79 insertions(+) diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj index d62faff204d..5fe78714420 100644 --- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj +++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj @@ -1658,17 +1658,22 @@ Token AnyIdentifier(): t = | t = | t = | + t = | + t = | t = | t = | t = | + t = | t = | t = | + t = | t = | t = | t = | t = | t = | t = | + t = | t = | t = | t =