Add comment to interface method ()

This commit is contained in:
sunboyy 2022-05-16 22:37:03 +07:00 committed by GitHub
parent 440b92a742
commit 0a1d5c8545
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 124 additions and 190 deletions

View file

@ -19,29 +19,27 @@ func ExtractComponents(f *ast.File) File {
}
for _, spec := range genDecl.Specs {
importSpec, ok := spec.(*ast.ImportSpec)
if ok {
switch spec := spec.(type) {
case *ast.ImportSpec:
var imp Import
if importSpec.Name != nil {
imp.Name = importSpec.Name.Name
if spec.Name != nil {
imp.Name = spec.Name.Name
}
importPath, err := strconv.Unquote(importSpec.Path.Value)
importPath, err := strconv.Unquote(spec.Path.Value)
if err != nil {
fmt.Printf("cannot unquote import %s : %s \n", importSpec.Path.Value, err)
fmt.Printf("cannot unquote import %s : %s \n", spec.Path.Value, err)
continue
}
imp.Path = importPath
file.Imports = append(file.Imports, imp)
}
typeSpec, ok := spec.(*ast.TypeSpec)
if ok {
switch t := typeSpec.Type.(type) {
case *ast.TypeSpec:
switch t := spec.Type.(type) {
case *ast.StructType:
file.Structs = append(file.Structs, extractStructType(typeSpec.Name.Name, t))
file.Structs = append(file.Structs, extractStructType(spec.Name.Name, t))
case *ast.InterfaceType:
file.Interfaces = append(file.Interfaces, extractInterfaceType(typeSpec.Name.Name, t))
file.Interfaces = append(file.Interfaces, extractInterfaceType(spec.Name.Name, t))
}
}
}
@ -88,7 +86,16 @@ func extractInterfaceType(name string, interfaceType *ast.InterfaceType) Interfa
break
}
meth := extractFunction(name, funcType)
var comments []string
if method.Doc != nil {
for _, comment := range method.Doc.List {
commentRunes := []rune(comment.Text)
commentText := strings.TrimSpace(string(commentRunes[2:]))
comments = append(comments, commentText)
}
}
meth := extractFunction(name, comments, funcType)
intf.Methods = append(intf.Methods, meth)
}
@ -118,9 +125,10 @@ func extractStructTag(tagValue string) map[string][]string {
return tags
}
func extractFunction(name string, funcType *ast.FuncType) Method {
func extractFunction(name string, comments []string, funcType *ast.FuncType) Method {
meth := Method{
Name: name,
Name: name,
Comments: comments,
}
for _, param := range funcType.Params.List {
paramType := getType(param.Type)
@ -173,25 +181,7 @@ func getType(expr ast.Expr) Type {
return MapType{KeyType: keyType, ValueType: valueType}
case *ast.InterfaceType:
var methods []Method
for _, method := range expr.Methods.List {
funcType, ok := method.Type.(*ast.FuncType)
if !ok {
continue
}
var name string
for _, n := range method.Names {
name = n.Name
break
}
methods = append(methods, extractFunction(name, funcType))
}
return InterfaceType{
Methods: methods,
}
return extractInterfaceType("", expr)
}
return nil

View file

@ -65,10 +65,10 @@ type UserModel struct {
ExpectedOutput: code.File{
PackageName: "user",
Structs: code.Structs{
{
code.Struct{
Name: "UserModel",
Fields: code.StructFields{
{
code.StructField{
Name: "ID",
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
Tags: map[string][]string{
@ -76,7 +76,7 @@ type UserModel struct {
"json": {"id"},
},
},
{
code.StructField{
Name: "Username",
Type: code.SimpleType("string"),
Tags: map[string][]string{
@ -99,6 +99,7 @@ type UserRepository interface {
FindByAgeBetween(ctx context.Context, fromAge, toAge int) ([]*UserModel, error)
InsertOne(ctx context.Context, user *UserModel) (interface{}, error)
UpdateAgreementByID(ctx context.Context, agreement map[string]bool, id primitive.ObjectID) (bool, error)
// CustomMethod does custom things.
CustomMethod(interface {
Run(arg1 int)
}) interface {
@ -108,7 +109,7 @@ type UserRepository interface {
ExpectedOutput: code.File{
PackageName: "user",
Interfaces: code.Interfaces{
{
code.InterfaceType{
Name: "UserRepository",
Methods: []code.Method{
{
@ -168,7 +169,8 @@ type UserRepository interface {
},
},
{
Name: "CustomMethod",
Name: "CustomMethod",
Comments: []string{"CustomMethod does custom things."},
Params: []code.Param{
{
Type: code.InterfaceType{
@ -228,10 +230,10 @@ type UserRepository interface {
{Path: "go.mongodb.org/mongo-driver/bson/primitive"},
},
Structs: code.Structs{
{
code.Struct{
Name: "UserModel",
Fields: code.StructFields{
{
code.StructField{
Name: "ID",
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
Tags: map[string][]string{
@ -239,7 +241,7 @@ type UserRepository interface {
"json": {"id"},
},
},
{
code.StructField{
Name: "Username",
Type: code.SimpleType("string"),
Tags: map[string][]string{
@ -251,7 +253,7 @@ type UserRepository interface {
},
},
Interfaces: code.Interfaces{
{
code.InterfaceType{
Name: "UserRepository",
Methods: []code.Method{
{

View file

@ -95,9 +95,10 @@ func (intf InterfaceType) IsNumber() bool {
// Method is a definition of the method inside the interface
type Method struct {
Name string
Params []Param
Returns []Type
Name string
Comments []string
Params []Param
Returns []Type
}
// Param is a model of method parameter

View file

@ -11,8 +11,8 @@ func TestStructsByName(t *testing.T) {
userStruct := code.Struct{
Name: "UserModel",
Fields: code.StructFields{
{Name: "ID", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
{Name: "Username", Type: code.SimpleType("string")},
code.StructField{Name: "ID", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
code.StructField{Name: "Username", Type: code.SimpleType("string")},
},
}
structs := code.Structs{userStruct}

View file

@ -32,7 +32,7 @@ func TestGenerateMongoRepository(t *testing.T) {
Name: "UserModel",
Fields: code.StructFields{
idField,
{
code.StructField{
Name: "Username",
Type: code.SimpleType("string"),
Tags: map[string][]string{"bson": {"username"}},

View file

@ -57,7 +57,7 @@ var userModel = code.Struct{
Name: "UserModel",
Fields: code.StructFields{
idField,
{
code.StructField{
Name: "Username",
Type: code.SimpleType("string"),
Tags: map[string][]string{"bson": {"username"}},
@ -989,7 +989,7 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel,
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{
@ -1030,7 +1030,7 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeMany,
Query: spec.QuerySpec{
@ -1071,7 +1071,7 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int,
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: spec.UpdateOperatorPush},
spec.UpdateField{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: spec.UpdateOperatorPush},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{
@ -1112,7 +1112,7 @@ func (r *UserRepositoryMongo) UpdateConsentHistoryPushByID(arg0 context.Context,
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorInc},
spec.UpdateField{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorInc},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{
@ -1154,8 +1154,8 @@ func (r *UserRepositoryMongo) UpdateAgeIncByID(arg0 context.Context, arg1 int, a
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{enabledField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 2, Operator: spec.UpdateOperatorPush},
spec.UpdateField{FieldReference: spec.FieldReference{enabledField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 2, Operator: spec.UpdateOperatorPush},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{
@ -1199,7 +1199,7 @@ func (r *UserRepositoryMongo) UpdateEnabledAndConsentHistoryPushByID(arg0 contex
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{
@ -2081,7 +2081,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{
@ -2133,7 +2133,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
},
Operation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: "APPEND"},
spec.UpdateField{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: "APPEND"},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{

View file

@ -60,10 +60,12 @@ func TestError(t *testing.T) {
},
{
Name: "IncompatibleUpdateOperatorError",
Error: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorInc, spec.FieldReference{{
Name: "City",
Type: code.SimpleType("string"),
}}),
Error: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorInc, spec.FieldReference{
code.StructField{
Name: "City",
Type: code.SimpleType("string"),
},
}),
ExpectedString: "cannot use update operator INC with struct field 'City' of type 'string'",
},
}

View file

@ -705,7 +705,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -729,7 +729,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeMany,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -753,7 +753,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -778,8 +778,8 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
{FieldReference: spec.FieldReference{cityField}, ParamIndex: 2, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{cityField}, ParamIndex: 2, Operator: spec.UpdateOperatorSet},
},
Mode: spec.QueryModeMany,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -803,7 +803,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: spec.UpdateOperatorPush},
spec.UpdateField{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: spec.UpdateOperatorPush},
},
Mode: spec.QueryModeMany,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -827,7 +827,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorInc},
spec.UpdateField{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorInc},
},
Mode: spec.QueryModeOne,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -852,8 +852,8 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
},
ExpectedOperation: spec.UpdateOperation{
Update: spec.UpdateFields{
{FieldReference: spec.FieldReference{enabledField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 2, Operator: spec.UpdateOperatorPush},
spec.UpdateField{FieldReference: spec.FieldReference{enabledField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
spec.UpdateField{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 2, Operator: spec.UpdateOperatorPush},
},
Mode: spec.QueryModeMany,
Query: spec.QuerySpec{Predicates: []spec.Predicate{
@ -1741,10 +1741,12 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
code.SimpleType("error"),
},
},
ExpectedError: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorPush, spec.FieldReference{{
Name: "Gender",
Type: code.SimpleType("Gender"),
}}),
ExpectedError: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorPush, spec.FieldReference{
code.StructField{
Name: "Gender",
Type: code.SimpleType("Gender"),
},
}),
},
{
Name: "inc operator in non-number field",
@ -1760,10 +1762,12 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
code.SimpleType("error"),
},
},
ExpectedError: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorInc, spec.FieldReference{{
Name: "City",
Type: code.SimpleType("string"),
}}),
ExpectedError: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorInc, spec.FieldReference{
code.StructField{
Name: "City",
Type: code.SimpleType("string"),
},
}),
},
{
Name: "update method without query",