Skip to content

Commit

Permalink
Merge pull request #10 from sergenyalcin/fix-9
Browse files Browse the repository at this point in the history
Support for string to struct maps
  • Loading branch information
muvaf authored Jan 31, 2022
2 parents 80e49fe + f6ea7ff commit 921e94e
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 4 deletions.
18 changes: 14 additions & 4 deletions pkg/packages/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,29 @@ type Imports struct {
// UseType adds the package of given type to the import map and returns the alias
// you can use in that Go file.
func (m *Imports) UseType(in string) string {
if strings.HasPrefix(in, "map") {
keyType := calculateTypeNameAndAlias(in[strings.Index(in, "[")+1:strings.Index(in, "]")], m.PackagePath, m.Imports)
valueType := calculateTypeNameAndAlias(in[strings.Index(in, "]")+1:], m.PackagePath, m.Imports)
return fmt.Sprintf("map[%s]%s", keyType, valueType)
}
return calculateTypeNameAndAlias(in, m.PackagePath, m.Imports)
}

func calculateTypeNameAndAlias(in, packagePath string, imports map[string]string) string {
pkgPath, typeNameFmt := parseTypeDec(in)
if isBuiltIn(typeNameFmt) {
return in
}
if strings.HasSuffix(m.PackagePath, pkgPath) {
if strings.HasSuffix(packagePath, pkgPath) {
// this is a temp hack for my own code :(
return strings.ReplaceAll(typeNameFmt, "%s.", "")
}
val, ok := m.Imports[pkgPath]
val, ok := imports[pkgPath]
if ok {
return fmt.Sprintf(typeNameFmt, val)
}
tmp := map[string]struct{}{}
for _, a := range m.Imports {
for _, a := range imports {
tmp[a] = struct{}{}
}
words := strings.Split(pkgPath, "/")
Expand All @@ -66,7 +75,7 @@ func (m *Imports) UseType(in string) string {
// the for loop above has to find a meaningful result before running out.
// The ReplaceAll statement is pinching hole in this completeness, but considering
// the paths are URLs, replacing dot with nothing should be fine.
m.Imports[pkgPath] = alias
imports[pkgPath] = alias
return fmt.Sprintf(typeNameFmt, alias)
}

Expand Down Expand Up @@ -111,6 +120,7 @@ func parseTypeDec(s string) (string, string) {
// pkg.Type
// *pkg.Type
// Get rid of slice and pointer chars.

tmp := strings.NewReplacer(
"[", "",
"]", "",
Expand Down
162 changes: 162 additions & 0 deletions pkg/packages/imports_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// Copyright 2022 Muvaffak Onus
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package packages

import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/muvaf/typewriter/pkg/test"
)

type importsModifier func(i *Imports)

func importsWithImportsMap(v map[string]string) importsModifier {
return func(i *Imports) {
i.Imports = v
}
}

func imports(cm ...importsModifier) *Imports {
c := &Imports{
Imports: map[string]string{},
}
for _, m := range cm {
m(c)
}
return c
}

func TestParseTypeDec(t *testing.T) {
type args struct {
s string
}
type want struct {
pkgName string
field string
}
cases := map[string]struct {
args
want
}{
"String": {
args: args{s: "string"},
want: want{pkgName: "", field: "string"},
},
"StringPointer": {
args: args{s: "*string"},
want: want{pkgName: "", field: "*string"},
},
"Bool": {
args: args{s: "bool"},
want: want{pkgName: "", field: "bool"},
},
"Int": {
args: args{s: "int"},
want: want{pkgName: "", field: "int"},
},
"Slice": {
args: args{s: "[]v1alpha1.ExampleStruct"},
want: want{pkgName: "v1alpha1", field: "[]%s.ExampleStruct"},
},
"SlicePointer": {
args: args{s: "[]*v1alpha1.ExampleStruct"},
want: want{pkgName: "v1alpha1", field: "[]*%s.ExampleStruct"},
},
}

for n, tc := range cases {
t.Run(n, func(t *testing.T) {
pkgName, field := parseTypeDec(tc.s)
if diff := cmp.Diff(tc.want.pkgName, pkgName, test.EquateErrors()); diff != "" {
t.Errorf("parseTypeDec(...) pkgName = %v, want %v", pkgName, tc.want.pkgName)
}
if diff := cmp.Diff(tc.want.field, field); diff != "" {
t.Errorf("parseTypeDec(...) field = %v, want %v", field, tc.want.field)
}
})
}
}

func TestImports_UseType(t *testing.T) {
type args struct {
m *Imports
in string
}
type want struct {
m *Imports
typeName string
}
cases := map[string]struct {
args
want
}{
"String": {
args: args{
m: imports(),
in: "string",
},
want: want{
m: imports(),
typeName: "string",
},
},
"MapStringToStruct": {
args: args{
m: imports(),
in: "map[string]github.com/org/repo/v1alpha1.ExampleStruct",
},
want: want{
m: imports(
importsWithImportsMap(map[string]string{
"github.com/org/repo/v1alpha1": "v1alpha1",
}),
),
typeName: "map[string]v1alpha1.ExampleStruct",
},
},
"MapStructToStruct": {
args: args{
m: imports(
importsWithImportsMap(map[string]string{
"github.com/example/ex/pkg": "exPkg",
}),
),
in: "map[github.com/org/repo/v1alpha1.ExampleStruct]github.com/org/repo/v1beta1.ExampleStruct1",
},
want: want{
m: imports(
importsWithImportsMap(map[string]string{
"github.com/example/ex/pkg": "exPkg",
"github.com/org/repo/v1alpha1": "v1alpha1",
"github.com/org/repo/v1beta1": "v1beta1",
}),
),
typeName: "map[v1alpha1.ExampleStruct]v1beta1.ExampleStruct1",
},
},
}
for n, tc := range cases {
t.Run(n, func(t *testing.T) {
gotTypeName := tc.args.m.UseType(tc.in)
if diff := cmp.Diff(tc.want.typeName, gotTypeName, test.EquateErrors()); diff != "" {
t.Errorf("useType(...) pkgName = %v, want %v", gotTypeName, tc.want.typeName)
}
if diff := cmp.Diff(tc.args.m, tc.want.m, test.EquateErrors()); diff != "" {
t.Errorf("useType(...) imports = %v, want %v", gotTypeName, tc.want.typeName)
}
})
}
}

0 comments on commit 921e94e

Please sign in to comment.