From dba985256788e62615dc14334954294c268fc32e Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 08:10:50 +0000 Subject: [PATCH] feat(forge): add safe service stringers Co-Authored-By: Virgil --- ax_stringer_test.go | 59 ++++++++++++ helpers.go | 4 + service_string.go | 221 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 service_string.go diff --git a/ax_stringer_test.go b/ax_stringer_test.go index 443d791..0f96a3e 100644 --- a/ax_stringer_test.go +++ b/ax_stringer_test.go @@ -173,3 +173,62 @@ func TestOption_Stringers_Empty(t *testing.T) { }) } } + +func TestService_Stringers_Good(t *testing.T) { + client := NewClient("https://forge.example", "token") + + cases := []struct { + name string + got fmt.Stringer + want string + }{ + { + name: "RepoService", + got: newRepoService(client), + want: `forge.RepoService{resource=forge.Resource{path="/api/v1/repos/{owner}/{repo}", collection="/api/v1/repos/{owner}"}}`, + }, + { + name: "AdminService", + got: newAdminService(client), + want: `forge.AdminService{client=forge.Client{baseURL="https://forge.example", token=set, userAgent="go-forge/0.1"}}`, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if got := tc.got.String(); got != tc.want { + t.Fatalf("got String()=%q, want %q", got, tc.want) + } + if got := fmt.Sprint(tc.got); got != tc.want { + t.Fatalf("got fmt.Sprint=%q, want %q", got, tc.want) + } + if got := fmt.Sprintf("%#v", tc.got); got != tc.want { + t.Fatalf("got GoString=%q, want %q", got, tc.want) + } + }) + } +} + +func TestService_Stringers_NilSafe(t *testing.T) { + var repo *RepoService + if got, want := repo.String(), "forge.RepoService{}"; got != want { + t.Fatalf("got String()=%q, want %q", got, want) + } + if got, want := fmt.Sprint(repo), "forge.RepoService{}"; got != want { + t.Fatalf("got fmt.Sprint=%q, want %q", got, want) + } + if got, want := fmt.Sprintf("%#v", repo), "forge.RepoService{}"; got != want { + t.Fatalf("got GoString=%q, want %q", got, want) + } + + var admin *AdminService + if got, want := admin.String(), "forge.AdminService{}"; got != want { + t.Fatalf("got String()=%q, want %q", got, want) + } + if got, want := fmt.Sprint(admin), "forge.AdminService{}"; got != want { + t.Fatalf("got fmt.Sprint=%q, want %q", got, want) + } + if got, want := fmt.Sprintf("%#v", admin), "forge.AdminService{}"; got != want { + t.Fatalf("got GoString=%q, want %q", got, want) + } +} diff --git a/helpers.go b/helpers.go index 7f08cd1..64a0b12 100644 --- a/helpers.go +++ b/helpers.go @@ -100,6 +100,10 @@ func formatOptionValue(v any) string { } } +func serviceString(typeName, fieldName string, value any) string { + return typeName + "{" + fieldName + "=" + fmt.Sprint(value) + "}" +} + func lastIndexByte(s string, b byte) int { for i := len(s) - 1; i >= 0; i-- { if s[i] == b { diff --git a/service_string.go b/service_string.go new file mode 100644 index 0000000..9bb619c --- /dev/null +++ b/service_string.go @@ -0,0 +1,221 @@ +package forge + +// String returns a safe summary of the actions service. +func (s *ActionsService) String() string { + if s == nil { + return "forge.ActionsService{}" + } + return serviceString("forge.ActionsService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the actions service. +func (s *ActionsService) GoString() string { return s.String() } + +// String returns a safe summary of the ActivityPub service. +func (s *ActivityPubService) String() string { + if s == nil { + return "forge.ActivityPubService{}" + } + return serviceString("forge.ActivityPubService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the ActivityPub service. +func (s *ActivityPubService) GoString() string { return s.String() } + +// String returns a safe summary of the admin service. +func (s *AdminService) String() string { + if s == nil { + return "forge.AdminService{}" + } + return serviceString("forge.AdminService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the admin service. +func (s *AdminService) GoString() string { return s.String() } + +// String returns a safe summary of the branch service. +func (s *BranchService) String() string { + if s == nil { + return "forge.BranchService{}" + } + return serviceString("forge.BranchService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the branch service. +func (s *BranchService) GoString() string { return s.String() } + +// String returns a safe summary of the commit service. +func (s *CommitService) String() string { + if s == nil { + return "forge.CommitService{}" + } + return serviceString("forge.CommitService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the commit service. +func (s *CommitService) GoString() string { return s.String() } + +// String returns a safe summary of the content service. +func (s *ContentService) String() string { + if s == nil { + return "forge.ContentService{}" + } + return serviceString("forge.ContentService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the content service. +func (s *ContentService) GoString() string { return s.String() } + +// String returns a safe summary of the issue service. +func (s *IssueService) String() string { + if s == nil { + return "forge.IssueService{}" + } + return serviceString("forge.IssueService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the issue service. +func (s *IssueService) GoString() string { return s.String() } + +// String returns a safe summary of the label service. +func (s *LabelService) String() string { + if s == nil { + return "forge.LabelService{}" + } + return serviceString("forge.LabelService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the label service. +func (s *LabelService) GoString() string { return s.String() } + +// String returns a safe summary of the milestone service. +func (s *MilestoneService) String() string { + if s == nil { + return "forge.MilestoneService{}" + } + return serviceString("forge.MilestoneService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the milestone service. +func (s *MilestoneService) GoString() string { return s.String() } + +// String returns a safe summary of the misc service. +func (s *MiscService) String() string { + if s == nil { + return "forge.MiscService{}" + } + return serviceString("forge.MiscService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the misc service. +func (s *MiscService) GoString() string { return s.String() } + +// String returns a safe summary of the notification service. +func (s *NotificationService) String() string { + if s == nil { + return "forge.NotificationService{}" + } + return serviceString("forge.NotificationService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the notification service. +func (s *NotificationService) GoString() string { return s.String() } + +// String returns a safe summary of the organisation service. +func (s *OrgService) String() string { + if s == nil { + return "forge.OrgService{}" + } + return serviceString("forge.OrgService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the organisation service. +func (s *OrgService) GoString() string { return s.String() } + +// String returns a safe summary of the package service. +func (s *PackageService) String() string { + if s == nil { + return "forge.PackageService{}" + } + return serviceString("forge.PackageService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the package service. +func (s *PackageService) GoString() string { return s.String() } + +// String returns a safe summary of the pull request service. +func (s *PullService) String() string { + if s == nil { + return "forge.PullService{}" + } + return serviceString("forge.PullService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the pull request service. +func (s *PullService) GoString() string { return s.String() } + +// String returns a safe summary of the release service. +func (s *ReleaseService) String() string { + if s == nil { + return "forge.ReleaseService{}" + } + return serviceString("forge.ReleaseService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the release service. +func (s *ReleaseService) GoString() string { return s.String() } + +// String returns a safe summary of the repository service. +func (s *RepoService) String() string { + if s == nil { + return "forge.RepoService{}" + } + return serviceString("forge.RepoService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the repository service. +func (s *RepoService) GoString() string { return s.String() } + +// String returns a safe summary of the team service. +func (s *TeamService) String() string { + if s == nil { + return "forge.TeamService{}" + } + return serviceString("forge.TeamService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the team service. +func (s *TeamService) GoString() string { return s.String() } + +// String returns a safe summary of the user service. +func (s *UserService) String() string { + if s == nil { + return "forge.UserService{}" + } + return serviceString("forge.UserService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the user service. +func (s *UserService) GoString() string { return s.String() } + +// String returns a safe summary of the webhook service. +func (s *WebhookService) String() string { + if s == nil { + return "forge.WebhookService{}" + } + return serviceString("forge.WebhookService", "resource", &s.Resource) +} + +// GoString returns a safe Go-syntax summary of the webhook service. +func (s *WebhookService) GoString() string { return s.String() } + +// String returns a safe summary of the wiki service. +func (s *WikiService) String() string { + if s == nil { + return "forge.WikiService{}" + } + return serviceString("forge.WikiService", "client", s.client) +} + +// GoString returns a safe Go-syntax summary of the wiki service. +func (s *WikiService) GoString() string { return s.String() }