Skip to content

Commit d0486ac

Browse files
authored
Ref in paths / responses / parameters: flatten $ref in Paths (covers skip schemas) (#111)
* fix(expander): support SkipSchema case for in Paths section * added some quick patches to keep things running on windows: a more elaborate approach is still needed to fully support file $ref on windows Signed-off-by: Frederic BIDON <[email protected]> * fixed some missing nested schema rebasing when SkipSchema is enabled Signed-off-by: Frederic BIDON <[email protected]> * more fixes Signed-off-by: Frederic BIDON <[email protected]> * added test and fixture on self-referencing pointers Signed-off-by: Frederic BIDON <[email protected]> * fixup ci: useless install step Signed-off-by: Frederic BIDON <[email protected]> * cleanup code Signed-off-by: Frederic BIDON <[email protected]> * fixup linting Signed-off-by: Frederic BIDON <[email protected]>
1 parent 81c4553 commit d0486ac

29 files changed

+991
-22
lines changed

.golangci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ linters:
3636
- nestif
3737
- godot
3838
- gofumpt
39+
- paralleltest

.travis.yml

-2
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,3 @@ notifications:
2929
secure: QUWvCkBBK09GF7YtEvHHVt70JOkdlNBG0nIKu/5qc4/nW5HP8I2w0SEf/XR2je0eED1Qe3L/AfMCWwrEj+IUZc3l4v+ju8X8R3Lomhme0Eb0jd1MTMCuPcBT47YCj0M7RON7vXtbFfm1hFJ/jLe5+9FXz0hpXsR24PJc5ZIi/ogNwkaPqG4BmndzecpSh0vc2FJPZUD9LT0I09REY/vXR0oQAalLkW0asGD5taHZTUZq/kBpsNxaAFrLM23i4mUcf33M5fjLpvx5LRICrX/57XpBrDh2TooBU6Qj3CgoY0uPRYUmSNxbVx1czNzl2JtEpb5yjoxfVPQeg0BvQM00G8LJINISR+ohrjhkZmAqchDupAX+yFrxTtORa78CtnIL6z/aTNlgwwVD8kvL/1pFA/JWYmKDmz93mV/+6wubGzNSQCstzjkFA4/iZEKewKUoRIAi/fxyscP6L/rCpmY/4llZZvrnyTqVbt6URWpopUpH4rwYqreXAtJxJsfBJIeSmUIiDIOMGkCTvyTEW3fWGmGoqWtSHLoaWDyAIGb7azb+KvfpWtEcoPFWfSWU+LGee0A/YsUhBl7ADB9A0CJEuR8q4BPpKpfLwPKSiKSAXL7zDkyjExyhtgqbSl2jS+rKIHOZNL8JkCcTP2MKMVd563C5rC5FMKqu3S9m2b6380E=
3030
script:
3131
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...
32-
- go get -u github.com/go-openapi/analysis@master
33-
#- gotestsum -f short-verbose -- -timeout=30m github.com/go-openapi/analysis/...

expander.go

+29-9
Original file line numberDiff line numberDiff line change
@@ -616,41 +616,61 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa
616616
if err != nil {
617617
return err
618618
}
619+
619620
if ref == nil {
620621
return nil
621622
}
623+
622624
parentRefs := []string{}
623-
if err := resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) {
625+
if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) {
624626
return err
625627
}
628+
626629
ref, sch, _ := getRefAndSchema(input)
627630
if ref.String() != "" {
628-
transitiveResolver, err := resolver.transitiveResolver(basePath, *ref)
629-
if transitiveResolver.shouldStopOnError(err) {
630-
return err
631+
transitiveResolver, ert := resolver.transitiveResolver(basePath, *ref)
632+
if transitiveResolver.shouldStopOnError(ert) {
633+
return ert
631634
}
632635
basePath = resolver.updateBasePath(transitiveResolver, basePath)
633636
resolver = transitiveResolver
634637
}
635638

636-
if sch != nil && sch.Ref.String() != "" {
637-
// schema expanded to a $ref in another root
638-
var ern error
639-
sch.Ref, ern = NewRef(normalizePaths(sch.Ref.String(), ref.RemoteURI()))
639+
if sch == nil {
640+
// nothing to be expanded
641+
if ref != nil {
642+
*ref = Ref{}
643+
}
644+
return nil
645+
}
646+
647+
if sch.Ref.String() != "" {
648+
rebasedRef, ern := NewRef(normalizePaths(sch.Ref.String(), basePath))
640649
if ern != nil {
641650
return ern
642651
}
652+
653+
if !resolver.options.SkipSchemas {
654+
// schema expanded to a $ref in another root
655+
sch.Ref = rebasedRef
656+
} else {
657+
// skip schema expansion but rebase $ref to schema
658+
sch.Ref = *denormalizeFileRef(&rebasedRef, basePath, resolver.context.basePath)
659+
}
643660
}
661+
644662
if ref != nil {
645663
*ref = Ref{}
646664
}
647665

648-
if !resolver.options.SkipSchemas && sch != nil {
666+
// expand schema
667+
if !resolver.options.SkipSchemas {
649668
s, err := expandSchema(*sch, parentRefs, resolver, basePath)
650669
if resolver.shouldStopOnError(err) {
651670
return err
652671
}
653672
*sch = *s
654673
}
674+
655675
return nil
656676
}

expander_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,19 @@ func TestNormalizePaths(t *testing.T) {
7676
// file basePath, absolute refPath, no fragment
7777
refPath: `C:\another\base\path.json`,
7878
base: `C:\base\path.json`,
79-
expOutput: `C:\another\base\path.json`,
79+
expOutput: `c:\another\base\path.json`,
8080
},
8181
{
8282
// file basePath, absolute refPath
8383
refPath: `C:\another\base\path.json#/definitions/Pet`,
8484
base: `C:\base\path.json`,
85-
expOutput: `C:\another\base\path.json#/definitions/Pet`,
85+
expOutput: `c:\another\base\path.json#/definitions/Pet`,
8686
},
8787
{
8888
// file basePath, relative refPath
8989
refPath: `another\base\path.json#/definitions/Pet`,
9090
base: `C:\base\path.json`,
91-
expOutput: `C:\base\another\base\path.json#/definitions/Pet`,
91+
expOutput: `c:\base\another\base\path.json#/definitions/Pet`,
9292
},
9393
}...)
9494
return testCases
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
definitions:
2+
named:
3+
type: string
4+
tag:
5+
type: object
6+
properties:
7+
id:
8+
type: integer
9+
format: int64
10+
value:
11+
type: string
12+
audit:
13+
$ref: "#/definitions/record"
14+
record:
15+
type: object
16+
properties:
17+
createdAt:
18+
type: string
19+
format: date-time
20+
21+
nestedThing:
22+
type: object
23+
properties:
24+
record:
25+
type: array
26+
items:
27+
- type: string
28+
format: date-time
29+
- type: object
30+
properties:
31+
createdAt:
32+
type: string
33+
format: date-time
34+
- allOf:
35+
- type: string
36+
format: date
37+
- type: object
38+
additionalProperties:
39+
type: object
40+
properties:
41+
id:
42+
type: integer
43+
format: int64
44+
value:
45+
type: string
46+
properties:
47+
value:
48+
type: string
49+
name:
50+
$ref: "definitions2.yml#/coordinate"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
coordinate:
2+
type: object
3+
properties:
4+
id:
5+
type: integer
6+
format: int64
7+
createdAt:
8+
type: string
9+
format: date-time

