Repository: googleapis/google-cloud-rust
Pull request #1454: feat(generator/dart): implement general json encoding and decoding
Author: login: devoncarew
Created: 2025-03-10T19:53:45Z | Merged: 2025-03-16T18:57:42Z

This implements general json encoding and decoding for the Dart backend,and fleshes out enough of the client impl. to allow us to do a full end-to-end call with the `google/cloud/language/v2` API - `LanguageService.analyzeSentiment()`.

This PR is a bit big; I was working locally towards being able to make an end-to-end call. I'm happy to convert this to a draft PR and pull separate pieces out for easier review.

- add general `toJson()` and `fromJson()` calls to messages
- create a new (hand-written) google_cloud_common package to contain code common to all the generated clients (http client code and json encoding utilities)
- contribute an end-to-end example in `google_cloud_language/example`
- implement round-tripping json encoding and decoding tests in `google_cloud_rpc/test/json_test.dart`
- generate `Any` and `Timestamp` in order to get correct analysis of the rest of the generated code; note that these implementations do not yet support their custom json formats

Also note that this PR does not change the nullability of message fields (i.e., it does not yet implement the implicit / explicit presence semantics of proto3).

cc @coryan 



Diff:
diff --git a/generator/dart/packages/generated/google_cloud_language/.sidekick.toml b/generator/dart/packages/generated/google_cloud_language/.sidekick.toml
new file mode 100644
index 0000000000..b2e80231b6
--- /dev/null
+++ b/generator/dart/packages/generated/google_cloud_language/.sidekick.toml
@@ -0,0 +1,20 @@
+# Copyright 2025 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[general]
+specification-source = 'google/cloud/language/v2'
+service-config = 'google/cloud/language/v2/language_v2.yaml'
+
+[codec]
+copyright-year = '2025'
diff --git a/generator/dart/packages/generated/google_cloud_language/README.md b/generator/dart/packages/generated/google_cloud_language/README.md
new file mode 100755
index 0000000000..6a699221f6
--- /dev/null
+++ b/generator/dart/packages/generated/google_cloud_language/README.md
@@ -0,0 +1,24 @@
+## Cloud Natural Language API
+
+The Google Cloud client library for the Cloud Natural Language API.
+
+<!-- Code generated by sidekick. DO NOT EDIT. -->
+
+> [!CAUTION]
+> This package is under active development! We expect multiple breaking changes
+> in upcoming releases. Testing is also incomplete; we do **not** recommend that
+> you use this package in production.
+
+We welcome feedback about the APIs, documentation, missing features, bugs, etc.
+
+## What's this?
+
+Provides natural language understanding technologies, such as sentiment
+analysis, entity recognition, entity sentiment analysis, and other text
+annotations, to developers.
+
+## Quickstart
+
+The main types for this package are:
+
+- LanguageService
diff --git a/generator/dart/packages/generated/google_cloud_language/lib/language.dart b/generator/dart/packages/generated/google_cloud_language/lib/language.dart
new file mode 100755
index 0000000000..da3f8bcf60
--- /dev/null
+++ b/generator/dart/packages/generated/google_cloud_language/lib/language.dart
@@ -0,0 +1,1129 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Code generated by sidekick. DO NOT EDIT.
+
+/// The Google Cloud client for the Cloud Natural Language API.
+///
+/// Provides natural language understanding technologies, such as sentiment
+/// analysis, entity recognition, entity sentiment analysis, and other text
+/// annotations, to developers.
+library;
+
+import 'package:google_cloud_common/common.dart';
+
+/// Provides text analysis operations such as sentiment analysis and entity
+/// recognition.
+class LanguageService extends CloudService {
+  static const String host = 'language.googleapis.com';
+
+  LanguageService({required super.client});
+
+  /// Analyzes the sentiment of the provided text.
+  Future<AnalyzeSentimentResponse> analyzeSentiment(AnalyzeSentimentRequest request) async {
+    final url = Uri.https(host, '/v2/documents:analyzeSentiment');
+    final response = await $post(url, body: request);
+    return AnalyzeSentimentResponse.fromJson(response);
+  }
+
+  /// Finds named entities (currently proper names and common nouns) in the text
+  /// along with entity types, probability, mentions for each entity, and
+  /// other properties.
+  Future<AnalyzeEntitiesResponse> analyzeEntities(AnalyzeEntitiesRequest request) async {
+    final url = Uri.https(host, '/v2/documents:analyzeEntities');
+    final response = await $post(url, body: request);
+    return AnalyzeEntitiesResponse.fromJson(response);
+  }
+
+  /// Classifies a document into categories.
+  Future<ClassifyTextResponse> classifyText(ClassifyTextRequest request) async {
+    final url = Uri.https(host, '/v2/documents:classifyText');
+    final response = await $post(url, body: request);
+    return ClassifyTextResponse.fromJson(response);
+  }
+
+  /// Moderates a document for harmful and sensitive categories.
+  Future<ModerateTextResponse> moderateText(ModerateTextRequest request) async {
+    final url = Uri.https(host, '/v2/documents:moderateText');
+    final response = await $post(url, body: request);
+    return ModerateTextResponse.fromJson(response);
+  }
+
+  /// A convenience method that provides all features in one call.
+  Future<AnnotateTextResponse> annotateText(AnnotateTextRequest request) async {
+    final url = Uri.https(host, '/v2/documents:annotateText');
+    final response = await $post(url, body: request);
+    return AnnotateTextResponse.fromJson(response);
+  }
+}
+
+/// Represents the input to API methods.
+class Document extends Message {
+  /// Required. If the type is not set or is `TYPE_UNSPECIFIED`,
+  /// returns an `INVALID_ARGUMENT` error.
+  final Document$Type? type;
+
+  /// The content of the input in string format.
+  /// Cloud audit logging exempt since it is based on user data.
+  final String? content;
+
+  /// The Google Cloud Storage URI where the file content is located.
+  /// This URI must be of the form: gs://bucket_name/object_name. For more
+  /// details, see https://cloud.google.com/storage/docs/reference-uris.
+  /// NOTE: Cloud Storage object versioning is not supported.
+  final String? gcsContentUri;
+
+  /// Optional. The language of the document (if not specified, the language is
+  /// automatically detected). Both ISO and BCP-47 language codes are
+  /// accepted.<br>
+  /// [Language
+  /// Support](https://cloud.google.com/natural-language/docs/languages) lists
+  /// currently supported languages for each API method. If the language (either
+  /// specified by the caller or automatically detected) is not supported by the
+  /// called API method, an `INVALID_ARGUMENT` error is returned.
+  final String? languageCode;
+
+  Document({
+    this.type,
+    this.content,
+    this.gcsContentUri,
+    this.languageCode,
+  });
+
+  factory Document.fromJson(Map<String, dynamic> json) {
+    return Document(
+      type: $decode(json['type'], Document$Type.fromJson),
+      content: json['content'],
+      gcsContentUri: json['gcsContentUri'],
+      languageCode: json['languageCode'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (type != null) 'type': type!.toJson(),
+      if (content != null) 'content': content,
+      if (gcsContentUri != null) 'gcsContentUri': gcsContentUri,
+      if (languageCode != null) 'languageCode': languageCode,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (type != null) 'type=$type',
+      if (content != null) 'content=$content',
+      if (gcsContentUri != null) 'gcsContentUri=$gcsContentUri',
+      if (languageCode != null) 'languageCode=$languageCode',
+    ].join(',');
+    return 'Document($contents)';
+  }
+}
+
+/// The document types enum.
+class Document$Type extends Enum {
+  /// The content type is not specified.
+  static const typeUnspecified = Document$Type('TYPE_UNSPECIFIED');
+
+  /// Plain text
+  static const plainText = Document$Type('PLAIN_TEXT');
+
+  /// HTML
+  static const html = Document$Type('HTML');
+
+  const Document$Type(super.value);
+
+  factory Document$Type.fromJson(String json) => Document$Type(json);
+
+  @override
+  bool operator ==(Object other) =>
+      other is Document$Type && value == other.value;
+
+  @override
+  String toString() => 'Type.$value';
+}
+
+/// Represents a sentence in the input document.
+class Sentence extends Message {
+  /// The sentence text.
+  final TextSpan? text;
+
+  /// For calls to [AnalyzeSentiment][] or if
+  /// [AnnotateTextRequest.Features.extract_document_sentiment][google.cloud.language.v2.AnnotateTextRequest.Features.extract_document_sentiment]
+  /// is set to true, this field will contain the sentiment for the sentence.
+  final Sentiment? sentiment;
+
+  Sentence({
+    this.text,
+    this.sentiment,
+  });
+
+  factory Sentence.fromJson(Map<String, dynamic> json) {
+    return Sentence(
+      text: $decode(json['text'], TextSpan.fromJson),
+      sentiment: $decode(json['sentiment'], Sentiment.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (text != null) 'text': text!.toJson(),
+      if (sentiment != null) 'sentiment': sentiment!.toJson(),
+    };
+  }
+
+  @override
+  String toString() => 'Sentence()';
+}
+
+/// Represents a phrase in the text that is a known entity, such as
+/// a person, an organization, or location. The API associates information, such
+/// as probability and mentions, with entities.
+class Entity extends Message {
+  /// The representative name for the entity.
+  final String? name;
+
+  /// The entity type.
+  final Entity$Type? type;
+
+  /// Metadata associated with the entity.
+  ///
+  /// For the metadata
+  /// associated with other entity types, see the Type table below.
+  final Map<String, String>? metadata;
+
+  /// The mentions of this entity in the input document. The API currently
+  /// supports proper noun mentions.
+  final List<EntityMention>? mentions;
+
+  /// For calls to [AnalyzeEntitySentiment][] or if
+  /// [AnnotateTextRequest.Features.extract_entity_sentiment][google.cloud.language.v2.AnnotateTextRequest.Features.extract_entity_sentiment]
+  /// is set to true, this field will contain the aggregate sentiment expressed
+  /// for this entity in the provided document.
+  final Sentiment? sentiment;
+
+  Entity({
+    this.name,
+    this.type,
+    this.metadata,
+    this.mentions,
+    this.sentiment,
+  });
+
+  factory Entity.fromJson(Map<String, dynamic> json) {
+    return Entity(
+      name: json['name'],
+      type: $decode(json['type'], Entity$Type.fromJson),
+      metadata: (json['metadata'] as Map?)?.cast(),
+      mentions: $decodeList(json['mentions'], EntityMention.fromJson),
+      sentiment: $decode(json['sentiment'], Sentiment.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (name != null) 'name': name,
+      if (type != null) 'type': type!.toJson(),
+      if (metadata != null) 'metadata': metadata,
+      if (mentions != null) 'mentions': $encodeList(mentions),
+      if (sentiment != null) 'sentiment': sentiment!.toJson(),
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (name != null) 'name=$name',
+      if (type != null) 'type=$type',
+    ].join(',');
+    return 'Entity($contents)';
+  }
+}
+
+/// The type of the entity. The table
+/// below lists the associated fields for entities that have different
+/// metadata.
+class Entity$Type extends Enum {
+  /// Unknown
+  static const unknown = Entity$Type('UNKNOWN');
+
+  /// Person
+  static const person = Entity$Type('PERSON');
+
+  /// Location
+  static const location = Entity$Type('LOCATION');
+
+  /// Organization
+  static const organization = Entity$Type('ORGANIZATION');
+
+  /// Event
+  static const event = Entity$Type('EVENT');
+
+  /// Artwork
+  static const workOfArt = Entity$Type('WORK_OF_ART');
+
+  /// Consumer product
+  static const consumerGood = Entity$Type('CONSUMER_GOOD');
+
+  /// Other types of entities
+  static const other = Entity$Type('OTHER');
+
+  /// Phone number
+  ///
+  /// The metadata lists the phone number, formatted according to local
+  /// convention, plus whichever additional elements appear in the text:
+  ///
+  /// * `number` - the actual number, broken down into sections as per local
+  /// convention
+  /// * `national_prefix` - country code, if detected
+  /// * `area_code` - region or area code, if detected
+  /// * `extension` - phone extension (to be dialed after connection), if
+  /// detected
+  static const phoneNumber = Entity$Type('PHONE_NUMBER');
+
+  /// Address
+  ///
+  /// The metadata identifies the street number and locality plus whichever
+  /// additional elements appear in the text:
+  ///
+  /// * `street_number` - street number
+  /// * `locality` - city or town
+  /// * `street_name` - street/route name, if detected
+  /// * `postal_code` - postal code, if detected
+  /// * `country` - country, if detected
+  /// * `broad_region` - administrative area, such as the state, if detected
+  /// * `narrow_region` - smaller administrative area, such as county, if
+  /// detected
+  /// * `sublocality` - used in Asian addresses to demark a district within a
+  /// city, if detected
+  static const address = Entity$Type('ADDRESS');
+
+  /// Date
+  ///
+  /// The metadata identifies the components of the date:
+  ///
+  /// * `year` - four digit year, if detected
+  /// * `month` - two digit month number, if detected
+  /// * `day` - two digit day number, if detected
+  static const date = Entity$Type('DATE');
+
+  /// Number
+  ///
+  /// The metadata is the number itself.
+  static const number = Entity$Type('NUMBER');
+
+  /// Price
+  ///
+  /// The metadata identifies the `value` and `currency`.
+  static const price = Entity$Type('PRICE');
+
+  const Entity$Type(super.value);
+
+  factory Entity$Type.fromJson(String json) => Entity$Type(json);
+
+  @override
+  bool operator ==(Object other) =>
+      other is Entity$Type && value == other.value;
+
+  @override
+  String toString() => 'Type.$value';
+}
+
+/// Represents the feeling associated with the entire text or entities in
+/// the text.
+class Sentiment extends Message {
+  /// A non-negative number in the [0, +inf) range, which represents
+  /// the absolute magnitude of sentiment regardless of score (positive or
+  /// negative).
+  final double? magnitude;
+
+  /// Sentiment score between -1.0 (negative sentiment) and 1.0
+  /// (positive sentiment).
+  final double? score;
+
+  Sentiment({
+    this.magnitude,
+    this.score,
+  });
+
+  factory Sentiment.fromJson(Map<String, dynamic> json) {
+    return Sentiment(
+      magnitude: json['magnitude'],
+      score: json['score'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (magnitude != null) 'magnitude': magnitude,
+      if (score != null) 'score': score,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (magnitude != null) 'magnitude=$magnitude',
+      if (score != null) 'score=$score',
+    ].join(',');
+    return 'Sentiment($contents)';
+  }
+}
+
+/// Represents a mention for an entity in the text. Currently, proper noun
+/// mentions are supported.
+class EntityMention extends Message {
+  /// The mention text.
+  final TextSpan? text;
+
+  /// The type of the entity mention.
+  final EntityMention$Type? type;
+
+  /// For calls to [AnalyzeEntitySentiment][] or if
+  /// [AnnotateTextRequest.Features.extract_entity_sentiment][google.cloud.language.v2.AnnotateTextRequest.Features.extract_entity_sentiment]
+  /// is set to true, this field will contain the sentiment expressed for this
+  /// mention of the entity in the provided document.
+  final Sentiment? sentiment;
+
+  /// Probability score associated with the entity.
+  ///
+  /// The score shows the probability of the entity mention being the entity
+  /// type. The score is in (0, 1] range.
+  final double? probability;
+
+  EntityMention({
+    this.text,
+    this.type,
+    this.sentiment,
+    this.probability,
+  });
+
+  factory EntityMention.fromJson(Map<String, dynamic> json) {
+    return EntityMention(
+      text: $decode(json['text'], TextSpan.fromJson),
+      type: $decode(json['type'], EntityMention$Type.fromJson),
+      sentiment: $decode(json['sentiment'], Sentiment.fromJson),
+      probability: json['probability'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (text != null) 'text': text!.toJson(),
+      if (type != null) 'type': type!.toJson(),
+      if (sentiment != null) 'sentiment': sentiment!.toJson(),
+      if (probability != null) 'probability': probability,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (type != null) 'type=$type',
+      if (probability != null) 'probability=$probability',
+    ].join(',');
+    return 'EntityMention($contents)';
+  }
+}
+
+/// The supported types of mentions.
+class EntityMention$Type extends Enum {
+  /// Unknown
+  static const typeUnknown = EntityMention$Type('TYPE_UNKNOWN');
+
+  /// Proper name
+  static const proper = EntityMention$Type('PROPER');
+
+  /// Common noun (or noun compound)
+  static const common = EntityMention$Type('COMMON');
+
+  const EntityMention$Type(super.value);
+
+  factory EntityMention$Type.fromJson(String json) => EntityMention$Type(json);
+
+  @override
+  bool operator ==(Object other) =>
+      other is EntityMention$Type && value == other.value;
+
+  @override
+  String toString() => 'Type.$value';
+}
+
+/// Represents a text span in the input document.
+class TextSpan extends Message {
+  /// The content of the text span, which is a substring of the document.
+  final String? content;
+
+  /// The API calculates the beginning offset of the content in the original
+  /// document according to the
+  /// [EncodingType][google.cloud.language.v2.EncodingType] specified in the API
+  /// request.
+  final int? beginOffset;
+
+  TextSpan({
+    this.content,
+    this.beginOffset,
+  });
+
+  factory TextSpan.fromJson(Map<String, dynamic> json) {
+    return TextSpan(
+      content: json['content'],
+      beginOffset: json['beginOffset'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (content != null) 'content': content,
+      if (beginOffset != null) 'beginOffset': beginOffset,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (content != null) 'content=$content',
+      if (beginOffset != null) 'beginOffset=$beginOffset',
+    ].join(',');
+    return 'TextSpan($contents)';
+  }
+}
+
+/// Represents a category returned from the text classifier.
+class ClassificationCategory extends Message {
+  /// The name of the category representing the document.
+  final String? name;
+
+  /// The classifier's confidence of the category. Number represents how certain
+  /// the classifier is that this category represents the given text.
+  final double? confidence;
+
+  /// Optional. The classifier's severity of the category. This is only present
+  /// when the ModerateTextRequest.ModelVersion is set to MODEL_VERSION_2, and
+  /// the corresponding category has a severity score.
+  final double? severity;
+
+  ClassificationCategory({
+    this.name,
+    this.confidence,
+    this.severity,
+  });
+
+  factory ClassificationCategory.fromJson(Map<String, dynamic> json) {
+    return ClassificationCategory(
+      name: json['name'],
+      confidence: json['confidence'],
+      severity: json['severity'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (name != null) 'name': name,
+      if (confidence != null) 'confidence': confidence,
+      if (severity != null) 'severity': severity,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (name != null) 'name=$name',
+      if (confidence != null) 'confidence=$confidence',
+      if (severity != null) 'severity=$severity',
+    ].join(',');
+    return 'ClassificationCategory($contents)';
+  }
+}
+
+/// The sentiment analysis request message.
+class AnalyzeSentimentRequest extends Message {
+  /// Required. Input document.
+  final Document? document;
+
+  /// The encoding type used by the API to calculate sentence offsets.
+  final EncodingType? encodingType;
+
+  AnalyzeSentimentRequest({
+    this.document,
+    this.encodingType,
+  });
+
+  factory AnalyzeSentimentRequest.fromJson(Map<String, dynamic> json) {
+    return AnalyzeSentimentRequest(
+      document: $decode(json['document'], Document.fromJson),
+      encodingType: $decode(json['encodingType'], EncodingType.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (document != null) 'document': document!.toJson(),
+      if (encodingType != null) 'encodingType': encodingType!.toJson(),
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (encodingType != null) 'encodingType=$encodingType',
+    ].join(',');
+    return 'AnalyzeSentimentRequest($contents)';
+  }
+}
+
+/// The sentiment analysis response message.
+class AnalyzeSentimentResponse extends Message {
+  /// The overall sentiment of the input document.
+  final Sentiment? documentSentiment;
+
+  /// The language of the text, which will be the same as the language specified
+  /// in the request or, if not specified, the automatically-detected language.
+  /// See [Document.language][] field for more details.
+  final String? languageCode;
+
+  /// The sentiment for all the sentences in the document.
+  final List<Sentence>? sentences;
+
+  /// Whether the language is officially supported. The API may still return a
+  /// response when the language is not supported, but it is on a best effort
+  /// basis.
+  final bool? languageSupported;
+
+  AnalyzeSentimentResponse({
+    this.documentSentiment,
+    this.languageCode,
+    this.sentences,
+    this.languageSupported,
+  });
+
+  factory AnalyzeSentimentResponse.fromJson(Map<String, dynamic> json) {
+    return AnalyzeSentimentResponse(
+      documentSentiment: $decode(json['documentSentiment'], Sentiment.fromJson),
+      languageCode: json['languageCode'],
+      sentences: $decodeList(json['sentences'], Sentence.fromJson),
+      languageSupported: json['languageSupported'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (documentSentiment != null) 'documentSentiment': documentSentiment!.toJson(),
+      if (languageCode != null) 'languageCode': languageCode,
+      if (sentences != null) 'sentences': $encodeList(sentences),
+      if (languageSupported != null) 'languageSupported': languageSupported,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (languageCode != null) 'languageCode=$languageCode',
+      if (languageSupported != null) 'languageSupported=$languageSupported',
+    ].join(',');
+    return 'AnalyzeSentimentResponse($contents)';
+  }
+}
+
+/// The entity analysis request message.
+class AnalyzeEntitiesRequest extends Message {
+  /// Required. Input document.
+  final Document? document;
+
+  /// The encoding type used by the API to calculate offsets.
+  final EncodingType? encodingType;
+
+  AnalyzeEntitiesRequest({
+    this.document,
+    this.encodingType,
+  });
+
+  factory AnalyzeEntitiesRequest.fromJson(Map<String, dynamic> json) {
+    return AnalyzeEntitiesRequest(
+      document: $decode(json['document'], Document.fromJson),
+      encodingType: $decode(json['encodingType'], EncodingType.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (document != null) 'document': document!.toJson(),
+      if (encodingType != null) 'encodingType': encodingType!.toJson(),
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (encodingType != null) 'encodingType=$encodingType',
+    ].join(',');
+    return 'AnalyzeEntitiesRequest($contents)';
+  }
+}
+
+/// The entity analysis response message.
+class AnalyzeEntitiesResponse extends Message {
+  /// The recognized entities in the input document.
+  final List<Entity>? entities;
+
+  /// The language of the text, which will be the same as the language specified
+  /// in the request or, if not specified, the automatically-detected language.
+  /// See [Document.language][] field for more details.
+  final String? languageCode;
+
+  /// Whether the language is officially supported. The API may still return a
+  /// response when the language is not supported, but it is on a best effort
+  /// basis.
+  final bool? languageSupported;
+
+  AnalyzeEntitiesResponse({
+    this.entities,
+    this.languageCode,
+    this.languageSupported,
+  });
+
+  factory AnalyzeEntitiesResponse.fromJson(Map<String, dynamic> json) {
+    return AnalyzeEntitiesResponse(
+      entities: $decodeList(json['entities'], Entity.fromJson),
+      languageCode: json['languageCode'],
+      languageSupported: json['languageSupported'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (entities != null) 'entities': $encodeList(entities),
+      if (languageCode != null) 'languageCode': languageCode,
+      if (languageSupported != null) 'languageSupported': languageSupported,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (languageCode != null) 'languageCode=$languageCode',
+      if (languageSupported != null) 'languageSupported=$languageSupported',
+    ].join(',');
+    return 'AnalyzeEntitiesResponse($contents)';
+  }
+}
+
+/// The document classification request message.
+class ClassifyTextRequest extends Message {
+  /// Required. Input document.
+  final Document? document;
+
+  ClassifyTextRequest({
+    this.document,
+  });
+
+  factory ClassifyTextRequest.fromJson(Map<String, dynamic> json) {
+    return ClassifyTextRequest(
+      document: $decode(json['document'], Document.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (document != null) 'document': document!.toJson(),
+    };
+  }
+
+  @override
+  String toString() => 'ClassifyTextRequest()';
+}
+
+/// The document classification response message.
+class ClassifyTextResponse extends Message {
+  /// Categories representing the input document.
+  final List<ClassificationCategory>? categories;
+
+  /// The language of the text, which will be the same as the language specified
+  /// in the request or, if not specified, the automatically-detected language.
+  /// See [Document.language][] field for more details.
+  final String? languageCode;
+
+  /// Whether the language is officially supported. The API may still return a
+  /// response when the language is not supported, but it is on a best effort
+  /// basis.
+  final bool? languageSupported;
+
+  ClassifyTextResponse({
+    this.categories,
+    this.languageCode,
+    this.languageSupported,
+  });
+
+  factory ClassifyTextResponse.fromJson(Map<String, dynamic> json) {
+    return ClassifyTextResponse(
+      categories: $decodeList(json['categories'], ClassificationCategory.fromJson),
+      languageCode: json['languageCode'],
+      languageSupported: json['languageSupported'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (categories != null) 'categories': $encodeList(categories),
+      if (languageCode != null) 'languageCode': languageCode,
+      if (languageSupported != null) 'languageSupported': languageSupported,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (languageCode != null) 'languageCode=$languageCode',
+      if (languageSupported != null) 'languageSupported=$languageSupported',
+    ].join(',');
+    return 'ClassifyTextResponse($contents)';
+  }
+}
+
+/// The document moderation request message.
+class ModerateTextRequest extends Message {
+  /// Required. Input document.
+  final Document? document;
+
+  /// Optional. The model version to use for ModerateText.
+  final ModerateTextRequest$ModelVersion? modelVersion;
+
+  ModerateTextRequest({
+    this.document,
+    this.modelVersion,
+  });
+
+  factory ModerateTextRequest.fromJson(Map<String, dynamic> json) {
+    return ModerateTextRequest(
+      document: $decode(json['document'], Document.fromJson),
+      modelVersion: $decode(json['modelVersion'], ModerateTextRequest$ModelVersion.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (document != null) 'document': document!.toJson(),
+      if (modelVersion != null) 'modelVersion': modelVersion!.toJson(),
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (modelVersion != null) 'modelVersion=$modelVersion',
+    ].join(',');
+    return 'ModerateTextRequest($contents)';
+  }
+}
+
+/// The model version to use for ModerateText.
+class ModerateTextRequest$ModelVersion extends Enum {
+  /// The default model version.
+  static const modelVersionUnspecified = ModerateTextRequest$ModelVersion('MODEL_VERSION_UNSPECIFIED');
+
+  /// Use the v1 model, this model is used by default when not provided.
+  /// The v1 model only returns probability (confidence) score for each
+  /// category.
+  static const modelVersion1 = ModerateTextRequest$ModelVersion('MODEL_VERSION_1');
+
+  /// Use the v2 model.
+  /// The v2 model only returns probability (confidence) score for each
+  /// category, and returns severity score for a subset of the categories.
+  static const modelVersion2 = ModerateTextRequest$ModelVersion('MODEL_VERSION_2');
+
+  const ModerateTextRequest$ModelVersion(super.value);
+
+  factory ModerateTextRequest$ModelVersion.fromJson(String json) => ModerateTextRequest$ModelVersion(json);
+
+  @override
+  bool operator ==(Object other) =>
+      other is ModerateTextRequest$ModelVersion && value == other.value;
+
+  @override
+  String toString() => 'ModelVersion.$value';
+}
+
+/// The document moderation response message.
+class ModerateTextResponse extends Message {
+  /// Harmful and sensitive categories representing the input document.
+  final List<ClassificationCategory>? moderationCategories;
+
+  /// The language of the text, which will be the same as the language specified
+  /// in the request or, if not specified, the automatically-detected language.
+  /// See [Document.language][] field for more details.
+  final String? languageCode;
+
+  /// Whether the language is officially supported. The API may still return a
+  /// response when the language is not supported, but it is on a best effort
+  /// basis.
+  final bool? languageSupported;
+
+  ModerateTextResponse({
+    this.moderationCategories,
+    this.languageCode,
+    this.languageSupported,
+  });
+
+  factory ModerateTextResponse.fromJson(Map<String, dynamic> json) {
+    return ModerateTextResponse(
+      moderationCategories: $decodeList(json['moderationCategories'], ClassificationCategory.fromJson),
+      languageCode: json['languageCode'],
+      languageSupported: json['languageSupported'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (moderationCategories != null) 'moderationCategories': $encodeList(moderationCategories),
+      if (languageCode != null) 'languageCode': languageCode,
+      if (languageSupported != null) 'languageSupported': languageSupported,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (languageCode != null) 'languageCode=$languageCode',
+      if (languageSupported != null) 'languageSupported=$languageSupported',
+    ].join(',');
+    return 'ModerateTextResponse($contents)';
+  }
+}
+
+/// The request message for the text annotation API, which can perform multiple
+/// analysis types in one call.
+class AnnotateTextRequest extends Message {
+  /// Required. Input document.
+  final Document? document;
+
+  /// Required. The enabled features.
+  final AnnotateTextRequest$Features? features;
+
+  /// The encoding type used by the API to calculate offsets.
+  final EncodingType? encodingType;
+
+  AnnotateTextRequest({
+    this.document,
+    this.features,
+    this.encodingType,
+  });
+
+  factory AnnotateTextRequest.fromJson(Map<String, dynamic> json) {
+    return AnnotateTextRequest(
+      document: $decode(json['document'], Document.fromJson),
+      features: $decode(json['features'], AnnotateTextRequest$Features.fromJson),
+      encodingType: $decode(json['encodingType'], EncodingType.fromJson),
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (document != null) 'document': document!.toJson(),
+      if (features != null) 'features': features!.toJson(),
+      if (encodingType != null) 'encodingType': encodingType!.toJson(),
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (encodingType != null) 'encodingType=$encodingType',
+    ].join(',');
+    return 'AnnotateTextRequest($contents)';
+  }
+}
+
+/// All available features.
+/// Setting each one to true will enable that specific analysis for the input.
+class AnnotateTextRequest$Features extends Message {
+  /// Optional. Extract entities.
+  final bool? extractEntities;
+
+  /// Optional. Extract document-level sentiment.
+  final bool? extractDocumentSentiment;
+
+  /// Optional. Classify the full document into categories.
+  final bool? classifyText;
+
+  /// Optional. Moderate the document for harmful and sensitive categories.
+  final bool? moderateText;
+
+  AnnotateTextRequest$Features({
+    this.extractEntities,
+    this.extractDocumentSentiment,
+    this.classifyText,
+    this.moderateText,
+  });
+
+  factory AnnotateTextRequest$Features.fromJson(Map<String, dynamic> json) {
+    return AnnotateTextRequest$Features(
+      extractEntities: json['extractEntities'],
+      extractDocumentSentiment: json['extractDocumentSentiment'],
+      classifyText: json['classifyText'],
+      moderateText: json['moderateText'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (extractEntities != null) 'extractEntities': extractEntities,
+      if (extractDocumentSentiment != null) 'extractDocumentSentiment': extractDocumentSentiment,
+      if (classifyText != null) 'classifyText': classifyText,
+      if (moderateText != null) 'moderateText': moderateText,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (extractEntities != null) 'extractEntities=$extractEntities',
+      if (extractDocumentSentiment != null) 'extractDocumentSentiment=$extractDocumentSentiment',
+      if (classifyText != null) 'classifyText=$classifyText',
+      if (moderateText != null) 'moderateText=$moderateText',
+    ].join(',');
+    return 'Features($contents)';
+  }
+}
+
+/// The text annotations response message.
+class AnnotateTextResponse extends Message {
+  /// Sentences in the input document. Populated if the user enables
+  /// [AnnotateTextRequest.Features.extract_document_sentiment][google.cloud.language.v2.AnnotateTextRequest.Features.extract_document_sentiment].
+  final List<Sentence>? sentences;
+
+  /// Entities, along with their semantic information, in the input document.
+  /// Populated if the user enables
+  /// [AnnotateTextRequest.Features.extract_entities][google.cloud.language.v2.AnnotateTextRequest.Features.extract_entities]
+  /// or
+  /// [AnnotateTextRequest.Features.extract_entity_sentiment][google.cloud.language.v2.AnnotateTextRequest.Features.extract_entity_sentiment].
+  final List<Entity>? entities;
+
+  /// The overall sentiment for the document. Populated if the user enables
+  /// [AnnotateTextRequest.Features.extract_document_sentiment][google.cloud.language.v2.AnnotateTextRequest.Features.extract_document_sentiment].
+  final Sentiment? documentSentiment;
+
+  /// The language of the text, which will be the same as the language specified
+  /// in the request or, if not specified, the automatically-detected language.
+  /// See [Document.language][] field for more details.
+  final String? languageCode;
+
+  /// Categories identified in the input document.
+  final List<ClassificationCategory>? categories;
+
+  /// Harmful and sensitive categories identified in the input document.
+  final List<ClassificationCategory>? moderationCategories;
+
+  /// Whether the language is officially supported by all requested features.
+  /// The API may still return a response when the language is not supported, but
+  /// it is on a best effort basis.
+  final bool? languageSupported;
+
+  AnnotateTextResponse({
+    this.sentences,
+    this.entities,
+    this.documentSentiment,
+    this.languageCode,
+    this.categories,
+    this.moderationCategories,
+    this.languageSupported,
+  });
+
+  factory AnnotateTextResponse.fromJson(Map<String, dynamic> json) {
+    return AnnotateTextResponse(
+      sentences: $decodeList(json['sentences'], Sentence.fromJson),
+      entities: $decodeList(json['entities'], Entity.fromJson),
+      documentSentiment: $decode(json['documentSentiment'], Sentiment.fromJson),
+      languageCode: json['languageCode'],
+      categories: $decodeList(json['categories'], ClassificationCategory.fromJson),
+      moderationCategories: $decodeList(json['moderationCategories'], ClassificationCategory.fromJson),
+      languageSupported: json['languageSupported'],
+    );
+  }
+
+  @override
+  Object toJson() {
+    return {
+      if (sentences != null) 'sentences': $encodeList(sentences),
+      if (entities != null) 'entities': $encodeList(entities),
+      if (documentSentiment != null) 'documentSentiment': documentSentiment!.toJson(),
+      if (languageCode != null) 'languageCode': languageCode,
+      if (categories != null) 'categories': $encodeList(categories),
+      if (moderationCategories != null) 'moderationCategories': $encodeList(moderationCategories),
+      if (languageSupported != null) 'languageSupported': languageSupported,
+    };
+  }
+
+  @override
+  String toString() {
+    final contents = [
+      if (languageCode != null) 'languageCode=$languageCode',
+      if (languageSupported != null) 'languageSupported=$languageSupported',
+    ].join(',');
+    return 'AnnotateTextResponse($contents)';
+  }
+}
+
+/// Represents the text encoding that the caller uses to process the output.
+/// Providing an `EncodingType` is recommended because the API provides the
+/// beginning offsets for various outputs, such as tokens and mentions, and
+/// languages that natively use different text encodings may access offsets
+/// differently.
+class EncodingType extends Enum {
+  /// If `EncodingType` is not specified, encoding-dependent information (such as
+  /// `begin_offset`) will be set at `-1`.
+  static const none = EncodingType('NONE');
+
+  /// Encoding-dependent information (such as `begin_offset`) is calculated based
+  /// on the UTF-8 encoding of the input. C++ and Go are examples of languages
+  /// that use this encoding natively.
+  static const utf8 = EncodingType('UTF8');
+
+  /// Encoding-dependent information (such as `begin_offset`) is calculated based
+  /// on the UTF-16 encoding of the input. Java and JavaScript are examples of
+  /// languages that use this encoding natively.
+  static const utf16 = EncodingType('UTF16');
+
+  /// Encoding-dependent information (such as `begin_offset`) is calculated based
+  /// on the UTF-32 encoding of the input. Python is an example of a language
+  /// that uses this encoding natively.
+  static const utf32 = EncodingType('UTF32');
+
+  const EncodingType(super.value);
+
+  factory EncodingType.fromJson(String json) => EncodingType(json);
+
+  @override
+  bool operator ==(Object other) =>
+      other is EncodingType && value == other.value;
+
+  @override
+  String toString() => 'EncodingType.$value';
+}
diff --git a/generator/dart/packages/generated/google_cloud_language/pubspec.yaml b/generator/dart/packages/generated/google_cloud_language/pubspec.yaml
new file mode 100644
index 0000000000..43334ab168
--- /dev/null
+++ b/generator/dart/packages/generated/google_cloud_language/pubspec.yaml
@@ -0,0 +1,27 @@
+# Copyright 2025 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Code generated by sidekick. DO NOT EDIT.
+
+name: google_cloud_language
+description: The Google Cloud client library for the Cloud Natural Language API.
+version: 0.1.0
+
+environment: 
+  sdk: ^3.6.0
+
+resolution: workspace
+
+dependencies:
+  google_cloud_common: any
diff --git a/generator/dart/packages/generated/google_cloud_protobuf/README.md b/generator/dart/packages/generated/google_cloud_protobuf/README.md
index 72c44060ee..47672c105f 100755
--- a/generator/dart/packages/generated/google_cloud_protobuf/README.md
+++ b/generator/dart/packages/generated/google_cloud_protobuf/README.md
@@ -6,8 +6,8 @@ The Google Cloud client library for the Core Protobuf Types.
 
 > [!CAUTION]
 > This package is under active development! We expect multiple breaking changes
-in upcoming releases. Testing is also incomplete; we do **not** recommend that
-you use this package in production.
+> in upcoming releases. Testing is also incomplete; we do **not** recommend that
+> you use this package in production.
 
 We welcome feedback about the APIs, documentation, missing features, bugs, etc.
 
diff --git a/generator/dart/packages/generated/google_cloud_protobuf/lib/protobuf.dart b/generator/dart/packages/generated/google_cloud_protobuf/lib/protobuf.dart
index d82660c600..73e3086c39 100755
--- a/generator/dart/packages/generated/google_cloud_protobuf/lib/protobuf.dart
+++ b/generator/dart/packages/generated/google_cloud_protobuf/lib/protobuf.dart
@@ -111,7 +111,6 @@ part 'src/protobuf.p.dart';
 ///       "value": "1.212s"
 ///     }
 class Any extends Message {
-
   /// A URL/resource name that uniquely identifies the type of the serialized
   /// protocol buffer message. This string must contain at least
   /// one "/" character. The last segment of the URL's path must represent
@@ -234,7 +233,6 @@ class Any extends Message {
 /// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
 /// microsecond should be expressed in JSON format as "3.000001s".
 class Duration extends Message {
-
   /// Signed seconds of the span of time. Must be from -315,576,000,000
   /// to +315,576,000,000 inclusive. Note: these bounds are computed from:
   /// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
@@ -470,7 +468,6 @@ class Duration extends Message {
 /// request should verify the included field paths, and return an
 /// `INVALID_ARGUMENT` error if any path is unmappable.
 class FieldMask extends Message {
-
   /// The set of field mask paths.
   final List<String>? paths;
 
diff --git a/generator/dart/packages/generated/google_cloud_rpc/README.md b/generator/dart/packages/generated/google_cloud_rpc/README.md
index 44c532c482..8d7c7b1ffb 100755
--- a/generator/dart/packages/generated/google_cloud_rpc/README.md
+++ b/generator/dart/packages/generated/google_cloud_rpc/README.md
@@ -6,8 +6,8 @@ The Google Cloud client library for the Google RPC Types.
 
 > [!CAUTION]
 > This package is under active development! We expect multiple breaking changes
-in upcoming releases. Testing is also incomplete; we do **not** recommend that
-you use this package in production.
+> in upcoming releases. Testing is also incomplete; we do **not** recommend that
+> you use this package in production.
 
 We welcome feedback about the APIs, documentation, missing features, bugs, etc.
 
diff --git a/generator/dart/packages/generated/google_cloud_rpc/lib/rpc.dart b/generator/dart/packages/generated/google_cloud_rpc/lib/rpc.dart
index 183ac76fd6..1e2b2d412b 100755
--- a/generator/dart/packages/generated/google_cloud_rpc/lib/rpc.dart
+++ b/generator/dart/packages/generated/google_cloud_rpc/lib/rpc.dart
@@ -49,7 +49,6 @@ import 'package:google_cloud_protobuf/protobuf.dart';
 ///       }
 ///     }
 class ErrorInfo extends Message {
-
   /// The reason of the error. This is a constant value that identifies the
   /// proximate cause of the error. Error reasons are unique within a particular
   /// domain of errors. This should be at most 63 characters and match a
@@ -123,7 +122,6 @@ class ErrorInfo extends Message {
 /// number of retries have been reached or a maximum retry delay cap has been
 /// reached.
 class RetryInfo extends Message {
-
   /// Clients should wait at least this long between retrying the same request.
   final Duration? retryDelay;
 
@@ -150,7 +148,6 @@ class RetryInfo extends Message {
 
 /// Describes additional debugging info.
 class DebugInfo extends Message {
-
   /// The stack trace entries indicating where the error occurred.
   final List<String>? stackEntries;
 
@@ -198,7 +195,6 @@ class DebugInfo extends Message {
 /// Also see RetryInfo and Help types for other details about handling a
 /// quota failure.
 class QuotaFailure extends Message {
-
   /// Describes all quota violations.
   final List<QuotaFailure$Violation>? violations;
 
@@ -226,7 +222,6 @@ class QuotaFailure extends Message {
 /// A message type used to describe a single quota violation.  For example, a
 /// daily quota or a custom quota that was exceeded.
 class QuotaFailure$Violation extends Message {
-
   /// The subject on which the quota check failed.
   /// For example, "clientip:<ip address of client>" or "project:<Google
   /// developer project id>".
@@ -277,7 +272,6 @@ class QuotaFailure$Violation extends Message {
 /// acknowledged, it could list the terms of service violation in the
 /// PreconditionFailure message.
 class PreconditionFailure extends Message {
-
   /// Describes all precondition violations.
   final List<PreconditionFailure$Violation>? violations;
 
@@ -304,7 +298,6 @@ class PreconditionFailure extends Message {
 
 /// A message type used to describe a single precondition failure.
 class PreconditionFailure$Violation extends Message {
-
   /// The type of PreconditionFailure. We recommend using a service-specific
   /// enum type to define the supported precondition violation subjects. For
   /// example, "TOS" for "Terms of Service violation".
@@ -358,7 +351,6 @@ class PreconditionFailure$Violation extends Message {
 /// Describes violations in a client request. This error type focuses on the
 /// syntactic aspects of the request.
 class BadRequest extends Message {
-
   /// Describes all violations in a client request.
   final List<BadRequest$FieldViolation>? fieldViolations;
 
@@ -385,7 +377,6 @@ class BadRequest extends Message {
 
 /// A message type used to describe a single bad request field.
 class BadRequest$FieldViolation extends Message {
-
   /// A path that leads to a field in the request body. The value will be a
   /// sequence of dot-separated identifiers that identify a protocol buffer
   /// field.
@@ -480,7 +471,6 @@ class BadRequest$FieldViolation extends Message {
 /// Contains metadata about the request that clients can attach when filing a bug
 /// or providing other forms of feedback.
 class RequestInfo extends Message {
-
   /// An opaque string that should only be interpreted by the service generating
   /// it. For example, it can be used to identify requests in the service's logs.
   final String? requestId;
@@ -521,7 +511,6 @@ class RequestInfo extends Message {
 
 /// Describes the resource that is being accessed.
 class ResourceInfo extends Message {
-
   /// A name for the type of resource being accessed, e.g. "sql table",
   /// "cloud storage bucket", "file", "Google calendar"; or the type URL
   /// of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic".
@@ -587,7 +576,6 @@ class ResourceInfo extends Message {
 /// project hasn't enabled the accessed service, this can contain a URL pointing
 /// directly to the right place in the developer console to flip the bit.
 class Help extends Message {
-
   /// URL(s) pointing to additional information on handling the current error.
   final List<Help$Link>? links;
 
@@ -614,7 +602,6 @@ class Help extends Message {
 
 /// Describes a URL link.
 class Help$Link extends Message {
-
   /// Describes what the link offers.
   final String? description;
 
@@ -654,7 +641,6 @@ class Help$Link extends Message {
 /// Provides a localized error message that is safe to return to the user
 /// which can be attached to an RPC error.
 class LocalizedMessage extends Message {
-
   /// The locale used following the specification defined at
   /// https://www.rfc-editor.org/rfc/bcp/bcp47.txt.
   /// Examples are: "en-US", "fr-CH", "es-MX"
@@ -695,7 +681,6 @@ class LocalizedMessage extends Message {
 
 /// Represents an HTTP request.
 class HttpRequest extends Message {
-
   /// The HTTP request method.
   final String? method;
 
@@ -748,7 +733,6 @@ class HttpRequest extends Message {
 
 /// Represents an HTTP response.
 class HttpResponse extends Message {
-
   /// The HTTP status code, such as 200 or 404.
   final int? status;
 
@@ -801,7 +785,6 @@ class HttpResponse extends Message {
 
 /// Represents an HTTP header.
 class HttpHeader extends Message {
-
   /// The HTTP header key. It is case insensitive.
   final String? key;
 
@@ -846,7 +829,6 @@ class HttpHeader extends Message {
 /// You can find out more about this error model and how to work with it in the
 /// [API Design Guide](https://cloud.google.com/apis/design/errors).
 class Status extends Message {
-
   /// The status code, which should be an enum value of
   /// [google.rpc.Code][google.rpc.Code].
   final int? code;
diff --git a/generator/dart/packages/generated/google_cloud_type/README.md b/generator/dart/packages/generated/google_cloud_type/README.md
index d2774c41ab..fe1d126ab8 100755
--- a/generator/dart/packages/generated/google_cloud_type/README.md
+++ b/generator/dart/packages/generated/google_cloud_type/README.md
@@ -6,8 +6,8 @@ The Google Cloud client library for the Common Types.
 
 > [!CAUTION]
 > This package is under active development! We expect multiple breaking changes
-in upcoming releases. Testing is also incomplete; we do **not** recommend that
-you use this package in production.
+> in upcoming releases. Testing is also incomplete; we do **not** recommend that
+> you use this package in production.
 
 We welcome feedback about the APIs, documentation, missing features, bugs, etc.
 
diff --git a/generator/dart/packages/generated/google_cloud_type/lib/type.dart b/generator/dart/packages/generated/google_cloud_type/lib/type.dart
index b2fb9e2261..46b644f64f 100755
--- a/generator/dart/packages/generated/google_cloud_type/lib/type.dart
+++ b/generator/dart/packages/generated/google_cloud_type/lib/type.dart
@@ -53,7 +53,6 @@ import 'package:google_cloud_common/common.dart';
 /// are determined by the service that evaluates it. See the service
 /// documentation for additional information.
 class Expr extends Message {
-
   /// Textual representation of an expression in Common Expression Language
   /// syntax.
   final String? expression;
diff --git a/generator/dart/packages/google_cloud_common/example/language.dart b/generator/dart/packages/google_cloud_common/example/language.dart
new file mode 100644
index 0000000000..c913a7d5a9
--- /dev/null
+++ b/generator/dart/packages/google_cloud_common/example/language.dart
@@ -0,0 +1,56 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/// A simple end-to-end example showing an API call through the
+/// `google_cloud_language` package with authentication via
+/// `package:googleapis_auth`.
+library;
+
+import 'dart:io';
+
+import 'package:google_cloud_language/language.dart';
+
+import 'package:googleapis_auth/auth_io.dart' as auth;
+
+void main(List<String> args) async {
+  if (args.isEmpty) {
+    print('usage: dart example/language.dart <api-key>');
+    exit(1);
+  }
+
+  final apiKey = args[0];
+
+  final client = auth.clientViaApiKey(apiKey);
+  final service = LanguageService(client: client);
+  final document = Document(
+    content: 'Hello, world!',
+    type: Document$Type.plainText,
+  );
+
+  final result = await service.analyzeSentiment(
+    AnalyzeSentimentRequest(document: document),
+  );
+
+  print('result: ${result}');
+  print('documentSentiment: ${result.documentSentiment}');
+
+  for (final sentence in result.sentences!) {
+    print('');
+    print('sentence:');
+    print('  text: ${sentence.text}');
+    print('  sentiment: ${sentence.sentiment}');
+  }
+
+  client.close();
+}
diff --git a/generator/dart/packages/google_cloud_common/pubspec.yaml b/generator/dart/packages/google_cloud_common/pubspec.yaml
index 4792a91344..c60e00e9f3 100644
--- a/generator/dart/packages/google_cloud_common/pubspec.yaml
+++ b/generator/dart/packages/google_cloud_common/pubspec.yaml
@@ -25,3 +25,9 @@ dependencies:
   google_cloud_rpc: ^0.1.0
   http: ^1.3.0
   test: ^1.25.0
+
+dev_dependencies:
+  # Used for example/language.dart.
+  google_cloud_language: any
+  # Used for example/language.dart.
+  googleapis_auth: ^1.6.0
diff --git a/generator/dart/pubspec.yaml b/generator/dart/pubspec.yaml
index 0213954194..41ae17d49b 100644
--- a/generator/dart/pubspec.yaml
+++ b/generator/dart/pubspec.yaml
@@ -21,5 +21,6 @@ environment:
 workspace:
   - packages/generated/google_cloud_protobuf
   - packages/generated/google_cloud_rpc
+  - packages/generated/google_cloud_language
   - packages/generated/google_cloud_type
   - packages/google_cloud_common
diff --git a/generator/internal/dart/dart.go b/generator/internal/dart/dart.go
index 385b30d30d..09928c20bf 100644
--- a/generator/internal/dart/dart.go
+++ b/generator/internal/dart/dart.go
@@ -42,6 +42,10 @@ var usesCustomEncoding = map[string]string{
 	".google.protobuf.FieldMask": ".google.protobuf.FieldMask",
 }
 
+var reservedNames = map[string]string{
+	"Function": "",
+}
+
 func Generate(model *api.API, outdir string, cfg *config.Config) error {
 	_, err := annotateModel(model, cfg.Codec)
 	if err != nil {
@@ -157,10 +161,18 @@ func resolveTypeName(message *api.Message, packageMapping map[string]string, imp
 }
 
 func messageName(m *api.Message) string {
-	if m.Parent != nil {
-		return messageName(m.Parent) + "$" + strcase.ToCamel(m.Name)
+	name := strcase.ToCamel(m.Name)
+
+	if m.Parent == nil {
+		// For top-most symbols, check for conflicts with reserved names.
+		if _, hasConflict := reservedNames[name]; hasConflict {
+			return name + "$"
+		} else {
+			return name
+		}
+	} else {
+		return messageName(m.Parent) + "$" + name
 	}
-	return strcase.ToCamel(m.Name)
 }
 
 func enumName(e *api.Enum) string {
@@ -174,10 +186,31 @@ func enumValueName(e *api.EnumValue) string {
 	return strcase.ToLowerCamel(e.Name)
 }
 
-func httpPathFmt(_ *api.PathInfo) string {
-	fmt := ""
-	// TODO(#1034): Determine the correct format for Dart.
-	return fmt
+func httpPathFmt(pathInfo *api.PathInfo) string {
+	var builder strings.Builder
+
+	for _, segment := range pathInfo.PathTemplate {
+		switch {
+		case segment.Literal != nil:
+			builder.WriteString("/")
+			builder.WriteString(*segment.Literal)
+		case segment.FieldPath != nil:
+			fieldPath := *segment.FieldPath
+			paths := strings.Split(fieldPath, ".")
+			for i, p := range paths {
+				paths[i] = strcase.ToLowerCamel(p)
+			}
+			fieldPath = strings.Join(paths, ".")
+			builder.WriteString("/${request.")
+			builder.WriteString(fieldPath)
+			builder.WriteString("}")
+		case segment.Verb != nil:
+			builder.WriteString(":")
+			builder.WriteString(*segment.Verb)
+		}
+	}
+
+	return builder.String()
 }
 
 func httpPathArgs(_ *api.PathInfo) []string {
diff --git a/generator/internal/dart/dart_test.go b/generator/internal/dart/dart_test.go
index fa12ac0779..aa81446773 100644
--- a/generator/internal/dart/dart_test.go
+++ b/generator/internal/dart/dart_test.go
@@ -63,8 +63,12 @@ func TestTemplatesAvailable(t *testing.T) {
 func TestMessageNames(t *testing.T) {
 	r := sample.Replication()
 	a := sample.Automatic()
+	f := &api.Message{
+		Name: "Function",
+		ID:   ".google.cloud.functions.v2.Function",
+	}
 	model := api.NewTestAPI(
-		[]*api.Message{r, a, sample.CustomerManagedEncryption()},
+		[]*api.Message{r, a, f, sample.CustomerManagedEncryption()},
 		[]*api.Enum{},
 		[]*api.Service{})
 	model.PackageName = "test"
@@ -76,6 +80,7 @@ func TestMessageNames(t *testing.T) {
 	}{
 		{message: r, want: "Replication"},
 		{message: a, want: "Replication$Automatic"},
+		{message: f, want: "Function$"},
 		{message: sample.SecretPayload(), want: "SecretPayload"},
 	} {
 		t.Run(test.want, func(t *testing.T) {
@@ -541,3 +546,21 @@ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
 		t.Errorf("mismatch in FormatDocComments (-want, +got)\n:%s", diff)
 	}
 }
+
+func TestHttpPathFmt(t *testing.T) {
+	for _, test := range []struct {
+		method *api.Method
+		want   string
+	}{
+		{method: sample.MethodCreate(), want: "/v1/${request.parent}/secrets/${request.secretId}"},
+		{method: sample.MethodUpdate(), want: "/v1/${request.secret.name}"},
+		{method: sample.MethodAddSecretVersion(), want: "/v1/projects/${request.project}/secrets/${request.secret}:addVersion"},
+		{method: sample.MethodListSecretVersions(), want: "/v1/projects/${request.parent}/secrets/${request.secret}:listSecretVersions"},
+	} {
+		t.Run(test.method.Name, func(t *testing.T) {
+			if got := httpPathFmt(test.method.PathInfo); got != test.want {
+				t.Errorf("unexpected httpPathFmt, got=%q, want=%q", got, test.want)
+			}
+		})
+	}
+}
diff --git a/generator/internal/dart/darttemplate.go b/generator/internal/dart/darttemplate.go
index fdfdea8e25..c7083b75a6 100644
--- a/generator/internal/dart/darttemplate.go
+++ b/generator/internal/dart/darttemplate.go
@@ -72,12 +72,16 @@ type messageAnnotation struct {
 
 type methodAnnotation struct {
 	// The method name using Dart naming conventions.
-	Name         string
-	RequestType  string
-	ResponseType string
-	DocLines     []string
-	PathParams   []*api.Field
-	QueryParams  []*api.Field
+	Name            string
+	RequestMethod   string
+	RequestType     string
+	ResponseType    string
+	DocLines        []string
+	HasBody         bool
+	ReturnsValue    bool
+	BodyMessageName string
+	PathParams      []*api.Field
+	QueryParams     []*api.Field
 }
 
 type pathInfoAnnotation struct {
@@ -504,13 +508,24 @@ func annotateMethod(method *api.Method, state *api.APIState, packageMapping map[
 	}
 	method.PathInfo.Codec = pathInfoAnnotation
 
+	bodyMessageName := method.PathInfo.BodyFieldPath
+	if bodyMessageName == "*" {
+		bodyMessageName = "request"
+	} else if bodyMessageName != "" {
+		bodyMessageName = "request." + strcase.ToLowerCamel(bodyMessageName)
+	}
+
 	annotation := &methodAnnotation{
-		Name:         strcase.ToLowerCamel(method.Name),
-		RequestType:  resolveTypeName(state.MessageByID[method.InputTypeID], packageMapping, imports),
-		ResponseType: resolveTypeName(state.MessageByID[method.OutputTypeID], packageMapping, imports),
-		DocLines:     formatDocComments(method.Documentation, state),
-		PathParams:   language.PathParams(method, state),
-		QueryParams:  language.QueryParams(method, state),
+		Name:            strcase.ToLowerCamel(method.Name),
+		RequestMethod:   strings.ToLower(method.PathInfo.Verb),
+		RequestType:     resolveTypeName(state.MessageByID[method.InputTypeID], packageMapping, imports),
+		ResponseType:    resolveTypeName(state.MessageByID[method.OutputTypeID], packageMapping, imports),
+		DocLines:        formatDocComments(method.Documentation, state),
+		HasBody:         method.PathInfo.BodyFieldPath != "",
+		ReturnsValue:    method.OutputTypeID != ".google.protobuf.Empty",
+		BodyMessageName: bodyMessageName,
+		PathParams:      language.PathParams(method, state),
+		QueryParams:     language.QueryParams(method, state),
 	}
 	method.Codec = annotation
 }
diff --git a/generator/internal/dart/templates/README.md.mustache b/generator/internal/dart/templates/README.md.mustache
index 0aa88f349b..2f627fccc9 100644
--- a/generator/internal/dart/templates/README.md.mustache
+++ b/generator/internal/dart/templates/README.md.mustache
@@ -21,8 +21,8 @@ The Google Cloud client library for the {{Title}}.
 
 > [!CAUTION]
 > This package is under active development! We expect multiple breaking changes
-in upcoming releases. Testing is also incomplete; we do **not** recommend that
-you use this package in production.
+> in upcoming releases. Testing is also incomplete; we do **not** recommend that
+> you use this package in production.
 
 We welcome feedback about the APIs, documentation, missing features, bugs, etc.
 
diff --git a/generator/internal/dart/templates/lib/field.mustache b/generator/internal/dart/templates/lib/field.mustache
index 220f069953..f245576109 100644
--- a/generator/internal/dart/templates/lib/field.mustache
+++ b/generator/internal/dart/templates/lib/field.mustache
@@ -13,8 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 }}
-
 {{#Codec.DocLines}}
 {{{.}}}
 {{/Codec.DocLines}}
 final {{{Codec.Type}}}{{^Codec.Required}}?{{/Codec.Required}} {{Codec.Name}};
+
diff --git a/generator/internal/dart/templates/lib/message.mustache b/generator/internal/dart/templates/lib/message.mustache
index da7f088a3e..b7fedf2097 100644
--- a/generator/internal/dart/templates/lib/message.mustache
+++ b/generator/internal/dart/templates/lib/message.mustache
@@ -22,7 +22,6 @@ class {{Codec.Name}} extends Message {
   {{#Fields}}
   {{> field}}
   {{/Fields}}
-
   {{Codec.Name}}({{#Codec.HasFields}}{
   {{#Fields}}
     {{#Codec.Required}}required {{/Codec.Required}}this.{{Codec.Name}},
diff --git a/generator/internal/dart/templates/lib/method.mustache b/generator/internal/dart/templates/lib/method.mustache
index f896b9fbd6..6459f447f5 100644
--- a/generator/internal/dart/templates/lib/method.mustache
+++ b/generator/internal/dart/templates/lib/method.mustache
@@ -17,6 +17,10 @@ limitations under the License.
 {{#Codec.DocLines}}
 {{{.}}}
 {{/Codec.DocLines}}
-Future<{{Codec.ResponseType}}> {{Codec.Name}}({{Codec.RequestType}} request) {
-  throw UnimplementedError('{{Codec.Name}}');
+Future<{{Codec.ResponseType}}> {{Codec.Name}}({{Codec.RequestType}} request) async {
+  final url = Uri.https(host, '{{PathInfo.Codec.PathFmt}}');
+  {{#Codec.ReturnsValue}}final response = {{/Codec.ReturnsValue}}await ${{Codec.RequestMethod}}(url{{#Codec.HasBody}}, body: {{Codec.BodyMessageName}}{{/Codec.HasBody}});
+{{#Codec.ReturnsValue}}
+  return {{Codec.ResponseType}}.fromJson(response);
+{{/Codec.ReturnsValue}}
 }
diff --git a/generator/testdata/dart/protobuf/golden/secretmanager/README.md b/generator/testdata/dart/protobuf/golden/secretmanager/README.md
index ee29558314..da2f759368 100755
--- a/generator/testdata/dart/protobuf/golden/secretmanager/README.md
+++ b/generator/testdata/dart/protobuf/golden/secretmanager/README.md
@@ -6,8 +6,8 @@ The Google Cloud client library for the Secret Manager API.
 
 > [!CAUTION]
 > This package is under active development! We expect multiple breaking changes
-in upcoming releases. Testing is also incomplete; we do **not** recommend that
-you use this package in production.
+> in upcoming releases. Testing is also incomplete; we do **not** recommend that
+> you use this package in production.
 
 We welcome feedback about the APIs, documentation, missing features, bugs, etc.
 
diff --git a/generator/testdata/dart/protobuf/golden/secretmanager/lib/secretmanager.dart b/generator/testdata/dart/protobuf/golden/secretmanager/lib/secretmanager.dart
index 7d41ff7446..8e8b515925 100755
--- a/generator/testdata/dart/protobuf/golden/secretmanager/lib/secretmanager.dart
+++ b/generator/testdata/dart/protobuf/golden/secretmanager/lib/secretmanager.dart
@@ -38,43 +38,56 @@ class SecretManagerService extends CloudService {
   SecretManagerService({required super.client});
 
   /// Lists [Secrets][google.cloud.secretmanager.v1.Secret].
-  Future<ListSecretsResponse> listSecrets(ListSecretsRequest request) {
-    throw UnimplementedError('listSecrets');
+  Future<ListSecretsResponse> listSecrets(ListSecretsRequest request) async {
+    final url = Uri.https(host, '/v1/${request.parent}/secrets');
+    final response = await $get(url);
+    return ListSecretsResponse.fromJson(response);
   }
 
   /// Creates a new [Secret][google.cloud.secretmanager.v1.Secret] containing no
   /// [SecretVersions][google.cloud.secretmanager.v1.SecretVersion].
-  Future<Secret> createSecret(CreateSecretRequest request) {
-    throw UnimplementedError('createSecret');
+  Future<Secret> createSecret(CreateSecretRequest request) async {
+    final url = Uri.https(host, '/v1/${request.parent}/secrets');
+    final response = await $post(url, body: request.secret);
+    return Secret.fromJson(response);
   }
 
   /// Creates a new [SecretVersion][google.cloud.secretmanager.v1.SecretVersion]
   /// containing secret data and attaches it to an existing
   /// [Secret][google.cloud.secretmanager.v1.Secret].
-  Future<SecretVersion> addSecretVersion(AddSecretVersionRequest request) {
-    throw UnimplementedError('addSecretVersion');
+  Future<SecretVersion> addSecretVersion(AddSecretVersionRequest request) async {
+    final url = Uri.https(host, '/v1/${request.parent}:addVersion');
+    final response = await $post(url, body: request);
+    return SecretVersion.fromJson(response);
   }
 
   /// Gets metadata for a given [Secret][google.cloud.secretmanager.v1.Secret].
-  Future<Secret> getSecret(GetSecretRequest request) {
-    throw UnimplementedError('getSecret');
+  Future<Secret> getSecret(GetSecretRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}');
+    final response = await $get(url);
+    return Secret.fromJson(response);
   }
 
   /// Updates metadata of an existing
   /// [Secret][google.cloud.secretmanager.v1.Secret].
-  Future<Secret> updateSecret(UpdateSecretRequest request) {
-    throw UnimplementedError('updateSecret');
+  Future<Secret> updateSecret(UpdateSecretRequest request) async {
+    final url = Uri.https(host, '/v1/${request.secret.name}');
+    final response = await $patch(url, body: request.secret);
+    return Secret.fromJson(response);
   }
 
   /// Deletes a [Secret][google.cloud.secretmanager.v1.Secret].
-  Future<void> deleteSecret(DeleteSecretRequest request) {
-    throw UnimplementedError('deleteSecret');
+  Future<void> deleteSecret(DeleteSecretRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}');
+    await $delete(url);
   }
 
   /// Lists [SecretVersions][google.cloud.secretmanager.v1.SecretVersion]. This
   /// call does not return secret data.
-  Future<ListSecretVersionsResponse> listSecretVersions(ListSecretVersionsRequest request) {
-    throw UnimplementedError('listSecretVersions');
+  Future<ListSecretVersionsResponse> listSecretVersions(ListSecretVersionsRequest request) async {
+    final url = Uri.https(host, '/v1/${request.parent}/versions');
+    final response = await $get(url);
+    return ListSecretVersionsResponse.fromJson(response);
   }
 
   /// Gets metadata for a
@@ -82,8 +95,10 @@ class SecretManagerService extends CloudService {
   ///
   /// `projects/*/secrets/*/versions/latest` is an alias to the most recently
   /// created [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
-  Future<SecretVersion> getSecretVersion(GetSecretVersionRequest request) {
-    throw UnimplementedError('getSecretVersion');
+  Future<SecretVersion> getSecretVersion(GetSecretVersionRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}');
+    final response = await $get(url);
+    return SecretVersion.fromJson(response);
   }
 
   /// Accesses a [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
@@ -91,8 +106,10 @@ class SecretManagerService extends CloudService {
   ///
   /// `projects/*/secrets/*/versions/latest` is an alias to the most recently
   /// created [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
-  Future<AccessSecretVersionResponse> accessSecretVersion(AccessSecretVersionRequest request) {
-    throw UnimplementedError('accessSecretVersion');
+  Future<AccessSecretVersionResponse> accessSecretVersion(AccessSecretVersionRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}:access');
+    final response = await $get(url);
+    return AccessSecretVersionResponse.fromJson(response);
   }
 
   /// Disables a [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
@@ -100,8 +117,10 @@ class SecretManagerService extends CloudService {
   /// Sets the [state][google.cloud.secretmanager.v1.SecretVersion.state] of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] to
   /// [DISABLED][google.cloud.secretmanager.v1.SecretVersion.State.DISABLED].
-  Future<SecretVersion> disableSecretVersion(DisableSecretVersionRequest request) {
-    throw UnimplementedError('disableSecretVersion');
+  Future<SecretVersion> disableSecretVersion(DisableSecretVersionRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}:disable');
+    final response = await $post(url, body: request);
+    return SecretVersion.fromJson(response);
   }
 
   /// Enables a [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
@@ -109,8 +128,10 @@ class SecretManagerService extends CloudService {
   /// Sets the [state][google.cloud.secretmanager.v1.SecretVersion.state] of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] to
   /// [ENABLED][google.cloud.secretmanager.v1.SecretVersion.State.ENABLED].
-  Future<SecretVersion> enableSecretVersion(EnableSecretVersionRequest request) {
-    throw UnimplementedError('enableSecretVersion');
+  Future<SecretVersion> enableSecretVersion(EnableSecretVersionRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}:enable');
+    final response = await $post(url, body: request);
+    return SecretVersion.fromJson(response);
   }
 
   /// Destroys a [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
@@ -119,8 +140,10 @@ class SecretManagerService extends CloudService {
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] to
   /// [DESTROYED][google.cloud.secretmanager.v1.SecretVersion.State.DESTROYED]
   /// and irrevocably destroys the secret data.
-  Future<SecretVersion> destroySecretVersion(DestroySecretVersionRequest request) {
-    throw UnimplementedError('destroySecretVersion');
+  Future<SecretVersion> destroySecretVersion(DestroySecretVersionRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}:destroy');
+    final response = await $post(url, body: request);
+    return SecretVersion.fromJson(response);
   }
 
   /// Sets the access control policy on the specified secret. Replaces any
@@ -130,14 +153,18 @@ class SecretManagerService extends CloudService {
   /// [SecretVersions][google.cloud.secretmanager.v1.SecretVersion] are enforced
   /// according to the policy set on the associated
   /// [Secret][google.cloud.secretmanager.v1.Secret].
-  Future<Policy> setIamPolicy(SetIamPolicyRequest request) {
-    throw UnimplementedError('setIamPolicy');
+  Future<Policy> setIamPolicy(SetIamPolicyRequest request) async {
+    final url = Uri.https(host, '/v1/${request.resource}:setIamPolicy');
+    final response = await $post(url, body: request);
+    return Policy.fromJson(response);
   }
 
   /// Gets the access control policy for a secret.
   /// Returns empty policy if the secret exists and does not have a policy set.
-  Future<Policy> getIamPolicy(GetIamPolicyRequest request) {
-    throw UnimplementedError('getIamPolicy');
+  Future<Policy> getIamPolicy(GetIamPolicyRequest request) async {
+    final url = Uri.https(host, '/v1/${request.resource}:getIamPolicy');
+    final response = await $get(url);
+    return Policy.fromJson(response);
   }
 
   /// Returns permissions that a caller has for the specified secret.
@@ -147,18 +174,24 @@ class SecretManagerService extends CloudService {
   /// Note: This operation is designed to be used for building permission-aware
   /// UIs and command-line tools, not for authorization checking. This operation
   /// may "fail open" without warning.
-  Future<TestIamPermissionsResponse> testIamPermissions(TestIamPermissionsRequest request) {
-    throw UnimplementedError('testIamPermissions');
+  Future<TestIamPermissionsResponse> testIamPermissions(TestIamPermissionsRequest request) async {
+    final url = Uri.https(host, '/v1/${request.resource}:testIamPermissions');
+    final response = await $post(url, body: request);
+    return TestIamPermissionsResponse.fromJson(response);
   }
 
   /// Lists information about the supported locations for this service.
-  Future<ListLocationsResponse> listLocations(ListLocationsRequest request) {
-    throw UnimplementedError('listLocations');
+  Future<ListLocationsResponse> listLocations(ListLocationsRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}/locations');
+    final response = await $get(url);
+    return ListLocationsResponse.fromJson(response);
   }
 
   /// Gets information about a location.
-  Future<Location> getLocation(GetLocationRequest request) {
-    throw UnimplementedError('getLocation');
+  Future<Location> getLocation(GetLocationRequest request) async {
+    final url = Uri.https(host, '/v1/${request.name}');
+    final response = await $get(url);
+    return Location.fromJson(response);
   }
 }
 
@@ -169,7 +202,6 @@ class SecretManagerService extends CloudService {
 /// [SecretVersions][google.cloud.secretmanager.v1.SecretVersion] that represent
 /// the secret data.
 class Secret extends Message {
-
   /// Output only. The resource name of the
   /// [Secret][google.cloud.secretmanager.v1.Secret] in the format
   /// `projects/*/secrets/*`.
@@ -331,7 +363,6 @@ class Secret extends Message {
 
 /// A secret version resource in the Secret Manager API.
 class SecretVersion extends Message {
-
   /// Output only. The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format
   /// `projects/*/secrets/*/versions/*`.
@@ -476,7 +507,6 @@ class SecretVersion$State extends Enum {
 
 /// A policy that defines the replication and encryption configuration of data.
 class Replication extends Message {
-
   /// The [Secret][google.cloud.secretmanager.v1.Secret] will automatically be
   /// replicated without any restrictions.
   final Replication$Automatic? automatic;
@@ -513,7 +543,6 @@ class Replication extends Message {
 /// [Secret][google.cloud.secretmanager.v1.Secret] payload without any
 /// restrictions.
 class Replication$Automatic extends Message {
-
   /// Optional. The customer-managed encryption configuration of the
   /// [Secret][google.cloud.secretmanager.v1.Secret]. If no configuration is
   /// provided, Google-managed default encryption is used.
@@ -550,7 +579,6 @@ class Replication$Automatic extends Message {
 /// [Secret][google.cloud.secretmanager.v1.Secret] payload into the locations
 /// specified in [Secret.replication.user_managed.replicas][]
 class Replication$UserManaged extends Message {
-
   /// Required. The list of Replicas for this
   /// [Secret][google.cloud.secretmanager.v1.Secret].
   ///
@@ -581,7 +609,6 @@ class Replication$UserManaged extends Message {
 /// Represents a Replica for this
 /// [Secret][google.cloud.secretmanager.v1.Secret].
 class Replication$UserManaged$Replica extends Message {
-
   /// The canonical IDs of the location to replicate data.
   /// For example: `"us-east1"`.
   final String? location;
@@ -629,7 +656,6 @@ class Replication$UserManaged$Replica extends Message {
 /// Configuration for encrypting secret payloads using customer-managed
 /// encryption keys (CMEK).
 class CustomerManagedEncryption extends Message {
-
   /// Required. The resource name of the Cloud KMS CryptoKey used to encrypt
   /// secret payloads.
   ///
@@ -674,7 +700,6 @@ class CustomerManagedEncryption extends Message {
 /// The replication status of a
 /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
 class ReplicationStatus extends Message {
-
   /// Describes the replication status of a
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] with
   /// automatic replication.
@@ -724,7 +749,6 @@ class ReplicationStatus extends Message {
 /// Only populated if the parent [Secret][google.cloud.secretmanager.v1.Secret]
 /// has an automatic replication policy.
 class ReplicationStatus$AutomaticStatus extends Message {
-
   /// Output only. The customer-managed encryption status of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion]. Only
   /// populated if customer-managed encryption is used.
@@ -758,7 +782,6 @@ class ReplicationStatus$AutomaticStatus extends Message {
 /// Only populated if the parent [Secret][google.cloud.secretmanager.v1.Secret]
 /// has a user-managed replication policy.
 class ReplicationStatus$UserManagedStatus extends Message {
-
   /// Output only. The list of replica statuses for the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
   final List<ReplicationStatus$UserManagedStatus$ReplicaStatus>? replicas;
@@ -787,7 +810,6 @@ class ReplicationStatus$UserManagedStatus extends Message {
 /// Describes the status of a user-managed replica for the
 /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
 class ReplicationStatus$UserManagedStatus$ReplicaStatus extends Message {
-
   /// Output only. The canonical ID of the replica location.
   /// For example: `"us-east1"`.
   final String? location;
@@ -828,7 +850,6 @@ class ReplicationStatus$UserManagedStatus$ReplicaStatus extends Message {
 
 /// Describes the status of customer-managed encryption.
 class CustomerManagedEncryptionStatus extends Message {
-
   /// Required. The resource name of the Cloud KMS CryptoKeyVersion used to
   /// encrypt the secret payload, in the following format:
   /// `projects/*/locations/*/keyRings/*/cryptoKeys/*/versions/*`.
@@ -863,7 +884,6 @@ class CustomerManagedEncryptionStatus extends Message {
 /// A Pub/Sub topic which Secret Manager will publish to when control plane
 /// events occur on this secret.
 class Topic extends Message {
-
   /// Required. The resource name of the Pub/Sub topic that will be published to,
   /// in the following format: `projects/*/topics/*`. For publication to succeed,
   /// the Secret Manager service agent must have the `pubsub.topic.publish`
@@ -903,7 +923,6 @@ class Topic extends Message {
 /// Secret. [Secret.topics][google.cloud.secretmanager.v1.Secret.topics] must be
 /// set to configure rotation.
 class Rotation extends Message {
-
   /// Optional. Timestamp in UTC at which the
   /// [Secret][google.cloud.secretmanager.v1.Secret] is scheduled to rotate.
   /// Cannot be set to less than 300s (5 min) in the future and at most
@@ -956,7 +975,6 @@ class Rotation extends Message {
 /// sensitive secret payload that is associated with a
 /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion].
 class SecretPayload extends Message {
-
   /// The secret data. Must be no larger than 64KiB.
   final Uint8List? data;
 
@@ -1011,7 +1029,6 @@ class SecretPayload extends Message {
 /// Request message for
 /// [SecretManagerService.ListSecrets][google.cloud.secretmanager.v1.SecretManagerService.ListSecrets].
 class ListSecretsRequest extends Message {
-
   /// Required. The resource name of the project associated with the
   /// [Secrets][google.cloud.secretmanager.v1.Secret], in the format `projects/*`
   /// or `projects/*/locations/*`
@@ -1074,7 +1091,6 @@ class ListSecretsRequest extends Message {
 /// Response message for
 /// [SecretManagerService.ListSecrets][google.cloud.secretmanager.v1.SecretManagerService.ListSecrets].
 class ListSecretsResponse extends Message {
-
   /// The list of [Secrets][google.cloud.secretmanager.v1.Secret] sorted in
   /// reverse by create_time (newest first).
   final List<Secret>? secrets;
@@ -1126,7 +1142,6 @@ class ListSecretsResponse extends Message {
 /// Request message for
 /// [SecretManagerService.CreateSecret][google.cloud.secretmanager.v1.SecretManagerService.CreateSecret].
 class CreateSecretRequest extends Message {
-
   /// Required. The resource name of the project to associate with the
   /// [Secret][google.cloud.secretmanager.v1.Secret], in the format `projects/*`
   /// or `projects/*/locations/*`.
@@ -1179,7 +1194,6 @@ class CreateSecretRequest extends Message {
 /// Request message for
 /// [SecretManagerService.AddSecretVersion][google.cloud.secretmanager.v1.SecretManagerService.AddSecretVersion].
 class AddSecretVersionRequest extends Message {
-
   /// Required. The resource name of the
   /// [Secret][google.cloud.secretmanager.v1.Secret] to associate with the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format
@@ -1222,7 +1236,6 @@ class AddSecretVersionRequest extends Message {
 /// Request message for
 /// [SecretManagerService.GetSecret][google.cloud.secretmanager.v1.SecretManagerService.GetSecret].
 class GetSecretRequest extends Message {
-
   /// Required. The resource name of the
   /// [Secret][google.cloud.secretmanager.v1.Secret], in the format
   /// `projects/*/secrets/*` or `projects/*/locations/*/secrets/*`.
@@ -1257,7 +1270,6 @@ class GetSecretRequest extends Message {
 /// Request message for
 /// [SecretManagerService.ListSecretVersions][google.cloud.secretmanager.v1.SecretManagerService.ListSecretVersions].
 class ListSecretVersionsRequest extends Message {
-
   /// Required. The resource name of the
   /// [Secret][google.cloud.secretmanager.v1.Secret] associated with the
   /// [SecretVersions][google.cloud.secretmanager.v1.SecretVersion] to list, in
@@ -1321,7 +1333,6 @@ class ListSecretVersionsRequest extends Message {
 /// Response message for
 /// [SecretManagerService.ListSecretVersions][google.cloud.secretmanager.v1.SecretManagerService.ListSecretVersions].
 class ListSecretVersionsResponse extends Message {
-
   /// The list of [SecretVersions][google.cloud.secretmanager.v1.SecretVersion]
   /// sorted in reverse by create_time (newest first).
   final List<SecretVersion>? versions;
@@ -1374,7 +1385,6 @@ class ListSecretVersionsResponse extends Message {
 /// Request message for
 /// [SecretManagerService.GetSecretVersion][google.cloud.secretmanager.v1.SecretManagerService.GetSecretVersion].
 class GetSecretVersionRequest extends Message {
-
   /// Required. The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format
   /// `projects/*/secrets/*/versions/*` or
@@ -1415,7 +1425,6 @@ class GetSecretVersionRequest extends Message {
 /// Request message for
 /// [SecretManagerService.UpdateSecret][google.cloud.secretmanager.v1.SecretManagerService.UpdateSecret].
 class UpdateSecretRequest extends Message {
-
   /// Required. [Secret][google.cloud.secretmanager.v1.Secret] with updated field
   /// values.
   final Secret secret;
@@ -1450,7 +1459,6 @@ class UpdateSecretRequest extends Message {
 /// Request message for
 /// [SecretManagerService.AccessSecretVersion][google.cloud.secretmanager.v1.SecretManagerService.AccessSecretVersion].
 class AccessSecretVersionRequest extends Message {
-
   /// Required. The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format
   /// `projects/*/secrets/*/versions/*` or
@@ -1491,7 +1499,6 @@ class AccessSecretVersionRequest extends Message {
 /// Response message for
 /// [SecretManagerService.AccessSecretVersion][google.cloud.secretmanager.v1.SecretManagerService.AccessSecretVersion].
 class AccessSecretVersionResponse extends Message {
-
   /// The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] in the format
   /// `projects/*/secrets/*/versions/*` or
@@ -1533,7 +1540,6 @@ class AccessSecretVersionResponse extends Message {
 /// Request message for
 /// [SecretManagerService.DeleteSecret][google.cloud.secretmanager.v1.SecretManagerService.DeleteSecret].
 class DeleteSecretRequest extends Message {
-
   /// Required. The resource name of the
   /// [Secret][google.cloud.secretmanager.v1.Secret] to delete in the format
   /// `projects/*/secrets/*`.
@@ -1577,7 +1583,6 @@ class DeleteSecretRequest extends Message {
 /// Request message for
 /// [SecretManagerService.DisableSecretVersion][google.cloud.secretmanager.v1.SecretManagerService.DisableSecretVersion].
 class DisableSecretVersionRequest extends Message {
-
   /// Required. The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] to disable in
   /// the format `projects/*/secrets/*/versions/*` or
@@ -1623,7 +1628,6 @@ class DisableSecretVersionRequest extends Message {
 /// Request message for
 /// [SecretManagerService.EnableSecretVersion][google.cloud.secretmanager.v1.SecretManagerService.EnableSecretVersion].
 class EnableSecretVersionRequest extends Message {
-
   /// Required. The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] to enable in
   /// the format `projects/*/secrets/*/versions/*` or
@@ -1669,7 +1673,6 @@ class EnableSecretVersionRequest extends Message {
 /// Request message for
 /// [SecretManagerService.DestroySecretVersion][google.cloud.secretmanager.v1.SecretManagerService.DestroySecretVersion].
 class DestroySecretVersionRequest extends Message {
-
   /// Required. The resource name of the
   /// [SecretVersion][google.cloud.secretmanager.v1.SecretVersion] to destroy in
   /// the format `projects/*/secrets/*/versions/*` or


Reviews:
user: login: coryan
body: The bulk is generated code now, and I trust myself to review this.  Some comments to get you started.

state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T21:59:15Z
user: login: devoncarew
body: Thanks for the review! Updated.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T15:55:19Z
user: login: coryan
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T16:03:06Z

Review comments:
diff_hunk: @@ -156,11 +156,22 @@ func resolveTypeName(message *api.Message, packageMapping map[string]string, imp
 	return messageName(message)
 }
 
+var messageRenames = map[string]string{
+	// 'Function' is a reserved keyword: https://dart.dev/language/keywords.
+	".google.cloud.functions.v2.Function": "CloudFunction",
path: generator/internal/dart/dart.go
user: login: coryan
body: I expect clashes between field names and the Dart keywords.  We should think of a more generic way to avoid conflicts.  For example, could replace `Function` with `Function_` or `Function$`.  

- Something that starts with the original name seems like would work better for code completion
- It also raises fewer questions about "Is this a mangled name?": the weird characters are obvious mangling.
- And both `$` and `_` [1] should not appear in the proto so no conflicts if the same service defines both `Function` and `CloudFunction` ([1] the latter just by convention).

created_at: 2025-03-14T21:51:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,56 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/// A simple end-to-end example showing an API call through the
+/// `google_cloud_language` package with authentication via
+/// `package:googleapis_auth`.
+library;
+
+import 'dart:io';
+
+import 'package:google_cloud_language/language.dart';
+
+import 'package:googleapis_auth/auth_io.dart' as auth;
+
+void main(List<String> args) async {
path: generator/dart/packages/google_cloud_common/example/language.dart
user: login: coryan
body: :shipit: 
created_at: 2025-03-14T21:52:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,9 +185,23 @@ func enumValueName(e *api.EnumValue) string {
 	return strcase.ToLowerCamel(e.Name)
 }
 
-func httpPathFmt(_ *api.PathInfo) string {
+func httpPathFmt(pathInfo *api.PathInfo) string {
 	fmt := ""
-	// TODO(#1034): Determine the correct format for Dart.
+	for _, segment := range pathInfo.PathTemplate {
+		if segment.Literal != nil {
path: generator/internal/dart/dart.go
user: login: coryan
body: I think the golang folks prefer `switch` and `case` over `if / else if`.   There is also this:

https://pkg.go.dev/strings#Builder

that could be handy.

created_at: 2025-03-14T21:57:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,9 +185,23 @@ func enumValueName(e *api.EnumValue) string {
 	return strcase.ToLowerCamel(e.Name)
 }
 
-func httpPathFmt(_ *api.PathInfo) string {
+func httpPathFmt(pathInfo *api.PathInfo) string {
path: generator/internal/dart/dart.go
user: login: coryan
body: I think this function deserves some unit tests now.
created_at: 2025-03-14T21:58:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,9 +185,23 @@ func enumValueName(e *api.EnumValue) string {
 	return strcase.ToLowerCamel(e.Name)
 }
 
-func httpPathFmt(_ *api.PathInfo) string {
+func httpPathFmt(pathInfo *api.PathInfo) string {
path: generator/internal/dart/dart.go
user: login: devoncarew
body: Done!
created_at: 2025-03-16T15:41:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,9 +185,23 @@ func enumValueName(e *api.EnumValue) string {
 	return strcase.ToLowerCamel(e.Name)
 }
 
-func httpPathFmt(_ *api.PathInfo) string {
+func httpPathFmt(pathInfo *api.PathInfo) string {
 	fmt := ""
-	// TODO(#1034): Determine the correct format for Dart.
+	for _, segment := range pathInfo.PathTemplate {
+		if segment.Literal != nil {
path: generator/internal/dart/dart.go
user: login: devoncarew
body: Thanks for the ptr to Builder! And, I'd seen that use for switch statements but hadn't started using it yet - I moved this code over to that pattern.
created_at: 2025-03-16T15:42:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -156,11 +156,22 @@ func resolveTypeName(message *api.Message, packageMapping map[string]string, imp
 	return messageName(message)
 }
 
+var messageRenames = map[string]string{
+	// 'Function' is a reserved keyword: https://dart.dev/language/keywords.
+	".google.cloud.functions.v2.Function": "CloudFunction",
path: generator/internal/dart/dart.go
user: login: devoncarew
body: I switched this over to using a (short) map of reserved words and resolving collisions by prefixing `$`. I don't really love how it looks but it is mechanical and, like you said, doesn't harm discovery.

In another PR, I may move the nested symbol concatenation to using `_` (currently `ReplicationStatus$UserManagedStatus$ReplicaStatus`). I looked into not using any concatenation, but there are too many short message names - `Policy` - and short, common enum names - `Type`, `State`. Perhaps messages could concatenate w/ `_` and enums could concatenatr w/o a separator? `Message_Message` vs `Message_MessageEnum`

created_at: 2025-03-16T15:52:54Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-10T20:13:19Z
body: ## [Codecov](https://app.codecov.io/gh/googleapis/google-cloud-rust/pull/1454?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=googleapis) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 95.36%. Comparing base [(`743229d`)](https://app.codecov.io/gh/googleapis/google-cloud-rust/commit/743229dad32ce0c7465d1ca08e7bb1fca4a6e4e4?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=googleapis) to head [(`125e293`)](https://app.codecov.io/gh/googleapis/google-cloud-rust/commit/125e2935b8906d2fa764663638ef33a1f8cbd297?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=googleapis).
> Report is 1 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #1454   +/-   ##
=======================================
  Coverage   95.36%   95.36%           
=======================================
  Files          38       38           
  Lines        1576     1576           
=======================================
  Hits         1503     1503           
  Misses         73       73           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/googleapis/google-cloud-rust/pull/1454?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=googleapis).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=googleapis).

<details><summary>🚀 New features to boost your workflow: </summary>

- ❄ [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: coryan
created_at: 2025-03-10T20:40:12Z
body: > This PR is a bit big; I was working locally to try and get to being able to make an end-to-end call. I'm happy to convert this to a draft and pull separate pieces out for easier review.

It would be great if you could break this down in smaller chunks.  I simply do not trust myself to review something this large. 

> 
> * add general `toJson()` and `fromJson()` calls to messages
> * create a new (hand-written) google_cloud_common package to contain code common to all the generated clients (http client code and json encoding utilities)
> * contribute an end-to-end example in `google_cloud_language/example`
> * implement round-tripping json encoding and decoding tests in `google_cloud_rpc/test/json_test.dart`
> * generate `Any` and `Timestamp` in order to get correct analysis of the rest of the generated code; note that these implementations do not yet support their custom json formats
> 
> Also not that this PR does not change the nullability of message fields (i.e., it does not yet implement the implicit / explicit presence semantics of proto3).

Ack. Thanks for the additional description, that will help as I go through the smaller PRs.

author_association: CONTRIBUTOR