Skip to content

feat: add parameter validation rules #4986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions packages/apidom-ls/src/config/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ enum ApilintCodes {
OPENAPI2_PARAMETER_FIELD_IN_EQUALS = 3100200,
OPENAPI2_PARAMETER_FIELD_IN_REQUIRED,
OPENAPI2_PARAMETER_FIELD_IN_VALID,
OPENAPI2_PARAMETER_FIELD_IN_MULTIPLE_BODY,
OPENAPI2_PARAMETER_FIELD_DESCRIPTION_TYPE = 3100300,
OPENAPI2_PARAMETER_FIELD_REQUIRED_TYPE = 3100400,
OPENAPI2_PARAMETER_FIELD_REQUIRED_REQUIRED,
Expand All @@ -740,6 +741,7 @@ enum ApilintCodes {
OPENAPI2_PARAMETER_FIELD_ENUM_TYPE = 3101800,
OPENAPI2_PARAMETER_FIELD_MULTIPLE_OF_TYPE = 3101900,
OPENAPI2_PARAMETER_FIELD_IN_PATH_TEMPLATE = 3102000,
OPENAPI2_PARAMETER_FIELD_NAME_UNIQUE = 3103000,

OPENAPI2_ITEMS = 3110000,
OPENAPI2_ITEMS_FIELD_TYPE_EQUALS = 3110100,
Expand Down Expand Up @@ -976,6 +978,8 @@ enum ApilintCodes {
OPENAPI3_0_PARAMETER_FIELD_IN_TYPE = 5150300,
OPENAPI3_0_PARAMETER_FIELD_IN_REQUIRED,
OPENAPI3_0_PARAMETER_FIELD_IN_EQUALS,
OPENAPI3_0_PARAMETER_FIELD_IN_AUTHORIZATION,
OPENAPI3_0_PARAMETER_FIELD_IN_CONTENT_TYPE,
OPENAPI3_0_PARAMETER_FIELD_DESCRIPTION_TYPE = 5150400,
OPENAPI3_0_PARAMETER_FIELD_REQUIRED_TYPE = 5150500,
OPENAPI3_0_PARAMETER_FIELD_REQUIRED_REQUIRED,
Expand Down
31 changes: 31 additions & 0 deletions packages/apidom-ls/src/config/openapi/parameter/lint/in--accept.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

import { OpenAPI3 } from '../../target-specs.ts';
import ApilintCodes from '../../../codes.ts';

const inAcceptLint = {
code: ApilintCodes.OPENAPI3_0_PARAMETER_FIELD_IN_CONTENT_TYPE,
source: 'apilint',
message:
'Header Parameter named "Accept" is ignored. The values for the "Accept" header are defined by `requestBody.content.<media-type>`',
severity: DiagnosticSeverity.Warning,
linterParams: ['^(?!\\b(A|a)ccept\\b).*$'],
linterFunction: 'apilintValueRegex',
marker: 'value',
target: 'name',
data: {},
conditions: [
{
targets: [
{
path: 'in',
},
],
function: 'apilintContainsValue',
params: ['header'],
},
],
targetSpecs: OpenAPI3,
};

export default inAcceptLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

import { OpenAPI3 } from '../../target-specs.ts';
import ApilintCodes from '../../../codes.ts';

const inAuthorizationLint = {
code: ApilintCodes.OPENAPI3_0_PARAMETER_FIELD_IN_AUTHORIZATION,
source: 'apilint',
message:
'Header Parameter named "Authorization" is ignored. Use the "securitySchemes" and "security" sections instead to define authorization',
severity: DiagnosticSeverity.Warning,
linterParams: ['^(?!\\b(A|a)uthorization\\b).*$'],
linterFunction: 'apilintValueRegex',
marker: 'value',
target: 'name',
data: {},
conditions: [
{
targets: [
{
path: 'in',
},
],
function: 'apilintContainsValue',
params: ['header'],
},
],
targetSpecs: OpenAPI3,
};

export default inAuthorizationLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

import { OpenAPI3 } from '../../target-specs.ts';
import ApilintCodes from '../../../codes.ts';

const inContentTypeLint = {
code: ApilintCodes.OPENAPI3_0_PARAMETER_FIELD_IN_CONTENT_TYPE,
source: 'apilint',
message:
'Header Parameter named "Content-Type" is ignored. The values for the "Content-Type" header are defined by `requestBody.content.<media-type>`',
severity: DiagnosticSeverity.Warning,
linterParams: ['^(?!\\b(C|c)ontent-(T|t)ype\\b).*$'],
linterFunction: 'apilintValueRegex',
marker: 'value',
target: 'name',
data: {},
conditions: [
{
targets: [
{
path: 'in',
},
],
function: 'apilintContainsValue',
params: ['header'],
},
],
targetSpecs: OpenAPI3,
};

export default inContentTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

import { OpenAPI2 } from '../../target-specs.ts';
import ApilintCodes from '../../../codes.ts';

const inMultipleBody = {
code: ApilintCodes.OPENAPI2_PARAMETER_FIELD_IN_MULTIPLE_BODY,
source: 'apilint',
message: 'Multiple body parameters are not allowed',
severity: DiagnosticSeverity.Error,
linterFunction: 'apilintPropertyUniqueSiblingValue',
linterParams: ['parameters', 'in'],
marker: 'key',
markerTarget: 'in',
target: 'in',
conditions: [
{
targets: [{ path: 'in' }],
function: 'apilintContainsValue',
params: ['body'],
},
],
data: {},
targetSpecs: OpenAPI2,
};

export default inMultipleBody;
10 changes: 10 additions & 0 deletions packages/apidom-ls/src/config/openapi/parameter/lint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,18 @@ import uniqueItemsTypeLint from './unique-items--type.ts';
import enumTypeLint from './enum--type.ts';
import multipleOfTypeLint from './multiple-of--type.ts';
import inPathTemplateLint from './in-path-template.ts';
import uniqueNameLint from './unique-name.ts';
import inAuthorizationLint from './in--authorization.ts';
import inContentTypeLint from './in--content-type.ts';
import inAcceptLint from './in--accept.ts';
import inMultipleBody from './in--multiple-body.ts';

const lints = [
nameTypeLint,
nameRequiredLint,
inEquals2_0Lint,
inEquals3_0__3_1Lint,
inAuthorizationLint,
inRequiredLint,
inValidLint,
descriptionTypeLint,
Expand Down Expand Up @@ -81,13 +87,17 @@ const lints = [
maxLengthTypeLint,
minLengthTypeLint,
uniqueItemsTypeLint,
uniqueNameLint,
enumTypeLint,
multipleOfTypeLint,
requiredFields3_0__3_1Lint,
allowedFields2_0Lint,
allowedFields3_0Lint,
allowedFields3_1Lint,
inPathTemplateLint,
inContentTypeLint,
inAcceptLint,
inMultipleBody,
];

export default lints;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

import ApilintCodes from '../../../codes.ts';
import { LinterMeta } from '../../../../apidom-language-types.ts';
import { OpenAPI2, OpenAPI3 } from '../../target-specs.ts';

const parametersTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI2_PARAMETER_FIELD_NAME_UNIQUE,
source: 'apilint',
message: 'Name must be unique among all parameters',
severity: DiagnosticSeverity.Error,
linterFunction: 'apilintPropertyUniqueSiblingValue',
linterParams: ['parameters', 'name'],
marker: 'key',
markerTarget: 'name',
target: 'name',
data: {},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the empty data needed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see it's a default in a case when we don't specify any quickfix rules

targetSpecs: [...OpenAPI2, ...OpenAPI3],
};

export default parametersTypeLint;
24 changes: 24 additions & 0 deletions packages/apidom-ls/src/services/validation/linter-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,30 @@ export const standardLinterfunctions: FunctionItem[] = [
return true;
},
},
{
functionName: 'apilintPropertyUniqueSiblingValue',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for the late reply, instead of having new linter, could the 'apilintPropertyUniqueValue' be used ?

function: (element, elementOrClasses, key) => {
const value = toValue(element);

const filterSiblingsOAS2 = (
el: Element & { key?: { content?: string }; content: { value?: string } },
) => isString(el) && el.key?.content === key && toValue(el.content.value) === value;

const filterSiblingsOAS3 = (el: Element) =>
isObject(el) && el.hasKey(key) && toValue(el.get(key)) === value;

const elements = filter((el: Element) => {
const classes: string[] = toValue(el.getMetaProperty('classes', []));

return (
(elementOrClasses.includes(el.element) ||
classes.every((v) => elementOrClasses.includes(v))) &&
(filterSiblingsOAS2(el) || filterSiblingsOAS3(el))
);
}, element.parent?.parent?.parent);
return elements.length <= 1;
},
},
{
functionName: 'apilintChannelParameterExist',
function: (element: Element): boolean => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
openapi: 3.0.0
info:
version: 1.0.0
title: 'test'
paths:
/:
get:
responses:
default:
description: 'test'
parameters:
- in: header
name: accept
content:
application/xml: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
openapi: 3.0.0
info:
version: 1.0.0
title: 'test'
paths:
/:
get:
responses:
default:
description: 'test'
parameters:
- in: header
name: Authorization
content:
application/xml: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
openapi: 3.0.0
info:
version: 1.0.0
title: 'test'
paths:
/:
get:
responses:
default:
description: 'test'
parameters:
- in: header
name: content-type
content:
application/xml: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
swagger: '2.0'
info:
title: 'test'
version: 1.0.0
paths:
/:
get:
responses:
default:
description: 'test'
consumes:
- multipart/form-data
parameters:
- in: body
name: Else1
schema: {}
- in: body
name: Else2
schema: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
swagger: "2.0"
info:
version: 1.0.0
title: 'test'
paths:
/pets:
get:
responses:
parameters:
- name: pathLevel
type: string
in: query
description: tags to filter by
schema:
type: string
- name: pathLevel
type: string
in: query
description: tags to filter by
schema:
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
openapi: 3.0.0
info:
version: 1.0.0
title: 'test'
paths:
/pets:
get:
responses:
parameters:
- name: pathLevel
in: query
description: tags to filter by
schema:
type: string
- name: pathLevel
in: query
description: tags to filter by
schema:
type: string
Loading