Skip to content

Commit

Permalink
Replace oas2-unused-definition with az-unused-definition
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekistler committed Apr 1, 2024
1 parent ec45477 commit 6230858
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 0 deletions.
44 changes: 44 additions & 0 deletions functions/unused-definition.js
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]),
);
};
11 changes: 11 additions & 0 deletions spectral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ functions:
- security-definitions
- security-requirements
- schema-type-and-format
- unused-definition
- version-policy
rules:
info-contact: off
no-$ref-siblings: off
oas2-api-host: off
oas2-api-schemes: off
oas2-unused-definition: off
openapi-tags: off
operation-description: off
operation-tags: off
Expand Down Expand Up @@ -695,6 +697,15 @@ rules:
field: schema
function: truthy

az-unused-definition:
description: Potentially unused definition has been detected.
severity: warn
formats: ['oas2']
resolved: false
given: $.definitions
then:
function: unused-definition

az-version-convention:
description: API version should be a date in YYYY-MM-DD format, optionally suffixed with '-preview'.
severity: error
Expand Down
170 changes: 170 additions & 0 deletions test/unused-definition.test.js
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);
});
});

0 comments on commit 6230858

Please sign in to comment.