Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
6 changes: 6 additions & 0 deletions packages/apidom-ls/src/config/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,7 @@ enum ApilintCodes {

OPENAPI2_REFERENCE = 3240000,
OPENAPI2_REFERENCE_FIELD_$REF_FORMAT_URI = 3240100,
OPENAPI2_REFERENCE_NOT_USED = 3240300,

OPENAPI3_0 = 5000000,

Expand Down Expand Up @@ -1066,6 +1067,11 @@ enum ApilintCodes {
OPENAPI3_0_REFERENCE = 5260000,
OPENAPI3_0_REFERENCE_FIELD_$REF_FORMAT_URI = 5260100,
OPENAPI3_0_REFERENCE_FIELD_$REF_NO_SIBLINGS,
OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES = 5260200,
OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING,
OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING_SCHEMA,
OPENAPI3_0_REFERENCE_FIELD_$REF_HEADER = 5260300,
OPENAPI3_0_REFERENCE_FIELD_$REF_PARAMETER = 5260400,

OPENAPI3_0_LINK = 5270000,
OPENAPI3_0_LINK_FIELD_OPERATION_REF_FORMAT_URI = 5270100,
Expand Down
19 changes: 19 additions & 0 deletions packages/apidom-ls/src/config/common/schema/lint/$ref--not-used.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

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

const $refNotUsedLint: LinterMeta = {
code: ApilintCodes.OPENAPI2_REFERENCE_NOT_USED,
source: 'apilint',
message: 'Definition was declared but never used in document',
severity: DiagnosticSeverity.Warning,
linterFunction: 'apilintReferenceNotUsed',
linterParams: ['string'],
marker: 'key',
data: {},
targetSpecs: [...OpenAPI2, ...OpenAPI3, ...OpenAPI31],
};

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

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

const $ref3RequestBodiesLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES,
source: 'apilint',
message:
'requestBody schema $refs must point to a position where a Schema Object can be legally placed',
severity: DiagnosticSeverity.Error,
linterFunction: 'parentExistFields',
linterParams: [['requestBody']],
conditions: [
{
targets: [{ path: '$ref' }],
function: 'apilintValueRegex',
params: ['^(?!.*#/components/schemas).*$'],
},
],
marker: 'value',
target: '$ref',
data: {},
targetSpecs: OpenAPI3,
};

export default $ref3RequestBodiesLint;
4 changes: 4 additions & 0 deletions packages/apidom-ls/src/config/common/schema/lint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import allowedFieldsOpenAPI3_0Lint from './allowed-fields-openapi-3-0.ts';
import $idFormatURILint from './$id--format-uri.ts';
import $refValidLint from './$ref--valid.ts';
import $refNoSiblingsLint from './$ref--no-siblings.ts';
import $ref3RequestBodiesLint from './$ref-3-0--request-bodies.ts';
import additionalItemsNonArrayLint from './additional-items--non-array.ts';
import additionalItemsTypeLint from './additional-items--type.ts';
import additionalItemsTypeOpenAPI3_1__AsyncAPI2Lint from './additional-items--type-openapi-3-1--asyncapi-2.ts';
Expand Down Expand Up @@ -81,13 +82,16 @@ import uniqueItemsNonArrayLint from './unique-items--non-array.ts';
import uniqueItemsTypeLint from './unique-items--type.ts';
import writeOnlyTypeLint from './write-only--type.ts';
import exampleDeprecatedLint from './example--deprecated.ts';
import $refNotUsedLint from './$ref--not-used.ts';

const schemaLints = [
allowedFieldsOpenAPI2_0Lint,
allowedFieldsOpenAPI3_0Lint,
$idFormatURILint,
$refValidLint,
$refNoSiblingsLint,
$refNotUsedLint,
$ref3RequestBodiesLint,
additionalItemsNonArrayLint,
additionalItemsTypeLint,
additionalItemsTypeOpenAPI3_1__AsyncAPI2Lint,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

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

const $ref3HeaderNamingLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_HEADER,
source: 'apilint',
message: 'OAS3 header $Ref should point to Header Object',
severity: DiagnosticSeverity.Error,
linterFunction: 'parentExistFields',
linterParams: [['header']],
conditions: [
{
targets: [{ path: '$ref' }],
function: 'apilintValueRegex',
params: ['^(?!.*#/components/headers).*$'],
},
],
marker: 'value',
target: '$ref',
data: {},
targetSpecs: OpenAPI3,
};

export default $ref3HeaderNamingLint;
2 changes: 2 additions & 0 deletions packages/apidom-ls/src/config/openapi/header/lint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ import minItemsTypeLint from './min-items--type.ts';
import uniqueItemsTypeLint from './unique-items--type.ts';
import enumTypeLint from './enum--type.ts';
import multipleOfTypeLint from './multiple-of--type.ts';
import $ref3HeaderNamingLint from './$ref-3-0--header.ts';

const lints = [
$ref3HeaderNamingLint,
descriptionTypeLint,
requiredTypeLint,
deprecatedTypeLint,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

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

const $ref3ParameterNamingLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_PARAMETER,
source: 'apilint',
message: 'OAS3 parameter $Ref should point to Parameter Object',
severity: DiagnosticSeverity.Error,
linterFunction: 'apilintValueRegex',
linterParams: ['^(.*#/components/parameters).*$'],
marker: 'value',
target: '$ref',
conditions: [
{
targets: [{ path: '$ref' }],
function: 'parentExistFields',
params: [['paths']],
},
],
data: {},
targetSpecs: OpenAPI3,
};

export default $ref3ParameterNamingLint;
2 changes: 2 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,8 +42,10 @@ 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 $ref3ParameterNamingLint from './$ref-3-0--parameter.ts';

const lints = [
$ref3ParameterNamingLint,
nameTypeLint,
nameRequiredLint,
inEquals2_0Lint,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { DiagnosticSeverity } from 'vscode-languageserver-types';

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

const $ref3RequestBodiesNamingSchemaLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING_SCHEMA,
source: 'apilint',
message:
"requestBody $refs cannot point to '#/components/schemas/…', they must point to '#/components/requestBodies/…'",
severity: DiagnosticSeverity.Error,
linterFunction: 'parentExistFields',
linterParams: [['requestBodies']],
conditions: [
{
targets: [{ path: '$ref' }],
function: 'apilintValueRegex',
params: ['^(.*#/components/schemas).*$'],
},
],
marker: 'value',
target: '$ref',
data: {},
targetSpecs: OpenAPI3,
};

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

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

const $ref3RequestBodiesNamingLint: LinterMeta = {
code: ApilintCodes.OPENAPI3_0_REFERENCE_FIELD_$REF_REQUEST_BODIES_NAMING,
source: 'apilint',
message: 'requestBody $refs must point to a position where a requestBody can be legally placed',
severity: DiagnosticSeverity.Error,
linterFunction: 'parentExistFields',
linterParams: [['requestBodies']],
conditions: [
{
targets: [{ path: '$ref' }],
function: 'apilintValueRegex',
params: ['^(?!.*#/components/(requestBodies|schemas)).*$'],
},
],
marker: 'value',
target: '$ref',
data: {},
targetSpecs: OpenAPI3,
};

export default $ref3RequestBodiesNamingLint;
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import descriptionTypeLint from './description--type.ts';
import contentValuesTypeLint from './content--values-type.ts';
import contentRequiredLint from './content--required.ts';
import requiredTypeLint from './required--type.ts';
import $ref3RequestBodiesNamingLint from './$ref-3-0--request-bodies-naming.ts';
import $ref3RequestBodiesNamingSchemaLint from './$ref-3-0--request-bodies-naming-schema.ts';

const lints = [
$ref3RequestBodiesNamingLint,
$ref3RequestBodiesNamingSchemaLint,
descriptionTypeLint,
contentRequiredLint,
contentValuesTypeLint,
Expand Down
4 changes: 4 additions & 0 deletions packages/apidom-ls/src/config/openapi/schema/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ import uniqueItemsNonArrayLint from '../../common/schema/lint/unique-items--non-
import uniqueItemsTypeLint from '../../common/schema/lint/unique-items--type.ts';
import writeOnlyTypeLint from '../../common/schema/lint/write-only--type.ts';
import exampleDeprecatedLint from '../../common/schema/lint/example--deprecated.ts';
import $refNotUsedLint from '../../common/schema/lint/$ref--not-used.ts';
import $ref3RequestBodiesLint from '../../common/schema/lint/$ref-3-0--request-bodies.ts';
import { OpenAPI31 } from '../target-specs.ts';

const schemaLints = [
Expand Down Expand Up @@ -154,6 +156,8 @@ const schemaLints = [
uniqueItemsTypeLint,
writeOnlyTypeLint,
exampleDeprecatedLint,
$refNotUsedLint,
$ref3RequestBodiesLint,
];

export default schemaLints;
36 changes: 36 additions & 0 deletions packages/apidom-ls/src/services/validation/linter-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ export const standardLinterfunctions: FunctionItem[] = [
return true;
},
},
{
functionName: 'parentExistFields',
function: (element: Element, keys: string[]): boolean => {
const parent = element?.parent?.parent?.parent?.parent;
if (parent && isObject(parent)) {
for (const key of keys) {
if (!parent.hasKey(key)) {
return false;
}
}
}
return true;
},
},
{
functionName: 'existAnyOfFields',
function: (element: Element, keys: string[], allowEmpty: boolean): boolean => {
Expand Down Expand Up @@ -1089,6 +1103,28 @@ export const standardLinterfunctions: FunctionItem[] = [
return true;
},
},
{
functionName: 'apilintReferenceNotUsed',
function: (element: Element & { content?: { key?: string } }) => {
const elParent: Element = element.parent?.parent?.parent?.parent;
if (typeof elParent.hasKey !== 'function' || !elParent.hasKey('schemas')) {
return true;
}

const api = root(element);
const isReferenceElement = (el: Element & { content?: { key?: string } }) =>
toValue(el.content.key) === '$ref';
const referenceElements = filter((el) => {
return isReferenceElement(el);
}, api);
const referenceNames = referenceElements.map((refElement: Element) =>
// @ts-expect-error
toValue(refElement.content.value).split('/').at(-1),
);
// @ts-expect-error
return referenceNames.includes(toValue(element.parent.key));
},
},
{
functionName: 'apilintOpenAPIParameterInPathTemplate',
function: (element: Element) => {
Expand Down
Loading