fixtures/flatten/external/errors.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error:
2+
type: object
3+
required:
4+
- id
5+
- message
6+
properties:
7+
id:
8+
type: integer
9+
format: int64
10+
readOnly: true
11+
message:
12+
type: string
13+
readOnly: true
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
bodyParam:
2+
name: body
3+
in: body
4+
schema:
5+
type: object
6+
properties:
7+
record:
8+
type: array
9+
items:
10+
- type: string
11+
format: date-time
12+
- type: object
13+
properties:
14+
createdAt:
15+
type: string
16+
format: date-time
17+
- allOf:
18+
- type: string
19+
format: date
20+
- type: object
21+
properties:
22+
id:
23+
type: integer
24+
format: int64
25+
value:
26+
type: string
27+
name:
28+
type: object
29+
properties:
30+
id:
31+
type: integer
32+
format: int64
33+
createdAt:
34+
type: string
35+
format: date-time
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
genericResponse:
2+
type: object
3+
properties:
4+
record:
5+
type: array
6+
items:
7+
- type: string
8+
format: date-time
9+
- type: object
10+
properties:
11+
createdAt:
12+
type: string
13+
format: date-time
14+
- allOf:
15+
- type: string
16+
format: date
17+
- type: object
18+
properties:
19+
id:
20+
type: integer
21+
format: int64
22+
value:
23+
type: string
24+
name:
25+
type: object
26+
properties:
27+
id:
28+
type: integer
29+
format: int64
30+
createdAt:
31+
type: string
32+
format: date-time
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
parameters:
2+
idParam:
3+
name: id
4+
in: path
5+
type: integer
6+
format: int32
7+
limitParam:
8+
name: limit
9+
in: query
10+
type: integer
11+
format: int32
12+
required: false
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
get:
2+
operationId: modelOp
3+
summary: many model variations
4+
description: Used to see if a codegen can render all the possible parameter variations for a header param
5+
tags:
6+
- testcgen
7+
responses:
8+
default:
9+
description: Generic Out
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
responses:
2+
notFound:
3+
schema:
4+
$ref: "errors.yml#/error"

