Skip to content

Commit

Permalink
Better handling of types defined in different files in the package.
Browse files Browse the repository at this point in the history
  • Loading branch information
diegofrata committed Feb 15, 2023
1 parent 4f41402 commit 713f9c5
Show file tree
Hide file tree
Showing 18 changed files with 159 additions and 60 deletions.
6 changes: 6 additions & 0 deletions examples/everything/child.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package everything

type Child struct {
ID ChildID `json:"id"`
Name string `json:"name"`
}
30 changes: 15 additions & 15 deletions examples/everything/everything.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ import 'package:json_annotation/json_annotation.dart';

part 'everything.g.dart';

@JsonSerializable()
class Child {
final int id;
final String name;

Child({
required this.id,
required this.name,
});

Map<String, dynamic> toJson() => _$ChildToJson(this);

factory Child.fromJson(Map<String, dynamic> json) => _$ChildFromJson(json);
}

@JsonSerializable()
class Parent {
final String id;
Expand Down Expand Up @@ -75,18 +90,3 @@ class Parent {
factory Parent.fromJson(Map<String, dynamic> json) => _$ParentFromJson(json);
}

@JsonSerializable()
class Child {
final int id;
final String name;

Child({
required this.id,
required this.name,
});

Map<String, dynamic> toJson() => _$ChildToJson(this);

factory Child.fromJson(Map<String, dynamic> json) => _$ChildFromJson(json);
}

5 changes: 5 additions & 0 deletions examples/everything/ids.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package everything

type ParentID string

type ChildID int64
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"time"
)

type ParentID string

