Skip to content

Commit 6f6a798

Browse files
feat: add reference requestbodies naming rules
1 parent 9a38571 commit 6f6a798

File tree

7 files changed

+234
-0
lines changed

7 files changed

+234
-0
lines changed

packages/apidom-ls/src/config/codes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,8 @@ enum ApilintCodes {
10721072
OPENAPI3_0_REFERENCE_FIELD_$REF_FORMAT_URI = 5260100,
10731073
OPENAPI3_0_REFERENCE_FIELD_$REF_NO_SIBLINGS,
10741074
OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES = 5260200,
1075+
OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING,
1076+
OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING_SCHEMA,
10751077

10761078
OPENAPI3_0_LINK = 5270000,
10771079
OPENAPI3_0_LINK_FIELD_OPERATION_REF_FORMAT_URI = 5270100,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { DiagnosticSeverity } from 'vscode-languageserver-types';
2+
3+
import ApilintCodes from '../../../codes.ts';
4+
import { LinterMeta } from '../../../../apidom-language-types.ts';
5+
import { OpenAPI3 } from '../../target-specs.ts';
6+
7+
const $ref3RequestBodiesNamingSchemaLint: LinterMeta = {
8+
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING_SCHEMA,
9+
source: 'apilint',
10+
message:
11+
"requestBody $refs cannot point to '#/components/schemas/…', they must point to '#/components/requestBodies/…'",
12+
severity: DiagnosticSeverity.Error,
13+
linterFunction: 'parentExistFields',
14+
linterParams: [['requestBodies']],
15+
conditions: [
16+
{
17+
targets: [{ path: '$ref' }],
18+
function: 'apilintValueRegex',
19+
params: ['^(.*#/components/schemas).*$'],
20+
},
21+
],
22+
marker: 'value',
23+
target: '$ref',
24+
data: {},
25+
targetSpecs: OpenAPI3,
26+
};
27+
28+
export default $ref3RequestBodiesNamingSchemaLint;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { DiagnosticSeverity } from 'vscode-languageserver-types';
2+
3+
import ApilintCodes from '../../../codes.ts';
4+
import { LinterMeta } from '../../../../apidom-language-types.ts';
5+
import { OpenAPI3 } from '../../target-specs.ts';
6+
7+
const $ref3RequestBodiesNamingLint: LinterMeta = {
8+
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING,
9+
source: 'apilint',
10+
message: 'requestBody $refs must point to a position where a requestBody can be legally placed',
11+
severity: DiagnosticSeverity.Error,
12+
linterFunction: 'parentExistFields',
13+
linterParams: [['requestBodies']],
14+
conditions: [
15+
{
16+
targets: [{ path: '$ref' }],
17+
function: 'apilintValueRegex',
18+
params: ['^(?!.*#/components/(requestBodies|schemas)).*$'],
19+
},
20+
],
21+
marker: 'value',
22+
target: '$ref',
23+
data: {},
24+
targetSpecs: OpenAPI3,
25+
};
26+
27+
export default $ref3RequestBodiesNamingLint;

packages/apidom-ls/src/config/openapi/reference/lint/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import $ref3_1AllowedSiblingsLint from './$ref-3-1--allowed-siblings.ts';
44
import description3_1TypeLint from './description-3-1--type.ts';
55
import summary3_1TypeLint from './summary-3-1--type.ts';
66
import $ref3RequestBodiesLint from './$ref-3-0--request-bodies.ts';
7+
import $ref3RequestBodiesNamingLint from './$ref-3-0--request-bodies-naming.ts';
8+
import $ref3RequestBodiesNamingSchemaLint from './$ref-3-0--request-bodies-naming-schema.ts';
79

810
const lints = [
911
$refFormatURILint,
1012
$ref2_0__3_0NoSiblingsLint,
1113
$ref3_1AllowedSiblingsLint,
1214
$ref3RequestBodiesLint,
15+
$ref3RequestBodiesNamingLint,
16+
$ref3RequestBodiesNamingSchemaLint,
1317
description3_1TypeLint,
1418
summary3_1TypeLint,
1519
];
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
openapi: 3.0.0
2+
info:
3+
version: 1.0.0
4+
title: 'test'
5+
paths:
6+
/:
7+
post:
8+
responses:
9+
default:
10+
description: 'test'
11+
operationId: myId
12+
requestBody:
13+
$ref: '#/components/schemas/MyBody'
14+
components:
15+
schemas:
16+
MyBody:
17+
description: 'test'
18+
requestBodies:
19+
MyBody:
20+
content:
21+
application/json:
22+
schema:
23+
type: string
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
openapi: 3.0.0
2+
info:
3+
version: 1.0.0
4+
title: 'test'
5+
paths:
6+
/:
7+
post:
8+
responses:
9+
default:
10+
description: 'test'
11+
operationId: myId
12+
requestBody:
13+
$ref: '#/components/headers/MyBody'
14+
components:
15+
headers:
16+
MyBody:
17+
schema:
18+
description: 'description'
19+
requestBodies:
20+
MyBody:
21+
content:
22+
application/json:
23+
schema:
24+
type: string

packages/apidom-ls/test/validate.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3071,6 +3071,124 @@ describe('apidom-ls-validate', function () {
30713071
languageService.terminate();
30723072
});
30733073

3074+
it('oas 3.0 / yaml - requestBody $refs must point to a position naming', async function () {
3075+
const validationContext: ValidationContext = {
3076+
comments: DiagnosticSeverity.Error,
3077+
maxNumberOfProblems: 100,
3078+
relatedInformation: false,
3079+
};
3080+
3081+
const spec = fs
3082+
.readFileSync(
3083+
path.join(__dirname, 'fixtures', 'validation', 'oas', 'ref-request-bodies-naming.yaml'),
3084+
)
3085+
.toString();
3086+
const doc: TextDocument = TextDocument.create(
3087+
'foo://bar/ref-request-bodies-naming.yaml',
3088+
'yaml',
3089+
0,
3090+
spec,
3091+
);
3092+
3093+
const languageService: LanguageService = getLanguageService(contextNoSchema);
3094+
3095+
const result = await languageService.doValidation(doc, validationContext);
3096+
result[0].code = 'test';
3097+
result[1].code = 'test';
3098+
const expected: Diagnostic[] = [
3099+
{
3100+
range: { start: { line: 12, character: 14 }, end: { line: 12, character: 43 } },
3101+
message: 'local reference not found',
3102+
severity: 1,
3103+
code: 'test',
3104+
source: 'apilint',
3105+
data: {
3106+
quickFix: [
3107+
{
3108+
message: 'update to #/components/requestBodies/MyBody',
3109+
action: 'updateValue',
3110+
functionParams: ['#/components/requestBodies/MyBody'],
3111+
},
3112+
],
3113+
},
3114+
},
3115+
{
3116+
range: { start: { line: 12, character: 14 }, end: { line: 12, character: 43 } },
3117+
message:
3118+
'requestBody $refs must point to a position where a requestBody can be legally placed',
3119+
severity: 1,
3120+
code: 'test',
3121+
source: 'apilint',
3122+
data: {},
3123+
},
3124+
];
3125+
assert.deepEqual(result, expected as Diagnostic[]);
3126+
3127+
languageService.terminate();
3128+
});
3129+
3130+
it('oas 3.0 / yaml - requestBody $refs must point to a position naming schema', async function () {
3131+
const validationContext: ValidationContext = {
3132+
comments: DiagnosticSeverity.Error,
3133+
maxNumberOfProblems: 100,
3134+
relatedInformation: false,
3135+
};
3136+
3137+
const spec = fs
3138+
.readFileSync(
3139+
path.join(
3140+
__dirname,
3141+
'fixtures',
3142+
'validation',
3143+
'oas',
3144+
'ref-request-bodies-naming-schema.yaml',
3145+
),
3146+
)
3147+
.toString();
3148+
const doc: TextDocument = TextDocument.create(
3149+
'foo://bar/ref-request-bodies-naming-schema.yaml',
3150+
'yaml',
3151+
0,
3152+
spec,
3153+
);
3154+
3155+
const languageService: LanguageService = getLanguageService(contextNoSchema);
3156+
3157+
const result = await languageService.doValidation(doc, validationContext);
3158+
result[0].code = 'test';
3159+
result[1].code = 'test';
3160+
const expected: Diagnostic[] = [
3161+
{
3162+
range: { start: { line: 12, character: 14 }, end: { line: 12, character: 43 } },
3163+
message: 'local reference not found',
3164+
severity: 1,
3165+
code: 'test',
3166+
source: 'apilint',
3167+
data: {
3168+
quickFix: [
3169+
{
3170+
message: 'update to #/components/requestBodies/MyBody',
3171+
action: 'updateValue',
3172+
functionParams: ['#/components/requestBodies/MyBody'],
3173+
},
3174+
],
3175+
},
3176+
},
3177+
{
3178+
range: { start: { line: 12, character: 14 }, end: { line: 12, character: 43 } },
3179+
message:
3180+
"requestBody $refs cannot point to '#/components/schemas/…', they must point to '#/components/requestBodies/…'",
3181+
severity: 1,
3182+
code: 'test',
3183+
source: 'apilint',
3184+
data: {},
3185+
},
3186+
];
3187+
assert.deepEqual(result, expected as Diagnostic[]);
3188+
3189+
languageService.terminate();
3190+
});
3191+
30743192
it('oas / yaml - test editor issue 3626 / inidrect ref', async function () {
30753193
const validationContext: ValidationContext = {
30763194
comments: DiagnosticSeverity.Error,
@@ -3243,6 +3361,14 @@ describe('apidom-ls-validate', function () {
32433361
],
32443362
},
32453363
},
3364+
{
3365+
range: { start: { line: 10, character: 4 }, end: { line: 10, character: 7 } },
3366+
message: 'Definition was declared but never used in document',
3367+
severity: 2,
3368+
code: 3240300,
3369+
source: 'apilint',
3370+
data: {},
3371+
},
32463372
];
32473373
assert.deepEqual(result, expected as Diagnostic[]);
32483374

0 commit comments

Comments
 (0)