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 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
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 field_name1 = 1 [json_name = "FieldName1"];
// field comment 2
repeated uint64 field_name2 = 2 [json_name = "FieldName2"];
}

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

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

var fieldComments map[string]string
if rinfo.Package != nil {
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 +218,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
72 changes: 70 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,69 @@
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 {
genDecl, ok := node.(*ast.GenDecl)
if !ok {
return true
}
for _, spec := range genDecl.Specs {
typeSpec, ok := spec.(*ast.TypeSpec)
if !ok {
continue

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

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L215 - L223 were not covered by tests
}

pkgType := pkg.getTypeByName(typeSpec.Name.Name)
if pkgType == nil {
continue

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L226-L228

Added lines #L226 - L228 were not covered by tests
}
if genDecl.Doc != nil {
// Set the type comment.
pkgType.Comment = strings.TrimSpace(genDecl.Doc.Text())
}

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

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L230 - L233 were not covered by tests

structType, ok := typeSpec.Type.(*ast.StructType)
if !ok {
continue

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L235-L237

Added lines #L235 - L237 were not covered by tests
}
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 {
pkgType.FieldComments = make(map[string]string)
}

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L239-L244

Added lines #L239 - L244 were not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L246

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

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L250

Added line #L250 was not covered by tests
})

return pkg

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L253

Added line #L253 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 261 in tm2/pkg/amino/pkg/pkg.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L257-L261

Added lines #L257 - L261 were not covered by tests
}

return nil

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

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/amino/pkg/pkg.go#L264

Added line #L264 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