Giter Club home page Giter Club logo

gowrap's Issues

log template not emitting anything if method returns value but no error

Very minor point about the provided log template.
If I have a method that returns a single result, but not an error, the template generates a deferred function to set the results but these are not emitted by a log call.
Consequently, the generated code fails to compile because of an unused variable.

I addressed the issue by adding the following before line 42 of the template:

{{else}}   
  _d._stdlog.Println(_results...)

Can't loading template during the gen

good afternoon

I've tried to generate a tracing wrapper by my custom teplate which is uploading from github https://github.com/XeniaBgd/templates/blob/main/tracing

The command is :
gowrap gen -p ./internal/domain/repository -i Repository -t https://raw.githubusercontent.com/XeniaBgd/templates/main/tracing -o ./internal/providers/analytics/tracing.go

But I've got this error:
"failed to load template: open https://raw.githubusercontent.com/XeniaBgd/templates/main/tracing: The filename, directory name, or volume label syntax is incorrect"

I've checked code
https://github.com/hexdigest/gowrap/blob/master/cmd_generate.go#L191

func underlyingErrorIs(err, target error) bool {
// Note that this function is not errors.Is:
// underlyingError only unwraps the specific error-wrapping types
// that it historically did, not all errors implementing Unwrap().
err = underlyingError(err)
if err == target {
return true
}
// To preserve prior behavior, only examine syscall errors.
e, ok := err.(syscallErrorType)
return ok && e.Is(target)
}

My error was "internal/syscall/windows.ERROR_INVALID_NAME (123)". That's why the function above returned false.

//if !os.IsNotExist(err) {
// return
//}

Without this code everything is ok.

Could somebody explain me why was that?

Merge generated file with existing instead of overwriting

I want to edit generated methods and I want them not to be overwritten by next generation. If new methods are added to interface I want them to be generated and added to the existing file.

So what I want is some kind of strategy. Invocation may look like:

gowrap gen -i Some -t mine.tmpl -o generated.go -strategy merge|overwrite

How woild this work:

Template:

type {{$decorator}} struct {
  logger *zap.Logger
  next {{.Interface.Type}}
}

{{range $method := .Interface.Methods}}
func (m *{{$decorator}}) {{$method.Declaration}} {
    m.logger.Info("{{ $method.Name }}")
    {{ $method.Pass "m.next." }}
}
{{end}}

Initial interface:

type Some interface {
    A()
}

Initial generated file:

type decorator struct {
    logger *zap.Logger
    next Some
}

func (d *decorator) A() {
    m.logger.Info("A") 
    m.next.A()
}

Updated file:

type decorator struct {
    logger *zap.Logger
    next Some
}

func (d *decorator) A() {
    m.logger.Info("A with updates") // updated generated file
    m.next.A()
}

Updated interface:

type Some interface {
    A()
    B() // New added method
}

Generated with stratedy 'merge' file:

type decorator struct {
    logger *zap.Logger
    next Some
}

func (d *decorator) A() {
    m.logger.Info("A with updates") // updates are not overwritten
    m.next.A()
}

func (d *decorator) B() {
    m.logger.Info("B") 
    m.next.A()
}

If you believe there is a place for such a feature in this library I might be able to implement it myself.

Add support for internal packages

When I try to generate a wrapper from an interface in an internal package, gowrap fails.

/path/to/package/internal/generated/prom_test.go:

package generated

//go:generate gowrap gen -g -p . -i TestInterface -t prometheus -o prom.go

type TestInterface interface{
    TestMethod()
}
go generate ./...
failed to parse source package: open repo.git/path/to/package/internal/generated: no such file or directory
internal/generated/prom_test.go:3: running "gowrap": exit status 1

Moving the file out of the internal subpackage makes it work.

Access to Package Name in Body Template

We need access to the interface’s package name in a template.
We can see this is available when the header template is executed, but don’t think it is available to body templates.
Could this be made available in the map?

Also, is there any way to customise the header template?

