github.com/cloudwego/kitex@v0.9.0/tool/internal_pkg/tpl/service.go (about)

     1  // Copyright 2022 CloudWeGo Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tpl
    16  
    17  // ServiceTpl is the template for generating the servicename.go source.
    18  var ServiceTpl string = `// Code generated by Kitex {{.Version}}. DO NOT EDIT.
    19  {{$HandlerReturnKeepResp := .HandlerReturnKeepResp}}
    20  {{$UseThriftReflection := .UseThriftReflection}}
    21  package {{ToLower .ServiceName}}
    22  
    23  import (
    24  	{{- range $path, $aliases := .Imports}}
    25  		{{- if not $aliases}}
    26  			"{{$path}}"
    27  		{{- else}}
    28  			{{- range $alias, $is := $aliases}}
    29  				{{$alias}} "{{$path}}"
    30  			{{- end}}
    31  		{{- end}}
    32  	{{- end}}
    33  )
    34  
    35  var errInvalidMessageType = errors.New("invalid message type for service method handler")
    36  
    37  {{- if gt (len .CombineServices) 0}}
    38  type {{call .ServiceTypeName}} interface {
    39  {{- range .CombineServices}}
    40  	{{.PkgRefName}}.{{.ServiceName}}
    41  {{- end}}
    42  }
    43  {{- end}}
    44  
    45  var serviceMethods = map[string]kitex.MethodInfo{
    46  	{{- range .AllMethods}}
    47  		"{{.RawName}}": kitex.NewMethodInfo(
    48  			{{LowerFirst .Name}}Handler,
    49  			new{{.ArgStructName}},
    50  			{{if .Oneway}}nil{{else}}new{{.ResStructName}}{{end}},
    51  			{{if .Oneway}}true{{else}}false{{end}},
    52  			kitex.WithStreamingMode(
    53  				{{- if and .ServerStreaming .ClientStreaming -}} kitex.StreamingBidirectional
    54  				{{- else if .ServerStreaming -}} kitex.StreamingServer
    55  				{{- else if .ClientStreaming -}} kitex.StreamingClient
    56  				{{- else -}}
    57  					 {{- if or (eq $.Codec "protobuf") (eq .Streaming.Mode "unary") -}} kitex.StreamingUnary
    58  					 {{- else -}} kitex.StreamingNone
    59  					 {{- end -}}
    60  				{{- end}}),
    61  		),
    62  	{{- end}}
    63  }
    64  
    65  var (
    66  	{{LowerFirst .ServiceName}}ServiceInfo = NewServiceInfo()
    67  	{{LowerFirst .ServiceName}}ServiceInfoForClient = NewServiceInfoForClient()
    68  	{{LowerFirst .ServiceName}}ServiceInfoForStreamClient = NewServiceInfoForStreamClient()
    69  )
    70  
    71  // for server
    72  func serviceInfo() *kitex.ServiceInfo {
    73  	return {{LowerFirst .ServiceName}}ServiceInfo
    74  }
    75  
    76  // for client
    77  func serviceInfoForStreamClient() *kitex.ServiceInfo {
    78  	return {{LowerFirst .ServiceName}}ServiceInfoForStreamClient
    79  }
    80  
    81  // for stream client
    82  func serviceInfoForClient() *kitex.ServiceInfo {
    83  	return {{LowerFirst .ServiceName}}ServiceInfoForClient
    84  }
    85  
    86  // NewServiceInfo creates a new ServiceInfo containing all methods
    87  {{- /* It's for the Server (providing both streaming/non-streaming APIs), or for the grpc client */}}
    88  func NewServiceInfo() *kitex.ServiceInfo {
    89  	return newServiceInfo({{- if .HasStreaming}}true{{else}}false{{end}}, true, true)
    90  }
    91  
    92  // NewServiceInfo creates a new ServiceInfo containing non-streaming methods
    93  {{- /* It's for the KitexThrift Client with only non-streaming APIs */}}
    94  func NewServiceInfoForClient() *kitex.ServiceInfo {
    95  	return newServiceInfo(false, false, true)
    96  }
    97  
    98  {{- /* It's for the StreamClient with only streaming APIs */}}
    99  func NewServiceInfoForStreamClient() *kitex.ServiceInfo {
   100  	return newServiceInfo(true, true, false)
   101  }
   102  
   103  func newServiceInfo(hasStreaming bool, keepStreamingMethods bool, keepNonStreamingMethods bool) *kitex.ServiceInfo {
   104  	serviceName := "{{.RawServiceName}}"
   105  	handlerType := (*{{call .ServiceTypeName}})(nil)
   106  	methods := map[string]kitex.MethodInfo{}
   107  	for name, m := range serviceMethods {
   108  		if m.IsStreaming() && !keepStreamingMethods {
   109  			continue
   110  		}
   111  		if !m.IsStreaming() && !keepNonStreamingMethods {
   112  			continue
   113  		}
   114  		methods[name] = m
   115  	}
   116  	extra := map[string]interface{}{
   117  		"PackageName":	 "{{.PkgInfo.PkgName}}",
   118  		{{- if $UseThriftReflection }}
   119  		"ServiceFilePath": {{ backquoted .ServiceFilePath }},
   120  		{{end}}
   121  	}
   122  	{{- if gt (len .CombineServices) 0}}
   123  	extra["combine_service"] = true
   124  	extra["combined_service_list"] = []string{
   125  		{{- range  .CombineServices}}"{{.ServiceName}}",{{- end}}
   126  	}
   127  	{{- end}}
   128  	if hasStreaming {
   129  		extra["streaming"] = hasStreaming
   130  	}
   131  	svcInfo := &kitex.ServiceInfo{
   132  		ServiceName: 	 serviceName,
   133  		HandlerType: 	 handlerType,
   134  		Methods:     	 methods,
   135  	{{- if ne "Hessian2" .ServiceInfo.Protocol}}
   136  		PayloadCodec:  	 kitex.{{.Codec | UpperFirst}},
   137  	{{- end}}
   138  		KiteXGenVersion: "{{.Version}}",
   139  		Extra:           extra,
   140  	}
   141  	return svcInfo
   142  }
   143  
   144  {{range .AllMethods}}
   145  {{- $isStreaming := or .ClientStreaming .ServerStreaming}}
   146  {{- $unary := and (not .ServerStreaming) (not .ClientStreaming)}}
   147  {{- $clientSide := and .ClientStreaming (not .ServerStreaming)}}
   148  {{- $serverSide := and (not .ClientStreaming) .ServerStreaming}}
   149  {{- $bidiSide := and .ClientStreaming .ServerStreaming}}
   150  {{- $arg := "" }}
   151  {{- if or (eq $.Codec "protobuf") ($isStreaming) }}
   152  {{- $arg = index .Args 0}}{{/* streaming api only supports exactly one argument */}}
   153  {{- end}}
   154  
   155  func {{LowerFirst .Name}}Handler(ctx context.Context, handler interface{}, arg, result interface{}) error {
   156  	{{- if eq $.Codec "protobuf"}} {{/* protobuf logic */}}
   157  	{{- if $unary}} {{/* unary logic */}}
   158  	switch s := arg.(type) {
   159  	case *streaming.Args:
   160  		st := s.Stream
   161  		req := new({{NotPtr $arg.Type}})
   162  		if err := st.RecvMsg(req); err != nil {
   163  			return err
   164  		}
   165  		resp, err := handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}(ctx, req)
   166  		if err != nil {
   167  			return err
   168  		}
   169  		return st.SendMsg(resp)
   170  	case *{{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ArgStructName}}:
   171  		success, err := handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}(ctx{{range .Args}}, s.{{.Name}}{{end}})
   172  		if err != nil {
   173  			return err
   174  		}
   175  		realResult := result.(*{{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ResStructName}})
   176  		realResult.Success = {{if .IsResponseNeedRedirect}}&{{end}}success
   177  		return nil
   178  	default:
   179  		return errInvalidMessageType
   180  	}
   181  	{{- else}}{{/* streaming logic */}}
   182  		streamingArgs, ok := arg.(*streaming.Args)
   183  		if !ok {
   184  			return errInvalidMessageType
   185  		}
   186  		st := streamingArgs.Stream
   187  		stream := &{{LowerFirst .ServiceName}}{{.RawName}}Server{st}
   188  		{{- if $serverSide}}
   189  		req := new({{NotPtr $arg.Type}})
   190  		if err := st.RecvMsg(req); err != nil {
   191  			return err
   192  		}
   193  		{{- end}}
   194  		return handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}({{if $serverSide}}req, {{end}}stream)
   195  	{{- end}} {{/* $unary end */}}
   196  	{{- else}} {{/* thrift logic */}}
   197  	{{- if $unary}} {{/* unary logic */}}
   198  	{{- if eq .Streaming.Mode "unary"}}
   199  	if streaming.GetStream(ctx) == nil {
   200  		return errors.New("{{.ServiceName}}.{{.Name}} is a thrift streaming unary method, please call with Kitex StreamClient or remove the annotation streaming.mode")
   201  	}
   202  	{{- end}}
   203  	{{if gt .ArgsLength 0}}realArg := {{else}}_ = {{end}}arg.(*{{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ArgStructName}})
   204  	{{if or (not .Void) .Exceptions}}realResult := result.(*{{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ResStructName}}){{end}}
   205  	{{if .Void}}err := handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}(ctx{{range .Args}}, realArg.{{.Name}}{{end}})
   206  	{{else}}success, err := handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}(ctx{{range .Args}}, realArg.{{.Name}}{{end}})
   207  	{{end -}}
   208  	if err != nil {
   209  	{{- if $HandlerReturnKeepResp }}
   210  		// still keep resp when err is not nil
   211  		// NOTE: use "-handler-return-keep-resp" to generate this
   212  		{{if not .Void}}realResult.Success = {{if .IsResponseNeedRedirect}}&{{end}}success{{- end}}
   213  	{{- end }}
   214  	{{if .Exceptions -}}
   215  		switch v := err.(type) {
   216  		{{range .Exceptions -}}
   217  		case {{.Type}}:
   218  			 realResult.{{.Name}} = v
   219  		{{end -}}
   220  		default:
   221  			 return err
   222  		}
   223  	} else {
   224  	{{else -}}
   225  		return err
   226  	}
   227  	{{end -}}
   228  	{{if not .Void}}realResult.Success = {{if .IsResponseNeedRedirect}}&{{end}}success{{end}}
   229  	{{- if .Exceptions}}}{{end}}
   230  	return nil
   231  	{{- else}} {{/* $isStreaming */}}
   232  	st, ok := arg.(*streaming.Args)
   233  	if !ok {
   234  		return errors.New("{{.ServiceName}}.{{.Name}} is a thrift streaming method, please call with Kitex StreamClient")
   235  	}
   236  	stream := &{{LowerFirst .ServiceName}}{{.RawName}}Server{st.Stream}
   237  		{{- if not $serverSide}}
   238  	return handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}(stream)
   239  		{{- else}} {{/* !$serverSide */}}
   240  		{{- $RequestType := $arg.Type}}
   241  	req := new({{NotPtr $RequestType}})
   242  	if err := st.Stream.RecvMsg(req); err != nil {
   243  		return err
   244  	}
   245  	return handler.({{.PkgRefName}}.{{.ServiceName}}).{{.Name}}(req, stream)
   246  		{{- end}} {{/* $serverSide end*/}}
   247  	{{- end}} {{/* thrift end */}}
   248  	{{- end}} {{/* protobuf end */}}
   249  }
   250  
   251  {{- /* define streaming struct */}}
   252  {{- if $isStreaming}}
   253  type {{LowerFirst .ServiceName}}{{.RawName}}Client struct {
   254  	streaming.Stream
   255  }
   256  
   257  {{- if or $clientSide $bidiSide}}
   258  func (x *{{LowerFirst .ServiceName}}{{.RawName}}Client) Send(m {{$arg.Type}}) error {
   259  	return x.Stream.SendMsg(m)
   260  }
   261  {{- end}}
   262  
   263  {{- if $clientSide}}
   264  func (x *{{LowerFirst .ServiceName}}{{.RawName}}Client) CloseAndRecv() ({{.Resp.Type}}, error) {
   265  	if err := x.Stream.Close(); err != nil {
   266  		return nil, err
   267  	}
   268  	m := new({{NotPtr .Resp.Type}})
   269  	return m, x.Stream.RecvMsg(m)
   270  }
   271  {{- end}}
   272  
   273  {{- if or $serverSide $bidiSide}}
   274  func (x *{{LowerFirst .ServiceName}}{{.RawName}}Client) Recv() ({{.Resp.Type}}, error) {
   275  	m := new({{NotPtr .Resp.Type}})
   276  	return m, x.Stream.RecvMsg(m)
   277  }
   278  {{- end}}
   279  
   280  type {{LowerFirst .ServiceName}}{{.RawName}}Server struct {
   281  	streaming.Stream
   282  }
   283  
   284  {{if or $serverSide $bidiSide}}
   285  func (x *{{LowerFirst .ServiceName}}{{.RawName}}Server) Send(m {{.Resp.Type}}) error {
   286  	return x.Stream.SendMsg(m)
   287  }
   288  {{end}}
   289  
   290  {{if $clientSide}}
   291  func (x *{{LowerFirst .ServiceName}}{{.RawName}}Server) SendAndClose(m {{.Resp.Type}}) error {
   292  	return x.Stream.SendMsg(m)
   293  }
   294  {{end}}
   295  
   296  {{if or $clientSide $bidiSide}}
   297  func (x *{{LowerFirst .ServiceName}}{{.RawName}}Server) Recv() ({{$arg.Type}}, error) {
   298  	m := new({{NotPtr $arg.Type}})
   299  	return m, x.Stream.RecvMsg(m)
   300  }
   301  {{end}}
   302  
   303  {{- end}}
   304  {{- /* define streaming struct end */}}
   305  func new{{.ArgStructName}}() interface{} {
   306  	return {{if not .GenArgResultStruct}}{{.PkgRefName}}.New{{.ArgStructName}}(){{else}}&{{.ArgStructName}}{}{{end}}
   307  }
   308  {{if not .Oneway}}
   309  func new{{.ResStructName}}() interface{} {
   310  	return {{if not .GenArgResultStruct}}{{.PkgRefName}}.New{{.ResStructName}}(){{else}}&{{.ResStructName}}{}{{end}}
   311  }{{end}}
   312  
   313  {{- if .GenArgResultStruct}}
   314  {{$arg := index .Args 0}}
   315  type {{.ArgStructName}} struct {
   316  	Req {{$arg.Type}}
   317  }
   318  
   319  {{- if and (eq $.Codec "protobuf") (not $.NoFastAPI)}} {{/* protobuf logic */}}
   320  func (p *{{.ArgStructName}}) FastRead(buf []byte, _type int8, number int32) (n int, err error) {
   321  	if !p.IsSetReq() {
   322  		p.Req = new({{NotPtr $arg.Type}})
   323  	}
   324  	return p.Req.FastRead(buf, _type, number)
   325  }
   326  
   327  func (p *{{.ArgStructName}}) FastWrite(buf []byte) (n int) {
   328  	if !p.IsSetReq() {
   329  		return 0
   330  	}
   331  	return p.Req.FastWrite(buf)
   332  }
   333  
   334  func (p *{{.ArgStructName}}) Size() (n int) {
   335  	if !p.IsSetReq() {
   336  		return 0
   337  	}
   338  	return p.Req.Size()
   339  }
   340  {{- end}} {{/* protobuf end */}}
   341  
   342  func (p *{{.ArgStructName}}) Marshal(out []byte) ([]byte, error) {
   343  	if !p.IsSetReq() {
   344  	   return out, nil
   345  	}
   346  	return proto.Marshal(p.Req)
   347  }
   348  
   349  func (p *{{.ArgStructName}}) Unmarshal(in []byte) error {
   350  	msg := new({{NotPtr $arg.Type}})
   351  	if err := proto.Unmarshal(in, msg); err != nil {
   352  	   return err
   353  	}
   354  	p.Req = msg
   355  	return nil
   356  }
   357  
   358  var {{.ArgStructName}}_Req_DEFAULT {{$arg.Type}}
   359  
   360  func (p *{{.ArgStructName}}) GetReq() {{$arg.Type}} {
   361  	if !p.IsSetReq() {
   362  	   return {{.ArgStructName}}_Req_DEFAULT
   363  	}
   364  	return p.Req
   365  }
   366  
   367  func (p *{{.ArgStructName}}) IsSetReq() bool {
   368  	return p.Req != nil
   369  }
   370  
   371  func (p *{{.ArgStructName}}) GetFirstArgument() interface{} {
   372  	return p.Req
   373  }
   374  
   375  type {{.ResStructName}} struct {
   376  	Success {{.Resp.Type}}
   377  }
   378  
   379  var {{.ResStructName}}_Success_DEFAULT {{.Resp.Type}}
   380  
   381  {{- if and (eq $.Codec "protobuf") (not $.NoFastAPI)}} {{/* protobuf logic */}}
   382  func (p *{{.ResStructName}}) FastRead(buf []byte, _type int8, number int32) (n int, err error) {
   383  	if !p.IsSetSuccess() {
   384  		p.Success = new({{NotPtr .Resp.Type}})
   385  	}
   386  	return p.Success.FastRead(buf, _type, number)
   387  }
   388  
   389  func (p *{{.ResStructName}}) FastWrite(buf []byte) (n int) {
   390  	if !p.IsSetSuccess() {
   391  		return 0
   392  	}
   393  	return p.Success.FastWrite(buf)
   394  }
   395  
   396  func (p *{{.ResStructName}}) Size() (n int) {
   397  	if !p.IsSetSuccess() {
   398  		return 0
   399  	}
   400  	return p.Success.Size()
   401  }
   402  {{- end}} {{/* protobuf end */}}
   403  
   404  func (p *{{.ResStructName}}) Marshal(out []byte) ([]byte, error) {
   405  	if !p.IsSetSuccess() {
   406  	   return out, nil
   407  	}
   408  	return proto.Marshal(p.Success)
   409  }
   410  
   411  func (p *{{.ResStructName}}) Unmarshal(in []byte) error {
   412  	msg := new({{NotPtr .Resp.Type}})
   413  	if err := proto.Unmarshal(in, msg); err != nil {
   414  	   return err
   415  	}
   416  	p.Success = msg
   417  	return nil
   418  }
   419  
   420  func (p *{{.ResStructName}}) GetSuccess() {{.Resp.Type}} {
   421  	if !p.IsSetSuccess() {
   422  	   return {{.ResStructName}}_Success_DEFAULT
   423  	}
   424  	return p.Success
   425  }
   426  
   427  func (p *{{.ResStructName}}) SetSuccess(x interface{}) {
   428  	p.Success = x.({{.Resp.Type}})
   429  }
   430  
   431  func (p *{{.ResStructName}}) IsSetSuccess() bool {
   432  	return p.Success != nil
   433  }
   434  
   435  func (p *{{.ResStructName}}) GetResult() interface{} {
   436  	return p.Success
   437  }
   438  {{- end}}
   439  {{end}}
   440  
   441  type kClient struct {
   442  	c client.Client
   443  }
   444  
   445  func newServiceClient(c client.Client) *kClient {
   446  	return &kClient{
   447  		c: c,
   448  	}
   449  }
   450  
   451  {{range .AllMethods}}
   452  {{- if or .ClientStreaming .ServerStreaming}}
   453  {{- /* streaming logic */}}
   454  func (p *kClient) {{.Name}}(ctx context.Context{{if not .ClientStreaming}}{{range .Args}}, {{LowerFirst .Name}} {{.Type}}{{end}}{{end}}) ({{.ServiceName}}_{{.RawName}}Client, error) {
   455  	streamClient, ok := p.c.(client.Streaming)
   456  	if !ok {
   457  		return nil, fmt.Errorf("client not support streaming")
   458  	}
   459  	res := new(streaming.Result)
   460  	err := streamClient.Stream(ctx, "{{.RawName}}", nil, res)
   461  	if err != nil {
   462  		return nil, err
   463  	}
   464  	stream := &{{LowerFirst .ServiceName}}{{.RawName}}Client{res.Stream}
   465  	{{if not .ClientStreaming -}}
   466  	{{$arg := index .Args 0}}
   467  	if err := stream.Stream.SendMsg({{LowerFirst $arg.Name}}); err != nil {
   468  		return nil, err
   469  	}
   470  	if err := stream.Stream.Close(); err != nil {
   471  		return nil, err
   472  	}
   473  	{{end -}}
   474  	return stream, nil
   475  }
   476  {{- else}}
   477  func (p *kClient) {{.Name}}(ctx context.Context {{range .Args}}, {{.RawName}} {{.Type}}{{end}}) ({{if not .Void}}r {{.Resp.Type}}, {{end}}err error) {
   478  	var _args {{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ArgStructName}}
   479  	{{range .Args -}}
   480  	_args.{{.Name}} = {{.RawName}}
   481  	{{end -}}
   482  {{if .Void -}}
   483  	{{if .Oneway -}}
   484  	if err = p.c.Call(ctx, "{{.RawName}}", &_args, nil); err != nil {
   485  		return
   486  	}
   487  	{{else -}}
   488  	var _result {{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ResStructName}}
   489  	if err = p.c.Call(ctx, "{{.RawName}}", &_args, &_result); err != nil {
   490  		return
   491  	}
   492  	{{if .Exceptions -}}
   493  	switch {
   494  	{{range .Exceptions -}}
   495  	case _result.{{.Name}} != nil:
   496  		return _result.{{.Name}}
   497  	{{end -}}
   498  	}
   499  	{{end -}}
   500  	{{end -}}
   501  	return nil
   502  {{else -}}
   503  	var _result {{if not .GenArgResultStruct}}{{.PkgRefName}}.{{end}}{{.ResStructName}}
   504  	if err = p.c.Call(ctx, "{{.RawName}}", &_args, &_result); err != nil {
   505  		return
   506  	}
   507  	{{if .Exceptions -}}
   508  	switch {
   509  	{{range .Exceptions -}}
   510  	case _result.{{.Name}} != nil:
   511  		return r, _result.{{.Name}}
   512  	{{end -}}
   513  	}
   514  	{{end -}}
   515  	return _result.GetSuccess(), nil
   516  {{end -}}
   517  }
   518  {{- end}}
   519  {{end}}
   520  
   521  {{- if .FrugalPretouch}}
   522  var pretouchOnce sync.Once
   523  func pretouch() {
   524  	pretouchOnce.Do(func() {
   525  {{- if gt (len .AllMethods) 0}}
   526  		var err error
   527  {{- range .AllMethods}}
   528  		err = frugal.Pretouch(reflect.TypeOf({{if not .GenArgResultStruct}}{{.PkgRefName}}.New{{.ArgStructName}}(){{else}}&{{.ArgStructName}}{}{{end}}))
   529  		if err != nil {
   530  			goto PRETOUCH_ERR
   531  		}
   532  {{- if not .Oneway}}
   533  		err = frugal.Pretouch(reflect.TypeOf({{if not .GenArgResultStruct}}{{.PkgRefName}}.New{{.ResStructName}}(){{else}}&{{.ResStructName}}{}{{end}}))
   534  		if err != nil {
   535  			goto PRETOUCH_ERR
   536  		}
   537  {{- end}}
   538  {{- end}}{{/* range .AllMethods */}}
   539  	return
   540  PRETOUCH_ERR:
   541  	println("Frugal pretouch in {{.ServiceName}} failed: " + err.Error())
   542  {{- end}}{{/* if gt (len .AllMethods) 0 */}}
   543  	})
   544  }
   545  {{- end}}{{/* if .FrugalPretouch */}}
   546  `