Skip to content

Commit 01675b7

Browse files
authored
feat(dart): Remove ..._gax dependency (#2713)
The functionality in `google_cloud_gax` is moving to `google_could_rpc`. This change supports that change by: 1. changing the import of `package:google_cloud_gax/gax.dart` to `package:google_cloud_rpc/src/service_client.dart` 2. support adding custom package dependencies in `pubspec.yaml`
1 parent 67cefb8 commit 01675b7

File tree

4 files changed

+144
-45
lines changed

4 files changed

+144
-45
lines changed

internal/sidekick/internal/dart/annotate.go

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"errors"
1919
"fmt"
2020
"log/slog"
21-
"slices"
2221
"sort"
2322
"strconv"
2423
"strings"
@@ -230,6 +229,7 @@ func (annotate *annotateModel) annotateModel(options map[string]string) error {
230229
packageVersion string
231230
partFileReference string
232231
doNotPublish bool
232+
dependencies = []string{}
233233
devDependencies = []string{}
234234
repositoryURL string
235235
readMeAfterTitleText string
@@ -270,6 +270,13 @@ func (annotate *annotateModel) annotateModel(options map[string]string) error {
270270
for i := range exports {
271271
exports[i] = strings.TrimSpace(exports[i])
272272
}
273+
case key == "dependencies":
274+
// dependencies = "http, googleapis_auth"
275+
// A list of dependencies to add to pubspec.yaml. This can be used to add dependencies for hand-written code.
276+
dependencies = strings.Split(definition, ",")
277+
for i := range dependencies {
278+
dependencies[i] = strings.TrimSpace(dependencies[i])
279+
}
273280
case key == "dev-dependencies":
274281
devDependencies = strings.Split(definition, ",")
275282
case key == "not-for-publication":
@@ -347,9 +354,9 @@ func (annotate *annotateModel) annotateModel(options map[string]string) error {
347354
// Add a dev dependency on package:lints.
348355
devDependencies = append(devDependencies, "lints")
349356

350-
// Add the import for the google_cloud_gax package.
357+
// Add the import for ServiceClient and related functionality.
351358
if len(model.Services) > 0 {
352-
annotate.imports[gaxImport] = true
359+
annotate.imports[serviceClientImport] = true
353360
}
354361

355362
// `google.protobuf` defines `JsonEncodable`, which is needed by any package that defines a
@@ -371,7 +378,12 @@ func (annotate *annotateModel) annotateModel(options map[string]string) error {
371378
}
372379

373380
pkgName = packageName(model, packageNameOverride)
374-
packageDependencies, err := calculateDependencies(annotate.imports, annotate.dependencyConstraints, pkgName)
381+
importedPackages := calculatePubPackages(annotate.imports)
382+
for _, d := range dependencies {
383+
importedPackages[d] = true
384+
}
385+
386+
packageDependencies, err := calculateDependencies(importedPackages, annotate.dependencyConstraints, pkgName)
375387
if err != nil {
376388
return err
377389
}
@@ -435,29 +447,35 @@ func calculateRequiredFields(model *api.API) map[string]*api.Field {
435447
return required
436448
}
437449

438-
// calculateDependencies calculates package dependencies based on `package:` imports.
439-
func calculateDependencies(imports map[string]bool, constraints map[string]string, packageName string) ([]packageDependency, error) {
440-
deps := []packageDependency{}
441-
450+
// calculatePubPackages returns a set of package names (e.g. "http"), given a
451+
// set of imports (e.g. "package:http/http.dart as http").
452+
func calculatePubPackages(imports map[string]bool) map[string]bool {
453+
packages := map[string]bool{}
442454
for imp := range imports {
443455
if name, hadPrefix := strings.CutPrefix(imp, "package:"); hadPrefix {
444456
name = strings.Split(name, "/")[0]
457+
packages[name] = true
458+
}
459+
}
460+
return packages
461+
}
445462

446-
if !slices.ContainsFunc(deps, func(dep packageDependency) bool {
447-
return dep.Name == name
448-
}) {
449-
constraint := constraints[name]
450-
if len(constraint) == 0 {
451-
return nil, fmt.Errorf("unknown version constraint for package %q (did you forget to add it to .sidekick.toml?)", name)
452-
}
463+
// calculateDependencies calculates package dependencies given a set of
464+
// package names (e.g. "http") and version constraints (e.g. {"http": "^1.2.3"}).
465+
//
466+
// Excludes packages that match the current package.
467+
func calculateDependencies(packages map[string]bool, constraints map[string]string, curPkgName string) ([]packageDependency, error) {
468+
deps := []packageDependency{}
453469

454-
if name != packageName {
455-
deps = append(deps, packageDependency{Name: name, Constraint: constraint})
456-
}
470+
for name := range packages {
471+
constraint := constraints[name]
472+
if name != curPkgName {
473+
if len(constraint) == 0 {
474+
return nil, fmt.Errorf("unknown version constraint for package %q (did you forget to add it to .sidekick.toml?)", name)
457475
}
476+
deps = append(deps, packageDependency{Name: name, Constraint: constraint})
458477
}
459478
}
460-
461479
sort.SliceStable(deps, func(i, j int) bool {
462480
return deps[i].Name < deps[j].Name
463481
})

internal/sidekick/internal/dart/annotate_test.go

Lines changed: 104 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package dart
1616

1717
import (
1818
"maps"
19+
"slices"
1920
"testing"
2021

2122
"github.com/google/go-cmp/cmp"
@@ -27,7 +28,7 @@ var (
2728
requiredConfig = map[string]string{
2829
"api-keys-environment-variables": "GOOGLE_API_KEY,GEMINI_API_KEY",
2930
"issue-tracker-url": "http://www.example.com/issues",
30-
"package:google_cloud_gax": "^1.2.3",
31+
"package:google_cloud_rpc": "^1.2.3",
3132
"package:http": "^4.5.6",
3233
"package:google_cloud_protobuf": "^7.8.9",
3334
}
@@ -38,7 +39,7 @@ func TestAnnotateModel(t *testing.T) {
3839
model.PackageName = "test"
3940

4041
options := maps.Clone(requiredConfig)
41-
maps.Copy(options, map[string]string{"package:google_cloud_gax": "^1.2.3"})
42+
maps.Copy(options, map[string]string{"package:google_cloud_rpc": "^1.2.3"})
4243

4344
annotate := newAnnotateModel(model)
4445
err := annotate.annotateModel(options)
@@ -81,6 +82,21 @@ func TestAnnotateModel_Options(t *testing.T) {
8182
}
8283
},
8384
},
85+
{
86+
map[string]string{
87+
"dependencies": "google_cloud_foo, google_cloud_bar",
88+
"package:google_cloud_bar": "^1.2.3",
89+
"package:google_cloud_foo": "^4.5.6"},
90+
func(t *testing.T, am *annotateModel) {
91+
codec := model.Codec.(*modelAnnotations)
92+
if !slices.Contains(codec.PackageDependencies, packageDependency{Name: "google_cloud_foo", Constraint: "^4.5.6"}) {
93+
t.Errorf("missing 'google_cloud_foo' in Codec.PackageDependencies, got %v", codec.PackageDependencies)
94+
}
95+
if !slices.Contains(codec.PackageDependencies, packageDependency{Name: "google_cloud_bar", Constraint: "^1.2.3"}) {
96+
t.Errorf("missing 'google_cloud_bar' in Codec.PackageDependencies, got %v", codec.PackageDependencies)
97+
}
98+
},
99+
},
84100
{
85101
map[string]string{"extra-exports": "export 'package:google_cloud_gax/gax.dart' show Any; export 'package:google_cloud_gax/gax.dart' show Status;"},
86102
func(t *testing.T, am *annotateModel) {
@@ -147,10 +163,10 @@ func TestAnnotateModel_Options(t *testing.T) {
147163
},
148164
},
149165
{
150-
map[string]string{"google_cloud_gax": "^1.2.3", "package:http": "1.2.0"},
166+
map[string]string{"google_cloud_rpc": "^1.2.3", "package:http": "1.2.0"},
151167
func(t *testing.T, am *annotateModel) {
152168
if diff := cmp.Diff(map[string]string{
153-
"google_cloud_gax": "^1.2.3",
169+
"google_cloud_rpc": "^1.2.3",
154170
"google_cloud_protobuf": "^7.8.9",
155171
"http": "1.2.0"},
156172
am.dependencyConstraints); diff != "" {
@@ -251,35 +267,100 @@ func TestAnnotateMethod(t *testing.T) {
251267
}
252268
}
253269

270+
func TestCalculatePubPackages(t *testing.T) {
271+
for _, test := range []struct {
272+
imports map[string]bool
273+
want map[string]bool
274+
}{
275+
{imports: map[string]bool{"dart:typed_data": true},
276+
want: map[string]bool{}},
277+
{imports: map[string]bool{"dart:typed_data as typed_data": true},
278+
want: map[string]bool{}},
279+
{imports: map[string]bool{"package:http/http.dart": true},
280+
want: map[string]bool{"http": true}},
281+
{imports: map[string]bool{"package:http/http.dart as http": true},
282+
want: map[string]bool{"http": true}},
283+
{imports: map[string]bool{"package:google_cloud_protobuf/src/encoding.dart": true},
284+
want: map[string]bool{"google_cloud_protobuf": true}},
285+
{imports: map[string]bool{"package:google_cloud_protobuf/src/encoding.dart as encoding": true},
286+
want: map[string]bool{"google_cloud_protobuf": true}},
287+
{imports: map[string]bool{"package:http/http.dart": true, "package:http/http.dart as http": true},
288+
want: map[string]bool{"http": true}},
289+
{imports: map[string]bool{
290+
"package:google_cloud_protobuf/src/encoding.dart": true,
291+
"package:http/http.dart": true,
292+
"dart:typed_data": true},
293+
want: map[string]bool{"google_cloud_protobuf": true, "http": true}},
294+
} { // package:http/http.dart as http
295+
got := calculatePubPackages(test.imports)
296+
297+
if !maps.Equal(got, test.want) {
298+
t.Errorf("calculatePubPackages(%v) = %v, want %v", test.imports, got, test.want)
299+
}
300+
}
301+
}
302+
254303
func TestCalculateDependencies(t *testing.T) {
255304
for _, test := range []struct {
256-
testName string
257-
pkgName string
258-
imports []string
259-
want []packageDependency
305+
testName string
306+
packages map[string]bool
307+
constraints map[string]string
308+
packageName string
309+
want []packageDependency
310+
wantErr bool
260311
}{
261-
{testName: "empty", pkgName: "google_cloud_bar", imports: []string{}, want: []packageDependency{}},
262-
{testName: "dart import", pkgName: "google_cloud_bar", imports: []string{typedDataImport}, want: []packageDependency{}},
263-
{testName: "package import", pkgName: "google_cloud_bar", imports: []string{httpImport}, want: []packageDependency{{Name: "http", Constraint: "^1.3.0"}}},
264-
{testName: "dart and package imports", pkgName: "google_cloud_bar", imports: []string{typedDataImport, httpImport}, want: []packageDependency{{Name: "http", Constraint: "^1.3.0"}}},
265-
{testName: "package imports", pkgName: "google_cloud_bar", imports: []string{
266-
httpImport,
267-
"package:google_cloud_foo/foo.dart",
268-
}, want: []packageDependency{{Name: "google_cloud_foo", Constraint: "^1.2.3"}, {Name: "http", Constraint: "^1.3.0"}}},
269-
{testName: "same package", pkgName: "google_cloud_bar", imports: []string{typedDataImport, httpImport, "google_cloud_bar"}, want: []packageDependency{{Name: "http", Constraint: "^1.3.0"}}},
312+
{
313+
testName: "empty",
314+
packages: map[string]bool{},
315+
constraints: map[string]string{},
316+
packageName: "google_cloud_bar",
317+
want: []packageDependency{},
318+
},
319+
{
320+
testName: "self dependency",
321+
packages: map[string]bool{"google_cloud_bar": true},
322+
constraints: map[string]string{},
323+
packageName: "google_cloud_bar",
324+
want: []packageDependency{},
325+
},
326+
{
327+
testName: "separate dependency",
328+
packages: map[string]bool{"google_cloud_foo": true},
329+
constraints: map[string]string{"google_cloud_foo": "^1.2.3"},
330+
packageName: "google_cloud_bar",
331+
want: []packageDependency{{Name: "google_cloud_foo", Constraint: "^1.2.3"}},
332+
},
333+
{
334+
testName: "missing constraint",
335+
packages: map[string]bool{"google_cloud_foo": true},
336+
constraints: map[string]string{},
337+
packageName: "google_cloud_bar",
338+
wantErr: true,
339+
},
340+
{
341+
testName: "multiple dependencies",
342+
packages: map[string]bool{"google_cloud_bar": true, "google_cloud_baz": true, "google_cloud_foo": true},
343+
constraints: map[string]string{"google_cloud_baz": "^1.2.3", "google_cloud_foo": "^4.5.6"},
344+
packageName: "google_cloud_bar",
345+
want: []packageDependency{
346+
{Name: "google_cloud_baz", Constraint: "^1.2.3"},
347+
{Name: "google_cloud_foo", Constraint: "^4.5.6"}},
348+
},
270349
} {
271350
t.Run(test.testName, func(t *testing.T) {
272-
deps := map[string]bool{}
273-
for _, imp := range test.imports {
274-
deps[imp] = true
351+
got, err := calculateDependencies(test.packages, test.constraints, test.packageName)
352+
if (err != nil) != test.wantErr {
353+
t.Errorf("calculateDependencies(%v, %v, %v) error = %v, want error presence = %t",
354+
test.packages, test.constraints, test.packageName, err, test.wantErr)
275355
}
276-
got, err := calculateDependencies(deps, map[string]string{"google_cloud_foo": "^1.2.3", "http": "^1.3.0"}, test.pkgName)
356+
277357
if err != nil {
278-
t.Fatal(err)
358+
return
279359
}
280360

281361
if diff := cmp.Diff(test.want, got); diff != "" {
282-
t.Errorf("mismatch in %q in calculateDependencies (-want, +got)\n:%s", test.testName, diff)
362+
t.Errorf("calculateDependencies(%v, %v, %v) = %v, want %v",
363+
test.packages, test.constraints, test.packageName, got, test.want)
283364
}
284365
})
285366
}

internal/sidekick/internal/dart/dart.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828

2929
var typedDataImport = "dart:typed_data"
3030
var httpImport = "package:http/http.dart as http"
31-
var gaxImport = "package:google_cloud_gax/gax.dart"
31+
var serviceClientImport = "package:google_cloud_rpc/service_client.dart"
3232
var encodingImport = "package:google_cloud_protobuf/src/encoding.dart"
3333
var protobufImport = "package:google_cloud_protobuf/protobuf.dart"
3434

internal/sidekick/internal/dart/generate_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func TestFromProtobuf(t *testing.T) {
5353
"not-for-publication": "true",
5454
"version": "0.1.0",
5555
"skip-format": "true",
56-
"package:google_cloud_gax": "^1.2.3",
56+
"package:google_cloud_rpc": "^1.2.3",
5757
"package:http": "^4.5.6",
5858
"package:google_cloud_location": "^7.8.9",
5959
"package:google_cloud_protobuf": "^0.1.2",
@@ -85,7 +85,7 @@ func TestGeneratedFiles(t *testing.T) {
8585
annotate := newAnnotateModel(model)
8686

8787
options := maps.Clone(requiredConfig)
88-
maps.Copy(options, map[string]string{"package:google_cloud_gax": "^1.2.3", "package:http": "^4.5.6"})
88+
maps.Copy(options, map[string]string{"package:google_cloud_rpc": "^1.2.3", "package:http": "^4.5.6"})
8989

9090
annotate.annotateModel(options)
9191
files := generatedFiles(model)

0 commit comments

Comments
 (0)