mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
fix: Issue #82
The index can now accept multiple parameters with the same name, as long as they have different `in` types.
This commit is contained in:
@@ -98,96 +98,96 @@ func CreateClosedAPIIndexConfig() *SpecIndexConfig {
|
|||||||
// quick direct access to paths, operations, tags are all available. No need to walk the entire node tree in rules,
|
// quick direct access to paths, operations, tags are all available. No need to walk the entire node tree in rules,
|
||||||
// everything is pre-walked if you need it.
|
// everything is pre-walked if you need it.
|
||||||
type SpecIndex struct {
|
type SpecIndex struct {
|
||||||
allRefs map[string]*Reference // all (deduplicated) refs
|
allRefs map[string]*Reference // all (deduplicated) refs
|
||||||
rawSequencedRefs []*Reference // all raw references in sequence as they are scanned, not deduped.
|
rawSequencedRefs []*Reference // all raw references in sequence as they are scanned, not deduped.
|
||||||
linesWithRefs map[int]bool // lines that link to references.
|
linesWithRefs map[int]bool // lines that link to references.
|
||||||
allMappedRefs map[string]*Reference // these are the located mapped refs
|
allMappedRefs map[string]*Reference // these are the located mapped refs
|
||||||
allMappedRefsSequenced []*ReferenceMapped // sequenced mapped refs
|
allMappedRefsSequenced []*ReferenceMapped // sequenced mapped refs
|
||||||
refsByLine map[string]map[int]bool // every reference and the lines it's referenced from
|
refsByLine map[string]map[int]bool // every reference and the lines it's referenced from
|
||||||
pathRefs map[string]map[string]*Reference // all path references
|
pathRefs map[string]map[string]*Reference // all path references
|
||||||
paramOpRefs map[string]map[string]map[string]*Reference // params in operations.
|
paramOpRefs map[string]map[string]map[string][]*Reference // params in operations.
|
||||||
paramCompRefs map[string]*Reference // params in components
|
paramCompRefs map[string]*Reference // params in components
|
||||||
paramAllRefs map[string]*Reference // combined components and ops
|
paramAllRefs map[string]*Reference // combined components and ops
|
||||||
paramInlineDuplicates map[string][]*Reference // inline params all with the same name
|
paramInlineDuplicateNames map[string][]*Reference // inline params all with the same name
|
||||||
globalTagRefs map[string]*Reference // top level global tags
|
globalTagRefs map[string]*Reference // top level global tags
|
||||||
securitySchemeRefs map[string]*Reference // top level security schemes
|
securitySchemeRefs map[string]*Reference // top level security schemes
|
||||||
requestBodiesRefs map[string]*Reference // top level request bodies
|
requestBodiesRefs map[string]*Reference // top level request bodies
|
||||||
responsesRefs map[string]*Reference // top level responses
|
responsesRefs map[string]*Reference // top level responses
|
||||||
headersRefs map[string]*Reference // top level responses
|
headersRefs map[string]*Reference // top level responses
|
||||||
examplesRefs map[string]*Reference // top level examples
|
examplesRefs map[string]*Reference // top level examples
|
||||||
securityRequirementRefs map[string]map[string][]*Reference // (NOT $ref) but a name based lookup for requirements
|
securityRequirementRefs map[string]map[string][]*Reference // (NOT $ref) but a name based lookup for requirements
|
||||||
callbacksRefs map[string]map[string][]*Reference // all links
|
callbacksRefs map[string]map[string][]*Reference // all links
|
||||||
linksRefs map[string]map[string][]*Reference // all callbacks
|
linksRefs map[string]map[string][]*Reference // all callbacks
|
||||||
operationTagsRefs map[string]map[string][]*Reference // tags found in operations
|
operationTagsRefs map[string]map[string][]*Reference // tags found in operations
|
||||||
operationDescriptionRefs map[string]map[string]*Reference // descriptions in operations.
|
operationDescriptionRefs map[string]map[string]*Reference // descriptions in operations.
|
||||||
operationSummaryRefs map[string]map[string]*Reference // summaries in operations
|
operationSummaryRefs map[string]map[string]*Reference // summaries in operations
|
||||||
callbackRefs map[string]*Reference // top level callback refs
|
callbackRefs map[string]*Reference // top level callback refs
|
||||||
serversRefs []*Reference // all top level server refs
|
serversRefs []*Reference // all top level server refs
|
||||||
rootServersNode *yaml.Node // servers root node
|
rootServersNode *yaml.Node // servers root node
|
||||||
opServersRefs map[string]map[string][]*Reference // all operation level server overrides.
|
opServersRefs map[string]map[string][]*Reference // all operation level server overrides.
|
||||||
polymorphicRefs map[string]*Reference // every reference to a polymorphic ref
|
polymorphicRefs map[string]*Reference // every reference to a polymorphic ref
|
||||||
polymorphicAllOfRefs []*Reference // every reference to 'allOf' references
|
polymorphicAllOfRefs []*Reference // every reference to 'allOf' references
|
||||||
polymorphicOneOfRefs []*Reference // every reference to 'oneOf' references
|
polymorphicOneOfRefs []*Reference // every reference to 'oneOf' references
|
||||||
polymorphicAnyOfRefs []*Reference // every reference to 'anyOf' references
|
polymorphicAnyOfRefs []*Reference // every reference to 'anyOf' references
|
||||||
externalDocumentsRef []*Reference // all external documents in spec
|
externalDocumentsRef []*Reference // all external documents in spec
|
||||||
rootSecurity []*Reference // root security definitions.
|
rootSecurity []*Reference // root security definitions.
|
||||||
rootSecurityNode *yaml.Node // root security node.
|
rootSecurityNode *yaml.Node // root security node.
|
||||||
refsWithSiblings map[string]Reference // references with sibling elements next to them
|
refsWithSiblings map[string]Reference // references with sibling elements next to them
|
||||||
pathRefsLock sync.Mutex // create lock for all refs maps, we want to build data as fast as we can
|
pathRefsLock sync.Mutex // create lock for all refs maps, we want to build data as fast as we can
|
||||||
externalDocumentsCount int // number of externalDocument nodes found
|
externalDocumentsCount int // number of externalDocument nodes found
|
||||||
operationTagsCount int // number of unique tags in operations
|
operationTagsCount int // number of unique tags in operations
|
||||||
globalTagsCount int // number of global tags defined
|
globalTagsCount int // number of global tags defined
|
||||||
totalTagsCount int // number unique tags in spec
|
totalTagsCount int // number unique tags in spec
|
||||||
securitySchemesCount int // security schemes
|
securitySchemesCount int // security schemes
|
||||||
globalRequestBodiesCount int // component request bodies
|
globalRequestBodiesCount int // component request bodies
|
||||||
globalResponsesCount int // component responses
|
globalResponsesCount int // component responses
|
||||||
globalHeadersCount int // component headers
|
globalHeadersCount int // component headers
|
||||||
globalExamplesCount int // component examples
|
globalExamplesCount int // component examples
|
||||||
globalLinksCount int // component links
|
globalLinksCount int // component links
|
||||||
globalCallbacksCount int // component callbacks
|
globalCallbacksCount int // component callbacks
|
||||||
globalCallbacks int // component callbacks.
|
globalCallbacks int // component callbacks.
|
||||||
pathCount int // number of paths
|
pathCount int // number of paths
|
||||||
operationCount int // number of operations
|
operationCount int // number of operations
|
||||||
operationParamCount int // number of params defined in operations
|
operationParamCount int // number of params defined in operations
|
||||||
componentParamCount int // number of params defined in components
|
componentParamCount int // number of params defined in components
|
||||||
componentsInlineParamUniqueCount int // number of inline params with unique names
|
componentsInlineParamUniqueCount int // number of inline params with unique names
|
||||||
componentsInlineParamDuplicateCount int // number of inline params with duplicate names
|
componentsInlineParamDuplicateCount int // number of inline params with duplicate names
|
||||||
schemaCount int // number of schemas
|
schemaCount int // number of schemas
|
||||||
refCount int // total ref count
|
refCount int // total ref count
|
||||||
root *yaml.Node // the root document
|
root *yaml.Node // the root document
|
||||||
pathsNode *yaml.Node // paths node
|
pathsNode *yaml.Node // paths node
|
||||||
tagsNode *yaml.Node // tags node
|
tagsNode *yaml.Node // tags node
|
||||||
componentsNode *yaml.Node // components node
|
componentsNode *yaml.Node // components node
|
||||||
parametersNode *yaml.Node // components/parameters node
|
parametersNode *yaml.Node // components/parameters node
|
||||||
allParametersNode map[string]*Reference // all parameters node
|
allParametersNode map[string]*Reference // all parameters node
|
||||||
allParameters map[string]*Reference // all parameters (components/defs)
|
allParameters map[string]*Reference // all parameters (components/defs)
|
||||||
schemasNode *yaml.Node // components/schemas node
|
schemasNode *yaml.Node // components/schemas node
|
||||||
allInlineSchemaDefinitions []*Reference // all schemas found in document outside of components (openapi) or definitions (swagger).
|
allInlineSchemaDefinitions []*Reference // all schemas found in document outside of components (openapi) or definitions (swagger).
|
||||||
allInlineSchemaObjectDefinitions []*Reference // all schemas that are objects found in document outside of components (openapi) or definitions (swagger).
|
allInlineSchemaObjectDefinitions []*Reference // all schemas that are objects found in document outside of components (openapi) or definitions (swagger).
|
||||||
allComponentSchemaDefinitions map[string]*Reference // all schemas found in components (openapi) or definitions (swagger).
|
allComponentSchemaDefinitions map[string]*Reference // all schemas found in components (openapi) or definitions (swagger).
|
||||||
securitySchemesNode *yaml.Node // components/securitySchemes node
|
securitySchemesNode *yaml.Node // components/securitySchemes node
|
||||||
allSecuritySchemes map[string]*Reference // all security schemes / definitions.
|
allSecuritySchemes map[string]*Reference // all security schemes / definitions.
|
||||||
requestBodiesNode *yaml.Node // components/requestBodies node
|
requestBodiesNode *yaml.Node // components/requestBodies node
|
||||||
allRequestBodies map[string]*Reference // all request bodies
|
allRequestBodies map[string]*Reference // all request bodies
|
||||||
responsesNode *yaml.Node // components/responses node
|
responsesNode *yaml.Node // components/responses node
|
||||||
allResponses map[string]*Reference // all responses
|
allResponses map[string]*Reference // all responses
|
||||||
headersNode *yaml.Node // components/headers node
|
headersNode *yaml.Node // components/headers node
|
||||||
allHeaders map[string]*Reference // all headers
|
allHeaders map[string]*Reference // all headers
|
||||||
examplesNode *yaml.Node // components/examples node
|
examplesNode *yaml.Node // components/examples node
|
||||||
allExamples map[string]*Reference // all components examples
|
allExamples map[string]*Reference // all components examples
|
||||||
linksNode *yaml.Node // components/links node
|
linksNode *yaml.Node // components/links node
|
||||||
allLinks map[string]*Reference // all links
|
allLinks map[string]*Reference // all links
|
||||||
callbacksNode *yaml.Node // components/callbacks node
|
callbacksNode *yaml.Node // components/callbacks node
|
||||||
allCallbacks map[string]*Reference // all components examples
|
allCallbacks map[string]*Reference // all components examples
|
||||||
externalDocumentsNode *yaml.Node // external documents node
|
externalDocumentsNode *yaml.Node // external documents node
|
||||||
allExternalDocuments map[string]*Reference // all external documents
|
allExternalDocuments map[string]*Reference // all external documents
|
||||||
externalSpecIndex map[string]*SpecIndex // create a primary index of all external specs and componentIds
|
externalSpecIndex map[string]*SpecIndex // create a primary index of all external specs and componentIds
|
||||||
refErrors []error // errors when indexing references
|
refErrors []error // errors when indexing references
|
||||||
operationParamErrors []error // errors when indexing parameters
|
operationParamErrors []error // errors when indexing parameters
|
||||||
allDescriptions []*DescriptionReference // every single description found in the spec.
|
allDescriptions []*DescriptionReference // every single description found in the spec.
|
||||||
allSummaries []*DescriptionReference // every single summary found in the spec.
|
allSummaries []*DescriptionReference // every single summary found in the spec.
|
||||||
allEnums []*EnumReference // every single enum found in the spec.
|
allEnums []*EnumReference // every single enum found in the spec.
|
||||||
allObjectsWithProperties []*ObjectReference // every single object with properties found in the spec.
|
allObjectsWithProperties []*ObjectReference // every single object with properties found in the spec.
|
||||||
enumCount int
|
enumCount int
|
||||||
descriptionCount int
|
descriptionCount int
|
||||||
summaryCount int
|
summaryCount int
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ func boostrapIndexCollections(rootNode *yaml.Node, index *SpecIndex) {
|
|||||||
index.refsByLine = make(map[string]map[int]bool)
|
index.refsByLine = make(map[string]map[int]bool)
|
||||||
index.linesWithRefs = make(map[int]bool)
|
index.linesWithRefs = make(map[int]bool)
|
||||||
index.pathRefs = make(map[string]map[string]*Reference)
|
index.pathRefs = make(map[string]map[string]*Reference)
|
||||||
index.paramOpRefs = make(map[string]map[string]map[string]*Reference)
|
index.paramOpRefs = make(map[string]map[string]map[string][]*Reference)
|
||||||
index.operationTagsRefs = make(map[string]map[string][]*Reference)
|
index.operationTagsRefs = make(map[string]map[string][]*Reference)
|
||||||
index.operationDescriptionRefs = make(map[string]map[string]*Reference)
|
index.operationDescriptionRefs = make(map[string]map[string]*Reference)
|
||||||
index.operationSummaryRefs = make(map[string]map[string]*Reference)
|
index.operationSummaryRefs = make(map[string]map[string]*Reference)
|
||||||
index.paramCompRefs = make(map[string]*Reference)
|
index.paramCompRefs = make(map[string]*Reference)
|
||||||
index.paramAllRefs = make(map[string]*Reference)
|
index.paramAllRefs = make(map[string]*Reference)
|
||||||
index.paramInlineDuplicates = make(map[string][]*Reference)
|
index.paramInlineDuplicateNames = make(map[string][]*Reference)
|
||||||
index.globalTagRefs = make(map[string]*Reference)
|
index.globalTagRefs = make(map[string]*Reference)
|
||||||
index.securitySchemeRefs = make(map[string]*Reference)
|
index.securitySchemeRefs = make(map[string]*Reference)
|
||||||
index.requestBodiesRefs = make(map[string]*Reference)
|
index.requestBodiesRefs = make(map[string]*Reference)
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ func (index *SpecIndex) GetMappedReferencesSequenced() []*ReferenceMapped {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetOperationParameterReferences will return all references to operation parameters
|
// GetOperationParameterReferences will return all references to operation parameters
|
||||||
func (index *SpecIndex) GetOperationParameterReferences() map[string]map[string]map[string]*Reference {
|
func (index *SpecIndex) GetOperationParameterReferences() map[string]map[string]map[string][]*Reference {
|
||||||
return index.paramOpRefs
|
return index.paramOpRefs
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +310,7 @@ func (index *SpecIndex) GetAllCallbacks() map[string]*Reference {
|
|||||||
|
|
||||||
// GetInlineOperationDuplicateParameters will return a map of duplicates located in operation parameters.
|
// GetInlineOperationDuplicateParameters will return a map of duplicates located in operation parameters.
|
||||||
func (index *SpecIndex) GetInlineOperationDuplicateParameters() map[string][]*Reference {
|
func (index *SpecIndex) GetInlineOperationDuplicateParameters() map[string][]*Reference {
|
||||||
return index.paramInlineDuplicates
|
return index.paramInlineDuplicateNames
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReferencesWithSiblings will return a map of all the references with sibling nodes (illegal)
|
// GetReferencesWithSiblings will return a map of all the references with sibling nodes (illegal)
|
||||||
@@ -359,7 +359,7 @@ func (index *SpecIndex) GetOperationTags() map[string]map[string][]*Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetAllParametersFromOperations will return all paths indexed in the document
|
// GetAllParametersFromOperations will return all paths indexed in the document
|
||||||
func (index *SpecIndex) GetAllParametersFromOperations() map[string]map[string]map[string]*Reference {
|
func (index *SpecIndex) GetAllParametersFromOperations() map[string]map[string]map[string][]*Reference {
|
||||||
return index.paramOpRefs
|
return index.paramOpRefs
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1104,14 +1104,23 @@ func (index *SpecIndex) GetOperationsParameterCount() int {
|
|||||||
for mName, mValue := range params {
|
for mName, mValue := range params {
|
||||||
for pName, pValue := range mValue {
|
for pName, pValue := range mValue {
|
||||||
if !strings.HasPrefix(pName, "#") {
|
if !strings.HasPrefix(pName, "#") {
|
||||||
index.paramInlineDuplicates[pName] = append(index.paramInlineDuplicates[pName], pValue)
|
index.paramInlineDuplicateNames[pName] = append(index.paramInlineDuplicateNames[pName], pValue...)
|
||||||
index.paramAllRefs[fmt.Sprintf("%s:::%s", path, mName)] = pValue
|
for i := range pValue {
|
||||||
|
if pValue[i] != nil {
|
||||||
|
_, in := utils.FindKeyNodeTop("in", pValue[i].Node.Content)
|
||||||
|
if in != nil {
|
||||||
|
index.paramAllRefs[fmt.Sprintf("%s:::%s:::%s", path, mName, in.Value)] = pValue[i]
|
||||||
|
} else {
|
||||||
|
index.paramAllRefs[fmt.Sprintf("%s:::%s", path, mName)] = pValue[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index.operationParamCount = len(index.paramCompRefs) + len(index.paramInlineDuplicates)
|
index.operationParamCount = len(index.paramCompRefs) + len(index.paramInlineDuplicateNames)
|
||||||
return index.operationParamCount
|
return index.operationParamCount
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1120,7 +1129,7 @@ func (index *SpecIndex) GetInlineDuplicateParamCount() int {
|
|||||||
if index.componentsInlineParamDuplicateCount > 0 {
|
if index.componentsInlineParamDuplicateCount > 0 {
|
||||||
return index.componentsInlineParamDuplicateCount
|
return index.componentsInlineParamDuplicateCount
|
||||||
}
|
}
|
||||||
dCount := len(index.paramInlineDuplicates) - index.countUniqueInlineDuplicates()
|
dCount := len(index.paramInlineDuplicateNames) - index.countUniqueInlineDuplicates()
|
||||||
index.componentsInlineParamDuplicateCount = dCount
|
index.componentsInlineParamDuplicateCount = dCount
|
||||||
return dCount
|
return dCount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ paths:
|
|||||||
|
|
||||||
index := NewSpecIndex(&rootNode)
|
index := NewSpecIndex(&rootNode)
|
||||||
|
|
||||||
assert.NotNil(t, index.GetAllParametersFromOperations()["/cakes"]["post"]["coffee-time.yaml"].Node)
|
assert.NotNil(t, index.GetAllParametersFromOperations()["/cakes"]["post"]["coffee-time.yaml"][0].Node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSpecIndex_lookupRemoteReference_SeenSourceSimulation_BadJSON(t *testing.T) {
|
func TestSpecIndex_lookupRemoteReference_SeenSourceSimulation_BadJSON(t *testing.T) {
|
||||||
@@ -775,18 +775,18 @@ components:
|
|||||||
if assert.Contains(t, params, "/") {
|
if assert.Contains(t, params, "/") {
|
||||||
if assert.Contains(t, params["/"], "top") {
|
if assert.Contains(t, params["/"], "top") {
|
||||||
if assert.Contains(t, params["/"]["top"], "#/components/parameters/param1") {
|
if assert.Contains(t, params["/"]["top"], "#/components/parameters/param1") {
|
||||||
assert.Equal(t, "$.components.parameters.param1", params["/"]["top"]["#/components/parameters/param1"].Path)
|
assert.Equal(t, "$.components.parameters.param1", params["/"]["top"]["#/components/parameters/param1"][0].Path)
|
||||||
}
|
}
|
||||||
if assert.Contains(t, params["/"]["top"], "paramour.yaml#/components/parameters/param3") {
|
if assert.Contains(t, params["/"]["top"], "paramour.yaml#/components/parameters/param3") {
|
||||||
assert.Equal(t, "$.components.parameters.param3", params["/"]["top"]["paramour.yaml#/components/parameters/param3"].Path)
|
assert.Equal(t, "$.components.parameters.param3", params["/"]["top"]["paramour.yaml#/components/parameters/param3"][0].Path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if assert.Contains(t, params["/"], "get") {
|
if assert.Contains(t, params["/"], "get") {
|
||||||
if assert.Contains(t, params["/"]["get"], "#/components/parameters/param2") {
|
if assert.Contains(t, params["/"]["get"], "#/components/parameters/param2") {
|
||||||
assert.Equal(t, "$.components.parameters.param2", params["/"]["get"]["#/components/parameters/param2"].Path)
|
assert.Equal(t, "$.components.parameters.param2", params["/"]["get"]["#/components/parameters/param2"][0].Path)
|
||||||
}
|
}
|
||||||
if assert.Contains(t, params["/"]["get"], "test") {
|
if assert.Contains(t, params["/"]["get"], "test") {
|
||||||
assert.Equal(t, "$.paths./.get.parameters[2]", params["/"]["get"]["test"].Path)
|
assert.Equal(t, "$.paths./.get.parameters[2]", params["/"]["get"]["test"][0].Path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -854,6 +854,103 @@ func TestSpecIndex_schemaComponentsHaveParentsAndPaths(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_ParamsWithDuplicateNamesButUniqueInTypes(t *testing.T) {
|
||||||
|
yml := `openapi: 3.1.0
|
||||||
|
info:
|
||||||
|
title: Test
|
||||||
|
version: 0.0.1
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:35123
|
||||||
|
paths:
|
||||||
|
/example/{action}:
|
||||||
|
parameters:
|
||||||
|
- name: fastAction
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: fastAction
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
get:
|
||||||
|
operationId: example
|
||||||
|
parameters:
|
||||||
|
- name: action
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: action
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal([]byte(yml), &rootNode)
|
||||||
|
|
||||||
|
idx := NewSpecIndex(&rootNode)
|
||||||
|
|
||||||
|
assert.Len(t, idx.paramAllRefs, 4)
|
||||||
|
assert.Len(t, idx.paramInlineDuplicateNames, 2)
|
||||||
|
assert.Len(t, idx.operationParamErrors, 0)
|
||||||
|
assert.Len(t, idx.refErrors, 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_ParamsWithDuplicateNamesAndSameInTypes(t *testing.T) {
|
||||||
|
yml := `openapi: 3.1.0
|
||||||
|
info:
|
||||||
|
title: Test
|
||||||
|
version: 0.0.1
|
||||||
|
servers:
|
||||||
|
- url: http://localhost:35123
|
||||||
|
paths:
|
||||||
|
/example/{action}:
|
||||||
|
parameters:
|
||||||
|
- name: fastAction
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: fastAction
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
get:
|
||||||
|
operationId: example
|
||||||
|
parameters:
|
||||||
|
- name: action
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: action
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal([]byte(yml), &rootNode)
|
||||||
|
|
||||||
|
idx := NewSpecIndex(&rootNode)
|
||||||
|
|
||||||
|
assert.Len(t, idx.paramAllRefs, 3)
|
||||||
|
assert.Len(t, idx.paramInlineDuplicateNames, 2)
|
||||||
|
assert.Len(t, idx.operationParamErrors, 1)
|
||||||
|
assert.Len(t, idx.refErrors, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSpecIndex_foundObjectsWithProperties(t *testing.T) {
|
func TestSpecIndex_foundObjectsWithProperties(t *testing.T) {
|
||||||
yml := `paths:
|
yml := `paths:
|
||||||
/test:
|
/test:
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ func (index *SpecIndex) countUniqueInlineDuplicates() int {
|
|||||||
return index.componentsInlineParamUniqueCount
|
return index.componentsInlineParamUniqueCount
|
||||||
}
|
}
|
||||||
unique := 0
|
unique := 0
|
||||||
for _, p := range index.paramInlineDuplicates {
|
for _, p := range index.paramInlineDuplicateNames {
|
||||||
if len(p) == 1 {
|
if len(p) == 1 {
|
||||||
unique++
|
unique++
|
||||||
}
|
}
|
||||||
@@ -279,13 +279,13 @@ func (index *SpecIndex) scanOperationParams(params []*yaml.Node, pathItemNode *y
|
|||||||
paramRef := index.allMappedRefs[paramRefName]
|
paramRef := index.allMappedRefs[paramRefName]
|
||||||
|
|
||||||
if index.paramOpRefs[pathItemNode.Value] == nil {
|
if index.paramOpRefs[pathItemNode.Value] == nil {
|
||||||
index.paramOpRefs[pathItemNode.Value] = make(map[string]map[string]*Reference)
|
index.paramOpRefs[pathItemNode.Value] = make(map[string]map[string][]*Reference)
|
||||||
index.paramOpRefs[pathItemNode.Value][method] = make(map[string]*Reference)
|
index.paramOpRefs[pathItemNode.Value][method] = make(map[string][]*Reference)
|
||||||
|
|
||||||
}
|
}
|
||||||
// if we know the path, but it's a new method
|
// if we know the path, but it's a new method
|
||||||
if index.paramOpRefs[pathItemNode.Value][method] == nil {
|
if index.paramOpRefs[pathItemNode.Value][method] == nil {
|
||||||
index.paramOpRefs[pathItemNode.Value][method] = make(map[string]*Reference)
|
index.paramOpRefs[pathItemNode.Value][method] = make(map[string][]*Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this is a duplicate, add an error and ignore it
|
// if this is a duplicate, add an error and ignore it
|
||||||
@@ -302,7 +302,8 @@ func (index *SpecIndex) scanOperationParams(params []*yaml.Node, pathItemNode *y
|
|||||||
Path: path,
|
Path: path,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
index.paramOpRefs[pathItemNode.Value][method][paramRefName] = paramRef
|
index.paramOpRefs[pathItemNode.Value][method][paramRefName] =
|
||||||
|
append(index.paramOpRefs[pathItemNode.Value][method][paramRefName], paramRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
@@ -334,30 +335,47 @@ func (index *SpecIndex) scanOperationParams(params []*yaml.Node, pathItemNode *y
|
|||||||
Path: path,
|
Path: path,
|
||||||
}
|
}
|
||||||
if index.paramOpRefs[pathItemNode.Value] == nil {
|
if index.paramOpRefs[pathItemNode.Value] == nil {
|
||||||
index.paramOpRefs[pathItemNode.Value] = make(map[string]map[string]*Reference)
|
index.paramOpRefs[pathItemNode.Value] = make(map[string]map[string][]*Reference)
|
||||||
index.paramOpRefs[pathItemNode.Value][method] = make(map[string]*Reference)
|
index.paramOpRefs[pathItemNode.Value][method] = make(map[string][]*Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we know the path but this is a new method.
|
// if we know the path but this is a new method.
|
||||||
if index.paramOpRefs[pathItemNode.Value][method] == nil {
|
if index.paramOpRefs[pathItemNode.Value][method] == nil {
|
||||||
index.paramOpRefs[pathItemNode.Value][method] = make(map[string]*Reference)
|
index.paramOpRefs[pathItemNode.Value][method] = make(map[string][]*Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this is a duplicate, add an error and ignore it
|
// if this is a duplicate name, check if the `in` type is also the same, if so, it's a duplicate.
|
||||||
if index.paramOpRefs[pathItemNode.Value][method][ref.Name] != nil {
|
if len(index.paramOpRefs[pathItemNode.Value][method][ref.Name]) > 0 {
|
||||||
path := fmt.Sprintf("$.paths.%s.%s.parameters[%d]", pathItemNode.Value, method, i)
|
|
||||||
if method == "top" {
|
|
||||||
path = fmt.Sprintf("$.paths.%s.parameters[%d]", pathItemNode.Value, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
index.operationParamErrors = append(index.operationParamErrors, &IndexingError{
|
currentNode := ref.Node
|
||||||
Err: fmt.Errorf("the `%s` operation parameter at path `%s`, "+
|
checkNodes := index.paramOpRefs[pathItemNode.Value][method][ref.Name]
|
||||||
"index %d has a duplicate name `%s`", method, pathItemNode.Value, i, vn.Value),
|
_, currentIn := utils.FindKeyNodeTop("in", currentNode.Content)
|
||||||
Node: param,
|
|
||||||
Path: path,
|
for _, checkNode := range checkNodes {
|
||||||
})
|
|
||||||
|
_, checkIn := utils.FindKeyNodeTop("in", checkNode.Node.Content)
|
||||||
|
|
||||||
|
if currentIn != nil && checkIn != nil && currentIn.Value == checkIn.Value {
|
||||||
|
|
||||||
|
path := fmt.Sprintf("$.paths.%s.%s.parameters[%d]", pathItemNode.Value, method, i)
|
||||||
|
if method == "top" {
|
||||||
|
path = fmt.Sprintf("$.paths.%s.parameters[%d]", pathItemNode.Value, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
index.operationParamErrors = append(index.operationParamErrors, &IndexingError{
|
||||||
|
Err: fmt.Errorf("the `%s` operation parameter at path `%s`, "+
|
||||||
|
"index %d has a duplicate name `%s` and `in` type", method, pathItemNode.Value, i, vn.Value),
|
||||||
|
Node: param,
|
||||||
|
Path: path,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
index.paramOpRefs[pathItemNode.Value][method][ref.Name] =
|
||||||
|
append(index.paramOpRefs[pathItemNode.Value][method][ref.Name], ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
index.paramOpRefs[pathItemNode.Value][method][ref.Name] = ref
|
index.paramOpRefs[pathItemNode.Value][method][ref.Name] =
|
||||||
|
append(index.paramOpRefs[pathItemNode.Value][method][ref.Name], ref)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user