Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: In amino.pkg, add optional WithComments, use them in GenerateProto3MessagePartial #1235

Merged
merged 4 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
61 changes: 61 additions & 0 deletions tm2/pkg/amino/genproto/comments_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package genproto

import (
"path"
"testing"

"github.com/gnolang/gno/tm2/pkg/amino"
"github.com/jaekwon/testify/assert"
)

// message comment
type TestMessageName struct {
// field comment 1
FieldName1 string
// field comment 2
FieldName2 []uint64
}

// message comment 2
type TestMessageName2 struct {
// another field comment
FieldName string
}

func TestComments(t *testing.T) {
pkg := amino.RegisterPackage(
amino.NewPackage(
"github.com/gnolang/gno/tm2/pkg/amino/genproto",
"amino_test",
amino.GetCallersDirname(),
).WithTypes(
&TestMessageName{},
&TestMessageName2{},
// Add comments from this same source file.
).WithComments(path.Join(amino.GetCallersDirname(), "comments_test.go")))

p3c := NewP3Context()
p3c.RegisterPackage(pkg)
p3c.ValidateBasic()
p3doc := p3c.GenerateProto3SchemaForTypes(pkg, pkg.ReflectTypes()...)
proto3Schema := p3doc.Print()
assert.Equal(t, proto3Schema, `syntax = "proto3";
package amino_test;

option go_package = "github.com/gnolang/gno/tm2/pkg/amino/genproto/pb";

// messages
// message comment
message TestMessageName {
// field comment 1
string FieldName1 = 1;
// field comment 2
repeated uint64 FieldName2 = 2;
}

// message comment 2
message TestMessageName2 {
// another field comment
string FieldName = 1;
}`)
}
10 changes: 10 additions & 0 deletions tm2/pkg/amino/genproto/genproto.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ func (p3c *P3Context) GenerateProto3MessagePartial(p3doc *P3Doc, rt reflect.Type

p3msg.Name = info.Name // not rinfo.

var fieldComments map[string]string
if pkgType, ok := rinfo.Package.GetType(rt); ok {
p3msg.Comment = pkgType.Comment
// We will check for optional field comments below.
fieldComments = pkgType.FieldComments
}

// Append to p3msg.Fields, fields of the struct.
for _, field := range rsfields { // rinfo.
fp3, fp3IsRepeated, implicit := typeToP3Type(info.Package, field.TypeInfo, field.FieldOptions)
Expand All @@ -209,6 +216,9 @@ func (p3c *P3Context) GenerateProto3MessagePartial(p3doc *P3Doc, rt reflect.Type
JSONName: field.JSONName,
Number: field.FieldOptions.BinFieldNum,
}
if fieldComments != nil {
p3Field.Comment = fieldComments[field.Name]
}
p3msg.Fields = append(p3msg.Fields, p3Field)
}

Expand Down
62 changes: 60 additions & 2 deletions tm2/pkg/amino/pkg/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"path/filepath"
"reflect"
"regexp"
Expand All @@ -11,8 +14,10 @@

type Type struct {
Type reflect.Type
Name string // proto3 name (override)
PointerPreferred bool // whether pointer is preferred for decoding interface.
Name string // proto3 name (override)
PointerPreferred bool // whether pointer is preferred for decoding interface.
Comment string // optional doc comment for the type
FieldComments map[string]string // If not nil, the optional doc comment for each field name
}

func (t *Type) FullName(pkg *Package) string {
Expand Down Expand Up @@ -196,6 +201,59 @@
return pkg
}

// Parse the Go code in filename and scan the AST looking for struct doc comments.
// Find the Type in pkg.Types and set its Comment and FieldComments, which are
// used by genproto.GenerateProto3MessagePartial to set the Comment in the P3Doc
// and related P3Field objects.
func (pkg *Package) WithComments(filename string) *Package {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
if err != nil {
panic(err)

Check warning on line 212 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L208-L212

Added lines #L208 - L212 were not covered by tests
}

ast.Inspect(f, func(node ast.Node) bool {
if genDecl, ok := node.(*ast.GenDecl); ok {
for _, spec := range genDecl.Specs {
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
if pkgType := pkg.getTypeByName(typeSpec.Name.Name); pkgType != nil {
if genDecl.Doc != nil {
// Set the type comment.
pkgType.Comment = strings.TrimSpace(genDecl.Doc.Text())
}
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
for _, field := range structType.Fields.List {
if field.Names != nil && len(field.Names) == 1 && field.Doc != nil {
// Set the field comment.
if pkgType.FieldComments == nil {
thehowl marked this conversation as resolved.
Show resolved Hide resolved
pkgType.FieldComments = make(map[string]string)
}

Check warning on line 230 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L215-L230

Added lines #L215 - L230 were not covered by tests

pkgType.FieldComments[field.Names[0].Name] = strings.TrimSpace(field.Doc.Text())

Check warning on line 232 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L232

Added line #L232 was not covered by tests
}
}
}
}
}
}
}
return true

Check warning on line 240 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L240

Added line #L240 was not covered by tests
})

return pkg

Check warning on line 243 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L243

Added line #L243 was not covered by tests
}

// Get the Type by name. If not found, return nil.
func (pkg *Package) getTypeByName(name string) *Type {
for _, t := range pkg.Types {
if t.Name == name {
return t
}

Check warning on line 251 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L247-L251

Added lines #L247 - L251 were not covered by tests
}

return nil

Check warning on line 254 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L254

Added line #L254 was not covered by tests
}

// Result cannot be modified.
func (pkg *Package) GetType(rt reflect.Type) (t Type, ok bool) {
if rt.Kind() == reflect.Ptr {
Expand Down
Loading