fixtures/flatten/flatten.yml

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
swagger: "2.0"
3+
info:
4+
version: "0.1.0"
5+
title: reference analysis
6+
7+
parameters:
8+
someParam:
9+
name: some
10+
in: query
11+
type: string
12+
responses:
13+
notFound:
14+
description: "Not Found"
15+
schema:
16+
$ref: "external/errors.yml#/error"
17+
18+
paths:
19+
"/some/where/{id}":
20+
parameters:
21+
- $ref: "external/parameters.yml#/parameters/idParam"
22+
23+
get:
24+
parameters:
25+
- $ref: "external/parameters.yml#/parameters/limitParam"
26+
- $ref: "#/parameters/someParam"
27+
- name: other
28+
in: query
29+
type: string
30+
- $ref: "external/nestedParams.yml#/bodyParam"
31+
32+
responses:
33+
default:
34+
$ref: "external/nestedResponses.yml#/genericResponse"
35+
404:
36+
$ref: "#/responses/notFound"
37+
200:
38+
description: "RecordHolder"
39+
schema:
40+
type: object
41+
properties:
42+
record:
43+
$ref: "external/definitions.yml#/definitions/nestedThing"
44+
"/other/place":
45+
$ref: "external/pathItem.yml"
46+
47+
definitions:
48+
namedAgain:
49+
$ref: "external/definitions.yml#/definitions/named"
50+
51+
datedTag:
52+
allOf:
53+
- type: string
54+
format: date
55+
- $ref: "external/definitions.yml#/definitions/tag"
56+
57+
records:
58+
type: array
59+
items:
60+
- $ref: "external/definitions.yml#/definitions/record"
61+
62+
datedRecords:
63+
type: array
64+
items:
65+
- type: string
66+
format: date-time
67+
- $ref: "external/definitions.yml#/definitions/record"
68+
69+
otherRecords:
70+
type: array
71+
items:
72+
$ref: "external/definitions.yml#/definitions/record"
73+
74+
tags:
75+
type: object
76+
additionalProperties:
77+
$ref: "external/definitions.yml#/definitions/tag"
78+
79+
namedThing:
80+
type: object
81+
properties:
82+
name:
83+
$ref: "external/definitions.yml#/definitions/named"
84+
namedAgain:
85+
$ref: "#/definitions/namedAgain"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
swagger: '2.0'
3+
info:
4+
version: '0.1.0'
5+
title: JSON pointers
6+
7+
paths:
8+
/some/where:
9+
get:
10+
responses:
11+
default:
12+
schema:
13+
$ref: '#/definitions/whiteStone/properties/p1'
14+
definitions:
15+
whiteStone:
16+
type: object
17+
properties:
18+
p1:
19+
$ref: '#/definitions/blackStone/properties/p2'
20+
blackStone:
21+
type: object
22+
properties:
23+
p2:
24+
$ref: '#/definitions/redStone/properties/p3'
25+
redStone:
26+
type: object
27+
properties:
28+
p3:
29+
$ref: '#/definitions/whiteStone/properties/p1'

0 commit comments

Comments
 (0)