Skip to content

OpenAPI 3.0.x language server linting rules #2078

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

Merged
merged 4 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions packages/apidom-ls/src/config/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,6 @@ enum ApilintCodes {
OPENAPI2 = 3000000,

OPENAPI2_CONTACT = 3010000,
OPENAPI2_CONTACT_FIELD_NAME_TYPE = 3010100,
OPENAPI2_CONTACT_FIELD_URL_FORMAT_URI = 3010200,
OPENAPI2_CONTACT_FIELD_EMAIL_FORMAT_EMAIL = 3010300,

OPENAPI2_INFO = 3020000,

Expand Down Expand Up @@ -603,6 +600,33 @@ enum ApilintCodes {
OPENAPI3_0_INFO_FIELD_CONTACT_TYPE = 5020400,
OPENAPI3_0_INFO_FIELD_LICENSE_TYPE = 5020500,

OPENAPI3_0_CONTACT = 5030000,
OPENAPI3_0_CONTACT_FIELD_NAME_TYPE = 5030100,
OPENAPI3_0_CONTACT_FIELD_URL_FORMAT_URI = 5030200,
OPENAPI3_0_CONTACT_FIELD_EMAIL_FORMAT_EMAIL = 5030300,

OPENAPI3_0_LICENSE = 5040000,
OPENAPI3_0_LICENSE_FIELD_NAME_TYPE = 5040100,
OPENAPI3_0_LICENSE_FIELD_NAME_REQUIRED,
OPENAPI3_0_LICENSE_FIELD_URL_FORMAT_URI = 5040200,

OPENAPI3_0_EXTERNAL_DOCUMENTATION = 5050000,
OPENAPI3_0_EXTERNAL_DOCUMENTATION_FIELD_DESCRIPTION_TYPE = 5050100,
OPENAPI3_0_EXTERNAL_DOCUMENTATION_FIELD_URL_FORMAT_URI = 5050200,
OPENAPI3_0_EXTERNAL_DOCUMENTATION_FIELD_URL_REQUIRED,

OPENAPI3_0_COMPONENTS = 5060000,
OPENAPI3_0_COMPONENTS_KEYS_PATTERN,
OPENAPI3_0_COMPONENTS_FIELD_SCHEMAS_VALUES_TYPE = 5060100,
OPENAPI3_0_COMPONENTS_FIELD_RESPONSES_VALUES_TYPE = 5060200,
OPENAPI3_0_COMPONENTS_FIELD_PARAMETERS_VALUES_TYPE = 5060300,
OPENAPI3_0_COMPONENTS_FIELD_EXAMPLES_VALUES_TYPE = 5060400,
OPENAPI3_0_COMPONENTS_FIELD_REQUEST_BODIES_VALUES_TYPE = 5060500,
OPENAPI3_0_COMPONENTS_FIELD_HEADERS_VALUES_TYPE = 5060600,
OPENAPI3_0_COMPONENTS_FIELD_SECURITY_SCHEMES_VALUES_TYPE = 5060700,
OPENAPI3_0_COMPONENTS_FIELD_LINKS_VALUES_TYPE = 5060800,
OPENAPI3_0_COMPONENTS_FIELD_CALLBACKS_VALUES_TYPE = 5060900,

OPENAPI3_1 = 7000000,

OPENAPI3_1_OPENAPI_VALUE_PATTERN_3_1_0 = 7000100,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

// eslint-disable-next-line @typescript-eslint/naming-convention
const allowedFieldsLint3_0: LinterMeta = {
code: ApilintCodes.NOT_ALLOWED_FIELDS,
source: 'apilint',
message: 'Object includes not allowed fields',
severity: 1,
linterFunction: 'allowedFields',
linterParams: [
[
'schemas',
'responses',
'parameters',
'examples',
'requestBodies',
'headers',
'securitySchemes',
'links',
'callbacks',
],
'x-',
],
marker: 'key',
targetSpecs: [
{ namespace: 'openapi', version: '3.0.0' },
{ namespace: 'openapi', version: '3.0.1' },
{ namespace: 'openapi', version: '3.0.2' },
{ namespace: 'openapi', version: '3.0.3' },
],
};

export default allowedFieldsLint3_0;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const callbacksValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_CALLBACKS_VALUES_TYPE,
source: 'apilint',
message: '"callbacks" members must be Callback Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['callback']],
marker: 'key',
markerTarget: 'callbacks',
target: 'callbacks',
data: {},
};

export default callbacksValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const examplesValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_EXAMPLES_VALUES_TYPE,
source: 'apilint',
message: '"examples" members must be Example Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['example']],
marker: 'key',
markerTarget: 'examples',
target: 'examples',
data: {},
};

export default examplesValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const headersValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_HEADERS_VALUES_TYPE,
source: 'apilint',
message: '"headers" members must be Parameter Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['header']],
marker: 'key',
markerTarget: 'headers',
target: 'headers',
data: {},
};

export default headersValuesTypeLint;
27 changes: 27 additions & 0 deletions packages/apidom-ls/src/config/openapi/components/lint/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import allowedFields3_0Lint from './allowed-fields-3-0';
import schemasValuesTypeLint from './schemas--values-type';
import responsesValuesTypeLint from './responses--values-type';
import parametersValuesTypeLint from './parameters--values-type';
import examplesValuesTypeLint from './examples--values-type';
import requestBodiesValuesTypeLint from './request-bodies--values-type';
import headersValuesTypeLint from './headers--values-type';
import securitySchemesValuesType from './security-schemes--values-type';
import linksValuesTypeLint from './links--values-type';
import callbacksValuesTypeLint from './callbacks--values-type';
import keysPatternLint from './keys--pattern';

