Skip to content

Commit 2a3b2bf

Browse files
authored
feat: add full method name in generated code (#252)
1 parent 30da470 commit 2a3b2bf

File tree

12 files changed

+626
-538
lines changed

12 files changed

+626
-538
lines changed

cmd/kod/internal/generate_generator.go

+34-12
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,9 @@ func newGenerator(opt Options, pkg *packages.Package, fset *token.FileSet) (*gen
157157
// kod.AutoMarshal struct.
158158
tset := newTypeSet(pkg)
159159

160-
// Find and process all components.
161-
components := map[string]*component{}
160+
// Find and process all seen.
161+
seen := map[string]*component{}
162+
components := []*component{}
162163
for _, file := range pkg.Syntax {
163164
filename := fset.Position(file.Package).Filename
164165
if filepath.Base(filename) == generatedCodeFile {
@@ -179,25 +180,28 @@ func newGenerator(opt Options, pkg *packages.Package, fset *token.FileSet) (*gen
179180
// This code relies on the fact that a component
180181
// interface and component implementation have to be in the same
181182
// package. If we lift this requirement, then this code will break.
182-
if existing, ok := components[c.fullIntfName()]; ok {
183+
if existing, ok := seen[c.fullIntfName()]; ok {
183184
errs = append(errs, errorf(pkg.Fset, c.impl.Obj().Pos(),
184185
"Duplicate implementation for component %s, other declaration: %v",
185186
c.fullIntfName(), fset.Position(existing.impl.Obj().Pos())))
186187
continue
187188
}
188-
components[c.fullIntfName()] = c
189+
seen[c.fullIntfName()] = c
190+
components = append(components, c)
189191
}
190192
}
191193
if err := errors.Join(errs...); err != nil {
192194
return nil, err
193195
}
194196

197+
// slices.Reverse(components)
198+
195199
return &generator{
196200
opt: opt,
197201
pkg: pkg,
198202
tset: tset,
199203
fileset: fset,
200-
components: lo.Values(components),
204+
components: components,
201205
}, nil
202206
}
203207

@@ -393,6 +397,10 @@ func (c *component) intfName() string {
393397
return c.intf.Obj().Name()
394398
}
395399

400+
func (c *component) fullMethodNameVar(methodName string) string {
401+
return fmt.Sprintf("%s_%s_FullMethodName", c.intfName(), methodName)
402+
}
403+
396404
// implName returns the component implementation name.
397405
func (c *component) implName() string {
398406
return c.impl.Obj().Name()
@@ -549,10 +557,10 @@ func (g *generator) generate() error {
549557
return nil
550558
}
551559

552-
// Process components in deterministic order.
553-
sort.Slice(g.components, func(i, j int) bool {
554-
return g.components[i].intfName() < g.components[j].intfName()
555-
})
560+
// // Process components in deterministic order.
561+
// sort.Slice(g.components, func(i, j int) bool {
562+
// return g.components[i].intfName() < g.components[j].intfName()
563+
// })
556564

557565
// Generate the file body.
558566
var body bytes.Buffer
@@ -574,7 +582,9 @@ func (g *generator) generate() error {
574582
fn := func(format string, args ...interface{}) {
575583
fmt.Fprintln(&header, fmt.Sprintf(format, args...))
576584
}
585+
577586
g.generateImports(fn)
587+
g.generateFullMethodNames(fn)
578588
}
579589

580590
// Create a generated file.
@@ -643,6 +653,19 @@ func (g *generator) generateImports(p printFn) {
643653
p(`)`)
644654
}
645655

656+
func (g *generator) generateFullMethodNames(p printFn) {
657+
p(``)
658+
p(`// Full method names for components.`)
659+
p(`const (`)
660+
for _, comp := range g.components {
661+
for _, m := range comp.methods() {
662+
p(`// %s is the full name of the method [%s.%s].`, comp.fullMethodNameVar(m.Name()), comp.implName(), m.Name())
663+
p(`%s = %q`, comp.fullMethodNameVar(m.Name()), comp.fullIntfName())
664+
}
665+
}
666+
p(`)`)
667+
}
668+
646669
// generateInstanceChecks generates code that checks that every component
647670
// implementation type implements kod.InstanceOf[T] for the appropriate T.
648671
func (g *generator) generateInstanceChecks(p printFn) {
@@ -798,10 +821,9 @@ func (g *generator) generateLocalStubs(p printFn) {
798821
p(`info := interceptor.CallInfo {
799822
Impl: s.impl,
800823
Component: s.name,
801-
FullMethod: "%s.%s",
802-
Method: "%s",
824+
FullMethod: %s,
803825
}
804-
`, comp.fullIntfName(), m.Name(), m.Name())
826+
`, comp.fullMethodNameVar(m.Name()))
805827

806828
p(`%s = s.interceptor(ctx, info, []any{%s}, []any{%s}, call)`,
807829
lo.If(haveError(mt), "err").Else("_"),

examples/helloworld/kod_gen.go

+56-50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

interceptor/interceptor.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ type CallInfo struct {
1212
Component string
1313
// The full name of the called method, in the format of "package/service.method".
1414
FullMethod string
15-
// The name of the method.
16-
Method string
1715
}
1816

1917
// HandleFunc is the type of the function invoked by Components.
@@ -102,6 +100,6 @@ func Not(condition Condition) Condition {
102100
// IsMethod returns a condition that checks if the method name matches the given method.
103101
func IsMethod(method string) Condition {
104102
return func(_ context.Context, info CallInfo) bool {
105-
return info.Method == method
103+
return info.FullMethod == method
106104
}
107105
}

interceptor/interceptor_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -272,15 +272,15 @@ func TestIsMethod(t *testing.T) {
272272
name: "Method matches",
273273
method: "test",
274274
info: CallInfo{
275-
Method: "test",
275+
FullMethod: "test",
276276
},
277277
expected: true,
278278
},
279279
{
280280
name: "Method does not match",
281281
method: "test",
282282
info: CallInfo{
283-
Method: "other",
283+
FullMethod: "other",
284284
},
285285
expected: false,
286286
},

interceptor/kaccesslog/accesslog.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func Interceptor() interceptor.Interceptor {
1919
attrs := []slog.Attr{
2020
slog.Any("req", req),
2121
slog.Any("reply", reply),
22-
slog.String("method", info.Method),
22+
slog.String("method", info.FullMethod),
2323
slog.Int64("cost", time.Since(now).Milliseconds()),
2424
}
2525

interceptor/kmetric/metric.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func Interceptor() interceptor.Interceptor {
3737

3838
as := attribute.NewSet(
3939
attribute.String("component", info.Component),
40-
attribute.String("method", info.Method),
40+
attribute.String("method", info.FullMethod),
4141
)
4242

4343
if err != nil {

0 commit comments

Comments
 (0)