Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions cmd/mobyextgen/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,18 @@ func fileDescriptor(pt point) (*descriptorpb.FileDescriptorProto, error) {

svc := &descriptorpb.ServiceDescriptorProto{Name: new(pt.service)}
for _, m := range pt.methods {
svc.Method = append(svc.Method, &descriptorpb.MethodDescriptorProto{
method := &descriptorpb.MethodDescriptorProto{
Name: new(m.name),
InputType: new("." + pt.id + "." + m.request),
OutputType: new("." + pt.id + "." + m.response),
})
}
if m.kind == methodClientStreaming {
method.ClientStreaming = new(true)
}
if m.kind == methodServerStreaming {
method.ServerStreaming = new(true)
}
svc.Method = append(svc.Method, method)
}
fd.Service = []*descriptorpb.ServiceDescriptorProto{svc}
return fd, nil
Expand Down
21 changes: 14 additions & 7 deletions cmd/mobyextgen/generation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ func TestGeneratedFilesInheritContractNotices(t *testing.T) {
assert.NilError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example.com/contract\n"), 0o644))
const contract = `package contract

import "context"

// SPDX-FileCopyrightText: ignore comments after the package clause
// SPDX-License-Identifier: ignore comments after the package clause
type Runtime interface{ Do(ctx interface{}, req *Req) (*Resp, error) }
type Runtime interface{ Do(ctx context.Context, req *Req) (*Resp, error) }
type Req struct{}
type Resp struct{}
`
Expand Down Expand Up @@ -88,8 +90,9 @@ func TestSingleMessageField(t *testing.T) {

func TestInitialismFieldBridgesNames(t *testing.T) {
const src = `package p
import "context"
import "github.com/moby/extensions"
type S interface{ Do(ctx interface{}, req *Req) (*Resp, error) }
type S interface{ Do(ctx context.Context, req *Req) (*Resp, error) }
type Req struct{ ContainerID string ` + "`pb:\"1\"`" + ` }
type Resp struct{ Ok bool ` + "`pb:\"1\"`" + ` }
var Point = extensions.DefinePoint[S]("test.gen.v1")
Expand All @@ -114,10 +117,11 @@ var Point = extensions.DefinePoint[S]("test.gen.v1")

func TestServiceContractWithoutAPoint(t *testing.T) {
const contract = `package p
import "context"
type Req struct{ Name string ` + "`pb:\"1\"`" + ` }
type Resp struct{ Ok bool ` + "`pb:\"1\"`" + ` }

type Runtime interface{ Do(ctx interface{}, req *Req) (*Resp, error) }
type Runtime interface{ Do(ctx context.Context, req *Req) (*Resp, error) }
`
pt, err := parseServiceSource(t, contract, "my.proto.pkg.v1.Runtime")
assert.NilError(t, err)
Expand All @@ -140,13 +144,14 @@ type Runtime interface{ Do(ctx interface{}, req *Req) (*Resp, error) }

func TestOrdinaryPointGeneratesPublicationAndClientAPIs(t *testing.T) {
const contract = `package p
import "context"
import "github.com/moby/extensions"
type Req struct{ Name string ` + "`pb:\"1\"`" + ` }
type Resp struct{ Ok bool ` + "`pb:\"1\"`" + ` }

type Runtime interface {
Do(ctx interface{}, req *Req) (*Resp, error)
Delete(ctx interface{}, req *Req) error
Do(ctx context.Context, req *Req) (*Resp, error)
Delete(ctx context.Context, req *Req) error
}
var Point = extensions.DefinePoint[Runtime]("my.proto.pkg.v1")
`
Expand All @@ -173,8 +178,9 @@ var Point = extensions.DefinePoint[Runtime]("my.proto.pkg.v1")

func TestReservedFieldNumbers(t *testing.T) {
const header = `package p
import "context"
import "github.com/moby/extensions"
type S interface{ Do(ctx interface{}, req *Req) (*Resp, error) }
type S interface{ Do(ctx context.Context, req *Req) (*Resp, error) }
type Resp struct{ Ok bool ` + "`pb:\"1\"`" + ` }

var Point = extensions.DefinePoint[S]("test.gen.v1")
Expand Down Expand Up @@ -224,8 +230,9 @@ var Point = extensions.DefinePoint[S]("test.gen.v1")

func TestSinglePointCardinality(t *testing.T) {
const contract = `package p
import "context"
import "github.com/moby/extensions"
type S interface{ Do(ctx interface{}, req *Req) (*Resp, error) }
type S interface{ Do(ctx context.Context, req *Req) (*Resp, error) }
type Req struct{ Name string ` + "`pb:\"1\"`" + ` }
type Resp struct{ Ok bool ` + "`pb:\"1\"`" + ` }
`
Expand Down
13 changes: 12 additions & 1 deletion cmd/mobyextgen/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type point struct {
iface string // Go service interface name
isPoint bool // whether the contract declares an extensions.Point
isSingle bool // whether the point was declared with DefineSinglePoint
doc string // documentation on the provider interface
methods []method
messages []message
}
Expand All @@ -24,12 +25,22 @@ func (p point) grpcService() string { return p.id + "." + p.service }
func (p point) protogenImport() string { return p.importPath + "/protogen" }

type method struct {
kind methodKind
name string // method/rpc name
request string // request message name
response string // response message name
bareError bool // true for `M(ctx, *Req) error`; response is a generated empty message
bareError bool // true only for legacy unary `M(ctx, *Req) error`
doc string // method documentation
}

type methodKind int

const (
methodUnary methodKind = iota
methodServerStreaming
methodClientStreaming
)

type message struct {
name string
fields []field
Expand Down
Loading
Loading