const lints = [
schemasValuesTypeLint,
responsesValuesTypeLint,
parametersValuesTypeLint,
examplesValuesTypeLint,
requestBodiesValuesTypeLint,
headersValuesTypeLint,
securitySchemesValuesType,
linksValuesTypeLint,
callbacksValuesTypeLint,
keysPatternLint,
allowedFields3_0Lint,
];

export default lints;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const keysPatternLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_KEYS_PATTERN,
source: 'apilint',
message: 'components keys must match the regular expression: `^[a-zA-Z0-9\\.\\-_]+$`',
severity: 1,
linterFunction: 'apilintMembersKeysRegex',
linterParams: ['^[a-zA-Z0-9\\.\\-_]+$'],
marker: 'key',
data: {},
};

export default keysPatternLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const linksValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_LINKS_VALUES_TYPE,
source: 'apilint',
message: '"links" members must be Link Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['link']],
marker: 'key',
markerTarget: 'links',
target: 'links',
data: {},
};

export default linksValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const parametersValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_PARAMETERS_VALUES_TYPE,
source: 'apilint',
message: '"parameters" members must be Parameter Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['parameter']],
marker: 'key',
markerTarget: 'parameters',
target: 'parameters',
data: {},
};

export default parametersValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const requestBodiesValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_REQUEST_BODIES_VALUES_TYPE,
source: 'apilint',
message: '"requestBodies" members must be Request Body Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['requestBody']],
marker: 'key',
markerTarget: 'requestBodies',
target: 'requestBodies',
data: {},
};

export default requestBodiesValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const responsesValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_RESPONSES_VALUES_TYPE,
source: 'apilint',
message: '"responses" members must be Response Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['response']],
marker: 'key',
markerTarget: 'responses',
target: 'responses',
data: {},
};

export default responsesValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const schemasValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_SCHEMAS_VALUES_TYPE,
source: 'apilint',
message: '"schemas" members must be Schema Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['schema']],
marker: 'key',
markerTarget: 'schemas',
target: 'schemas',
data: {},
};

export default schemasValuesTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const securitySchemesValuesTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_COMPONENTS_FIELD_SECURITY_SCHEMES_VALUES_TYPE,
source: 'apilint',
message: '"securitySchemes" members must be Security Scheme Object',
severity: 1,
linterFunction: 'apilintChildrenOfElementsOrClasses',
linterParams: [['securityScheme']],
marker: 'key',
markerTarget: 'securitySchemes',
target: 'securitySchemes',
data: {},
};

export default securitySchemesValuesTypeLint;
2 changes: 2 additions & 0 deletions packages/apidom-ls/src/config/openapi/components/meta.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import lint from './lint';
import completion from './completion';
import documentation from './documentation';
import { FormatMeta } from '../../../apidom-language-types';

const meta: FormatMeta = {
lint,
completion,
documentation,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const emailFormatEmailLint: LinterMeta = {
code: ApilintCodes.OPENAPI2_CONTACT_FIELD_EMAIL_FORMAT_EMAIL,
code: ApilintCodes.OPENAPI3_0_CONTACT_FIELD_EMAIL_FORMAT_EMAIL,
source: 'apilint',
message: "'email' must be a valid email",
severity: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const nameTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI2_CONTACT_FIELD_NAME_TYPE,
code: ApilintCodes.OPENAPI3_0_CONTACT_FIELD_NAME_TYPE,
source: 'apilint',
message: "'name' must be a string",
severity: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const urlFormatURILint: LinterMeta = {
code: ApilintCodes.OPENAPI2_CONTACT_FIELD_URL_FORMAT_URI,
code: ApilintCodes.OPENAPI3_0_CONTACT_FIELD_URL_FORMAT_URI,
source: 'apilint',
message: "'url' value must be a valid URL",
severity: 1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const allowedFieldsLint: LinterMeta = {
code: ApilintCodes.NOT_ALLOWED_FIELDS,
source: 'apilint',
message: 'Object includes not allowed fields',
severity: 1,
linterFunction: 'allowedFields',
linterParams: [['description', 'url'], 'x-'],
marker: 'key',
};

export default allowedFieldsLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const descriptionTypeLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_EXTERNAL_DOCUMENTATION_FIELD_DESCRIPTION_TYPE,
source: 'apilint',
message: "'description' must be a string",
severity: 1,
linterFunction: 'apilintType',
linterParams: ['string'],
marker: 'value',
target: 'description',
data: {},
};

export default descriptionTypeLint;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import allowedFieldsLint from './allowed-fields';
import descriptionTypeLint from './description--type';
import urlRequiredLint from './url--required';
import urlFormatURILint from './url--format-uri';

const contactLints = [descriptionTypeLint, urlRequiredLint, urlFormatURILint, allowedFieldsLint];

export default contactLints;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import ApilintCodes from '../../../codes';
import { LinterMeta } from '../../../../apidom-language-types';

const urlFormatURILint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_EXTERNAL_DOCUMENTATION_FIELD_URL_FORMAT_URI,
source: 'apilint',
message: "'url' value must be a valid URL",
severity: 1,
linterFunction: 'apilintValidURI',
marker: 'value',
target: 'url',
data: {},
};

export default urlFormatURILint;
Loading