From 8c86d4816034c4474f5e35f51e55cd8986a1e19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Gorej?= Date: Fri, 12 Jan 2024 10:30:03 +0100 Subject: [PATCH] feat(ls): add rules for OpenAPI 2.0 Tag Object (#3665) Refs #3611 --- packages/apidom-ls/src/config/codes.ts | 6 +++ .../src/config/openapi/tag/completion.ts | 43 ++++++++++++++++++- .../src/config/openapi/tag/documentation.ts | 12 +++++- .../config/openapi/tag/lint/allowed-fields.ts | 4 +- .../openapi/tag/lint/description--type.ts | 6 +-- .../openapi/tag/lint/external-docs--type.ts | 6 +-- .../config/openapi/tag/lint/name--required.ts | 6 +-- .../src/config/openapi/tag/lint/name--type.ts | 6 +-- 8 files changed, 73 insertions(+), 16 deletions(-) diff --git a/packages/apidom-ls/src/config/codes.ts b/packages/apidom-ls/src/config/codes.ts index e1b09cc0f5..78d58d56e9 100644 --- a/packages/apidom-ls/src/config/codes.ts +++ b/packages/apidom-ls/src/config/codes.ts @@ -778,6 +778,12 @@ enum ApilintCodes { OPENAPI2_SCOPES = 3180000, OPENAPI2_SCOPES_VALUES_TYPE = 3180100, + OPENAPI2_TAG = 3190000, + OPENAPI2_TAG_FIELD_NAME_TYPE = 3190100, + OPENAPI2_TAG_FIELD_NAME_REQUIRED, + OPENAPI2_TAG_FIELD_DESCRIPTION_TYPE = 3190200, + OPENAPI2_TAG_FIELD_EXTERNAL_DOCS_TYPE = 3190300, + OPENAPI3_0 = 5000000, OPENAPI3_0_OPENAPI_VALUE_PATTERN_3_0_0 = 5000100, diff --git a/packages/apidom-ls/src/config/openapi/tag/completion.ts b/packages/apidom-ls/src/config/openapi/tag/completion.ts index 3e377f2cf7..1f3119c1f5 100644 --- a/packages/apidom-ls/src/config/openapi/tag/completion.ts +++ b/packages/apidom-ls/src/config/openapi/tag/completion.ts @@ -3,9 +3,22 @@ import { CompletionFormat, CompletionType, } from '../../../apidom-language-types'; -import { OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; +import { OpenAPI2, OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; const completion: ApidomCompletionItem[] = [ + { + label: 'name', + insertText: 'name', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: '**Required.** The name of the tag.', + }, + targetSpecs: OpenAPI2, + }, { label: 'name', insertText: 'name', @@ -19,6 +32,20 @@ const completion: ApidomCompletionItem[] = [ }, targetSpecs: OpenAPI3, }, + { + label: 'description', + insertText: 'description', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'A short description for the tag. [GFM syntax](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown) can be used for rich text representation.', + }, + targetSpecs: OpenAPI2, + }, { label: 'description', insertText: 'description', @@ -33,6 +60,20 @@ const completion: ApidomCompletionItem[] = [ }, targetSpecs: OpenAPI3, }, + { + label: 'externalDocs', + insertText: 'externalDocs', + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + '[External Documentation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#externalDocumentationObject)\n\\\n\\\nAdditional external documentation for this tag.', + }, + targetSpecs: OpenAPI2, + }, { label: 'externalDocs', insertText: 'externalDocs', diff --git a/packages/apidom-ls/src/config/openapi/tag/documentation.ts b/packages/apidom-ls/src/config/openapi/tag/documentation.ts index 6901e0b8ed..34e5bdb49e 100644 --- a/packages/apidom-ls/src/config/openapi/tag/documentation.ts +++ b/packages/apidom-ls/src/config/openapi/tag/documentation.ts @@ -1,4 +1,4 @@ -import { OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; +import { OpenAPI2, OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; /** * Omitted fixed fields: @@ -11,12 +11,22 @@ import { OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; */ const documentation = [ + { target: 'name', docs: '**Required.** The name of the tag.', targetSpecs: OpenAPI2 }, { target: 'name', docs: '**REQUIRED**. The name of the tag.', targetSpecs: OpenAPI3 }, + { + target: 'description', + docs: 'A short description for the tag. [GFM syntax](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown) can be used for rich text representation.', + targetSpecs: OpenAPI2, + }, { target: 'description', docs: 'A description for the tag. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.', targetSpecs: OpenAPI3, }, + { + docs: '#### [Tag Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#tagObject)\n\nAllows adding meta data to a single tag that is used by the [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#operationObject). It is not mandatory to have a Tag Object per tag used there.\n\n##### Fixed Fields\nField Name | Type | Description\n---|:---:|---\nname | `string` | **Required.** The name of the tag.\ndescription | `string` | A short description for the tag. [GFM syntax](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown) can be used for rich text representation.\nexternalDocs | [External Documentation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#externalDocumentationObject) | Additional external documentation for this tag.\n\n##### Patterned Fields\nField Pattern | Type | Description\n---|:---:|---\n^x- | Any | Allows extensions to the Swagger Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. The value can be `null`, a primitive, an array or an object. See [Vendor Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#vendorExtensions) for further details.\n\n##### Tag Object Example\n\n```js\n{\n\t"name": "pet",\n\t"description": "Pets operations"\n}\n```\n\n\n\\\nYAML\n```yaml\nname: pet\ndescription: Pets operations\n```', + targetSpecs: OpenAPI2, + }, { docs: '#### [Tag Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#tagObject)\n\nAdds metadata to a single tag that is used by the [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operationObject).\nIt is not mandatory to have a Tag Object per tag defined in the Operation Object instances.\n\n##### Fixed Fields\nField Name | Type | Description\n---|:---:|---\nname | `string` | **REQUIRED**. The name of the tag.\ndescription | `string` | A short description for the tag. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.\nexternalDocs | [External Documentation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#externalDocumentationObject) | Additional external documentation for this tag.\n\nThis object MAY be extended with [Specification Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions).\n\n##### Tag Object Example\n\n\n\\\nJSON\n```json\n{\n\t"name": "pet",\n\t"description": "Pets operations"\n}\n```\n\n\n\\\nYAML\n```yaml\nname: pet\ndescription: Pets operations\n```', targetSpecs: OpenAPI30, diff --git a/packages/apidom-ls/src/config/openapi/tag/lint/allowed-fields.ts b/packages/apidom-ls/src/config/openapi/tag/lint/allowed-fields.ts index 9250b21c34..fb0fad3ba8 100644 --- a/packages/apidom-ls/src/config/openapi/tag/lint/allowed-fields.ts +++ b/packages/apidom-ls/src/config/openapi/tag/lint/allowed-fields.ts @@ -2,7 +2,7 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const allowedFieldsLint: LinterMeta = { code: ApilintCodes.NOT_ALLOWED_FIELDS, @@ -12,7 +12,7 @@ const allowedFieldsLint: LinterMeta = { linterFunction: 'allowedFields', linterParams: [['name', 'description', 'externalDocs'], 'x-'], marker: 'key', - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default allowedFieldsLint; diff --git a/packages/apidom-ls/src/config/openapi/tag/lint/description--type.ts b/packages/apidom-ls/src/config/openapi/tag/lint/description--type.ts index ad432cfd96..a2da7e3035 100644 --- a/packages/apidom-ls/src/config/openapi/tag/lint/description--type.ts +++ b/packages/apidom-ls/src/config/openapi/tag/lint/description--type.ts @@ -2,10 +2,10 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const descriptionTypeLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_TAG_FIELD_DESCRIPTION_TYPE, + code: ApilintCodes.OPENAPI2_TAG_FIELD_DESCRIPTION_TYPE, source: 'apilint', message: "'description' value must be a string", severity: DiagnosticSeverity.Error, @@ -14,7 +14,7 @@ const descriptionTypeLint: LinterMeta = { marker: 'value', target: 'description', data: {}, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default descriptionTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/tag/lint/external-docs--type.ts b/packages/apidom-ls/src/config/openapi/tag/lint/external-docs--type.ts index 559ad862c6..7ba25d717c 100644 --- a/packages/apidom-ls/src/config/openapi/tag/lint/external-docs--type.ts +++ b/packages/apidom-ls/src/config/openapi/tag/lint/external-docs--type.ts @@ -2,10 +2,10 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const externalDocsTypeLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_TAG_FIELD_EXTERNAL_DOCS_TYPE, + code: ApilintCodes.OPENAPI2_TAG_FIELD_EXTERNAL_DOCS_TYPE, source: 'apilint', message: 'externalDocs must be an object', severity: DiagnosticSeverity.Error, @@ -14,7 +14,7 @@ const externalDocsTypeLint: LinterMeta = { marker: 'value', target: 'externalDocs', data: {}, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default externalDocsTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/tag/lint/name--required.ts b/packages/apidom-ls/src/config/openapi/tag/lint/name--required.ts index 25c2af5374..008573424d 100644 --- a/packages/apidom-ls/src/config/openapi/tag/lint/name--required.ts +++ b/packages/apidom-ls/src/config/openapi/tag/lint/name--required.ts @@ -2,10 +2,10 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const nameRequiredLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_TAG_FIELD_NAME_REQUIRED, + code: ApilintCodes.OPENAPI2_TAG_FIELD_NAME_REQUIRED, source: 'apilint', message: "should always have a 'name'", severity: DiagnosticSeverity.Error, @@ -22,7 +22,7 @@ const nameRequiredLint: LinterMeta = { }, ], }, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default nameRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/tag/lint/name--type.ts b/packages/apidom-ls/src/config/openapi/tag/lint/name--type.ts index 1bc199e252..c19cedcea3 100644 --- a/packages/apidom-ls/src/config/openapi/tag/lint/name--type.ts +++ b/packages/apidom-ls/src/config/openapi/tag/lint/name--type.ts @@ -2,10 +2,10 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const nameTypeLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_TAG_FIELD_NAME_TYPE, + code: ApilintCodes.OPENAPI2_TAG_FIELD_NAME_TYPE, source: 'apilint', message: "'name' value must be a string", severity: DiagnosticSeverity.Error, @@ -14,7 +14,7 @@ const nameTypeLint: LinterMeta = { marker: 'value', target: 'name', data: {}, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default nameTypeLint;