8000 feat: support embed struct fields without `tstype: ",extends"` by mtt0 · Pull Request #35 · gzuidhof/tygo · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: support embed struct fields without tstype: ",extends" #35

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

Merged
merged 3 commits into from
Aug 25, 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
2 changes: 1 addition & 1 deletion examples/bookstore/book.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ type Book struct {
}

type TextBook[T int] struct {
Book ` tstype:",inline"`
Book `tstype:",extends"`
Pages T ` json:"pages"`
}
2 changes: 1 addition & 1 deletion examples/bookstore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ export interface Book {
chapters: Chapter[];
published_at?: string /* RFC 3339 formatted */;
}
export interface TextBook<T extends number /* int */> {
export interface TextBook<T extends number /* int */> extends Book {
pages: T;
}
16 changes: 16 additions & 0 deletions examples/embed/embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package embed

import bookapp "github.com/gzuidhof/tygo/examples/bookstore"

// TokenType Built-in type alias
type TokenType string

type StructEmbed struct {
Base `json:",inline" tstype:",extends"` // embed struct with `tstype:"extends"`
TokenType `json:"tokenType"` // built-in type field without `tstype:"extends"`
Reference `json:"reference"` // embed struct without `tstype:"extends"`
OtherReference Reference `json:"other_reference"`
Bar string `json:"bar"`
bookapp.Book `json:"book"` // embed external struct without `tstype:"extends"`
*bookapp.Chapter `json:"chapter"` // embed external struct pointer without `tstype:"extends"`
}
34 changes: 34 additions & 0 deletions examples/embed/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Code generated by tygo. DO NOT EDIT.
import * as bookapp from "../bookstore"

//////////
// source: embed.go

/**
* TokenType Built-in type alias
*/
export type TokenType = string;
export interface StructEmbed extends Base {
tokenType: TokenType; // built-in type field without `tstype:"extends"`
reference: Reference; // embed struct without `tstype:"extends"`
other_reference: Reference;
bar: string;
book: bookapp.Book; // embed external struct without `tstype:"extends"`
chapter?: bookapp.Chapter; // embed external struct pointer without `tstype:"extends"`
}

//////////
// source: types.go
/*
Package embed types defined in the Go file after the parsed file in the same package
*/

export interface Base {
id: string;
}
/**
* Reference struct type, defined after embed.go, the same pkg but not the same file
*/
export interface Reference {
foo: string;
}
11 changes: 11 additions & 0 deletions examples/embed/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Package embed types defined in the Go file after the parsed file in the same package
package embed

type Base struct {
ID string `json:"id"`
}

// Reference struct type, defined after embed.go, the same pkg but not the same file
type Reference struct {
Foo string `json:"foo"`
}
8 changes: 8 additions & 0 deletions tygo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ packages:
frontmatter:
| # We can define some additional text to put at the start of the file.
import * as bookapp from "../bookstore"
- path: "github.com/gzuidhof/tygo/examples/embed"
fallback_type: unknown
type_mappings:
bookapp.Book: "bookapp.Book"
bookapp.Chapter: "bookapp.Chapter"
frontmatter:
| # We can define some additional text to put at the start of the file.
import * as bookapp from "../bookstore"
- path: "github.com/gzuidhof/tygo/examples/generic"
fallback_type: unknown
- path: "github.com/gzuidhof/tygo/examples/preserveTypeComments"
Expand Down
5 changes: 5 additions & 0 deletions tygo/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ func (g *PackageGenerator) writeStructFields(s *strings.Builder, fields []*ast.F
readonly := false

var fieldName string
if len(f.Names) == 0 { // anonymous field
if name, valid := getAnonymousFieldName(f.Type); valid {
fieldName = name
}
}
if len(f.Names) != 0 && f.Names[0] != nil && len(f.Names[0].Name) != 0 {
fieldName = f.Names[0].Name
}
Expand Down
32 changes: 32 additions & 0 deletions tygo/write_toplevel.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tygo
import (
"fmt"
"go/ast"
"go/token"
"strings"

"github.com/fatih/structtag"
Expand Down Expand Up @@ -241,6 +242,10 @@ func getInheritedType(f ast.Expr, tag *structtag.Tag) (name string, valid bool)
valid = isStruct && dcl.Name.IsExported()
name = dcl.Name.Name
}
} else {
// Types defined in the Go file after the parsed file in the same package
valid = token.IsExported(ft.Name)
name = ft.Name
}
case *ast.IndexExpr:
name, valid = getInheritedType(ft.X, tag)
Expand Down Expand Up @@ -272,3 +277,30 @@ func getInheritedType(f ast.Expr, tag *structtag.Tag) (name string, valid bool)
}
return
}

func getAnonymousFieldName(f ast.Expr) (name string, valid bool) {
switch ft := f.(type) {
case *ast.Ident:
name = ft.Name
if ft.Obj != nil && ft.Obj.Decl != nil {
dcl, ok := ft.Obj.Decl.(*ast.TypeSpec)
if ok {
valid = dcl.Name.IsExported()
}
} else {
// Types defined in the Go file after the parsed file in the same package
valid = token.IsExported(name)
}
case *ast.IndexExpr:
return getAnonymousFieldName(ft.X)
case *ast.IndexListExpr:
return getAnonymousFieldName(ft.X)
case *ast.SelectorExpr:
valid = ft.Sel.IsExported()
name = ft.Sel.String()
case *ast.StarExpr:
return getAnonymousFieldName(ft.X)
}

return
}
0