template path in generated code uses OS specific path separators

When using file paths to specify the location of a template, the generated code will use either a "/" or a "\" to separate directories in the path. This is an issue if you checkin the generated code and you have some users that generate using a Linux system and other users that generate using a Windows system.

The expectation is that the generated code should not change based on what type of system the generation is performed on.

Propose to do a simple search/replace on the file path and replace any "\" with a "/"

method.Declaration does not add package names in argument types and return types

The
func (_d {{$decorator}}) {{$method.Declaration}} {
line generates

func (_d wrapped) Method(ctx context.Context, paramName ParamType) (returnName ReturnType)
instead of the expected
func (_d wrapped) Method(ctx context.Context, paramName wrappedtype.ParamType) (returnName wrappedtype.ReturnType)

This change in behaviour has happened between release 1.2.7 and 1.3.0

Prometheus metric is not registered

Prometheus metrics must be registered. Not registered metrics are not avaliable in metrics path.

There are two ways to resolve it:
*Add metric registration in constructor
*Make metric variable public and delegate registration to developer

template/retry: do not use time.After

I think, it should not be difficult to change usage of time.After to time.NewTimer.
The problem is described in docs of time.After.
I some edge cases it should reduce memory consumption.
Because it is a template, it should not break back capability.

{{range $method := .Interface.Methods}}
	{{if $method.ReturnsError}}
	// {{$method.Name}} implements {{$.Interface.Type}}
	func (_d {{$decorator}}) {{$method.Declaration}} {
		for _i := 0; _i < _d._retryCount; _i++ {
			{{$method.ResultsNames}} = _d.{{$.Interface.Name}}.{{$method.Call}}
			if err == nil {
				break
			}
			if _d._retryCount > 1 {
				{{- if $method.AcceptsContext}}
				_t := time.NewTimer(_d._retryInterval)
				defer _t.Stop()
				select {
				case <-ctx.Done():
					return {{$method.ResultsNames}}
				case <-_t.C:
				}
				{{else}}
				time.Sleep(_d._retryInterval)
				{{end -}}
			}
		}
		return {{$method.ResultsNames}}
	}
	{{end}}
{{end}}

Unable to generate if destination directory does not contain go files

When trying to generate files with -o option pointing to an empty directory the command fails with
failed to load destination package <relative_destination_package_path> -: unknown import path <full_destination_package_path>: cannot find module providing package <full_destination_package_path>

The error goes away if any .go file is created into destination directory.

Imports of modules with custom names are not included into generated code

The generator does not work with the case when the name of the package imported into source file does not match last import path segment.

For example, source file like

package authz

import (
	"mymodulename/pkg/api/iam/v1" // Go package name is "iamv1"
)

type Enforcer interface {
	Enforce(ctx context.Context, request *iamv1.Request) ([]string, error)
}

Will result generated code that is using *iamv1.Request type in method signatures, however mymodulename/pkg/api/iam/v1 will not be added to the imports section.

I tried all sorts of aliases for this module, however, nothing helps. Generator only works if I rename imported package to v1.

Unable to install this package

I'm trying to install gowrap using command go get -u github.com/hexdigest/gowrap/cmd/gowrap
And receiving an error:

go get: github.com/cavaliercoder/[email protected] updating to
github.com/cavaliercoder/[email protected]: parsing go.mod:
module declares its path as: github.com/cavaliergopher/cpio
but was required as: github.com/cavaliercoder/go-cpio

comments on the top of generated file

Greetings!
We use gowrap and golines in out project. As you can see here golines checks a few top lines of each file to check if it generated, but gowrap places comments after imports block

Screenshot ![image](https://user-images.githubusercontent.com/6426720/136575496-b641600a-e7e2-4922-aa9d-db17b5bc81f9.png)

Could you fix it and place comments on the top?

Add support for build tags

When attempting to generate from a file with a build tag, gowrap exits with an error.

//go:build unit

package main

//go:generate gowrap gen -g -p . -i TestInterface -t prometheus -o prom.go

type TestInterface interface{
    TestMethod()
}
go generate -tags unit ./...
failed to load source package: -: build constraints exclude all Go files in /path/to/package
path/to/package/prom_test.go:5: running "gowrap": exit status 1

Access to Documentation Comments

We would like to be able to make interface and method ‘documentation’ comments available to templates.

For example, we would like to use a method comment to provide hints to a logging decorator about what and how to log specific params and results (avoiding monolithic log output, hiding sensitive data etc)

The documentary comments are readily available in the ast and so could be copied to the template input.

I’m happy to prototype this and raise a pull request, but would welcome your opinion on whether this would be a useful feature.

.Interface.Methods no longer contains nested methods

proofOfBug.tpl:

{{range $method := .Interface.Methods}}
func {{$method.Declaration}}{}
{{end}}

proofOfBug.go:

//go:generate gowrap gen -g  -v DecoratorName=POC -i Base -t proofOfBug.tpl -o proofOfBug.gen.go
type Base interface {
	A()
	Nested
}

type Nested interface {
	B()
}

version 1.2.7 did not ignore nesteds

Wrong position of package comment if template has no own `import`

If template has own import section (e.g. with github.com/prometheus/client_golang/prometheus) then the generated file header looks correct :

package name

// DO NOT EDIT!
// This code is generated with http://github.com/hexdigest/gowrap tool
// using templates/metrics template

import (
	"context"
	
	"github.com/prometheus/client_golang/prometheus"
)

But if template doesn't have own import section then package comment goes after import in generated file. It looks bad:

package name

import (
	"context"
)

// DO NOT EDIT!
// This code is generated with http://github.com/hexdigest/gowrap tool
// using templates/metrics template

import() in the beginning of template fixes it but looks weird.

Method.ReturnsError is not a proper interface/implements check

I have code that implements a more advanced error model which is passed around as its own interface rather than error (which it does, implement). The code:

https://github.com/hexdigest/gowrap/blob/master/generator/types.go#L95

Dees not do an error interface check and therefore does not work for anything except a literal error type. A proper type check would look something like:

var paramType ast.Type
types.Implements(paramType, ErrorInterface)

where:

// ErrorInterface defines the error interface as a type for comparison.
var ErrorInterface = types.NewInterfaceType([]*types.Func{
	types.NewFunc(
		0,
		nil,
		"Error",
		types.NewSignatureType(nil, nil, nil, nil,
			types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.String])),
			false)),
}, nil)

