diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 430a85e..3f9e337 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml
@@ -7,5 +7,4 @@ - package-ecosystem: "github-actions" directory: "/" schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" + interval: "monthly"
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 62bd4b7..579ab68 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml
@@ -1,4 +1,4 @@ -# Created with package:mono_repo v5.0.1 +# Created with package:mono_repo v6.2.0 name: Dart CI on: push: @@ -19,20 +19,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:stable" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable" restore-keys: | os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: stable - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - name: mono_repo self validate - run: dart pub global activate mono_repo 5.0.1 + run: dart pub global activate mono_repo 6.2.0 - name: mono_repo self validate run: dart pub global run mono_repo generate --validate job_002: @@ -40,20 +40,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:protobuf;commands:analyze_1-analyze_2" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0;packages:protobuf;commands:analyze_1-analyze_2" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:protobuf - os:ubuntu-latest;pub-cache-hosted;dart:2.12.0 + os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0;packages:protobuf + os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: "2.12.0" - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -72,20 +72,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:api_benchmark-query_benchmark;commands:format-command_0-command_1-analyze_0" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:api_benchmark-query_benchmark;commands:format-command_0-command_1-analyze_0" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:api_benchmark-query_benchmark - os:ubuntu-latest;pub-cache-hosted;dart:dev + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:api_benchmark-query_benchmark + os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: api_benchmark_pub_upgrade name: api_benchmark; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -133,20 +133,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:format-analyze_0" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protobuf;commands:format-analyze_0" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf - os:ubuntu-latest;pub-cache-hosted;dart:dev + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protobuf + os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -165,20 +165,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin;commands:format-command_0-command_2-analyze_0" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protoc_plugin;commands:format-command_0-command_2-analyze_0" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin - os:ubuntu-latest;pub-cache-hosted;dart:dev + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protoc_plugin + os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protoc_plugin_pub_upgrade name: protoc_plugin; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -205,20 +205,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:protobuf;commands:test" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0;packages:protobuf;commands:test" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:protobuf - os:ubuntu-latest;pub-cache-hosted;dart:2.12.0 + os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0;packages:protobuf + os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: "2.12.0" - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -239,20 +239,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:protoc_plugin;commands:command_0-command_2-test" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0;packages:protoc_plugin;commands:command_0-command_2-test" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:protoc_plugin - os:ubuntu-latest;pub-cache-hosted;dart:2.12.0 + os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0;packages:protoc_plugin + os:ubuntu-latest;pub-cache-hosted;sdk:2.12.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: "2.12.0" - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protoc_plugin_pub_upgrade name: protoc_plugin; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -281,20 +281,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:test" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protobuf;commands:test" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf - os:ubuntu-latest;pub-cache-hosted;dart:dev + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protobuf + os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -315,20 +315,20 @@ runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin;commands:command_0-command_2-test" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protoc_plugin;commands:command_0-command_2-test" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin - os:ubuntu-latest;pub-cache-hosted;dart:dev + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:protoc_plugin + os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protoc_plugin_pub_upgrade name: protoc_plugin; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -357,20 +357,20 @@ runs-on: macos-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:macos-latest;pub-cache-hosted;dart:2.12.0;packages:protobuf;commands:test" + key: "os:macos-latest;pub-cache-hosted;sdk:2.12.0;packages:protobuf;commands:test" restore-keys: | - os:macos-latest;pub-cache-hosted;dart:2.12.0;packages:protobuf - os:macos-latest;pub-cache-hosted;dart:2.12.0 + os:macos-latest;pub-cache-hosted;sdk:2.12.0;packages:protobuf + os:macos-latest;pub-cache-hosted;sdk:2.12.0 os:macos-latest;pub-cache-hosted os:macos-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: "2.12.0" - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -391,20 +391,20 @@ runs-on: macos-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: "~/.pub-cache/hosted" - key: "os:macos-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:test" + key: "os:macos-latest;pub-cache-hosted;sdk:dev;packages:protobuf;commands:test" restore-keys: | - os:macos-latest;pub-cache-hosted;dart:dev;packages:protobuf - os:macos-latest;pub-cache-hosted;dart:dev + os:macos-latest;pub-cache-hosted;sdk:dev;packages:protobuf + os:macos-latest;pub-cache-hosted;sdk:dev os:macos-latest;pub-cache-hosted os:macos-latest - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -424,11 +424,11 @@ name: "run_tests; windows; Dart 2.12.0; PKG: protobuf; `dart test`" runs-on: windows-latest steps: - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: "2.12.0" - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -448,11 +448,11 @@ name: "run_tests; windows; Dart dev; PKG: protobuf; `dart test`" runs-on: windows-latest steps: - - uses: dart-lang/setup-dart@v1.1 + - uses: dart-lang/setup-dart@v1.3 with: sdk: dev - id: checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.0.0 - id: protobuf_pub_upgrade name: protobuf; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'"
diff --git a/analysis_options.yaml b/analysis_options.yaml deleted file mode 100644 index 6e1ff09..0000000 --- a/analysis_options.yaml +++ /dev/null
@@ -1,79 +0,0 @@ -linter: - rules: - - always_require_non_null_named_parameters - - annotate_overrides - - avoid_empty_else - - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - - avoid_returning_null_for_void - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_types_as_parameter_names - - await_only_futures - - camel_case_extensions - - camel_case_types - - constant_identifier_names - - control_flow_in_finally - - curly_braces_in_flow_control_structures - - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - exhaustive_cases - - file_names - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - - library_names - - library_prefixes - - list_remove_unrelated_type - - no_duplicate_case_values - - non_constant_identifier_names - - null_closures - - overridden_fields - - package_names - - package_prefixed_library_names - - prefer_adjacent_string_concatenation - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields - - prefer_for_elements_to_map_fromIterable - - prefer_function_declarations_over_variables - - prefer_generic_function_type_aliases - - prefer_if_null_operators - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_is_empty - - prefer_is_not_empty - - prefer_is_not_operator - - prefer_iterable_whereType - - prefer_null_aware_operators - - prefer_relative_imports - - prefer_single_quotes - - prefer_spread_collections - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message - - recursive_getters - - slash_for_doc_comments - - type_init_formals - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_getters_setters - - unnecessary_new - - unnecessary_null_in_if_null_operators - - unnecessary_overrides - - unnecessary_string_escapes - - unnecessary_string_interpolations - - unnecessary_this - - unrelated_type_equality_checks - - use_function_type_syntax_for_parameters - - use_rethrow_when_possible - - valid_regexps - - void_checks
diff --git a/api_benchmark/analysis_options.yaml b/api_benchmark/analysis_options.yaml new file mode 100644 index 0000000..e841247 --- /dev/null +++ b/api_benchmark/analysis_options.yaml
@@ -0,0 +1,9 @@ +include: package:lints/recommended.yaml + +linter: + rules: + - comment_references + - directives_ordering + - prefer_relative_imports + - prefer_single_quotes + - prefer_spread_collections
diff --git a/api_benchmark/mono_pkg.yaml b/api_benchmark/mono_pkg.yaml index e822136..b23af8b 100644 --- a/api_benchmark/mono_pkg.yaml +++ b/api_benchmark/mono_pkg.yaml
@@ -7,4 +7,4 @@ - command: ./../tool/setup.sh - command: ./compile_protos.sh - analyze: --fatal-infos - dart: dev + sdk: dev
diff --git a/api_benchmark/pubspec.yaml b/api_benchmark/pubspec.yaml index 4c59173..e5e6601 100644 --- a/api_benchmark/pubspec.yaml +++ b/api_benchmark/pubspec.yaml
@@ -5,17 +5,21 @@ name: api_benchmark description: Benchmarking a number of different api calls. +# This package is not intended for consumption on pub.dev. DO NOT publish. +publish_to: none + environment: sdk: '>=2.11.99 <3.0.0' dependencies: - protobuf: + protobuf: any dev_dependencies: build: ^2.0.0 build_runner: ^2.0.6 build_web_compilers: ^3.0.0 glob: ^2.0.0 + lints: ^1.0.0 yaml: ^3.0.0 protoc_plugin: path: "../protoc_plugin"
diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md index 77c583c..9debaf7 100644 --- a/protobuf/CHANGELOG.md +++ b/protobuf/CHANGELOG.md
@@ -1,5 +1,6 @@ -## 2.0.1-dev +## 2.0.1 +* Fix bug of parsing map-values with default values. * Merge fixes from version `1.1.2` - `1.1.4` into v2. ## 2.0.0 @@ -293,7 +294,7 @@ ## 0.9.0+1 -* Dart SDK upper constraint raised to declare compatability with Dart 2.0 +* Dart SDK upper constraint raised to declare compatibility with Dart 2.0 stable. ## 0.9.0
diff --git a/protobuf/LICENSE b/protobuf/LICENSE index ab3bfa0..7efe25f 100644 --- a/protobuf/LICENSE +++ b/protobuf/LICENSE
@@ -1,4 +1,4 @@ -Copyright 2013, the Dart project authors. +Copyright 2013, the Dart project authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are
diff --git a/protobuf/README.md b/protobuf/README.md index 25c67cd..0bba861 100644 --- a/protobuf/README.md +++ b/protobuf/README.md
@@ -1,17 +1,17 @@ [![pub package](https://img.shields.io/pub/v/protobuf.svg)](https://pub.dev/packages/protobuf) -Provides runtime support for a Dart implementation of protobufs. +Provides runtime support for a Dart implementation of [protobufs][1]. -Typically one do not need to import this library–only libraries -generated by the protoc plugin import this library directly. +Typically one does not need to import this library. The [protoc plugin][2] +compiles proto definitions to Dart files that import this library. If your +library or application uses generated protobuf libraries, add this library as a +dependency. -If your library or application uses generated protobuf libraries, add this -library as a dependency. +[1]: https://developers.google.com/protocol-buffers +[2]: https://pub.dev/packages/protoc_plugin ### References -* [Dart tutorial](https://developers.google.com/protocol-buffers/docs/darttutorial) -* [Dart generated code guide](https://developers.google.com/protocol-buffers/docs/reference/dart-generated) -* [Dart API](https://pub.dev/documentation/protobuf/latest/) -* [Protobuf repository](https://github.com/google/protobuf) -* [Protoc plugin project](https://github.com/google/protobuf.dart/tree/master/protoc_plugin) +* [Protobuf Dart tutorial](https://developers.google.com/protocol-buffers/docs/darttutorial) +* [Guide to generated Dart code](https://developers.google.com/protocol-buffers/docs/reference/dart-generated) +* [Dart API](https://pub.dev/documentation/protobuf/latest/protobuf/protobuf-library.html)
diff --git a/protobuf/analysis_options.yaml b/protobuf/analysis_options.yaml index 56e6618..e841247 100644 --- a/protobuf/analysis_options.yaml +++ b/protobuf/analysis_options.yaml
@@ -2,7 +2,8 @@ linter: rules: - directives_ordering: true - prefer_relative_imports: true - prefer_single_quotes: true - prefer_spread_collections: false + - comment_references + - directives_ordering + - prefer_relative_imports + - prefer_single_quotes + - prefer_spread_collections
diff --git a/protobuf/benchmarks/README.md b/protobuf/benchmarks/README.md index df5d8ab..6a0824e 100644 --- a/protobuf/benchmarks/README.md +++ b/protobuf/benchmarks/README.md
@@ -3,8 +3,8 @@ This directory contains protobuf benchmarks adapted from [original protobuf]( https://github.com/google/protobuf/tree/master/benchmarks) library. -These benchmarks cover parsing and serializing protobufs both to -binary and JSON formats. +These benchmarks cover parsing and serializing protobufs both to binary and +JSON formats, and hash code generation for messages. ## Prerequisites
diff --git a/protobuf/benchmarks/benchmark_js.dart b/protobuf/benchmarks/benchmark_js.dart index 0d32987..63c08c5 100644 --- a/protobuf/benchmarks/benchmark_js.dart +++ b/protobuf/benchmarks/benchmark_js.dart
@@ -26,4 +26,5 @@ ToBinaryBenchmark(datasets).report(); ToJsonBenchmark(datasets).report(); FromJsonBenchmark(datasets).report(); + HashCodeBenchmark(datasets).report(); }
diff --git a/protobuf/benchmarks/benchmark_vm.dart b/protobuf/benchmarks/benchmark_vm.dart index 2b28bc4..77306f8 100644 --- a/protobuf/benchmarks/benchmark_vm.dart +++ b/protobuf/benchmarks/benchmark_vm.dart
@@ -24,4 +24,5 @@ ToBinaryBenchmark(datasets).report(); ToJsonBenchmark(datasets).report(); FromJsonBenchmark(datasets).report(); + HashCodeBenchmark(datasets).report(); }
diff --git a/protobuf/benchmarks/common.dart b/protobuf/benchmarks/common.dart index dbdfe1e..dbccf9d 100644 --- a/protobuf/benchmarks/common.dart +++ b/protobuf/benchmarks/common.dart
@@ -42,7 +42,7 @@ /// Messages deserialized from [packed]. Used in serialization benchmarks. final List<GeneratedMessage> unpacked = <GeneratedMessage>[]; - /// Create [Dataset] from a [BenchmarkDataset] proto. + /// Create [Dataset] from a `BenchmarkDataset` proto. factory Dataset.fromBinary(List<int> binary) { final dataSet = BenchmarkDataset.fromBuffer(binary); @@ -73,7 +73,7 @@ static Factories forMessage(String name) => _factories[name] ?? (throw 'Unsupported message: $name'); - /// Mapping between [BenchmarkProto.messageName] and corresponding + /// Mapping between `BenchmarkDataset.messageName` and corresponding /// deserialization factories. static final _factories = { 'benchmarks.proto2.GoogleMessage1': Factories._( @@ -164,3 +164,17 @@ } } } + +/// HashCode computation benchmark. +class HashCodeBenchmark extends _ProtobufBenchmark { + HashCodeBenchmark(datasets) : super(datasets, 'HashCode'); + + @override + void run() { + for (final dataset in datasets) { + for (final unpacked in dataset.unpacked) { + unpacked.hashCode; + } + } + } +}
diff --git a/protobuf/benchmarks/compile-js.sh b/protobuf/benchmarks/compile-js.sh index 0a93550..a232416 100755 --- a/protobuf/benchmarks/compile-js.sh +++ b/protobuf/benchmarks/compile-js.sh
@@ -10,7 +10,7 @@ mkdir -p "${OUTPUT_DIR}" -dart2js --trust-type-annotations \ +dart2js --omit-implicit-checks \ --trust-primitives \ -o "${OUTPUT_DIR}"/benchmark.js \ "${SCRIPT_DIR}"/benchmark_js.dart
diff --git a/protobuf/benchmarks/compile-protos.sh b/protobuf/benchmarks/compile-protos.sh index b01cb47..46dafd6 100755 --- a/protobuf/benchmarks/compile-protos.sh +++ b/protobuf/benchmarks/compile-protos.sh
@@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. @@ -30,8 +30,6 @@ mkdir -p ${OUTPUT_DIR} -for proto in ${PROTOS[@]} -do - echo "PROTOC ${proto}" - protoc -I"${SCRIPT_DIR}" --dart_out="${OUTPUT_DIR}" "${SCRIPT_DIR}/$proto" -done +set -x + +protoc -I"${SCRIPT_DIR}" --dart_out="${OUTPUT_DIR}" "${PROTOS[@]/#/$SCRIPT_DIR/}"
diff --git a/protobuf/benchmarks/d8.dart b/protobuf/benchmarks/d8.dart index d709383..f55ef70 100644 --- a/protobuf/benchmarks/d8.dart +++ b/protobuf/benchmarks/d8.dart
@@ -11,11 +11,11 @@ import 'package:js/js.dart'; /// Read the file at the given [path] and return its contents in -/// an [ArrayBuffer]. +/// an [ByteBuffer]. @JS() external ByteBuffer readbuffer(String path); -/// Read the file at the given [path] and return its contents in +/// Read the [file] and return its contents in /// a Uint8List. Uint8List readAsBytesSync(String file) { return Uint8List.view(readbuffer(file));
diff --git a/protobuf/lib/meta.dart b/protobuf/lib/meta.dart index 6601c02..446853b 100644 --- a/protobuf/lib/meta.dart +++ b/protobuf/lib/meta.dart
@@ -26,8 +26,6 @@ 'eventPlugin', 'extensionsAreInitialized', 'freeze', - 'fromBuffer', - 'fromJson', 'getDefaultForField', 'getExtension', 'getField', @@ -60,7 +58,6 @@ 'writeToCodedBufferWriter', 'writeToJson', 'writeToJsonMap', - r'$_defaultFor', r'$_ensure', r'$_get', r'$_getI64', @@ -83,6 +80,12 @@ r'$_setString', r'$_setUnsignedInt32', r'$_whichOneof', + + // Names below are no longer reserved and should be removed in the next major + // release + 'fromBuffer', + 'fromJson', + r'$_defaultFor', ]; // List of names which cannot be used in a subclass of ProtobufEnum. @@ -91,8 +94,11 @@ 'Object', 'ProtobufEnum', 'hashCode', - 'initByValue', 'noSuchMethod', 'runtimeType', - 'toString' + 'toString', + + // Names below are no longer reserved and should be removed in the next major + // release + 'initByValue', ];
diff --git a/protobuf/lib/protobuf.dart b/protobuf/lib/protobuf.dart index e2d5cdc..97e9044 100644 --- a/protobuf/lib/protobuf.dart +++ b/protobuf/lib/protobuf.dart
@@ -11,6 +11,7 @@ import 'dart:typed_data' show TypedData, Uint8List, ByteData, Endian; import 'package:fixnum/fixnum.dart' show Int64; +import 'package:meta/meta.dart' show UseResult; import 'src/protobuf/json_parsing_context.dart'; import 'src/protobuf/permissive_compare.dart'; @@ -20,6 +21,7 @@ part 'src/protobuf/coded_buffer.dart'; part 'src/protobuf/coded_buffer_reader.dart'; part 'src/protobuf/coded_buffer_writer.dart'; +part 'src/protobuf/consts.dart'; part 'src/protobuf/builder_info.dart'; part 'src/protobuf/event_plugin.dart'; part 'src/protobuf/exceptions.dart';
diff --git a/protobuf/lib/src/protobuf/builder_info.dart b/protobuf/lib/src/protobuf/builder_info.dart index 28f8b64..890daaf 100644 --- a/protobuf/lib/src/protobuf/builder_info.dart +++ b/protobuf/lib/src/protobuf/builder_info.dart
@@ -8,12 +8,22 @@ class BuilderInfo { /// The fully qualified name of this message. final String qualifiedMessageName; + + /// Maps [FieldInfo.index]s to [FieldInfo]s. final List<FieldInfo> byIndex = <FieldInfo>[]; + + /// Maps [FieldInfo.tagNumber]s to [FieldInfo]s. final Map<int, FieldInfo> fieldInfo = <int, FieldInfo>{}; + final Map<String, FieldInfo> byTagAsString = <String, FieldInfo>{}; + + /// Maps [FieldInfo.name]s to [FieldInfo]s. final Map<String, FieldInfo> byName = <String, FieldInfo>{}; - // Maps a tag number to the corresponding oneof index (if any). + + /// Maps a tag number ([FieldInfo.tagNumber]) to the corresponding `oneof` + /// index (if any). final Map<int, int> oneofs = <int, int>{}; + bool hasExtensions = false; bool hasRequiredFields = true; List<FieldInfo>? _sortedByTag; @@ -56,8 +66,8 @@ void addMapField<K, V>( int tagNumber, String name, - int? keyFieldType, - int? valueFieldType, + int keyFieldType, + int valueFieldType, BuilderInfo mapEntryBuilderInfo, CreateBuilderFunc? valueCreator, {ProtobufEnum? defaultEnumValue, @@ -211,8 +221,8 @@ // Map field. void m<K, V>(int tagNumber, String name, {String? entryClassName, - int? keyFieldType, - int? valueFieldType, + required int keyFieldType, + required int valueFieldType, CreateBuilderFunc? valueCreator, ValueOfFunc? valueOf, List<ProtobufEnum>? enumValues, @@ -267,7 +277,7 @@ return i?.valueOf; } - /// The FieldInfo for each field in tag number order. + /// The [FieldInfo] for each field in tag number order. List<FieldInfo> get sortedByTag => _sortedByTag ??= _computeSortedByTag(); /// The message name. Also see [qualifiedMessageName].
diff --git a/protobuf/lib/src/protobuf/coded_buffer.dart b/protobuf/lib/src/protobuf/coded_buffer.dart index 45c3f4e..be316c4 100644 --- a/protobuf/lib/src/protobuf/coded_buffer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer.dart
@@ -53,7 +53,7 @@ fs._setFieldUnchecked(meta, fi, input.readBool()); break; case PbFieldType._OPTIONAL_BYTES: - fs._setFieldUnchecked(meta, fi, input.readBytes()); + fs._setFieldUnchecked(meta, fi, Uint8List.fromList(input.readBytes())); break; case PbFieldType._OPTIONAL_STRING: fs._setFieldUnchecked(meta, fi, input.readString()); @@ -126,7 +126,9 @@ _readPackable(meta, fs, input, wireType, fi, input.readBool); break; case PbFieldType._REPEATED_BYTES: - fs._ensureRepeatedField(meta, fi).add(input.readBytes()); + fs + ._ensureRepeatedField(meta, fi) + .add(Uint8List.fromList(input.readBytes())); break; case PbFieldType._REPEATED_STRING: fs._ensureRepeatedField(meta, fi).add(input.readString());
diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index a39c620..2c8f37f 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart
@@ -14,7 +14,7 @@ /// length-delimited representation, which means that they are represented as /// a varint encoded length followed by specified number of bytes of data. /// -/// Due to this [CodedBufferWritter] maintains two output buffers: +/// Due to this [CodedBufferWriter] maintains two output buffers: /// [_outputChunks] which contains all continuously written bytes and /// [_splices] which describes additional bytes to splice in-between /// [_outputChunks] bytes. @@ -65,7 +65,7 @@ } void writeField(int fieldNumber, int fieldType, fieldValue) { - final valueType = fieldType & ~0x07; + final valueType = PbFieldType._baseType(fieldType); if ((fieldType & PbFieldType._PACKED_BIT) != 0) { if (!fieldValue.isEmpty) { @@ -79,8 +79,6 @@ return; } - final wireFormat = _wireTypes[_valueTypeIndex(valueType)]; - if ((fieldType & PbFieldType._MAP_BIT) != 0) { final keyWireFormat = _wireTypes[_valueTypeIndex(fieldValue.keyFieldType)]; @@ -99,6 +97,8 @@ return; } + final wireFormat = _wireTypes[_valueTypeIndex(valueType)]; + if ((fieldType & PbFieldType._REPEATED_BIT) != 0) { for (var i = 0; i < fieldValue.length; i++) { _writeValue(fieldNumber, valueType, fieldValue[i], wireFormat); @@ -176,8 +176,8 @@ /// Move the current [_outputChunk] into [_outputChunks]. /// - /// If [allocateNew] is [true] then allocate a new chunk, otherwise - /// set [_outputChunk] to null. + /// If [allocateNew] is `true` then allocate a new chunk, otherwise + /// set [_outputChunk] to `null`. void _commitChunk(bool allocateNew) { if (_bytesInChunk != 0) { _outputChunks.add(_outputChunk); @@ -445,8 +445,10 @@ /// where multiplication becomes a floating point multiplication. /// /// [1] http://supertech.csail.mit.edu/papers/debruijn.pdf - static int _valueTypeIndex(int powerOf2) => - ((0x077CB531 * powerOf2) >> 27) & 31; + int _valueTypeIndex(int powerOf2) { + assert(powerOf2 & (powerOf2 - 1) == 0, '$powerOf2 is not a power of 2'); + return ((0x077CB531 * powerOf2) >> 27) & 31; + } /// Precomputed indices for all FbFieldType._XYZ_BIT values: ///
diff --git a/protobuf/lib/src/protobuf/consts.dart b/protobuf/lib/src/protobuf/consts.dart new file mode 100644 index 0000000..a4fcd16 --- /dev/null +++ b/protobuf/lib/src/protobuf/consts.dart
@@ -0,0 +1,17 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of protobuf; + +/// Constant string value of double.infinity.toString() and the infinity value +/// recognized by double.parse(..). +const infinity = 'Infinity'; + +/// Constant string value of double.negativeInfinity.toString() and the negative +/// infinity value recognized by double.parse(..). +const negativeInfinity = '-Infinity'; + +/// Constant string value of double.nan.toString() and the NaN (not a number) +/// value recognized by double.parse(..). +const nan = 'NaN';
diff --git a/protobuf/lib/src/protobuf/extension_field_set.dart b/protobuf/lib/src/protobuf/extension_field_set.dart index 2497e03..c3f9e3a 100644 --- a/protobuf/lib/src/protobuf/extension_field_set.dart +++ b/protobuf/lib/src/protobuf/extension_field_set.dart
@@ -132,6 +132,9 @@ if (_parent._hasObservers) { _parent._eventPlugin!.beforeSetField(fi, value); } + // If there was already an unknown field with the same tag number, + // overwrite it. + _parent._unknownFields?.clearField(fi.tagNumber); _values[fi.tagNumber] = value; }
diff --git a/protobuf/lib/src/protobuf/extension_registry.dart b/protobuf/lib/src/protobuf/extension_registry.dart index 93aa9fc..196b1fd 100644 --- a/protobuf/lib/src/protobuf/extension_registry.dart +++ b/protobuf/lib/src/protobuf/extension_registry.dart
@@ -35,7 +35,7 @@ return null; } - /// Returns a shallow copy of [message], with all extensions in [this] parsed + /// Returns a shallow copy of [message], with all extensions in `this` parsed /// from the unknown fields of [message] and of every nested submessage. /// /// Extensions already present in [message] will be preserved. @@ -49,7 +49,7 @@ /// /// Using this method to retrieve extensions is more expensive overall than /// using an [ExtensionRegistry] with all the needed extensions when doing - /// [GeneratedMessage.fromBuffer]. + /// [GeneratedMessage.mergeFromBuffer]. /// /// Example: /// @@ -148,7 +148,7 @@ } else if (field is MapFieldInfo) { final messageMap = message._fieldSet._values[field.index!]; if (messageMap == null) continue; - if (_isGroupOrMessage(field.valueFieldType!)) { + if (_isGroupOrMessage(field.valueFieldType)) { for (var key in messageMap.keys) { final GeneratedMessage value = messageMap[key]; final reparsedValue = _reparseMessage(value, extensionRegistry);
diff --git a/protobuf/lib/src/protobuf/field_info.dart b/protobuf/lib/src/protobuf/field_info.dart index 9d9deb3..637ed96 100644 --- a/protobuf/lib/src/protobuf/field_info.dart +++ b/protobuf/lib/src/protobuf/field_info.dart
@@ -8,44 +8,71 @@ class FieldInfo<T> { FrozenPbList<T>? _emptyList; - /// Name of this field as the `json_name` reported by protoc. - /// - /// This will typically be in camel case. + /// Name of this field as the `json_name` reported by protoc. Example: + /// ```proto + /// message Msg { + /// int32 foo_name = 1 [json_name = "barName"]; + /// } + /// ``` + /// Here `name` of the field is `barName`. When `json_name` is not specified + /// in the proto definition, this is the camelCase version of the field name. + /// In the example above, without the `json_name` field option, `name` would + /// be `"fooName"`. final String name; - /// The name of this field as written in the proto-definition. - /// + /// Name of this field as written in the proto definition. Example: + /// ```proto + /// message SearchRequest { + /// ... + /// int32 result_per_page = 3; + /// } + /// ``` + /// `protoName` for the `result_per_page` field above is `"result_per_page"`. /// This will typically consist of words separated with underscores. - final String protoName; + String get protoName { + return _protoName ??= _unCamelCase(name); + } + String? _protoName; + + /// Field number as specified in the proto definition. Example: + /// ```proto + /// message SearchRequest { + /// ... + /// int32 result_per_page = 3; + /// } + /// ``` + /// `tagNumber` of `result_per_page` field is 3. final int tagNumber; - final int? index; // index of the field's value. Null for extensions. + + /// Index of the field in [_FieldSet._values] list of this field's message. + /// `null` for extensions. + final int? index; + + /// Type of this field. See `field_type.dart`. final int type; - // Constructs the default value of a field. - // (Only used for repeated fields where check is null.) + /// Constructs the default value of a field. For repeated fields, only used + /// when the `check` property is null. final MakeDefaultFunc? makeDefault; - // Creates an empty message or group when decoding a message. - // Not used for other types. - // see GeneratedMessage._getEmptyMessage + /// Only available in fields with message type. Creates an empty message or + /// group when decoding a message. final CreateBuilderFunc? subBuilder; - // List of all enum enumValues. - // (Not used for other types.) + /// Only available in enum fields. List of all enum values. final List<ProtobufEnum>? enumValues; - // Default enum value, if type is a PbList<ProtobufEnum> or a - // PbMap<[anything], ProtobufEnum>. + /// Only available in enum fields. Default enum value or a + /// `PbMap<[anything], ProtobufEnum>`. final ProtobufEnum? defaultEnumValue; - // Looks up the enum value given its integer code. - // (Not used for other types.) - // see GeneratedMessage._getValueOfFunc + /// Only available in enum fields. Looks up the enum value given its integer + /// code. final ValueOfFunc? valueOf; - // Verifies an item being added to a repeated field - // (Not used for non-repeated fields.) + /// Only available in repeated fields. Verifies an item being added to a + /// repeated field. final CheckFunc<T>? check; FieldInfo(this.name, this.tagNumber, this.index, this.type, @@ -57,7 +84,7 @@ String? protoName}) : makeDefault = findMakeDefault(type, defaultOrMaker), check = null, - protoName = protoName ?? _unCamelCase(name), + _protoName = protoName, assert(type != 0), assert(!_isGroupOrMessage(type) || subBuilder != null || @@ -67,7 +94,7 @@ // Represents a field that has been removed by a program transformation. FieldInfo.dummy(this.index) : name = '<removed field>', - protoName = '<removed field>', + _protoName = '<removed field>', tagNumber = 0, type = 0, makeDefault = null, @@ -81,7 +108,7 @@ this.check, this.subBuilder, {this.valueOf, this.enumValues, this.defaultEnumValue, String? protoName}) : makeDefault = (() => PbList<T>(check: check!)), - protoName = protoName ?? _unCamelCase(name) { + _protoName = protoName { ArgumentError.checkNotNull(name, 'name'); ArgumentError.checkNotNull(tagNumber, 'tagNumber'); assert(_isRepeated(type)); @@ -105,8 +132,8 @@ bool get isEnum => _isEnum(type); bool get isMapField => _isMapField(type); - /// Returns a read-only default value for a field. - /// (Unlike getField, doesn't create a repeated field.) + /// Returns a read-only default value for a field. Unlike + /// [GeneratedMessage.getField], doesn't create a repeated field. dynamic get readonlyDefault { if (isRepeated) { return _emptyList ??= FrozenPbList._([]); @@ -198,8 +225,17 @@ } class MapFieldInfo<K, V> extends FieldInfo<PbMap<K, V>?> { - final int? keyFieldType; - final int? valueFieldType; + /// Key type of the map. Per proto2 and proto3 specs, this needs to be an + /// integer type or `string`, and the type cannot be `repeated`. + /// + /// The `int` value is interpreted the same way as [FieldInfo.type]. + final int keyFieldType; + + /// Value type of the map. Per proto2 and proto3 specs, this can be any type + /// other than `map`, and the type cannot be `repeated`. + /// + /// The `int` value is interpreted the same way as [FieldInfo.type]. + final int valueFieldType; /// Creates a new empty instance of the value type. ///
diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart index f2e6faa..ff36282 100644 --- a/protobuf/lib/src/protobuf/field_set.dart +++ b/protobuf/lib/src/protobuf/field_set.dart
@@ -244,7 +244,7 @@ List<T> _getDefaultList<T>(FieldInfo<T> fi) { assert(fi.isRepeated); - if (_isReadOnly) return FrozenPbList._(const []); + if (_isReadOnly) return fi.readonlyDefault; // TODO(skybrian) we could avoid this by generating another // method for repeated fields: @@ -387,7 +387,7 @@ assert(fi.index != null); // Map fields are not allowed to be extensions. var value = _getFieldOrNull(fi); - if (value != null) return (value as Map<K, V>) as PbMap<K, V>; + if (value != null) return value as PbMap<K, V>; var newValue = fi._createMapField(_message!); _setNonExtensionFieldUnchecked(meta, fi, newValue); @@ -465,8 +465,7 @@ if (defaultValue != null) return defaultValue; value = _getDefault(_nonExtensionInfoByIndex(index)); } - bool result = value; - return result; + return value; } /// The implementation of a generated getter for `bool` fields that default to @@ -474,8 +473,7 @@ bool _$getBF(int index) { var value = _values[index]; if (value == null) return false; - bool result = value; - return result; + return value; } /// The implementation of a generated getter for int fields. @@ -485,8 +483,7 @@ if (defaultValue != null) return defaultValue; value = _getDefault(_nonExtensionInfoByIndex(index)); } - int result = value; - return result; + return value; } /// The implementation of a generated getter for `int` fields (int32, uint32, @@ -494,8 +491,7 @@ int _$getIZ(int index) { var value = _values[index]; if (value == null) return 0; - int result = value; - return result; + return value; } /// The implementation of a generated getter for String fields. @@ -505,8 +501,7 @@ if (defaultValue != null) return defaultValue; value = _getDefault(_nonExtensionInfoByIndex(index)); } - String result = value; - return result; + return value; } /// The implementation of a generated getter for String fields that default to @@ -514,16 +509,14 @@ String _$getSZ(int index) { var value = _values[index]; if (value == null) return ''; - String result = value; - return result; + return value; } /// The implementation of a generated getter for Int64 fields. Int64 _$getI64(int index) { var value = _values[index]; value ??= _getDefault(_nonExtensionInfoByIndex(index)); - Int64 result = value; - return result; + return value; } /// The implementation of a generated 'has' method. @@ -636,6 +629,11 @@ // We don't want reading a field to change equality comparisons. if (val is List && val.isEmpty) return true; + // An empty map field is the same as uninitialized. + // This is because accessing a map field automatically creates it. + // We don't want reading a field to change equality comparisons. + if (val is Map && val.isEmpty) return true; + // For now, initialized and uninitialized fields are different. // TODO(skybrian) consider other cases; should we compare with the // default value or not? @@ -654,60 +652,65 @@ if (_hashCodesCanBeMemoized && _memoizedHashCode != null) { return _memoizedHashCode!; } - // Hashes the value of one field (recursively). - int hashField(int hash, FieldInfo fi, value) { - if (value is List && value.isEmpty) { - return hash; // It's either repeated or an empty byte array. - } - - hash = _HashUtils._combine(hash, fi.tagNumber); - if (_isBytes(fi.type)) { - // Bytes are represented as a List<int> (Usually with byte-data). - // We special case that to match our equality semantics. - hash = _HashUtils._combine(hash, _HashUtils._hashObjects(value)); - } else if (!_isEnum(fi.type)) { - hash = _HashUtils._combine(hash, value.hashCode); - } else if (fi.isRepeated) { - hash = _HashUtils._hashObjects(value.map((enm) => enm.value)); - } else { - ProtobufEnum enm = value; - hash = _HashUtils._combine(hash, enm.value); - } - - return hash; - } - - int hashEachField(int hash) { - //non-extension fields - hash = _infosSortedByTag.where((fi) => _values[fi.index!] != null).fold( - hash, (int h, FieldInfo fi) => hashField(h, fi, _values[fi.index!])); - - if (!_hasExtensions) return hash; - - hash = - _sorted(_extensions!._tagNumbers).fold(hash, (int h, int tagNumber) { - var fi = _extensions!._getInfoOrNull(tagNumber)!; - return hashField(h, fi, _extensions!._getFieldOrNull(fi)); - }); - - return hash; - } // Hash with descriptor. var hash = _HashUtils._combine(0, _meta.hashCode); - // Hash with fields. - hash = hashEachField(hash); - // Hash with unknown fields. - if (_hasUnknownFields) { - hash = _HashUtils._combine(hash, _unknownFields.hashCode); + + // Hash with non-extension fields. + final values = _values; + for (final fi in _infosSortedByTag) { + final value = values[fi.index!]; + if (value == null) continue; + hash = _hashField(hash, fi, value); } + // Hash with extension fields. + if (_hasExtensions) { + final extensions = _extensions!; + final sortedByTagNumbers = _sorted(extensions._tagNumbers); + for (final tagNumber in sortedByTagNumbers) { + final fi = extensions._getInfoOrNull(tagNumber)!; + hash = _hashField(hash, fi, extensions._getFieldOrNull(fi)); + } + } + + // Hash with unknown fields. + hash = _HashUtils._combine(hash, _unknownFields?.hashCode ?? 0); + if (_isReadOnly && _hashCodesCanBeMemoized) { _frozenState = hash; } return hash; } + // Hashes the value of one field (recursively). + static int _hashField(int hash, FieldInfo fi, value) { + if (value is List && value.isEmpty) { + return hash; // It's either repeated or an empty byte array. + } + + if (value is Map && value.isEmpty) { + return hash; + } + + hash = _HashUtils._combine(hash, fi.tagNumber); + if (_isBytes(fi.type)) { + // Bytes are represented as a List<int> (Usually with byte-data). + // We special case that to match our equality semantics. + hash = _HashUtils._combine(hash, _HashUtils._hashObjects(value)); + } else if (!_isEnum(fi.type)) { + hash = _HashUtils._combine(hash, value.hashCode); + } else if (fi.isRepeated) { + hash = _HashUtils._combine( + hash, _HashUtils._hashObjects(value.map((enm) => enm.value))); + } else { + ProtobufEnum enm = value; + hash = _HashUtils._combine(hash, enm.value); + } + + return hash; + } + void writeString(StringBuffer out, String indent) { void renderValue(key, value) { if (value is GeneratedMessage) { @@ -741,7 +744,8 @@ } for (var fi in _infosSortedByTag) { - writeFieldValue(_values[fi.index!], fi.name); + writeFieldValue(_values[fi.index!], + fi.name == '' ? fi.tagNumber.toString() : fi.name); } if (_hasExtensions) { @@ -765,7 +769,7 @@ /// recursively merged. void _mergeFromMessage(_FieldSet other) { // TODO(https://github.com/google/protobuf.dart/issues/60): Recognize - // when [this] and [other] are the same protobuf (e.g. from cloning). In + // when `this` and [other] are the same protobuf (e.g. from cloning). In // this case, we can merge the non-extension fields without field lookups or // validation checks. @@ -803,7 +807,7 @@ if (fi!.isMapField) { var f = fi as MapFieldInfo<dynamic, dynamic>; - mustClone = _isGroupOrMessage(f.valueFieldType!); + mustClone = _isGroupOrMessage(f.valueFieldType); var map = f._ensureMapField(meta, this) as PbMap<dynamic, dynamic>; if (mustClone) { for (MapEntry entry in fieldValue.entries) {
diff --git a/protobuf/lib/src/protobuf/generated_message.dart b/protobuf/lib/src/protobuf/generated_message.dart index 64d1395..6fa71d7 100644 --- a/protobuf/lib/src/protobuf/generated_message.dart +++ b/protobuf/lib/src/protobuf/generated_message.dart
@@ -29,19 +29,6 @@ if (eventPlugin != null) eventPlugin!.attach(this); } - GeneratedMessage.fromBuffer( - List<int> input, ExtensionRegistry extensionRegistry) { - __fieldSet = _FieldSet(this, info_, eventPlugin); - if (eventPlugin != null) eventPlugin!.attach(this); - mergeFromBuffer(input, extensionRegistry); - } - - GeneratedMessage.fromJson(String input, ExtensionRegistry extensionRegistry) { - __fieldSet = _FieldSet(this, info_, eventPlugin); - if (eventPlugin != null) eventPlugin!.attach(this); - mergeFromJson(input, extensionRegistry); - } - // Overridden by subclasses. BuilderInfo get info_; @@ -78,11 +65,11 @@ /// Returns a writable, shallow copy of this message. /// - /// Sub messages will be shared with [this] and will still be frozen if [this] + /// Sub messages will be shared with `this` and will still be frozen if `this` /// is frozen. /// /// The lists representing repeated fields are copied. But their elements will - /// be shared with the corresponding list in [this]. + /// be shared with the corresponding list in `this`. /// /// Similarly for map fields, the maps will be copied, but share the elements. // TODO(nichite, sigurdm): Consider returning an actual builder object that @@ -95,7 +82,7 @@ /// Apply [updates] to a copy of this message. /// - /// Makes a writable shawwol copy of this message, applies the [updates] to + /// Makes a writable shallow copy of this message, applies the [updates] to /// it, and marks the copy read-only before returning it. @Deprecated('Using this can add significant size overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' @@ -216,10 +203,10 @@ /// actual runtime value) are represented as strings. Enumerated values are /// represented as their integer value. /// - /// For the proto3 JSON format use: [toProto3JSON]. + /// For the proto3 JSON format use: [toProto3Json]. String writeToJson() => jsonEncode(writeToJsonMap()); - /// Returns an Object representing Proto3 JSON serialization of [this]. + /// Returns an Object representing Proto3 JSON serialization of `this`. /// /// The key for each field is be the camel-cased name of the field. /// @@ -273,7 +260,7 @@ /// Merges field values from [data], a JSON object, encoded as described by /// [GeneratedMessage.writeToJson]. /// - /// For the proto3 JSON format use: [mergeFromProto3JSON]. + /// For the proto3 JSON format use: [mergeFromProto3Json]. void mergeFromJson(String data, [ExtensionRegistry extensionRegistry = ExtensionRegistry.EMPTY]) { /// Disable lazy creation of Dart objects for a dart2js speedup. @@ -506,27 +493,42 @@ // Support for generating a read-only default singleton instance. - static final Map<Function?, Function> _defaultMakers = {}; + static final Map<Function?, _SingletonMaker<GeneratedMessage>> + _defaultMakers = {}; static T Function() _defaultMakerFor<T extends GeneratedMessage>( - T Function()? createFn) { - return (_defaultMakers[createFn] ??= _createDefaultMakerFor<T>(createFn!)) - as T Function(); - } - - static T Function() _createDefaultMakerFor<T extends GeneratedMessage>( - T Function() createFn) { - T? defaultValue; - T defaultMaker() { - return defaultValue ??= createFn()..freeze(); - } - - return defaultMaker; - } + T Function()? createFn) => + _getSingletonMaker(createFn!)._frozenSingletonCreator; /// For generated code only. static T $_defaultFor<T extends GeneratedMessage>(T Function() createFn) => - _defaultMakerFor<T>(createFn)(); + _getSingletonMaker(createFn)._frozenSingleton; + + static _SingletonMaker<T> _getSingletonMaker<T extends GeneratedMessage>( + T Function() fun) { + final oldMaker = _defaultMakers[fun]; + if (oldMaker != null) { + // The CFE will insert an implicit downcast to `_SingletonMaker<T>`. We + // avoid making that explicit because implicit downcasts are avoided by + // dart2js in production code. + return oldMaker as dynamic; + } + return _defaultMakers[fun] = _SingletonMaker<T>(fun); + } +} + +// We use a class that creates singletones instead of a closure function. We do +// so because the result of the lookup in [_defaultMakers] has to be downcasted. +// A downcast to a generic interface type is much easier to perform at runtime +// than a downcast to a generic function type. +class _SingletonMaker<T extends GeneratedMessage> { + final T Function() _creator; + + _SingletonMaker(this._creator); + + late final T _frozenSingleton = _creator()..freeze(); + // ignore: prefer_function_declarations_over_variables + late final T Function() _frozenSingletonCreator = () => _frozenSingleton; } /// The package name of a protobuf message. @@ -543,6 +545,8 @@ /// /// Makes a writable shallow copy of this message, applies the [updates] to /// it, and marks the copy read-only before returning it. + @UseResult('[GeneratedMessageGenericExtensions.rebuild] ' + 'does not update the message, returns a new message') T rebuild(void Function(T) updates) { if (!isFrozen) { throw ArgumentError('Rebuilding only works on frozen messages.');
diff --git a/protobuf/lib/src/protobuf/json.dart b/protobuf/lib/src/protobuf/json.dart index 0a5c827..011323f 100644 --- a/protobuf/lib/src/protobuf/json.dart +++ b/protobuf/lib/src/protobuf/json.dart
@@ -15,14 +15,25 @@ switch (baseType) { case PbFieldType._BOOL_BIT: case PbFieldType._STRING_BIT: - case PbFieldType._FLOAT_BIT: - case PbFieldType._DOUBLE_BIT: case PbFieldType._INT32_BIT: case PbFieldType._SINT32_BIT: case PbFieldType._UINT32_BIT: case PbFieldType._FIXED32_BIT: case PbFieldType._SFIXED32_BIT: return fieldValue; + case PbFieldType._FLOAT_BIT: + case PbFieldType._DOUBLE_BIT: + final value = fieldValue as double; + if (value.isNaN) { + return nan; + } + if (value.isInfinite) { + return value.isNegative ? negativeInfinity : infinity; + } + if (fieldValue.toInt() == fieldValue) { + return fieldValue.toInt(); + } + return value; case PbFieldType._BYTES_BIT: // Encode 'bytes' as a base64-encoded string. return base64Encode(fieldValue as List<int>); @@ -45,9 +56,9 @@ List _writeMap(dynamic fieldValue, MapFieldInfo fi) => List.from(fieldValue.entries.map((MapEntry e) => { - '${PbMap._keyFieldNumber}': convertToMap(e.key, fi.keyFieldType!), + '${PbMap._keyFieldNumber}': convertToMap(e.key, fi.keyFieldType), '${PbMap._valueFieldNumber}': - convertToMap(e.value, fi.valueFieldType!) + convertToMap(e.value, fi.valueFieldType) })); var result = <String, dynamic>{}; @@ -131,14 +142,14 @@ entryFieldSet, jsonEntry['${PbMap._keyFieldNumber}'], PbMap._keyFieldNumber, - fi.keyFieldType!, + fi.keyFieldType, registry); var convertedValue = _convertJsonValue( entryMeta, entryFieldSet, jsonEntry['${PbMap._valueFieldNumber}'], PbMap._valueFieldNumber, - fi.valueFieldType!, + fi.valueFieldType, registry); // In the case of an unknown enum value, the converted value may return // null. The default enum value should be used in these cases, which is @@ -166,7 +177,7 @@ /// Converts [value] from the Json format to the Dart data type /// suitable for inserting into the corresponding [GeneratedMessage] field. /// -/// Returns the converted value. This function returns [null] if it is an +/// Returns the converted value. This function returns `null` if it is an /// unknown enum value, in which case the caller should figure out the default /// enum value to return instead. /// This function throws [ArgumentError] if it cannot convert the value.
diff --git a/protobuf/lib/src/protobuf/json_parsing_context.dart b/protobuf/lib/src/protobuf/json_parsing_context.dart index 7d74fbf..5d11ced 100644 --- a/protobuf/lib/src/protobuf/json_parsing_context.dart +++ b/protobuf/lib/src/protobuf/json_parsing_context.dart
@@ -24,7 +24,7 @@ _path.removeLast(); } - /// Returns a FormatException indicating the indices to the current [path]. + /// Returns a FormatException indicating the indices to the current path. Exception parseException(String message, Object? source) { var formattedPath = _path.map((s) => '["$s"]').join(); return FormatException(
diff --git a/protobuf/lib/src/protobuf/mixins/well_known.dart b/protobuf/lib/src/protobuf/mixins/well_known.dart index 308832b..66854c9 100644 --- a/protobuf/lib/src/protobuf/mixins/well_known.dart +++ b/protobuf/lib/src/protobuf/mixins/well_known.dart
@@ -8,7 +8,6 @@ import '../../../protobuf.dart'; import '../json_parsing_context.dart'; -import '../type_registry.dart'; abstract class AnyMixin implements GeneratedMessage { String get typeUrl; @@ -86,7 +85,7 @@ 'The type of the Any message (${any.typeUrl}) is not in the given typeRegistry.'); } var unpacked = info.createEmptyInstance!()..mergeFromBuffer(any.value); - var proto3Json = unpacked.toProto3Json(); + var proto3Json = unpacked.toProto3Json(typeRegistry: typeRegistry); if (info.toProto3Json == null) { var map = proto3Json as Map<String, dynamic>; map['@type'] = any.typeUrl; @@ -152,16 +151,19 @@ /// /// The result is in UTC time zone and has microsecond precision, as /// [DateTime] does not support nanosecond precision. - DateTime toDateTime() => DateTime.fromMicrosecondsSinceEpoch( - seconds.toInt() * Duration.microsecondsPerSecond + nanos ~/ 1000, - isUtc: true); + /// + /// Use [toLocal] to convert to local time zone, instead of the default UTC. + DateTime toDateTime({bool toLocal = false}) => + DateTime.fromMicrosecondsSinceEpoch( + seconds.toInt() * Duration.microsecondsPerSecond + nanos ~/ 1000, + isUtc: !toLocal); - /// Updates [target] to be the time at [datetime]. + /// Updates [target] to be the time at [dateTime]. /// /// Time zone information will not be preserved. static void setFromDateTime(TimestampMixin target, DateTime dateTime) { var micros = dateTime.microsecondsSinceEpoch; - target.seconds = Int64(micros ~/ Duration.microsecondsPerSecond); + target.seconds = Int64((micros / Duration.microsecondsPerSecond).floor()); target.nanos = (micros % Duration.microsecondsPerSecond).toInt() * 1000; }
diff --git a/protobuf/lib/src/protobuf/pb_list.dart b/protobuf/lib/src/protobuf/pb_list.dart index fac87cd..6b53d1f 100644 --- a/protobuf/lib/src/protobuf/pb_list.dart +++ b/protobuf/lib/src/protobuf/pb_list.dart
@@ -75,118 +75,86 @@ /// Freezes the list by converting to [FrozenPbList]. FrozenPbList<E> toFrozenPbList() => FrozenPbList<E>.from(this); - /// Adds [value] at the end of the list, extending the length by one. - /// Throws an [UnsupportedError] if the list is not extendable. @override - void add(E value) { - check(value); - _wrappedList.add(value); + void add(E element) { + check(element); + _wrappedList.add(element); } - /// Appends all elements of the [collection] to the end of list. - /// Extends the length of the list by the length of [collection]. - /// Throws an [UnsupportedError] if the list is not extendable. @override - void addAll(Iterable<E> collection) { - collection.forEach(check); - _wrappedList.addAll(collection); + void addAll(Iterable<E> iterable) { + iterable.forEach(check); + _wrappedList.addAll(iterable); } - /// Returns an [Iterable] of the objects in this list in reverse order. @override Iterable<E> get reversed => _wrappedList.reversed; - /// Sorts this list according to the order specified by the [compare] - /// function. @override void sort([int Function(E a, E b)? compare]) => _wrappedList.sort(compare); - /// Shuffles the elements of this list randomly. @override void shuffle([math.Random? random]) => _wrappedList.shuffle(random); - /// Removes all objects from this list; the length of the list becomes zero. @override void clear() => _wrappedList.clear(); - /// Inserts a new element in the list. - /// The element must be valid (and not nullable) for the PbList type. @override void insert(int index, E element) { check(element); _wrappedList.insert(index, element); } - /// Inserts all elements of [iterable] at position [index] in the list. - /// - /// Elements in [iterable] must be valid and not nullable for the PbList type. @override void insertAll(int index, Iterable<E> iterable) { iterable.forEach(check); _wrappedList.insertAll(index, iterable); } - /// Overwrites elements of `this` with elements of [iterable] starting at - /// position [index] in the list. - /// - /// Elements in [iterable] must be valid and not nullable for the PbList type. @override void setAll(int index, Iterable<E> iterable) { iterable.forEach(check); _wrappedList.setAll(index, iterable); } - /// Removes the first occurrence of [value] from this list. @override - bool remove(Object? value) => _wrappedList.remove(value); + bool remove(Object? element) => _wrappedList.remove(element); - /// Removes the object at position [index] from this list. @override E removeAt(int index) => _wrappedList.removeAt(index); - /// Pops and returns the last object in this list. @override E removeLast() => _wrappedList.removeLast(); - /// Removes all objects from this list that satisfy [test]. @override void removeWhere(bool Function(E element) test) => _wrappedList.removeWhere(test); - /// Removes all objects from this list that fail to satisfy [test]. @override void retainWhere(bool Function(E element) test) => _wrappedList.retainWhere(test); - /// Copies [:end - start:] elements of the [from] array, starting from - /// [skipCount], into [:this:], starting at [start]. - /// Throws an [UnsupportedError] if the list is not extendable. @override - void setRange(int start, int end, Iterable<E> from, [int skipCount = 0]) { + void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { // NOTE: In case `take()` returns less than `end - start` elements, the // _wrappedList will fail with a `StateError`. - from.skip(skipCount).take(end - start).forEach(check); - _wrappedList.setRange(start, end, from, skipCount); + iterable.skip(skipCount).take(end - start).forEach(check); + _wrappedList.setRange(start, end, iterable, skipCount); } - /// Removes the objects in the range [start] inclusive to [end] exclusive. @override void removeRange(int start, int end) => _wrappedList.removeRange(start, end); - /// Sets the objects in the range [start] inclusive to [end] exclusive to the - /// given [fillValue]. @override - void fillRange(int start, int end, [E? fillValue]) { - check(fillValue); - _wrappedList.fillRange(start, end, fillValue); + void fillRange(int start, int end, [E? fill]) { + check(fill); + _wrappedList.fillRange(start, end, fill); } - /// Removes the objects in the range [start] inclusive to [end] exclusive and - /// inserts the contents of [replacement] in its place. @override - void replaceRange(int start, int end, Iterable<E> replacement) { - final values = replacement.toList(); - replacement.forEach(check); + void replaceRange(int start, int end, Iterable<E> newContents) { + final values = newContents.toList(); + newContents.forEach(check); _wrappedList.replaceRange(start, end, values); } } @@ -213,167 +181,119 @@ @override int get hashCode => _HashUtils._hashObjects(_wrappedList); - /// Returns an [Iterator] for the list. @override Iterator<E> get iterator => _wrappedList.iterator; - /// Returns a new lazy [Iterable] with elements that are created by calling - /// `f` on each element of this `PbListBase` in iteration order. @override Iterable<T> map<T>(T Function(E e) f) => _wrappedList.map<T>(f); - /// Returns a new lazy [Iterable] with all elements that satisfy the predicate - /// [test]. @override Iterable<E> where(bool Function(E element) test) => _wrappedList.where(test); - /// Expands each element of this [Iterable] into zero or more elements. @override Iterable<T> expand<T>(Iterable<T> Function(E element) f) => _wrappedList.expand(f); - /// Returns true if the collection contains an element equal to [element]. @override bool contains(Object? element) => _wrappedList.contains(element); - /// Applies the function [f] to each element of this list in iteration order. @override - void forEach(void Function(E element) f) { - _wrappedList.forEach(f); + void forEach(void Function(E element) action) { + _wrappedList.forEach(action); } - /// Reduces a collection to a single value by iteratively combining elements - /// of the collection using the provided function. @override E reduce(E Function(E value, E element) combine) => _wrappedList.reduce(combine); - /// Reduces a collection to a single value by iteratively combining each - /// element of the collection with an existing value. @override T fold<T>(T initialValue, T Function(T previousValue, E element) combine) => _wrappedList.fold(initialValue, combine); - /// Checks whether every element of this iterable satisfies [test]. @override bool every(bool Function(E element) test) => _wrappedList.every(test); - /// Converts each element to a [String] and concatenates the strings. @override String join([String separator = '']) => _wrappedList.join(separator); - /// Checks whether any element of this iterable satisfies [test]. @override bool any(bool Function(E element) test) => _wrappedList.any(test); - /// Creates a [List] containing the elements of this [Iterable]. @override List<E> toList({bool growable = true}) => _wrappedList.toList(growable: growable); - /// Creates a [Set] containing the same elements as this iterable. @override Set<E> toSet() => _wrappedList.toSet(); - /// Returns `true` if there are no elements in this collection. @override bool get isEmpty => _wrappedList.isEmpty; - /// Returns `true` if there is at least one element in this collection. @override bool get isNotEmpty => _wrappedList.isNotEmpty; - /// Returns a lazy iterable of the [count] first elements of this iterable. @override Iterable<E> take(int count) => _wrappedList.take(count); - /// Returns a lazy iterable of the leading elements satisfying [test]. @override Iterable<E> takeWhile(bool Function(E value) test) => _wrappedList.takeWhile(test); - /// Returns an [Iterable] that provides all but the first [count] elements. @override Iterable<E> skip(int count) => _wrappedList.skip(count); - /// Returns an `Iterable` that skips leading elements while [test] is - /// satisfied. @override Iterable<E> skipWhile(bool Function(E value) test) => _wrappedList.skipWhile(test); - /// Returns the first element. @override E get first => _wrappedList.first; - /// Returns the last element. @override E get last => _wrappedList.last; - /// Checks that this iterable has only one element, and returns that element. @override E get single => _wrappedList.single; - /// Returns the first element that satisfies the given predicate [test]. @override E firstWhere(bool Function(E element) test, {E Function()? orElse}) => _wrappedList.firstWhere(test, orElse: orElse); - /// Returns the last element that satisfies the given predicate [test]. @override E lastWhere(bool Function(E element) test, {E Function()? orElse}) => _wrappedList.lastWhere(test, orElse: orElse); - /// Returns the single element that satisfies [test]. - // TODO(jakobr): Implement once Dart 2 corelib changes have landed. - //E singleWhere(bool test(E element), {E orElse()}) => - // _wrappedList.singleWhere(test, orElse: orElse); - - /// Returns the [index]th element. @override E elementAt(int index) => _wrappedList.elementAt(index); - /// Returns a string representation of (some of) the elements of `this`. @override String toString() => _wrappedList.toString(); - /// Returns the element at the given [index] in the list or throws an - /// [IndexOutOfRangeException] if [index] is out of bounds. @override E operator [](int index) => _wrappedList[index]; - /// Returns the number of elements in this collection. @override int get length => _wrappedList.length; // TODO(jakobr): E instead of Object once dart-lang/sdk#31311 is fixed. - /// Returns the first index of [element] in this list. @override int indexOf(Object? element, [int start = 0]) => _wrappedList.indexOf(element as E, start); // TODO(jakobr): E instead of Object once dart-lang/sdk#31311 is fixed. - /// Returns the last index of [element] in this list. @override int lastIndexOf(Object? element, [int? start]) => _wrappedList.lastIndexOf(element as E, start); - /// Returns a new list containing the objects from [start] inclusive to [end] - /// exclusive. @override List<E> sublist(int start, [int? end]) => _wrappedList.sublist(start, end); - /// Returns an [Iterable] that iterates over the objects in the range [start] - /// inclusive to [end] exclusive. @override Iterable<E> getRange(int start, int end) => _wrappedList.getRange(start, end); - /// Returns an unmodifiable [Map] view of `this`. @override Map<int, E> asMap() => _wrappedList.asMap(); - /// Sets the entry at the given [index] in the list to [value]. - /// Throws an [IndexOutOfRangeException] if [index] is out of bounds. @override void operator []=(int index, E value) { check(value);
diff --git a/protobuf/lib/src/protobuf/pb_map.dart b/protobuf/lib/src/protobuf/pb_map.dart index cb0b5cd..712f812 100644 --- a/protobuf/lib/src/protobuf/pb_map.dart +++ b/protobuf/lib/src/protobuf/pb_map.dart
@@ -5,8 +5,17 @@ part of protobuf; class PbMap<K, V> extends MapBase<K, V> { - final int? keyFieldType; - final int? valueFieldType; + /// Key type of the map. Per proto2 and proto3 specs, this needs to be an + /// integer type or `string`, and the type cannot be `repeated`. + /// + /// The `int` value is interpreted the same way as [FieldInfo.type]. + final int keyFieldType; + + /// Value type of the map. Per proto2 and proto3 specs, this can be any type + /// other than `map`, and the type cannot be `repeated`. + /// + /// The `int` value is interpreted the same way as [FieldInfo.type]. + final int valueFieldType; static const int _keyFieldNumber = 1; static const int _valueFieldNumber = 2; @@ -52,11 +61,6 @@ return false; } for (final key in keys) { - if (!other.containsKey(key)) { - return false; - } - } - for (final key in keys) { if (other[key] != this[key]) { return false; } @@ -100,8 +104,10 @@ _mergeFromCodedBufferReader(mapEntryMeta, entryFieldSet, input, registry!); input.checkLastTagWas(0); input._currentLimit = oldLimit; - var key = entryFieldSet._$get<K>(0, null); - var value = entryFieldSet._$get<V>(1, null); + var key = + entryFieldSet._values[0] ?? mapEntryMeta.byIndex[0].makeDefault!(); + var value = + entryFieldSet._values[1] ?? mapEntryMeta.byIndex[1].makeDefault!(); _wrappedMap[key] = value; } @@ -113,7 +119,7 @@ PbMap freeze() { _isReadonly = true; - if (_isGroupOrMessage(valueFieldType!)) { + if (_isGroupOrMessage(valueFieldType)) { for (var subMessage in values as Iterable<GeneratedMessage>) { subMessage.freeze(); }
diff --git a/protobuf/lib/src/protobuf/proto3_json.dart b/protobuf/lib/src/protobuf/proto3_json.dart index 6d35db9..4b69b9c 100644 --- a/protobuf/lib/src/protobuf/proto3_json.dart +++ b/protobuf/lib/src/protobuf/proto3_json.dart
@@ -61,13 +61,11 @@ case PbFieldType._FLOAT_BIT: case PbFieldType._DOUBLE_BIT: double value = fieldValue; - if (value.isNaN) return 'NaN'; + if (value.isNaN) { + return nan; + } if (value.isInfinite) { - if (value.isNegative) { - return '-Infinity'; - } else { - return 'Infinity'; - } + return value.isNegative ? negativeInfinity : infinity; } return value; case PbFieldType._UINT64_BIT: @@ -96,7 +94,7 @@ if (fieldInfo.isMapField) { jsonValue = (value as PbMap).map((key, entryValue) { var mapEntryInfo = fieldInfo as MapFieldInfo; - return MapEntry(convertToMapKey(key, mapEntryInfo.keyFieldType!), + return MapEntry(convertToMapKey(key, mapEntryInfo.keyFieldType), valueToProto3Json(entryValue, mapEntryInfo.valueFieldType)); }); } else if (fieldInfo.isRepeated) { @@ -223,6 +221,7 @@ throw context.parseException( 'Expected enum as a string or integer', value); case PbFieldType._UINT32_BIT: + case PbFieldType._FIXED32_BIT: int result; if (value is int) { result = value; @@ -235,7 +234,6 @@ return check32BitUnsigned(result); case PbFieldType._INT32_BIT: case PbFieldType._SINT32_BIT: - case PbFieldType._FIXED32_BIT: case PbFieldType._SFIXED32_BIT: int result; if (value is int) { @@ -366,7 +364,7 @@ throw context.parseException('Expected a String key', subKey); } context.addMapIndex(subKey); - fieldValues[decodeMapKey(subKey, mapFieldInfo.keyFieldType!)] = + fieldValues[decodeMapKey(subKey, mapFieldInfo.keyFieldType)] = convertProto3JsonValue( subValue, mapFieldInfo.valueFieldInfo); context.popIndex();
diff --git a/protobuf/lib/src/protobuf/protobuf_enum.dart b/protobuf/lib/src/protobuf/protobuf_enum.dart index 32253db..2fb989c 100644 --- a/protobuf/lib/src/protobuf/protobuf_enum.dart +++ b/protobuf/lib/src/protobuf/protobuf_enum.dart
@@ -54,7 +54,7 @@ @override int get hashCode => value; - /// Returns this enum's [name]. + /// Returns this enum's [name] or the [value] if names are not represented. @override - String toString() => name; + String toString() => name == '' ? value.toString() : name; }
diff --git a/protobuf/lib/src/protobuf/unknown_field_set.dart b/protobuf/lib/src/protobuf/unknown_field_set.dart index a0baca6..8c1159c 100644 --- a/protobuf/lib/src/protobuf/unknown_field_set.dart +++ b/protobuf/lib/src/protobuf/unknown_field_set.dart
@@ -28,6 +28,11 @@ _fields.clear(); } + void clearField(int tagNumber) { + _ensureWritable('clearField'); + _fields.remove(tagNumber); + } + UnknownFieldSetField? getField(int tagNumber) => _fields[tagNumber]; bool hasField(int tagNumber) => _fields.containsKey(tagNumber); @@ -267,12 +272,13 @@ return hash; } - List get values => [] - ..addAll(lengthDelimited) - ..addAll(varints) - ..addAll(fixed32s) - ..addAll(fixed64s) - ..addAll(groups); + List get values => [ + ...lengthDelimited, + ...varints, + ...fixed32s, + ...fixed64s, + ...groups, + ]; void writeTo(int fieldNumber, CodedBufferWriter output) { void write(type, value) {
diff --git a/protobuf/mono_pkg.yaml b/protobuf/mono_pkg.yaml index 5f8f170..1136bf1 100644 --- a/protobuf/mono_pkg.yaml +++ b/protobuf/mono_pkg.yaml
@@ -5,12 +5,12 @@ - group: - format - analyze: --fatal-infos - dart: [dev] + sdk: [dev] - group: - analyze: lib - analyze: test - dart: [2.12.0] + sdk: [2.12.0] - run_tests: - group: [test] - dart: [2.12.0, dev] + sdk: [2.12.0, dev] os: [linux, osx, windows]
diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml index 0bec734..259c8c6 100644 --- a/protobuf/pubspec.yaml +++ b/protobuf/pubspec.yaml
@@ -1,19 +1,21 @@ name: protobuf -version: 2.0.1-dev +version: 2.0.1 description: >- Runtime library for protocol buffers support. Use https://pub.dev/packages/protoc_plugin to generate dart code for your '.proto' files. -homepage: https://github.com/google/protobuf.dart +repository: https://github.com/google/protobuf.dart/tree/master/protobuf environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: fixnum: ^1.0.0 collection: ^1.15.0 + meta: ^1.7.0 dev_dependencies: test: ^1.16.0 benchmark_harness: ^2.0.0 js: ^0.6.3 lints: ^1.0.0 + matcher: ^0.12.11
diff --git a/protobuf/test/event_test.dart b/protobuf/test/event_test.dart index 77c4886..9d3f1d1 100644 --- a/protobuf/test/event_test.dart +++ b/protobuf/test/event_test.dart
@@ -5,8 +5,6 @@ /// Tests event delivery using PbEventMixin. library event_test; -import 'package:protobuf/protobuf.dart' - show GeneratedMessage, Extension, ExtensionRegistry, PbFieldType; import 'package:protobuf/protobuf.dart'; import 'package:protobuf/src/protobuf/mixins/event_mixin.dart' show PbEventMixin, PbFieldChange;
diff --git a/protobuf/test/json_test.dart b/protobuf/test/json_test.dart index 6291ad8..bf72b2b 100644 --- a/protobuf/test/json_test.dart +++ b/protobuf/test/json_test.dart
@@ -105,7 +105,7 @@ expect(decoded.int64, value); }); - test('tesFrozentInt64JsonEncoding', () { + test('testFrozentInt64JsonEncoding', () { final value = Int64.parseInt('1234567890123456789'); final frozen = T() ..int64 = value
diff --git a/protoc_plugin/Makefile b/protoc_plugin/Makefile index 02718d8..3a7ada9 100644 --- a/protoc_plugin/Makefile +++ b/protoc_plugin/Makefile
@@ -21,10 +21,12 @@ google/protobuf/timestamp \ google/protobuf/type \ google/protobuf/unittest_import \ + google/protobuf/unittest_nested_any \ google/protobuf/unittest_optimize_for \ google/protobuf/unittest_well_known_types \ google/protobuf/unittest \ google/protobuf/wrappers \ + bytes \ custom_option \ dart_name \ default_value_escape \ @@ -54,7 +56,9 @@ package1 \ package2 \ package3 \ + proto2_repeated \ proto3_optional \ + proto3_repeated \ service \ service2 \ service3 \ @@ -96,7 +100,7 @@ protos: $(PLUGIN_PATH) $(TEST_PROTO_LIBS) run-tests: protos - pub run test + dart run test clean: rm -rf benchmark/lib/generated
diff --git a/protoc_plugin/README.md b/protoc_plugin/README.md index 6c06b0f..20506d3 100644 --- a/protoc_plugin/README.md +++ b/protoc_plugin/README.md
@@ -2,64 +2,96 @@ [![pub package](https://img.shields.io/pub/v/protoc_plugin.svg)](https://pub.dev/packages/protoc_plugin) -This repository provides a plugin for the [protoc -compiler](https://developers.google.com/protocol-buffers/docs/cpptutorial#compiling-your-protocol-buffers). -It generates Dart files for working with data in protocol buffers format. +This repository provides a plugin for the [protoc compiler][1]. It generates +Dart files for working with data in protocol buffers format. -Requirements ------------- +[1]: https://developers.google.com/protocol-buffers/docs/cpptutorial#compiling-your-protocol-buffers -To compile a .proto file, you must use the 'protoc' command which is [installed -separately](https://developers.google.com/protocol-buffers/docs/downloads). -Protobuf 3.0.0 or above is required. +## Requirements -The generated files are pure Dart code that run in either in the Dart VM or in a -browser (using dart2js). They depend the [protobuf Dart -package](https://pub.dev/packages/protobuf). A Dart project that -includes generated files should add "protobuf" to its pubspec.yaml file. +To compile a .proto file, you must use the `protoc` command which is [installed +separately][1]. protoc 3.0.0 or above is required. +The generated files are pure Dart code that run either in the Dart VM or in a +browser (using [dart2js][2]). They depend on the [protobuf Dart package][3]. A +Dart project that includes generated files should add `protobuf` as a +dependency in the `pubspec.yaml` file. -How to build and use --------------------- +[1]: https://developers.google.com/protocol-buffers/docs/downloads +[2]: https://dart.dev/tools/dart2js +[3]: https://pub.dev/packages/protobuf -*Note:* currently the workflow is POSIX-oriented. +## How to build -To build standalone `protoc` plugin: -- run `pub install` to install all dependencies -- Now you can use the plugin either by adding the `bin` directory to your `PATH`, - or passing it directly with `protoc`'s `--plugin` option. +Make sure you have `dart` executable in your `PATH`. See the [Dart installation +instructions][1] for details. -Please, remember that the plugin is pure Dart script and requires the presence -of `dart` executable in your `PATH`. +If you encounter any issues while following the instructions below, please make +sure you have the latest version of Dart installed. -When both the `dart` executable and `bin/protoc-gen-dart` are in the -`PATH` the protocol buffer compiler can be invoked to generate like this: +[1]: https://dart.dev/get-dart + +**The recommended way** is to activate the latest published version of the +plugin: + + $ dart pub global activate protoc_plugin + +Make sure you have `~/.pub-cache/bin` in your `PATH`. + +This method installs a Dart script and requires presence of `dart` executable +in your `PATH`. + +**To build from the source:** + +- Run `dart pub get` in `protoc_plugin` directory +- Add `protoc_plugin/bin` to your `PATH`, or pass the path to + `protoc_plugin/bin/protoc-gen-dart` to `protoc`'s `--plugin` option. + +The `protoc-gen-dart` executable is a Dart script and requires presence of +`dart` executable in your `PATH`. + +**To build a standalone executable from the source:** + +- Run `dart pub get` in `protoc_plugin` +- Build standalone executable with `dart compile exe bin/protoc_plugin.dart` in + `protoc_plugin` + +The generated executable does not require a `dart` executable to run. You +should copy the generated executable `protoc_plugin/bin/protoc_plugin.exe` to +your `PATH` with name `protoc-gen-dart`, or pass the path to it to `protoc`'s +`--plugin` option when invoking `protoc`. + +## How to use + +Once you have `protoc-gen-dart` in the `PATH` the protocol buffer compiler can +be invoked like this to generate Dart for the proto file `test.proto`: $ protoc --dart_out=. test.proto -### Optionally using `pub global` +If you don't want to add `protoc-gen-dart` to `PATH`, you can specify the path +to it like this: - $ pub global activate protoc_plugin - -And then add `.pub-cache/bin` in your home dir to your `PATH` if you haven't already. - -This will activate the latest published version of the plugin. If you wish to use a -local working copy, use - - $ pub global activate -s path <path/to/your/dart-protoc-plugin> - + $ protoc --dart_out=. test.proto --plugin=<path to plugin executable> ### Options to control the generated Dart code The protocol buffer compiler accepts options for each plugin. For the Dart plugin, these options are passed together with the `--dart_out` -option. The individial options are separated using comma, and the +option. The individual options are separated using comma, and the final output directive is separated from the options using colon. Pass options `<option 1>` and `<option 2>` like this: --dart_out="<option 1>,<option 2>:." + +### Generating grpc Headers - ### Generating Code Info +To generate code for [grpc], you will need to pass in the `grpc` option: + + --dart_out="grpc:." + +[grpc]: https://pub.dev/packages/grpc + +### Generating Code Info The plugin includes the `generate_kythe_info` option, which, if passed at run time, will make the plugin generate metadata files alongside the `.dart` files @@ -68,61 +100,69 @@ --dart_out="generate_kythe_info,<other options>:." -Using protocol buffer libraries to build new libraries ------------------------------------------------------- +## Using protocol buffer libraries to build new libraries The protocol buffer compiler produces several files for each `.proto` file it compiles. In some cases this is not exactly what is needed, e.g one would like to create new libraries which exposes the objects in these -libraries or create new librares combining object definitions from +libraries or create new libraries combining object definitions from several `.proto` libraries into one. -The best way to aproach this is to create the new libraries needed and +The best way to approach this is to create the new libraries needed and re-export the relevant protocol buffer classes. Say we have the file `m1.proto` with the following content - message M1 { - optional string a; - } +```proto +syntax = "proto3"; + +message M1 { + string a = 1; +} +``` and `m2.proto` containing - message M2 { - optional string b; - } +```proto +syntax = "proto3"; + +message M2 { + string b = 1; +} +``` Compiling these to Dart will produce two libraries in `m1.pb.dart` and -`m2.pb.dart`. The following code shows a library M which combines +`m2.pb.dart`. The following code shows a library `M` which combines these two protocol buffer libraries, exposes the classes `M1` and `M2` and -adds som additional methods. +adds some additional methods. - library M; +```dart +library M; - import "m1.pb.dart"; - import "m2.pb.dart"; +import "m1.pb.dart"; +import "m2.pb.dart"; - export "m1.pb.dart" show M1; - export "m2.pb.dart" show M2; +export "m1.pb.dart" show M1; +export "m2.pb.dart" show M2; - M1 createM1() => new M1(); - M2 createM2() => new M2(); +M1 createM1() => new M1(); +M2 createM2() => new M2(); +``` -Hacking -------- +## Hacking Here are some ways to get protoc: * Linux: `apt-get install protobuf-compiler` -* Mac [homebrew](http://brew.sh/): `brew install protobuf` +* Mac [homebrew](https://brew.sh/): `brew install protobuf` If the version installed this way doesn't work, an alternative is to [compile protoc from source](https://developers.google.com/protocol-buffers/docs/downloads). -Remember to run the tests. That is as easy as `make run-tests`. +Remember to run the tests. That is as easy as `dart pub get` and then `make +run-tests`. -Useful references ------------------ +## Useful references * [Main Dart site](https://dart.dev) * [Main protobuf site](https://github.com/protocolbuffers/protobuf)
diff --git a/protoc_plugin/analysis_options.yaml b/protoc_plugin/analysis_options.yaml index dc7ec89..5cb030e 100644 --- a/protoc_plugin/analysis_options.yaml +++ b/protoc_plugin/analysis_options.yaml
@@ -6,9 +6,10 @@ linter: rules: - camel_case_types: true - control_flow_in_finally: true - directives_ordering: true - prefer_relative_imports: true - prefer_single_quotes: true - throw_in_finally: true + - camel_case_types + - comment_references + - control_flow_in_finally + - directives_ordering + - prefer_relative_imports + - prefer_single_quotes + - throw_in_finally
diff --git a/protoc_plugin/bin/protoc_plugin.dart b/protoc_plugin/bin/protoc_plugin.dart index 8e45871..54da34c 100755 --- a/protoc_plugin/bin/protoc_plugin.dart +++ b/protoc_plugin/bin/protoc_plugin.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'dart:io'; import 'package:protoc_plugin/protoc.dart';
diff --git a/protoc_plugin/bin/protoc_plugin_bazel.dart b/protoc_plugin/bin/protoc_plugin_bazel.dart index 843239e..ce74938 100755 --- a/protoc_plugin/bin/protoc_plugin_bazel.dart +++ b/protoc_plugin/bin/protoc_plugin_bazel.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'dart:io'; import 'package:protoc_plugin/bazel.dart';
diff --git a/protoc_plugin/lib/names.dart b/protoc_plugin/lib/names.dart index 1694f0b..f96d861 100644 --- a/protoc_plugin/lib/names.dart +++ b/protoc_plugin/lib/names.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'dart:math' as math; import 'package:protobuf/meta.dart'; @@ -24,11 +22,15 @@ /// The index of this field in MessageGenerator.fieldList. /// The same index will be stored in FieldInfo.index. - final int index; + /// + /// `null` for extensions. + final int? index; /// The position of this field as it appeared in the original DescriptorProto. /// Used to construct metadata. - final int sourcePosition; + /// + /// `null` for extensions. + final int? sourcePosition; /// Identifier for generated getters/setters. final String fieldName; @@ -36,17 +38,17 @@ /// Identifier for the generated hasX() method, without braces. /// /// `null` for repeated fields. - final String hasMethodName; + final String? hasMethodName; /// Identifier for the generated clearX() method, without braces. /// /// `null` for repeated fields. - final String clearMethodName; + final String? clearMethodName; // Identifier for the generated ensureX() method, without braces. // - //'null' for scalar, repeated, and map fields. - final String ensureMethodName; + // 'null' for scalar, repeated, and map fields. + final String? ensureMethodName; FieldNames(this.descriptor, this.index, this.sourcePosition, this.fieldName, {this.hasMethodName, this.clearMethodName, this.ensureMethodName}); @@ -152,13 +154,13 @@ /// /// The chosen name is added to [usedNames]. /// -/// If [variants] is given, all the variants of a name must be available before -/// that name is chosen, and all the chosen variants will be added to +/// If [generateVariants] is given, all the variants of a name must be available +/// before that name is chosen, and all the chosen variants will be added to /// [usedNames]. /// The returned name is that, which will generate the accepted variants. String disambiguateName( String name, Set<String> usedNames, Iterable<String> suffixes, - {List<String> Function(String candidate) generateVariants}) { + {List<String> Function(String candidate)? generateVariants}) { generateVariants ??= (String name) => <String>[name]; bool allVariantsAvailable(List<String> variants) { @@ -259,21 +261,19 @@ indexes[field.name] = index; } - var existingNames = <String>{} - ..addAll(reservedMemberNames) - ..addAll(reserved); + var existingNames = <String>{...reservedMemberNames, ...reserved}; - var fieldNames = List<FieldNames>.filled(indexes.length, null); + var fieldNames = List<FieldNames?>.filled(indexes.length, null); void takeFieldNames(FieldNames chosen) { - fieldNames[chosen.index] = chosen; + fieldNames[chosen.index!] = chosen; existingNames.add(chosen.fieldName); if (chosen.hasMethodName != null) { - existingNames.add(chosen.hasMethodName); + existingNames.add(chosen.hasMethodName!); } if (chosen.clearMethodName != null) { - existingNames.add(chosen.clearMethodName); + existingNames.add(chosen.clearMethodName!); } } @@ -281,17 +281,17 @@ // They have higher priority than automatically chosen names. // Explicitly setting a name that's already taken is a build error. for (var field in sorted) { - if (_nameOption(field).isNotEmpty) { + if (_nameOption(field)!.isNotEmpty) { takeFieldNames(_memberNamesFromOption(descriptor, field, - indexes[field.name], sourcePositions[field.name], existingNames)); + indexes[field.name]!, sourcePositions[field.name]!, existingNames)); } } // Then do other fields. // They are automatically renamed until we find something unused. for (var field in sorted) { - if (_nameOption(field).isEmpty) { - var index = indexes[field.name]; + if (_nameOption(field)!.isEmpty) { + var index = indexes[field.name]!; var sourcePosition = sourcePositions[field.name]; takeFieldNames( _unusedMemberNames(field, index, sourcePosition, existingNames)); @@ -302,16 +302,9 @@ void takeOneofNames(OneofNames chosen) { oneofNames.add(chosen); - - if (chosen.whichOneofMethodName != null) { - existingNames.add(chosen.whichOneofMethodName); - } - if (chosen.clearMethodName != null) { - existingNames.add(chosen.clearMethodName); - } - if (chosen.byTagMapName != null) { - existingNames.add(chosen.byTagMapName); - } + existingNames.add(chosen.whichOneofMethodName); + existingNames.add(chosen.clearMethodName); + existingNames.add(chosen.byTagMapName); } List<String> oneofNameVariants(String name) { @@ -336,7 +329,7 @@ _defaultWhichMethodName(oneofName), oneofEnumName, enumMapName)); } - return MemberNames(fieldNames, oneofNames); + return MemberNames(fieldNames.cast<FieldNames>(), oneofNames); } /// Chooses the member names for a field that has the 'dart_name' option. @@ -359,7 +352,7 @@ } } - var name = _nameOption(field); + var name = _nameOption(field)!; if (name.isEmpty) { throw ArgumentError("field doesn't have dart_name option"); } @@ -379,7 +372,7 @@ var clearMethod = 'clear${_capitalize(name)}'; checkAvailable(clearMethod); - String ensureMethod; + String? ensureMethod; if (_isGroupOrMessage(field)) { ensureMethod = 'ensure${_capitalize(name)}'; @@ -399,8 +392,8 @@ } } -FieldNames _unusedMemberNames(FieldDescriptorProto field, int index, - int sourcePosition, Set<String> existingNames) { +FieldNames _unusedMemberNames(FieldDescriptorProto field, int? index, + int? sourcePosition, Set<String> existingNames) { if (_isRepeated(field)) { return FieldNames( field, @@ -427,7 +420,8 @@ _memberNamesSuffix(field.number), generateVariants: generateNameVariants); - return FieldNames(field, index, sourcePosition, _defaultFieldName(name), + return FieldNames(field, index, sourcePosition, + avoidInitialUnderscore(_defaultFieldName(name)), hasMethodName: _defaultHasMethodName(name), clearMethodName: _defaultClearMethodName(name), ensureMethodName: @@ -454,7 +448,7 @@ /// The suffix to use for this field in Dart method names. /// (It should be camelcase and begin with an uppercase letter.) String _fieldMethodSuffix(FieldDescriptorProto field) { - var name = _nameOption(field); + var name = _nameOption(field)!; if (name.isNotEmpty) return _capitalize(name); if (field.type != FieldDescriptorProto_Type.TYPE_GROUP) { @@ -483,8 +477,8 @@ field.type == FieldDescriptorProto_Type.TYPE_MESSAGE || field.type == FieldDescriptorProto_Type.TYPE_GROUP; -String _nameOption(FieldDescriptorProto field) => - field.options.getExtension(Dart_options.dartName) as String; +String? _nameOption(FieldDescriptorProto field) => + field.options.getExtension(Dart_options.dartName) as String?; bool _isDartFieldName(String name) => name.startsWith(_dartFieldNameExpr);
diff --git a/protoc_plugin/lib/protoc.dart b/protoc_plugin/lib/protoc.dart index cba09b7..f6001b3 100644 --- a/protoc_plugin/lib/protoc.dart +++ b/protoc_plugin/lib/protoc.dart
@@ -1,5 +1,3 @@ -// @dart=2.11 - import 'dart:convert'; import 'package:dart_style/dart_style.dart';
diff --git a/protoc_plugin/lib/src/base_type.dart b/protoc_plugin/lib/src/base_type.dart index 0003f1b..4721566 100644 --- a/protoc_plugin/lib/src/base_type.dart +++ b/protoc_plugin/lib/src/base_type.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; /// Represents the base type of a particular field in a proto definition. @@ -19,11 +17,11 @@ final String typeConstantSuffix; // Method name of the setter method for this type. - final String setter; + final String? setter; // The generator corresponding to this type. // (Null for primitive types.) - final ProtobufContainer generator; + final ProtobufContainer? generator; const BaseType._raw(this.descriptor, this.typeConstantSuffix, this.unprefixed, this.setter, this.generator); @@ -37,18 +35,19 @@ /// The package where this type is declared. /// (Always the empty string for primitive types.) - String get package => generator == null ? '' : generator.package; + String get package => generator == null ? '' : generator!.package; /// The Dart expression to use for this type when in a different file. String get prefixed => generator == null ? unprefixed - : generator.fileImportPrefix + '.' + unprefixed; + : generator!.fileImportPrefix + '.' + unprefixed; /// Returns the name to use in generated code for this Dart type. /// /// Doesn't include the List type for repeated fields. - /// [protoFileUri] represents the current proto file where we are generating - /// code. The Dart class might be imported from a different proto file. + /// [FileGenerator.protoFileUri] represents the current proto file where we + /// are generating code. + /// The Dart class might be imported from a different proto file. String getDartType(FileGenerator fileGen) => (fileGen.protoFileUri == generator?.fileGen?.protoFileUri) ? unprefixed @@ -134,6 +133,6 @@ } return BaseType._raw( - field.type, constSuffix, generator.classname, null, generator); + field.type, constSuffix, generator.classname!, null, generator); } }
diff --git a/protoc_plugin/lib/src/client_generator.dart b/protoc_plugin/lib/src/client_generator.dart index 500c0c9..8fa0374 100644 --- a/protoc_plugin/lib/src/client_generator.dart +++ b/protoc_plugin/lib/src/client_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; class ClientApiGenerator {
diff --git a/protoc_plugin/lib/src/code_generator.dart b/protoc_plugin/lib/src/code_generator.dart index 38e7596..1d93559 100644 --- a/protoc_plugin/lib/src/code_generator.dart +++ b/protoc_plugin/lib/src/code_generator.dart
@@ -2,10 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'dart:io'; -import 'dart:typed_data'; import 'package:fixnum/fixnum.dart'; import 'package:protobuf/protobuf.dart'; @@ -24,7 +21,7 @@ static int _idx = 0; String get package; - String get classname; + String? get classname; String get fullName; /// The field path contains the field IDs and indices (for repeated fields) @@ -33,7 +30,7 @@ /// the message in question. /// For more information see /// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto#L728 - List<int> get fieldPath; + List<int>? get fieldPath; /// The fully qualified name with a leading '.'. /// @@ -43,12 +40,12 @@ String get fileImportPrefix => _getFileImportPrefix(); String get binaryDescriptorName => - '${lowerCaseFirstLetter(classname)}Descriptor'; + '${lowerCaseFirstLetter(classname!)}Descriptor'; String _getFileImportPrefix() { - var path = fileGen.protoFileUri.toString(); + var path = fileGen!.protoFileUri.toString(); if (_importPrefixes.containsKey(path)) { - return _importPrefixes[path]; + return _importPrefixes[path]!; } final alias = '\$$_idx'; _importPrefixes[path] = alias; @@ -59,21 +56,21 @@ /// The generator of the .pb.dart file defining this entity. /// /// (Represents the .pb.dart file that we need to import in order to use it.) - FileGenerator get fileGen; + FileGenerator? get fileGen; // The generator containing this entity. - ProtobufContainer get parent; + ProtobufContainer? get parent; /// The top-level parent of this entity. If this entity is a top-level entity, /// returns this. - ProtobufContainer get toplevelParent { + ProtobufContainer? get toplevelParent { if (parent == null) { return null; } if (parent is FileGenerator) { return this; } - return parent.toplevelParent; + return parent?.toplevelParent; } } @@ -85,14 +82,12 @@ /// Runs the code generator. The optional [optionParsers] can be used to /// change how command line options are parsed (see [parseGenerationOptions] - /// for details), and [outputConfiguration] can be used to override where + /// for details), and [config] can be used to override where /// generated files are created and how imports between generated files are /// constructed (see [OutputConfiguration] for details). void generate( - {Map<String, SingleOptionParser> optionParsers, - OutputConfiguration config}) { - config ??= DefaultOutputConfiguration(); - + {Map<String, SingleOptionParser>? optionParsers, + OutputConfiguration config = const DefaultOutputConfiguration()}) { var extensions = ExtensionRegistry(); Dart_options.registerAllExtensions(extensions); @@ -137,14 +132,19 @@ @override String get package => ''; + @override - String get classname => null; + String? get classname => null; + @override String get fullName => ''; + @override - FileGenerator get fileGen => null; + FileGenerator? get fileGen => null; + @override - ProtobufContainer get parent => null; + ProtobufContainer? get parent => null; + @override - List<int> get fieldPath => []; + List<int>? get fieldPath => []; }
diff --git a/protoc_plugin/lib/src/enum_generator.dart b/protoc_plugin/lib/src/enum_generator.dart index 2b3da04..b1159ce 100644 --- a/protoc_plugin/lib/src/enum_generator.dart +++ b/protoc_plugin/lib/src/enum_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; class EnumAlias { @@ -14,11 +12,14 @@ class EnumGenerator extends ProtobufContainer { @override - final ProtobufContainer parent; + final ProtobufContainer? parent; + @override - final String classname; + final String? classname; + @override final String fullName; + final EnumDescriptorProto _descriptor; final List<EnumValueDescriptorProto> _canonicalValues = <EnumValueDescriptorProto>[]; @@ -28,20 +29,19 @@ /// Maps the name of an enum value to the Dart name we will use for it. final Map<String, String> dartNames = <String, String>{}; final List<int> _originalAliasIndices = <int>[]; - List<int> _fieldPath; + List<int>? _fieldPath; final List<int> _fieldPathSegment; /// See [[ProtobufContainer] @override - List<int> get fieldPath => - _fieldPath ??= List.from(parent.fieldPath)..addAll(_fieldPathSegment); + List<int>? get fieldPath => + _fieldPath ??= List.from(parent!.fieldPath!)..addAll(_fieldPathSegment); EnumGenerator._(EnumDescriptorProto descriptor, this.parent, Set<String> usedClassNames, int repeatedFieldIndex, int fieldIdTag) - : assert(parent != null), - _fieldPathSegment = [fieldIdTag, repeatedFieldIndex], + : _fieldPathSegment = [fieldIdTag, repeatedFieldIndex], classname = messageOrEnumClassName(descriptor.name, usedClassNames, - parent: parent?.classname ?? ''), + parent: parent!.classname ?? ''), fullName = parent.fullName == '' ? descriptor.name : '${parent.fullName}.${descriptor.name}', @@ -80,9 +80,10 @@ _nestedFieldTag); @override - String get package => parent.package; + String get package => parent!.package; + @override - FileGenerator get fileGen => parent.fileGen; + FileGenerator? get fileGen => parent!.fileGen; /// Make this enum available as a field type. void register(GenerationContext ctx) { @@ -93,7 +94,7 @@ /// [usage] represents the .pb.dart file where the expression will be used. String getJsonConstant(FileGenerator usage) { var name = '$classname\$json'; - if (usage.protoFileUri == fileGen.protoFileUri) { + if (usage.protoFileUri == fileGen!.protoFileUri) { return name; } return '$fileImportPrefix.$name'; @@ -106,13 +107,15 @@ 'class $classname extends $protobufImportPrefix.ProtobufEnum {', '}\n', [ NamedLocation( - name: classname, fieldPathSegment: fieldPath, start: 'class '.length) + name: classname!, + fieldPathSegment: fieldPath!, + start: 'class '.length) ], () { // ----------------------------------------------------------------- // Define enum types. for (var i = 0; i < _canonicalValues.length; i++) { var val = _canonicalValues[i]; - final name = dartNames[val.name]; + final name = dartNames[val.name]!; final conditionalValName = configurationDependent( 'protobuf.omit_enum_names', quoted(val.name)); out.printlnAnnotated( @@ -121,7 +124,7 @@ [ NamedLocation( name: name, - fieldPathSegment: List.from(fieldPath) + fieldPathSegment: List.from(fieldPath!) ..addAll([_enumValueTag, _originalCanonicalIndices[i]]), start: 'static const $classname '.length) ]); @@ -130,14 +133,14 @@ out.println(); for (var i = 0; i < _aliases.length; i++) { var alias = _aliases[i]; - final name = dartNames[alias.value.name]; + final name = dartNames[alias.value.name]!; out.printlnAnnotated( 'static const $classname $name =' ' ${dartNames[alias.canonicalValue.name]};', [ NamedLocation( name: name, - fieldPathSegment: List.from(fieldPath) + fieldPathSegment: List.from(fieldPath!) ..addAll([_enumValueTag, _originalAliasIndices[i]]), start: 'static const $classname '.length) ]); @@ -169,11 +172,11 @@ /// Writes a Dart constant containing the JSON for the EnumProtoDescriptor. void generateConstants(IndentingWriter out) { - var name = getJsonConstant(fileGen); + var name = getJsonConstant(fileGen!); var json = _descriptor.writeToJsonMap(); out.println('@$coreImportPrefix.Deprecated' - '(\'Use ${toplevelParent.binaryDescriptorName} instead\')'); + '(\'Use ${toplevelParent!.binaryDescriptorName} instead\')'); out.print('const $name = '); writeJsonConst(out, json); out.println(';');
diff --git a/protoc_plugin/lib/src/extension_generator.dart b/protoc_plugin/lib/src/extension_generator.dart index 9e8f088..1351038 100644 --- a/protoc_plugin/lib/src/extension_generator.dart +++ b/protoc_plugin/lib/src/extension_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; class ExtensionGenerator { @@ -11,15 +9,15 @@ final ProtobufContainer _parent; // populated by resolve() - ProtobufField _field; + late ProtobufField _field; + bool _resolved = false; final String _extensionName; String _extendedFullName = ''; - List<int> _fieldPath; final List<int> _fieldPathSegment; - /// See [[ProtobufContainer] - List<int> get fieldPath => - _fieldPath ??= List.from(_parent.fieldPath)..addAll(_fieldPathSegment); + /// See [ProtobufContainer] + late final List<int> fieldPath = List.from(_parent.fieldPath!) + ..addAll(_fieldPathSegment); ExtensionGenerator._(this._descriptor, this._parent, Set<String> usedNames, int repeatedFieldIndex, int fieldIdTag) @@ -40,6 +38,7 @@ void resolve(GenerationContext ctx) { _field = ProtobufField.extension(_descriptor, _parent, ctx); + _resolved = true; var extendedType = ctx.getFieldType(_descriptor.extendee); // TODO(skybrian) When would this be null? @@ -51,16 +50,16 @@ String get package => _parent.package; /// The generator of the .pb.dart file where this extension will be defined. - FileGenerator get fileGen => _parent.fileGen; + FileGenerator? get fileGen => _parent.fileGen; String get name { - if (_field == null) throw StateError('resolve not called'); + if (!_resolved) throw StateError('resolve not called'); var name = _extensionName; return _parent is MessageGenerator ? '${_parent.classname}.$name' : name; } bool get needsFixnumImport { - if (_field == null) throw StateError('resolve not called'); + if (!_resolved) throw StateError('resolve not called'); return _field.needsFixnumImport; } @@ -70,37 +69,35 @@ /// add its generator. void addImportsTo( Set<FileGenerator> imports, Set<FileGenerator> enumImports) { - if (_field == null) throw StateError('resolve not called'); + if (!_resolved) throw StateError('resolve not called'); var typeGen = _field.baseType.generator; if (typeGen != null) { // The type of this extension is defined in a different file, // so we need to import it. if (typeGen is EnumGenerator) { // Enums are always in a different file. - enumImports.add(typeGen.fileGen); + enumImports.add(typeGen.fileGen!); } else if (typeGen.fileGen != fileGen) { - imports.add(typeGen.fileGen); + imports.add(typeGen.fileGen!); } } } - /// Adds dependencies of [generateConstants] to [imports]. - /// /// For each .pb.dart file that the generated code needs to import, /// add its generator. void addConstantImportsTo(Set<FileGenerator> imports) { - if (_field == null) throw StateError('resolve not called'); + if (!_resolved) throw StateError('resolve not called'); // No dependencies - nothing to do. } void generate(IndentingWriter out) { - if (_field == null) throw StateError('resolve not called'); + if (!_resolved) throw StateError('resolve not called'); var name = _extensionName; final conditionalName = configurationDependent( 'protobuf.omit_field_names', quoted(_extensionName)); var type = _field.baseType; - var dartType = type.getDartType(fileGen); + var dartType = type.getDartType(fileGen!); final conditionalExtendedName = configurationDependent( 'protobuf.omit_message_names', quoted(_extendedFullName)); @@ -111,7 +108,7 @@ positionals.add('${_field.number}'); positionals.add(_field.typeConstant); - var named = <String, String>{}; + var named = <String, String?>{}; named['protoName'] = _field.quotedProtoName; if (_field.isRepeated) { invocation = '$protobufImportPrefix.Extension<$dartType>.repeated'; @@ -125,16 +122,15 @@ } } else { invocation = '$protobufImportPrefix.Extension<$dartType>'; - named['defaultOrMaker'] = _field.generateDefaultFunction(fileGen); + named['defaultOrMaker'] = _field.generateDefaultFunction(); if (type.isMessage || type.isGroup) { named['subBuilder'] = '$dartType.create'; } else if (type.isEnum) { - var dartEnum = type.getDartType(fileGen); + var dartEnum = type.getDartType(fileGen!); named['valueOf'] = '$dartEnum.valueOf'; named['enumValues'] = '$dartEnum.values'; } } - assert(invocation != null); var fieldDefinition = 'static final '; out.printAnnotated( '$fieldDefinition$name = '
diff --git a/protoc_plugin/lib/src/file_generator.dart b/protoc_plugin/lib/src/file_generator.dart index afd013c..b2600b6 100644 --- a/protoc_plugin/lib/src/file_generator.dart +++ b/protoc_plugin/lib/src/file_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; final _dartIdentifier = RegExp(r'^\w+$'); @@ -32,6 +30,11 @@ ': $value'; } +enum ProtoSyntax { + proto2, + proto3, +} + /// Generates the Dart output files for one .proto input file. /// /// Outputs include .pb.dart, pbenum.dart, and .pbjson.dart. @@ -91,16 +94,16 @@ throw mixinError('Cycle in parent chain: $cycle'); } parentChain.add(parentName); - currentMixin = dartMixins[parentName]; + currentMixin = dartMixins[parentName]!; } } // Turn DartMixins into PbMixins. final pbMixins = <String, PbMixin>{}; - PbMixin resolveMixin(String name) { + PbMixin? resolveMixin(String name) { if (pbMixins.containsKey(name)) return pbMixins[name]; if (dartMixins.containsKey(name)) { - var dartMixin = dartMixins[name]; + var dartMixin = dartMixins[name]!; var pbMixin = PbMixin(dartMixin.name, importFrom: dartMixin.importFrom, parent: resolveMixin(dartMixin.parent)); @@ -145,8 +148,13 @@ /// True if cross-references have been resolved. bool _linked = false; + final ProtoSyntax syntax; + FileGenerator(this.descriptor, this.options) - : protoFileUri = Uri.file(descriptor.name) { + : protoFileUri = Uri.file(descriptor.name), + syntax = descriptor.syntax == 'proto3' + ? ProtoSyntax.proto3 + : ProtoSyntax.proto2 { if (protoFileUri.isAbsolute) { // protoc should never generate an import with an absolute path. throw 'FAILURE: Import with absolute path is not supported'; @@ -154,7 +162,7 @@ var declaredMixins = _getDeclaredMixins(descriptor); var defaultMixinName = - descriptor.options?.getExtension(Dart_options.defaultMixin) as String ?? + descriptor.options.getExtension(Dart_options.defaultMixin) as String? ?? ''; var defaultMixin = declaredMixins[defaultMixinName] ?? findMixin(defaultMixinName); @@ -206,14 +214,19 @@ @override String get package => descriptor.package; + @override String get classname => ''; + @override String get fullName => descriptor.package; + @override FileGenerator get fileGen => this; + @override - ProtobufContainer get parent => null; + ProtobufContainer? get parent => null; + @override List<int> get fieldPath => []; @@ -638,6 +651,7 @@ 'prefer_final_fields', 'return_of_invalid_type', 'unnecessary_const', + 'unnecessary_import', 'unnecessary_this', 'unused_import', 'unused_shown_name',
diff --git a/protoc_plugin/lib/src/grpc_generator.dart b/protoc_plugin/lib/src/grpc_generator.dart index 73fe67e..dd936aa 100644 --- a/protoc_plugin/lib/src/grpc_generator.dart +++ b/protoc_plugin/lib/src/grpc_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; class GrpcServiceGenerator { @@ -24,13 +22,13 @@ final _undefinedDeps = <String, String>{}; /// Fully-qualified gRPC service name. - String _fullServiceName; + late final String _fullServiceName; /// Dart class name for client stub. - String _clientClassname; + late final String _clientClassname; /// Dart class name for server stub. - String _serviceClassname; + late final String _serviceClassname; /// List of gRPC methods. final _methods = <_GrpcMethod>[]; @@ -39,7 +37,7 @@ final name = _descriptor.name; final package = fileGen.package; - if (package != null && package.isNotEmpty) { + if (package.isNotEmpty) { _fullServiceName = '$package.$name'; } else { _fullServiceName = name; @@ -69,7 +67,7 @@ void _addDependency(GenerationContext ctx, String fqname, String location) { if (_deps.containsKey(fqname)) return; // Already added. - final mg = ctx.getFieldType(fqname) as MessageGenerator; + final mg = ctx.getFieldType(fqname) as MessageGenerator?; if (mg == null) { _undefinedDeps[fqname] = location; return;
diff --git a/protoc_plugin/lib/src/linker.dart b/protoc_plugin/lib/src/linker.dart index 740e719..ef99f9f 100644 --- a/protoc_plugin/lib/src/linker.dart +++ b/protoc_plugin/lib/src/linker.dart
@@ -2,14 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import '../protoc.dart' show FileGenerator; import 'code_generator.dart'; import 'options.dart'; /// Resolves all cross-references in a set of proto files. -void link(GenerationOptions options, Iterable<FileGenerator> files) { +void link(GenerationOptions? options, Iterable<FileGenerator> files) { var ctx = GenerationContext(options); // Register the targets of cross-references. @@ -41,7 +39,7 @@ } class GenerationContext { - final GenerationOptions options; + final GenerationOptions? options; /// The files available for import. final Map<String, FileGenerator> _files = <String, FileGenerator>{}; @@ -67,9 +65,9 @@ /// Returns info about a .pb.dart being imported, /// based on the filename given to us by protoc. - FileGenerator getImportedProtoFile(String name) => _files[name]; + FileGenerator? getImportedProtoFile(String name) => _files[name]; /// Returns info about the type of a message, group, or enum field, /// based on the fully qualified name given to us by protoc. - ProtobufContainer getFieldType(String name) => _typeRegistry[name]; + ProtobufContainer? getFieldType(String name) => _typeRegistry[name]; }
diff --git a/protoc_plugin/lib/src/message_generator.dart b/protoc_plugin/lib/src/message_generator.dart index acf3bfa..a2efc02 100644 --- a/protoc_plugin/lib/src/message_generator.dart +++ b/protoc_plugin/lib/src/message_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; /// Generates the Dart enum corresponding to a oneof declaration. @@ -15,7 +13,7 @@ IndentingWriter out, String classname, List<ProtobufField> fields) { out.addBlock('enum $classname {', '}\n', () { for (var field in fields) { - final name = oneofEnumMemberName(field.memberNames.fieldName); + final name = oneofEnumMemberName(field.memberNames!.fieldName); out.println('$name, '); } out.println('notSet'); @@ -51,10 +49,11 @@ String get messageName => fullName.substring(package.isEmpty ? 0 : package.length + 1); - PbMixin mixin; + PbMixin? mixin; @override - final ProtobufContainer parent; + final ProtobufContainer? parent; + final DescriptorProto _descriptor; final List<EnumGenerator> _enumGenerators = <EnumGenerator>[]; final List<MessageGenerator> _messageGenerators = <MessageGenerator>[]; @@ -64,18 +63,18 @@ /// by the index in the containing types's oneof_decl list. /// Only contains the 'real' oneofs. final List<List<ProtobufField>> _oneofFields; - List<OneofNames> _oneofNames; + late List<OneofNames> _oneofNames; - List<int> _fieldPath; final List<int> _fieldPathSegment; /// See [[ProtobufContainer] @override - List<int> get fieldPath => - _fieldPath ??= List.from(parent.fieldPath)..addAll(_fieldPathSegment); + late final List<int> fieldPath = List.from(parent!.fieldPath!) + ..addAll(_fieldPathSegment); // populated by resolve() - List<ProtobufField> _fieldList; + late List<ProtobufField> _fieldList; + bool _resolved = false; Set<String> _usedTopLevelNames; @@ -83,7 +82,7 @@ DescriptorProto descriptor, this.parent, Map<String, PbMixin> declaredMixins, - PbMixin defaultMixin, + PbMixin? defaultMixin, this._usedTopLevelNames, int repeatedFieldIndex, int fieldIdTag) @@ -92,7 +91,7 @@ classname = messageOrEnumClassName(descriptor.name, _usedTopLevelNames, parent: parent?.classname ?? ''), assert(parent != null), - fullName = parent.fullName == '' + fullName = parent!.fullName == '' ? descriptor.name : '${parent.fullName}.${descriptor.name}', _oneofFields = @@ -127,7 +126,7 @@ DescriptorProto descriptor, ProtobufContainer parent, Map<String, PbMixin> declaredMixins, - PbMixin defaultMixin, + PbMixin? defaultMixin, Set<String> usedNames, int repeatedFieldIndex) : this._(descriptor, parent, declaredMixins, defaultMixin, usedNames, @@ -137,22 +136,22 @@ DescriptorProto descriptor, ProtobufContainer parent, Map<String, PbMixin> declaredMixins, - PbMixin defaultMixin, + PbMixin? defaultMixin, Set<String> usedNames, int repeatedFieldIndex) : this._(descriptor, parent, declaredMixins, defaultMixin, usedNames, repeatedFieldIndex, _nestedMessageTag); @override - String get package => parent.package; + String get package => parent!.package; /// The generator of the .pb.dart file that will declare this type. @override - FileGenerator get fileGen => parent.fileGen; + FileGenerator get fileGen => parent!.fileGen!; /// Throws an exception if [resolve] hasn't been called yet. void checkResolved() { - if (_fieldList == null) { + if (!_resolved) { throw StateError('message not resolved: $fullName'); } } @@ -170,7 +169,7 @@ /// Adds all mixins used in this message and any submessages. void addMixinsTo(Set<PbMixin> output) { if (mixin != null) { - output.addAll(mixin.findMixinsToApply()); + output.addAll(mixin!.findMixinsToApply()); } for (var m in _messageGenerators) { m.addMixinsTo(output); @@ -190,7 +189,8 @@ // Creates fields and resolves extension targets. void resolve(GenerationContext ctx) { - if (_fieldList != null) throw StateError('message already resolved'); + if (_resolved) throw StateError('message already resolved'); + _resolved = true; var reserved = mixin?.findReservedNames() ?? const <String>[]; var members = messageMemberNames(_descriptor, classname, _usedTopLevelNames, @@ -216,7 +216,7 @@ } bool get needsFixnumImport { - if (_fieldList == null) throw StateError('message not resolved'); + checkResolved(); for (var field in _fieldList) { if (field.needsFixnumImport) return true; } @@ -235,13 +235,13 @@ /// add its generator. void addImportsTo( Set<FileGenerator> imports, Set<FileGenerator> enumImports) { - if (_fieldList == null) throw StateError('message not resolved'); + checkResolved(); for (var field in _fieldList) { var typeGen = field.baseType.generator; if (typeGen is EnumGenerator) { - enumImports.add(typeGen.fileGen); + enumImports.add(typeGen.fileGen!); } else if (typeGen != null) { - imports.add(typeGen.fileGen); + imports.add(typeGen.fileGen!); } } for (var m in _messageGenerators) { @@ -266,7 +266,7 @@ /// For each .pbjson.dart file that the generated code needs to import, /// add its generator. void addConstantImportsTo(Set<FileGenerator> imports) { - if (_fieldList == null) throw StateError('message not resolved'); + checkResolved(); for (var m in _messageGenerators) { m.addConstantImportsTo(imports); } @@ -293,7 +293,7 @@ var mixinClause = ''; if (mixin != null) { var mixinNames = - mixin.findMixinsToApply().map((m) => '$mixinImportPrefix.${m.name}'); + mixin!.findMixinsToApply().map((m) => '$mixinImportPrefix.${m.name}'); mixinClause = ' with ${mixinNames.join(", ")}'; } @@ -304,8 +304,8 @@ var packageClause = package == '' ? '' : ', package: $conditionalPackageName'; var proto3JsonClause = (mixin?.hasProto3JsonHelpers ?? false) - ? ', toProto3Json: $mixinImportPrefix.${mixin.name}.toProto3JsonHelper, ' - 'fromProto3Json: $mixinImportPrefix.${mixin.name}.fromProto3JsonHelper' + ? ', toProto3Json: $mixinImportPrefix.${mixin!.name}.toProto3JsonHelper, ' + 'fromProto3Json: $mixinImportPrefix.${mixin!.name}.fromProto3JsonHelper' : ''; out.addAnnotatedBlock( 'class $classname extends $protobufImportPrefix.GeneratedMessage$mixinClause {', @@ -319,7 +319,7 @@ '};', () { for (var field in _oneofFields[oneof.index]) { final oneofMemberName = - oneofEnumMemberName(field.memberNames.fieldName); + oneofEnumMemberName(field.memberNames!.fieldName); out.println( '${field.number} : ${oneof.oneofEnumName}.$oneofMemberName,'); } @@ -342,7 +342,7 @@ } for (var field in _fieldList) { - out.println(field.generateBuilderInfoCall(fileGen, package)); + out.println(field.generateBuilderInfoCall(package)); } if (_descriptor.extensionRange.isNotEmpty) { @@ -369,10 +369,10 @@ _emitDeprecatedIf(field.isDeprecated, out); if (field.isRepeated && !field.isMapField) { out.println( - ' ${field.baseType.getRepeatedDartTypeIterable(fileGen)}? ${field.memberNames.fieldName},'); + ' ${field.baseType.getRepeatedDartTypeIterable(fileGen)}? ${field.memberNames!.fieldName},'); } else { out.println( - ' ${field.getDartType(fileGen)}? ${field.memberNames.fieldName},'); + ' ${field.getDartType()}? ${field.memberNames!.fieldName},'); } } out.print('}'); @@ -381,17 +381,17 @@ out.println(') {'); out.println(' final _result = create();'); for (final field in _fieldList) { - out.println(' if (${field.memberNames.fieldName} != null) {'); + out.println(' if (${field.memberNames!.fieldName} != null) {'); if (field.isDeprecated) { out.println( ' // ignore: deprecated_member_use_from_same_package'); } if (field.isRepeated || field.isMapField) { out.println( - ' _result.${field.memberNames.fieldName}.addAll(${field.memberNames.fieldName});'); + ' _result.${field.memberNames!.fieldName}.addAll(${field.memberNames!.fieldName});'); } else { out.println( - ' _result.${field.memberNames.fieldName} = ${field.memberNames.fieldName};'); + ' _result.${field.memberNames!.fieldName} = ${field.memberNames!.fieldName};'); } out.println(' }'); } @@ -452,7 +452,7 @@ // already_seen is used to avoid checking the same type multiple times // (and also to protect against unbounded recursion). bool _hasRequiredFields(MessageGenerator type, Set alreadySeen) { - if (type._fieldList == null) throw StateError('message not resolved'); + checkResolved(); if (alreadySeen.contains(type.fullName)) { // The type is already in cache. This means that either: @@ -495,7 +495,7 @@ for (var field in _fieldList) { out.println(); var memberFieldPath = List<int>.from(fieldPath) - ..addAll([_messageFieldTag, field.sourcePosition]); + ..addAll([_messageFieldTag, field.sourcePosition!]); generateFieldAccessorsMutators(field, out, memberFieldPath); } } @@ -510,17 +510,17 @@ void generateFieldAccessorsMutators( ProtobufField field, IndentingWriter out, List<int> memberFieldPath) { - var fieldTypeString = field.getDartType(fileGen); + var fieldTypeString = field.getDartType(); var defaultExpr = field.getDefaultExpr(); var names = field.memberNames; _emitDeprecatedIf(field.isDeprecated, out); _emitOverrideIf(field.overridesGetter, out); _emitIndexAnnotation(field.number, out); - final getterExpr = _getterExpression(fieldTypeString, field.index, + final getterExpr = _getterExpression(fieldTypeString, field.index!, defaultExpr, field.isRepeated, field.isMapField); out.printlnAnnotated( - '$fieldTypeString get ${names.fieldName} => $getterExpr;', [ + '$fieldTypeString get ${names!.fieldName} => $getterExpr;', [ NamedLocation( name: names.fieldName, fieldPathSegment: memberFieldPath, @@ -579,7 +579,7 @@ ' \$_has(${field.index});', [ NamedLocation( - name: names.hasMethodName, + name: names.hasMethodName!, fieldPathSegment: memberFieldPath, start: '$coreImportPrefix.bool '.length) ]); @@ -592,7 +592,7 @@ ' clearField(${field.number});', [ NamedLocation( - name: names.clearMethodName, + name: names.clearMethodName!, fieldPathSegment: memberFieldPath, start: 'void '.length) ]); @@ -604,7 +604,7 @@ '\$_ensure(${field.index});', <NamedLocation>[ NamedLocation( - name: names.ensureMethodName, + name: names.ensureMethodName!, fieldPathSegment: memberFieldPath, start: '$fieldTypeString '.length) ]); @@ -677,8 +677,8 @@ void generateConstants(IndentingWriter out) { const nestedTypeTag = 3; const enumTypeTag = 4; - assert(_descriptor.info_.fieldInfo[nestedTypeTag].name == 'nestedType'); - assert(_descriptor.info_.fieldInfo[enumTypeTag].name == 'enumType'); + assert(_descriptor.info_.fieldInfo[nestedTypeTag]!.name == 'nestedType'); + assert(_descriptor.info_.fieldInfo[enumTypeTag]!.name == 'enumType'); var name = getJsonConstant(fileGen); var json = _descriptor.writeToJsonMap(); @@ -688,7 +688,7 @@ _enumGenerators.map((e) => e.getJsonConstant(fileGen)).toList(); out.println('@$coreImportPrefix.Deprecated' - '(\'Use ${toplevelParent.binaryDescriptorName} instead\')'); + '(\'Use ${toplevelParent!.binaryDescriptorName} instead\')'); out.addBlock('const $name = const {', '};', () { for (var key in json.keys) { out.print("'$key': "); @@ -718,9 +718,10 @@ /// Returns the mixin for this message, or null if none. /// - /// First searches [wellKnownMixins], then [declaredMixins], + /// First searches [_wellKnownMixins], then [declaredMixins], /// then internal mixins declared by [findMixin]. - PbMixin _getMixin(Map<String, PbMixin> declaredMixins, PbMixin defaultMixin) { + PbMixin? _getMixin( + Map<String, PbMixin> declaredMixins, PbMixin? defaultMixin) { var wellKnownMixin = wellKnownMixinForFullName(fullName); if (wellKnownMixin != null) return wellKnownMixin; if (!_descriptor.hasOptions() || @@ -732,7 +733,7 @@ if (name.isEmpty) return null; // don't use any mixins (override default) var mixin = declaredMixins[name] ?? findMixin(name); if (mixin == null) { - throw '${_descriptor.name} in ${parent.fileGen.descriptor.name}: mixin "$name" not found'; + throw '${_descriptor.name} in ${parent!.fileGen!.descriptor.name}: mixin "$name" not found'; } return mixin; }
diff --git a/protoc_plugin/lib/src/options.dart b/protoc_plugin/lib/src/options.dart index 55323ba..aa7b463 100644 --- a/protoc_plugin/lib/src/options.dart +++ b/protoc_plugin/lib/src/options.dart
@@ -92,7 +92,7 @@ } /// Parser used by the compiler, which supports the `rpc` option (see -/// [RpcOptionParser]) and any additional option added in [parsers]. If +/// [GrpcOptionParser]) and any additional option added in [parsers]. If /// [parsers] has a key for `rpc`, it will be ignored. GenerationOptions? parseGenerationOptions( CodeGeneratorRequest request, CodeGeneratorResponse response,
diff --git a/protoc_plugin/lib/src/protobuf_field.dart b/protoc_plugin/lib/src/protobuf_field.dart index 7f8dad6..b8f5b3f 100644 --- a/protoc_plugin/lib/src/protobuf_field.dart +++ b/protoc_plugin/lib/src/protobuf_field.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; class ProtobufField { @@ -22,10 +20,11 @@ final FieldDescriptorProto descriptor; /// Dart names within a GeneratedMessage or `null` for an extension. - final FieldNames memberNames; + final FieldNames? memberNames; final String fullName; final BaseType baseType; + final ProtobufContainer parent; ProtobufField.message( FieldNames names, ProtobufContainer parent, GenerationContext ctx) @@ -35,8 +34,8 @@ ProtobufContainer parent, GenerationContext ctx) : this._(descriptor, null, parent, ctx); - ProtobufField._(this.descriptor, FieldNames dartNames, - ProtobufContainer parent, GenerationContext ctx) + ProtobufField._(this.descriptor, FieldNames? dartNames, this.parent, + GenerationContext ctx) : memberNames = dartNames, fullName = '${parent.fullName}.${descriptor.name}', baseType = BaseType(descriptor, ctx); @@ -44,18 +43,18 @@ /// The index of this field in MessageGenerator.fieldList. /// /// `null` for an extension. - int get index => memberNames?.index; + int? get index => memberNames?.index; - String get quotedProtoName => + String? get quotedProtoName => (_unCamelCase(descriptor.jsonName) == descriptor.name) ? null : "'${descriptor.name}'"; /// The position of this field as it appeared in the original DescriptorProto. - int get sourcePosition => memberNames.sourcePosition; + int? get sourcePosition => memberNames?.sourcePosition; /// True if the field is to be encoded with [deprecated = true] encoding. - bool get isDeprecated => descriptor.options?.deprecated; + bool get isDeprecated => descriptor.options.deprecated; bool get isRequired => descriptor.label == FieldDescriptorProto_Label.LABEL_REQUIRED; @@ -63,9 +62,33 @@ bool get isRepeated => descriptor.label == FieldDescriptorProto_Label.LABEL_REPEATED; - /// True if the field is to be encoded with [packed=true] encoding. - bool get isPacked => - isRepeated && descriptor.options != null && descriptor.options.packed; + /// True if a numeric field is repeated and it should be encoded with packed + /// encoding. In proto3 repeated fields are encoded as packed by default. + /// proto2 requires `[packed=true]` option. + bool get isPacked { + if (!isRepeated) { + return false; // only repeated fields can be packed + } + + if (!baseType.isPackable) { + return false; + } + + switch (parent.fileGen!.syntax) { + case ProtoSyntax.proto3: + if (!descriptor.hasOptions()) { + return true; // packed by default in proto3 + } else { + return !descriptor.options.hasPacked() || descriptor.options.packed; + } + case ProtoSyntax.proto2: + if (!descriptor.hasOptions()) { + return false; // not packed by default in proto3 + } else { + return descriptor.options.packed; + } + } + } /// Whether the field has the `overrideGetter` annotation set to true. bool get overridesGetter => _hasBooleanOption(Dart_options.overrideGetter); @@ -114,16 +137,15 @@ /// Returns the expression to use for the Dart type. /// /// This will be a List for repeated types. - /// [fileGen] represents the .proto file where we are generating code. - String getDartType(FileGenerator fileGen) { + String getDartType() { if (isMapField) { final d = baseType.generator as MessageGenerator; - var keyType = d._fieldList[0].baseType.getDartType(fileGen); - var valueType = d._fieldList[1].baseType.getDartType(fileGen); + var keyType = d._fieldList[0].baseType.getDartType(parent.fileGen!); + var valueType = d._fieldList[1].baseType.getDartType(parent.fileGen!); return '$coreImportPrefix.Map<$keyType, $valueType>'; } - if (isRepeated) return baseType.getRepeatedDartType(fileGen); - return baseType.getDartType(fileGen); + if (isRepeated) return baseType.getRepeatedDartType(parent.fileGen!); + return baseType.getDartType(parent.fileGen!); } /// Returns the tag number of the underlying proto field. @@ -145,7 +167,7 @@ } static String _formatArguments( - List<String> positionals, Map<String, String> named) { + List<String?> positionals, Map<String, String?> named) { final args = positionals.toList(); while (args.last == null) { args.removeLast(); @@ -165,20 +187,19 @@ /// Returns Dart code adding this field to a BuilderInfo object. /// The call will start with ".." and a method name. - /// [fileGen] represents the .proto file where the code will be evaluated. - String generateBuilderInfoCall(FileGenerator fileGen, String package) { + String generateBuilderInfoCall(String package) { assert(descriptor.hasJsonName()); var quotedName = configurationDependent( 'protobuf.omit_field_names', quoted(descriptor.jsonName), ); - var type = baseType.getDartType(fileGen); + var type = baseType.getDartType(parent.fileGen!); String invocation; var args = <String>[]; - var named = <String, String>{'protoName': quotedProtoName}; + var named = <String, String?>{'protoName': quotedProtoName}; args.add('$number'); args.add(quotedName); @@ -186,8 +207,8 @@ final generator = baseType.generator as MessageGenerator; var key = generator._fieldList[0]; var value = generator._fieldList[1]; - var keyType = key.baseType.getDartType(fileGen); - var valueType = value.baseType.getDartType(fileGen); + var keyType = key.baseType.getDartType(parent.fileGen!); + var valueType = value.baseType.getDartType(parent.fileGen!); invocation = 'm<$keyType, $valueType>'; @@ -200,7 +221,7 @@ if (value.baseType.isEnum) { named['valueOf'] = '$valueType.valueOf'; named['enumValues'] = '$valueType.values'; - named['defaultEnumValue'] = value.generateDefaultFunction(fileGen); + named['defaultEnumValue'] = value.generateDefaultFunction(); } if (package != '') { named['packageName'] = @@ -222,12 +243,12 @@ } else if (baseType.isEnum) { named['valueOf'] = '$type.valueOf'; named['enumValues'] = '$type.values'; - named['defaultEnumValue'] = generateDefaultFunction(fileGen); + named['defaultEnumValue'] = generateDefaultFunction(); } } } else { // Singular field. - var makeDefault = generateDefaultFunction(fileGen); + var makeDefault = generateDefaultFunction(); if (baseType.isEnum) { args.add(typeConstant); @@ -279,7 +300,6 @@ } } } - assert(invocation != null); return '..$invocation(${_formatArguments(args, named)})'; } @@ -291,25 +311,22 @@ if (isRepeated) return 'null'; switch (descriptor.type) { case FieldDescriptorProto_Type.TYPE_BOOL: - return _getDefaultAsBoolExpr('false'); + return _getDefaultAsBoolExpr('false')!; case FieldDescriptorProto_Type.TYPE_INT32: case FieldDescriptorProto_Type.TYPE_UINT32: case FieldDescriptorProto_Type.TYPE_SINT32: case FieldDescriptorProto_Type.TYPE_FIXED32: case FieldDescriptorProto_Type.TYPE_SFIXED32: - return _getDefaultAsInt32Expr('0'); + return _getDefaultAsInt32Expr('0')!; case FieldDescriptorProto_Type.TYPE_STRING: - return _getDefaultAsStringExpr("''"); + return _getDefaultAsStringExpr("''")!; default: return 'null'; } } /// Returns a function expression that returns the field's default value. - /// - /// [fileGen] represents the .proto file where the expression will be - /// evaluated. - String generateDefaultFunction(FileGenerator fileGen) { + String? generateDefaultFunction() { assert(!isRepeated); switch (descriptor.type) { case FieldDescriptorProto_Type.TYPE_BOOL: @@ -363,9 +380,9 @@ return '() => <$coreImportPrefix.int>[$byteList]'; case FieldDescriptorProto_Type.TYPE_GROUP: case FieldDescriptorProto_Type.TYPE_MESSAGE: - return '${baseType.getDartType(fileGen)}.getDefault'; + return '${baseType.getDartType(parent.fileGen!)}.getDefault'; case FieldDescriptorProto_Type.TYPE_ENUM: - var className = baseType.getDartType(fileGen); + var className = baseType.getDartType(parent.fileGen!); final gen = baseType.generator as EnumGenerator; if (descriptor.hasDefaultValue() && descriptor.defaultValue.isNotEmpty) { @@ -379,14 +396,14 @@ } } - String _getDefaultAsBoolExpr(String noDefault) { + String? _getDefaultAsBoolExpr(String? noDefault) { if (descriptor.hasDefaultValue() && 'false' != descriptor.defaultValue) { return descriptor.defaultValue; } return noDefault; } - String _getDefaultAsStringExpr(String noDefault) { + String? _getDefaultAsStringExpr(String? noDefault) { if (!descriptor.hasDefaultValue() || descriptor.defaultValue.isEmpty) { return noDefault; } @@ -394,7 +411,7 @@ return quoted(descriptor.defaultValue); } - String _getDefaultAsInt32Expr(String noDefault) { + String? _getDefaultAsInt32Expr(String? noDefault) { if (descriptor.hasDefaultValue() && '0' != descriptor.defaultValue) { return descriptor.defaultValue; } @@ -402,7 +419,7 @@ } bool _hasBooleanOption(Extension extension) => - descriptor?.options?.getExtension(extension) as bool ?? false; + descriptor.options.getExtension(extension) as bool? ?? false; String get _invalidDefaultValue => 'dart-protoc-plugin:' ' invalid default value (${descriptor.defaultValue})' @@ -416,6 +433,6 @@ static String _unCamelCase(String name) { return name.replaceAllMapped( - _upperCase, (match) => '_${match.group(0).toLowerCase()}'); + _upperCase, (match) => '_${match.group(0)!.toLowerCase()}'); } }
diff --git a/protoc_plugin/lib/src/service_generator.dart b/protoc_plugin/lib/src/service_generator.dart index 3fcd1a9..53ef39c 100644 --- a/protoc_plugin/lib/src/service_generator.dart +++ b/protoc_plugin/lib/src/service_generator.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; class ServiceGenerator { @@ -68,7 +66,7 @@ void _addDependency(GenerationContext ctx, String fqname, String location) { if (_deps.containsKey(fqname)) return; // Already added. - final mg = ctx.getFieldType(fqname) as MessageGenerator; + final mg = ctx.getFieldType(fqname) as MessageGenerator?; if (mg == null) { _undefinedDeps[fqname] = location; return; @@ -226,7 +224,7 @@ var typeConstants = <String, String>{}; for (var key in _transitiveDeps.keys) { - typeConstants[key] = _transitiveDeps[key].getJsonConstant(fileGen); + typeConstants[key] = _transitiveDeps[key]!.getJsonConstant(fileGen); } out.println('@$coreImportPrefix.Deprecated'
diff --git a/protoc_plugin/lib/src/well_known_types.dart b/protoc_plugin/lib/src/well_known_types.dart index 7fabd87..24e360b 100644 --- a/protoc_plugin/lib/src/well_known_types.dart +++ b/protoc_plugin/lib/src/well_known_types.dart
@@ -2,11 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - part of '../protoc.dart'; -PbMixin wellKnownMixinForFullName(String qualifiedName) => +PbMixin? wellKnownMixinForFullName(String qualifiedName) => _wellKnownMixins[qualifiedName]; const _wellKnownImportPath =
diff --git a/protoc_plugin/mono_pkg.yaml b/protoc_plugin/mono_pkg.yaml index efa3a9e..ba38d24 100644 --- a/protoc_plugin/mono_pkg.yaml +++ b/protoc_plugin/mono_pkg.yaml
@@ -6,10 +6,10 @@ - command: ./../tool/setup.sh - command: make protos - analyze: --fatal-infos - dart: [dev] + sdk: [dev] - run_tests: - group: - command: ./../tool/setup.sh - command: make protos - test - dart: [2.12.0, dev] + sdk: [2.12.0, dev]
diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml index bcdd56f..2febd42 100644 --- a/protoc_plugin/pubspec.yaml +++ b/protoc_plugin/pubspec.yaml
@@ -1,7 +1,7 @@ name: protoc_plugin version: 20.0.1-dev description: Protoc compiler plugin to generate Dart code -homepage: https://github.com/google/protobuf.dart +repository: https://github.com/google/protobuf.dart/tree/master/protoc_plugin environment: sdk: '>=2.12.0 <3.0.0'
diff --git a/protoc_plugin/test/all_tests.dart b/protoc_plugin/test/all_tests.dart deleted file mode 100755 index d85093f..0000000 --- a/protoc_plugin/test/all_tests.dart +++ /dev/null
@@ -1,90 +0,0 @@ -#!/usr/bin/env dart -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// @dart=2.11 - -import 'any_test.dart' as any; -import 'bazel_test.dart' as bazel; -import 'client_generator_test.dart' as client_generator; -import 'const_generator_test.dart' as const_generator; -import 'default_value_escape_test.dart' as default_value_escape; -import 'descriptor_test.dart' as descriptor_test; -import 'enum_generator_test.dart' as enum_generator; -import 'extension_generator_test.dart' as extension_generator_test; -import 'extension_test.dart' as extension_test; -import 'file_generator_test.dart' as file_generator; -import 'generated_message_test.dart' as generated_message; -import 'hash_code_test.dart' as hash_code; -import 'high_tagnumber_test.dart' as high_tagnumber; -import 'import_public_test.dart' as import_public; -import 'import_test.dart' as import_prefix; -import 'indenting_writer_test.dart' as indenting_writer; -import 'json_test.dart' as json; -import 'leading_underscores_test.dart' as leading_underscores; -import 'map_field_test.dart' as map_field; -import 'map_test.dart' as map; -import 'merge_test.dart' as merge; -import 'message_generator_test.dart' as message_generator; -import 'message_test.dart' as message; -import 'mixin_test.dart' as mixin_test; -import 'names_test.dart' as names; -import 'omit_enum_names_test.dart' as omit_enum_names; -import 'omit_field_names_test.dart' as omit_field_names; -import 'omit_message_names_test.dart' as omit_message_names; -import 'oneof_test.dart' as oneof; -import 'proto3_optional_test.dart' as proto3_optional; -import 'protoc_options_test.dart' as protoc_options; -import 'repeated_field_test.dart' as repeated_field; -import 'reserved_names_test.dart' as reserved_names; -import 'send_protos_via_sendports_test.dart' as send_protos_via_sendports_test; -import 'service_generator_test.dart' as service_generator; -import 'service_test.dart' as service; -import 'to_builder_test.dart' as to_builder; -import 'unknown_field_set_test.dart' as unknown_field_set; -import 'validate_fail_test.dart' as validate_fail; -import 'wire_format_test.dart' as wire_format; - -void main() { - any.main(); - bazel.main(); - client_generator.main(); - const_generator.main(); - default_value_escape.main(); - descriptor_test.main(); - enum_generator.main(); - extension_generator_test.main(); - extension_test.main(); - file_generator.main(); - generated_message.main(); - hash_code.main(); - high_tagnumber.main(); - import_prefix.main(); - import_public.main(); - indenting_writer.main(); - json.main(); - leading_underscores.main(); - map.main(); - map_field.main(); - merge.main(); - message.main(); - message_generator.main(); - mixin_test.main(); - names.main(); - omit_enum_names.main(); - omit_field_names.main(); - omit_message_names.main(); - oneof.main(); - proto3_optional.main(); - protoc_options.main(); - repeated_field.main(); - reserved_names.main(); - send_protos_via_sendports_test.main(); - service.main(); - service_generator.main(); - to_builder.main(); - unknown_field_set.main(); - validate_fail.main(); - wire_format.main(); -}
diff --git a/protoc_plugin/test/any_test.dart b/protoc_plugin/test/any_test.dart index a29d6d1..df1cb12 100644 --- a/protoc_plugin/test/any_test.dart +++ b/protoc_plugin/test/any_test.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protobuf/protobuf.dart'; import 'package:test/test.dart';
diff --git a/protoc_plugin/test/bazel_test.dart b/protoc_plugin/test/bazel_test.dart index e1ef89c..0cca05b 100644 --- a/protoc_plugin/test/bazel_test.dart +++ b/protoc_plugin/test/bazel_test.dart
@@ -2,17 +2,15 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/bazel.dart'; import 'package:test/test.dart'; void main() { group('BazelOptionParser', () { - BazelOptionParser optionParser; - Map<String, BazelPackage> packages; - List<String> errors; - + late BazelOptionParser optionParser; + late Map<String, BazelPackage> packages; + late List<String> errors; + final optionName = 'name'; setUp(() { packages = {}; optionParser = BazelOptionParser(packages); @@ -24,95 +22,95 @@ } test('should call onError for null values', () { - optionParser.parse(null, null, _onError); + optionParser.parse(optionName, null, _onError); expect(errors, isNotEmpty); }); test('should call onError for empty values', () { - optionParser.parse(null, '', _onError); + optionParser.parse(optionName, '', _onError); expect(errors, isNotEmpty); }); test('should call onError for malformed entries', () { - optionParser.parse(null, 'foo', _onError); - optionParser.parse(null, 'foo|bar', _onError); - optionParser.parse(null, 'foo|bar|baz|quux', _onError); + optionParser.parse(optionName, 'foo', _onError); + optionParser.parse(optionName, 'foo|bar', _onError); + optionParser.parse(optionName, 'foo|bar|baz|quux', _onError); expect(errors.length, 3); expect(packages, isEmpty); }); test('should handle a single package|path entry', () { - optionParser.parse(null, 'foo|bar/baz|wibble/wobble', _onError); + optionParser.parse(optionName, 'foo|bar/baz|wibble/wobble', _onError); expect(errors, isEmpty); expect(packages.length, 1); - expect(packages['bar/baz'].name, 'foo'); - expect(packages['bar/baz'].inputRoot, 'bar/baz'); - expect(packages['bar/baz'].outputRoot, 'wibble/wobble'); + expect(packages['bar/baz']!.name, 'foo'); + expect(packages['bar/baz']!.inputRoot, 'bar/baz'); + expect(packages['bar/baz']!.outputRoot, 'wibble/wobble'); }); test('should handle multiple package|path entries', () { optionParser.parse( - null, + optionName, 'foo|bar/baz|wibble/wobble;a|b/c/d|e/f;one.two|three|four/five', _onError); expect(errors, isEmpty); expect(packages.length, 3); - expect(packages['bar/baz'].name, 'foo'); - expect(packages['bar/baz'].inputRoot, 'bar/baz'); - expect(packages['bar/baz'].outputRoot, 'wibble/wobble'); - expect(packages['b/c/d'].name, 'a'); - expect(packages['b/c/d'].inputRoot, 'b/c/d'); - expect(packages['b/c/d'].outputRoot, 'e/f'); - expect(packages['three'].name, 'one.two'); - expect(packages['three'].inputRoot, 'three'); - expect(packages['three'].outputRoot, 'four/five'); + expect(packages['bar/baz']!.name, 'foo'); + expect(packages['bar/baz']!.inputRoot, 'bar/baz'); + expect(packages['bar/baz']!.outputRoot, 'wibble/wobble'); + expect(packages['b/c/d']!.name, 'a'); + expect(packages['b/c/d']!.inputRoot, 'b/c/d'); + expect(packages['b/c/d']!.outputRoot, 'e/f'); + expect(packages['three']!.name, 'one.two'); + expect(packages['three']!.inputRoot, 'three'); + expect(packages['three']!.outputRoot, 'four/five'); }); test('should skip and continue past malformed entries', () { - optionParser.parse(null, + optionParser.parse(optionName, 'foo|bar/baz|wibble/wobble;fizz;a.b|c/d|e/f;x|y|zz|y', _onError); expect(errors.length, 2); expect(packages.length, 2); - expect(packages['bar/baz'].name, 'foo'); - expect(packages['c/d'].name, 'a.b'); + expect(packages['bar/baz']!.name, 'foo'); + expect(packages['c/d']!.name, 'a.b'); }); test('should emit error for conflicting package names', () { - optionParser.parse(null, + optionParser.parse(optionName, 'foo|bar/baz|wibble/wobble;flob|bar/baz|wibble/wobble', _onError); expect(errors.length, 1); expect(packages.length, 1); - expect(packages['bar/baz'].name, 'foo'); + expect(packages['bar/baz']!.name, 'foo'); }); - test('should emit error for conflicting output_roots', () { - optionParser.parse(null, + test('should emit error for conflicting outputRoots', () { + optionParser.parse(optionName, 'foo|bar/baz|wibble/wobble;foo|bar/baz|womble/wumble', _onError); expect(errors.length, 1); expect(packages.length, 1); - expect(packages['bar/baz'].outputRoot, 'wibble/wobble'); + expect(packages['bar/baz']!.outputRoot, 'wibble/wobble'); }); test('should normalize paths', () { - optionParser.parse( - null, 'foo|bar//baz/|quux/;a|b/|c;c|d//e/f///|g//h//', _onError); + optionParser.parse(optionName, + 'foo|bar//baz/|quux/;a|b/|c;c|d//e/f///|g//h//', _onError); expect(errors, isEmpty); expect(packages.length, 3); - expect(packages['bar/baz'].name, 'foo'); - expect(packages['bar/baz'].inputRoot, 'bar/baz'); - expect(packages['bar/baz'].outputRoot, 'quux'); - expect(packages['b'].name, 'a'); - expect(packages['b'].inputRoot, 'b'); - expect(packages['b'].outputRoot, 'c'); - expect(packages['d/e/f'].name, 'c'); - expect(packages['d/e/f'].inputRoot, 'd/e/f'); - expect(packages['d/e/f'].outputRoot, 'g/h'); + expect(packages['bar/baz']!.name, 'foo'); + expect(packages['bar/baz']!.inputRoot, 'bar/baz'); + expect(packages['bar/baz']!.outputRoot, 'quux'); + expect(packages['b']!.name, 'a'); + expect(packages['b']!.inputRoot, 'b'); + expect(packages['b']!.outputRoot, 'c'); + expect(packages['d/e/f']!.name, 'c'); + expect(packages['d/e/f']!.inputRoot, 'd/e/f'); + expect(packages['d/e/f']!.outputRoot, 'g/h'); }); }); group('BazelOutputConfiguration', () { Map<String, BazelPackage> packages; - BazelOutputConfiguration config; + late BazelOutputConfiguration config; setUp(() { packages = {
diff --git a/protoc_plugin/test/client_generator_test.dart b/protoc_plugin/test/client_generator_test.dart index 157805c..fbe2398 100644 --- a/protoc_plugin/test/client_generator_test.dart +++ b/protoc_plugin/test/client_generator_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/indenting_writer.dart'; import 'package:protoc_plugin/protoc.dart'; import 'package:protoc_plugin/src/linker.dart';
diff --git a/protoc_plugin/test/coded_buffer_test.dart b/protoc_plugin/test/coded_buffer_test.dart new file mode 100644 index 0000000..e171f06 --- /dev/null +++ b/protoc_plugin/test/coded_buffer_test.dart
@@ -0,0 +1,30 @@ +#!/usr/bin/env dart +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; + +import '../out/protos/bytes.pb.dart'; + +void main() { + test('Does not reuse input buffer for bytes fields', () { + var message = BytesEntity()..value = [1, 2, 3]; + var bytes = message.writeToBuffer(); + var deserialized1 = BytesEntity()..mergeFromBuffer(bytes); + var deserialized2 = BytesEntity()..mergeFromBuffer(bytes); + deserialized1.value[0] = 100; + expect(deserialized1.value[0], 100); + expect(deserialized2.value[0], 1); + }); + + test('Does not reuse input buffer for repeated bytes fields', () { + var message = BytesEntity()..values.add([1, 2, 3]); + var bytes = message.writeToBuffer(); + var deserialized1 = BytesEntity()..mergeFromBuffer(bytes); + var deserialized2 = BytesEntity()..mergeFromBuffer(bytes); + deserialized1.values.first[0] = 100; + expect(deserialized1.values.first[0], 100); + expect(deserialized2.values.first[0], 1); + }); +}
diff --git a/protoc_plugin/test/default_value_escape_test.dart b/protoc_plugin/test/default_value_escape_test.dart index 2894c50..b71a01b 100644 --- a/protoc_plugin/test/default_value_escape_test.dart +++ b/protoc_plugin/test/default_value_escape_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:test/test.dart'; import '../out/protos/default_value_escape.pb.dart';
diff --git a/protoc_plugin/test/descriptor_test.dart b/protoc_plugin/test/descriptor_test.dart index cc97675..34085cf 100644 --- a/protoc_plugin/test/descriptor_test.dart +++ b/protoc_plugin/test/descriptor_test.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protobuf/protobuf.dart'; import 'package:protoc_plugin/src/generated/descriptor.pb.dart'; import 'package:test/test.dart';
diff --git a/protoc_plugin/test/enum_generator_test.dart b/protoc_plugin/test/enum_generator_test.dart index a2b7b02..715df7e 100755 --- a/protoc_plugin/test/enum_generator_test.dart +++ b/protoc_plugin/test/enum_generator_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/indenting_writer.dart'; import 'package:protoc_plugin/protoc.dart'; import 'package:protoc_plugin/src/generated/descriptor.pb.dart';
diff --git a/protoc_plugin/test/extension_generator_test.dart b/protoc_plugin/test/extension_generator_test.dart index b49ff6d..ceb0696 100644 --- a/protoc_plugin/test/extension_generator_test.dart +++ b/protoc_plugin/test/extension_generator_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/indenting_writer.dart'; import 'package:protoc_plugin/protoc.dart'; import 'package:protoc_plugin/src/generated/descriptor.pb.dart' as pb;
diff --git a/protoc_plugin/test/extension_test.dart b/protoc_plugin/test/extension_test.dart index 56b7408..5925251 100644 --- a/protoc_plugin/test/extension_test.dart +++ b/protoc_plugin/test/extension_test.dart
@@ -3,8 +3,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - +import 'dart:typed_data'; import 'package:protobuf/protobuf.dart'; import 'package:test/test.dart'; @@ -17,7 +16,8 @@ import '../out/protos/non_nested_extension.pb.dart'; import 'test_util.dart'; -Matcher throwsArgError(String expectedMessage) => throwsA(predicate((x) { +Matcher throwsArgError(String expectedMessage) => + throwsA(predicate((dynamic x) { expect(x, isArgumentError); expect(x.message, expectedMessage); return true; @@ -174,14 +174,14 @@ }); test('can extend a message with a message field with a different type', () { - expect(Non_nested_extension.nonNestedExtension.makeDefault(), + expect(Non_nested_extension.nonNestedExtension.makeDefault!(), TypeMatcher<MyNonNestedExtension>()); expect(Non_nested_extension.nonNestedExtension.name, 'nonNestedExtension'); }); test('can extend a message with a message field of the same type', () { expect( - MyNestedExtension.recursiveExtension.makeDefault() + MyNestedExtension.recursiveExtension.makeDefault!() is MessageToBeExtended, isTrue); expect(MyNestedExtension.recursiveExtension.name, 'recursiveExtension'); @@ -532,7 +532,7 @@ final withUnknownFields = Outer.fromBuffer(original.writeToBuffer()); expect( - withUnknownFields.innerMap[0] + withUnknownFields.innerMap[0]! .hasExtension(Extend_unittest.innerExtensionString), isFalse); @@ -540,11 +540,23 @@ final reparsed = r.reparseMessage(withUnknownFields); expect( - reparsed.innerMap[0].hasExtension(Extend_unittest.innerExtensionString), + reparsed.innerMap[0]! + .hasExtension(Extend_unittest.innerExtensionString), isTrue); expect( identical(withUnknownFields.innerMap[1], reparsed.innerMap[1]), isTrue); expect(withUnknownFields.stringMap.length, reparsed.stringMap.length); expect(withUnknownFields.stringMap[0], reparsed.stringMap[0]); }); + + test('consistent hashcode for reparsed messages with extensions', () { + final r = ExtensionRegistry()..add(Extend_unittest.outer); + final m = TestAllExtensions() + ..setExtension( + Extend_unittest.outer, Outer()..inner = (Inner()..value = 'hello')); + final Uint8List b = m.writeToBuffer(); + final c = TestAllExtensions.fromBuffer(b); + final d = r.reparseMessage(c); + expect(m.hashCode, d.hashCode); + }); }
diff --git a/protoc_plugin/test/extension_unknown_interaction_test.dart b/protoc_plugin/test/extension_unknown_interaction_test.dart new file mode 100644 index 0000000..9acb389 --- /dev/null +++ b/protoc_plugin/test/extension_unknown_interaction_test.dart
@@ -0,0 +1,23 @@ +#!/usr/bin/env dart +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:protobuf/protobuf.dart'; +import 'package:test/test.dart'; + +import '../out/protos/google/protobuf/unittest.pb.dart'; + +void main() { + test('setExtension clears unknown field with same tag number', () { + final m = TestAllExtensions(); + m.unknownFields.addField(Unittest.optionalInt32Extension.tagNumber, + UnknownFieldSetField()..addFixed32(33)); + expect(m.unknownFields.hasField(Unittest.optionalInt32Extension.tagNumber), + isTrue); + m.setExtension(Unittest.optionalInt32Extension, 42); + expect(m.getExtension(Unittest.optionalInt32Extension), 42); + expect(m.unknownFields.hasField(Unittest.optionalInt32Extension.tagNumber), + isFalse); + }); +}
diff --git a/protoc_plugin/test/file_generator_test.dart b/protoc_plugin/test/file_generator_test.dart index 84c733a..6763579 100644 --- a/protoc_plugin/test/file_generator_test.dart +++ b/protoc_plugin/test/file_generator_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/indenting_writer.dart'; import 'package:protoc_plugin/protoc.dart'; import 'package:protoc_plugin/src/generated/descriptor.pb.dart'; @@ -95,8 +93,8 @@ test('FileGenerator outputs a .pb.dart file for a proto with one message', () { var fd = buildFileDescriptor(); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); expectMatchesGoldenFile( @@ -105,8 +103,8 @@ test('FileGenerator outputs a .pb.dart file for an Int64 message', () { var fd = createInt64Proto(); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); expectMatchesGoldenFile( @@ -119,7 +117,7 @@ var fd = buildFileDescriptor(); var options = parseGenerationOptions( CodeGeneratorRequest()..parameter = 'generate_kythe_info', - CodeGeneratorResponse()); + CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); expectMatchesGoldenFile(fg.generateMainFile().sourceLocationInfo.toString(), @@ -129,8 +127,8 @@ test('FileGenerator outputs a pbjson.dart file for a proto with one message', () { var fd = buildFileDescriptor(); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); expectMatchesGoldenFile( @@ -139,8 +137,8 @@ test('FileGenerator generates files for a top-level enum', () { var fd = buildFileDescriptor(phoneNumber: false, topLevelEnum: true); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); @@ -154,7 +152,7 @@ var fd = buildFileDescriptor(phoneNumber: false, topLevelEnum: true); var options = parseGenerationOptions( CodeGeneratorRequest()..parameter = 'generate_kythe_info', - CodeGeneratorResponse()); + CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); @@ -166,8 +164,8 @@ test('FileGenerator generates a .pbjson.dart file for a top-level enum', () { var fd = buildFileDescriptor(phoneNumber: false, topLevelEnum: true); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); @@ -178,8 +176,8 @@ test('FileGenerator outputs library for a .proto in a package', () { var fd = buildFileDescriptor(); fd.package = 'pb_library'; - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); @@ -203,8 +201,8 @@ ..type = FieldDescriptorProto_Type.TYPE_INT64 ])); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); @@ -230,8 +228,8 @@ ..messageType.add(empty) ..service.add(sd); - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; var fg = FileGenerator(fd, options); link(options, [fg]); @@ -420,7 +418,7 @@ fd.dependency.addAll(['package1.proto', 'package2.proto']); var request = CodeGeneratorRequest(); var response = CodeGeneratorResponse(); - var options = parseGenerationOptions(request, response); + var options = parseGenerationOptions(request, response)!; var fg = FileGenerator(fd, options); link(options,
diff --git a/protoc_plugin/test/goldens/grpc_service.pb b/protoc_plugin/test/goldens/grpc_service.pb index bb87200..40d318a 100644 --- a/protoc_plugin/test/goldens/grpc_service.pb +++ b/protoc_plugin/test/goldens/grpc_service.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/grpc_service.pbgrpc b/protoc_plugin/test/goldens/grpc_service.pbgrpc index e03a826..a221d1f 100644 --- a/protoc_plugin/test/goldens/grpc_service.pbgrpc +++ b/protoc_plugin/test/goldens/grpc_service.pbgrpc
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:async' as $async;
diff --git a/protoc_plugin/test/goldens/header_in_package.pb b/protoc_plugin/test/goldens/header_in_package.pb index ee271f7..b102c15 100644 --- a/protoc_plugin/test/goldens/header_in_package.pb +++ b/protoc_plugin/test/goldens/header_in_package.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/header_with_fixnum.pb b/protoc_plugin/test/goldens/header_with_fixnum.pb index 3eb7a37..c9dfa5d 100644 --- a/protoc_plugin/test/goldens/header_with_fixnum.pb +++ b/protoc_plugin/test/goldens/header_with_fixnum.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/imports.pb b/protoc_plugin/test/goldens/imports.pb index 47e7a8b..275c153 100644 --- a/protoc_plugin/test/goldens/imports.pb +++ b/protoc_plugin/test/goldens/imports.pb
@@ -3,7 +3,7 @@ // source: test.proto // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/imports.pbjson b/protoc_plugin/test/goldens/imports.pbjson index baf0213..66934b0 100644 --- a/protoc_plugin/test/goldens/imports.pbjson +++ b/protoc_plugin/test/goldens/imports.pbjson
@@ -3,5 +3,5 @@ // source: test.proto // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
diff --git a/protoc_plugin/test/goldens/int64.pb b/protoc_plugin/test/goldens/int64.pb index 2a1aff1..3d4184a 100644 --- a/protoc_plugin/test/goldens/int64.pb +++ b/protoc_plugin/test/goldens/int64.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/oneMessage.pb b/protoc_plugin/test/goldens/oneMessage.pb index 3f44fbb..f47d665 100644 --- a/protoc_plugin/test/goldens/oneMessage.pb +++ b/protoc_plugin/test/goldens/oneMessage.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/oneMessage.pb.meta b/protoc_plugin/test/goldens/oneMessage.pb.meta index a287f25..2b7dcac 100644 --- a/protoc_plugin/test/goldens/oneMessage.pb.meta +++ b/protoc_plugin/test/goldens/oneMessage.pb.meta
@@ -2,15 +2,15 @@ path: 4 path: 0 sourceFile: test - begin: 420 - end: 431 + begin: 439 + end: 450 } annotation: { path: 4 path: 0 sourceFile: test - begin: 992 - end: 1003 + begin: 1011 + end: 1022 } annotation: { path: 4 @@ -18,8 +18,8 @@ path: 2 path: 0 sourceFile: test - begin: 2732 - end: 2738 + begin: 2751 + end: 2757 } annotation: { path: 4 @@ -27,8 +27,8 @@ path: 2 path: 0 sourceFile: test - begin: 2780 - end: 2786 + begin: 2799 + end: 2805 } annotation: { path: 4 @@ -36,8 +36,8 @@ path: 2 path: 0 sourceFile: test - begin: 2859 - end: 2868 + begin: 2878 + end: 2887 } annotation: { path: 4 @@ -45,8 +45,8 @@ path: 2 path: 0 sourceFile: test - begin: 2911 - end: 2922 + begin: 2930 + end: 2941 } annotation: { path: 4 @@ -54,8 +54,8 @@ path: 2 path: 1 sourceFile: test - begin: 2980 - end: 2984 + begin: 2999 + end: 3003 } annotation: { path: 4 @@ -63,8 +63,8 @@ path: 2 path: 1 sourceFile: test - begin: 3026 - end: 3030 + begin: 3045 + end: 3049 } annotation: { path: 4 @@ -72,8 +72,8 @@ path: 2 path: 1 sourceFile: test - begin: 3105 - end: 3112 + begin: 3124 + end: 3131 } annotation: { path: 4 @@ -81,8 +81,8 @@ path: 2 path: 1 sourceFile: test - begin: 3155 - end: 3164 + begin: 3174 + end: 3183 } annotation: { path: 4 @@ -90,8 +90,8 @@ path: 2 path: 2 sourceFile: test - begin: 3225 - end: 3229 + begin: 3244 + end: 3248 } annotation: { path: 4 @@ -99,8 +99,8 @@ path: 2 path: 2 sourceFile: test - begin: 3276 - end: 3280 + begin: 3295 + end: 3299 } annotation: { path: 4 @@ -108,8 +108,8 @@ path: 2 path: 2 sourceFile: test - begin: 3353 - end: 3360 + begin: 3372 + end: 3379 } annotation: { path: 4 @@ -117,6 +117,6 @@ path: 2 path: 2 sourceFile: test - begin: 3403 - end: 3412 + begin: 3422 + end: 3431 }
diff --git a/protoc_plugin/test/goldens/oneMessage.pbjson b/protoc_plugin/test/goldens/oneMessage.pbjson index 2ee61f2..1bf29b9 100644 --- a/protoc_plugin/test/goldens/oneMessage.pbjson +++ b/protoc_plugin/test/goldens/oneMessage.pbjson
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core; import 'dart:convert' as $convert;
diff --git a/protoc_plugin/test/goldens/service.pb b/protoc_plugin/test/goldens/service.pb index 562d64f..ef803ec 100644 --- a/protoc_plugin/test/goldens/service.pb +++ b/protoc_plugin/test/goldens/service.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:async' as $async; import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/service.pbserver b/protoc_plugin/test/goldens/service.pbserver index 56ea3aa..51dad74 100644 --- a/protoc_plugin/test/goldens/service.pbserver +++ b/protoc_plugin/test/goldens/service.pbserver
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:async' as $async;
diff --git a/protoc_plugin/test/goldens/serviceGenerator.pb.json b/protoc_plugin/test/goldens/serviceGenerator.pb.json index ad1b9e2..419d00e 100644 --- a/protoc_plugin/test/goldens/serviceGenerator.pb.json +++ b/protoc_plugin/test/goldens/serviceGenerator.pb.json
@@ -3,7 +3,7 @@ // source: testpkg.proto // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core; import 'dart:convert' as $convert;
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pb b/protoc_plugin/test/goldens/topLevelEnum.pb index 2a5f821..d82fcc5 100644 --- a/protoc_plugin/test/goldens/topLevelEnum.pb +++ b/protoc_plugin/test/goldens/topLevelEnum.pb
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbenum b/protoc_plugin/test/goldens/topLevelEnum.pbenum index ec6cf92..326cbe0 100644 --- a/protoc_plugin/test/goldens/topLevelEnum.pbenum +++ b/protoc_plugin/test/goldens/topLevelEnum.pbenum
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name // ignore_for_file: UNDEFINED_SHOWN_NAME import 'dart:core' as $core;
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta b/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta index ed85783..92298cb 100644 --- a/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta +++ b/protoc_plugin/test/goldens/topLevelEnum.pbenum.meta
@@ -2,8 +2,8 @@ path: 5 path: 0 sourceFile: test - begin: 460 - end: 469 + begin: 479 + end: 488 } annotation: { path: 5 @@ -11,8 +11,8 @@ path: 2 path: 0 sourceFile: test - begin: 522 - end: 528 + begin: 541 + end: 547 } annotation: { path: 5 @@ -20,8 +20,8 @@ path: 2 path: 1 sourceFile: test - begin: 650 - end: 654 + begin: 669 + end: 673 } annotation: { path: 5 @@ -29,8 +29,8 @@ path: 2 path: 2 sourceFile: test - begin: 774 - end: 778 + begin: 793 + end: 797 } annotation: { path: 5 @@ -38,6 +38,6 @@ path: 2 path: 3 sourceFile: test - begin: 899 - end: 907 + begin: 918 + end: 926 }
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbjson b/protoc_plugin/test/goldens/topLevelEnum.pbjson index 5ade8bc..f00b03d 100644 --- a/protoc_plugin/test/goldens/topLevelEnum.pbjson +++ b/protoc_plugin/test/goldens/topLevelEnum.pbjson
@@ -3,7 +3,7 @@ // source: test // // @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name import 'dart:core' as $core; import 'dart:convert' as $convert;
diff --git a/protoc_plugin/test/json_test.dart b/protoc_plugin/test/json_test.dart index 15c9326..8e5f6f1 100755 --- a/protoc_plugin/test/json_test.dart +++ b/protoc_plugin/test/json_test.dart
@@ -14,19 +14,19 @@ void main() { final testAllJsonTypes = '{"1":101,"2":"102","3":103,"4":"104",' - '"5":105,"6":"106","7":107,"8":"108","9":109,"10":"110","11":111.0,' - '"12":112.0,"13":true,"14":"115","15":"MTE2","16":{"17":117},' + '"5":105,"6":"106","7":107,"8":"108","9":109,"10":"110","11":111,' + '"12":112,"13":true,"14":"115","15":"MTE2","16":{"17":117},' '"18":{"1":118},"19":{"1":119},"20":{"1":120},"21":3,"22":6,"23":9,' '"24":"124","25":"125","31":[201,301],"32":["202","302"],' '"33":[203,303],"34":["204","304"],"35":[205,305],"36":["206","306"],' '"37":[207,307],"38":["208","308"],"39":[209,309],"40":["210","310"],' - '"41":[211.0,311.0],"42":[212.0,312.0],"43":[true,false],' + '"41":[211,311],"42":[212,312],"43":[true,false],' '"44":["215","315"],"45":["MjE2","MzE2"],"46":[{"47":217},{"47":317}],' '"48":[{"1":218},{"1":318}],"49":[{"1":219},{"1":319}],' '"50":[{"1":220},{"1":320}],"51":[2,3],"52":[5,6],"53":[8,9],' '"54":["224","324"],"55":["225","325"],"61":401,"62":"402","63":403,' '"64":"404","65":405,"66":"406","67":407,"68":"408","69":409,' - '"70":"410","71":411.0,"72":412.0,"73":false,"74":"415","75":"NDE2",' + '"70":"410","71":411,"72":412,"73":false,"74":"415","75":"NDE2",' '"81":1,"82":4,"83":7,"84":"424","85":"425"}'; // Checks that message once serialized to JSON @@ -128,6 +128,37 @@ expect(parsed, expected); }); + group('testConvertDouble', () { + test('WithDecimal', () { + final json = '{"12":1.2}'; + TestAllTypes proto = TestAllTypes()..optionalDouble = 1.2; + expect(TestAllTypes.fromJson(json), proto); + expect(proto.writeToJson(), json); + }); + + test('WholeNumber', () { + final json = '{"12":5}'; + TestAllTypes proto = TestAllTypes()..optionalDouble = 5.0; + expect(TestAllTypes.fromJson(json), proto); + expect(proto.writeToJson(), json); + }); + + test('Infinity', () { + final json = '{"12":"Infinity"}'; + TestAllTypes proto = TestAllTypes()..optionalDouble = double.infinity; + expect(TestAllTypes.fromJson(json), proto); + expect(proto.writeToJson(), json); + }); + + test('NegativeInfinity', () { + final json = '{"12":"-Infinity"}'; + TestAllTypes proto = TestAllTypes() + ..optionalDouble = double.negativeInfinity; + expect(TestAllTypes.fromJson(json), proto); + expect(proto.writeToJson(), json); + }); + }); + test('testParseUnsignedLegacy', () { var parsed = TestAllTypes.fromJson( '{"4":"-1152921500311945216","8":"-1152921500311945215"}');
diff --git a/protoc_plugin/test/map_field_test.dart b/protoc_plugin/test/map_field_test.dart index 75f1fbd..eae4cfb 100644 --- a/protoc_plugin/test/map_field_test.dart +++ b/protoc_plugin/test/map_field_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'dart:convert'; import 'package:protobuf/protobuf.dart'; @@ -83,9 +81,9 @@ expect(testMap.int32ToEnumField[2], TestMap_EnumValue.BAR); expect(testMap.int32ToEnumField[3], TestMap_EnumValue.BAZ); - expect(testMap.int32ToMessageField[1].value, 11); - expect(testMap.int32ToMessageField[2].value, 22); - expect(testMap.int32ToMessageField[3].value, 33); + expect(testMap.int32ToMessageField[1]!.value, 11); + expect(testMap.int32ToMessageField[2]!.value, 22); + expect(testMap.int32ToMessageField[3]!.value, 33); expect(testMap.stringToInt32Field['1'], 11); expect(testMap.stringToInt32Field['2'], 22); @@ -114,9 +112,9 @@ expect(testMap.int32ToEnumField[4], TestMap_EnumValue.ZOP); expect(testMap.int32ToMessageField.length, 3); - expect(testMap.int32ToMessageField[1].value, 111); - expect(testMap.int32ToMessageField[3].value, 33); - expect(testMap.int32ToMessageField[4].value, 44); + expect(testMap.int32ToMessageField[1]!.value, 111); + expect(testMap.int32ToMessageField[3]!.value, 33); + expect(testMap.int32ToMessageField[4]!.value, 44); expect(testMap.stringToInt32Field.length, 3); expect(testMap.stringToInt32Field['1'], 111); @@ -142,45 +140,6 @@ _expectMapValuesUpdated(testMap); }); - test('null keys and value are not allowed', () { - var testMap = TestMap(); - - try { - testMap.stringToInt32Field[null] = 1; - fail('Should have thrown an exception.'); - } on ArgumentError catch (e) { - expect(e.message, "Can't add a null to a map field"); - } - - try { - testMap.int32ToBytesField[1] = null; - fail('Should have thrown an exception.'); - } on ArgumentError catch (e) { - expect(e.message, "Can't add a null to a map field"); - } - - try { - testMap.int32ToStringField[1] = null; - fail('Should have thrown an exception.'); - } on ArgumentError catch (e) { - expect(e.message, "Can't add a null to a map field"); - } - - try { - testMap.int32ToEnumField[1] = null; - fail('Should have thrown an exception.'); - } on ArgumentError catch (e) { - expect(e.message, "Can't add a null to a map field"); - } - - try { - testMap.int32ToMessageField[1] = null; - fail('Should have thrown an exception.'); - } on ArgumentError catch (e) { - expect(e.message, "Can't add a null to a map field"); - } - }); - test('Serialize and parse map', () { var testMap = TestMap(); _setValues(testMap); @@ -255,9 +214,9 @@ ..int32ToMessageField[1] = (TestMap_MessageValue()..secondValue = 43); testMap.mergeFromMessage(other); - expect(testMap.int32ToMessageField[1].value, 0); - expect(testMap.int32ToMessageField[1].secondValue, 43); - expect(testMap.int32ToMessageField[2].value, 44); + expect(testMap.int32ToMessageField[1]!.value, 0); + expect(testMap.int32ToMessageField[1]!.secondValue, 43); + expect(testMap.int32ToMessageField[2]!.value, 44); }); test('parse duplicate keys', () { @@ -286,12 +245,12 @@ test('retain explicit default values of sub-messages', () { var testMap = TestMap()..int32ToMessageField[1] = TestMap_MessageValue(); - expect(testMap.int32ToMessageField[1].secondValue, 42); + expect(testMap.int32ToMessageField[1]!.secondValue, 42); var testMap2 = TestMap()..int32ToMessageField[2] = TestMap_MessageValue(); testMap.mergeFromBuffer(testMap2.writeToBuffer()); - expect(testMap.int32ToMessageField[2].secondValue, 42); + expect(testMap.int32ToMessageField[2]!.secondValue, 42); }); test('Freeze message with map field', () { @@ -301,7 +260,7 @@ expect(() => _updateValues(testMap), throwsA(const TypeMatcher<UnsupportedError>())); - expect(() => testMap.int32ToMessageField[1].value = 42, + expect(() => testMap.int32ToMessageField[1]!.value = 42, throwsA(const TypeMatcher<UnsupportedError>())); expect(() => testMap.int32ToStringField.remove(1), throwsA(const TypeMatcher<UnsupportedError>())); @@ -315,8 +274,8 @@ testMap.int32ToMessageField[2] = (TestMap_MessageValue()..secondValue = 12); void testValues(TestMap candidate) { - final message1 = candidate.int32ToMessageField[1]; - final message2 = candidate.int32ToMessageField[2]; + final message1 = candidate.int32ToMessageField[1]!; + final message2 = candidate.int32ToMessageField[2]!; expect(message1.hasValue(), true); expect(message1.value, 11); @@ -342,7 +301,7 @@ expect(value is Map<int, List<int>>, true); }); - test('named optional arguments in cosntructor', () { + test('named optional arguments in constructor', () { final testMap = TestMap( int32ToInt32Field: {1: 11, 2: 22, 3: 33}, int32ToStringField: {1: '11', 2: '22', 3: '33'}, @@ -365,4 +324,36 @@ ); _expectMapValuesSet(testMap); }); + + test('Parses null keys and values', () { + // Use a desugared version of the message to create missing + // values in the serialized form. + final d = Desugared(int32ToStringField: [ + Desugared_Int32ToString(key: null, value: 'abc'), + Desugared_Int32ToString(key: 42, value: null), + Desugared_Int32ToString(key: 11, value: 'def'), + ], stringToInt32Field: [ + Desugared_StringToInt32(key: null, value: 11), + Desugared_StringToInt32(key: 'abc', value: null), + Desugared_StringToInt32(key: 'def', value: 42), + ]); + + final m = TestMap.fromBuffer(d.writeToBuffer()); + expect(m.int32ToStringField[0], 'abc'); + expect(m.int32ToStringField[42], ''); + expect(m.int32ToStringField[11], 'def'); + expect(m.stringToInt32Field['abc'], 0); + expect(m.stringToInt32Field[''], 11); + expect(m.stringToInt32Field['def'], 42); + }); + + test('Map field reads should not affect equality or hash of message', () { + final m1 = TestMap.create(); + final m2 = TestMap.create(); + expect(m1, equals(m2)); + expect(m1.hashCode, equals(m2.hashCode)); + m1.int32ToStringField; // read a map field + expect(m1, equals(m2)); + expect(m1.hashCode, equals(m2.hashCode)); + }); }
diff --git a/protoc_plugin/test/message_generator_test.dart b/protoc_plugin/test/message_generator_test.dart index 1cf2c4a..e8b6d2e 100755 --- a/protoc_plugin/test/message_generator_test.dart +++ b/protoc_plugin/test/message_generator_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'dart:collection'; import 'package:collection/collection.dart'; @@ -19,9 +17,9 @@ import 'golden_file.dart'; void main() { - FileDescriptorProto fd; + late FileDescriptorProto fd; EnumDescriptorProto ed; - DescriptorProto md; + late DescriptorProto md; setUp(() async { fd = FileDescriptorProto(); ed = EnumDescriptorProto() @@ -76,11 +74,12 @@ ..enumType.add(ed); }); test('testMessageGenerator', () { - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; - var fg = FileGenerator(fd, options); - var mg = MessageGenerator.topLevel(md, fg, {}, null, <String>{}, 0); + FileGenerator fg = FileGenerator(fd, options); + MessageGenerator mg = + MessageGenerator.topLevel(md, fg, {}, null, <String>{}, 0); var ctx = GenerationContext(options); mg.register(ctx); @@ -101,10 +100,11 @@ }); test('testMetadataIndices', () { - var options = - parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse()); - var fg = FileGenerator(fd, options); - var mg = MessageGenerator.topLevel(md, fg, {}, null, <String>{}, 0); + var options = parseGenerationOptions( + CodeGeneratorRequest(), CodeGeneratorResponse())!; + FileGenerator fg = FileGenerator(fd, options); + MessageGenerator mg = + MessageGenerator.topLevel(md, fg, {}, null, <String>{}, 0); var ctx = GenerationContext(options); mg.register(ctx);
diff --git a/protoc_plugin/test/mirror_util.dart b/protoc_plugin/test/mirror_util.dart index 959a4f5..70a7487 100644 --- a/protoc_plugin/test/mirror_util.dart +++ b/protoc_plugin/test/mirror_util.dart
@@ -4,8 +4,8 @@ import 'dart:mirrors'; -/// Returns the names of the public properties and methods on a class. -/// (Also visits its superclasses, recursively.) +/// Returns the names of the public properties and non-static methods of a +/// class. Also visits its superclasses, recursively. Set<String> findMemberNames(String importName, Symbol classSymbol) { var lib = currentMirrorSystem().libraries[Uri.parse(importName)]!; var cls = lib.declarations[classSymbol] as ClassMirror?; @@ -26,7 +26,8 @@ for (var decl in cls.declarations.values) { if (!decl.isPrivate && decl is! VariableMirror && - decl is! TypeVariableMirror) { + decl is! TypeVariableMirror && + !(decl is MethodMirror && decl.isStatic)) { result.add(chooseName(decl.simpleName)); } }
diff --git a/protoc_plugin/test/mixin_test.dart b/protoc_plugin/test/mixin_test.dart index e4b6641..16bc720 100644 --- a/protoc_plugin/test/mixin_test.dart +++ b/protoc_plugin/test/mixin_test.dart
@@ -12,8 +12,8 @@ }); test('is a Mixin1', () { - expect(proto is Mixin1, isTrue); - expect(proto is Mixin2, isFalse); + expect(proto, isA<Mixin1>()); + expect(proto, isNot(isA<Mixin2>())); }); test('implements interface defined by mixins', () { @@ -59,9 +59,9 @@ }); test('is both Mixin1 (from parent) and Mixin3', () { - expect(proto is Mixin1, isTrue); - expect(proto is Mixin2, isFalse); - expect(proto is Mixin3, isTrue); + expect(proto, isA<Mixin1>()); + expect(proto, isNot(isA<Mixin2>())); + expect(proto, isA<Mixin3>()); }); }); }
diff --git a/protoc_plugin/test/names_test.dart b/protoc_plugin/test/names_test.dart index 4e1adf3..a9ac9ce 100644 --- a/protoc_plugin/test/names_test.dart +++ b/protoc_plugin/test/names_test.dart
@@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/names.dart' as names; import 'package:protoc_plugin/src/generated/dart_options.pb.dart'; import 'package:protoc_plugin/src/generated/descriptor.pb.dart'; @@ -32,6 +30,12 @@ expect(msg.hasRenamedField(), false); }); + test('Can access a filed started with underscore and digit', () { + var msg = pb.UnderscoreDigitName(); + msg.x3d = 'one'; + expect(msg.getField(1), 'one'); + }); + test('Can swap field names using dart_name option', () { var msg = pb.SwapNames(); msg.first = 'one'; @@ -220,7 +224,7 @@ }); test('The proto name is set correctly', () { - expect(json_name.JsonNamedMessage().info_.byName['barName'].protoName, + expect(json_name.JsonNamedMessage().info_.byName['barName']!.protoName, 'foo_name'); });
diff --git a/protoc_plugin/test/omit_enum_names_test.dart b/protoc_plugin/test/omit_enum_names_test.dart index a9af671..341ba45 100644 --- a/protoc_plugin/test/omit_enum_names_test.dart +++ b/protoc_plugin/test/omit_enum_names_test.dart
@@ -16,6 +16,11 @@ const bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FOREIGN_FOO'); + expect( + ForeignEnum.FOREIGN_FOO.toString(), + const bool.fromEnvironment('protobuf.omit_enum_names') + ? '4' + : 'FOREIGN_FOO'); expect(constant(), 'SHOULD_BE_PRESENT'); }); }
diff --git a/protoc_plugin/test/omit_field_names_test.dart b/protoc_plugin/test/omit_field_names_test.dart index 3673f3a..7dba8b2 100644 --- a/protoc_plugin/test/omit_field_names_test.dart +++ b/protoc_plugin/test/omit_field_names_test.dart
@@ -12,10 +12,11 @@ Future<void> main() async { test('enum name available depending on environment', () { var proto = TestAllTypes()..optionalForeignMessage = ForeignMessage(); + expect( proto.toString(), const bool.fromEnvironment('protobuf.omit_field_names') - ? ': {\n}\n' + ? '19: {\n}\n' : 'optionalForeignMessage: {\n}\n'); expect(constant(), 'SHOULD_BE_PRESENT'); });
diff --git a/protoc_plugin/test/oneof_test.dart b/protoc_plugin/test/oneof_test.dart index de1c00a..dcd65fa 100644 --- a/protoc_plugin/test/oneof_test.dart +++ b/protoc_plugin/test/oneof_test.dart
@@ -161,11 +161,15 @@ test('copyWith preserves oneof state', () { var foo = Foo(); expectOneofNotSet(foo); - var copy1 = foo.deepCopy().freeze().rebuild((_) {}) as Foo; + // `ignore` below to work around https://github.com/dart-lang/sdk/issues/48879 + var copy1 = + foo.deepCopy().freeze().rebuild((_) {}) as Foo; // ignore: unused_result expectOneofNotSet(copy1); foo.first = 'oneof'; expectFirstSet(foo); - var copy2 = foo.deepCopy().freeze().rebuild((_) {}) as Foo; + // `ignore` below to work around https://github.com/dart-lang/sdk/issues/48879 + var copy2 = + foo.deepCopy().freeze().rebuild((_) {}) as Foo; // ignore: unused_result expectFirstSet(copy2); });
diff --git a/protoc_plugin/test/proto3_json_test.dart b/protoc_plugin/test/proto3_json_test.dart index 02fb71a..e0a2f4e 100644 --- a/protoc_plugin/test/proto3_json_test.dart +++ b/protoc_plugin/test/proto3_json_test.dart
@@ -17,6 +17,7 @@ import '../out/protos/google/protobuf/struct.pb.dart'; import '../out/protos/google/protobuf/timestamp.pb.dart'; import '../out/protos/google/protobuf/unittest.pb.dart'; +import '../out/protos/google/protobuf/unittest_nested_any.pb.dart'; import '../out/protos/google/protobuf/unittest_well_known_types.pb.dart'; import '../out/protos/google/protobuf/wrappers.pb.dart'; import '../out/protos/map_field.pb.dart'; @@ -270,6 +271,26 @@ throwsA(TypeMatcher<ArgumentError>())); }); + test('Nested Any', () { + final packedOne = Any.pack(AnyMessage1()..value = '1'); + final packedTwo = Any.pack(AnyMessage2() + ..value = '2' + ..anyField2 = packedOne); + expect( + packedTwo.toProto3Json( + typeRegistry: TypeRegistry([AnyMessage1(), AnyMessage2()])), + { + 'anyField2': { + 'value': '1', + '@type': + 'type.googleapis.com/protobuf_unittest_nested_any.AnyMessage1' + }, + 'value': '2', + '@type': + 'type.googleapis.com/protobuf_unittest_nested_any.AnyMessage2' + }); + }); + test('struct', () { final s = Struct() ..fields['null'] = (Value()..nullValue = NullValue.NULL_VALUE) @@ -775,61 +796,47 @@ ..optionalUint64 = Int64.fromBytes([255, 255, 255, 255, 255, 255, 255, 255])); - expect( - () => TestAllTypes() - ..mergeFromProto3Json({ - 'optionalUint32': '-1', - }), - parseFailure(['optionalUint32'])); + void expectRoundTrip(String typeName, int value) { + final t = TestAllTypes() + ..mergeFromProto3Json({ + typeName: value, + }); + expect(t.getField(t.getTagNumber(typeName)!), value); + final t2 = TestAllTypes() + ..mergeFromProto3Json({ + typeName: value.toString(), + }); + expect(t2.getField(t2.getTagNumber(typeName)!), value); + } - expect( - () => TestAllTypes() - ..mergeFromProto3Json({ - 'optionalUint32': -1, - }), - parseFailure(['optionalUint32'])); + void expectFailure(String typeName, int value) { + expect( + () => TestAllTypes()..mergeFromProto3Json({typeName: -2147483649}), + parseFailure([typeName])); + } - expect( - () => TestAllTypes() - ..mergeFromProto3Json({ - 'optionalUint32': 0xFFFFFFFF + 1, - }), - parseFailure(['optionalUint32'])); + void expectSigned32(String typeName) { + expectRoundTrip(typeName, 1); + expectRoundTrip(typeName, 0); + expectRoundTrip(typeName, 2147483647); + expectRoundTrip(typeName, -2147483648); + expectFailure(typeName, 2147483648); + expectFailure(typeName, -2147483649); + } - expect( - TestAllTypes() - ..mergeFromProto3Json({ - 'optionalInt32': '2147483647', - }), - TestAllTypes()..optionalInt32 = 2147483647); + void expectUnsigned32(String typeName) { + expectRoundTrip(typeName, 1); + expectRoundTrip(typeName, 0); + expectRoundTrip(typeName, 0xFFFFFFFF); + expectFailure(typeName, 0xFFFFFFFF + 1); + expectFailure(typeName, -1); + } - expect( - TestAllTypes() - ..mergeFromProto3Json({ - 'optionalInt32': '-2147483648', - }), - TestAllTypes()..optionalInt32 = -2147483648); - - expect( - () => TestAllTypes() - ..mergeFromProto3Json({ - 'optionalInt32': 2147483647 + 1, - }), - parseFailure(['optionalInt32'])); - - expect( - () => TestAllTypes() - ..mergeFromProto3Json({ - 'optionalInt32': (2147483647 + 1).toString(), - }), - parseFailure(['optionalInt32'])); - - expect( - () => TestAllTypes() - ..mergeFromProto3Json({ - 'optionalInt32': -2147483648 - 1, - }), - parseFailure(['optionalInt32'])); + expectUnsigned32('optionalFixed32'); + expectUnsigned32('optionalUint32'); + expectSigned32('optionalInt32'); + expectSigned32('optionalSfixed32'); + expectSigned32('optionalSint32'); }); test('unknown fields', () { @@ -852,6 +859,7 @@ expect(t, TestAllTypes()); expect(t.unknownFields.isEmpty, isTrue); }); + test('Any', () { final m1 = Any() ..mergeFromProto3Json({ @@ -929,6 +937,28 @@ parseFailure([])); }); + test('Nested Any', () { + final m1 = Any() + ..mergeFromProto3Json({ + 'anyField2': { + 'value': '1', + '@type': + 'type.googleapis.com/protobuf_unittest_nested_any.AnyMessage1' + }, + 'value': '2', + '@type': + 'type.googleapis.com/protobuf_unittest_nested_any.AnyMessage2' + }, typeRegistry: TypeRegistry([AnyMessage1(), AnyMessage2()])); + + expect( + m1 + .unpackInto(AnyMessage2()) + .anyField2 + .unpackInto(AnyMessage1()) + .value, + '1'); + }); + test('Duration', () { expect( Duration()..mergeFromProto3Json('0s'), @@ -1214,4 +1244,35 @@ expectSecondSet(Foo()..mergeFromProto3Json({'second': 1})); expectOneofNotSet(Foo()..mergeFromProto3Json({})); }); + + group('Convert Double', () { + test('With Decimal', () { + final json = {'optionalDouble': 1.2}; + TestAllTypes proto = TestAllTypes()..optionalDouble = 1.2; + expect(TestAllTypes()..mergeFromProto3Json(json), proto); + expect(proto.toProto3Json(), json); + }); + + test('Whole Number', () { + final json = {'optionalDouble': 5}; + TestAllTypes proto = TestAllTypes()..optionalDouble = 5.0; + expect(TestAllTypes()..mergeFromProto3Json(json), proto); + expect(proto.toProto3Json(), json); + }); + + test('Infinity', () { + final json = {'optionalDouble': 'Infinity'}; + TestAllTypes proto = TestAllTypes()..optionalDouble = double.infinity; + expect(TestAllTypes()..mergeFromProto3Json(json), proto); + expect(proto.toProto3Json(), json); + }); + + test('Negative Infinity', () { + final json = {'optionalDouble': '-Infinity'}; + TestAllTypes proto = TestAllTypes() + ..optionalDouble = double.negativeInfinity; + expect(TestAllTypes()..mergeFromProto3Json(json), proto); + expect(proto.toProto3Json(), json); + }); + }); }
diff --git a/protoc_plugin/test/protoc_options_test.dart b/protoc_plugin/test/protoc_options_test.dart index f463b94..f197efb 100644 --- a/protoc_plugin/test/protoc_options_test.dart +++ b/protoc_plugin/test/protoc_options_test.dart
@@ -3,15 +3,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/src/generated/plugin.pb.dart'; import 'package:protoc_plugin/src/options.dart'; import 'package:test/test.dart'; void main() { test('testValidGeneratorOptions', () { - void checkValid(String parameter) { + void checkValid(String? parameter) { var request = CodeGeneratorRequest(); if (parameter != null) request.parameter = parameter; var response = CodeGeneratorResponse(); @@ -28,9 +26,9 @@ }); test('testInvalidGeneratorOptions', () { - void checkInvalid(String parameter) { + checkInvalid(String parameter) { var request = CodeGeneratorRequest(); - if (parameter != null) request.parameter = parameter; + request.parameter = parameter; var response = CodeGeneratorResponse(); var options = parseGenerationOptions(request, response); expect(options, isNull);
diff --git a/protoc_plugin/test/protos/bytes.proto b/protoc_plugin/test/protos/bytes.proto new file mode 100644 index 0000000..4ba43f3 --- /dev/null +++ b/protoc_plugin/test/protos/bytes.proto
@@ -0,0 +1,6 @@ +syntax = "proto2"; + +message BytesEntity { + optional bytes value = 1; + repeated bytes values = 2; +}
diff --git a/protoc_plugin/test/protos/dart_name.proto b/protoc_plugin/test/protos/dart_name.proto index 533d43c..a09c742 100644 --- a/protoc_plugin/test/protos/dart_name.proto +++ b/protoc_plugin/test/protos/dart_name.proto
@@ -37,3 +37,7 @@ message Function_ { optional string fun1 = 1; } + +message UnderscoreDigitName { + optional string _3d = 1; +}
diff --git a/protoc_plugin/test/protos/google/protobuf/unittest_nested_any.proto b/protoc_plugin/test/protos/google/protobuf/unittest_nested_any.proto new file mode 100644 index 0000000..d929b54 --- /dev/null +++ b/protoc_plugin/test/protos/google/protobuf/unittest_nested_any.proto
@@ -0,0 +1,15 @@ +syntax = "proto3"; + +package protobuf_unittest_nested_any; + +import "google/protobuf/any.proto"; + +message AnyMessage1 { + google.protobuf.Any any_field1 = 1; + string value = 2; +} + +message AnyMessage2 { + google.protobuf.Any any_field2 = 1; + string value = 2; +}
diff --git a/protoc_plugin/test/protos/map_field.proto b/protoc_plugin/test/protos/map_field.proto index 0017d72..8236376 100644 --- a/protoc_plugin/test/protos/map_field.proto +++ b/protoc_plugin/test/protos/map_field.proto
@@ -37,3 +37,16 @@ message Outer { optional Inner i = 1; } + +message Desugared { + message Int32ToString { + optional int32 key = 1; + optional string value = 2; + } + message StringToInt32 { + optional string key = 1; + optional int32 value = 2; + } + repeated Int32ToString int32_to_string_field = 2; + repeated StringToInt32 string_to_int32_field = 6; +}
diff --git a/protoc_plugin/test/protos/proto2_repeated.proto b/protoc_plugin/test/protos/proto2_repeated.proto new file mode 100644 index 0000000..ee3b156 --- /dev/null +++ b/protoc_plugin/test/protos/proto2_repeated.proto
@@ -0,0 +1,11 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +syntax = "proto2"; + +message Proto2Repeated { + repeated int32 ints_default = 1; + repeated int32 ints_packed = 2 [packed=true]; + repeated int32 ints_not_packed = 3 [packed=false]; +}
diff --git a/protoc_plugin/test/protos/proto3_repeated.proto b/protoc_plugin/test/protos/proto3_repeated.proto new file mode 100644 index 0000000..723d154 --- /dev/null +++ b/protoc_plugin/test/protos/proto3_repeated.proto
@@ -0,0 +1,11 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +syntax = "proto3"; + +message Proto3Repeated { + repeated int32 ints_default = 1; + repeated int32 ints_packed = 2 [packed=true]; + repeated int32 ints_not_packed = 3 [packed=false]; +}
diff --git a/protoc_plugin/test/repeated_encoding_test.dart b/protoc_plugin/test/repeated_encoding_test.dart new file mode 100644 index 0000000..17a990a --- /dev/null +++ b/protoc_plugin/test/repeated_encoding_test.dart
@@ -0,0 +1,50 @@ +#!/usr/bin/env dart +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; + +import '../out/protos/proto2_repeated.pb.dart'; +import '../out/protos/proto3_repeated.pb.dart'; + +void main() { + test('check proto2 and proto3 repeated field encodings', () { + final proto2 = Proto2Repeated( + intsDefault: [1, 2], intsPacked: [1, 2], intsNotPacked: [1, 2]); + final proto2Encoded = proto2.writeToBuffer(); + expect( + proto2Encoded.toList(), + equals([ + 8, // field = 1, type = varint + 1, // value = 1 + 8, // field = 1, type = varint + 2, // value = 2 + 18, // field = 2, type = length delimited + 2, // length = 2 + 1, 2, // values = [1, 2] + 24, // field = 3, type = varint + 1, // value = 1 + 24, // field = 3, type = varint + 2, // value = 2 + ])); + + final proto3 = Proto3Repeated( + intsDefault: [1, 2], intsPacked: [1, 2], intsNotPacked: [1, 2]); + final proto3Encoded = proto3.writeToBuffer(); + expect( + proto3Encoded.toList(), + equals([ + 10, // field = 1, type = length delimited + 2, // length = 2 + 1, 2, // values = [1, 2] + 18, // field = 2, type = length delimited + 2, // length = 2 + 1, 2, // values = [1, 2] + 24, // field = 3, type = varint + 1, // value = 1 + 24, // field = 3, type = varint + 2, // value = 2 + ])); + }); +}
diff --git a/protoc_plugin/test/repeated_field_test.dart b/protoc_plugin/test/repeated_field_test.dart index 2683745..d62ccf4 100644 --- a/protoc_plugin/test/repeated_field_test.dart +++ b/protoc_plugin/test/repeated_field_test.dart
@@ -32,4 +32,16 @@ .check, isNotNull); }); + + test('check read-only default list type', () { + final msg = TestAllTypes()..freeze(); + final list = msg.repeatedInt32; + expect( + list.firstWhere( + (_msg) => false, + orElse: () => 123, + ), + 123, + ); + }); }
diff --git a/protoc_plugin/test/reserved_names_test.dart b/protoc_plugin/test/reserved_names_test.dart index dbac073..43c9eff 100755 --- a/protoc_plugin/test/reserved_names_test.dart +++ b/protoc_plugin/test/reserved_names_test.dart
@@ -22,13 +22,26 @@ import 'mirror_util.dart' show findMemberNames; +// These names are no longer reserved but we keep them in +// `GeneratedMessage_reservedNames` to keep generated code backwards +// compatible. Remove in next major release. +const List<String> oldGeneratedMessageReservedNames = [ + 'fromBuffer', + 'fromJson', + r'$_defaultFor', +]; + +// These names are no longer reserved but we keep them in +// `ProtobufEnum_reservedNames` to keep generated code backwards compatible. +// Remove in next major release. +const List<String> oldProtobufEnumReservedNames = ['initByValue']; + void main() { test('GeneratedMessage reserved names are up to date', () { var actual = Set<String>.from(GeneratedMessage_reservedNames); var expected = findMemberNames('package:protobuf/protobuf.dart', #GeneratedMessage) - // TODO: see https://github.com/google/protobuf.dart/issues/527 - ..removeAll(_oneOffNames); + ..addAll(oldGeneratedMessageReservedNames); expect(actual.toList()..sort(), equals(expected.toList()..sort())); }); @@ -37,17 +50,14 @@ var actual = Set<String>.from(ProtobufEnum_reservedNames); var expected = findMemberNames('package:protobuf/protobuf.dart', #ProtobufEnum) - // TODO: see https://github.com/google/protobuf.dart/issues/527 - ..removeAll(_oneOffNames); + ..addAll(oldProtobufEnumReservedNames); expect(actual.toList()..sort(), equals(expected.toList()..sort())); }); test("ReadonlyMessageMixin doesn't add any reserved names", () { - var mixinNames = - findMemberNames('package:protobuf/protobuf.dart', #ReadonlyMessageMixin) - // TODO: see https://github.com/google/protobuf.dart/issues/527 - ..removeAll(_oneOffNames); + var mixinNames = findMemberNames( + 'package:protobuf/protobuf.dart', #ReadonlyMessageMixin); var reservedNames = Set<String>.from(GeneratedMessage_reservedNames); for (var name in mixinNames) { if (name == 'ReadonlyMessageMixin' || name == 'unknownFields') continue; @@ -63,9 +73,7 @@ var expected = findMemberNames(meta.importFrom, #PbMapMixin) ..addAll(findMemberNames('dart:collection', #MapMixin)) - ..removeAll(GeneratedMessage_reservedNames) - // TODO: see https://github.com/google/protobuf.dart/issues/527 - ..removeAll(_oneOffNames); + ..removeAll(GeneratedMessage_reservedNames); expect( actual.toList()..sort(), containsAllInOrder(expected.toList()..sort())); @@ -76,17 +84,8 @@ var actual = Set<String>.from(meta.findReservedNames()); var expected = findMemberNames(meta.importFrom, #PbEventMixin) - ..removeAll(GeneratedMessage_reservedNames) - // TODO: see https://github.com/google/protobuf.dart/issues/527 - ..removeAll(_oneOffNames); + ..removeAll(GeneratedMessage_reservedNames); expect(actual.toList()..sort(), equals(expected.toList()..sort())); }); } - -// See https://github.com/google/protobuf.dart/issues/527 -const _oneOffNames = { - 'hash', - 'hashAll', - 'hashAllUnordered', -};
diff --git a/protoc_plugin/test/service_generator_test.dart b/protoc_plugin/test/service_generator_test.dart index 5dc0214..388a78a 100644 --- a/protoc_plugin/test/service_generator_test.dart +++ b/protoc_plugin/test/service_generator_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:protoc_plugin/indenting_writer.dart'; import 'package:protoc_plugin/protoc.dart'; import 'package:protoc_plugin/src/linker.dart';
diff --git a/protoc_plugin/test/timestamp_test.dart b/protoc_plugin/test/timestamp_test.dart index 5d02e21..6203139 100644 --- a/protoc_plugin/test/timestamp_test.dart +++ b/protoc_plugin/test/timestamp_test.dart
@@ -23,6 +23,17 @@ expect(fromProto, dateTime); }); + test('negative Timestamp', () { + final secondBeforeEpoch = Timestamp(seconds: Int64(-1), nanos: 1000000); + var dateTime = DateTime.fromMillisecondsSinceEpoch(-999, isUtc: true); + + expect(secondBeforeEpoch.toDateTime().millisecondsSinceEpoch, + dateTime.millisecondsSinceEpoch); + expect(secondBeforeEpoch.toDateTime(), dateTime); + expect(Timestamp.fromDateTime(dateTime).nanos, 1000000); + expect(Timestamp.fromDateTime(dateTime).seconds, Int64(-1)); + }); + test('local datetime -> timestamp -> datetime', () { var dateTime = DateTime(2019, 02, 15, 10, 21, 25, 5, 5); var fromProto = Timestamp.fromDateTime(dateTime).toDateTime();
diff --git a/protoc_plugin/test/unknown_field_set_test.dart b/protoc_plugin/test/unknown_field_set_test.dart index e8b36b6..7ca5efd 100755 --- a/protoc_plugin/test/unknown_field_set_test.dart +++ b/protoc_plugin/test/unknown_field_set_test.dart
@@ -316,4 +316,13 @@ _checkNotEqual(f1, f2); }); + + test( + 'consistent hashcode for messages with no unknown fields set and an empty unknown field set', + () { + final m = TestAllExtensions(); + // Force an unknown field set. + final m2 = TestAllExtensions()..unknownFields; + expect(m.hashCode, m2.hashCode); + }); }
diff --git a/protoc_plugin/test/validate_fail_test.dart b/protoc_plugin/test/validate_fail_test.dart index 5c04584..5dde01e 100755 --- a/protoc_plugin/test/validate_fail_test.dart +++ b/protoc_plugin/test/validate_fail_test.dart
@@ -3,8 +3,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.11 - import 'package:fixnum/fixnum.dart'; import 'package:test/test.dart'; @@ -25,10 +23,6 @@ var builder = TestAllTypes(); expect(() { - builder.optionalInt32 = null; - }, throwsArgumentError); - - expect(() { builder.optionalInt32 = cast('101') as int; }, badArgument); expect(() {
diff --git a/query_benchmark/analysis_options.yaml b/query_benchmark/analysis_options.yaml new file mode 100644 index 0000000..e841247 --- /dev/null +++ b/query_benchmark/analysis_options.yaml
@@ -0,0 +1,9 @@ +include: package:lints/recommended.yaml + +linter: + rules: + - comment_references + - directives_ordering + - prefer_relative_imports + - prefer_single_quotes + - prefer_spread_collections
diff --git a/query_benchmark/bin/set_nested_value.dart b/query_benchmark/bin/set_nested_value.dart index 6df654f..0b7afb6 100644 --- a/query_benchmark/bin/set_nested_value.dart +++ b/query_benchmark/bin/set_nested_value.dart
@@ -20,7 +20,7 @@ title: 'protobuf_decode', duration: measure(() => a.rebuild((f0.A0 a0Builder) { a0Builder.a4.last = a0Builder.a4.last.rebuild((f2.A1 a1builder) { - a1builder.a378.rebuild( + a1builder.a378 = a1builder.a378.rebuild( (f19.A220 a220builder) => a220builder.a234 = 'new_value'); }); })),
diff --git a/query_benchmark/mono_pkg.yaml b/query_benchmark/mono_pkg.yaml index e822136..b23af8b 100644 --- a/query_benchmark/mono_pkg.yaml +++ b/query_benchmark/mono_pkg.yaml
@@ -7,4 +7,4 @@ - command: ./../tool/setup.sh - command: ./compile_protos.sh - analyze: --fatal-infos - dart: dev + sdk: dev
diff --git a/query_benchmark/pubspec.yaml b/query_benchmark/pubspec.yaml index f264e55..1b4d85d 100644 --- a/query_benchmark/pubspec.yaml +++ b/query_benchmark/pubspec.yaml
@@ -5,13 +5,17 @@ name: query_benchmark description: Measuring encoding and decoding of a "real-world" protobuf. +# This package is not intended for consumption on pub.dev. DO NOT publish. +publish_to: none + environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: - protobuf: + protobuf: any dev_dependencies: + lints: ^1.0.0 protoc_plugin: path: "../protoc_plugin"
diff --git a/tool/ci.sh b/tool/ci.sh index c323e5c..3251acc 100755 --- a/tool/ci.sh +++ b/tool/ci.sh
@@ -1,5 +1,5 @@ #!/bin/bash -# Created with package:mono_repo v5.0.1 +# Created with package:mono_repo v6.2.0 # Support built in commands on windows out of the box. # When it is a flutter repo (check the pubspec.yaml for "sdk: flutter")