type Parent struct {
ID ParentID `json:"id"`

Expand Down Expand Up @@ -45,10 +43,3 @@ type Parent struct {
Map1 map[string]float64 `json:"map1"`
Map2 map[ChildID]Child `json:"map2_weird_name"`
}

type ChildID int64

type Child struct {
ID ChildID `json:"id"`
Name string `json:"name"`
}
15 changes: 8 additions & 7 deletions generator/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,25 @@ package generator

import (
"fmt"
"github.com/11wizards/go-to-dart/generator/format"
"github.com/openconfig/goyang/pkg/indent"
"go/ast"
"io"
)

func generateFields(wr io.Writer, st *ast.StructType) {
func generateFields(wr io.Writer, st *ast.StructType, registry *format.TypeFormatterRegistry) {
for _, f := range st.Fields.List {
generateFieldDeclaration(wr, f)
generateFieldDeclaration(wr, f, registry)
fmt.Fprintln(wr, ";")
}
fmt.Fprintln(wr)
}

func generateConstructor(wr io.Writer, ts *ast.TypeSpec, st *ast.StructType) {
func generateConstructor(wr io.Writer, ts *ast.TypeSpec, st *ast.StructType, registry *format.TypeFormatterRegistry) {
fmt.Fprintf(wr, "%s({\n", ts.Name)

for _, f := range st.Fields.List {
generateFieldConstrutor(indent.NewWriter(wr, "\t"), f)
generateFieldConstrutor(indent.NewWriter(wr, "\t"), f, registry)
fmt.Fprintln(wr, ",")
}

Expand All @@ -36,14 +37,14 @@ func generateDeserialization(wr io.Writer, ts *ast.TypeSpec) {
fmt.Fprintf(wr, "factory %s.fromJson(Map<String, dynamic> json) => _$%sFromJson(json);\n", ts.Name, ts.Name)
}

func generateDartClass(outputFile io.Writer, ts *ast.TypeSpec, st *ast.StructType) bool {
func generateDartClass(outputFile io.Writer, ts *ast.TypeSpec, st *ast.StructType, registry *format.TypeFormatterRegistry) bool {
fmt.Fprintln(outputFile, "@JsonSerializable()")
fmt.Fprintf(outputFile, "class %s {\n", ts.Name)

wr := indent.NewWriter(outputFile, "\t")

generateFields(wr, st)
generateConstructor(wr, ts, st)
generateFields(wr, st, registry)
generateConstructor(wr, ts, st, registry)
generateSerialization(wr, ts)
generateDeserialization(wr, ts)

Expand Down
8 changes: 4 additions & 4 deletions generator/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"io"
)

func generateFieldDeclaration(writer io.Writer, f *ast.Field) {
formatter := format.GetTypeFormatter(f.Type)
func generateFieldDeclaration(writer io.Writer, f *ast.Field, registry *format.TypeFormatterRegistry) {
formatter := registry.GetTypeFormatter(f.Type)
fieldName := format.GetFieldName(f)
jsonFieldName := format.GetJSONFieldName(f)

Expand All @@ -21,7 +21,7 @@ func generateFieldDeclaration(writer io.Writer, f *ast.Field) {
fmt.Fprintf(writer, "final %s", formatter.Declaration(format.GetFieldName(f), f.Type))
}

func generateFieldConstrutor(writer io.Writer, f *ast.Field) {
formatter := format.GetTypeFormatter(f.Type)
func generateFieldConstrutor(writer io.Writer, f *ast.Field, registry *format.TypeFormatterRegistry) {
formatter := registry.GetTypeFormatter(f.Type)
fmt.Fprint(writer, formatter.Constructor(format.GetFieldName(f), f.Type))
}
5 changes: 3 additions & 2 deletions generator/format/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

type AliasFormatter struct {
TypeFormatterBase
}

func (f *AliasFormatter) under(expr ast.Expr) *ast.Ident {
Expand All @@ -25,7 +26,7 @@ func (f *AliasFormatter) CanFormat(expr ast.Expr) bool {

func (f *AliasFormatter) Signature(expr ast.Expr) string {
u := f.under(expr)
return GetTypeFormatter(u).Signature(u)
return f.Registry.GetTypeFormatter(u).Signature(u)
}

func (f *AliasFormatter) Declaration(fieldName string, expr ast.Expr) string {
Expand All @@ -34,5 +35,5 @@ func (f *AliasFormatter) Declaration(fieldName string, expr ast.Expr) string {

func (f *AliasFormatter) Constructor(fieldName string, expr ast.Expr) string {
u := f.under(expr)
return GetTypeFormatter(u).Constructor(fieldName, u)
return f.Registry.GetTypeFormatter(u).Constructor(fieldName, u)
}
3 changes: 2 additions & 1 deletion generator/format/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
)

type ArrayFormatter struct {
TypeFormatterBase
}

func (f *ArrayFormatter) under(expr ast.Expr) (TypeFormatter, ast.Expr) {
arrayExpr := expr.(*ast.ArrayType)
formatter := GetTypeFormatter(arrayExpr.Elt)
formatter := f.Registry.GetTypeFormatter(arrayExpr.Elt)
return formatter, arrayExpr.Elt
}

Expand Down
41 changes: 41 additions & 0 deletions generator/format/fallback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package format

import (
"fmt"
"go/ast"
)

type FallbackFormatter struct {
TypeFormatterBase
}

func (f *FallbackFormatter) under(expr ast.Expr) *ast.TypeSpec {
if e, ok := expr.(*ast.Ident); ok && e.Obj == nil {
if val, ok := f.Registry.KnownTypes[e.Name]; ok {
return val
}
}
return nil
}

func (f *FallbackFormatter) CanFormat(expr ast.Expr) bool {
return f.under(expr) != nil
}

func (f *FallbackFormatter) Signature(expr ast.Expr) string {
t := f.under(expr)
switch t.Type.(type) {
case *ast.Ident:
return f.Registry.GetTypeFormatter(t.Type).Signature(t.Type)
default:
return t.Name.Name
}
}

func (f *FallbackFormatter) Declaration(fieldName string, expr ast.Expr) string {
return fmt.Sprintf("%s %s", f.Signature(expr), fieldName)
}

func (f *FallbackFormatter) Constructor(fieldName string, _ ast.Expr) string {
return "required this." + fieldName
}
35 changes: 31 additions & 4 deletions generator/format/format.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
package format

import (
"fmt"
"go/ast"
)

type TypeFormatter interface {
SetRegistry(registry *TypeFormatterRegistry)
CanFormat(expr ast.Expr) bool
Signature(expr ast.Expr) string
Declaration(fieldName string, expr ast.Expr) string
Constructor(fieldName string, expr ast.Expr) string
}

var Formatters []TypeFormatter
type TypeFormatterBase struct {
Registry *TypeFormatterRegistry
}

func (t *TypeFormatterBase) SetRegistry(registry *TypeFormatterRegistry) {
t.Registry = registry
}

type TypeFormatterRegistry struct {
KnownTypes map[string]*ast.TypeSpec
Formatters []TypeFormatter
}

func NewTypeFormatterRegistry() *TypeFormatterRegistry {
return &TypeFormatterRegistry{
KnownTypes: make(map[string]*ast.TypeSpec),
Formatters: make([]TypeFormatter, 0),
}
}
func (t *TypeFormatterRegistry) RegisterTypeFormatter(formatter TypeFormatter) {
t.Formatters = append(t.Formatters, formatter)
formatter.SetRegistry(t)
}

func GetTypeFormatter(expr ast.Expr) TypeFormatter {
for _, f := range Formatters {
func (t *TypeFormatterRegistry) GetTypeFormatter(expr ast.Expr) TypeFormatter {
// walks the t.Formatters in reverse order
// so that the last registered formatter is the first to be checked
for i := len(t.Formatters) - 1; i >= 0; i-- {
f := t.Formatters[i]
if f.CanFormat(expr) {
return f
}
}

panic("no formatter found for type")
panic(fmt.Sprintf("no formatter found for %v", expr))
}
5 changes: 3 additions & 2 deletions generator/format/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import (
)

type MapFormatter struct {
TypeFormatterBase
}

func (f *MapFormatter) under(expr ast.Expr) (TypeFormatter, TypeFormatter, ast.Expr, ast.Expr) {
mapExpr := expr.(*ast.MapType)
keyFormatter := GetTypeFormatter(mapExpr.Key)
valueFormatter := GetTypeFormatter(mapExpr.Value)
keyFormatter := f.Registry.GetTypeFormatter(mapExpr.Key)
valueFormatter := f.Registry.GetTypeFormatter(mapExpr.Value)
return keyFormatter, valueFormatter, mapExpr.Key, mapExpr.Value
}

Expand Down
3 changes: 2 additions & 1 deletion generator/format/mo/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
)

type OptionFormatter struct {
format.TypeFormatterBase
}

func (f *OptionFormatter) under(expr ast.Expr) (format.TypeFormatter, ast.Expr) {
e := expr.(*ast.IndexExpr).Index
formatter := format.GetTypeFormatter(e)
formatter := f.Registry.GetTypeFormatter(e)
return formatter, e
}

Expand Down
3 changes: 2 additions & 1 deletion generator/format/pointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
)

type PointerFormatter struct {
TypeFormatterBase
}

func (f *PointerFormatter) under(expr ast.Expr) (TypeFormatter, ast.Expr) {
starExpr := expr.(*ast.StarExpr)
formatter := GetTypeFormatter(starExpr.X)
formatter := f.Registry.GetTypeFormatter(starExpr.X)
return formatter, starExpr.X
}

Expand Down
1 change: 1 addition & 0 deletions generator/format/primitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

type PrimitiveFormatter struct {
TypeFormatterBase
}

func (f *PrimitiveFormatter) toDartPrimitive(expr ast.Expr) string {
Expand Down
1 change: 1 addition & 0 deletions generator/format/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

type StructFormatter struct {
TypeFormatterBase
}

func (f *StructFormatter) under(expr ast.Expr) *ast.TypeSpec {
Expand Down
1 change: 1 addition & 0 deletions generator/format/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

type TimeFormatter struct {
TypeFormatterBase
}

func (f *TimeFormatter) CanFormat(expr ast.Expr) bool {
Expand Down
Loading

0 comments on commit 713f9c5

Please sign in to comment.