Unfortunately this would require a much larger re-writing of the existing code so I'm only filing an issue instead of a fix :(.

Reason for errUnexportableType error

I am curious to know why the use of an unexported type should abort decorator generation (line 138 of printer.go).

I want to generate decorators for an interface that is only used in the context of the package in which it is defined, but this error blocks me from doing that.

If I comment out the check, everything is generated as I need.

Cannot iterate over m.Params names

I am trying to implement a custom template which needs to provide each of the method's parameters in a certain way

Based on the log template here: https://github.com/hexdigest/gowrap/blob/master/templates/log

I need to make this code

 _params := []interface{}{"{{$decorator}}: calling {{$method.Name}} with params:", {{$method.ParamsNames}} }

To be this code instead

      var _params []zapcore.Field
      var _field zapcore.Field
      {{range $param := $method.ParamsSlice}}
      _field = zapcore.Field{ Key:"{{$decorator}}: calling {{$method.Name}} with params:", Type: zapcore.ObjectMarshalerType, Interface: {{$param.Name}}}
      _params = append(_params, _field)
      {{end}}

To make it happen had to add the ParamsSlice function to gowrap code, so the slice is public and available to be used. I may be missing something or not?

This is the code I've added to types.go to make it work

// ParamsSlice returns a list of method params
func (m Method) ParamsSlice() []Param {
	return m.Params
}

Hope this makes sense or please point me to the best practice to consuming that data

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.