Skip to content

Commit

Permalink
wrap $ref in allOf when readonly is set (#1034)
Browse files Browse the repository at this point in the history
  • Loading branch information
josephzidell authored Oct 26, 2021
1 parent 7ed539e commit b5ca0bb
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 2 deletions.
4 changes: 4 additions & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,10 @@ func (parser *Parser) parseStructField(file *ast.File, field *ast.Field) (map[st

schema.Description = structField.desc
schema.ReadOnly = structField.readOnly
if !reflect.ValueOf(schema.SchemaProps.Ref).IsZero() && schema.ReadOnly {
schema.AllOf = []spec.Schema{*RefSchema(strings.TrimPrefix(schema.SchemaProps.Ref.Ref.String(), "#/definitions/"))}
schema.Ref = spec.Ref{} // clear out existing ref
}
schema.Default = structField.defaultValue
schema.Example = structField.exampleValue
if structField.schemaType != ARRAY {
Expand Down
111 changes: 109 additions & 2 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,98 @@ func TestParser_ParseGeneralAPISecurity(t *testing.T) {
"@authorizationurl https://example.com/oauth/authorize",
"@scope.read,write Multiple scope"}))
})
}

func TestParser_RefWithOtherPropertiesIsWrappedInAllOf(t *testing.T) {
t.Run("Readonly", func(t *testing.T) {
src := `
package main
type Teacher struct {
Name string
} //@name Teacher
type Student struct {
Name string
Age int ` + "`readonly:\"true\"`" + `
Teacher Teacher ` + "`readonly:\"true\"`" + `
OtherTeacher Teacher
} //@name Student
// @Success 200 {object} Student
// @Router /test [get]
func Fun() {
}
`
expected := `{
"info": {
"contact": {}
},
"paths": {
"/test": {
"get": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/Student"
}
}
}
}
}
},
"definitions": {
"Student": {
"type": "object",
"properties": {
"age": {
"type": "integer",
"readOnly": true
},
"name": {
"type": "string"
},
"otherTeacher": {
"$ref": "#/definitions/Teacher"
},
"teacher": {
"allOf": [
{
"$ref": "#/definitions/Teacher"
}
],
"readOnly": true
}
}
},
"Teacher": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}`

f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments)
assert.NoError(t, err)

p := New()
p.packages.CollectAstFile("api", "api/api.go", f)

_, err = p.packages.ParseTypes()
assert.NoError(t, err)

err = p.ParseRouterAPIInfo("", f)
assert.NoError(t, err)

b, _ := json.MarshalIndent(p.swagger, "", " ")
assert.Equal(t, expected, string(b))
})
}

func TestGetAllGoFileInfo(t *testing.T) {
Expand Down Expand Up @@ -3056,7 +3147,6 @@ func Fun() {
err = p.ParseRouterAPIInfo("", f)
assert.NoError(t, err)

assert.NoError(t, err)
teacher, ok := p.swagger.Definitions["Teacher"]
assert.True(t, ok)

Expand Down Expand Up @@ -3452,6 +3542,24 @@ func TestParseFieldTag(t *testing.T) {
[]string{"string"})
assert.Error(t, err)
})

t.Run("Readonly tag", func(t *testing.T) {
t.Parallel()
parser := New()

field, err := parser.parseFieldTag(
&ast.Field{
Tag: &ast.BasicLit{
Value: `json:"test" readonly:"true"`,
},
},
[]string{"string"})
assert.NoError(t, err)
assert.Equal(t, &structField{
schemaType: "string",
readOnly: true,
}, field)
})
}

func TestSetRouteMethodOp(t *testing.T) {
Expand Down Expand Up @@ -3581,5 +3689,4 @@ func TestGetFieldType(t *testing.T) {
field, err = getFieldType(&ast.StarExpr{X: &ast.SelectorExpr{X: &ast.Ident{Name: "models"}, Sel: &ast.Ident{Name: "User"}}})
assert.NoError(t, err)
assert.Equal(t, "models.User", field)

}

0 comments on commit b5ca0bb

Please sign in to comment.