-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace oas2-unused-definition with az-unused-definition
- Loading branch information
1 parent
ec45477
commit 6230858
Showing
3 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Check all definitions in the document to see if they are used | ||
// Use the spectral unreferencedReusableObject to find its list of unused definitions, | ||
// and then remove any that `allOf` a used schema. | ||
|
||
const { unreferencedReusableObject } = require('@stoplight/spectral-functions'); | ||
|
||
const isObject = (obj) => obj && typeof obj === 'object'; | ||
|
||
// given should point to the member holding the potential reusable objects. | ||
module.exports = (given, _, context) => { | ||
if (!isObject(given)) { | ||
return []; | ||
} | ||
const opts = { | ||
reusableObjectsLocation: '#/definitions', | ||
}; | ||
const unreferencedDefinitionErrors = unreferencedReusableObject(given, opts, context); | ||
|
||
const unusedDefinitions = unreferencedDefinitionErrors.map((error) => error.path[1]); | ||
|
||
const allOfsUsedSchema = (schemaName) => { | ||
const schema = given[schemaName]; | ||
if (!isObject(schema) || !Array.isArray(schema.allOf)) { | ||
return false; | ||
} | ||
|
||
return schema.allOf.some((subSchema) => { | ||
if (!isObject(subSchema) || !subSchema.$ref) { | ||
return false; | ||
} | ||
|
||
const reffedSchema = subSchema.$ref.split('/').pop(); | ||
if (unusedDefinitions.includes(reffedSchema)) { | ||
return false; | ||
} | ||
|
||
return true; | ||
}); | ||
}; | ||
|
||
return unreferencedDefinitionErrors.filter( | ||
(error) => !allOfsUsedSchema(error.path[1]), | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
const { linterForRule } = require('./utils'); | ||
|
||
let linter; | ||
|
||
beforeAll(async () => { | ||
linter = await linterForRule('az-unused-definition'); | ||
return linter; | ||
}); | ||
|
||
test('az-unused-definition should find errors', () => { | ||
const oasDoc = { | ||
swagger: '2.0', | ||
paths: { | ||
'/test1': { | ||
post: { | ||
parameters: [ | ||
{ | ||
in: 'body', | ||
name: 'body', | ||
schema: { | ||
type: 'string', | ||
}, | ||
}, | ||
], | ||
responses: { | ||
200: { | ||
description: 'Success', | ||
schema: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
definitions: { | ||
Model1: { | ||
type: 'object', | ||
allOf: [ | ||
{ | ||
$ref: '#/definitions/Model3', | ||
}, | ||
], | ||
}, | ||
Model2: { | ||
type: 'object', | ||
properties: { | ||
id: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
Model3: { | ||
type: 'object', | ||
properties: { | ||
foo: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
return linter.run(oasDoc).then((results) => { | ||
expect(results.length).toBe(1); | ||
// Note: Model3 is not flagged as unused because it is used in Model1, | ||
// even though Model1 is not used. And the new logic now filters out the | ||
// error for Model1 because it allOfs Model3. | ||
expect(results[0].path.join('.')).toBe('definitions.Model2'); | ||
}); | ||
}); | ||
|
||
test('az-unused-definition should not find errors', () => { | ||
const oasDoc = { | ||
swagger: '2.0', | ||
paths: { | ||
'/test1': { | ||
post: { | ||
parameters: [ | ||
{ | ||
in: 'body', | ||
name: 'body', | ||
schema: { | ||
$ref: '#/definitions/Model1', | ||
}, | ||
}, | ||
], | ||
responses: { | ||
200: { | ||
description: 'Success', | ||
schema: { | ||
$ref: '#/definitions/Model2', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
'/test2': { | ||
post: { | ||
parameters: [ | ||
{ | ||
in: 'body', | ||
name: 'body', | ||
schema: { | ||
$ref: '#/definitions/Model4', | ||
}, | ||
}, | ||
], | ||
responses: { | ||
200: { | ||
description: 'Success', | ||
schema: { | ||
$ref: '#/definitions/Model3', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
definitions: { | ||
Model1: { | ||
type: 'object', | ||
allOf: [ | ||
{ | ||
$ref: '#/definitions/Model3', | ||
}, | ||
], | ||
}, | ||
Model2: { | ||
type: 'object', | ||
properties: { | ||
id: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
Model3: { | ||
type: 'object', | ||
properties: { | ||
foo: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
Model4: { | ||
type: 'object', | ||
properties: { | ||
id: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
Model5: { | ||
type: 'object', | ||
properties: { | ||
bar: { | ||
type: 'string', | ||
}, | ||
}, | ||
allOf: [ | ||
{ | ||
$ref: '#/definitions/Model4', | ||
}, | ||
], | ||
}, | ||
}, | ||
}; | ||
return linter.run(oasDoc).then((results) => { | ||
expect(results.length).toBe(0); | ||
}); | ||
}); |